diff --git a/zod/src/__tests__/zod.ts b/zod/src/__tests__/zod.ts index 51698216..73b206a1 100644 --- a/zod/src/__tests__/zod.ts +++ b/zod/src/__tests__/zod.ts @@ -1,4 +1,4 @@ -import { zodResolver } from '..'; +import { zodResolver, zodResolverSync } from '..'; import { schema, validData, invalidData, fields } from './__fixtures__/data'; const shouldUseNativeValidation = false; @@ -22,9 +22,7 @@ describe('zodResolver', () => { const parseSpy = vi.spyOn(schema, 'parse'); const parseAsyncSpy = vi.spyOn(schema, 'parseAsync'); - const result = await zodResolver(schema, undefined, { - mode: 'sync', - })(validData, undefined, { fields, shouldUseNativeValidation }); + const result = await zodResolverSync(schema, undefined)(validData, undefined, { fields, shouldUseNativeValidation }); expect(parseSpy).toHaveBeenCalledTimes(1); expect(parseAsyncSpy).not.toHaveBeenCalled(); @@ -45,9 +43,7 @@ describe('zodResolver', () => { const parseSpy = vi.spyOn(schema, 'parse'); const parseAsyncSpy = vi.spyOn(schema, 'parseAsync'); - const result = await zodResolver(schema, undefined, { - mode: 'sync', - })(invalidData, undefined, { fields, shouldUseNativeValidation }); + const result = await zodResolverSync(schema, undefined)(invalidData, undefined, { fields, shouldUseNativeValidation }); expect(parseSpy).toHaveBeenCalledTimes(1); expect(parseAsyncSpy).not.toHaveBeenCalled(); @@ -65,7 +61,7 @@ describe('zodResolver', () => { }); it('should return all the errors from zodResolver when validation fails with `validateAllFieldCriteria` set to true and `mode: sync`', async () => { - const result = await zodResolver(schema, undefined, { mode: 'sync' })( + const result = await zodResolverSync(schema, undefined)( invalidData, undefined, { diff --git a/zod/src/types.ts b/zod/src/types.ts index eae802ce..f6c693ba 100644 --- a/zod/src/types.ts +++ b/zod/src/types.ts @@ -6,9 +6,21 @@ export type Resolver = >( schemaOptions?: Partial, factoryOptions?: { /** - * @default async + * Return the raw input values rather than the parsed values. + * @default false */ - mode?: 'async' | 'sync'; + raw?: boolean; + }, +) => ( + values: TFieldValues, + context: TContext | undefined, + options: ResolverOptions, +) => Promise>; + +export type ResolverSync = >( + schema: T, + schemaOptions?: Partial, + factoryOptions?: { /** * Return the raw input values rather than the parsed values. * @default false @@ -19,4 +31,4 @@ export type Resolver = >( values: TFieldValues, context: TContext | undefined, options: ResolverOptions, -) => Promise>; +) => ResolverResult; diff --git a/zod/src/zod.ts b/zod/src/zod.ts index 8a5e2416..1e369aaf 100644 --- a/zod/src/zod.ts +++ b/zod/src/zod.ts @@ -1,7 +1,7 @@ import { appendErrors, FieldError, FieldErrors } from 'react-hook-form'; import { z, ZodError } from 'zod'; import { toNestErrors, validateFieldsNatively } from '@hookform/resolvers'; -import type { Resolver } from './types'; +import type { Resolver, ResolverSync } from './types'; const isZodError = (error: any): error is ZodError => error.errors != null; @@ -59,9 +59,7 @@ export const zodResolver: Resolver = (schema, schemaOptions, resolverOptions = {}) => async (values, _, options) => { try { - const data = await schema[ - resolverOptions.mode === 'sync' ? 'parse' : 'parseAsync' - ](values, schemaOptions); + const data = await schema.parseAsync(values, schemaOptions); options.shouldUseNativeValidation && validateFieldsNatively({}, options); @@ -87,3 +85,34 @@ export const zodResolver: Resolver = throw error; } }; + +export const zodResolverSync: ResolverSync = + (schema, schemaOptions, resolverOptions = {}) => + (values, _, options) => { + try { + const data = schema.parse(values, schemaOptions); + + options.shouldUseNativeValidation && validateFieldsNatively({}, options); + + return { + errors: {} as FieldErrors, + values: resolverOptions.raw ? values : data, + }; + } catch (error: any) { + if (isZodError(error)) { + return { + values: {}, + errors: toNestErrors( + parseErrorSchema( + error.errors, + !options.shouldUseNativeValidation && + options.criteriaMode === 'all', + ), + options, + ), + }; + } + + throw error; + } + }; \ No newline at end of file