File size: 1,502 Bytes
107b5c2 |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 |
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);
}
};
}
|