-
-
Notifications
You must be signed in to change notification settings - Fork 29
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[FEATURE] [v7] Support schema nested objects validation #51
Comments
Hi @alexambrinos, thank you for opening this issue. I understand the problem and yes, it would be nice to be able to pass multiple schemas into a single input object. next-safe-action, since version 6, uses TypeSchema under the hood to support a wide range of validation libraries, so it's no longer tied to just Zod, therefore it can't and doesn't use When I released version 6, I wrote a custom function to build the The only (robust) solution that comes to mind is to return the actual With a schema like this one: const schema = z.object({
productSchema: z.object({
name: z.string().min(1).max(30),
}),
userSchema: z.object({
username: z.string().min(1).max(20),
}),
}); Assuming that validation fails for both nested properties, you get back a broken {
productSchema: [
"String must contain at least 1 character(s)"
],
name: [
"String must contain at least 1 character(s)"
],
userSchema: [
"String must contain at least 1 character(s)"
],
username: [
"String must contain at least 1 character(s)"
]
} Instead, if we rely on the "raw" issues array of objects from TypeSchema, we get back something like this: [
{
message: "String must contain at least 1 character(s)",
path: ["productSchema", "name"]
},
{
message: "String must contain at least 1 character(s)",
path: ["userSchema", "username"]
}
] I honestly think that the second one is much more reliable, since it allows granular control over validation errors, with the only drawback of being a little more verbose. It's also a breaking change though, so it requires some thinking to understand if it's the best approach for this problem, but I'm pretty confident it is. Please let me know what you think about it. If we all agree that this is the best way to handle validation errors from now on, I'll include these changes in next-safe-action v7. Thank you! |
A different approach would be to emulate (recreate) the |
I'd vote for emulating |
BREAKING CHANGE: `validationErrors` object now follows the same structure as Zod's [`format()`](https://zod.dev/ERROR_HANDLING?id=formatting-errors) function. re #51
The |
It returns the errors nested perfectly! The only problem I saw when trying to implement it is if I |
I cannot reproduce the issue. Can you please provide a link to an example repo/StackBlitz project so I can investigate the problem? Thank you! |
I managed to reproduce it. If your nested object is optional... with this schema:
It works fine and But, if I adjust the schema and make customer optional:
It shows that The infered type of
|
Sorry, haven't had the time to get into why that was happening, but I can confirm that my address schema was optional, since the user decides if they want to insert the address now or later. |
It's caused by the export type SchemaErrors<S> = {
[K in keyof S]?: S[K] extends object ? Extend<ErrorList & SchemaErrors<S[K]>> : ErrorList;
} & {}; this adjustment seems to fix it: type SchemaErrorValue<Value> = Value extends object ? Extend<ErrorList & SchemaErrors<Value>> : ErrorList;
type IsNullable<T> = undefined extends T ? true : null extends T ? true : false;
export type SchemaErrors<S> = {
[K in keyof S]?: IsNullable<S[K]> extends true ? SchemaErrorValue<NonNullable<S[K]>> : SchemaErrorValue<S[K]>;
} & {}; |
Thank you @theboxer for your findings. I just tried to declare the export type SchemaErrors<S> = {
[K in keyof S]?: S[K] extends object | null | undefined
? Extend<ErrorList & SchemaErrors<S[K]>>
: ErrorList;
} & {}; |
Should be fixed in |
Are you using the latest version of this library?
Is there an existing issue for this?
Suggest an idea
I wanted to implement a form where a user enters the customer info and the address info at the same time. I've made a custom zod validation like this:
z.object({address: addressSchema, customer: customerSchema })
I did it this way since I can automatically get the schema from drizzle-orm based on the db.
But the problem i faced when implementing this is that the zod validation breaks since flatten() can't have nested objects. Wouldn't it be better to implement the zod validation errors using the format() function instead so we can have nested objects?
The way I need to implement it currently is using two different actions so each form has it's own validation but I lose the ability to add the customer and address in a db transaction since they will be sepparate.
Additional context
No response
The text was updated successfully, but these errors were encountered: