joi 10.5.2 → 10.6.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/README.md +1 -1
- package/lib/index.js +5 -1
- package/lib/language.js +1 -0
- package/lib/types/array/index.js +49 -6
- package/lib/types/string/index.js +41 -40
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -125,7 +125,7 @@ When validating a schema:
|
|
|
125
125
|
* Rules are defined in an additive fashion and evaluated in order after whitelist and blacklist checks.
|
|
126
126
|
|
|
127
127
|
# API
|
|
128
|
-
See the [API Reference](https://github.com/hapijs/joi/blob/v10.
|
|
128
|
+
See the [API Reference](https://github.com/hapijs/joi/blob/v10.6.0/API.md).
|
|
129
129
|
|
|
130
130
|
# Browsers
|
|
131
131
|
|
package/lib/index.js
CHANGED
|
@@ -330,7 +330,11 @@ internals.root = function () {
|
|
|
330
330
|
}
|
|
331
331
|
|
|
332
332
|
if (rule.setup) {
|
|
333
|
-
rule.setup.call(schema, arg);
|
|
333
|
+
const newSchema = rule.setup.call(schema, arg);
|
|
334
|
+
if (newSchema !== undefined) {
|
|
335
|
+
Hoek.assert(newSchema instanceof Any, `Setup of extension Joi.${this._type}().${rule.name}() must return undefined or a Joi object`);
|
|
336
|
+
schema = newSchema;
|
|
337
|
+
}
|
|
334
338
|
}
|
|
335
339
|
|
|
336
340
|
return schema;
|
package/lib/language.js
CHANGED
|
@@ -42,6 +42,7 @@ exports.errors = {
|
|
|
42
42
|
length: 'must contain {{limit}} items',
|
|
43
43
|
ordered: 'at position {{pos}} fails because {{reason}}',
|
|
44
44
|
orderedLength: 'at position {{pos}} fails because array must contain at most {{limit}} items',
|
|
45
|
+
ref: 'references "{{ref}}" which is not a positive integer',
|
|
45
46
|
sparse: 'must not be a sparse array',
|
|
46
47
|
unique: 'position {{pos}} contains a duplicate value'
|
|
47
48
|
},
|
package/lib/types/array/index.js
CHANGED
|
@@ -4,6 +4,7 @@
|
|
|
4
4
|
|
|
5
5
|
const Any = require('../any');
|
|
6
6
|
const Cast = require('../../cast');
|
|
7
|
+
const Ref = require('../../ref');
|
|
7
8
|
const Hoek = require('hoek');
|
|
8
9
|
|
|
9
10
|
|
|
@@ -390,11 +391,25 @@ internals.Array = class extends Any {
|
|
|
390
391
|
|
|
391
392
|
min(limit) {
|
|
392
393
|
|
|
393
|
-
|
|
394
|
+
const isRef = Ref.isRef(limit);
|
|
395
|
+
|
|
396
|
+
Hoek.assert((Number.isSafeInteger(limit) && limit >= 0) || isRef, 'limit must be a positive integer or reference');
|
|
394
397
|
|
|
395
398
|
return this._test('min', limit, function (value, state, options) {
|
|
396
399
|
|
|
397
|
-
|
|
400
|
+
let compareTo;
|
|
401
|
+
if (isRef) {
|
|
402
|
+
compareTo = limit(state.reference || state.parent, options);
|
|
403
|
+
|
|
404
|
+
if (!(Number.isSafeInteger(compareTo) && compareTo >= 0)) {
|
|
405
|
+
return this.createError('array.ref', { ref: limit.key }, state, options);
|
|
406
|
+
}
|
|
407
|
+
}
|
|
408
|
+
else {
|
|
409
|
+
compareTo = limit;
|
|
410
|
+
}
|
|
411
|
+
|
|
412
|
+
if (value.length >= compareTo) {
|
|
398
413
|
return value;
|
|
399
414
|
}
|
|
400
415
|
|
|
@@ -404,11 +419,25 @@ internals.Array = class extends Any {
|
|
|
404
419
|
|
|
405
420
|
max(limit) {
|
|
406
421
|
|
|
407
|
-
|
|
422
|
+
const isRef = Ref.isRef(limit);
|
|
423
|
+
|
|
424
|
+
Hoek.assert((Number.isSafeInteger(limit) && limit >= 0) || isRef, 'limit must be a positive integer or reference');
|
|
408
425
|
|
|
409
426
|
return this._test('max', limit, function (value, state, options) {
|
|
410
427
|
|
|
411
|
-
|
|
428
|
+
let compareTo;
|
|
429
|
+
if (isRef) {
|
|
430
|
+
compareTo = limit(state.reference || state.parent, options);
|
|
431
|
+
|
|
432
|
+
if (!(Number.isSafeInteger(compareTo) && compareTo >= 0)) {
|
|
433
|
+
return this.createError('array.ref', { ref: limit.key }, state, options);
|
|
434
|
+
}
|
|
435
|
+
}
|
|
436
|
+
else {
|
|
437
|
+
compareTo = limit;
|
|
438
|
+
}
|
|
439
|
+
|
|
440
|
+
if (value.length <= compareTo) {
|
|
412
441
|
return value;
|
|
413
442
|
}
|
|
414
443
|
|
|
@@ -418,11 +447,25 @@ internals.Array = class extends Any {
|
|
|
418
447
|
|
|
419
448
|
length(limit) {
|
|
420
449
|
|
|
421
|
-
|
|
450
|
+
const isRef = Ref.isRef(limit);
|
|
451
|
+
|
|
452
|
+
Hoek.assert((Number.isSafeInteger(limit) && limit >= 0) || isRef, 'limit must be a positive integer or reference');
|
|
422
453
|
|
|
423
454
|
return this._test('length', limit, function (value, state, options) {
|
|
424
455
|
|
|
425
|
-
|
|
456
|
+
let compareTo;
|
|
457
|
+
if (isRef) {
|
|
458
|
+
compareTo = limit(state.reference || state.parent, options);
|
|
459
|
+
|
|
460
|
+
if (!(Number.isSafeInteger(compareTo) && compareTo >= 0)) {
|
|
461
|
+
return this.createError('array.ref', { ref: limit.key }, state, options);
|
|
462
|
+
}
|
|
463
|
+
}
|
|
464
|
+
else {
|
|
465
|
+
compareTo = limit;
|
|
466
|
+
}
|
|
467
|
+
|
|
468
|
+
if (value.length === compareTo) {
|
|
426
469
|
return value;
|
|
427
470
|
}
|
|
428
471
|
|
|
@@ -15,7 +15,17 @@ const Ip = require('./ip');
|
|
|
15
15
|
|
|
16
16
|
const internals = {
|
|
17
17
|
uriRegex: Uri.createUriRegex(),
|
|
18
|
-
ipRegex: Ip.createIpRegex(['ipv4', 'ipv6', 'ipvfuture'], 'optional')
|
|
18
|
+
ipRegex: Ip.createIpRegex(['ipv4', 'ipv6', 'ipvfuture'], 'optional'),
|
|
19
|
+
guidBrackets: {
|
|
20
|
+
'{': '}', '[': ']', '(': ')', '': ''
|
|
21
|
+
},
|
|
22
|
+
guidVersions: {
|
|
23
|
+
uuidv1: '1',
|
|
24
|
+
uuidv2: '2',
|
|
25
|
+
uuidv3: '3',
|
|
26
|
+
uuidv4: '4',
|
|
27
|
+
uuidv5: '5'
|
|
28
|
+
}
|
|
19
29
|
};
|
|
20
30
|
|
|
21
31
|
internals.String = class extends Any {
|
|
@@ -326,19 +336,7 @@ internals.String = class extends Any {
|
|
|
326
336
|
|
|
327
337
|
guid(guidOptions) {
|
|
328
338
|
|
|
329
|
-
|
|
330
|
-
'{': '}', '[': ']', '(': ')', '': ''
|
|
331
|
-
};
|
|
332
|
-
|
|
333
|
-
const uuids = {
|
|
334
|
-
'uuidv1': '1',
|
|
335
|
-
'uuidv2': '2',
|
|
336
|
-
'uuidv3': '3',
|
|
337
|
-
'uuidv4': '4',
|
|
338
|
-
'uuidv5': '5'
|
|
339
|
-
};
|
|
340
|
-
|
|
341
|
-
const versions = [];
|
|
339
|
+
let versionNumbers = '';
|
|
342
340
|
|
|
343
341
|
if (guidOptions && guidOptions.version) {
|
|
344
342
|
if (!Array.isArray(guidOptions.version)) {
|
|
@@ -346,50 +344,36 @@ internals.String = class extends Any {
|
|
|
346
344
|
}
|
|
347
345
|
|
|
348
346
|
Hoek.assert(guidOptions.version.length >= 1, 'version must have at least 1 valid version specified');
|
|
347
|
+
const versions = new Set();
|
|
349
348
|
|
|
350
349
|
for (let i = 0; i < guidOptions.version.length; ++i) {
|
|
351
350
|
let version = guidOptions.version[i];
|
|
352
351
|
Hoek.assert(typeof version === 'string', 'version at position ' + i + ' must be a string');
|
|
353
352
|
version = version.toLowerCase();
|
|
354
|
-
|
|
355
|
-
Hoek.assert(
|
|
356
|
-
versions.
|
|
353
|
+
const versionNumber = internals.guidVersions[version];
|
|
354
|
+
Hoek.assert(versionNumber, 'version at position ' + i + ' must be one of ' + Object.keys(internals.guidVersions).join(', '));
|
|
355
|
+
Hoek.assert(!(versions.has(versionNumber)), 'version at position ' + i + ' must not be a duplicate.');
|
|
356
|
+
|
|
357
|
+
versionNumbers += versionNumber;
|
|
358
|
+
versions.add(versionNumber);
|
|
357
359
|
}
|
|
358
360
|
}
|
|
359
361
|
|
|
360
|
-
const
|
|
362
|
+
const guidRegex = new RegExp(`^([\\[{\\(]?)[0-9A-F]{8}([:-]?)[0-9A-F]{4}\\2?[${versionNumbers || '0-9A-F'}][0-9A-F]{3}\\2?[${versionNumbers ? '89AB' : '0-9A-F'}][0-9A-F]{3}\\2?[0-9A-F]{12}([\\]}\\)]?)$`, 'i');
|
|
361
363
|
|
|
362
364
|
return this._test('guid', guidOptions, function (value, state, options) {
|
|
363
365
|
|
|
364
|
-
const results =
|
|
366
|
+
const results = guidRegex.exec(value);
|
|
365
367
|
|
|
366
368
|
if (!results) {
|
|
367
369
|
return this.createError('string.guid', { value }, state, options);
|
|
368
370
|
}
|
|
369
371
|
|
|
370
372
|
// Matching braces
|
|
371
|
-
if (
|
|
372
|
-
return this.createError('string.guid', { value }, state, options);
|
|
373
|
-
}
|
|
374
|
-
|
|
375
|
-
// Matching separators
|
|
376
|
-
if (results[3] !== results[5] || results[3] !== results[7] || results[3] !== results[9]) {
|
|
373
|
+
if (internals.guidBrackets[results[1]] !== results[results.length - 1]) {
|
|
377
374
|
return this.createError('string.guid', { value }, state, options);
|
|
378
375
|
}
|
|
379
376
|
|
|
380
|
-
// Specific UUID versions
|
|
381
|
-
if (versions.length) {
|
|
382
|
-
const validVersions = versions.some((uuidVersion) => {
|
|
383
|
-
|
|
384
|
-
return results[6][0] === uuids[uuidVersion];
|
|
385
|
-
});
|
|
386
|
-
|
|
387
|
-
// Valid version and 89AB check
|
|
388
|
-
if (!(validVersions && /[89AB]/i.test(results[8][0]))) {
|
|
389
|
-
return this.createError('string.guid', { value }, state, options);
|
|
390
|
-
}
|
|
391
|
-
}
|
|
392
|
-
|
|
393
377
|
return value;
|
|
394
378
|
});
|
|
395
379
|
}
|
|
@@ -408,9 +392,26 @@ internals.String = class extends Any {
|
|
|
408
392
|
});
|
|
409
393
|
}
|
|
410
394
|
|
|
411
|
-
base64() {
|
|
395
|
+
base64(base64Options) {
|
|
396
|
+
|
|
397
|
+
base64Options = base64Options || {};
|
|
398
|
+
|
|
399
|
+
// Validation.
|
|
400
|
+
Hoek.assert(typeof base64Options === 'object', 'base64 options must be an object');
|
|
401
|
+
Hoek.assert(typeof base64Options.paddingRequired === 'undefined' || typeof base64Options.paddingRequired === 'boolean',
|
|
402
|
+
'paddingRequired must be boolean');
|
|
403
|
+
|
|
404
|
+
// Determine if padding is required.
|
|
405
|
+
const paddingRequired = base64Options.paddingRequired === false ?
|
|
406
|
+
base64Options.paddingRequired
|
|
407
|
+
: base64Options.paddingRequired || true;
|
|
412
408
|
|
|
413
|
-
|
|
409
|
+
// Set validation based on preference.
|
|
410
|
+
const regex = paddingRequired ?
|
|
411
|
+
// Padding is required.
|
|
412
|
+
/^(?:[A-Za-z0-9+\/]{4})*(?:[A-Za-z0-9+\/]{2}==|[A-Za-z0-9+\/]{3}=)?$/
|
|
413
|
+
// Padding is optional.
|
|
414
|
+
: /^(?:[A-Za-z0-9+\/]{4})*(?:[A-Za-z0-9+\/]{2}(==)?|[A-Za-z0-9+\/]{3}=?)?$/;
|
|
414
415
|
|
|
415
416
|
return this._test('base64', regex, function (value, state, options) {
|
|
416
417
|
|