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.
- package/LICENSE.md +10 -0
- package/README.md +9 -118
- package/dist/joi-browser.min.js +1 -0
- package/lib/annotate.js +175 -0
- package/lib/base.js +1068 -0
- package/lib/cache.js +143 -0
- package/lib/common.js +216 -0
- package/lib/compile.js +283 -0
- package/lib/errors.js +160 -269
- package/lib/extend.js +312 -0
- package/lib/index.d.ts +2200 -0
- package/lib/index.js +179 -347
- package/lib/manifest.js +476 -0
- package/lib/messages.js +178 -0
- package/lib/modify.js +267 -0
- package/lib/ref.js +386 -25
- package/lib/schemas.js +291 -15
- package/lib/state.js +152 -0
- package/lib/template.js +427 -0
- package/lib/trace.js +346 -0
- package/lib/types/alternatives.js +329 -0
- package/lib/types/any.js +174 -0
- package/lib/types/array.js +775 -0
- package/lib/types/binary.js +98 -0
- package/lib/types/boolean.js +150 -0
- package/lib/types/date.js +233 -0
- package/lib/types/function.js +93 -0
- package/lib/types/keys.js +1043 -0
- package/lib/types/link.js +168 -0
- package/lib/types/number.js +335 -0
- package/lib/types/object.js +22 -0
- package/lib/types/string.js +820 -0
- package/lib/types/symbol.js +102 -0
- package/lib/validator.js +650 -0
- package/lib/values.js +263 -0
- package/package.json +34 -29
- package/CHANGELOG.md +0 -3
- package/LICENSE +0 -25
- package/lib/cast.js +0 -64
- package/lib/language.js +0 -166
- package/lib/set.js +0 -191
- package/lib/types/alternatives/index.js +0 -218
- package/lib/types/any/index.js +0 -978
- package/lib/types/any/settings.js +0 -36
- package/lib/types/array/index.js +0 -707
- package/lib/types/binary/index.js +0 -100
- package/lib/types/boolean/index.js +0 -100
- package/lib/types/date/index.js +0 -182
- package/lib/types/func/index.js +0 -90
- package/lib/types/lazy/index.js +0 -82
- package/lib/types/number/index.js +0 -248
- package/lib/types/object/index.js +0 -957
- package/lib/types/state.js +0 -11
- package/lib/types/string/index.js +0 -703
- package/lib/types/string/ip.js +0 -54
- package/lib/types/string/rfc3986.js +0 -219
- package/lib/types/string/uri.js +0 -46
- package/lib/types/symbol/index.js +0 -93
- package/lib/types/symbols.js +0 -5
package/lib/types/any/index.js
DELETED
|
@@ -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
|
-
};
|