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( req: Request, schema: T ): Promise> { try { return await schema.parseAsync(req); } catch (error: any) { throw badRequest(extractZodMessage(error)); } } export function wrap( fn: (req: Request, res: Response, next: NextFunction) => Promise ) { return async function (req: Request, res: Response, next: NextFunction) { try { return await fn(req, res, next); } catch (err) { next(err); } }; }