| import type { Request, Response, NextFunction } from 'express'; |
| import { AnyZodObject, z } from 'zod'; |
| import { badRequest } from '@hapi/boom'; |
|
|
| function indent(str: string, spaces: number) { |
| return str |
| .split('\n') |
| .map(line => ' '.repeat(spaces) + line) |
| .join('\n'); |
| } |
|
|
| function extractZodMessage(error: any): string { |
| if (Array.isArray(error)) { |
| return error.map(extractZodMessage).join('\n'); |
| } else { |
| let union: string[] = []; |
| if ('unionErrors' in error) { |
| union = error.unionErrors.map(extractZodMessage); |
| } else if ('issues' in error) { |
| union = error.issues.map(extractZodMessage); |
| } |
| if ( |
| 'message' in error && |
| typeof error.message === 'string' && |
| !error.message.includes('\n') |
| ) { |
| if (union.length === 0) return error.message; |
| return error.message + '\n' + indent(union.join('\n'), 2); |
| } else if (union.length > 0) { |
| return union.join('\n'); |
| } else { |
| return ''; |
| } |
| } |
| } |
|
|
| export async function validate<T extends AnyZodObject>( |
| req: Request, |
| schema: T |
| ): Promise<z.infer<T>> { |
| try { |
| return await schema.parseAsync(req); |
| } catch (error: any) { |
| throw badRequest(extractZodMessage(error)); |
| } |
| } |
|
|
| export function wrap( |
| fn: (req: Request, res: Response, next: NextFunction) => Promise<any> |
| ) { |
| return async function (req: Request, res: Response, next: NextFunction) { |
| try { |
| return await fn(req, res, next); |
| } catch (err) { |
| next(err); |
| } |
| }; |
| } |
|
|