Skip to content

Commit 22e7545

Browse files
authored
feat: add Zod sync validation (#114)
1 parent b7dd0e6 commit 22e7545

File tree

4 files changed

+88
-16
lines changed

4 files changed

+88
-16
lines changed

zod/src/__tests__/__snapshots__/zod.ts.snap

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,46 @@ Object {
4040
}
4141
`;
4242

43+
exports[`zodResolver should return a single error from zodResolver with \`mode: sync\` when validation fails 1`] = `
44+
Object {
45+
"errors": Object {
46+
"birthYear": Object {
47+
"message": "Invalid input",
48+
"type": "invalid_union",
49+
},
50+
"confirm": Object {
51+
"message": "Passwords don't match",
52+
"type": "custom_error",
53+
},
54+
"email": Object {
55+
"message": "Invalid email",
56+
"type": "invalid_string",
57+
},
58+
"enabled": Object {
59+
"message": "Required",
60+
"type": "invalid_type",
61+
},
62+
"password": Object {
63+
"message": "Invalid",
64+
"type": "invalid_string",
65+
},
66+
"repeatPassword": Object {
67+
"message": "Required",
68+
"type": "invalid_type",
69+
},
70+
"tags": Object {
71+
"message": "Required",
72+
"type": "invalid_type",
73+
},
74+
"username": Object {
75+
"message": "Required",
76+
"type": "invalid_type",
77+
},
78+
},
79+
"values": Object {},
80+
}
81+
`;
82+
4383
exports[`zodResolver should return all the errors from zodResolver when validation fails with \`validateAllFieldCriteria\` set to true 1`] = `
4484
Object {
4585
"errors": Object {

zod/src/__tests__/zod.ts

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,22 @@ describe('zodResolver', () => {
3434
expect(result).toEqual({ errors: {}, values: data });
3535
});
3636

37+
it('should return values from zodResolver with `mode: sync` when validation pass', async () => {
38+
const data: z.infer<typeof schema> = {
39+
username: 'Doe',
40+
password: 'Password123',
41+
repeatPassword: 'Password123',
42+
birthYear: 2000,
43+
44+
tags: ['tag1', 'tag2'],
45+
enabled: true,
46+
};
47+
48+
const result = await zodResolver(schema, undefined, { mode: 'sync' })(data);
49+
50+
expect(result).toEqual({ errors: {}, values: data });
51+
});
52+
3753
it('should return a single error from zodResolver when validation fails', async () => {
3854
const data = {
3955
password: '___',
@@ -46,6 +62,18 @@ describe('zodResolver', () => {
4662
expect(result).toMatchSnapshot();
4763
});
4864

65+
it('should return a single error from zodResolver with `mode: sync` when validation fails', async () => {
66+
const data = {
67+
password: '___',
68+
email: '',
69+
birthYear: 'birthYear',
70+
};
71+
72+
const result = await zodResolver(schema, undefined, { mode: 'sync' })(data);
73+
74+
expect(result).toMatchSnapshot();
75+
});
76+
4977
it('should return all the errors from zodResolver when validation fails with `validateAllFieldCriteria` set to true', async () => {
5078
const data = {
5179
password: '___',

zod/src/types.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,8 @@ import type { ParseParams } from 'zod/lib/src/parser';
88

99
export type Resolver = <T extends z.ZodSchema<any, any>>(
1010
schema: T,
11-
options?: ParseParams,
11+
schemaOptions?: ParseParams,
12+
resolverOptions?: { mode: 'async' | 'sync' },
1213
) => <TFieldValues extends FieldValues, TContext>(
1314
values: UnpackNestedValue<TFieldValues>,
1415
context?: TContext,

zod/src/zod.ts

Lines changed: 18 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -47,21 +47,24 @@ const parseErrorSchema = (
4747
);
4848
};
4949

50-
export const zodResolver: Resolver = (schema, options) => async (
51-
values,
52-
_,
53-
validateAllFieldCriteria = false,
54-
) => {
55-
const result = schema.safeParse(values, options);
50+
export const zodResolver: Resolver = (
51+
schema,
52+
schemaOptions,
53+
{ mode } = { mode: 'async' },
54+
) => async (values, _, validateAllFieldCriteria = false) => {
55+
try {
56+
const result =
57+
mode === 'async'
58+
? await schema.parseAsync(values, schemaOptions)
59+
: schema.parse(values, schemaOptions);
5660

57-
if (result.success) {
58-
return { values: result.data, errors: {} };
61+
return { values: result, errors: {} };
62+
} catch (error) {
63+
return {
64+
values: {},
65+
errors: transformToNestObject(
66+
parseErrorSchema(error, validateAllFieldCriteria),
67+
),
68+
};
5969
}
60-
61-
return {
62-
values: {},
63-
errors: transformToNestObject(
64-
parseErrorSchema(result.error, validateAllFieldCriteria),
65-
),
66-
};
6770
};

0 commit comments

Comments
 (0)