joi 17.3.0 → 17.4.3

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.
@@ -1,6 +1,7 @@
1
1
  'use strict';
2
2
 
3
3
  const Assert = require('@hapi/hoek/lib/assert');
4
+ const Merge = require('@hapi/hoek/lib/merge');
4
5
 
5
6
  const Any = require('./any');
6
7
  const Common = require('../common');
@@ -44,8 +45,7 @@ module.exports = Any.extend({
44
45
  // Match all or one
45
46
 
46
47
  if (schema._flags.match) {
47
- let hits = 0;
48
- let matched;
48
+ const matched = [];
49
49
 
50
50
  for (let i = 0; i < schema.$_terms.matches.length; ++i) {
51
51
  const item = schema.$_terms.matches[i];
@@ -54,23 +54,27 @@ module.exports = Any.extend({
54
54
 
55
55
  const result = item.schema.$_validate(value, localState, prefs);
56
56
  if (!result.errors) {
57
- ++hits;
58
- matched = result.value;
57
+ matched.push(result.value);
59
58
  }
60
59
  else {
61
60
  localState.restore();
62
61
  }
63
62
  }
64
63
 
65
- if (!hits) {
64
+ if (matched.length === 0) {
66
65
  return { errors: error('alternatives.any') };
67
66
  }
68
67
 
69
68
  if (schema._flags.match === 'one') {
70
- return hits === 1 ? { value: matched } : { errors: error('alternatives.one') };
69
+ return matched.length === 1 ? { value: matched[0] } : { errors: error('alternatives.one') };
71
70
  }
72
71
 
73
- return hits === schema.$_terms.matches.length ? { value } : { errors: error('alternatives.all') };
72
+ if (matched.length !== schema.$_terms.matches.length) {
73
+ return { errors: error('alternatives.all') };
74
+ }
75
+
76
+ const allobj = schema.$_terms.matches.reduce((acc, v) => acc && v.schema.type === 'object', true);
77
+ return allobj ? { value: matched.reduce((acc, v) => Merge(acc, v, { mergeArrays: false })) } : { value: matched[matched.length - 1] };
74
78
  }
75
79
 
76
80
  // Match any
@@ -319,7 +319,7 @@ module.exports = Any.extend({
319
319
  continue;
320
320
  }
321
321
 
322
- if (schema.$_terms._inclusions.length &&
322
+ if ((schema.$_terms._inclusions.length || schema.$_terms._requireds.length) &&
323
323
  !isValid) {
324
324
 
325
325
  if (stripUnknown) {
@@ -342,6 +342,10 @@ module.exports = Any.extend({
342
342
 
343
343
  if (ordereds.length) {
344
344
  internals.fillOrderedErrors(schema, errors, ordereds, value, state, prefs);
345
+
346
+ if (!errors.length) {
347
+ internals.fillDefault(ordereds, value, state, prefs);
348
+ }
345
349
  }
346
350
 
347
351
  return errors.length ? errors : value;
@@ -677,6 +681,33 @@ internals.fillOrderedErrors = function (schema, errors, ordereds, value, state,
677
681
  };
678
682
 
679
683
 
684
+ internals.fillDefault = function (ordereds, value, state, prefs) {
685
+
686
+ const overrides = [];
687
+ let trailingUndefined = true;
688
+
689
+ for (let i = ordereds.length - 1; i >= 0; --i) {
690
+ const ordered = ordereds[i];
691
+ const ancestors = [value, ...state.ancestors];
692
+ const override = ordered.$_validate(undefined, state.localize(state.path, ancestors, ordered), prefs).value;
693
+
694
+ if (trailingUndefined) {
695
+ if (override === undefined) {
696
+ continue;
697
+ }
698
+
699
+ trailingUndefined = false;
700
+ }
701
+
702
+ overrides.unshift(override);
703
+ }
704
+
705
+ if (overrides.length) {
706
+ value.push(...overrides);
707
+ }
708
+ };
709
+
710
+
680
711
  internals.fastSplice = function (arr, i) {
681
712
 
682
713
  let pos = i;
package/lib/types/keys.js CHANGED
@@ -112,6 +112,10 @@ module.exports = Any.extend({
112
112
  return { value, errors: result.errors };
113
113
  }
114
114
 
115
+ if (result.value !== undefined) {
116
+ value[key] = result.value;
117
+ }
118
+
115
119
  errors.push(...result.errors);
116
120
  }
117
121
  else if (child.schema._flags.result === 'strip' ||
@@ -600,7 +604,7 @@ internals.dependency = function (schema, rel, key, peers, options) {
600
604
  const separator = Common.default(options.separator, '.');
601
605
  const paths = [];
602
606
  for (const peer of peers) {
603
- Assert(typeof peer === 'string', rel, 'peers must be a string or a reference');
607
+ Assert(typeof peer === 'string', rel, 'peers must be strings');
604
608
  paths.push(Compile.ref(peer, { separator, ancestor: 0, prefix: false }));
605
609
  }
606
610
 
@@ -257,7 +257,7 @@ module.exports = Any.extend({
257
257
  method(options) {
258
258
 
259
259
  if (options) {
260
- Common.assertOptions(options, ['allowUnicode', 'maxDomainSegments', 'minDomainSegments', 'tlds']);
260
+ Common.assertOptions(options, ['allowFullyQualified', 'allowUnicode', 'maxDomainSegments', 'minDomainSegments', 'tlds']);
261
261
  }
262
262
 
263
263
  const address = internals.addressOptions(options);
@@ -276,7 +276,7 @@ module.exports = Any.extend({
276
276
  email: {
277
277
  method(options = {}) {
278
278
 
279
- Common.assertOptions(options, ['allowUnicode', 'ignoreLength', 'maxDomainSegments', 'minDomainSegments', 'multiple', 'separator', 'tlds']);
279
+ Common.assertOptions(options, ['allowFullyQualified', 'allowUnicode', 'ignoreLength', 'maxDomainSegments', 'minDomainSegments', 'multiple', 'separator', 'tlds']);
280
280
  Assert(options.multiple === undefined || typeof options.multiple === 'boolean', 'multiple option must be an boolean');
281
281
 
282
282
  const address = internals.addressOptions(options);
@@ -632,7 +632,7 @@ module.exports = Any.extend({
632
632
  Common.assertOptions(options, ['allowRelative', 'allowQuerySquareBrackets', 'domain', 'relativeOnly', 'scheme']);
633
633
 
634
634
  if (options.domain) {
635
- Common.assertOptions(options.domain, ['allowUnicode', 'maxDomainSegments', 'minDomainSegments', 'tlds']);
635
+ Common.assertOptions(options.domain, ['allowFullyQualified', 'allowUnicode', 'maxDomainSegments', 'minDomainSegments', 'tlds']);
636
636
  }
637
637
 
638
638
  const { regex, scheme } = Uri.regex(options);
@@ -647,11 +647,12 @@ module.exports = Any.extend({
647
647
 
648
648
  const match = regex.exec(value);
649
649
  if (match) {
650
- if (domain) {
651
- const matched = match[1] || match[2];
652
- if (!Domain.isValid(matched, domain)) {
653
- return helpers.error('string.domain', { value: matched });
654
- }
650
+ const matched = match[1] || match[2];
651
+ if (domain &&
652
+ (!options.allowRelative || matched) &&
653
+ !Domain.isValid(matched, domain)) {
654
+
655
+ return helpers.error('string.domain', { value: matched });
655
656
  }
656
657
 
657
658
  return value;