UNPKG

@volverjs/form-vue

Version:

Vue 3 Forms with @volverjs/ui-vue

103 lines (101 loc) 2.55 kB
import { type z, type AnyZodObject, type ZodTypeAny, ZodDefault, ZodObject, ZodEffects, ZodSchema, ZodNullable, ZodOptional, ZodArray, } from 'zod' import type { FormSchema } from './types' export const defaultObjectBySchema = <Schema extends FormSchema>( schema: Schema, original: Partial<z.infer<Schema>> = {}, ): Partial<z.infer<Schema>> => { const getInnerType = <Type extends ZodTypeAny>( schema: | Type | ZodEffects<Type> | ZodEffects<ZodEffects<Type>> | ZodOptional<Type>, ) => { let toReturn = schema while (toReturn instanceof ZodEffects) { toReturn = toReturn.innerType() } if (toReturn instanceof ZodOptional) { toReturn = toReturn._def.innerType } return toReturn } const innerType = getInnerType<AnyZodObject>(schema) const unknownKeys = innerType instanceof ZodObject ? innerType._def.unknownKeys === 'passthrough' : false return { ...(unknownKeys ? original : {}), ...Object.fromEntries( (Object.entries(innerType.shape) as [string, ZodTypeAny][]).map( ([key, subSchema]) => { const originalValue = original[key] let innerType = getInnerType(subSchema) let defaultValue: Partial<z.infer<Schema>> | undefined = undefined if (innerType instanceof ZodDefault) { defaultValue = innerType._def.defaultValue() innerType = innerType._def.innerType } if ( originalValue === null && innerType instanceof ZodNullable ) { return [key, originalValue] } if (innerType instanceof ZodSchema) { const parse = subSchema.safeParse(originalValue) if (parse.success) { return [key, parse.data ?? defaultValue] } } if ( innerType instanceof ZodArray && Array.isArray(originalValue) && originalValue.length ) { const arrayType = getInnerType(innerType._def.type) if (arrayType instanceof ZodObject) { return [ key, originalValue.map((element: unknown) => defaultObjectBySchema( arrayType, element && typeof element === 'object' ? element : undefined, ), ) ?? defaultValue, ] } } if (innerType instanceof ZodObject) { return [ key, defaultObjectBySchema( innerType, originalValue && typeof originalValue === 'object' ? originalValue : defaultValue, ), ] } return [key, defaultValue] }, ), ), } as Partial<z.infer<Schema>> }