|
1 | | -import { NextFunction, Request, Response } from 'express' |
2 | | -import { z } from 'zod' |
| 1 | +import type { NextFunction, Request, Response } from 'express' |
| 2 | + |
| 3 | +import * as z from 'zod' |
| 4 | + |
| 5 | +type ValidateRequest<B, P, Q> = { |
| 6 | + body?: B |
| 7 | + params?: P |
| 8 | + query?: Q |
| 9 | +} |
3 | 10 |
|
4 | 11 | export const validateRequest = |
5 | 12 | <B extends z.ZodSchema, P extends z.ZodSchema, Q extends z.ZodSchema>({ |
6 | | - body, |
7 | | - params, |
8 | | - query |
9 | | - }: { |
10 | | - body?: B |
11 | | - params?: P |
12 | | - query?: Q |
13 | | - }) => |
| 13 | + body: bodySchema, |
| 14 | + params: paramsSchema, |
| 15 | + query: querySchema |
| 16 | + }: ValidateRequest<B, P, Q>) => |
14 | 17 | ( |
15 | 18 | req: Request<z.infer<P>, unknown, z.infer<B>, z.infer<Q>>, |
16 | 19 | res: Response, |
17 | 20 | next: NextFunction |
18 | 21 | ) => { |
19 | | - try { |
20 | | - if (body) body.parse(req.body) |
21 | | - |
22 | | - if (params) params.parse(req.params) |
23 | | - |
24 | | - if (query) query.parse(req.query) |
25 | | - |
26 | | - next() |
27 | | - } catch (e) { |
28 | | - if (e instanceof z.ZodError) { |
29 | | - const errors = Object.fromEntries( |
30 | | - Object.entries(e.flatten().fieldErrors).map(([key, value]) => [ |
31 | | - key, |
32 | | - value?.join(', ') |
33 | | - ]) |
34 | | - ) |
35 | | - res.status(400).json({ statusCode: 400, messages: errors }) |
| 22 | + const errors: Record<string, string> = {} |
| 23 | + |
| 24 | + const parseAndValidate = <T extends z.ZodSchema>( |
| 25 | + data: Pick<Request, 'body' | 'params' | 'query'>, |
| 26 | + schema?: T |
| 27 | + ) => { |
| 28 | + if (!schema) return data |
| 29 | + |
| 30 | + try { |
| 31 | + return schema.parse(data) |
| 32 | + } catch (e) { |
| 33 | + if (e instanceof z.ZodError) { |
| 34 | + e.errors.forEach(({ path, message }) => { |
| 35 | + const errorPath = `${path.join('.')}` |
| 36 | + errors[errorPath] = message |
| 37 | + }) |
| 38 | + } |
36 | 39 | } |
37 | 40 | } |
| 41 | + |
| 42 | + parseAndValidate(req.body, bodySchema) |
| 43 | + parseAndValidate(req.params, paramsSchema) |
| 44 | + parseAndValidate(req.query, querySchema) |
| 45 | + |
| 46 | + if (Object.keys(errors).length > 0) { |
| 47 | + return res.status(400).json({ statusCode: 400, messages: errors }) |
| 48 | + } |
| 49 | + |
| 50 | + next() |
38 | 51 | } |
0 commit comments