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

  1. Install schelo + zod.
  2. Add a file (e.g. lib/api-schemas.ts) with createInterceptor and Zod imports.
  3. Pass routes (and optional request / response / validate: false per route).
  4. 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:

OptionTypeDefaultWhat it does
mode"observe" | "warn" | "strict""observe"On failure: observe console.log; warn console.warn; strict console.error + throw. Success: silent.
routesrecord of route schemasRequired.
warnOnUnmatchedbooleanfalseconsole.warn when no route matches (no box).
debugbooleanfalseMatch 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"]:

FieldTypeDefaultMeaning
requestZod schemaValidate JSON you send (optional).
responseZod schemaValidate JSON you receive (optional).
validatebooleantruefalse = 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();

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(),
      }),
    },
  },
});

Also: validateMatch, SchemaInterceptor — see README.