Skip to content

Commit b7d3be2

Browse files
committed
doc(validator): validator documentation
1 parent c459aef commit b7d3be2

6 files changed

Lines changed: 356 additions & 1 deletion

File tree

doc/api/cli.md

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2013,6 +2013,14 @@ changes:
20132013

20142014
Disable the experimental [`node:sqlite`][] module.
20152015

2016+
### `--no-experimental-validator`
2017+
2018+
<!-- YAML
2019+
added: REPLACEME
2020+
-->
2021+
2022+
Disable the experimental [`node:validator`][] module.
2023+
20162024
### `--no-experimental-websocket`
20172025

20182026
<!-- YAML
@@ -3744,6 +3752,7 @@ one is included in the list below.
37443752
* `--no-experimental-repl-await`
37453753
* `--no-experimental-sqlite`
37463754
* `--no-experimental-strip-types`
3755+
* `--no-experimental-validator`
37473756
* `--no-experimental-websocket`
37483757
* `--no-experimental-webstorage`
37493758
* `--no-extra-info-on-fatal-exception`
@@ -4351,6 +4360,7 @@ node --stack-trace-limit=12 -p -e "Error.stackTraceLimit" # prints 12
43514360
[`node:ffi`]: ffi.md
43524361
[`node:sqlite`]: sqlite.md
43534362
[`node:stream/iter`]: stream_iter.md
4363+
[`node:validator`]: validator.md
43544364
[`process.setUncaughtExceptionCaptureCallback()`]: process.md#processsetuncaughtexceptioncapturecallbackfn
43554365
[`tls.DEFAULT_MAX_VERSION`]: tls.md#tlsdefault_max_version
43564366
[`tls.DEFAULT_MIN_VERSION`]: tls.md#tlsdefault_min_version

doc/api/errors.md

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3277,6 +3277,19 @@ transformation with [type-stripping][].
32773277

32783278
An attempt was made to use something that was already closed.
32793279

3280+
<a id="ERR_VALIDATOR_INVALID_SCHEMA"></a>
3281+
3282+
### `ERR_VALIDATOR_INVALID_SCHEMA`
3283+
3284+
<!-- YAML
3285+
added: REPLACEME
3286+
-->
3287+
3288+
Thrown by the [`node:validator`][] [`Schema`][] constructor when the schema
3289+
definition is malformed — for example, an unknown `type`, a constraint that
3290+
does not apply to the declared type, an invalid regular expression in
3291+
`pattern`, or a `required` entry not listed in `properties`.
3292+
32803293
<a id="ERR_VALID_PERFORMANCE_ENTRY_TYPE"></a>
32813294

32823295
### `ERR_VALID_PERFORMANCE_ENTRY_TYPE`
@@ -4440,6 +4453,7 @@ An error occurred trying to allocate memory. This should never happen.
44404453
[`new URL(input)`]: url.md#new-urlinput-base
44414454
[`new URLPattern(input)`]: url.md#new-urlpatternstring-baseurl-options
44424455
[`new URLSearchParams(iterable)`]: url.md#new-urlsearchparamsiterable
4456+
[`node:validator`]: validator.md
44434457
[`package.json`]: packages.md#nodejs-packagejson-field-definitions
44444458
[`postMessage()`]: worker_threads.md#portpostmessagevalue-transferlist
44454459
[`postMessageToThread()`]: worker_threads.md#worker_threadspostmessagetothreadthreadid-value-transferlist-timeout
@@ -4449,6 +4463,7 @@ An error occurred trying to allocate memory. This should never happen.
44494463
[`readable._read()`]: stream.md#readable_readsize
44504464
[`require('node:crypto').setEngine()`]: crypto.md#cryptosetengineengine-flags
44514465
[`require()`]: modules.md#requireid
4466+
[`Schema`]: validator.md#class-schema
44524467
[`server.close()`]: net.md#serverclosecallback
44534468
[`server.listen()`]: net.md#serverlisten
44544469
[`sign.sign()`]: crypto.md#signsignprivatekey-outputencoding

