joi 17.13.2 → 18.0.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/dist/joi-browser.min.js +1 -1
- package/lib/annotate.js +2 -2
- package/lib/base.js +151 -74
- package/lib/cache.js +3 -4
- package/lib/common.js +1 -2
- package/lib/compile.js +23 -23
- package/lib/extend.js +10 -11
- package/lib/index.d.ts +78 -20
- package/lib/index.js +9 -10
- package/lib/manifest.js +15 -16
- package/lib/messages.js +10 -11
- package/lib/modify.js +10 -10
- package/lib/ref.js +15 -17
- package/lib/state.js +4 -5
- package/lib/template.js +8 -10
- package/lib/trace.js +4 -4
- package/lib/types/alternatives.js +39 -13
- package/lib/types/any.js +5 -5
- package/lib/types/array.js +32 -10
- package/lib/types/binary.js +3 -3
- package/lib/types/boolean.js +3 -3
- package/lib/types/date.js +3 -3
- package/lib/types/function.js +4 -4
- package/lib/types/keys.js +39 -16
- package/lib/types/link.js +11 -11
- package/lib/types/number.js +4 -4
- package/lib/types/string.js +84 -52
- package/lib/types/symbol.js +5 -5
- package/lib/validator.js +26 -18
- package/lib/values.js +4 -5
- package/package.json +21 -12
package/lib/annotate.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
-
const
|
|
3
|
+
const { clone } = require('@hapi/hoek');
|
|
4
4
|
|
|
5
5
|
const Common = require('./common');
|
|
6
6
|
|
|
@@ -22,7 +22,7 @@ exports.error = function (stripColorCodes) {
|
|
|
22
22
|
const redBgEscape = stripColorCodes ? '' : '\u001b[41m';
|
|
23
23
|
const endColor = stripColorCodes ? '' : '\u001b[0m';
|
|
24
24
|
|
|
25
|
-
const obj =
|
|
25
|
+
const obj = clone(this._original);
|
|
26
26
|
|
|
27
27
|
for (let i = this.details.length - 1; i >= 0; --i) { // Reverse order to process deepest child first
|
|
28
28
|
const pos = i + 1;
|
package/lib/base.js
CHANGED
|
@@ -1,9 +1,6 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
-
const
|
|
4
|
-
const Clone = require('@hapi/hoek/lib/clone');
|
|
5
|
-
const DeepEqual = require('@hapi/hoek/lib/deepEqual');
|
|
6
|
-
const Merge = require('@hapi/hoek/lib/merge');
|
|
3
|
+
const { assert, clone, deepEqual, merge } = require('@hapi/hoek');
|
|
7
4
|
|
|
8
5
|
const Cache = require('./cache');
|
|
9
6
|
const Common = require('./common');
|
|
@@ -61,7 +58,7 @@ internals.Base = class {
|
|
|
61
58
|
|
|
62
59
|
describe() {
|
|
63
60
|
|
|
64
|
-
|
|
61
|
+
assert(typeof Manifest.describe === 'function', 'Manifest functionality disabled');
|
|
65
62
|
return Manifest.describe(this);
|
|
66
63
|
}
|
|
67
64
|
|
|
@@ -75,14 +72,14 @@ internals.Base = class {
|
|
|
75
72
|
|
|
76
73
|
alter(targets) {
|
|
77
74
|
|
|
78
|
-
|
|
79
|
-
|
|
75
|
+
assert(targets && typeof targets === 'object' && !Array.isArray(targets), 'Invalid targets argument');
|
|
76
|
+
assert(!this._inRuleset(), 'Cannot set alterations inside a ruleset');
|
|
80
77
|
|
|
81
78
|
const obj = this.clone();
|
|
82
79
|
obj.$_terms.alterations = obj.$_terms.alterations || [];
|
|
83
80
|
for (const target in targets) {
|
|
84
81
|
const adjuster = targets[target];
|
|
85
|
-
|
|
82
|
+
assert(typeof adjuster === 'function', 'Alteration adjuster for', target, 'must be a function');
|
|
86
83
|
obj.$_terms.alterations.push({ target, adjuster });
|
|
87
84
|
}
|
|
88
85
|
|
|
@@ -92,16 +89,16 @@ internals.Base = class {
|
|
|
92
89
|
|
|
93
90
|
artifact(id) {
|
|
94
91
|
|
|
95
|
-
|
|
96
|
-
|
|
92
|
+
assert(id !== undefined, 'Artifact cannot be undefined');
|
|
93
|
+
assert(!this._cache, 'Cannot set an artifact with a rule cache');
|
|
97
94
|
|
|
98
95
|
return this.$_setFlag('artifact', id);
|
|
99
96
|
}
|
|
100
97
|
|
|
101
98
|
cast(to) {
|
|
102
99
|
|
|
103
|
-
|
|
104
|
-
|
|
100
|
+
assert(to === false || typeof to === 'string', 'Invalid to value');
|
|
101
|
+
assert(to === false || this._definition.cast[to], 'Type', this.type, 'does not support casting to', to);
|
|
105
102
|
|
|
106
103
|
return this.$_setFlag('cast', to === false ? undefined : to);
|
|
107
104
|
}
|
|
@@ -113,7 +110,7 @@ internals.Base = class {
|
|
|
113
110
|
|
|
114
111
|
description(desc) {
|
|
115
112
|
|
|
116
|
-
|
|
113
|
+
assert(desc && typeof desc === 'string', 'Description must be a non-empty string');
|
|
117
114
|
|
|
118
115
|
return this.$_setFlag('description', desc);
|
|
119
116
|
}
|
|
@@ -131,15 +128,15 @@ internals.Base = class {
|
|
|
131
128
|
|
|
132
129
|
error(err) {
|
|
133
130
|
|
|
134
|
-
|
|
135
|
-
|
|
131
|
+
assert(err, 'Missing error');
|
|
132
|
+
assert(err instanceof Error || typeof err === 'function', 'Must provide a valid Error object or a function');
|
|
136
133
|
|
|
137
134
|
return this.$_setFlag('error', err);
|
|
138
135
|
}
|
|
139
136
|
|
|
140
137
|
example(example, options = {}) {
|
|
141
138
|
|
|
142
|
-
|
|
139
|
+
assert(example !== undefined, 'Missing example');
|
|
143
140
|
Common.assertOptions(options, ['override']);
|
|
144
141
|
|
|
145
142
|
return this._inner('examples', example, { single: true, override: options.override });
|
|
@@ -148,13 +145,13 @@ internals.Base = class {
|
|
|
148
145
|
external(method, description) {
|
|
149
146
|
|
|
150
147
|
if (typeof method === 'object') {
|
|
151
|
-
|
|
148
|
+
assert(!description, 'Cannot combine options with description');
|
|
152
149
|
description = method.description;
|
|
153
150
|
method = method.method;
|
|
154
151
|
}
|
|
155
152
|
|
|
156
|
-
|
|
157
|
-
|
|
153
|
+
assert(typeof method === 'function', 'Method must be a function');
|
|
154
|
+
assert(description === undefined || description && typeof description === 'string', 'Description must be a non-empty string');
|
|
158
155
|
|
|
159
156
|
return this._inner('externals', { method, description }, { single: true });
|
|
160
157
|
}
|
|
@@ -175,8 +172,8 @@ internals.Base = class {
|
|
|
175
172
|
return this.$_setFlag('id', undefined);
|
|
176
173
|
}
|
|
177
174
|
|
|
178
|
-
|
|
179
|
-
|
|
175
|
+
assert(typeof id === 'string', 'id must be a non-empty string');
|
|
176
|
+
assert(/^[^\.]+$/.test(id), 'id cannot contain period character');
|
|
180
177
|
|
|
181
178
|
return this.$_setFlag('id', id);
|
|
182
179
|
}
|
|
@@ -188,23 +185,23 @@ internals.Base = class {
|
|
|
188
185
|
|
|
189
186
|
label(name) {
|
|
190
187
|
|
|
191
|
-
|
|
188
|
+
assert(name && typeof name === 'string', 'Label name must be a non-empty string');
|
|
192
189
|
|
|
193
190
|
return this.$_setFlag('label', name);
|
|
194
191
|
}
|
|
195
192
|
|
|
196
193
|
meta(meta) {
|
|
197
194
|
|
|
198
|
-
|
|
195
|
+
assert(meta !== undefined, 'Meta cannot be undefined');
|
|
199
196
|
|
|
200
197
|
return this._inner('metas', meta, { single: true });
|
|
201
198
|
}
|
|
202
199
|
|
|
203
200
|
note(...notes) {
|
|
204
201
|
|
|
205
|
-
|
|
202
|
+
assert(notes.length, 'Missing notes');
|
|
206
203
|
for (const note of notes) {
|
|
207
|
-
|
|
204
|
+
assert(note && typeof note === 'string', 'Notes must be non-empty strings');
|
|
208
205
|
}
|
|
209
206
|
|
|
210
207
|
return this._inner('notes', notes);
|
|
@@ -212,7 +209,7 @@ internals.Base = class {
|
|
|
212
209
|
|
|
213
210
|
only(mode = true) {
|
|
214
211
|
|
|
215
|
-
|
|
212
|
+
assert(typeof mode === 'boolean', 'Invalid mode:', mode);
|
|
216
213
|
|
|
217
214
|
return this.$_setFlag('only', mode);
|
|
218
215
|
}
|
|
@@ -224,11 +221,11 @@ internals.Base = class {
|
|
|
224
221
|
|
|
225
222
|
prefs(prefs) {
|
|
226
223
|
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
224
|
+
assert(prefs, 'Missing preferences');
|
|
225
|
+
assert(prefs.context === undefined, 'Cannot override context');
|
|
226
|
+
assert(prefs.externals === undefined, 'Cannot override externals');
|
|
227
|
+
assert(prefs.warnings === undefined, 'Cannot override warnings');
|
|
228
|
+
assert(prefs.debug === undefined, 'Cannot override debug');
|
|
232
229
|
|
|
233
230
|
Common.checkPreferences(prefs);
|
|
234
231
|
|
|
@@ -239,7 +236,7 @@ internals.Base = class {
|
|
|
239
236
|
|
|
240
237
|
presence(mode) {
|
|
241
238
|
|
|
242
|
-
|
|
239
|
+
assert(['optional', 'required', 'forbidden'].includes(mode), 'Unknown presence mode', mode);
|
|
243
240
|
|
|
244
241
|
return this.$_setFlag('presence', mode);
|
|
245
242
|
}
|
|
@@ -251,7 +248,7 @@ internals.Base = class {
|
|
|
251
248
|
|
|
252
249
|
result(mode) {
|
|
253
250
|
|
|
254
|
-
|
|
251
|
+
assert(['raw', 'strip'].includes(mode), 'Unknown result mode', mode);
|
|
255
252
|
|
|
256
253
|
return this.$_setFlag('result', mode);
|
|
257
254
|
}
|
|
@@ -277,9 +274,9 @@ internals.Base = class {
|
|
|
277
274
|
|
|
278
275
|
tag(...tags) {
|
|
279
276
|
|
|
280
|
-
|
|
277
|
+
assert(tags.length, 'Missing tags');
|
|
281
278
|
for (const tag of tags) {
|
|
282
|
-
|
|
279
|
+
assert(tag && typeof tag === 'string', 'Tags must be non-empty strings');
|
|
283
280
|
}
|
|
284
281
|
|
|
285
282
|
return this._inner('tags', tags);
|
|
@@ -287,7 +284,7 @@ internals.Base = class {
|
|
|
287
284
|
|
|
288
285
|
unit(name) {
|
|
289
286
|
|
|
290
|
-
|
|
287
|
+
assert(name && typeof name === 'string', 'Unit name must be a non-empty string');
|
|
291
288
|
|
|
292
289
|
return this.$_setFlag('unit', name);
|
|
293
290
|
}
|
|
@@ -313,8 +310,8 @@ internals.Base = class {
|
|
|
313
310
|
if (!['any', 'link'].includes(obj.type)) {
|
|
314
311
|
const conditions = when.is ? [when] : when.switch;
|
|
315
312
|
for (const item of conditions) {
|
|
316
|
-
|
|
317
|
-
|
|
313
|
+
assert(!item.then || item.then.type === 'any' || item.then.type === obj.type, 'Cannot combine', obj.type, 'with', item.then && item.then.type);
|
|
314
|
+
assert(!item.otherwise || item.otherwise.type === 'any' || item.otherwise.type === obj.type, 'Cannot combine', obj.type, 'with', item.otherwise && item.otherwise.type);
|
|
318
315
|
|
|
319
316
|
}
|
|
320
317
|
}
|
|
@@ -327,9 +324,9 @@ internals.Base = class {
|
|
|
327
324
|
|
|
328
325
|
cache(cache) {
|
|
329
326
|
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
327
|
+
assert(!this._inRuleset(), 'Cannot set caching inside a ruleset');
|
|
328
|
+
assert(!this._cache, 'Cannot override schema cache');
|
|
329
|
+
assert(this._flags.artifact === undefined, 'Cannot cache a rule with an artifact');
|
|
333
330
|
|
|
334
331
|
const obj = this.clone();
|
|
335
332
|
obj._cache = cache || Cache.provider.provision();
|
|
@@ -345,10 +342,10 @@ internals.Base = class {
|
|
|
345
342
|
|
|
346
343
|
concat(source) {
|
|
347
344
|
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
345
|
+
assert(Common.isSchema(source), 'Invalid schema object');
|
|
346
|
+
assert(this.type === 'any' || source.type === 'any' || source.type === this.type, 'Cannot merge type', this.type, 'with another type:', source.type);
|
|
347
|
+
assert(!this._inRuleset(), 'Cannot concatenate onto a schema with open ruleset');
|
|
348
|
+
assert(!source._inRuleset(), 'Cannot concatenate a schema with open ruleset');
|
|
352
349
|
|
|
353
350
|
let obj = this.clone();
|
|
354
351
|
|
|
@@ -401,16 +398,16 @@ internals.Base = class {
|
|
|
401
398
|
obj._flags.empty = obj._flags.empty.concat(source._flags.empty);
|
|
402
399
|
const flags = Object.assign({}, source._flags);
|
|
403
400
|
delete flags.empty;
|
|
404
|
-
|
|
401
|
+
merge(obj._flags, flags);
|
|
405
402
|
}
|
|
406
403
|
else if (source._flags.empty) {
|
|
407
404
|
obj._flags.empty = source._flags.empty;
|
|
408
405
|
const flags = Object.assign({}, source._flags);
|
|
409
406
|
delete flags.empty;
|
|
410
|
-
|
|
407
|
+
merge(obj._flags, flags);
|
|
411
408
|
}
|
|
412
409
|
else {
|
|
413
|
-
|
|
410
|
+
merge(obj._flags, source._flags);
|
|
414
411
|
}
|
|
415
412
|
|
|
416
413
|
// Terms
|
|
@@ -446,7 +443,7 @@ internals.Base = class {
|
|
|
446
443
|
|
|
447
444
|
extend(options) {
|
|
448
445
|
|
|
449
|
-
|
|
446
|
+
assert(!options.base, 'Cannot extend type with another base');
|
|
450
447
|
|
|
451
448
|
return Extend.type(this, options);
|
|
452
449
|
}
|
|
@@ -459,7 +456,7 @@ internals.Base = class {
|
|
|
459
456
|
|
|
460
457
|
fork(paths, adjuster) {
|
|
461
458
|
|
|
462
|
-
|
|
459
|
+
assert(!this._inRuleset(), 'Cannot fork inside a ruleset');
|
|
463
460
|
|
|
464
461
|
let obj = this; // eslint-disable-line consistent-this
|
|
465
462
|
for (let path of [].concat(paths)) {
|
|
@@ -471,24 +468,57 @@ internals.Base = class {
|
|
|
471
468
|
return obj;
|
|
472
469
|
}
|
|
473
470
|
|
|
471
|
+
isAsync() {
|
|
472
|
+
|
|
473
|
+
if (Boolean(this.$_terms.externals?.length)) {
|
|
474
|
+
return true;
|
|
475
|
+
}
|
|
476
|
+
|
|
477
|
+
if (this.$_terms.whens) {
|
|
478
|
+
for (const when of this.$_terms.whens) {
|
|
479
|
+
if (when.then?.isAsync()) {
|
|
480
|
+
return true;
|
|
481
|
+
}
|
|
482
|
+
|
|
483
|
+
if (when.otherwise?.isAsync()) {
|
|
484
|
+
return true;
|
|
485
|
+
}
|
|
486
|
+
|
|
487
|
+
if (when.switch) {
|
|
488
|
+
for (const item of when.switch) {
|
|
489
|
+
if (item.then?.isAsync()) {
|
|
490
|
+
return true;
|
|
491
|
+
}
|
|
492
|
+
|
|
493
|
+
if (item.otherwise?.isAsync()) {
|
|
494
|
+
return true;
|
|
495
|
+
}
|
|
496
|
+
}
|
|
497
|
+
}
|
|
498
|
+
}
|
|
499
|
+
}
|
|
500
|
+
|
|
501
|
+
return false;
|
|
502
|
+
}
|
|
503
|
+
|
|
474
504
|
rule(options) {
|
|
475
505
|
|
|
476
506
|
const def = this._definition;
|
|
477
507
|
Common.assertOptions(options, Object.keys(def.modifiers));
|
|
478
508
|
|
|
479
|
-
|
|
509
|
+
assert(this.$_temp.ruleset !== false, 'Cannot apply rules to empty ruleset or the last rule added does not support rule properties');
|
|
480
510
|
const start = this.$_temp.ruleset === null ? this._rules.length - 1 : this.$_temp.ruleset;
|
|
481
|
-
|
|
511
|
+
assert(start >= 0 && start < this._rules.length, 'Cannot apply rules to empty ruleset');
|
|
482
512
|
|
|
483
513
|
const obj = this.clone();
|
|
484
514
|
|
|
485
515
|
for (let i = start; i < obj._rules.length; ++i) {
|
|
486
516
|
const original = obj._rules[i];
|
|
487
|
-
const rule =
|
|
517
|
+
const rule = clone(original);
|
|
488
518
|
|
|
489
519
|
for (const name in options) {
|
|
490
520
|
def.modifiers[name](rule, options[name]);
|
|
491
|
-
|
|
521
|
+
assert(rule.name === original.name, 'Cannot change rule name');
|
|
492
522
|
}
|
|
493
523
|
|
|
494
524
|
obj._rules[i] = rule;
|
|
@@ -504,7 +534,7 @@ internals.Base = class {
|
|
|
504
534
|
|
|
505
535
|
get ruleset() {
|
|
506
536
|
|
|
507
|
-
|
|
537
|
+
assert(!this._inRuleset(), 'Cannot start a new ruleset without closing the previous one');
|
|
508
538
|
|
|
509
539
|
const obj = this.clone();
|
|
510
540
|
obj.$_temp.ruleset = obj._rules.length;
|
|
@@ -520,7 +550,7 @@ internals.Base = class {
|
|
|
520
550
|
|
|
521
551
|
targets = [].concat(targets);
|
|
522
552
|
|
|
523
|
-
|
|
553
|
+
assert(!this._inRuleset(), 'Cannot tailor inside a ruleset');
|
|
524
554
|
|
|
525
555
|
let obj = this; // eslint-disable-line consistent-this
|
|
526
556
|
|
|
@@ -528,7 +558,7 @@ internals.Base = class {
|
|
|
528
558
|
for (const { target, adjuster } of this.$_terms.alterations) {
|
|
529
559
|
if (targets.includes(target)) {
|
|
530
560
|
obj = adjuster(obj);
|
|
531
|
-
|
|
561
|
+
assert(Common.isSchema(obj), 'Alteration adjuster for', target, 'failed to return a schema object');
|
|
532
562
|
}
|
|
533
563
|
}
|
|
534
564
|
}
|
|
@@ -563,11 +593,11 @@ internals.Base = class {
|
|
|
563
593
|
options = { name: options };
|
|
564
594
|
}
|
|
565
595
|
|
|
566
|
-
|
|
567
|
-
|
|
596
|
+
assert(options && typeof options === 'object', 'Invalid options');
|
|
597
|
+
assert(options.name && typeof options.name === 'string', 'Invalid rule name');
|
|
568
598
|
|
|
569
599
|
for (const key in options) {
|
|
570
|
-
|
|
600
|
+
assert(key[0] !== '_', 'Cannot set private rule properties');
|
|
571
601
|
}
|
|
572
602
|
|
|
573
603
|
const rule = Object.assign({}, options); // Shallow cloned
|
|
@@ -577,14 +607,14 @@ internals.Base = class {
|
|
|
577
607
|
const definition = this._definition.rules[rule.method];
|
|
578
608
|
const args = rule.args;
|
|
579
609
|
|
|
580
|
-
|
|
610
|
+
assert(definition, 'Unknown rule', rule.method);
|
|
581
611
|
|
|
582
612
|
// Args
|
|
583
613
|
|
|
584
614
|
const obj = this.clone();
|
|
585
615
|
|
|
586
616
|
if (args) {
|
|
587
|
-
|
|
617
|
+
assert(Object.keys(args).length === 1 || Object.keys(args).length === this._definition.rules[rule.name].args.length, 'Invalid rule definition for', this.type, rule.name);
|
|
588
618
|
|
|
589
619
|
for (const key in args) {
|
|
590
620
|
let arg = args[key];
|
|
@@ -606,7 +636,7 @@ internals.Base = class {
|
|
|
606
636
|
|
|
607
637
|
if (resolver.assert) {
|
|
608
638
|
const error = Common.validateArg(arg, key, resolver);
|
|
609
|
-
|
|
639
|
+
assert(!error, error, 'or reference');
|
|
610
640
|
}
|
|
611
641
|
}
|
|
612
642
|
}
|
|
@@ -690,7 +720,7 @@ internals.Base = class {
|
|
|
690
720
|
|
|
691
721
|
$_mutateRebuild() {
|
|
692
722
|
|
|
693
|
-
|
|
723
|
+
assert(!this._inRuleset(), 'Cannot add this rule inside a ruleset');
|
|
694
724
|
|
|
695
725
|
this._refs.reset();
|
|
696
726
|
this._ids.reset();
|
|
@@ -736,14 +766,14 @@ internals.Base = class {
|
|
|
736
766
|
|
|
737
767
|
$_setFlag(name, value, options = {}) {
|
|
738
768
|
|
|
739
|
-
|
|
769
|
+
assert(name[0] === '_' || !this._inRuleset(), 'Cannot set flag inside a ruleset');
|
|
740
770
|
|
|
741
771
|
const flag = this._definition.flags[name] || {};
|
|
742
|
-
if (
|
|
772
|
+
if (deepEqual(value, flag.default)) {
|
|
743
773
|
value = undefined;
|
|
744
774
|
}
|
|
745
775
|
|
|
746
|
-
if (
|
|
776
|
+
if (deepEqual(value, this._flags[name])) {
|
|
747
777
|
return this;
|
|
748
778
|
}
|
|
749
779
|
|
|
@@ -790,7 +820,7 @@ internals.Base = class {
|
|
|
790
820
|
target._valids = this._valids && this._valids.clone();
|
|
791
821
|
target._invalids = this._invalids && this._invalids.clone();
|
|
792
822
|
target._rules = this._rules.slice();
|
|
793
|
-
target._singleRules =
|
|
823
|
+
target._singleRules = clone(this._singleRules, { shallow: true });
|
|
794
824
|
target._refs = this._refs.clone();
|
|
795
825
|
target._flags = Object.assign({}, this._flags);
|
|
796
826
|
target._cache = null;
|
|
@@ -828,8 +858,8 @@ internals.Base = class {
|
|
|
828
858
|
|
|
829
859
|
Common.assertOptions(options, 'literal');
|
|
830
860
|
|
|
831
|
-
|
|
832
|
-
|
|
861
|
+
assert(value !== undefined, 'Missing', flag, 'value');
|
|
862
|
+
assert(typeof value === 'function' || !options.literal, 'Only function value supports literal option');
|
|
833
863
|
|
|
834
864
|
if (typeof value === 'function' &&
|
|
835
865
|
options.literal) {
|
|
@@ -938,7 +968,7 @@ internals.Base = class {
|
|
|
938
968
|
|
|
939
969
|
_inner(type, values, options = {}) {
|
|
940
970
|
|
|
941
|
-
|
|
971
|
+
assert(!this._inRuleset(), `Cannot set ${type} inside a ruleset`);
|
|
942
972
|
|
|
943
973
|
const obj = this.clone();
|
|
944
974
|
if (!obj.$_terms[type] ||
|
|
@@ -1025,14 +1055,14 @@ internals.Base = class {
|
|
|
1025
1055
|
}
|
|
1026
1056
|
|
|
1027
1057
|
for (const value of values) {
|
|
1028
|
-
|
|
1029
|
-
|
|
1058
|
+
assert(value !== undefined, 'Cannot call allow/valid/invalid with undefined');
|
|
1059
|
+
assert(value !== Common.symbols.override, 'Override must be the first value');
|
|
1030
1060
|
|
|
1031
1061
|
const other = key === '_invalids' ? '_valids' : '_invalids';
|
|
1032
1062
|
if (obj[other]) {
|
|
1033
1063
|
obj[other].remove(value);
|
|
1034
1064
|
if (!obj[other].length) {
|
|
1035
|
-
|
|
1065
|
+
assert(key === '_valids' || !obj._flags.only, 'Setting invalid value', value, 'leaves schema rejecting all values due to previous valid rule');
|
|
1036
1066
|
obj[other] = null;
|
|
1037
1067
|
}
|
|
1038
1068
|
}
|
|
@@ -1042,6 +1072,53 @@ internals.Base = class {
|
|
|
1042
1072
|
|
|
1043
1073
|
return obj;
|
|
1044
1074
|
}
|
|
1075
|
+
|
|
1076
|
+
// Standard Schema
|
|
1077
|
+
|
|
1078
|
+
get '~standard'() {
|
|
1079
|
+
|
|
1080
|
+
const mapToStandardError = (error) => {
|
|
1081
|
+
|
|
1082
|
+
let issues;
|
|
1083
|
+
if (Errors.ValidationError.isError(error)) {
|
|
1084
|
+
issues = error.details.map(({ message, path }) => ({
|
|
1085
|
+
message,
|
|
1086
|
+
path
|
|
1087
|
+
}));
|
|
1088
|
+
}
|
|
1089
|
+
else {
|
|
1090
|
+
issues = [{
|
|
1091
|
+
message: error.message
|
|
1092
|
+
}];
|
|
1093
|
+
}
|
|
1094
|
+
|
|
1095
|
+
return {
|
|
1096
|
+
issues
|
|
1097
|
+
};
|
|
1098
|
+
};
|
|
1099
|
+
|
|
1100
|
+
const mapToStandardValue = (value) => ({ value });
|
|
1101
|
+
|
|
1102
|
+
return {
|
|
1103
|
+
version: 1,
|
|
1104
|
+
vendor: 'joi',
|
|
1105
|
+
validate: (value) => {
|
|
1106
|
+
|
|
1107
|
+
const result = Validator.standard(value, this);
|
|
1108
|
+
|
|
1109
|
+
if (result instanceof Promise) {
|
|
1110
|
+
return result
|
|
1111
|
+
.then(mapToStandardValue, mapToStandardError);
|
|
1112
|
+
}
|
|
1113
|
+
|
|
1114
|
+
if (!result.error) {
|
|
1115
|
+
return mapToStandardValue(result.value);
|
|
1116
|
+
}
|
|
1117
|
+
|
|
1118
|
+
return mapToStandardError(result.error);
|
|
1119
|
+
}
|
|
1120
|
+
};
|
|
1121
|
+
}
|
|
1045
1122
|
};
|
|
1046
1123
|
|
|
1047
1124
|
|
package/lib/cache.js
CHANGED
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
-
const
|
|
4
|
-
const Clone = require('@hapi/hoek/lib/clone');
|
|
3
|
+
const { assert, clone } = require('@hapi/hoek');
|
|
5
4
|
|
|
6
5
|
const Common = require('./common');
|
|
7
6
|
|
|
@@ -28,7 +27,7 @@ internals.Cache = class {
|
|
|
28
27
|
constructor(options = {}) {
|
|
29
28
|
|
|
30
29
|
Common.assertOptions(options, ['max']);
|
|
31
|
-
|
|
30
|
+
assert(options.max === undefined || options.max && options.max > 0 && isFinite(options.max), 'Invalid max cache size');
|
|
32
31
|
|
|
33
32
|
this._max = options.max || internals.max;
|
|
34
33
|
|
|
@@ -66,7 +65,7 @@ internals.Cache = class {
|
|
|
66
65
|
const node = this._map.get(key);
|
|
67
66
|
if (node) {
|
|
68
67
|
this._list.first(node);
|
|
69
|
-
return
|
|
68
|
+
return clone(node.value);
|
|
70
69
|
}
|
|
71
70
|
}
|
|
72
71
|
|