SchemaParser

Request validation against the schemas declared in a RouteConfig.

Schemas are taken as Standard Schema, so any library implementing that spec works — Zod, Valibot, ArkType and others — without corpus depending on any of them. The same interface also supplies the inferred types that flow into Context, so declaring a schema both validates the request and types the handler.

App calls this after each surface is parsed, so what a handler sees on Context.body, Context.search and Context.params is already validated. A failure raises Status.UNPROCESSABLE_ENTITY with a message naming the offending fields, so the client is told what was wrong rather than just that something was.

Contents
  1. SchemaParserInterface
  2. SchemaParser
  3. Schema
  4. InferSchemaIn
  5. InferSchemaOut
  6. ValidationIssues
  7. InferModel

SchemaParserInterface

interface

interface SchemaParserInterface

The public shape of a schema parser, implemented by SchemaParser. Assign an alternative to ParsersRegistry.schemaParser to change how validation failures are reported.

SchemaParserInterface.parse()

parse<T = Record<string, unknown>>(label: string, input: unknown, schema?: Schema<T>): Promise<T>

Validates a value against a schema.

Parameters

Returns — The validated value.

SchemaParserInterface.parseSync()

parseSync<T = Record<string, unknown>>(label: string, input: unknown, schema?: Schema<T>): T

Validates a value against a synchronous schema.

Parameters

Returns — The validated value.

SchemaParser

class

class SchemaParser implements SchemaParserInterface

Default SchemaParserInterface implementation.

A missing schema is not an error — the value passes through untouched, which is what makes RouteConfig entirely optional.

SchemaParser.parse()

async parse<T = Record<string, unknown>>(label: string, data: unknown, schema?: Schema<T>, ): Promise<T>

Validates a value against a schema.

This is what App uses during the request lifecycle, since a schema may validate asynchronously.

Parameters

Returns — The validated value, with whatever transformations the schema applies.

Throws — Exception with Status.UNPROCESSABLE_ENTITY when validation fails, carrying the rejected data as exception data.

SchemaParser.parseSync()

parseSync<T = Record<string, unknown>>(label: string, data: unknown, schema?: Schema<T>): T

Validates a value without awaiting, for callers that cannot be async.

Whether a schema validates synchronously is not visible in its type, so it is detected at runtime: a validator that returns a promise is rejected outright rather than having its result silently used as a value.

Parameters

Returns — The validated value.

Throws — Error when the schema validates asynchronously — use SchemaParser.parse instead.

Throws — Exception with Status.UNPROCESSABLE_ENTITY when validation fails.

SchemaParser.issuesToErrorMessage()

issuesToErrorMessage(label: string, data: unknown, issues: ValidationIssues): string

Renders validation issues into the message sent to the client.

Each issue is reported as in <label> <path> (received <value>): <message>, so a client can see which field failed and what it actually sent — a schema's own message alone rarely says which field it came from. Path segments are joined with dots, and the offending value is looked up by walking the original data along that path. Issues with no path are global to the surface and keep their message unadorned.

Override this to change the wording or to withhold the received values.

Parameters

Returns — One line per issue, newline-joined, or an empty string when there are none.

Schema

type

type Schema<T = unknown> = StandardSchemaV1<unknown, T>;

Any Standard Schema validator producing T. This is the type RouteConfig fields accept.

Type parameters

InferSchemaIn

type

type InferSchemaIn<T extends Schema> = StandardSchemaV1.InferInput<T>;

The type a schema accepts as input, before transformation.

Type parameters

InferSchemaOut

type

type InferSchemaOut<T extends Schema> = StandardSchemaV1.InferOutput<T>;

The type a schema produces after validation. This is what a route's Context fields are typed as.

Type parameters

ValidationIssues

type

type ValidationIssues = readonly StandardSchemaV1.Issue[];

The validation failures a schema reports.

InferModel

type

type InferModel<T extends Record<string, any>> = {
	[K in keyof T as K extends "prototype" ? never : K]: T[K] extends RouteConfig<any, any, any, any>
		? Prettify<
				(T[K]["body"] extends Schema ? { body: InferSchemaOut<T[K]["body"]> } : {}) &
					(T[K]["search"] extends Schema ? { search: InferSchemaOut<T[K]["search"]> } : {}) &
					(T[K]["params"] extends Schema ? { params: InferSchemaOut<T[K]["params"]> } : {}) &
					(T[K]["response"] extends Schema ? { response: InferSchemaOut<T[K]["response"]> } : {})
			>
		: T[K] extends Schema
			? InferSchemaOut<T[K]>
			: never;
};

If you prefer to put all schemas into a single object, this will be helpful