diff --git a/package.json b/package.json index 1caed23..3a223de 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@thilawyn/thilalib", - "version": "0.1.10", + "version": "0.1.11", "type": "module", "files": [ "./dist" diff --git a/src/Schema/Jsonifiable.ts b/src/Schema/Jsonifiable.ts deleted file mode 100644 index 3a006cd..0000000 --- a/src/Schema/Jsonifiable.ts +++ /dev/null @@ -1,13 +0,0 @@ -import { Schema } from "@effect/schema" -import type { Jsonifiable as TJsonifiable } from "type-fest" - - -export const Jsonifiable = < - JsonifiableA, - JsonifiableI extends TJsonifiable, - JsonifiableR, ->( - jsonifiable: Schema.Schema -) => - (schema: Schema.Schema) => - jsonifiable.pipe(Schema.compose(schema)) diff --git a/src/Schema/composeJsonifiable.ts b/src/Schema/composeJsonifiable.ts new file mode 100644 index 0000000..0599622 --- /dev/null +++ b/src/Schema/composeJsonifiable.ts @@ -0,0 +1,13 @@ +import { Schema } from "@effect/schema" +import type { JsonValue } from "type-fest" + + +export const composeJsonifiable = < + JsonifiableA, + JsonifiableI extends JsonValue, + JsonifiableR, +>( + jsonifiableSchema: Schema.Schema +) => + (decodedSchema: Schema.Schema) => + Schema.compose(jsonifiableSchema, decodedSchema) diff --git a/src/Schema/encodedAsPrismaJsonValue.ts b/src/Schema/encodedAsPrismaJsonValue.ts new file mode 100644 index 0000000..b58ac01 --- /dev/null +++ b/src/Schema/encodedAsPrismaJsonValue.ts @@ -0,0 +1,13 @@ +import type { Schema } from "@effect/schema" +import type { JsonValue } from "type-fest" +import type { PrismaJson } from "../Types" + + +/** + * Takes a schema of which the encoded value satisfies type-fest's `JsonValue` and returns the same schema with Prisma's `JsonValue` as its encoded type instead. + * This allows you use to use jsonifiable schemas to strongly type `Json` database fields in Prisma. + * + * This is needed because Prisma's `JsonValue` is poorly implemented and does not work well with some types, such as readonly arrays. + */ +export const encodedAsPrismaJsonValue = (schema: Schema.Schema) => + schema as unknown as Schema.Schema diff --git a/src/Schema/index.ts b/src/Schema/index.ts index 8e5942f..0342e44 100644 --- a/src/Schema/index.ts +++ b/src/Schema/index.ts @@ -1,6 +1,7 @@ export * from "./Class" +export * from "./composeJsonifiable" export * from "./DateTime" -export * from "./Jsonifiable" +export * from "./encodedAsPrismaJsonValue" export * from "./Kind" export * as MobX from "./MobX" export * from "./MutableClass" diff --git a/src/Types/PrismaJson.ts b/src/Types/PrismaJson.ts new file mode 100644 index 0000000..4d15721 --- /dev/null +++ b/src/Types/PrismaJson.ts @@ -0,0 +1,51 @@ +/** + * `@prisma/client`'s Json types + * @module + */ + + +/** + * From https://github.com/sindresorhus/type-fest/ + * Matches a JSON object. + * This type can be useful to enforce some input to be JSON-compatible or as a super-type to be extended from. + */ +export type JsonObject = {[Key in string]?: JsonValue} + +/** + * From https://github.com/sindresorhus/type-fest/ + * Matches a JSON array. + */ +export interface JsonArray extends Array {} + +/** + * From https://github.com/sindresorhus/type-fest/ + * Matches any valid JSON value. + */ +export type JsonValue = string | number | boolean | JsonObject | JsonArray | null + +/** + * Matches a JSON object. + * Unlike `JsonObject`, this type allows undefined and read-only properties. + */ +export type InputJsonObject = {readonly [Key in string]?: InputJsonValue | null} + +/** + * Matches a JSON array. + * Unlike `JsonArray`, readonly arrays are assignable to this type. + */ +export interface InputJsonArray extends ReadonlyArray {} + +/** + * Matches any valid value that can be used as an input for operations like + * create and update as the value of a JSON field. Unlike `JsonValue`, this + * type allows read-only arrays and read-only object properties and disallows + * `null` at the top level. + * + * `null` cannot be used as the value of a JSON field because its meaning + * would be ambiguous. Use `Prisma.JsonNull` to store the JSON null value or + * `Prisma.DbNull` to clear the JSON value and set the field to the database + * NULL value instead. + * + * @see https://www.prisma.io/docs/concepts/components/prisma-client/working-with-fields/working-with-json-fields#filtering-by-null-values + */ +export type InputJsonValue = string | number | boolean | InputJsonObject | InputJsonArray | { toJSON(): unknown } diff --git a/src/Types/index.ts b/src/Types/index.ts index 78e48e0..e6b8475 100644 --- a/src/Types/index.ts +++ b/src/Types/index.ts @@ -1,4 +1,5 @@ export * from "./CommonKeys" export * from "./Extend" export * from "./Merge" +export * as PrismaJson from "./PrismaJson" export * from "./StaticType" diff --git a/src/tests.ts b/src/tests.ts index 764e0f2..cf38378 100644 --- a/src/tests.ts +++ b/src/tests.ts @@ -1,7 +1,7 @@ import { Schema as S } from "@effect/schema" import { reaction, runInAction } from "mobx" import type { Simplify } from "type-fest" -import { Jsonifiable, MutableTaggedClass } from "./Schema" +import { composeJsonifiable, MutableTaggedClass } from "./Schema" import { ObservableClass } from "./Schema/MobX" import type { ExtendAll } from "./Types" @@ -26,7 +26,7 @@ class User extends MutableTaggedClass()("User", { ) {} const JsonifiableUser = User.pipe( - Jsonifiable(S.Struct({ + composeJsonifiable(S.Struct({ ...User.fields, id: S.BigInt, }))