Skip to content

Commit

Permalink
feat: add Zod sync validation (#114)
Browse files Browse the repository at this point in the history
  • Loading branch information
jorisre authored Jan 21, 2021
1 parent b7dd0e6 commit 22e7545
Show file tree
Hide file tree
Showing 4 changed files with 88 additions and 16 deletions.
40 changes: 40 additions & 0 deletions zod/src/__tests__/__snapshots__/zod.ts.snap
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,46 @@ Object {
}
`;

exports[`zodResolver should return a single error from zodResolver with \`mode: sync\` when validation fails 1`] = `
Object {
"errors": Object {
"birthYear": Object {
"message": "Invalid input",
"type": "invalid_union",
},
"confirm": Object {
"message": "Passwords don't match",
"type": "custom_error",
},
"email": Object {
"message": "Invalid email",
"type": "invalid_string",
},
"enabled": Object {
"message": "Required",
"type": "invalid_type",
},
"password": Object {
"message": "Invalid",
"type": "invalid_string",
},
"repeatPassword": Object {
"message": "Required",
"type": "invalid_type",
},
"tags": Object {
"message": "Required",
"type": "invalid_type",
},
"username": Object {
"message": "Required",
"type": "invalid_type",
},
},
"values": Object {},
}
`;

exports[`zodResolver should return all the errors from zodResolver when validation fails with \`validateAllFieldCriteria\` set to true 1`] = `
Object {
"errors": Object {
Expand Down
28 changes: 28 additions & 0 deletions zod/src/__tests__/zod.ts
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,22 @@ describe('zodResolver', () => {
expect(result).toEqual({ errors: {}, values: data });
});

it('should return values from zodResolver with `mode: sync` when validation pass', async () => {
const data: z.infer<typeof schema> = {
username: 'Doe',
password: 'Password123',
repeatPassword: 'Password123',
birthYear: 2000,
email: '[email protected]',
tags: ['tag1', 'tag2'],
enabled: true,
};

const result = await zodResolver(schema, undefined, { mode: 'sync' })(data);

expect(result).toEqual({ errors: {}, values: data });
});

it('should return a single error from zodResolver when validation fails', async () => {
const data = {
password: '___',
Expand All @@ -46,6 +62,18 @@ describe('zodResolver', () => {
expect(result).toMatchSnapshot();
});

it('should return a single error from zodResolver with `mode: sync` when validation fails', async () => {
const data = {
password: '___',
email: '',
birthYear: 'birthYear',
};

const result = await zodResolver(schema, undefined, { mode: 'sync' })(data);

expect(result).toMatchSnapshot();
});

it('should return all the errors from zodResolver when validation fails with `validateAllFieldCriteria` set to true', async () => {
const data = {
password: '___',
Expand Down
3 changes: 2 additions & 1 deletion zod/src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,8 @@ import type { ParseParams } from 'zod/lib/src/parser';

export type Resolver = <T extends z.ZodSchema<any, any>>(
schema: T,
options?: ParseParams,
schemaOptions?: ParseParams,
resolverOptions?: { mode: 'async' | 'sync' },
) => <TFieldValues extends FieldValues, TContext>(
values: UnpackNestedValue<TFieldValues>,
context?: TContext,
Expand Down
33 changes: 18 additions & 15 deletions zod/src/zod.ts
Original file line number Diff line number Diff line change
Expand Up @@ -47,21 +47,24 @@ const parseErrorSchema = (
);
};

export const zodResolver: Resolver = (schema, options) => async (
values,
_,
validateAllFieldCriteria = false,
) => {
const result = schema.safeParse(values, options);
export const zodResolver: Resolver = (
schema,
schemaOptions,
{ mode } = { mode: 'async' },
) => async (values, _, validateAllFieldCriteria = false) => {
try {
const result =
mode === 'async'
? await schema.parseAsync(values, schemaOptions)
: schema.parse(values, schemaOptions);

if (result.success) {
return { values: result.data, errors: {} };
return { values: result, errors: {} };
} catch (error) {
return {
values: {},
errors: transformToNestObject(
parseErrorSchema(error, validateAllFieldCriteria),
),
};
}

return {
values: {},
errors: transformToNestObject(
parseErrorSchema(result.error, validateAllFieldCriteria),
),
};
};

0 comments on commit 22e7545

Please sign in to comment.