import { trait } from "@thilawyn/traitify-ts" import { Effect, pipe } from "effect" import { HasRequiredKeys } from "type-fest" import { z } from "zod" import { ZodSchemaClass } from "../shapes/ZodSchemaClass" import { parseZodTypeEffect } from "../util" type NewZodSchemaInstanceInput< Values extends object, DefaultValues extends Partial, > = { [Key in Exclude]: Values[Key] } & { [Key in keyof DefaultValues]?: Key extends keyof Values ? Values[Key] : never } type ParseParamsArgs = [] | [params: Partial] type NewZodSchemaInstanceArgs = ( HasRequiredKeys extends true ? [values: Input, ...args: ParseParamsArgs] : [] | [values: Input, ...args: ParseParamsArgs] ) export const InstantiableZodSchemaObject = trait .implement(Super => class InstantiableZodSchemaObject extends Super { static create< Instance extends Values, SchemaT extends z.ZodRawShape, SchemaUnknownKeys extends z.UnknownKeysParam, SchemaCatchall extends z.ZodTypeAny, Values extends object, DefaultValues extends Partial, >( this: ZodSchemaClass, ...[values, params]: NewZodSchemaInstanceArgs< NewZodSchemaInstanceInput > ) { return new this( this.schema.parse({ ...this.defaultValues, ...values }, params) ) } static async createPromise< Instance extends Values, SchemaT extends z.ZodRawShape, SchemaUnknownKeys extends z.UnknownKeysParam, SchemaCatchall extends z.ZodTypeAny, Values extends object, DefaultValues extends Partial, >( this: ZodSchemaClass, ...[values, params]: NewZodSchemaInstanceArgs< NewZodSchemaInstanceInput > ) { return new this( await this.schema.parseAsync({ ...this.defaultValues, ...values }, params) ) } static createEffect< Instance extends Values, SchemaT extends z.ZodRawShape, SchemaUnknownKeys extends z.UnknownKeysParam, SchemaCatchall extends z.ZodTypeAny, Values extends object, DefaultValues extends Partial, >( this: ZodSchemaClass, ...[values, params]: NewZodSchemaInstanceArgs< NewZodSchemaInstanceInput > ) { return pipe( parseZodTypeEffect( this.schema, { ...this.defaultValues, ...values }, params, ), Effect.map(values => new this(values)), ) } protected static initialize() { } }) .build()