import { ImplStatic, TraitClass, trait } from "@thilawyn/traitify-ts" import { Class, Jsonifiable } from "type-fest" import { z } from "zod" import { parseZodSchemaEffect } from "../util" import { ZodSchemaObjectTrait } from "./ZodSchemaObject" export const JsonifiedZodSchemaObject = < Of extends TraitClass>, T extends z.ZodRawShape, Catchall extends z.ZodTypeAny, Values extends object, PartialValues extends Partial, JsonifyT extends z.ZodRawShape, JsonifyCatchall extends z.ZodTypeAny, DejsonifyT extends z.ZodRawShape, DejsonifyCatchall extends z.ZodTypeAny, JsonifiedValues extends Jsonifiable, >( of: Of | TraitClass>, props: { jsonifySchema: ( schema: typeof of.schema ) => z.ZodObject, dejsonifySchema: ( schema: typeof of.schema ) => z.ZodObject, }, ) => trait .implement(Super => class JsonifiedZodSchemaObjectImpl extends Super { static readonly of = of as Of static readonly jsonifySchema = props.jsonifySchema(of.schema) static readonly dejsonifySchema = props.dejsonifySchema(of.schema) static pipeSchemaIntoInstance< Instance extends JsonifiedValues, SchemaT extends z.ZodRawShape, SchemaUnknownKeys extends z.UnknownKeysParam, SchemaCatchall extends z.ZodTypeAny, SchemaOutput extends JsonifiedValues, SchemaInput, >( this: Class, schema: z.ZodObject, ) { return schema.transform(values => new this(values)) } static jsonify< Instance extends JsonifiedValues >( this: ( Class & ImplStatic ), values: Values, params?: Partial, ) { return this .pipeSchemaIntoInstance(this.jsonifySchema) .parse(values, params) } static jsonifyPromise< Instance extends JsonifiedValues >( this: ( Class & ImplStatic ), values: Values, params?: Partial, ) { return this .pipeSchemaIntoInstance(this.jsonifySchema) .parseAsync(values, params) } static jsonifyEffect< Instance extends JsonifiedValues >( this: ( Class & ImplStatic ), values: Values, params?: Partial, ) { return parseZodSchemaEffect( this.pipeSchemaIntoInstance(this.jsonifySchema), values, params, ) } }) .build()