Option jsonification work
All checks were successful
continuous-integration/drone/push Build is passing

This commit is contained in:
Julien Valverdé
2024-03-21 14:38:12 +01:00
parent a5c5b62c9f
commit 7bc302d882
4 changed files with 38 additions and 52 deletions

View File

@@ -1,29 +1,19 @@
import { identity } from "lodash-es"
import { Opaque } from "type-fest"
import { z } from "zod" import { z } from "zod"
export type JsonifiedDate = Opaque<string, "@thilawyn/zod-schema-class/JsonifiedDate"> export type JsonifiedDateBrand = "@thilawyn/zod-schema-class/JsonifiedDate"
export function jsonifyDateSchema<S extends z.ZodType<Date>>(schema: S) { export function jsonifyDateSchema<S extends z.ZodType<Date>>(schema: S) {
return schema.transform(v => v.toString() as JsonifiedDate) return schema
.transform(v => v.toString())
.brand<JsonifiedDateBrand>()
} }
export function dejsonifyDateSchema<S extends z.ZodType<Date>>(schema: S) { export function dejsonifyDateSchema<S extends z.ZodType<Date>>(schema: S) {
return z return z
.custom<JsonifiedDate>(identity) .custom<string & z.BRAND<JsonifiedDateBrand>>()
.pipe( .pipe(z.string())
z .pipe(z.coerce.date())
.string()
.transform(v => {
try {
return new Date(v)
}
catch (e) {
return v
}
})
)
.pipe(schema) .pipe(schema)
} }

View File

