import { expression } from "@thilawyn/traitify-ts" import { AbstractClass } from "type-fest" import { z } from "zod" import { ExtendableZodSchemaObject } from "./traits/ExtendableZodSchemaObject" import { InstantiableZodSchemaObject } from "./traits/InstantiableZodSchemaObject" import { Extend, StaticMembers } from "./util" export function ZodSchemaClassOf< Super extends AbstractClass, SchemaT extends z.ZodRawShape, SchemaUnknownKeys extends z.UnknownKeysParam, SchemaCatchall extends z.ZodTypeAny, Values extends {}, DefaultValues extends Partial, >( of: Super, { schema, defaultValues }: { schema: z.ZodObject defaultValues: DefaultValues }, ) { const exp = expression .extends(class extends (of as AbstractClass<{}, []>) { static readonly schema = schema static readonly defaultValues = defaultValues constructor(values: Values) { super() Object.assign(this, values) } }) .expresses( InstantiableZodSchemaObject, ExtendableZodSchemaObject, ) .build() return exp.extends as AbstractClass< Extend<[ InstanceType, InstanceType, Values, ]>, ConstructorParameters > & Extend<[ StaticMembers, StaticMembers, ]> } class DefaultRoot {} export function ZodSchemaClass< SchemaT extends z.ZodRawShape, SchemaUnknownKeys extends z.UnknownKeysParam, SchemaCatchall extends z.ZodTypeAny, Values extends {}, DefaultValues extends Partial, >( props: { schema: z.ZodObject defaultValues: DefaultValues }, ) { return ZodSchemaClassOf(DefaultRoot, props) }