joi 9.0.3 → 9.2.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/LICENSE CHANGED
@@ -1,5 +1,5 @@
1
- Copyright (c) 2012-2016, Project contributors.
2
- Copyright (c) 2012-2014, Walmart.
1
+ Copyright (c) 2012-2016, Project contributors
2
+ Copyright (c) 2012-2014, Walmart
3
3
  All rights reserved.
4
4
 
5
5
  Redistribution and use in source and binary forms, with or without
@@ -26,4 +26,4 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26
26
 
27
27
  * * *
28
28
 
29
- The complete list of contributors can be found at: https://github.com/hapijs/joi/graphs/contributors
29
+ The complete list of contributors can be found at: https://github.com/hapijs/joi/graphs/contributors
package/README.md CHANGED
@@ -4,8 +4,15 @@ Object schema description language and validator for JavaScript objects.
4
4
 
5
5
  [![npm version](https://badge.fury.io/js/joi.svg)](http://badge.fury.io/js/joi)
6
6
  [![Build Status](https://secure.travis-ci.org/hapijs/joi.svg?branch=master)](http://travis-ci.org/hapijs/joi)
7
+ <!--
8
+
9
+ Remove those badges until they work properly on semver.
10
+
7
11
  [![Dependencies Status](https://david-dm.org/hapijs/joi.svg)](https://david-dm.org/hapijs/joi)
8
12
  [![DevDependencies Status](https://david-dm.org/hapijs/joi/dev-status.svg)](https://david-dm.org/hapijs/joi#info=devDependencies)
13
+
14
+ -->
15
+ [![NSP Status](https://nodesecurity.io/orgs/hapijs/projects/0394bf83-b5bc-410b-878c-e8cf1b92033e/badge)](https://nodesecurity.io/orgs/hapijs/projects/0394bf83-b5bc-410b-878c-e8cf1b92033e)
9
16
  [![Known Vulnerabilities](https://snyk.io/test/npm/joi/badge.svg)](https://snyk.io/test/npm/joi)
10
17
 
11
18
  [![Join the chat at https://gitter.im/hapijs/joi](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/hapijs/joi?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
@@ -95,7 +102,7 @@ When validating a schema:
95
102
  * Rules are defined in an additive fashion and evaluated in order after whitelist and blacklist checks.
96
103
 
97
104
  # API
98
- See the [API Reference](https://github.com/hapijs/joi/blob/v9.0.3/API.md).
105
+ See the [API Reference](https://github.com/hapijs/joi/blob/v9.2.0/API.md).
99
106
 
100
107
  # Browsers
101
108
 
package/lib/any.js CHANGED
@@ -450,15 +450,15 @@ module.exports = internals.Any = class {
450
450
  else if (typeof this._flags.default === 'function' &&
451
451
  !(this._flags.func && !this._flags.default.description)) {
452
452
 
453
- let arg;
453
+ let args;
454
454
 
455
455
  if (state.parent !== null &&
456
456
  this._flags.default.length > 0) {
457
457
 
458
- arg = Hoek.clone(state.parent);
458
+ args = [Hoek.clone(state.parent), options];
459
459
  }
460
460
 
461
- const defaultValue = internals._try(this._flags.default, arg);
461
+ const defaultValue = internals._try(this._flags.default, args);
462
462
  finalValue = defaultValue.value;
463
463
  if (defaultValue.error) {
464
464
  errors.push(this.createError('any.default', defaultValue.error, state, options));
@@ -766,13 +766,13 @@ internals.Any.prototype.disallow = internals.Any.prototype.not = internals.Any.p
766
766
  internals.Any.prototype.exist = internals.Any.prototype.required;
767
767
 
768
768
 
769
- internals._try = function (fn, arg) {
769
+ internals._try = function (fn, args) {
770
770
 
771
771
  let err;
772
772
  let result;
773
773
 
774
774
  try {
775
- result = fn.call(null, arg);
775
+ result = fn.apply(null, args);
776
776
  }
777
777
  catch (e) {
778
778
  err = e;
package/lib/array.js CHANGED
@@ -509,14 +509,14 @@ internals.Array = class extends Any {
509
509
 
510
510
  if (knownMisses.length) {
511
511
  if (unknownMisses) {
512
- errors.push(this.createError('array.includesRequiredBoth', { knownMisses: knownMisses, unknownMisses: unknownMisses }, { key: state.key, path: state.path }, options));
512
+ errors.push(this.createError('array.includesRequiredBoth', { knownMisses, unknownMisses }, { key: state.key, path: state.path }, options));
513
513
  }
514
514
  else {
515
- errors.push(this.createError('array.includesRequiredKnowns', { knownMisses: knownMisses }, { key: state.key, path: state.path }, options));
515
+ errors.push(this.createError('array.includesRequiredKnowns', { knownMisses }, { key: state.key, path: state.path }, options));
516
516
  }
517
517
  }
518
518
  else {
519
- errors.push(this.createError('array.includesRequiredUnknowns', { unknownMisses: unknownMisses }, { key: state.key, path: state.path }, options));
519
+ errors.push(this.createError('array.includesRequiredUnknowns', { unknownMisses }, { key: state.key, path: state.path }, options));
520
520
  }
521
521
  }
522
522
 
package/lib/errors.js CHANGED
@@ -232,7 +232,11 @@ internals.serializer = function () {
232
232
  };
233
233
 
234
234
 
235
- internals.annotate = function () {
235
+ internals.annotate = function (stripColorCodes) {
236
+
237
+ const redFgEscape = stripColorCodes ? '' : '\u001b[31m';
238
+ const redBgEscape = stripColorCodes ? '' : '\u001b[41m';
239
+ const endColor = stripColorCodes ? '' : '\u001b[0m';
236
240
 
237
241
  if (typeof this._object !== 'object') {
238
242
  return this.details[0].message;
@@ -242,7 +246,7 @@ internals.annotate = function () {
242
246
 
243
247
  const lookup = {};
244
248
  for (let i = this.details.length - 1; i >= 0; --i) { // Reverse order to process deepest child first
245
- const pos = this.details.length - i;
249
+ const pos = i + 1;
246
250
  const error = this.details[i];
247
251
  const path = error.path.split('.');
248
252
  let ref = obj;
@@ -254,13 +258,13 @@ internals.annotate = function () {
254
258
  else {
255
259
  const value = ref[seg];
256
260
  if (Array.isArray(ref)) {
257
- const arrayLabel = '_$idx$_' + (i + 1) + '_$end$_';
261
+ const arrayLabel = `_$idx$_${pos}_$end$_`;
258
262
  if (!ref.placeholders) {
259
263
  ref.placeholders = {};
260
264
  }
261
265
 
262
266
  if (ref.placeholders[seg]) {
263
- ref.placeholders[seg] = ref.placeholders[seg].replace('_$end$_', ', ' + (i + 1) + '_$end$_');
267
+ ref.placeholders[seg] = ref.placeholders[seg].replace('_$end$_', `, ${pos}_$end$_`);
264
268
  }
265
269
  else {
266
270
  ref.placeholders[seg] = arrayLabel;
@@ -269,19 +273,19 @@ internals.annotate = function () {
269
273
  else {
270
274
  if (value !== undefined) {
271
275
  delete ref[seg];
272
- const objectLabel = seg + '_$key$_' + pos + '_$end$_';
276
+ const objectLabel = `${seg}_$key$_${pos}_$end$_`;
273
277
  ref[objectLabel] = value;
274
278
  lookup[error.path] = objectLabel;
275
279
  }
276
280
  else if (lookup[error.path]) {
277
281
  const replacement = lookup[error.path];
278
- const appended = replacement.replace('_$end$_', ', ' + pos + '_$end$_');
282
+ const appended = replacement.replace('_$end$_', `, ${pos}_$end$_`);
279
283
  ref[appended] = ref[replacement];
280
284
  lookup[error.path] = appended;
281
285
  delete ref[replacement];
282
286
  }
283
287
  else {
284
- ref['_$miss$_' + seg + '|' + pos + '_$end$_'] = '__missing__';
288
+ ref[`_$miss$_${seg}|${pos}_$end$_`] = '__missing__';
285
289
  }
286
290
  }
287
291
  }
@@ -296,18 +300,19 @@ internals.annotate = function () {
296
300
  };
297
301
 
298
302
  let message = internals.safeStringify(obj, 2)
299
- .replace(replacers.key, ($0, $1) => '" \u001b[31m[' + $1 + ']\u001b[0m')
300
- .replace(replacers.missing, ($0, $1, $2) => '\u001b[41m"' + $1 + '"\u001b[0m\u001b[31m [' + $2 + ']: -- missing --\u001b[0m')
301
- .replace(replacers.arrayIndex, ($0, $1, $2) => '\n' + $2 + ' \u001b[31m[' + $1 + ']\u001b[0m')
303
+ .replace(replacers.key, ($0, $1) => `" ${redFgEscape}[${$1}]${endColor}`)
304
+ .replace(replacers.missing, ($0, $1, $2) => `${redBgEscape}"${$1}"${endColor}${redFgEscape} [${$2}]: -- missing --${endColor}`)
305
+ .replace(replacers.arrayIndex, ($0, $1, $2) => `\n${$2} ${redFgEscape}[${$1}]${endColor}`)
302
306
  .replace(replacers.specials, ($0, $1) => $1);
303
307
 
304
- message = message + '\n\u001b[31m';
308
+ message = `${message}\n${redFgEscape}`;
305
309
 
306
310
  for (let i = 0; i < this.details.length; ++i) {
307
- message = message + '\n[' + (i + 1) + '] ' + this.details[i].message;
311
+ const pos = i + 1;
312
+ message = `${message}\n[${pos}] ${this.details[i].message}`;
308
313
  }
309
314
 
310
- message = message + '\u001b[0m';
315
+ message = message + endColor;
311
316
 
312
317
  return message;
313
318
  };
package/lib/object.js CHANGED
@@ -244,7 +244,7 @@ internals.Object = class extends Any {
244
244
 
245
245
  for (let i = 0; i < this._inner.dependencies.length; ++i) {
246
246
  const dep = this._inner.dependencies[i];
247
- const err = internals[dep.type].call(this, dep.key !== null && value[dep.key], dep.peers, target, { key: dep.key, path: (state.path || '') + (dep.key ? '.' + dep.key : '') }, options);
247
+ const err = internals[dep.type].call(this, dep.key !== null && target[dep.key], dep.peers, target, { key: dep.key, path: (state.path || '') + (dep.key ? '.' + dep.key : '') }, options);
248
248
  if (err instanceof Errors.Err) {
249
249
  errors.push(err);
250
250
  if (options.abortEarly) {
package/lib/string.js CHANGED
@@ -292,18 +292,73 @@ internals.String = class extends Any {
292
292
  });
293
293
  }
294
294
 
295
- guid() {
295
+ guid(guidOptions) {
296
296
 
297
- const regex = /^[A-F0-9]{8}(?:-?[A-F0-9]{4}){3}-?[A-F0-9]{12}$/i;
298
- const regex2 = /^\{[A-F0-9]{8}(?:-?[A-F0-9]{4}){3}-?[A-F0-9]{12}\}$/i;
297
+ const brackets = {
298
+ '{': '}', '[': ']', '(': ')', '': ''
299
+ };
300
+
301
+ const uuids = {
302
+ 'uuidv1': '1',
303
+ 'uuidv2': '2',
304
+ 'uuidv3': '3',
305
+ 'uuidv4': '4',
306
+ 'uuidv5': '5'
307
+ };
299
308
 
300
- return this._test('guid', undefined, function (value, state, options) {
309
+ const versions = [];
301
310
 
302
- if (regex.test(value) || regex2.test(value)) {
303
- return value;
311
+ if (guidOptions && guidOptions.version) {
312
+ if (!Array.isArray(guidOptions.version)) {
313
+ guidOptions.version = [guidOptions.version];
314
+ }
315
+
316
+ Hoek.assert(guidOptions.version.length >= 1, 'version must have at least 1 valid version specified');
317
+
318
+ for (let i = 0; i < guidOptions.version.length; ++i) {
319
+ let version = guidOptions.version[i];
320
+ Hoek.assert(typeof version === 'string', 'version at position ' + i + ' must be a string');
321
+ version = version.toLowerCase();
322
+ Hoek.assert(uuids[version], 'version at position ' + i + ' must be one of ' + Object.keys(uuids).join(', '));
323
+ Hoek.assert(versions.indexOf(version) === -1, 'version at position ' + i + ' must not be a duplicate.');
324
+ versions.push(version);
325
+ }
326
+ }
327
+
328
+ const regex = /^([\[{\(]?)([0-9A-F]{8})([:-]?)([0-9A-F]{4})([:-]?)([0-9A-F]{4})([:-]?)([0-9A-F]{4})([:-]?)([0-9A-F]{12})([\]}\)]?)$/i;
329
+
330
+ return this._test('guid', guidOptions, function (value, state, options) {
331
+
332
+ const results = regex.exec(value);
333
+
334
+ if (!results) {
335
+ return this.createError('string.guid', { value }, state, options);
336
+ }
337
+
338
+ // Matching braces
339
+ if (brackets[results[1]] !== results[11]) {
340
+ return this.createError('string.guid', { value }, state, options);
341
+ }
342
+
343
+ // Matching separators
344
+ if (results[3] !== results[5] || results[3] !== results[7] || results[3] !== results[9]) {
345
+ return this.createError('string.guid', { value }, state, options);
304
346
  }
305
347
 
306
- return this.createError('string.guid', { value }, state, options);
348
+ // Specific UUID versions
349
+ if (versions.length) {
350
+ const validVersions = versions.some((uuidVersion) => {
351
+
352
+ return results[6][0] === uuids[uuidVersion];
353
+ });
354
+
355
+ // Valid version and 89AB check
356
+ if (!(validVersions && /[89AB]/i.test(results[8][0]))) {
357
+ return this.createError('string.guid', { value }, state, options);
358
+ }
359
+ }
360
+
361
+ return value;
307
362
  });
308
363
  }
309
364
 
@@ -475,5 +530,8 @@ internals.String.prototype.length = internals.compare('length', (value, limit, e
475
530
  return length === limit;
476
531
  });
477
532
 
533
+ // Aliases
534
+
535
+ internals.String.prototype.uuid = internals.String.prototype.guid;
478
536
 
479
537
  module.exports = new internals.String();
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "joi",
3
3
  "description": "Object schema validation",
4
- "version": "9.0.3",
4
+ "version": "9.2.0",
5
5
  "homepage": "https://github.com/hapijs/joi",
6
6
  "repository": "git://github.com/hapijs/joi",
7
7
  "main": "lib/index.js",
@@ -21,9 +21,9 @@
21
21
  "topo": "2.x.x"
22
22
  },
23
23
  "devDependencies": {
24
- "code": "3.x.x",
25
- "lab": "10.x.x",
26
- "markdown-toc": "0.12.x"
24
+ "code": "4.x.x",
25
+ "lab": "11.x.x",
26
+ "markdown-toc": "0.13.x"
27
27
  },
28
28
  "scripts": {
29
29
  "test": "lab -t 100 -a code -L",