Validation
DaloyJS validates inputs through Standard Schema — a tiny interface that Zod, Valibot, ArkType, and TypeBox all implement. Pick whichever validator fits your project.
What gets validated
For each route you can declare schemas for:
request.params— path parameters (always strings; coerce in your schema if needed).request.query— query string.request.headers— request headers.request.body— parsed JSON body. Only read when declared (no overhead otherwise).responses[status].body— typed responses.
Example with Zod
import { z } from "zod";
app.route({
method: "POST",
path: "/orders",
operationId: "createOrder",
request: {
body: z.object({
sku: z.string(),
qty: z.number().int().positive(),
}),
},
responses: {
201: {
description: "Created",
body: z.object({ id: z.string().uuid(), sku: z.string(), qty: z.number() }),
},
422: { description: "Validation failed" },
},
handler: async ({ body }) => ({
status: 201,
body: { id: crypto.randomUUID(), sku: body.sku, qty: body.qty },
}),
});On invalid input, DaloyJS returns 422 Unprocessable Entity as RFC 9457 problem+json with the per-issue path and message array.
Body limits and content types
When a route declares request.body, DaloyJS will also enforce:
- Content-Length / streamed size against
app.bodyLimitBytes→ 413. - Content-Type against
app.allowedContentTypes(defaultapplication/json) → 415. - Prototype-pollution-safe JSON parsing (
__proto__,constructor,prototypestripped).
Other validators
// Valibot
import * as v from "valibot";
const Body = v.object({ sku: v.string(), qty: v.pipe(v.number(), v.integer(), v.minValue(1)) });
// ArkType
import { type } from "arktype";
const Body = type({ sku: "string", qty: "1<=number.integer" });
// TypeBox
import { Type } from "@sinclair/typebox";
const Body = Type.Object({ sku: Type.String(), qty: Type.Integer({ minimum: 1 }) });All four expose a ~standard property that DaloyJS picks up automatically.
Type inference
Whatever validator you use, the handler context is fully typed: body, params,query, and headers are inferred from your schemas. The return value is also typed — TypeScript yells if you return a status not declared in responses.