diff --git a/packages/validator-zod/src/index.ts b/packages/validator-zod/src/index.ts index a236cf2b..f3c65af1 100644 --- a/packages/validator-zod/src/index.ts +++ b/packages/validator-zod/src/index.ts @@ -7,42 +7,49 @@ import type { Extender, } from '@felte/common'; import { _update } from '@felte/common'; -import type { ZodError, AnyZodObject } from 'zod'; +import type { ZodError, ZodSchema } from 'zod'; -type ZodSchema = { - parseAsync: AnyZodObject['parseAsync']; -}; - -export type ValidatorConfig = { - schema: ZodSchema; +export type ValidatorConfig = { + schema: ZodSchema; level?: 'error' | 'warning'; }; export function validateSchema( schema: ZodSchema ): ValidationFunction { - function shapeErrors(errors: ZodError): AssignableErrors { - return errors.issues.reduce((err, value) => { - /* istanbul ignore next */ - if (!value.path) return err; - return _update( - err, - value.path.join('.'), - (currentValue: undefined | string[]) => { - if (!currentValue || !Array.isArray(currentValue)) - return [value.message]; - return [...currentValue, value.message]; - } - ); - }, {} as AssignableErrors); - } return async function validate( values: Data ): Promise | undefined> { - try { - await schema.parseAsync(values); - } catch (error) { - return shapeErrors(error as ZodError); + async function walk( + error: ZodError, + err: AssignableErrors + ): Promise> { + for (const issue of error.issues) { + if (issue.code === 'invalid_union') { + for (const unionError of issue.unionErrors) { + err = await walk(unionError, err); + } + } else { + if (!issue.path) continue; + + const updater = (currentValue?: string[]) => { + if (!currentValue || !Array.isArray(currentValue)) { + return [issue.message]; + } + return [...currentValue, issue.message]; + }; + err = _update(err, issue.path.join('.'), updater); + } + } + + return err; + } + + const result = await schema.safeParseAsync(values); + if (!result.success) { + let err = {} as AssignableErrors; + err = await walk(result.error, err); + return err; } }; } diff --git a/packages/validator-zod/tests/validator.spec.ts b/packages/validator-zod/tests/validator.spec.ts index cf9a6725..7c50a974 100644 --- a/packages/validator-zod/tests/validator.spec.ts +++ b/packages/validator-zod/tests/validator.spec.ts @@ -314,7 +314,7 @@ describe('Validator zod', () => { }); const mockData = { elems: [null, { name: '' }] }; - const { validate, errors } = createForm({ + const { validate, errors } = createForm({ initialValues: mockData, onSubmit: vi.fn(), extend: validator({ schema }), @@ -327,7 +327,7 @@ describe('Validator zod', () => { }); }); - test.skip('should surface union type errors', async () => { + test('should surface union type errors', async () => { async function t(schema: ZodSchema, initialValues: object) { const { validate, errors } = createForm({ initialValues,