import { AbstractClass, Class as ConcreteClass } from "type-fest" import { z } from "zod" import { SchemableClass } from "." import { StaticMembers } from "./util" export function extendSchemableClass< C extends SchemableClass< ExtendSchemaT, ExtendSchemaUnknownKeys, ExtendSchemaCatchall, ExtendSchemaValues, ExtendDefaultValues >, ExtendSchemaT extends z.ZodRawShape, ExtendSchemaUnknownKeys extends z.UnknownKeysParam, ExtendSchemaCatchall extends z.ZodTypeAny, ExtendSchemaValues extends {}, ExtendDefaultValues extends Partial, SchemaT extends z.ZodRawShape, SchemaUnknownKeys extends z.UnknownKeysParam, SchemaCatchall extends z.ZodTypeAny, SchemaValues extends ExtendSchemaValues, DefaultValues extends Partial, >( extend: C | SchemableClass< ExtendSchemaT, ExtendSchemaUnknownKeys, ExtendSchemaCatchall, ExtendSchemaValues, ExtendDefaultValues >, props: { schema: (props: { schema: z.ZodObject< ExtendSchemaT, ExtendSchemaUnknownKeys, ExtendSchemaCatchall, ExtendSchemaValues, ExtendSchemaValues > shape: ExtendSchemaT }) => z.ZodObject< SchemaT, SchemaUnknownKeys, SchemaCatchall, SchemaValues, SchemaValues > defaultValues: (defaultValues: ExtendDefaultValues) => DefaultValues }, ) { type Class = ( C extends ConcreteClass ? ConcreteClass : AbstractClass ) const schema = props.schema({ schema: extend.schema, shape: extend.schema.shape, }) const defaultValues = props.defaultValues(extend.defaultValues) return class extends extend { static readonly schema = schema readonly schema = schema static readonly defaultValues = defaultValues readonly defaultValues = defaultValues } as unknown as ( Class< Omit, "schema" | "defaultValues" | keyof ExtendSchemaValues> & { readonly schema: typeof schema, readonly defaultValues: typeof defaultValues, } & SchemaValues, Parameters<(values: SchemaValues) => void> > & Omit, "schema" | "defaultValues"> & { readonly schema: typeof schema, readonly defaultValues: typeof defaultValues, } ) }