import { Trait, TraitExpressionBuilder, expression } from "@thilawyn/traitify-ts" import { AbstractClass } from "type-fest" import { EmptyObject } from "type-fest/source/empty-object" import { JsonifiableObject } from "type-fest/source/jsonifiable" import { z } from "zod" import { JsonifiableZodSchemaObject } from "../traits/JsonifiableZodSchemaObject" import { ZodSchemaObject } from "../traits/ZodSchemaObject" export class ZodSchemaClassBuilder< Superclass extends AbstractClass, const Traits extends readonly Trait[], Schemas extends object, > { declare ["constructor"]: typeof ZodSchemaClassBuilder constructor( protected readonly expression: TraitExpressionBuilder, protected readonly schemas: Schemas, ) {} schema< SchemaT extends z.ZodRawShape, SchemaUnknownKeys extends z.UnknownKeysParam, SchemaCatchall extends z.ZodTypeAny, SchemaWithDefaultValuesT extends z.ZodRawShape, SchemaWithDefaultValuesUnknownKeys extends z.UnknownKeysParam, SchemaWithDefaultValuesCatchall extends z.ZodTypeAny, Values extends object, PartialValues extends Partial, >( this: ZodSchemaClassBuilder, props: { schema: z.ZodObject schemaWithDefaultValues: ( schema: z.ZodObject ) => z.ZodObject }, ) { const schema = props.schema const schemaWithDefaultValues = props.schemaWithDefaultValues(props.schema) abstract class ZodSchemaObjectConstructor { constructor(values: Values) { Object.assign(this, values) } } return new this.constructor( this.expression .extends(ZodSchemaObjectConstructor as AbstractClass) .expresses(ZodSchemaObject(schema, schemaWithDefaultValues)), { schema, schemaWithDefaultValues } as const, ) } jsonifiable< S extends { readonly schema: z.ZodObject, readonly schemaWithDefaultValues: z.ZodObject, jsonifySchema?: never dejsonifySchema?: never }, SchemaT extends z.ZodRawShape, SchemaUnknownKeys extends z.UnknownKeysParam, SchemaCatchall extends z.ZodTypeAny, SchemaWithDefaultValuesT extends z.ZodRawShape, SchemaWithDefaultValuesUnknownKeys extends z.UnknownKeysParam, SchemaWithDefaultValuesCatchall extends z.ZodTypeAny, Values extends object, PartialValues extends Partial, JsonifySchemaT extends z.ZodRawShape, JsonifySchemaUnknownKeys extends z.UnknownKeysParam, JsonifySchemaCatchall extends z.ZodTypeAny, DejsonifySchemaT extends z.ZodRawShape, DejsonifySchemaUnknownKeys extends z.UnknownKeysParam, DejsonifySchemaCatchall extends z.ZodTypeAny, JsonifiedValues extends JsonifiableObject, >( this: ZodSchemaClassBuilder, readonly schemaWithDefaultValues: z.ZodObject, jsonifySchema?: never dejsonifySchema?: never }>, props: { jsonifySchema: ( schema: z.ZodObject ) => z.ZodObject dejsonifySchema: ( schema: z.ZodObject ) => z.ZodObject }, ) { const jsonifySchema = props.jsonifySchema(this.schemas.schema) const dejsonifySchema = props.dejsonifySchema(this.schemas.schema) return new this.constructor( this.expression.expresses( JsonifiableZodSchemaObject( this.schemas.schema, this.schemas.schemaWithDefaultValues, jsonifySchema, dejsonifySchema, ) ), { ...this.schemas as S, jsonifySchema, dejsonifySchema } as const, ) } toExpression() { return this.expression } } export const zodSchemaClass = new ZodSchemaClassBuilder(expression, {})