joi 14.2.0 → 17.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.
Files changed (59) hide show
  1. package/LICENSE.md +10 -0
  2. package/README.md +9 -118
  3. package/dist/joi-browser.min.js +1 -0
  4. package/lib/annotate.js +175 -0
  5. package/lib/base.js +1068 -0
  6. package/lib/cache.js +143 -0
  7. package/lib/common.js +216 -0
  8. package/lib/compile.js +283 -0
  9. package/lib/errors.js +160 -269
  10. package/lib/extend.js +312 -0
  11. package/lib/index.d.ts +2200 -0
  12. package/lib/index.js +179 -347
  13. package/lib/manifest.js +476 -0
  14. package/lib/messages.js +178 -0
  15. package/lib/modify.js +267 -0
  16. package/lib/ref.js +386 -25
  17. package/lib/schemas.js +291 -15
  18. package/lib/state.js +152 -0
  19. package/lib/template.js +427 -0
  20. package/lib/trace.js +346 -0
  21. package/lib/types/alternatives.js +329 -0
  22. package/lib/types/any.js +174 -0
  23. package/lib/types/array.js +775 -0
  24. package/lib/types/binary.js +98 -0
  25. package/lib/types/boolean.js +150 -0
  26. package/lib/types/date.js +233 -0
  27. package/lib/types/function.js +93 -0
  28. package/lib/types/keys.js +1043 -0
  29. package/lib/types/link.js +168 -0
  30. package/lib/types/number.js +335 -0
  31. package/lib/types/object.js +22 -0
  32. package/lib/types/string.js +820 -0
  33. package/lib/types/symbol.js +102 -0
  34. package/lib/validator.js +650 -0
  35. package/lib/values.js +263 -0
  36. package/package.json +34 -29
  37. package/CHANGELOG.md +0 -3
  38. package/LICENSE +0 -25
  39. package/lib/cast.js +0 -64
  40. package/lib/language.js +0 -166
  41. package/lib/set.js +0 -191
  42. package/lib/types/alternatives/index.js +0 -218
  43. package/lib/types/any/index.js +0 -978
  44. package/lib/types/any/settings.js +0 -36
  45. package/lib/types/array/index.js +0 -707
  46. package/lib/types/binary/index.js +0 -100
  47. package/lib/types/boolean/index.js +0 -100
  48. package/lib/types/date/index.js +0 -182
  49. package/lib/types/func/index.js +0 -90
  50. package/lib/types/lazy/index.js +0 -82
  51. package/lib/types/number/index.js +0 -248
  52. package/lib/types/object/index.js +0 -957
  53. package/lib/types/state.js +0 -11
  54. package/lib/types/string/index.js +0 -703
  55. package/lib/types/string/ip.js +0 -54
  56. package/lib/types/string/rfc3986.js +0 -219
  57. package/lib/types/string/uri.js +0 -46
  58. package/lib/types/symbol/index.js +0 -93
  59. package/lib/types/symbols.js +0 -5
