import { Trait, TraitExpressionBuilder, expression } from "@thilawyn/traitify-ts" import { AbstractClass, Simplify } from "type-fest" import { z } from "zod" import { ExtendableZodSchemaObject } from "./traits/ExtendableZodSchemaObject" import { InstantiableZodSchemaObject } from "./traits/InstantiableZodSchemaObject" import { Extend, StaticMembers } from "./util" export class ZodSchemaClassBuilder< Superclass extends AbstractClass, const Traits extends Trait[], > extends TraitExpressionBuilder { // extends< // This extends ZodSchemaClassBuilder< // typeof TraitExpression.NullSuperclass, // Ensures `extends` can only be called when the expression does not have a superclass // Traits // >, // Super extends AbstractClass, // >( // this: This, // superclass: Super, // ) { // return new ZodSchemaClassBuilder( // this.expressionBuilder.extends(superclass) // ) // } schema< Superclass extends AbstractClass & { schema?: never, defaultValues?: never }, SchemaT extends z.ZodRawShape, SchemaUnknownKeys extends z.UnknownKeysParam, SchemaCatchall extends z.ZodTypeAny, Values extends object, DefaultValues extends Partial, >( this: ZodSchemaClassBuilder, schema: z.ZodObject, defaultValues: DefaultValues, ) { class Schemas extends (this.expressionSuperclass as AbstractClass) { static readonly schema = schema static readonly defaultValues = defaultValues constructor(values: Values) { super() Object.assign(this, values) } } return new ZodSchemaClassBuilder( Schemas as unknown as ( AbstractClass< InstanceType & Simplify< Extend<[Schemas, Values]> >, ConstructorParameters > & Simplify< Extend<[ StaticMembers, StaticMembers, ]> > ), [ ...this.expressionTraits, InstantiableZodSchemaObject, ExtendableZodSchemaObject, ], ) } jsonifiable() { } } export function ZodSchemaClassOf< Superclass extends AbstractClass, SchemaT extends z.ZodRawShape, SchemaUnknownKeys extends z.UnknownKeysParam, SchemaCatchall extends z.ZodTypeAny, Values extends object, DefaultValues extends Partial, >( of: Superclass, { schema, defaultValues }: { schema: z.ZodObject defaultValues: DefaultValues }, ) { class Schemas extends (of as AbstractClass) { static readonly schema = schema static readonly defaultValues = defaultValues constructor(values: Values) { super() Object.assign(this, values) } } return expression .extends(Schemas as unknown as ( AbstractClass< InstanceType & Simplify< Extend<[Schemas, Values]> >, ConstructorParameters > & Simplify< Extend<[ StaticMembers, StaticMembers, ]> > )) .expresses( InstantiableZodSchemaObject, ExtendableZodSchemaObject, ) } class DefaultRoot {} export function ZodSchemaClass< SchemaT extends z.ZodRawShape, SchemaUnknownKeys extends z.UnknownKeysParam, SchemaCatchall extends z.ZodTypeAny, Values extends object, DefaultValues extends Partial, >( props: { schema: z.ZodObject defaultValues: DefaultValues }, ) { return ZodSchemaClassOf(DefaultRoot, props) }