From 222676dfafdf9fb4f848ee59ab9091bae7d7065b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Julien=20Valverd=C3=A9?= Date: Wed, 17 Jan 2024 16:23:53 +0100 Subject: [PATCH] Jsonifiable schemas work --- src/jsonifiable/schema/bigint.ts | 30 +++++++++++++++++++----------- src/jsonifiable/schema/date.ts | 30 +++++++++++++++++++----------- src/jsonifiable/schema/decimal.ts | 30 +++++++++++++++++++----------- src/tests.ts | 11 +++++------ src/util.ts | 5 +++++ 5 files changed, 67 insertions(+), 39 deletions(-) diff --git a/src/jsonifiable/schema/bigint.ts b/src/jsonifiable/schema/bigint.ts index 099d309..76a605d 100644 --- a/src/jsonifiable/schema/bigint.ts +++ b/src/jsonifiable/schema/bigint.ts @@ -1,20 +1,28 @@ +import { Opaque } from "type-fest" import { z } from "zod" +import { identity } from "../../util" + + +export type JsonifiedBigInt = Opaque export function jsonifyBigIntSchema(schema: S) { - return schema.transform(v => v.toString()) + return schema.transform(v => v.toString() as JsonifiedBigInt) } export function dejsonifyBigIntSchema(schema: S) { return z - .string() - .transform(v => { - try { - return BigInt(v) - } - catch (e) { - return v - } - }) - .pipe(schema) + .custom(identity) + .pipe(z + .string() + .transform(v => { + try { + return BigInt(v) + } + catch (e) { + return v + } + }) + .pipe(schema) + ) } diff --git a/src/jsonifiable/schema/date.ts b/src/jsonifiable/schema/date.ts index ea0ee6f..c70b2ed 100644 --- a/src/jsonifiable/schema/date.ts +++ b/src/jsonifiable/schema/date.ts @@ -1,20 +1,28 @@ +import { Opaque } from "type-fest" import { z } from "zod" +import { identity } from "../../util" + + +export type JsonifiedDate = Opaque export function jsonifyDateSchema(schema: S) { - return schema.transform(v => v.toString()) + return schema.transform(v => v.toString() as JsonifiedDate) } export function dejsonifyDateSchema(schema: S) { return z - .string() - .transform(v => { - try { - return new Date(v) - } - catch (e) { - return v - } - }) - .pipe(schema) + .custom(identity) + .pipe(z + .string() + .transform(v => { + try { + return new Date(v) + } + catch (e) { + return v + } + }) + .pipe(schema) + ) } diff --git a/src/jsonifiable/schema/decimal.ts b/src/jsonifiable/schema/decimal.ts index ca01261..be387ee 100644 --- a/src/jsonifiable/schema/decimal.ts +++ b/src/jsonifiable/schema/decimal.ts @@ -1,25 +1,33 @@ import { Decimal } from "decimal.js" +import { Opaque } from "type-fest" import { z } from "zod" +import { identity } from "../../util" + + +export type JsonifiedDecimal = Opaque export function jsonifyDecimalSchema< S extends z.ZodType >(schema: S) { - return schema.transform(v => v.toJSON()) + return schema.transform(v => v.toJSON() as JsonifiedDecimal) } export function dejsonifyDecimalSchema< S extends z.ZodType >(schema: S) { return z - .string() - .transform(v => { - try { - return new Decimal(v) - } - catch (e) { - return v - } - }) - .pipe(schema) + .custom(identity) + .pipe(z + .string() + .transform(v => { + try { + return new Decimal(v) + } + catch (e) { + return v + } + }) + .pipe(schema) + ) } diff --git a/src/tests.ts b/src/tests.ts index 00be534..8cbcee3 100644 --- a/src/tests.ts +++ b/src/tests.ts @@ -1,8 +1,7 @@ import { pipeInto } from "ts-functional-pipe" import { z } from "zod" import { extendSchemableClass, makeSchemableClass, newSchemable } from "." -import { dejsonifySchemable, makeJsonifiableSchemableClass } from "./jsonifiable" -import { dejsonifyBigIntSchema, jsonifyBigIntSchema } from "./legacy/jsonifiable" +import { dejsonifyBigIntSchema, dejsonifySchemable, jsonifyBigIntSchema, makeJsonifiableSchemableClass } from "./jsonifiable" const UserLevel = z.enum(["User", "Admin"]) @@ -10,9 +9,9 @@ const UserLevel = z.enum(["User", "Admin"]) const UserProto = makeSchemableClass({ schema: z.object({ - id: z.bigint(), - name: z.string(), - level: UserLevel, + id: z.bigint(), + name: z.string(), + level: UserLevel, }), defaultValues: { @@ -44,7 +43,7 @@ class User extends pipeInto( dejsonifySchema: ({ schema, shape }) => schema.extend({ id: dejsonifyBigIntSchema(shape.id) }), - }) + }), ) {} diff --git a/src/util.ts b/src/util.ts index 1f2ea6b..a1c11d4 100644 --- a/src/util.ts +++ b/src/util.ts @@ -3,6 +3,11 @@ import { AbstractClass, Class as ConcreteClass } from "type-fest" import { z } from "zod" +export function identity(value: T) { + return value +} + + export type ClassType = "AbstractClass" | "Class" export type Class<