diff --git a/src/schema/jsonify/bigint.ts b/src/schema/jsonify/bigint.ts new file mode 100644 index 0000000..513eaa0 --- /dev/null +++ b/src/schema/jsonify/bigint.ts @@ -0,0 +1,28 @@ +import { identity } from "lodash-es" +import { Opaque } from "type-fest" +import { z } from "zod" + + +export type JsonifiedBigInt = Opaque + + +export function jsonifyBigIntSchema(schema: S) { + return schema.transform(v => v.toString() as JsonifiedBigInt) +} + +export function dejsonifyBigIntSchema(schema: S) { + return z + .custom(identity) + .pipe(z + .string() + .transform(v => { + try { + return BigInt(v) + } + catch (e) { + return v + } + }) + .pipe(schema) + ) +} diff --git a/src/schema/jsonify/date.ts b/src/schema/jsonify/date.ts new file mode 100644 index 0000000..a84dc61 --- /dev/null +++ b/src/schema/jsonify/date.ts @@ -0,0 +1,28 @@ +import { identity } from "lodash-es" +import { Opaque } from "type-fest" +import { z } from "zod" + + +export type JsonifiedDate = Opaque + + +export function jsonifyDateSchema(schema: S) { + return schema.transform(v => v.toString() as JsonifiedDate) +} + +export function dejsonifyDateSchema(schema: S) { + return z + .custom(identity) + .pipe(z + .string() + .transform(v => { + try { + return new Date(v) + } + catch (e) { + return v + } + }) + .pipe(schema) + ) +} diff --git a/src/schema/jsonify/decimal.ts b/src/schema/jsonify/decimal.ts new file mode 100644 index 0000000..4a4e67e --- /dev/null +++ b/src/schema/jsonify/decimal.ts @@ -0,0 +1,33 @@ +import { Decimal } from "decimal.js" +import { identity } from "lodash-es" +import { Opaque } from "type-fest" +import { z } from "zod" + + +export type JsonifiedDecimal = Opaque + + +export function jsonifyDecimalSchema< + S extends z.ZodType +>(schema: S) { + return schema.transform(v => v.toJSON() as JsonifiedDecimal) +} + +export function dejsonifyDecimalSchema< + S extends z.ZodType +>(schema: S) { + return z + .custom(identity) + .pipe(z + .string() + .transform(v => { + try { + return new Decimal(v) + } + catch (e) { + return v + } + }) + .pipe(schema) + ) +} diff --git a/src/schema/jsonify/index.ts b/src/schema/jsonify/index.ts new file mode 100644 index 0000000..753d3a3 --- /dev/null +++ b/src/schema/jsonify/index.ts @@ -0,0 +1,16 @@ +import { dejsonifyBigIntSchema, jsonifyBigIntSchema } from "./bigint" +import { dejsonifyDateSchema, jsonifyDateSchema } from "./date" +import { dejsonifyDecimalSchema, jsonifyDecimalSchema } from "./decimal" + + +export const jsonify = { + bigint: jsonifyBigIntSchema, + date: jsonifyDateSchema, + decimal: jsonifyDecimalSchema, +} + +export const dejsonify = { + bigint: dejsonifyBigIntSchema, + date: dejsonifyDateSchema, + decimal: dejsonifyDecimalSchema, +} diff --git a/src/tests.ts b/src/tests.ts index 3a49e24..a43865c 100644 --- a/src/tests.ts +++ b/src/tests.ts @@ -1,6 +1,7 @@ import { Implements, TraitExpression } from "@thilawyn/traitify-ts" import { z } from "zod" import { ZodSchemaClassBuilder } from "./ZodSchemaClass" +import { dejsonify, jsonify } from "./schema/jsonify" import { ObservableZodSchemaObject } from "./traits/ObservableZodSchemaObject" @@ -15,8 +16,12 @@ const newTestExp = new ZodSchemaClassBuilder(TraitExpression.NullSuperclass, []) defaultValues: { id: -1n }, }) .jsonifiable({ - jsonifySchema: ({ schema }) => schema.extend({}), - dejsonifySchema: ({ schema }) => schema.extend({}), + jsonifySchema: ({ schema, shape }) => schema.extend({ + id: jsonify.bigint(shape.id) + }), + dejsonifySchema: ({ schema, shape }) => schema.extend({ + id: dejsonify.bigint(shape.id) + }), }) .expresses(ObservableZodSchemaObject) .build()