@@ -1,19 +1,19 @@
import { Decimal } from "decimal.js" import { Decimal } from "decimal.js"
import { identity } from "lodash-es"
import { Opaque } from "type-fest"
import { z } from "zod" import { z } from "zod"
export type JsonifiedDecimal = Opaque<string, "@thilawyn/zod-schema-class/JsonifiedDecimal"> export type JsonifiedDecimalBrand = "@thilawyn/zod-schema-class/JsonifiedDecimal"
export function jsonifyDecimalSchema<S extends z.ZodType<Decimal>>(schema: S) { export function jsonifyDecimalSchema<S extends z.ZodType<Decimal>>(schema: S) {
return schema.transform(v => v.toJSON() as JsonifiedDecimal) return schema
.transform(v => v.toJSON())
.brand<JsonifiedDecimalBrand>()
} }
export function dejsonifyDecimalSchema<S extends z.ZodType<Decimal>>(schema: S) { export function dejsonifyDecimalSchema<S extends z.ZodType<Decimal>>(schema: S) {
return z return z
.custom<JsonifiedDecimal>(identity) .custom<string & z.BRAND<JsonifiedDecimalBrand>>()
.pipe( .pipe(
z z
.string() .string()

View File

@@ -1,13 +1,10 @@
import { Option } from "effect" import { Option } from "effect"
import { identity } from "lodash-es" import { identity } from "lodash-es"
import { Jsonifiable, Opaque } from "type-fest"
import { z } from "zod" import { z } from "zod"
import { ZodEffectOption, ZodEffectOptionNone, ZodEffectOptionSome, effectOptionNoneSchema, effectOptionSomeInnerSchema, effectOptionSomeSchema } from "../effect" import { ZodEffectOption, ZodEffectOptionNone, ZodEffectOptionSome, effectOptionNoneSchema, effectOptionSomeInnerSchema, effectOptionSomeSchema } from "../effect"
export type JsonifiedEffectOption<T extends Jsonifiable> = Opaque<T | null, "@thilawyn/zod-schema-class/JsonifiedEffectOption"> export type JsonifiedEffectOptionSomeBrand = "@thilawyn/zod-schema-class/JsonifiedEffectOptionSome"
export type JsonifiedEffectOptionSome<T> = Opaque<T, "@thilawyn/zod-schema-class/JsonifiedEffectOptionSome">
export type JsonifiedEffectOptionNone = Opaque<null, "@thilawyn/zod-schema-class/JsonifiedEffectOptionNone">
export const jsonifyOption = { export const jsonifyOption = {
@@ -31,7 +28,7 @@ export const jsonifyOption = {
) => schema ) => schema
.transform(v => Option.getOrThrow(v)) .transform(v => Option.getOrThrow(v))
.pipe(jsonifySchema(effectOptionSomeInnerSchema(schema))) .pipe(jsonifySchema(effectOptionSomeInnerSchema(schema)))
.brand<"@thilawyn/zod-schema-class/JsonifiedEffectOptionSome">(), .brand<JsonifiedEffectOptionSomeBrand>(),
none: < none: <
InnerS extends z.ZodTypeAny, InnerS extends z.ZodTypeAny,
@@ -46,31 +43,35 @@ export const jsonifyOption = {
export const dejsonifyOption = { export const dejsonifyOption = {
option: < option: <
InnerS extends z.ZodTypeAny, InnerS extends z.ZodTypeAny,
JsonifiedInnerS extends z.ZodTypeAny = InnerS, DejsonifiedInnerS extends z.ZodTypeAny = InnerS,
>( >(
schema: ZodEffectOption<InnerS>, schema: ZodEffectOption<InnerS>,
jsonifySchema: (schema: InnerS) => JsonifiedInnerS = identity, dejsonifySchema: (schema: InnerS) => DejsonifiedInnerS = identity,
) => z.union([ ) => z.union([
jsonifyOption.some(effectOptionSomeSchema(schema), jsonifySchema), dejsonifyOption.some(effectOptionSomeSchema(schema), dejsonifySchema),
jsonifyOption.none(effectOptionNoneSchema(schema), jsonifySchema), dejsonifyOption.none(effectOptionNoneSchema(schema), dejsonifySchema),
]), ]),
some: < some: <
InnerS extends z.ZodTypeAny, InnerS extends z.ZodTypeAny,
JsonifiedInnerS extends z.ZodTypeAny = InnerS, DejsonifiedInnerS extends z.ZodTypeAny = InnerS,
>( >(
schema: ZodEffectOptionSome<InnerS>, schema: ZodEffectOptionSome<InnerS>,
jsonifySchema: (schema: InnerS) => JsonifiedInnerS = identity, dejsonifySchema: (schema: InnerS) => DejsonifiedInnerS = identity,
) => schema ) => z
.transform(v => Option.getOrThrow(v)) .custom<z.input<DejsonifiedInnerS> & z.BRAND<JsonifiedEffectOptionSomeBrand>>()
.pipe(jsonifySchema(effectOptionSomeInnerSchema(schema))), .pipe(dejsonifySchema(effectOptionSomeInnerSchema(schema)))
.transform(v => Option.some<z.output<DejsonifiedInnerS>>(v))
.pipe(schema),
none: < none: <
InnerS extends z.ZodTypeAny, InnerS extends z.ZodTypeAny,
JsonifiedInnerS extends z.ZodTypeAny = InnerS, DejsonifiedInnerS extends z.ZodTypeAny = InnerS,
>( >(
schema: ZodEffectOptionNone<InnerS>, schema: ZodEffectOptionNone<InnerS>,
_jsonifySchema?: (schema: InnerS) => JsonifiedInnerS, _dejsonifySchema?: (schema: InnerS) => DejsonifiedInnerS,
) => ) => z
z.null().pipe(schema), .null()
.transform(() => Option.none<z.output<DejsonifiedInnerS>>())
.pipe(schema),
} as const } as const

View File

@@ -2,7 +2,7 @@ import { Implements } from "@thilawyn/traitify-ts"
import { Option } from "effect" import { Option } from "effect"
import { z } from "zod" import { z } from "zod"
import { ZodSchemaClass } from "./ZodSchemaClass" import { ZodSchemaClass } from "./ZodSchemaClass"
import { dejsonify, jsonify } from "./schema/jsonified" import { jsonify } from "./schema/jsonified"
import { jsonifyBigIntSchema } from "./schema/jsonified/bigint" import { jsonifyBigIntSchema } from "./schema/jsonified/bigint"
import { effect } from "./schema/lib" import { effect } from "./schema/lib"
import { MobXObservableZodSchemaObject } from "./traits/MobXObservableZodSchemaObject" import { MobXObservableZodSchemaObject } from "./traits/MobXObservableZodSchemaObject"
@@ -36,7 +36,6 @@ const jsonifiedBigIntOption = jsonify.option.option(
) )
type T1 = z.output<typeof jsonifiedBigIntOption> type T1 = z.output<typeof jsonifiedBigIntOption>
const jsonifiedBigIntOptionSome = jsonify.option.some( const jsonifiedBigIntOptionSome = jsonify.option.some(
effect.option.some(z.bigint()), effect.option.some(z.bigint()),
jsonifyBigIntSchema, jsonifyBigIntSchema,
@@ -50,10 +49,6 @@ const jsonifiedBigIntOptionNone = jsonify.option.none(
type T3 = z.output<typeof jsonifiedBigIntOptionNone> type T3 = z.output<typeof jsonifiedBigIntOptionNone>
const dejsonifyBigInt = dejsonify.bigint(z.bigint())
type T4 = z.input<typeof dejsonifyBigInt>
// const jsonifiedUserExp = JsonifiedZodSchemaClass(User, { // const jsonifiedUserExp = JsonifiedZodSchemaClass(User, {
// jsonifySchema: s => s.extend({ // jsonifySchema: s => s.extend({
// id: jsonify.bigint(s.shape.id) // id: jsonify.bigint(s.shape.id)