Skip to content

Instantly share code, notes, and snippets.

@raynirola
Last active December 28, 2023 11:52
Show Gist options
  • Save raynirola/d4fdb99f49f377b592bb0f4e1f615b68 to your computer and use it in GitHub Desktop.
Save raynirola/d4fdb99f49f377b592bb0f4e1f615b68 to your computer and use it in GitHub Desktop.
Higher Order Function that wraps Next Api handler with Zod validation library, handles errors as well.
import { ZodError, ZodTypeAny, z } from 'zod'
import type { NextApiHandler, NextApiRequest, NextApiResponse } from 'next'
interface WithZodArgs<T> {
schema: T
method?: NextApiRequest['method']
}
interface ZodRequest<T> extends NextApiRequest {
body: T
}
export interface NextApiHandlerWithZod<T extends ZodTypeAny> {
(req: ZodRequest<z.infer<T>>, res: NextApiResponse): Promise<void>
}
interface WithZod {
<T extends ZodTypeAny>(handler: NextApiHandlerWithZod<T>, options: WithZodArgs<T>): NextApiHandler
}
const withZod: WithZod = (handler, options) => async (req, res) => {
const { schema, method } = options
if (method && req.method !== method) {
return res
.setHeader('Allow', method)
.status(405)
.json({
name: 'MethodNotAllowed',
message: `Cannot ${req.method} ${req.url}`
})
}
try {
await schema.parseAsync(req.body)
return handler(req, res)
} catch (error) {
if (error instanceof ZodError<typeof schema._type>) {
return res.status(400).json({
name: 'ValidationError',
errors: (error as ZodError<typeof schema._type>).formErrors.fieldErrors
})
}
}
}
export default withZod
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment