Skip to content

Commit

Permalink
feat(zod): formatted errors instead of flattened BREAKING CHANGE
Browse files Browse the repository at this point in the history
This enables nested field error checking as the `user.name` error in the test, which is no longer on the `user` field.
  • Loading branch information
MiroslavPetrik committed Sep 25, 2024
1 parent d36b0ab commit 45d9f79
Show file tree
Hide file tree
Showing 3 changed files with 42 additions and 36 deletions.
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "react-form-action",
"version": "1.0.1",
"version": "1.1.0",
"description": "State management helpers for the react form actions.",
"repository": {
"type": "git",
Expand Down
22 changes: 14 additions & 8 deletions src/formAction.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -171,11 +171,19 @@ describe("formAction", () => {
expect(result).toHaveProperty("data", null);
expect(result).toHaveProperty("error", null);
expect(result).toHaveProperty("validationError", {
fieldErrors: {
allright: ["Invalid input"],
user: ["String must contain at least 3 character(s)"],
_errors: [],
allright: {
_errors: [
'Invalid literal value, expected "on"',
"Invalid literal value, expected undefined",
],
},
user: {
_errors: [],
name: {
_errors: ["String must contain at least 3 character(s)"],
},
},
formErrors: [],
});
});
});
Expand Down Expand Up @@ -226,10 +234,8 @@ describe("formAction", () => {
);

expect(result).toHaveProperty("validationError", {
fieldErrors: {
confirm: ["Passwords don't match"],
},
formErrors: [],
_errors: [],
confirm: { _errors: ["Passwords don't match"] },
});
expect(result).toHaveProperty("error", null);
});
Expand Down
54 changes: 27 additions & 27 deletions src/formAction.ts
Original file line number Diff line number Diff line change
Expand Up @@ -164,34 +164,34 @@ function formActionBuilder<
schema === emptyInput
? undefined
: <Data>(action: SchemaAction<Data, Context, RealSchema>) => {
return createFormAction<
Data,
Err,
z.inferFlattenedErrors<RealSchema>
>(({ success, failure, invalid }) => {
const formDataSchema = zfd.formData(schema);

return async (state, formData) => {
const ctx = await createContext(formData);
const result = formDataSchema.safeParse(formData);

if (!result.success) {
return invalid(result.error.flatten());
}

const input = result.data as z.infer<RealSchema>;

try {
return success(await action({ input, ctx }));
} catch (error) {
if (processError) {
return failure(processError({ error, ctx }));
return createFormAction<Data, Err, z.inferFormattedError<RealSchema>>(
({ success, failure, invalid }) => {
const formDataSchema = zfd.formData(schema);

return async (state, formData) => {
const ctx = await createContext(formData);
const result = formDataSchema.safeParse(formData);

if (!result.success) {
return invalid(
result.error.format() as z.inferFormattedError<RealSchema>,
);
}
// must be handled by error boundary
throw error;
}
};
});

const input = result.data as z.infer<RealSchema>;

try {
return success(await action({ input, ctx }));
} catch (error) {
if (processError) {
return failure(processError({ error, ctx }));
}
// must be handled by error boundary
throw error;
}
};
},
);
};

return {
Expand Down

0 comments on commit 45d9f79

Please sign in to comment.