accept ZOD validator
radoslavirha opened this issue · comments
Support plan
- is this issue currently blocking your project? (yes/no): no
- is this issue affecting a production system? (yes/no): no
Context
- node version: 16.16.0
- module version: 21.1.0
- environment (e.g. node, browser, native): node
- used with (e.g. hapi application, another framework, standalone, ...): hapi application
- any other relevant information:
How can we help?
Basically I would like to replace Joi with ZOD (better with typescript, type inference). I can set my own validation on each route, validate payload/params/query and return error/pass. But Hapi always adds own validation
object in returned error, I would say it expects Joi errror and is written to parse it. It would be nice to accept ZOD on route validation.
Just set?:
server.validator(z);
and use
{
method: 'POST',
path: `/validate`,
handler: (req, h) => h.response().code(200),
options: {
validate: {
payload: z.object({
a: z.string(),
b: z.string()
})
}
}
}
instead of:
{
method: 'POST',
path: `/validate`,
handler: (req, h) => h.response().code(200),
options: {
validate: {
payload: Joi.object({
a: Joi.string().required(),
b: Joi.string().required()
})
}
}
}
I can create validators and infere types in separate files, and use it as needed.
Thanks
It should just be a handful of lines of code to get basic zod support working. Here's a working example: https://runkit.com/devinivy/63c4627a352d980008baa41b. The core idea is this:
const zodValidator = {
compile: (schema) => ({
validate: (val) => schema.parse(val)
})
};
server.validator(zodValidator);
Is it something that the hapi team considers to be the right way?
I know, I just want to know if it's kind of hack or it could be implemented natively in future :)
I'm not a zod user, but the solution looks legit to me. I'll let Devin comment further.
Yep, you should be good to go! Any change to this validator interface would be considered a breaking change to hapi, i.e. it's considered part of our API. If anyone is interested in calling this out more explicitly in the docs, would happily take a PR!
I'll try to implement it partially in the next weeks (there are tons of Joi validators on the routes). Maybe I'll find out something interesting and let you know!
I'm still in researching stage right now.
Thanks
If you want to change your validator piecemeal, you can also specify the validator in each individual route config. E.g. this would work:
server.route({
method: 'post',
path: '/validate',
handler: () => ({ success: true }),
options: {
validate: {
validator: zodValidator, // Can specify a validator just for this route
payload: z.object({
foo: z.number().int(),
bar: z.string().optional()
})
}
}
});