Skip to content

Commit

Permalink
fix(conform-zod): enable zod object coercion (#733)
Browse files Browse the repository at this point in the history
  • Loading branch information
edmundhung authored Sep 10, 2024
1 parent 3a7f02e commit 3b8abb4
Show file tree
Hide file tree
Showing 3 changed files with 79 additions and 11 deletions.
7 changes: 7 additions & 0 deletions .changeset/tender-kiwis-flash.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
---
'@conform-to/zod': patch
---

fix(conform-zod): enable zod object coercion

Conform should support nested fields with only checkboxes now. Fix #391.
33 changes: 22 additions & 11 deletions packages/conform-zod/coercion.ts
Original file line number Diff line number Diff line change
Expand Up @@ -185,17 +185,28 @@ export function enableTypeCoercion<Schema extends ZodTypeAny>(
}),
);
} else if (def.typeName === 'ZodObject') {
const shape = Object.fromEntries(
Object.entries(def.shape()).map(([key, def]) => [
key,
// @ts-expect-error see message above
enableTypeCoercion(def, cache),
]),
);
schema = new ZodObject({
...def,
shape: () => shape,
});
schema = any()
.transform((value) => {
if (typeof value === 'undefined') {
// Defaults it to an empty object
return {};
}

return value;
})
.pipe(
new ZodObject({
...def,
shape: () =>
Object.fromEntries(
Object.entries(def.shape()).map(([key, def]) => [
key,
// @ts-expect-error see message above
enableTypeCoercion(def, cache),
]),
),
}),
);
} else if (def.typeName === 'ZodEffects') {
if (isFileSchema(type as unknown as ZodEffects<any, any, any>)) {
schema = any()
Expand Down
50 changes: 50 additions & 0 deletions tests/conform-zod.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -524,6 +524,56 @@ describe('conform-zod', () => {
});
});

test('z.object', () => {
const schema = z.object({
a: z.object({
text: z.string({
required_error: 'required',
}),
flag: z.boolean({
required_error: 'required',
}),
}),
b: z
.object({
text: z.string({
required_error: 'required',
}),
flag: z.boolean({
required_error: 'required',
}),
})
.optional(),
});

expect(parseWithZod(createFormData([]), { schema })).toEqual({
status: 'error',
payload: {},
error: {
'a.text': ['required'],
'a.flag': ['required'],
},
reply: expect.any(Function),
});
expect(
parseWithZod(createFormData([['b.text', '']]), { schema }),
).toEqual({
status: 'error',
payload: {
b: {
text: '',
},
},
error: {
'a.text': ['required'],
'a.flag': ['required'],
'b.text': ['required'],
'b.flag': ['required'],
},
reply: expect.any(Function),
});
});

test('z.array', () => {
const createSchema = (
element: z.ZodTypeAny = z.string({
Expand Down

0 comments on commit 3b8abb4

Please sign in to comment.