Comparing version 16.1.4 to 16.1.5
@@ -660,3 +660,7 @@ 'use strict'; | ||
return !Validator.validate(value, this, state, prefs, overrides).errors; | ||
state.snapshot(); | ||
const result = !Validator.validate(value, this, state, prefs, overrides).errors; | ||
state.restore(); | ||
return result; | ||
} | ||
@@ -663,0 +667,0 @@ |
@@ -166,47 +166,2 @@ 'use strict'; | ||
exports.State = class { | ||
constructor(path, ancestors, state) { | ||
this.path = path; | ||
this.ancestors = ancestors; // [parent, ..., root] | ||
this.mainstay = state.mainstay; | ||
this.schemas = state.schemas; // [current, ..., root] | ||
this.debug = null; | ||
} | ||
localize(path, ancestors = null, schema = null) { | ||
const state = new exports.State(path, ancestors, this); | ||
if (schema && | ||
state.schemas) { | ||
state.schemas = [internals.schemas(schema), ...state.schemas]; | ||
} | ||
return state; | ||
} | ||
nest(schema, debug) { | ||
const state = new exports.State(this.path, this.ancestors, this); | ||
state.schemas = state.schemas && [internals.schemas(schema), ...state.schemas]; | ||
state.debug = debug; | ||
return state; | ||
} | ||
}; | ||
internals.schemas = function (schema) { | ||
if (exports.isSchema(schema)) { | ||
return { schema }; | ||
} | ||
return schema; | ||
}; | ||
exports.tryWithPath = function (fn, key, options = {}) { | ||
@@ -213,0 +168,0 @@ |
@@ -152,3 +152,3 @@ 'use strict'; | ||
resolved = state.mainstay.shadow.get(this.path); | ||
resolved = state.mainstay.shadow.get(this.absolute(state)); | ||
} | ||
@@ -183,2 +183,7 @@ | ||
absolute(state) { | ||
return [...state.path.slice(0, -this.ancestor), ...this.path]; | ||
} | ||
clone() { | ||
@@ -185,0 +190,0 @@ |
@@ -52,3 +52,6 @@ 'use strict'; | ||
const item = schema.$_terms.matches[i]; | ||
const result = item.schema.$_validate(value, state.nest(item.schema, `match.${i}`), prefs); | ||
const localState = state.nest(item.schema, `match.${i}`); | ||
localState.snapshot(); | ||
const result = item.schema.$_validate(value, localState, prefs); | ||
if (!result.errors) { | ||
@@ -58,2 +61,5 @@ ++hits; | ||
} | ||
else { | ||
localState.restore(); | ||
} | ||
} | ||
@@ -81,3 +87,6 @@ | ||
if (item.schema) { | ||
const result = item.schema.$_validate(value, state.nest(item.schema, `match.${i}`), prefs); | ||
const localState = state.nest(item.schema, `match.${i}`); | ||
localState.snapshot(); | ||
const result = item.schema.$_validate(value, localState, prefs); | ||
if (!result.errors) { | ||
@@ -87,2 +96,3 @@ return result; | ||
localState.restore(); | ||
errors.push({ schema: item.schema, reports: result.errors }); | ||
@@ -89,0 +99,0 @@ continue; |
@@ -83,3 +83,3 @@ 'use strict'; | ||
}, | ||
validate(value, { state, prefs, error, schema }, { schema: has }) { | ||
validate(value, { state, prefs, error }, { schema: has }) { | ||
@@ -223,3 +223,6 @@ const ancestors = [value, ...state.ancestors]; | ||
for (let j = 0; j < jl; ++j) { | ||
const res = requireds[j].$_validate(item, state.localize(path, ancestors, requireds[j]), prefs); | ||
const localState = state.localize(path, ancestors, requireds[j]); | ||
localState.snapshot(); | ||
const res = requireds[j].$_validate(item, localState, prefs); | ||
requiredChecks[j] = res; | ||
@@ -245,2 +248,4 @@ | ||
} | ||
localState.restore(); | ||
} | ||
@@ -267,3 +272,6 @@ | ||
else { | ||
res = inclusion.$_validate(item, state.localize(path, ancestors, inclusion), prefs); | ||
const localState = state.localize(path, ancestors, inclusion); | ||
localState.snapshot(); | ||
res = inclusion.$_validate(item, localState, prefs); | ||
if (!res.errors) { | ||
@@ -288,2 +296,4 @@ if (inclusion._flags.result === 'strip') { | ||
} | ||
localState.restore(); | ||
} | ||
@@ -316,3 +326,5 @@ | ||
if (schema.$_terms._inclusions.length && !isValid) { | ||
if (schema.$_terms._inclusions.length && | ||
!isValid) { | ||
if (stripUnknown) { | ||
@@ -342,2 +354,3 @@ internals.fastSplice(value, i); | ||
}, | ||
priority: true, | ||
@@ -344,0 +357,0 @@ manifest: false |
@@ -205,3 +205,4 @@ 'use strict'; | ||
const about = subject.resolve(value, state, prefs); | ||
if (schema.$_match(about, state.localize([], [value, ...state.ancestors], schema), prefs)) { | ||
const path = Ref.isRef(subject) ? subject.absolute(state) : []; | ||
if (schema.$_match(about, state.localize(path, [value, ...state.ancestors], schema), prefs)) { | ||
return value; | ||
@@ -208,0 +209,0 @@ } |
@@ -10,2 +10,3 @@ 'use strict'; | ||
const Errors = require('./errors'); | ||
const State = require('./state'); | ||
@@ -128,3 +129,3 @@ | ||
const schemas = schema._ids._schemaChain ? [{ schema }] : null; | ||
const state = new Common.State([], [], { mainstay, schemas }); | ||
const state = new State([], [], { mainstay, schemas }); | ||
@@ -466,2 +467,6 @@ // Validate value | ||
} | ||
for (const error of errors) { | ||
Assert(error instanceof Error || error instanceof Errors.Report, 'error() must return an Error object'); | ||
} | ||
} | ||
@@ -512,4 +517,3 @@ else { | ||
state.mainstay.tracer.value(state, schema._flags.result, value, result.value); | ||
state.mainstay.shadow = state.mainstay.shadow || new internals.Shadow(); | ||
state.mainstay.shadow.set(state.path, value); | ||
state.shadow(value, schema._flags.result); | ||
} | ||
@@ -608,39 +612,2 @@ | ||
internals.Shadow = class { | ||
constructor() { | ||
this._value = null; | ||
} | ||
set(path, value) { | ||
if (!path.length) { // No need to store root value | ||
return; | ||
} | ||
this._value = this._value || new Map(); | ||
let node = this._value; | ||
for (let i = 0; i < path.length - 1; ++i) { | ||
const segment = path[i]; | ||
let next = node.get(segment); | ||
if (!next) { | ||
next = new Map(); | ||
node.set(segment, next); | ||
} | ||
node = next; | ||
} | ||
node.set(path[path.length - 1], value); | ||
} | ||
get(path) { | ||
return Reach(this._value, path, { iterables: true }); | ||
} | ||
}; | ||
internals.ignore = { | ||
@@ -647,0 +614,0 @@ active: false, |
{ | ||
"name": "@hapi/joi", | ||
"description": "Object schema validation", | ||
"version": "16.1.4", | ||
"version": "16.1.5", | ||
"repository": "git://github.com/hapijs/joi", | ||
@@ -6,0 +6,0 @@ "main": "lib/index.js", |
143
README.md
@@ -5,140 +5,13 @@ <a href="https://hapi.dev"><img src="https://raw.githubusercontent.com/hapijs/assets/master/images/family.png" width="180px" align="right" /></a> | ||
The most powerful schema description language and data validator for JavaScript. | ||
#### The most powerful schema description language and data validator for JavaScript. | ||
[![Build Status](https://travis-ci.org/hapijs/joi.svg?branch=master)](https://travis-ci.org/hapijs/joi) | ||
**joi** is part of the **hapi** ecosystem and was designed to work seamlessly with the [hapi web framework](https://hapi.dev) and its other components (but works great on its own or with other frameworks). If you are using a different web framework and find this module useful, check out [hapi](https://hapi.dev) – they work even better together. | ||
## Introduction | ||
### Visit the [hapi.dev](https://hapi.dev) Developer Portal for tutorials, documentation, and support | ||
**joi** lets you describe your data using a simple, intuitive, and readable language. Like the rest of the [hapi ecosystem](https://hapi.dev) it fits in, **joi** allows you to describe your data for both input and output validation, as part of a hapi HTTP server or standalone. | ||
## Useful resources | ||
## API | ||
See the detailed [API Reference](https://hapi.dev/family/joi/). | ||
## Example | ||
```js | ||
const Joi = require('@hapi/joi'); | ||
const schema = Joi.object({ | ||
username: Joi.string() | ||
.alphanum() | ||
.min(3) | ||
.max(30) | ||
.required(), | ||
password: Joi.string() | ||
.pattern(/^[a-zA-Z0-9]{3,30}$/), | ||
repeat_password: Joi.ref('password'), | ||
access_token: [ | ||
Joi.string(), | ||
Joi.number() | ||
], | ||
birth_year: Joi.number() | ||
.integer() | ||
.min(1900) | ||
.max(2013), | ||
email: Joi.string() | ||
.email({ minDomainSegments: 2, tlds: { allow: ['com', 'net'] } }) | ||
}) | ||
.with('username', 'birth_year') | ||
.xor('password', 'access_token') | ||
.with('password', 'repeat_password'); | ||
schema.validate({ username: 'abc', birth_year: 1994 }); | ||
// -> { value: { username: 'abc', birth_year: 1994 } } | ||
schema.validate({}); | ||
// -> { value: {}, error: '"username" is required' } | ||
// Also - | ||
try { | ||
const value = await schema.validateAsync({ username: 'abc', birth_year: 1994 }); | ||
} | ||
catch (err) { } | ||
``` | ||
The above schema defines the following constraints: | ||
* `username` | ||
* a required string | ||
* must contain only alphanumeric characters | ||
* at least 3 characters long but no more than 30 | ||
* must be accompanied by `birth_year` | ||
* `password` | ||
* an optional string | ||
* must satisfy the custom regex pattern | ||
* cannot appear together with `access_token` | ||
* must be accompanied by `repeat_password` and equal to it | ||
* `access_token` | ||
* an optional, unconstrained string or number | ||
* `birth_year` | ||
* an integer between 1900 and 2013 | ||
* `email` | ||
* a valid email address string | ||
* must have two domain parts e.g. `example.com` | ||
* TLD must be `.com` or `.net` | ||
## Usage | ||
Usage is a two steps process: | ||
First, a schema is constructed using the provided types and constraints: | ||
```js | ||
const schema = Joi.object({ | ||
a: Joi.string() | ||
}); | ||
``` | ||
Note that **joi** schema objects are immutable which means every additional rule added (e.g. | ||
`.min(5)`) will return a new schema object. | ||
Second, the value is validated against the defined schema: | ||
```js | ||
const { error, value } = schema.validate({ a: 'a string' }); | ||
``` | ||
If the input is valid, then the `error` will be `null`. If the input is invalid, `error` is assigned | ||
a [`ValidationError`](https://github.com/hapijs/joi/blob/master/API.md#validationerror) object | ||
providing more information. | ||
The schema can be a plain JavaScript object where every key is assigned a **joi** type, or it can be a **joi** type directly: | ||
```js | ||
const schema = Joi.string().min(10); | ||
``` | ||
If the schema is a **joi** type, the `schema.validate(value)` can be called directly on the type. When passing a non-type schema object, | ||
the module converts it internally to an object() type equivalent to: | ||
```js | ||
const schema = Joi.object().keys({ | ||
a: Joi.string() | ||
}); | ||
``` | ||
When validating a schema: | ||
* Values (or keys in case of objects) are optional by default. | ||
```js | ||
Joi.string().validate(undefined); // validates fine | ||
``` | ||
To disallow this behavior, you can either set the schema as `required()`, or set `presence` to `"required"` when passing `options`: | ||
```js | ||
Joi.string().required().validate(undefined); | ||
// or | ||
Joi.string().validate(undefined, /* options */ { presence: "required" }); | ||
``` | ||
* Strings are utf-8 encoded by default. | ||
* Rules are defined in an additive fashion and evaluated in order, first the inclusive rules, then the exclusive rules. | ||
- [Documentation and API](https://hapi.dev/family/joi/) | ||
- [Versions status](https://hapi.dev/resources/status/#joi) | ||
- [Project policies](https://hapi.dev/policies/) | ||
- [Free and commercial support options](https://hapi.dev/support/) |
Sorry, the diff of this file is too big to display
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
445286
37
7655
17