hapijs / hapi

The Simple, Secure Framework Developers Trust

Home Page:https://hapi.dev

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

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?

@radik24, @devinivy is part of the hapi team 😄

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()
            })
        }
    }
});