Press n or j to go to the next uncovered block, b, p or k for the previous block.
| 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 | 19x 119x 20x 20x 20x 20x 22x 22x 22x 22x 20x | import { zValidator } from "@hono/zod-validator";
import type { ValidationTargets } from "hono";
import type { ZodSchema, ZodIssue } from "zod";
/**
* Wrapper around @hono/zod-validator that returns a stable, user-friendly
* validation error envelope. The default zValidator sends the full Zod result
* (including the stringified `issues` array) as the response — that array leaks
* into the UI as raw JSON.
*
* Response shape on validation failure:
* {
* success: false,
* error: {
* code: "VALIDATION_ERROR",
* message: "Please fix the errors below",
* fieldErrors: { phone: "Phone number must be at least 10 digits", ... }
* }
* }
*
* Drop-in replacement: same signature as zValidator for the common two-arg case.
*/
export function zv<T extends ZodSchema, Target extends keyof ValidationTargets>(
target: Target,
schema: T,
) {
return zValidator(target, schema, (result, c) => {
if (!result.success) {
const issues = (result.error as { issues: ZodIssue[] }).issues;
return c.json(
{
success: false,
error: {
code: "VALIDATION_ERROR",
message: "Please fix the errors below",
fieldErrors: flattenFieldErrors(issues),
},
},
400,
);
}
});
}
function flattenFieldErrors(issues: ZodIssue[]): Record<string, string> {
const fieldErrors: Record<string, string> = {};
for (const issue of issues) {
const path = issue.path.join(".");
const key = path || "_root";
// Keep the first message per field — good enough for inline UX.
Eif (!fieldErrors[key]) {
fieldErrors[key] = issue.message;
}
}
return fieldErrors;
}
|