joi 11.3.0 → 11.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -1
- package/lib/errors.js +4 -0
- package/lib/index.js +2 -0
- package/lib/language.js +5 -1
- package/lib/types/alternatives/index.js +30 -15
- package/lib/types/any/index.js +7 -2
- package/lib/types/object/index.js +2 -2
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -26,7 +26,7 @@ Imagine you run facebook and you want visitors to sign up on the website with re
|
|
|
26
26
|
This is joi, joi allows you to create *blueprints* or *schemas* for JavaScript objects (an object that stores information) to ensure *validation* of key information.
|
|
27
27
|
|
|
28
28
|
# API
|
|
29
|
-
See the detailed [API Reference](https://github.com/hapijs/joi/blob/v11.
|
|
29
|
+
See the detailed [API Reference](https://github.com/hapijs/joi/blob/v11.4.0/API.md).
|
|
30
30
|
|
|
31
31
|
# Example
|
|
32
32
|
|
package/lib/errors.js
CHANGED
|
@@ -88,6 +88,10 @@ exports.Err = class {
|
|
|
88
88
|
|
|
89
89
|
format = format || Hoek.reach(localized, this.type) || Hoek.reach(Language.errors, this.type);
|
|
90
90
|
|
|
91
|
+
if (format === undefined) {
|
|
92
|
+
return `Error code "${this.type}" is not defined, your custom type is missing the correct language definition`;
|
|
93
|
+
}
|
|
94
|
+
|
|
91
95
|
let wrapArrays = Hoek.reach(localized, 'messages.wrapArrays');
|
|
92
96
|
if (typeof wrapArrays !== 'boolean') {
|
|
93
97
|
wrapArrays = Language.errors.messages.wrapArrays;
|
package/lib/index.js
CHANGED
package/lib/language.js
CHANGED
|
@@ -97,7 +97,11 @@ exports.errors = {
|
|
|
97
97
|
assert: '!!"{{ref}}" validation failed because "{{ref}}" failed to {{message}}',
|
|
98
98
|
rename: {
|
|
99
99
|
multiple: 'cannot rename child "{{from}}" because multiple renames are disabled and another key was already renamed to "{{to}}"',
|
|
100
|
-
override: 'cannot rename child "{{from}}" because override is disabled and target "{{to}}" exists'
|
|
100
|
+
override: 'cannot rename child "{{from}}" because override is disabled and target "{{to}}" exists',
|
|
101
|
+
regex: {
|
|
102
|
+
multiple: 'cannot rename children {{from}} because multiple renames are disabled and another key was already renamed to "{{to}}"',
|
|
103
|
+
override: 'cannot rename children {{from}} because override is disabled and target "{{to}}" exists'
|
|
104
|
+
}
|
|
101
105
|
},
|
|
102
106
|
type: 'must be an instance of "{{type}}"',
|
|
103
107
|
schema: 'must be a Joi instance'
|
|
@@ -31,9 +31,10 @@ internals.Alternatives = class extends Any {
|
|
|
31
31
|
|
|
32
32
|
for (let i = 0; i < il; ++i) {
|
|
33
33
|
const item = this._inner.matches[i];
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
const
|
|
34
|
+
if (!item.schema) {
|
|
35
|
+
const schema = item.peek || item.is;
|
|
36
|
+
const input = item.is ? item.ref(state.reference || state.parent, options) : value;
|
|
37
|
+
const failed = schema._validate(input, null, options, state.parent).errors;
|
|
37
38
|
|
|
38
39
|
if (failed) {
|
|
39
40
|
if (item.otherwise) {
|
|
@@ -51,7 +52,7 @@ internals.Alternatives = class extends Any {
|
|
|
51
52
|
continue;
|
|
52
53
|
}
|
|
53
54
|
|
|
54
|
-
const result = schema._validate(value, state, options);
|
|
55
|
+
const result = item.schema._validate(value, state, options);
|
|
55
56
|
if (!result.errors) { // Found a valid match
|
|
56
57
|
return result;
|
|
57
58
|
}
|
|
@@ -84,25 +85,35 @@ internals.Alternatives = class extends Any {
|
|
|
84
85
|
return obj;
|
|
85
86
|
}
|
|
86
87
|
|
|
87
|
-
when(
|
|
88
|
+
when(condition, options) {
|
|
88
89
|
|
|
89
|
-
|
|
90
|
+
let schemaCondition = false;
|
|
91
|
+
Hoek.assert(Ref.isRef(condition) || typeof condition === 'string' || (schemaCondition = condition instanceof Any), 'Invalid condition:', condition);
|
|
90
92
|
Hoek.assert(options, 'Missing options');
|
|
91
93
|
Hoek.assert(typeof options === 'object', 'Invalid options');
|
|
92
|
-
|
|
94
|
+
if (schemaCondition) {
|
|
95
|
+
Hoek.assert(!options.hasOwnProperty('is'), '"is" can not be used with a schema condition');
|
|
96
|
+
}
|
|
97
|
+
else {
|
|
98
|
+
Hoek.assert(options.hasOwnProperty('is'), 'Missing "is" directive');
|
|
99
|
+
}
|
|
93
100
|
Hoek.assert(options.then !== undefined || options.otherwise !== undefined, 'options must have at least one of "then" or "otherwise"');
|
|
94
101
|
|
|
95
102
|
const obj = this.clone();
|
|
96
|
-
let is
|
|
103
|
+
let is;
|
|
104
|
+
if (!schemaCondition) {
|
|
105
|
+
is = Cast.schema(this._currentJoi, options.is);
|
|
97
106
|
|
|
98
|
-
|
|
107
|
+
if (options.is === null || !(Ref.isRef(options.is) || options.is instanceof Any)) {
|
|
99
108
|
|
|
100
|
-
|
|
101
|
-
|
|
109
|
+
// Only apply required if this wasn't already a schema or a ref, we'll suppose people know what they're doing
|
|
110
|
+
is = is.required();
|
|
111
|
+
}
|
|
102
112
|
}
|
|
103
113
|
|
|
104
114
|
const item = {
|
|
105
|
-
ref: Cast.ref(
|
|
115
|
+
ref: schemaCondition ? null : Cast.ref(condition),
|
|
116
|
+
peek: schemaCondition ? condition : null,
|
|
106
117
|
is,
|
|
107
118
|
then: options.then !== undefined ? Cast.schema(this._currentJoi, options.then) : undefined,
|
|
108
119
|
otherwise: options.otherwise !== undefined ? Cast.schema(this._currentJoi, options.otherwise) : undefined
|
|
@@ -114,8 +125,10 @@ internals.Alternatives = class extends Any {
|
|
|
114
125
|
item.otherwise = item.otherwise && obj._baseType.concat(item.otherwise);
|
|
115
126
|
}
|
|
116
127
|
|
|
117
|
-
|
|
118
|
-
|
|
128
|
+
if (!schemaCondition) {
|
|
129
|
+
Ref.push(obj._refs, item.ref);
|
|
130
|
+
obj._refs = obj._refs.concat(item.is._refs);
|
|
131
|
+
}
|
|
119
132
|
|
|
120
133
|
if (item.then && item.then._refs) {
|
|
121
134
|
obj._refs = obj._refs.concat(item.then._refs);
|
|
@@ -146,9 +159,11 @@ internals.Alternatives = class extends Any {
|
|
|
146
159
|
|
|
147
160
|
// when()
|
|
148
161
|
|
|
149
|
-
const when = {
|
|
162
|
+
const when = item.is ? {
|
|
150
163
|
ref: item.ref.toString(),
|
|
151
164
|
is: item.is.describe()
|
|
165
|
+
} : {
|
|
166
|
+
peek: item.peek.describe()
|
|
152
167
|
};
|
|
153
168
|
|
|
154
169
|
if (item.then) {
|
package/lib/types/any/index.js
CHANGED
|
@@ -385,7 +385,7 @@ module.exports = internals.Any = class {
|
|
|
385
385
|
return obj;
|
|
386
386
|
}
|
|
387
387
|
|
|
388
|
-
when(
|
|
388
|
+
when(condition, options) {
|
|
389
389
|
|
|
390
390
|
Hoek.assert(options && typeof options === 'object', 'Invalid options');
|
|
391
391
|
Hoek.assert(options.then !== undefined || options.otherwise !== undefined, 'options must have at least one of "then" or "otherwise"');
|
|
@@ -394,7 +394,12 @@ module.exports = internals.Any = class {
|
|
|
394
394
|
const otherwise = options.hasOwnProperty('otherwise') ? this.concat(Cast.schema(this._currentJoi, options.otherwise)) : undefined;
|
|
395
395
|
|
|
396
396
|
Alternatives = Alternatives || require('../alternatives');
|
|
397
|
-
|
|
397
|
+
|
|
398
|
+
const alternativeOptions = { then, otherwise };
|
|
399
|
+
if (Object.prototype.hasOwnProperty.call(options, 'is')) {
|
|
400
|
+
alternativeOptions.is = options.is;
|
|
401
|
+
}
|
|
402
|
+
const obj = Alternatives.when(condition, alternativeOptions);
|
|
398
403
|
obj._flags.presence = 'ignore';
|
|
399
404
|
obj._baseType = this;
|
|
400
405
|
|
|
@@ -112,7 +112,7 @@ internals.Object = class extends Any {
|
|
|
112
112
|
if (!rename.options.multiple &&
|
|
113
113
|
renamed[rename.to]) {
|
|
114
114
|
|
|
115
|
-
errors.push(this.createError('object.rename.multiple', { from: matchedTargetKeys, to: rename.to }, state, options));
|
|
115
|
+
errors.push(this.createError('object.rename.regex.multiple', { from: matchedTargetKeys, to: rename.to }, state, options));
|
|
116
116
|
if (options.abortEarly) {
|
|
117
117
|
return finish();
|
|
118
118
|
}
|
|
@@ -122,7 +122,7 @@ internals.Object = class extends Any {
|
|
|
122
122
|
!rename.options.override &&
|
|
123
123
|
!renamed[rename.to]) {
|
|
124
124
|
|
|
125
|
-
errors.push(this.createError('object.rename.override', { from:
|
|
125
|
+
errors.push(this.createError('object.rename.regex.override', { from: matchedTargetKeys, to: rename.to }, state, options));
|
|
126
126
|
if (options.abortEarly) {
|
|
127
127
|
return finish();
|
|
128
128
|
}
|