doc/api/index.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,7 @@
6565
* [URL](url.md)
6666
* [Utilities](util.md)
6767
* [V8](v8.md)
68+
* [Validator](validator.md)
6869
* [VM](vm.md)
6970
* [WASI](wasi.md)
7071
* [Web Crypto API](webcrypto.md)

doc/api/validator.md

Lines changed: 323 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,323 @@
1+
# Validator
2+
3+
<!--introduced_in=vREPLACEME-->
4+
5+
<!-- YAML
6+
added: REPLACEME
7+
-->
8+
9+
> Stability: 1.0 - Early development
10+
11+
> This feature is experimental and may change at any time. To disable it,
12+
> start Node.js with [`--no-experimental-validator`][].
13+
14+
<!-- source_link=lib/validator.js -->
15+
16+
The `node:validator` module provides a schema-based object validator for
17+
simple REST API input validation. It supports basic type checking, property
18+
constraints, required fields, and nested schemas.
19+
20+
To access it:
21+
22+
```mjs
23+
import { Schema } from 'node:validator';
24+
```
25+
26+
```cjs
27+
const { Schema } = require('node:validator');
28+
```
29+
30+
This module is only available under the `node:` scheme.
31+
32+
The following example shows the basic usage of the `node:validator` module
33+
to validate a user object.
34+
35+
```mjs
36+
import { Schema } from 'node:validator';
37+
38+
const userSchema = new Schema({
39+
type: 'object',
40+
required: ['name', 'email'],
41+
properties: {
42+
name: { type: 'string', minLength: 1, maxLength: 100 },
43+
email: { type: 'string', pattern: '^[^@]+@[^@]+$' },
44+
age: { type: 'integer', minimum: 0, maximum: 150 },
45+
tags: { type: 'array', items: { type: 'string' }, maxItems: 10 },
46+
},
47+
});
48+
49+
const result = userSchema.validate({
50+
name: 'Alice',
51+
52+
age: 30,
53+
tags: ['admin'],
54+
});
55+
56+
console.log(result.valid); // true
57+
console.log(result.errors); // []
58+
```
59+
60+
```cjs
61+
'use strict';
62+
const { Schema } = require('node:validator');
63+
64+
const userSchema = new Schema({
65+
type: 'object',
66+
required: ['name', 'email'],
67+
properties: {
68+
name: { type: 'string', minLength: 1, maxLength: 100 },
69+
email: { type: 'string', pattern: '^[^@]+@[^@]+$' },
70+
age: { type: 'integer', minimum: 0, maximum: 150 },
71+
tags: { type: 'array', items: { type: 'string' }, maxItems: 10 },
72+
},
73+
});
74+
75+
const result = userSchema.validate({
76+
name: 'Alice',
77+
78+
age: 30,
79+
tags: ['admin'],
80+
});
81+
82+
console.log(result.valid); // true
83+
console.log(result.errors); // []
84+
```
85+
86+
## Validation error codes
87+
88+
<!-- YAML
89+
added: REPLACEME
90+
-->
91+
92+
The following error codes are returned in the `code` field of validation
93+
error objects. They are also available as properties of the `codes` export.
94+
95+
| Code | Description |
96+
| ---- | ----------- |
97+
| `INVALID_TYPE` | Value type does not match the declared type |
98+
| `MISSING_REQUIRED` | A required property is missing |
99+
| `STRING_TOO_SHORT` | String is shorter than `minLength` |
100+
| `STRING_TOO_LONG` | String is longer than `maxLength` |
101+
| `PATTERN_MISMATCH` | String does not match the `pattern` regex |
102+
| `ENUM_MISMATCH` | Value is not one of the allowed `enum` values |
103+
| `NUMBER_TOO_SMALL` | Number is below `minimum` or `exclusiveMinimum` |
104+
| `NUMBER_TOO_LARGE` | Number is above `maximum` or `exclusiveMaximum` |
105+
| `NUMBER_NOT_MULTIPLE` | Number is not a multiple of `multipleOf` |
106+
| `NOT_INTEGER` | Value is not an integer when `type` is `'integer'` |
107+
| `ARRAY_TOO_SHORT` | Array has fewer items than `minItems` |
108+
| `ARRAY_TOO_LONG` | Array has more items than `maxItems` |
109+
| `ADDITIONAL_PROPERTY` | Object has a property not listed in `properties` when `additionalProperties` is `false` |
110+
111+
Compare the `code` field of a validation error against the `codes` export
112+
instead of hard-coding string literals:
113+
114+
```cjs
115+
const { Schema, codes } = require('node:validator');
116+
117+
const schema = new Schema({ type: 'number', minimum: 0 });
118+
const result = schema.validate(-1);
119+
if (!result.valid && result.errors[0].code === codes.NUMBER_TOO_SMALL) {
120+
// Handle the below-minimum case.
121+
}
122+
```
123+
124+
## Class: `Schema`
125+
126+
<!-- YAML
127+
added: REPLACEME
128+
-->
129+
130+
### `new Schema(definition)`
131+
132+
<!-- YAML
133+
added: REPLACEME
134+
-->
135+
136+
* `definition` {Object} A schema definition object.
137+
138+
Creates a new `Schema` instance. The schema definition is validated and
139+
compiled at construction time. [`ERR_VALIDATOR_INVALID_SCHEMA`][] is thrown
140+
if the definition is invalid.
141+
142+
The `definition` object must have a `type` property set to one of the
143+
supported types: `'string'`, `'number'`, `'integer'`, `'boolean'`,
144+
`'object'`, `'array'`, or `'null'`.
145+
146+
#### Schema definition properties
147+
148+
The following properties are supported depending on the schema type.
149+
150+
##### All types
151+
152+
* `type` {string} **Required.** One of `'string'`, `'number'`, `'integer'`,
153+
`'boolean'`, `'object'`, `'array'`, `'null'`.
154+
* `default` {any} Default value to apply when using
155+
[`schema.applyDefaults()`][].
156+
157+
##### Type: `'string'`
158+
159+
* `minLength` {number} Minimum string length (inclusive). Must be a
160+
non-negative integer.
161+
* `maxLength` {number} Maximum string length (inclusive). Must be a
162+
non-negative integer.
163+
* `pattern` {string} A regular expression pattern the string must match.
164+
* `enum` {Array} An array of allowed values.
165+
166+
##### Type: `'number'`
167+
168+
* `minimum` {number} Minimum value (inclusive).
169+
* `maximum` {number} Maximum value (inclusive).
170+
* `exclusiveMinimum` {number} Minimum value (exclusive).
171+
* `exclusiveMaximum` {number} Maximum value (exclusive).
172+
* `multipleOf` {number} The value must be a multiple of this number. Must be
173+
greater than 0.
174+
175+
##### Type: `'integer'`
176+
177+
Same constraints as `'number'`. Additionally, the value must be an integer.
178+
179+
##### Type: `'array'`
180+
181+
* `items` {Object} A schema definition for array elements.
182+
* `minItems` {number} Minimum array length (inclusive). Must be a
183+
non-negative integer.
184+
* `maxItems` {number} Maximum array length (inclusive). Must be a
185+
non-negative integer.
186+
187+
##### Type: `'object'`
188+
189+
* `properties` {Object} A map of property names to schema definitions.
190+
* `required` {string\[]} An array of required property names. Each name must
191+
be defined in `properties`.
192+
* `additionalProperties` {boolean} Whether properties not listed in
193+
`properties` are allowed. **Default:** `true`.
194+
195+
### `schema.validate(data)`
196+
197+
<!-- YAML
198+
added: REPLACEME
199+
-->
200+
201+
* `data` {any} The value to validate.
202+
* Returns: {ValidationResult}
203+
204+
Validates the given data against the schema. Returns a frozen object with
205+
`valid` and `errors` properties. Validation never throws; all validation
206+
failures are returned in the `errors` array.
207+
208+
```cjs
209+
const { Schema } = require('node:validator');
210+
const schema = new Schema({ type: 'string', minLength: 1 });
211+
212+
const good = schema.validate('hello');
213+
console.log(good.valid); // true
214+
215+
const bad = schema.validate('');
216+
console.log(bad.valid); // false
217+
console.log(bad.errors[0].code); // 'STRING_TOO_SHORT'
218+
```
219+
220+
### `schema.applyDefaults(data)`
221+
222+
<!-- YAML
223+
added: REPLACEME
224+
-->
225+
226+
* `data` {any} The data object to apply defaults to.
227+
* Returns: {Object} A new object with defaults applied.
228+
229+
Returns a new object with default values applied for missing or `undefined`
230+
properties. The input data is not mutated. Defaults are applied recursively
231+
for nested object schemas.
232+
233+
```cjs
234+
const { Schema } = require('node:validator');
235+
const schema = new Schema({
236+
type: 'object',
237+
properties: {
238+
host: { type: 'string', default: 'localhost' },
239+
port: { type: 'integer', default: 3000 },
240+
},
241+
});
242+
243+
const config = schema.applyDefaults({});
244+
console.log(config.host); // 'localhost'
245+
console.log(config.port); // 3000
246+
```
247+
248+
### `schema.toJSON()`
249+
250+
<!-- YAML
251+
added: REPLACEME
252+
-->
253+
254+
* Returns: {Object} A frozen copy of the original schema definition.
255+
256+
Returns the original schema definition as a frozen plain object. This is
257+
useful for composing schemas — pass the result as a sub-schema definition
258+
in another schema:
259+
260+
```cjs
261+
const { Schema } = require('node:validator');
262+
const addressSchema = new Schema({
263+
type: 'object',
264+
properties: {
265+
street: { type: 'string' },
266+
city: { type: 'string' },
267+
},
268+
});
269+
270+
const userSchema = new Schema({
271+
type: 'object',
272+
properties: {
273+
name: { type: 'string' },
274+
address: addressSchema.toJSON(),
275+
},
276+
});
277+
```
278+
279+
### Static method: `Schema.validate(definition, data)`
280+
281+
<!-- YAML
282+
added: REPLACEME
283+
-->
284+
285+
* `definition` {Object} A schema definition object.
286+
* `data` {any} The value to validate.
287+
* Returns: {ValidationResult}
288+
289+
Convenience method that creates a `Schema` and validates in one call.
290+
Equivalent to `new Schema(definition).validate(data)`. The definition is
291+
compiled on every invocation; when validating repeatedly against the same
292+
schema, reuse a single `new Schema()` instance instead.
293+
294+
```cjs
295+
const { Schema } = require('node:validator');
296+
const result = Schema.validate({ type: 'number', minimum: 0 }, 42);
297+
console.log(result.valid); // true
298+
```
299+
300+
## Type: `ValidationResult`
301+
302+
<!-- YAML
303+
added: REPLACEME
304+
-->
305+
306+
The object returned by [`schema.validate()`][]. It is a frozen plain object
307+
with the following properties:
308+
309+
* `valid` {boolean} `true` if the data matches the schema.
310+
* `errors` {Object\[]} A frozen array of error objects. Empty when `valid`
311+
is `true`. Each error object has the following properties:
312+
* `path` {string} The path to the invalid value using dot notation for
313+
object properties and bracket notation for array indices. The root
314+
path is an empty string.
315+
* `message` {string} A human-readable error description.
316+
* `code` {string} A machine-readable error code from the
317+
[validation error codes][] table.
318+
319+
[`--no-experimental-validator`]: cli.md#--no-experimental-validator
320+
[`ERR_VALIDATOR_INVALID_SCHEMA`]: errors.md#err_validator_invalid_schema
321+
[`schema.applyDefaults()`]: #schemaapplydefaultsdata
322+
[`schema.validate()`]: #schemavalidatedata
323+
[validation error codes]: #validation-error-codes

0 commit comments

Comments
 (0)