Skip to content

Commit

Permalink
fix/actions-default-values: set default values from zod if FormData k…
Browse files Browse the repository at this point in the history
…ey is not present
  • Loading branch information
billy-le committed Aug 8, 2024
1 parent 6b99523 commit 1b964dc
Show file tree
Hide file tree
Showing 3 changed files with 68 additions and 0 deletions.
5 changes: 5 additions & 0 deletions .changeset/nervous-garlics-beam.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'astro': patch
---

Set action input default values from zod if FormData key is not present
15 changes: 15 additions & 0 deletions packages/astro/src/actions/runtime/virtual/server.ts
Original file line number Diff line number Diff line change
Expand Up @@ -137,6 +137,21 @@ export function formDataToObject<T extends z.AnyZodObject>(
while (validator instanceof z.ZodOptional || validator instanceof z.ZodNullable) {
validator = validator._def.innerType;
}

// use zod default value when key is undefined
// else continue to get correct zod class
if(validator instanceof z.ZodDefault) {
if(!formData.has(key)) {
obj[key] = validator._def.defaultValue();
continue;
}

while (validator instanceof z.ZodOptional || validator instanceof z.ZodNullable) {
validator = validator._def.innerType;
}
}


if (validator instanceof z.ZodBoolean) {
obj[key] = formData.has(key);
} else if (validator instanceof z.ZodArray) {
Expand Down
48 changes: 48 additions & 0 deletions packages/astro/test/units/actions/form-data-to-object.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,37 @@ describe('formDataToObject', () => {
assert.equal(res.age, null);
});

it('should handle zod default values', () => {
const formData = new FormData();

const input = z.object({
name: z.string().default("test"),
email: z.string().default('[email protected]'),
favoriteNumbers: z.array(z.number()).default([1,2])
});

const res = formDataToObject(formData, input);
assert.equal(res.name, 'test');
assert.equal(res.email, '[email protected]');
assert.deepEqual(res.favoriteNumbers, [1, 2]);
})

it('should handle zod chaining of optional, default, and nullish values', () => {
const formData = new FormData();
formData.set('email', '[email protected]')

const input = z.object({
name: z.string().default("test").optional(),
email: z.string().optional().nullish(),
favoriteNumbers: z.array(z.number()).default([1,2]).nullish().optional()
});

const res = formDataToObject(formData, input);
assert.equal(res.name, 'test');
assert.equal(res.email, '[email protected]');
assert.deepEqual(res.favoriteNumbers, [1, 2])
})

it('should handle File objects', () => {
const formData = new FormData();
formData.set('file', new File([''], 'test.txt'));
Expand Down Expand Up @@ -135,4 +166,21 @@ describe('formDataToObject', () => {
assert.ok(Array.isArray(res.age), 'age is not an array');
assert.deepEqual(res.age.sort(), [25, 30, 35]);
});

it('should handle an array of File objects', () => {
const formData = new FormData();
const file1 = new File([''], 'test1.txt');
const file2 = new File([''], 'test2.txt')
formData.append('files', file1);
formData.append('files', file2);

const input = z.object({
files: z.array(z.instanceof(File))
});

const res = formDataToObject(formData, input);

assert.equal(res.files instanceof Array, true);
assert.deepEqual(res.files, [file1, file2])
});
});

0 comments on commit 1b964dc

Please sign in to comment.