Skip to content

Commit

Permalink
Add support for Zod .refine and .superRefine (#1319)
Browse files Browse the repository at this point in the history
  • Loading branch information
piotrpospiech authored May 24, 2024
1 parent a77b8e2 commit 7d6db69
Show file tree
Hide file tree
Showing 2 changed files with 51 additions and 2 deletions.
43 changes: 43 additions & 0 deletions packages/uniforms-bridge-zod/__tests__/ZodBridge.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ import {
undefined as undefined_,
union,
unknown,
ZodIssueCode,
} from 'zod';

describe('ZodBridge', () => {
Expand Down Expand Up @@ -71,6 +72,42 @@ describe('ZodBridge', () => {
expect(bridge.getError('a.b', error)).toBe(null);
expect(bridge.getError('a.b.c', error)).toBe(issues?.[0]);
});

it('works with refined schema', () => {
const errorMessage = 'Different values';

const schema = object({
a: string(),
b: string(),
}).refine(({ a, b }) => a === b, {
message: errorMessage,
path: ['b'],
});

const bridge = new ZodBridge({ schema });
const error = bridge.getValidator()({ a: 'a', b: 'b' });
expect(error?.issues?.[0]?.message).toBe(errorMessage);
});

it('works with super refined schema', () => {
const errorMessage = 'Different values';

const schema = object({
a: string(),
b: string(),
}).superRefine((val, ctx) => {
if (val.a !== val.b) {
ctx.addIssue({
code: ZodIssueCode.custom,
message: errorMessage,
});
}
});

const bridge = new ZodBridge({ schema });
const error = bridge.getValidator()({ a: 'a', b: 'b' });
expect(error?.issues?.[0]?.message).toBe(errorMessage);
});
});

describe('#getErrorMessage', () => {
Expand Down Expand Up @@ -201,6 +238,12 @@ describe('ZodBridge', () => {
expect(bridge.getField('a')).toBe(schema.shape.a);
expect(bridge.getField('a.b')).toBe(schema.shape.a.unwrap().shape.b);
});

it('works with ZodEffects', () => {
const schema = object({}).refine(data => data);
const bridge = new ZodBridge({ schema });
expect(bridge.getField('')).toBe(schema._def.schema);
});
});

describe('#getInitialValue', () => {
Expand Down
10 changes: 8 additions & 2 deletions packages/uniforms-bridge-zod/src/ZodBridge.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import {
ZodBoolean,
ZodDate,
ZodDefault,
ZodEffects,
ZodEnum,
ZodError,
ZodIssue,
Expand Down Expand Up @@ -55,14 +56,14 @@ type Option<Value> = {
};

export default class ZodBridge<T extends ZodRawShape> extends Bridge {
schema: ZodObject<T>;
schema: ZodObject<T> | ZodEffects<ZodObject<T>>;
provideDefaultLabelFromFieldName: boolean;

constructor({
schema,
provideDefaultLabelFromFieldName = true,
}: {
schema: ZodObject<T>;
schema: ZodObject<T> | ZodEffects<ZodObject<T>>;
provideDefaultLabelFromFieldName?: boolean;
}) {
super();
Expand Down Expand Up @@ -106,6 +107,11 @@ export default class ZodBridge<T extends ZodRawShape> extends Bridge {

getField(name: string) {
let field: ZodType = this.schema;

if (this.schema instanceof ZodEffects) {
field = this.schema._def.schema;
}

for (const key of joinName(null, name)) {
if (field instanceof ZodDefault) {
field = field.removeDefault();
Expand Down

0 comments on commit 7d6db69

Please sign in to comment.