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 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.3.0/API.md).
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
@@ -26,6 +26,8 @@ const internals = {
26
26
 
27
27
  internals.applyDefaults = function (schema) {
28
28
 
29
+ Hoek.assert(this, 'Must be invoked on a Joi instance.');
30
+
29
31
  if (this._defaults) {
30
32
  schema = this._defaults(schema);
31
33
  }
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
- const schema = item.schema;
35
- if (!schema) {
36
- const failed = item.is._validate(item.ref(state.reference || state.parent, options), null, options, state.parent).errors;
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(ref, options) {
88
+ when(condition, options) {
88
89
 
89
- Hoek.assert(Ref.isRef(ref) || typeof ref === 'string', 'Invalid reference:', ref);
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
- Hoek.assert(options.hasOwnProperty('is'), 'Missing "is" directive');
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 = Cast.schema(this._currentJoi, options.is);
103
+ let is;
104
+ if (!schemaCondition) {
105
+ is = Cast.schema(this._currentJoi, options.is);
97
106
 
98
- if (options.is === null || !(Ref.isRef(options.is) || options.is instanceof Any)) {
107
+ if (options.is === null || !(Ref.isRef(options.is) || options.is instanceof Any)) {
99
108
 
100
- // Only apply required if this wasn't already a schema or a ref, we'll suppose people know what they're doing
101
- is = is.required();
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(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
- Ref.push(obj._refs, item.ref);
118
- obj._refs = obj._refs.concat(item.is._refs);
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) {
@@ -385,7 +385,7 @@ module.exports = internals.Any = class {
385
385
  return obj;
386
386
  }
387
387
 
388
- when(ref, options) {
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
- const obj = Alternatives.when(ref, { is: options.is, then, otherwise });
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: rename.from, to: rename.to }, state, options));
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
  }
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "joi",
3
3
  "description": "Object schema validation",
4
- "version": "11.3.0",
4
+ "version": "11.4.0",
5
5
  "homepage": "https://github.com/hapijs/joi",
6
6
  "repository": "git://github.com/hapijs/joi",
7
7
  "main": "lib/index.js",