Configuration & API reference
Register Zod schemas per route. With enable(), matching fetch calls get JSON bodies validated. Failures print a boxed message in the console; passes print nothing (console only). Manual validateRequest / validateResponse return a ValidationResult.
1. Four steps
- Install
schelo+zod. - Add a file (e.g.
lib/api-schemas.ts) withcreateInterceptorand Zod imports. - Pass
routes(and optionalrequest/response/validate: falseper route). - Call
enable()at startup, or use the Next.js CLI +InterceptorProvider.
2. Route keys
"METHOD /path" — e.g. GET /api/health, GET /api/users/:id. Pathname only; query and host ignored.
3. createInterceptor options
Besides required routes:
| Option | Type | Default | What it does |
|---|---|---|---|
mode | "observe" | "warn" | "strict" | "observe" | On failure: observe → console.log; warn → console.warn; strict → console.error + throw. Success: silent. |
routes | record of route schemas | — | Required. |
warnOnUnmatched | boolean | false | console.warn when no route matches (no box). |
debug | boolean | false | Match debug lines when not production. |
consoleAggregation | "off" | "array" | "array" | array: merge repeated array-index errors when possible. off: one line per error (0.title, …). |
4. Route entry fields
Per routes["METHOD /path"]:
| Field | Type | Default | Meaning |
|---|---|---|---|
request | Zod schema | — | Validate JSON you send (optional). |
response | Zod schema | — | Validate JSON you receive (optional). |
validate | boolean | true | false = skip route (no validation, no failure box). |
5. Types
ValidationResult: valid, errors, optional log (LogEntry) if a route matched.
FieldError: path, message, expected/received. LogEntry: method, path, pattern, direction, errors, mode, optional statusCode.
6. Minimal example
import { createInterceptor } from "schelo";
import { z } from "zod";
export const interceptor = createInterceptor({
mode: "warn",
routes: {
"GET /api/health": {
response: z.object({ status: z.literal("ok") }),
},
},
});
// After creating the instance (e.g. in app entry or provider):
// interceptor.enable();import { createInterceptor } from "schelo";
import { z } from "zod";
export const interceptor = createInterceptor({
mode: "warn",
routes: {
"GET /api/health": {
response: z.object({ status: z.literal("ok") }),
},
},
});
// After creating the instance (e.g. in app entry or provider):
// interceptor.enable();7. Full example
import { createInterceptor } from "schelo";
import { z } from "zod";
const userSchema = z.object({
id: z.string(),
name: z.string(),
email: z.string().email(),
});
const apiErrorSchema = z.object({ error: z.string() });
export const interceptor = createInterceptor({
mode: "warn",
warnOnUnmatched: true,
debug: true,
consoleAggregation: "array",
routes: {
"GET /api/users/:id": {
response: z.union([userSchema, apiErrorSchema]),
},
"POST /api/login": {
validate: false,
request: z.object({
email: z.string().email(),
password: z.string().min(1),
}),
response: z.object({
accessToken: z.string(),
expiresIn: z.number(),
}),
},
},
});import { createInterceptor } from "schelo";
import { z } from "zod";
const userSchema = z.object({
id: z.string(),
name: z.string(),
email: z.string().email(),
});
const apiErrorSchema = z.object({ error: z.string() });
export const interceptor = createInterceptor({
mode: "warn",
warnOnUnmatched: true,
debug: true,
consoleAggregation: "array",
routes: {
"GET /api/users/:id": {
response: z.union([userSchema, apiErrorSchema]),
},
"POST /api/login": {
validate: false,
request: z.object({
email: z.string().email(),
password: z.string().min(1),
}),
response: z.object({
accessToken: z.string(),
expiresIn: z.number(),
}),
},
},
});Also: validateMatch, SchemaInterceptor — see README.