File size: 2,132 Bytes
4e23b01 | 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 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 | import { ErrorCode } from '../protocol/error-codes';
import type { z } from 'zod';
interface ValidationRequest {
id: string;
body?: unknown;
query?: unknown;
params?: unknown;
}
interface ValidationReply {
send(payload: unknown): unknown;
}
type PreHandlerHook = (
req: ValidationRequest,
reply: ValidationReply,
done: (err?: Error) => void,
) => void;
interface ValidationDetailItem {
path: string;
message: string;
}
function zodIssuesToDetails(error: z.ZodError): ValidationDetailItem[] {
return error.issues.map((issue) => ({
path: issue.path.join('.'),
message: issue.message,
}));
}
function buildValidationEnvelope(
details: ValidationDetailItem[],
requestId: string,
): {
code: number;
msg: string;
data: null;
request_id: string;
details: ValidationDetailItem[];
} {
const first = details[0];
const msg = first === undefined
? 'validation failed'
: first.path === ''
? first.message
: `${first.path}: ${first.message}`;
return {
code: ErrorCode.VALIDATION_FAILED,
msg,
data: null,
request_id: requestId,
details,
};
}
export function validateBody<T>(schema: z.ZodType<T>): PreHandlerHook {
return (req, reply, done) => {
const result = schema.safeParse(req.body);
if (!result.success) {
reply.send(buildValidationEnvelope(zodIssuesToDetails(result.error), req.id));
return;
}
req.body = result.data;
done();
};
}
export function validateQuery<T>(schema: z.ZodType<T>): PreHandlerHook {
return (req, reply, done) => {
const result = schema.safeParse(req.query);
if (!result.success) {
reply.send(buildValidationEnvelope(zodIssuesToDetails(result.error), req.id));
return;
}
req.query = result.data;
done();
};
}
export function validateParams<T>(schema: z.ZodType<T>): PreHandlerHook {
return (req, reply, done) => {
const result = schema.safeParse(req.params);
if (!result.success) {
reply.send(buildValidationEnvelope(zodIssuesToDetails(result.error), req.id));
return;
}
req.params = result.data;
done();
};
}
|