@@ -1,978 +0,0 @@
1
- 'use strict';
2
-
3
- // Load modules
4
-
5
- const Hoek = require('hoek');
6
- const Settings = require('./settings');
7
- const Ref = require('../../ref');
8
- const Errors = require('../../errors');
9
- const State = require('../state');
10
- const Symbols = require('../symbols');
11
-
12
- // Delay-loaded to prevent circular dependencies
13
- let Alternatives = null;
14
- let Cast = null;
15
- let Schemas = null;
16
-
17
-
18
- // Declare internals
19
-
20
- const internals = {
21
- Set: require('../../set')
22
- };
23
-
24
-
25
- internals.defaults = {
26
- abortEarly: true,
27
- convert: true,
28
- allowUnknown: false,
29
- skipFunctions: false,
30
- stripUnknown: false,
31
- language: {},
32
- presence: 'optional',
33
- strip: false,
34
- noDefaults: false,
35
- escapeHtml: false
36
-
37
- // context: null
38
- };
39
-
40
-
41
- module.exports = internals.Any = class {
42
-
43
- constructor() {
44
-
45
- Cast = Cast || require('../../cast');
46
-
47
- this.isJoi = true;
48
- this._type = 'any';
49
- this._settings = null;
50
- this._valids = new internals.Set();
51
- this._invalids = new internals.Set();
52
- this._tests = [];
53
- this._refs = [];
54
- this._flags = {
55
- /*
56
- presence: 'optional', // optional, required, forbidden, ignore
57
- allowOnly: false,
58
- allowUnknown: undefined,
59
- default: undefined,
60
- forbidden: false,
61
- encoding: undefined,
62
- insensitive: false,
63
- trim: false,
64
- normalize: undefined, // NFC, NFD, NFKC, NFKD
65
- case: undefined, // upper, lower
66
- empty: undefined,
67
- func: false,
68
- raw: false
69
- */
70
- };
71
-
72
- this._description = null;
73
- this._unit = null;
74
- this._notes = [];
75
- this._tags = [];
76
- this._examples = [];
77
- this._meta = [];
78
-
79
- this._inner = {}; // Hash of arrays of immutable objects
80
- }
81
-
82
- _init() {
83
-
84
- return this;
85
- }
86
-
87
- get schemaType() {
88
-
89
- return this._type;
90
- }
91
-
92
- createError(type, context, state, options, flags = this._flags) {
93
-
94
- return Errors.create(type, context, state, options, flags);
95
- }
96
-
97
- createOverrideError(type, context, state, options, message, template) {
98
-
99
- return Errors.create(type, context, state, options, this._flags, message, template);
100
- }
101
-
102
- checkOptions(options) {
103
-
104
- Schemas = Schemas || require('../../schemas');
105
-
106
- const result = Schemas.options.validate(options);
107
-
108
- if (result.error) {
109
- throw new Error(result.error.details[0].message);
110
- }
111
- }
112
-
113
- clone() {
114
-
115
- const obj = Object.create(Object.getPrototypeOf(this));
116
-
117
- obj.isJoi = true;
118
- obj._currentJoi = this._currentJoi;
119
- obj._type = this._type;
120
- obj._settings = this._settings;
121
- obj._baseType = this._baseType;
122
- obj._valids = this._valids.slice();
123
- obj._invalids = this._invalids.slice();
124
- obj._tests = this._tests.slice();
125
- obj._refs = this._refs.slice();
126
- obj._flags = Hoek.clone(this._flags);
127
-
128
- obj._description = this._description;
129
- obj._unit = this._unit;
130
- obj._notes = this._notes.slice();
131
- obj._tags = this._tags.slice();
132
- obj._examples = this._examples.slice();
133
- obj._meta = this._meta.slice();
134
-
135
- obj._inner = {};
136
- const inners = Object.keys(this._inner);
137
- for (let i = 0; i < inners.length; ++i) {
138
- const key = inners[i];
139
- obj._inner[key] = this._inner[key] ? this._inner[key].slice() : null;
140
- }
141
-
142
- return obj;
143
- }
144
-
145
- concat(schema) {
146
-
147
- Hoek.assert(schema instanceof internals.Any, 'Invalid schema object');
148
- Hoek.assert(this._type === 'any' || schema._type === 'any' || schema._type === this._type, 'Cannot merge type', this._type, 'with another type:', schema._type);
149
-
150
- let obj = this.clone();
151
-
152
- if (this._type === 'any' && schema._type !== 'any') {
153
-
154
- // Reset values as if we were "this"
155
- const tmpObj = schema.clone();
156
- const keysToRestore = ['_settings', '_valids', '_invalids', '_tests', '_refs', '_flags', '_description', '_unit',
157
- '_notes', '_tags', '_examples', '_meta', '_inner'];
158
-
159
- for (let i = 0; i < keysToRestore.length; ++i) {
160
- tmpObj[keysToRestore[i]] = obj[keysToRestore[i]];
161
- }
162
-
163
- obj = tmpObj;
164
- }
165
-
166
- obj._settings = obj._settings ? Settings.concat(obj._settings, schema._settings) : schema._settings;
167
- obj._valids.merge(schema._valids, schema._invalids);
168
- obj._invalids.merge(schema._invalids, schema._valids);
169
- obj._tests.push(...schema._tests);
170
- obj._refs.push(...schema._refs);
171
- if (obj._flags.empty && schema._flags.empty) {
172
- obj._flags.empty = obj._flags.empty.concat(schema._flags.empty);
173
- const flags = Object.assign({}, schema._flags);
174
- delete flags.empty;
175
- Hoek.merge(obj._flags, flags);
176
- }
177
- else if (schema._flags.empty) {
178
- obj._flags.empty = schema._flags.empty;
179
- const flags = Object.assign({}, schema._flags);
180
- delete flags.empty;
181
- Hoek.merge(obj._flags, flags);
182
- }
183
- else {
184
- Hoek.merge(obj._flags, schema._flags);
185
- }
186
-
187
- obj._description = schema._description || obj._description;
188
- obj._unit = schema._unit || obj._unit;
189
- obj._notes.push(...schema._notes);
190
- obj._tags.push(...schema._tags);
191
- obj._examples.push(...schema._examples);
192
- obj._meta.push(...schema._meta);
193
-
194
- const inners = Object.keys(schema._inner);
195
- const isObject = obj._type === 'object';
196
- for (let i = 0; i < inners.length; ++i) {
197
- const key = inners[i];
198
- const source = schema._inner[key];
199
- if (source) {
200
- const target = obj._inner[key];
201
- if (target) {
202
- if (isObject && key === 'children') {
203
- const keys = {};
204
-
205
- for (let j = 0; j < target.length; ++j) {
206
- keys[target[j].key] = j;
207
- }
208
-
209
- for (let j = 0; j < source.length; ++j) {
210
- const sourceKey = source[j].key;
211
- if (keys[sourceKey] >= 0) {
212
- target[keys[sourceKey]] = {
213
- key: sourceKey,
214
- schema: target[keys[sourceKey]].schema.concat(source[j].schema)
215
- };
216
- }
217
- else {
218
- target.push(source[j]);
219
- }
220
- }
221
- }
222
- else {
223
- obj._inner[key] = obj._inner[key].concat(source);
224
- }
225
- }
226
- else {
227
- obj._inner[key] = source.slice();
228
- }
229
- }
230
- }
231
-
232
- return obj;
233
- }
234
-
235
- _test(name, arg, func, options) {
236
-
237
- const obj = this.clone();
238
- obj._tests.push({ func, name, arg, options });
239
- return obj;
240
- }
241
-
242
- _testUnique(name, arg, func, options) {
243
-
244
- const obj = this.clone();
245
- obj._tests = obj._tests.filter((test) => test.name !== name);
246
- obj._tests.push({ func, name, arg, options });
247
- return obj;
248
- }
249
-
250
- options(options) {
251
-
252
- Hoek.assert(!options.context, 'Cannot override context');
253
- this.checkOptions(options);
254
-
255
- const obj = this.clone();
256
- obj._settings = Settings.concat(obj._settings, options);
257
- return obj;
258
- }
259
-
260
- strict(isStrict) {
261
-
262
- const obj = this.clone();
263
-
264
- const convert = isStrict === undefined ? false : !isStrict;
265
- obj._settings = Settings.concat(obj._settings, { convert });
266
- return obj;
267
- }
268
-
269
- raw(isRaw) {
270
-
271
- const value = isRaw === undefined ? true : isRaw;
272
-
273
- if (this._flags.raw === value) {
274
- return this;
275
- }
276
-
277
- const obj = this.clone();
278
- obj._flags.raw = value;
279
- return obj;
280
- }
281
-
282
- error(err, options = { self: false }) {
283
-
284
- Hoek.assert(err && (err instanceof Error || typeof err === 'function'), 'Must provide a valid Error object or a function');
285
-
286
- const unknownKeys = Object.keys(options).filter((k) => !['self'].includes(k));
287
- Hoek.assert(unknownKeys.length === 0, `Options ${unknownKeys} are unknown`);
288
-
289
- const obj = this.clone();
290
- obj._flags.error = err;
291
-
292
- if (options.self) {
293
- obj._flags.selfError = true;
294
- }
295
-
296
- return obj;
297
- }
298
-
299
- allow(...values) {
300
-
301
- const obj = this.clone();
302
- values = Hoek.flatten(values);
303
- for (let i = 0; i < values.length; ++i) {
304
- const value = values[i];
305
-
306
- Hoek.assert(value !== undefined, 'Cannot call allow/valid/invalid with undefined');
307
- obj._invalids.remove(value);
308
- obj._valids.add(value, obj._refs);
309
- }
310
-
311
- return obj;
312
- }
313
-
314
- valid(...values) {
315
-
316
- const obj = this.allow(...values);
317
- obj._flags.allowOnly = true;
318
- return obj;
319
- }
320
-
321
- invalid(...values) {
322
-
323
- const obj = this.clone();
324
- values = Hoek.flatten(values);
325
- for (let i = 0; i < values.length; ++i) {
326
- const value = values[i];
327
-
328
- Hoek.assert(value !== undefined, 'Cannot call allow/valid/invalid with undefined');
329
- obj._valids.remove(value);
330
- obj._invalids.add(value, obj._refs);
331
- }
332
-
333
- return obj;
334
- }
335
-
336
- required() {
337
-
338
- if (this._flags.presence === 'required') {
339
- return this;
340
- }
341
-
342
- const obj = this.clone();
343
- obj._flags.presence = 'required';
344
- return obj;
345
- }
346
-
347
- optional() {
348
-
349
- if (this._flags.presence === 'optional') {
350
- return this;
351
- }
352
-
353
- const obj = this.clone();
354
- obj._flags.presence = 'optional';
355
- return obj;
356
- }
357
-
358
-
359
- forbidden() {
360
-
361
- if (this._flags.presence === 'forbidden') {
362
- return this;
363
- }
364
-
365
- const obj = this.clone();
366
- obj._flags.presence = 'forbidden';
367
- return obj;
368
- }
369
-
370
-
371
- strip() {
372
-
373
- if (this._flags.strip) {
374
- return this;
375
- }
376
-
377
- const obj = this.clone();
378
- obj._flags.strip = true;
379
- return obj;
380
- }
381
-
382
- applyFunctionToChildren(children, fn, args = [], root) {
383
-
384
- children = [].concat(children);
385
-
386
- if (children.length !== 1 || children[0] !== '') {
387
- root = root ? (root + '.') : '';
388
-
389
- const extraChildren = (children[0] === '' ? children.slice(1) : children).map((child) => {
390
-
391
- return root + child;
392
- });
393
-
394
- throw new Error('unknown key(s) ' + extraChildren.join(', '));
395
- }
396
-
397
- return this[fn](...args);
398
- }
399
-
400
- default(value, description) {
401
-
402
- if (typeof value === 'function' &&
403
- !Ref.isRef(value)) {
404
-
405
- if (!value.description &&
406
- description) {
407
-
408
- value.description = description;
409
- }
410
-
411
- if (!this._flags.func) {
412
- Hoek.assert(typeof value.description === 'string' && value.description.length > 0, 'description must be provided when default value is a function');
413
- }
414
- }
415
-
416
- const obj = this.clone();
417
- obj._flags.default = value;
418
- Ref.push(obj._refs, value);
419
- return obj;
420
- }
421
-
422
- empty(schema) {
423
-
424
- const obj = this.clone();
425
- if (schema === undefined) {
426
- delete obj._flags.empty;
427
- }
428
- else {
429
- obj._flags.empty = Cast.schema(this._currentJoi, schema);
430
- }
431
-
432
- return obj;
433
- }
434
-
435
- when(condition, options) {
436
-
437
- Hoek.assert(options && typeof options === 'object', 'Invalid options');
438
- Hoek.assert(options.then !== undefined || options.otherwise !== undefined, 'options must have at least one of "then" or "otherwise"');
439
-
440
- const then = options.hasOwnProperty('then') ? this.concat(Cast.schema(this._currentJoi, options.then)) : undefined;
441
- const otherwise = options.hasOwnProperty('otherwise') ? this.concat(Cast.schema(this._currentJoi, options.otherwise)) : undefined;
442
-
443
- Alternatives = Alternatives || require('../alternatives');
444
-
445
- const alternativeOptions = { then, otherwise };
446
- if (Object.prototype.hasOwnProperty.call(options, 'is')) {
447
- alternativeOptions.is = options.is;
448
- }
449
-
450
- const obj = Alternatives.when(condition, alternativeOptions);
451
- obj._flags.presence = 'ignore';
452
- obj._baseType = this;
453
-
454
- return obj;
455
- }
456
-
457
- description(desc) {
458
-
459
- Hoek.assert(desc && typeof desc === 'string', 'Description must be a non-empty string');
460
-
461
- const obj = this.clone();
462
- obj._description = desc;
463
- return obj;
464
- }
465
-
466
- notes(notes) {
467
-
468
- Hoek.assert(notes && (typeof notes === 'string' || Array.isArray(notes)), 'Notes must be a non-empty string or array');
469
-
470
- const obj = this.clone();
471
- obj._notes = obj._notes.concat(notes);
472
- return obj;
473
- }
474
-
475
- tags(tags) {
476
-
477
- Hoek.assert(tags && (typeof tags === 'string' || Array.isArray(tags)), 'Tags must be a non-empty string or array');
478
-
479
- const obj = this.clone();
480
- obj._tags = obj._tags.concat(tags);
481
- return obj;
482
- }
483
-
484
- meta(meta) {
485
-
486
- Hoek.assert(meta !== undefined, 'Meta cannot be undefined');
487
-
488
- const obj = this.clone();
489
- obj._meta = obj._meta.concat(meta);
490
- return obj;
491
- }
492
-
493
- example(...examples) {
494
-
495
- Hoek.assert(examples.length > 0, 'Missing examples');
496
-
497
- const processed = [];
498
- for (let i = 0; i < examples.length; ++i) {
499
- const example = [].concat(examples[i]);
500
- Hoek.assert(example.length <= 2, `Bad example format at index ${i}`);
501
-
502
- const value = example[0];
503
- let options = example[1];
504
- if (options !== undefined) {
505
- Hoek.assert(options && typeof options === 'object', `Options for example at index ${i} must be an object`);
506
- const unknownOptions = Object.keys(options).filter((option) => !['parent', 'context'].includes(option));
507
- Hoek.assert(unknownOptions.length === 0, `Unknown example options ${unknownOptions} at index ${i}`);
508
- }
509
- else {
510
- options = {};
511
- }
512
-
513
- const localState = new State('', [], options.parent || null);
514
- const result = this._validate(value, localState, Settings.concat(internals.defaults, options.context ? { context: options.context } : null));
515
- Hoek.assert(!result.errors, `Bad example at index ${i}:`, result.errors && Errors.process(result.errors, value));
516
-
517
- const ex = { value };
518
- if (Object.keys(options).length) {
519
- ex.options = options;
520
- }
521
-
522
- processed.push(ex);
523
- }
524
-
525
- const obj = this.clone();
526
- obj._examples = processed;
527
- return obj;
528
- }
529
-
530
- unit(name) {
531
-
532
- Hoek.assert(name && typeof name === 'string', 'Unit name must be a non-empty string');
533
-
534
- const obj = this.clone();
535
- obj._unit = name;
536
- return obj;
537
- }
538
-
539
- _prepareEmptyValue(value) {
540
-
541
- if (typeof value === 'string' && this._flags.trim) {
542
- return value.trim();
543
- }
544
-
545
- return value;
546
- }
547
-
548
- _validate(value, state, options, reference) {
549
-
550
- const originalValue = value;
551
-
552
- // Setup state and settings
553
-
554
- state = state || new State('', [], null, reference);
555
-
556
- if (this._settings) {
557
- const isDefaultOptions = options === internals.defaults;
558
- if (isDefaultOptions && this._settings[Symbols.settingsCache]) {
559
- options = this._settings[Symbols.settingsCache];
560
- }
561
- else {
562
- options = Settings.concat(options, this._settings);
563
- if (isDefaultOptions) {
564
- this._settings[Symbols.settingsCache] = options;
565
- }
566
- }
567
- }
568
-
569
- let errors = [];
570
-
571
- if (this._coerce) {
572
- const coerced = this._coerce(value, state, options);
573
- if (coerced.errors) {
574
- value = coerced.value;
575
- errors = errors.concat(coerced.errors);
576
- return this._finalizeValue(value, originalValue, errors, state, options); // Coerced error always aborts early
577
- }
578
-
579
- value = coerced.value;
580
- }
581
-
582
- if (this._flags.empty && !this._flags.empty._validate(this._prepareEmptyValue(value), null, internals.defaults).errors) {
583
- value = undefined;
584
- }
585
-
586
- // Check presence requirements
587
-
588
- const presence = this._flags.presence || options.presence;
589
- if (presence === 'optional') {
590
- if (value === undefined) {
591
- const isDeepDefault = this._flags.hasOwnProperty('default') && this._flags.default === undefined;
592
- if (isDeepDefault && this._type === 'object') {
593
- value = {};
594
- }
595
- else {
596
- return this._finalizeValue(value, originalValue, errors, state, options);
597
- }
598
- }
599
- }
600
- else if (presence === 'required' &&
601
- value === undefined) {
602
-
603
- errors.push(this.createError('any.required', null, state, options));
604
- return this._finalizeValue(value, originalValue, errors, state, options);
605
- }
606
- else if (presence === 'forbidden') {
607
- if (value === undefined) {
608
- return this._finalizeValue(value, originalValue, errors, state, options);
609
- }
610
-
611
- errors.push(this.createError('any.unknown', null, state, options));
612
- return this._finalizeValue(value, originalValue, errors, state, options);
613
- }
614
-
615
- // Check allowed and denied values using the original value
616
-
617
- let match = this._valids.get(value, state, options, this._flags.insensitive);
618
- if (match) {
619
- if (options.convert) {
620
- value = match.value;
621
- }
622
-
623
- return this._finalizeValue(value, originalValue, errors, state, options);
624
- }
625
-
626
- if (this._invalids.has(value, state, options, this._flags.insensitive)) {
627
- errors.push(this.createError(value === '' ? 'any.empty' : 'any.invalid', { value, invalids: this._invalids.values({ stripUndefined: true }) }, state, options));
628
- if (options.abortEarly) {
629
-
630
- return this._finalizeValue(value, originalValue, errors, state, options);
631
- }
632
- }
633
-
634
- // Convert value and validate type
635
-
636
- if (this._base) {
637
- const base = this._base(value, state, options);
638
- if (base.errors) {
639
- value = base.value;
640
- errors = errors.concat(base.errors);
641
- return this._finalizeValue(value, originalValue, errors, state, options); // Base error always aborts early
642
- }
643
-
644
- if (base.value !== value) {
645
- value = base.value;
646
-
647
- // Check allowed and denied values using the converted value
648
-
649
- match = this._valids.get(value, state, options, this._flags.insensitive);
650
- if (match) {
651
- value = match.value;
652
- return this._finalizeValue(value, originalValue, errors, state, options);
653
- }
654
-
655
- if (this._invalids.has(value, state, options, this._flags.insensitive)) {
656
- errors.push(this.createError(value === '' ? 'any.empty' : 'any.invalid', { value, invalids: this._invalids.values({ stripUndefined: true }) }, state, options));
657
- if (options.abortEarly) {
658
- return this._finalizeValue(value, originalValue, errors, state, options);
659
- }
660
- }
661
- }
662
- }
663
-
664
- // Required values did not match
665
-
666
- if (this._flags.allowOnly) {
667
- errors.push(this.createError('any.allowOnly', { value, valids: this._valids.values({ stripUndefined: true }) }, state, options));
668
- if (options.abortEarly) {
669
- return this._finalizeValue(value, originalValue, errors, state, options);
670
- }
671
- }
672
-
673
- // Validate tests
674
-
675
- for (let i = 0; i < this._tests.length; ++i) {
676
- const test = this._tests[i];
677
- const ret = test.func.call(this, value, state, options);
678
- if (ret instanceof Errors.Err) {
679
- errors.push(ret);
680
- if (options.abortEarly) {
681
- return this._finalizeValue(value, originalValue, errors, state, options);
682
- }
683
- }
684
- else {
685
- value = ret;
686
- }
687
- }
688
-
689
- return this._finalizeValue(value, originalValue, errors, state, options);
690
- }
691
-
692
- _finalizeValue(value, originalValue, errors, state, options) {
693
-
694
- let finalValue;
695
-
696
- if (value !== undefined) {
697
- finalValue = this._flags.raw ? originalValue : value;
698
- }
699
- else if (options.noDefaults) {
700
- finalValue = value;
701
- }
702
- else if (Ref.isRef(this._flags.default)) {
703
- finalValue = this._flags.default(state.parent, options);
704
- }
705
- else if (typeof this._flags.default === 'function' &&
706
- !(this._flags.func && !this._flags.default.description)) {
707
-
708
- let args;
709
-
710
- if (state.parent !== null &&
711
- this._flags.default.length > 0) {
712
-
713
- args = [Hoek.clone(state.parent), options];
714
- }
715
-
716
- const defaultValue = internals._try(this._flags.default, args);
717
- finalValue = defaultValue.value;
718
- if (defaultValue.error) {
719
- errors.push(this.createError('any.default', { error: defaultValue.error }, state, options));
720
- }
721
- }
722
- else {
723
- finalValue = Hoek.clone(this._flags.default);
724
- }
725
-
726
- if (errors.length &&
727
- typeof this._flags.error === 'function' &&
728
- (
729
- !this._flags.selfError ||
730
- errors.some((e) => state.path.length === e.path.length)
731
- )
732
- ) {
733
- const change = this._flags.error.call(this, errors);
734
-
735
- if (typeof change === 'string') {
736
- errors = [this.createOverrideError('override', { reason: errors }, state, options, change)];
737
- }
738
- else {
739
- errors = [].concat(change)
740
- .map((err) => {
741
-
742
- return err instanceof Error ?
743
- err :
744
- this.createOverrideError(err.type || 'override', err.context, state, options, err.message, err.template);
745
- });
746
- }
747
- }
748
-
749
- return {
750
- value: this._flags.strip ? undefined : finalValue,
751
- finalValue,
752
- errors: errors.length ? errors : null
753
- };
754
- }
755
-
756
- _validateWithOptions(value, options, callback) {
757
-
758
- if (options) {
759
- this.checkOptions(options);
760
- }
761
-
762
- const settings = Settings.concat(internals.defaults, options);
763
- const result = this._validate(value, null, settings);
764
- const errors = Errors.process(result.errors, value);
765
-
766
- if (callback) {
767
- return callback(errors, result.value);
768
- }
769
-
770
- return {
771
- error: errors,
772
- value: result.value,
773
- then(resolve, reject) {
774
-
775
- if (errors) {
776
- return Promise.reject(errors).catch(reject);
777
- }
778
-
779
- return Promise.resolve(result.value).then(resolve);
780
- },
781
- catch(reject) {
782
-
783
- if (errors) {
784
- return Promise.reject(errors).catch(reject);
785
- }
786
-
787
- return Promise.resolve(result.value);
788
- }
789
- };
790
- }
791
-
792
- validate(value, options, callback) {
793
-
794
- if (typeof options === 'function') {
795
- return this._validateWithOptions(value, null, options);
796
- }
797
-
798
- return this._validateWithOptions(value, options, callback);
799
- }
800
-
801
- describe() {
802
-
803
- const description = {
804
- type: this._type
805
- };
806
-
807
- const flags = Object.keys(this._flags);
808
- if (flags.length) {
809
- if (['empty', 'default', 'lazy', 'label'].some((flag) => this._flags.hasOwnProperty(flag))) {
810
- description.flags = {};
811
- for (let i = 0; i < flags.length; ++i) {
812
- const flag = flags[i];
813
- if (flag === 'empty') {
814
- description.flags[flag] = this._flags[flag].describe();
815
- }
816
- else if (flag === 'default') {
817
- if (Ref.isRef(this._flags[flag])) {
818
- description.flags[flag] = this._flags[flag].toString();
819
- }
820
- else if (typeof this._flags[flag] === 'function') {
821
- description.flags[flag] = {
822
- description: this._flags[flag].description,
823
- function : this._flags[flag]
824
- };
825
- }
826
- else {
827
- description.flags[flag] = this._flags[flag];
828
- }
829
- }
830
- else if (flag === 'lazy' || flag === 'label') {
831
- // We don't want it in the description
832
- }
833
- else {
834
- description.flags[flag] = this._flags[flag];
835
- }
836
- }
837
- }
838
- else {
839
- description.flags = this._flags;
840
- }
841
- }
842
-
843
- if (this._settings) {
844
- description.options = Hoek.clone(this._settings);
845
- }
846
-
847
- if (this._baseType) {
848
- description.base = this._baseType.describe();
849
- }
850
-
851
- if (this._description) {
852
- description.description = this._description;
853
- }
854
-
855
- if (this._notes.length) {
856
- description.notes = this._notes;
857
- }
858
-
859
- if (this._tags.length) {
860
- description.tags = this._tags;
861
- }
862
-
863
- if (this._meta.length) {
864
- description.meta = this._meta;
865
- }
866
-
867
- if (this._examples.length) {
868
- description.examples = this._examples;
869
- }
870
-
871
- if (this._unit) {
872
- description.unit = this._unit;
873
- }
874
-
875
- const valids = this._valids.values();
876
- if (valids.length) {
877
- description.valids = valids.map((v) => {
878
-
879
- return Ref.isRef(v) ? v.toString() : v;
880
- });
881
- }
882
-
883
- const invalids = this._invalids.values();
884
- if (invalids.length) {
885
- description.invalids = invalids.map((v) => {
886
-
887
- return Ref.isRef(v) ? v.toString() : v;
888
- });
889
- }
890
-
891
- description.rules = [];
892
-
893
- for (let i = 0; i < this._tests.length; ++i) {
894
- const validator = this._tests[i];
895
- const item = { name: validator.name };
896
-
897
- if (validator.arg !== void 0) {
898
- item.arg = Ref.isRef(validator.arg) ? validator.arg.toString() : validator.arg;
899
- }
900
-
901
- const options = validator.options;
902
- if (options) {
903
- if (options.hasRef) {
904
- item.arg = {};
905
- const keys = Object.keys(validator.arg);
906
- for (let j = 0; j < keys.length; ++j) {
907
- const key = keys[j];
908
- const value = validator.arg[key];
909
- item.arg[key] = Ref.isRef(value) ? value.toString() : value;
910
- }
911
- }
912
-
913
- if (typeof options.description === 'string') {
914
- item.description = options.description;
915
- }
916
- else if (typeof options.description === 'function') {
917
- item.description = options.description(item.arg);
918
- }
919
- }
920
-
921
- description.rules.push(item);
922
- }
923
-
924
- if (!description.rules.length) {
925
- delete description.rules;
926
- }
927
-
928
- const label = this._getLabel();
929
- if (label) {
930
- description.label = label;
931
- }
932
-
933
- return description;
934
- }
935
-
936
- label(name) {
937
-
938
- Hoek.assert(name && typeof name === 'string', 'Label name must be a non-empty string');
939
-
940
- const obj = this.clone();
941
- obj._flags.label = name;
942
- return obj;
943
- }
944
-
945
- _getLabel(def) {
946
-
947
- return this._flags.label || def;
948
- }
949
-
950
- };
951
-
952
-
953
- internals.Any.prototype.isImmutable = true; // Prevents Hoek from deep cloning schema objects
954
-
955
- // Aliases
956
-
957
- internals.Any.prototype.only = internals.Any.prototype.equal = internals.Any.prototype.valid;
958
- internals.Any.prototype.disallow = internals.Any.prototype.not = internals.Any.prototype.invalid;
959
- internals.Any.prototype.exist = internals.Any.prototype.required;
960
-
961
-
962
- internals._try = function (fn, args = []) {
963
-
964
- let err;
965
- let result;
966
-
967
- try {
968
- result = fn(...args);
969
- }
970
- catch (e) {
971
- err = e;
972
- }
973
-
974
- return {
975
- value: result,
976
- error: err
977
- };
978
- };