validate
Validates domain accumulator (acc) properties against JSON Schemas compiled at factory
time using AJV. Supports body, query parameter,
and route parameter schemas. Includes ajv-formats for standard format
keywords (email, uri, date-time, uuid, etc.) out of the box
(fast mode by default for ReDoS safety).
Pipeline stage: Validation (after body() and url())
Import
Section titled “Import”import {validate} from '@centralping/ergo';Options
Section titled “Options”The validate() factory accepts two arguments: a schemas object and an
options object — validate(schemas, options).
Schemas (first argument)
Section titled “Schemas (first argument)”| Property | Type | Default | Description |
|---|---|---|---|
body |
object |
— | JSON Schema for the parsed request body |
query |
object |
— | JSON Schema for query parameters |
params |
object |
— | JSON Schema for route path parameters |
These are direct properties of the first argument, not nested under a
wrapper key. For example: validate({body: schema}), not
validate({schemas: {body: schema}}).
Shorthand Form (body-only)
Section titled “Shorthand Form (body-only)”A raw JSON Schema can be passed directly — it is interpreted as body
validation. The shorthand is detected when the first argument contains at
least one JSON Schema keyword and none of the targeted keys (body,
query, params).
validate({ type: 'object', properties: {name: {type: 'string'}}, required: ['name'],});Detection keywords include: type, properties, required, items,
$schema, $ref, $id, $defs, allOf, anyOf, oneOf, not,
if, enum, const, additionalProperties, patternProperties.
Precedence: The targeted form takes priority — when any of body,
query, or params is present, the object is always treated as a
targeted schema map regardless of other keys.
Empty object: {} is not treated as shorthand (no indicator keywords
are present) and produces no validators — validation is effectively skipped.
Options (second argument)
Section titled “Options (second argument)”| Property | Type | Default | Description |
|---|---|---|---|
formats |
boolean | string[] | object |
all standard (fast mode) | ajv-formats configuration |
formats Values
Section titled “formats Values”| Value | Behavior |
|---|---|
undefined or true |
All standard formats enabled in fast mode (simplified regexes — safe for untrusted input) |
false |
Formats disabled (AJV strict mode rejects unknown format keywords) |
['email', 'uri'] |
Only listed formats enabled (full-mode regexes — ReDoS risk with untrusted input) |
{mode: 'full'} |
All standard formats with strict RFC compliance (ReDoS exposure with untrusted input) |
{mode: 'fast'} |
Equivalent to the default — all standard formats in fast mode |
Route Parameter Resolution
Section titled “Route Parameter Resolution”Route parameters are resolved from acc.route?.params (ergo-router) with
a fallback to acc.params (standalone).
Return Value
Section titled “Return Value”The middleware returns undefined on success — validation is a gate, not
a data producer.
Error Responses
Section titled “Error Responses”| Status | Condition |
|---|---|
| 422 Unprocessable Entity | Validation failure — response includes details array with per-field errors |
| 500 Internal Server Error | A body schema is configured but acc.body is missing — body() middleware was not placed before validate() in the pipeline. Emits a one-time ERGO_VALIDATE_NO_BODY process warning |
Validation Error Response
Section titled “Validation Error Response”When validation fails, the 422 response body is an
RFC 9457 Problem Details object
with a details extension member containing per-field errors:
{ "type": "about:blank", "title": "Unprocessable Entity", "status": 422, "detail": "Validation failed", "details": [ { "path": "/name", "message": "must be string", "params": { "type": "string" } } ]}details Entry Shape
Section titled “details Entry Shape”| Property | Type | Description |
|---|---|---|
path |
string |
JSON Pointer to the failing field (e.g., '/name', '/address/zip'); '/' for root-level errors |
message |
string |
Human-readable error description from AJV |
params |
object |
Keyword-dependent parameters from the failing AJV rule |
The params object shape depends on which JSON Schema keyword failed:
| Keyword | params Example |
|---|---|
required |
{missingProperty: 'name'} |
type |
{type: 'string'} |
minLength |
{limit: 1} |
pattern |
{pattern: '^[a-z]+$'} |
For the complete list of keyword-specific params, see the
AJV error objects documentation.
Validation Order
Section titled “Validation Order”Targets are validated in order: body → query → params. The first
target that fails produces the 422 response — subsequent targets are
not validated. For example, if both body and query schemas are
configured and the body is invalid, only body errors appear in
details.
Targeted Form
Section titled “Targeted Form”import {compose, body, url, validate} from '@centralping/ergo';
const pipeline = compose( body(), url(), validate({ body: { type: 'object', properties: {name: {type: 'string'}}, required: ['name'], }, query: { type: 'object', properties: { page: {type: 'string', pattern: '^[0-9]+$'}, }, }, }),);router.post('/users', { validate: { body: { type: 'object', properties: {name: {type: 'string', format: 'email'}}, required: ['name'], }, params: { type: 'object', properties: {id: {type: 'string', minLength: 1}}, required: ['id'], }, }, execute: (req, res, acc) => ({ response: {statusCode: 201, body: {created: true}}, }),});Shorthand Form
Section titled “Shorthand Form”import {compose, body, validate} from '@centralping/ergo';
const pipeline = compose( body(), validate({ type: 'object', properties: {name: {type: 'string'}}, required: ['name'], }),);router.post('/users', { validate: { type: 'object', properties: {name: {type: 'string'}}, required: ['name'], }, execute: (req, res, acc) => ({ response: {statusCode: 201, body: {created: true}}, }),});RFC References
Section titled “RFC References”API Reference
Section titled “API Reference”See the auto-generated validate API docs.