API reference
Every export of schiva, with its options. The guide explains how to use them together;
this page is the list to come back to. Everything is exported from schiva, with
require and with import.
compileJsonSchema(json, options)
Compiles a JSON Schema (draft-04 to 2020-12) into a validation function. The function returns the errors of a
value: [] when it is valid. What it returns depends on the
compile options; the JSON Schema options
choose how the schema is read. It throws when the schema is not supported (an unknown keyword, a reference
that does not resolve...), with the place in the schema.
const validate = compileJsonSchema({ type: 'object', properties: { age: { type: 'integer', minimum: 0 } } });
validate({ age: -1 }); // ['age must be at least 0']
const isValid = compileJsonSchema(schema, { errors: false }); // (value) => true or false
const firstError = compileJsonSchema(schema, { allErrors: false }); // [] or [the first error]
const withObjects = compileJsonSchema(schema, { errors: 'objects' }); // error objects
In TypeScript, compileJsonSchema<T>(json, { errors: false }) is a type guard for
T.
compileJsonSchemaAsync(json, options)
The same, for a schema that references documents to load first: a promise of the validation function. It
calls options.loadSchema(uri), an async function you write, for each document the schema
reaches and options.schemas does not have, and for the ones those reference in turn, once each.
A reference relative to a schema without $id is not loaded; an error of
loadSchema rejects the promise.
const validate = await compileJsonSchemaAsync(schema, {
loadSchema: async (uri) => (await fetch(uri)).json(),
});
loadJsonSchemas(json, options)
Loads the same documents without compiling: a promise of options.schemas with them added, as
{ uri: schema }, to pass to compileJsonSchema() or
standaloneJsonSchema() later.
fromJsonSchema(json, options)
Converts a JSON Schema into schiva types, with the same JSON Schema options, without compiling: the result has
validate(value), isValid(value) and compile(options) like any type.
compileJsonSchema(json, options) is compileType(fromJsonSchema(json, options), options).
type.compile(options) and compileType(type, options)
Compile a DSL schema or any type into a validation function, with the compile
options: type.compile(options) and compileType(type, options) are the same.
Compile once, when the program starts, and keep the function. Three older functions compile one mode each:
| Function | Returns a function giving | Same as |
|---|---|---|
compileIsValid(type) | true or false | compileType(type, { errors: false }) |
compileFirstError(type) | the first message, or undefined | the first element of { allErrors: false } |
compileErrors(type) | every message | compileType(type) |
Compile options
| Option | Values | Meaning |
|---|---|---|
allErrors | true (default), false | every error, or only the first one: the function stops at the first failing check, faster on invalid values |
errors | true (default), 'objects', false | error messages (strings), error objects, or true/false with no errors built at all (the fastest) |
JSON Schema options
For compileJsonSchema(), compileJsonSchemaAsync(), loadJsonSchemas(),
fromJsonSchema() and standaloneJsonSchema(), next to the compile options:
| Option | Values | Meaning |
|---|---|---|
schemas | { uri: schema } or an array of schemas with $id (id in draft-04) | documents that $ref can point to, and meta-schemas $schema can name (see Several documents) |
draft | 'draft-04', 'draft-06', 'draft-07', '2019-09', '2020-12' | the draft of the schema; by default the one $schema names, else draft-07 |
formats | true, a list of built-in names, or { name: true | false | RegExp | function | { validate, compare } } (false: known, not checked); builtInFormats() gives every built-in one | checks format, an annotation without it; with strict, a format it does not name throws (see Formats and Formats of your own) |
strict | true (default), false | with false, unknown keywords, keywords of other drafts and keywords a type excludes are ignored instead of throwing |
keywords | list of names and definitions | names are annotations of your own ('x-internal'); definitions are keywords that check values |
useDefaults | false (default), true, 'empty' | assigns the default of missing properties and tuple elements; 'empty' also replaces null and '' (see Changing the data) |
removeAdditional | false (default), true, 'all', 'failing' | removes additional properties: where additionalProperties is false; all of them; or the ones that fail additionalProperties |
coerceTypes | false (default), true, 'array' | converts values to the types type asks for, with ajv's rules; 'array' also wraps and unwraps arrays |
multipleOfPrecision | a positive integer | decimal digits: multipleOf accepts a division within 1e-n of an integer, so 0.3 is a multiple of 0.1 |
loadSchema | async (uri) => schema | for compileJsonSchemaAsync() and loadJsonSchemas() only |
standaloneJsonSchema, standaloneCode and standaloneModule
Write validators out as the source of a JavaScript module, to save to a file when building: loading it
generates no code, so it runs under a strict Content Security Policy, and it needs nothing else, not even
schiva. Each one takes the compile options, and format: 'commonjs' (default) or
'esm'.
| Function | Module |
|---|---|
standaloneJsonSchema(json, options) | the validator of a JSON Schema as its default export; takes the JSON Schema options too |
standaloneCode(type, options) | the validator of a type (a DSL schema, or the result of fromJsonSchema()) as its default export |
standaloneModule({ name: type }, options) | one named export for each entry, sharing the code they have in common |
fs.writeFileSync('validate-order.js', standaloneJsonSchema(orderSchema, { format: 'esm', formats: true }));
fs.writeFileSync('validators.cjs', standaloneModule({ order, customer }, { errors: 'objects' }));
Everything the schema needs is written into the module: the built-in formats, error objects, defaults and the
keywords that are macros or regular expressions. Functions of your own cannot be written out: types of your
own, keywords with validate or compile, and formats given as functions throw a
message naming them.
inferJsonSchema(samples, options) and inferSchemaCode(samples, options)
The schema of a list of sample values (a single value goes in a list), merged from all of them: a key is
required when every object at that place has it, null makes a value nullable, integers and
numbers make a number, array elements are merged, and strings get a format every one of them matches (see
Schemas from samples, or try Schema from JSON).
inferJsonSchema() returns a JSON Schema object; inferSchemaCode() returns the source
of a module that builds the same schema with the DSL.
| Option | Value | Meaning |
|---|---|---|
closed | false (default) or true | objects reject keys the samples do not have (additionalProperties: false, ClosedSchema) |
formats | true (default) or false | detect date-time, date, time, email, uuid, ipv4, ipv6 and uri |
draft | '2020-12' (default), '2019-09', 'draft-07', 'draft-06', 'draft-04' | the $schema written |
name | 'schema' (default) | inferSchemaCode() only: the name of the variable |
module | 'commonjs' (default), 'esm', 'none' | inferSchemaCode() only: the import line, with the names the code uses |
Values that are not JSON (functions, Date objects, NaN) throw, naming where they
are; keys whose value is undefined are taken as absent.
Common options and methods of the types
Every DSL type takes these options and has these methods:
| Option or method | Meaning |
|---|---|
isMandatory | default true: undefined (a missing property) is an error, is mandatory |
isNullable | default false: null is an error, cannot be null |
.optional(), .required() | set isMandatory to false or true, and return the type |
.nullable(), .notNull() | set isNullable to true or false, and return the type |
.mandatory(flag), .nullable(flag) | the same with a value |
.validate(value, fieldName) | the errors without compiling: undefined, a message or a list (see validate() results) |
.isValid(value) | true or false without compiling |
.compile(options) | a validation function (see Compile options) |
Wherever a type is expected, a plain object stands for new Schema(object) (an open schema). A
value that is neither a type nor an object of types throws when the type is built.
new Schema(shape, options) and new ClosedSchema(shape, options)
A schema for objects: each key of shape is an expected property with its type. Declared keys
are read as own properties only. ClosedSchema is a Schema with
isOpen: false.
| Option | Meaning |
|---|---|
isOpen | default true; false rejects keys the shape does not declare: Unexpected key: extra |
additionalType | type of the keys the shape does not declare |
patternTypes | [{ pattern, type }]: type of the keys a regular expression matches; they are not additional keys |
propertyNameType | type every key must satisfy; its errors name the key Key name |
minProperties, maxProperties | number of keys |
dependencies | [{ key, required: [keys] }] or [{ key, type }]: when key is present, those keys must be too, or the whole object must satisfy type |
isMandatory, isNullable | as for every type |
const config = new ClosedSchema(
{ name: String(), port: Integer({ min: 1, max: 65535 }), tls: Boolean().optional(), cert: String().optional() },
{ patternTypes: [{ pattern: /^x-/, type: Any() }], dependencies: [{ key: 'tls', required: ['cert'] }] }
);
config.compile()({ name: 'api', port: 443, tls: true, 'x-team': 'a', debug: true });
// ['Unexpected key: debug', 'cert is mandatory when tls is present']
String, Integer, Float and Boolean
| Type | Options |
|---|---|
String(options)StringType |
min, max: length; pattern: a RegExp;
format: a built-in format (email, date, uuid...);
allowEmpty: whether '' passes min (by default, when the string
is optional); countCodePoints: count lengths in Unicode code points instead of UTF-16
units (as JSON Schema does)
|
Integer(options), Float(options)IntegerType, FloatType |
min, max, exclusiveMin, exclusiveMax,
multipleOf, multipleOfPrecision. Numbers must be finite:
NaN and Infinity are not numbers
|
Boolean(options)BooleanType | the common options |
Enum, Values and Const
| Type | Accepts |
|---|---|
Enum({ options })EnumType | one of the strings of options; takes the options of String too |
Values({ values })ValuesType | one of values, of any JSON type, compared deeply (objects and arrays by their content) |
Const(value, options) | that value only: Values({ values: [value], ...options }) |
ArrayOf(options)
| Option | Meaning |
|---|---|
type | the type of every element, or an array of types for the elements at each position (a tuple) |
additionalType | with a tuple, the type of the elements after it |
min, max | number of elements |
unique | no two elements are equal (compared deeply) |
contains, minContains, maxContains | at least one element (or between the two numbers) satisfies contains |
ArrayOf({ type: [String(), Integer()], additionalType: Boolean(), min: 2 }); // ['a', 1, true, false]
AnyOf, AllOf, OneOf and Not
| Type | Accepts |
|---|---|
AnyOf({ types }) | values at least one of the types accepts; otherwise the errors of every type |
AllOf({ types }) | values every type accepts; the errors of each one |
OneOf({ types }) | values exactly one of the types accepts |
Not({ type }) | values the type rejects: must not match the excluded schema |
Conditional and When
| Type | Accepts |
|---|---|
Conditional({ ifType, thenType, elseType }) | when the value satisfies ifType, it must satisfy thenType, else elseType (JSON Schema's if/then/else); either may be left out |
When({ jsonType, type }) | checks type only for values of that JSON type ('object', 'array', 'string', 'number'); other values pass. isJsonType(value, jsonType) is its test |
Conditional({
ifType: { country: Const('US') },
thenType: { zip: String({ pattern: /^\d{5}$/ }) },
elseType: { zip: String() },
});
Any, Never, Obj and Ref
| Type | Accepts |
|---|---|
Any(options) | every value (with the presence options) |
Never(options) | no value: is not allowed; with isMandatory: false (the default of never()), a missing property passes |
Obj({ schema }) | any object, or one a schema accepts |
Ref({ target }) | what target accepts; set ref.target later for recursive schemas (see Recursive schemas) |
Short helpers
Functions with positional arguments, for short schemas. Each has an optional version starting with
o (isMandatory defaults to false).
| Helper | Same as |
|---|---|
str(min, max, isMandatory, isNullable), ostr | String({ min, max, ... }) |
int(min, max, ...), oint | Integer({ min, max, ... }) |
float(min, max, ...), ofloat, num, onum | Float({ min, max, ... }) |
bool(isMandatory, isNullable), obool | Boolean() |
any(), oany, never() | Any(), Never() |
enumt(options, ...), oenumt, oenum | Enum({ options }) |
arrOf(type, min, max, ...), oarrOf | ArrayOf({ type, min, max }); arrOf({ type, min, ... }) takes the options |
obj(shape, ...), oobj | Obj({ schema: shape }); obj({ schema, isNullable, ... }) takes the options |
anyOf(types), allOf, oneOf, and oanyOf, oallOf, ooneOf | AnyOf({ types })... |
not(type), onot | Not({ type }) |
ValidateType
The base class of every type. Extend it (or a built-in type) with your own validate(value, fieldName)
returning undefined or a message, and optionally a faster isValid(value); the
compiled code calls them for their part of a schema. super.validate(value, fieldName) checks
isMandatory and isNullable. checkPresence(value) gives the verdict for
undefined and null (undefined for other values). See
Types of your own.
Keyword definitions
Items of the JSON Schema option keywords that check values:
| Property | Meaning |
|---|---|
keyword | its name; not a keyword of JSON Schema |
type | JSON types of the values it checks ('string', 'number', 'integer', 'boolean', 'object', 'array', 'null'), one or a list; every value by default. A macro takes object, array, string or number |
validate(value, data, parentSchema) | called for each value with the value of the keyword: true when valid |
compile(value, parentSchema, { draft }) | called once, when compiling: gives the function checking the data, or a regular expression the data must match |
macro(value, parentSchema, { draft }) | gives a schema to check instead; compiles to the same code as its keywords |
message | the text of its error after the name of the value, or (value, data) => text; must pass the "<keyword>" keyword by default. A function with one parameter is called once, when compiling |
A definition has exactly one of validate, compile and macro. Compiled,
a keyword becomes a KeywordType ({ keyword, check, message, jsonTypes }), which can
also be used in the DSL.
ajvKeywords(names)
Definitions of the keywords of ajv-keywords, with the same results: all of them, or the ones named (a name or
a list). transform, dynamicDefaults and select throw, with the reason.
| Keyword | Value | Checks | Standalone |
|---|---|---|---|
typeof | a name or names | the typeof of the value | no |
instanceof | 'Date', 'RegExp', 'Map'... or a list | the class of the value | no |
range, exclusiveRange | [min, max] | numbers between the two, included or not | yes |
regexp | '/pattern/flags' or { pattern, flags } | strings the regular expression matches | yes, without the flags g and y |
uniqueItemProperties | property names | no two elements have equal values of each one | no |
allRequired | true | every key of properties is present | yes |
anyRequired, oneRequired | property names | at least one, or exactly one, is present | yes |
patternRequired | patterns | for each one, a key matches it | no |
prohibited | property names | none of them is present: x is not allowed | yes |
deepProperties | { '/json/pointer': schema } | the values at those pointers | yes |
deepRequired | JSON pointers | the values at those pointers are defined | no |
Formats of your own
In the JSON Schema option formats, a name maps to true (a built-in format),
false (a format that is known but not checked, as OpenAPI's int32), a regular
expression, a function (string) => boolean, or { validate, compare },
whose compare(a, b) gives a negative number, 0 or a positive number, so that
formatMinimum, formatMaximum, formatExclusiveMinimum and
formatExclusiveMaximum can limit its values.
compileJsonSchema(schema, {
formats: {
date: true,
sku: /^SKU-\d+$/,
version: { validate: /^\d+\.\d+$/, compare: (a, b) => a.localeCompare(b, 'en', { numeric: true }) },
},
});
builtInFormats() gives every built-in format as { date: true, ... }, to check them
all and add others: formats: { ...builtInFormats(), int32: false, sku: /^SKU-\d+$/ }. With
strict (the default), a format the option does not name throws when compiling.
validate() results, toErrors and hasErrors
type.validate(value) (without compiling) returns undefined when the value is valid,
a message, or a list that may nest lists (combinations collect the errors of their parts).
toErrors(result) gives its messages as a flat list, each once, as the compiled function gives
them; hasErrors(result) tells whether it has any.
toErrors(schema.validate(value)); // ['name is mandatory', ...]
hasErrors(schema.validate(value)); // true
Error objects
With errors: 'objects', each error is an object:
| Property | Meaning |
|---|---|
path | the keys and indexes of the value: ['lines', 0, 'price'], [] for the value itself |
pointer | the same path as a JSON Pointer: '/lines/0/price' |
keyword | the check that failed (see Messages and keywords) |
params | its details, {} when there are none |
message | the message of the default mode |
propertyName | true for an error of a key checked by propertyNames, whose path is the one of its property |
Messages and keywords
Every message starts with the name of the value (lines[0].price, or Value for the
value itself). The keyword and params are the ones of error objects.
| Message after the name | keyword | params |
|---|---|---|
| is mandatory | required | {} |
| cannot be null | nullable | {} |
| must be a string, a number, an integer, a boolean, an object, an array | type | { type } |
| must be at least N characters long, at most N characters long | minLength, maxLength | { limit } |
| does not match the required pattern | pattern | { pattern } |
| must be a valid FORMAT | format | { format } |
| must be at least N, at most N, greater than N, less than N | minimum, maximum, exclusiveMinimum, exclusiveMaximum | { limit } |
| must be a multiple of N | multipleOf | { multipleOf } |
| must be at least, at most, greater than, less than LIMIT (a format) | formatMinimum, formatMaximum, formatExclusiveMinimum, formatExclusiveMaximum | { comparison, limit } |
| must be one of: A, B | enum | { allowedValues } |
| must be equal to A | const | { allowedValue } |
| must have at least N elements, at most N elements | minItems, maxItems | { limit } |
| must not have duplicate elements | uniqueItems | {} |
| must contain at least one matching element | contains | {} |
| must contain at least N matching elements, at most N matching elements | minContains, maxContains | { limit } |
| must have at least N properties, at most N properties | minProperties, maxProperties | { limit } |
| (the whole message) Unexpected key: NAME | additionalProperties, unevaluatedProperties | { property } |
| is mandatory when KEY is present | dependentRequired | { property, missingProperty } |
| is not allowed | false | {} |
| must not match the excluded schema | not | {} |
| must match exactly one schema, but matches none (or more than one) | oneOf | { passing } |
| TAG is mandatory, must be a string, must be one of: A, B | discriminator | { error, tag, tagValue } |
| the message of a keyword of your own | its name | {} |
| the message of a type of your own | custom | {} |
TypeScript types
| Type | Meaning |
|---|---|
Infer<typeof schema> | the type of the values a DSL schema accepts |
ErrorsFunction, ErrorObjectsFunction, IsValidFunction<T> | the compiled functions of each mode; the last one is a type guard |
ErrorObject | an error object |
CompileOptions, JsonSchemaOptions, StandaloneOptions, LoadSchemaOptions | the options above |
JsonSchema, JsonSchemaObject, JsonSchemaDraft | a JSON Schema, and the names of the drafts |
KeywordDefinition, AjvKeywordName, FormatDefinition, FormatName, FormatCheck | keywords and formats of your own, and the built-in names |
ValidationResult | what validate() returns |
StringOptions, NumberOptions, ArrayOfOptions, SchemaOptions... | the options of each type |