Skip to content

Commit dec12ec

Browse files
ben-waltersMarsup
authored andcommitted
Added wrapper option to uuid function
1 parent 703c12c commit dec12ec

File tree

3 files changed

+120
-15
lines changed

3 files changed

+120
-15
lines changed

API.md

Lines changed: 19 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -2801,24 +2801,32 @@ Possible validation errors: [`string.email`](#stringemail)
28012801

28022802
Requires the string value to be a valid GUID.
28032803

2804-
- `options` - optional settings:
2805-
- `version` - specifies one or more acceptable versions. Can be an Array or String with the following values:
2806-
`uuidv1`, `uuidv2`, `uuidv3`, `uuidv4`, `uuidv5`, `uuidv6`, `uuidv7` or `uuidv8`. If no `version` is specified then it is assumed to be a generic `guid`
2807-
which will not validate the version or variant of the guid and just check for general structure format.
2808-
- `separator` - defines the allowed or required GUID separator where:
2809-
- `true` - a separator is required, can be either `:` or `-`.
2810-
- `false` - separator is not allowed.
2811-
- `'-'` - a dash separator is required.
2812-
- `':'` - a colon separator is required.
2813-
- defaults to optional `:` or `-` separator.
2804+
- `options` - optional settings:
2805+
- `version` - specifies one or more acceptable versions. Can be an Array or String with the following values:
2806+
`uuidv1`, `uuidv2`, `uuidv3`, `uuidv4`, `uuidv5`. If no `version` is specified then it is assumed to be a generic `guid`
2807+
which will not validate the version or variant of the guid and just check for general structure format.
2808+
- `separator` - defines the allowed or required GUID separator where:
2809+
- `true` - a separator is required, can be either `:` or `-`.
2810+
- `false` - separator is not allowed.
2811+
- `'-'` - a dash separator is required.
2812+
- `':'` - a colon separator is required.
2813+
- defaults to optional `:` or `-` separator.
2814+
- `wrapper` - defines the allowed or required GUID wrapper characters where:
2815+
- `undefined` - (default) the GUID can be optionally wrapped with `{}`, `[]`, or `()`. The opening and closing characters must be a matching pair.
2816+
- `true` - the GUID must be wrapped with `{}`, `[]`, or `()`. The opening and closing characters must be a matching pair.
2817+
- `false` - wrapper characters are not allowed.
2818+
- `'['`, `'{'`, or `'('` - a specific wrapper is required (e.g., if `wrapper` is `'['`, the GUID must be enclosed in square brackets).
2819+
28142820

28152821
```js
28162822
const schema = Joi.string().guid({
28172823
version: [
28182824
'uuidv4',
28192825
'uuidv5'
2820-
]
2826+
],
2827+
wrapper: false
28212828
});
2829+
28222830
```
28232831

28242832
Possible validation errors: [`string.guid`](#stringguid)

lib/types/string.js

Lines changed: 49 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -316,7 +316,23 @@ module.exports = Any.extend({
316316
alias: 'uuid',
317317
method(options = {}) {
318318

319-
Common.assertOptions(options, ['version', 'separator']);
319+
Common.assertOptions(options, ['version', 'separator', 'wrapper']);
320+
321+
if (
322+
options.wrapper !== undefined &&
323+
options.wrapper !== true &&
324+
options.wrapper !== false
325+
) {
326+
const validWrappers = Object.keys(internals.guidBrackets).filter(
327+
(key) => !!key
328+
);
329+
assert(
330+
validWrappers.includes(options.wrapper),
331+
`"wrapper" must be true, false, or one of ${validWrappers.join(
332+
', '
333+
)}`
334+
);
335+
}
320336

321337
let versionNumbers = '';
322338

@@ -343,10 +359,38 @@ module.exports = Any.extend({
343359
options.separator === true ? '[:-]' :
344360
options.separator === false ? '[]?' : `\\${options.separator}`;
345361

346-
const regex = new RegExp(`^([\\[{\\(]?)[0-9A-F]{8}(${separator})[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');
362+
let wrapperStart = '';
363+
let wrapperEnd = '';
364+
365+
if (options.wrapper === undefined) {
366+
wrapperStart = '[\\[{\\(]?';
367+
wrapperEnd = '[\\]}\\)]?';
368+
}
369+
else if (options.wrapper === true) {
370+
wrapperStart = '[\\[{\\(]';
371+
wrapperEnd = '[\\]}\\)]';
372+
}
373+
else if (options.wrapper === false) {
374+
wrapperStart = '';
375+
wrapperEnd = '';
376+
}
377+
else {
378+
wrapperStart = escapeRegex(options.wrapper);
379+
wrapperEnd = escapeRegex(internals.guidBrackets[options.wrapper]);
380+
}
381+
382+
const regex = new RegExp(
383+
`^(${wrapperStart})[0-9A-F]{8}(${separator})[0-9A-F]{4}\\2?[${
384+
versionNumbers || '0-9A-F'
385+
}][0-9A-F]{3}\\2?[${
386+
versionNumbers ? '89AB' : '0-9A-F'
387+
}][0-9A-F]{3}\\2?[0-9A-F]{12}(${wrapperEnd})$`,
388+
'i'
389+
);
347390

348391
return this.$_addRule({ name: 'guid', args: { options }, regex });
349392
},
393+
350394
validate(value, helpers, args, { regex }) {
351395

352396
const results = regex.exec(value);
@@ -355,9 +399,10 @@ module.exports = Any.extend({
355399
return helpers.error('string.guid');
356400
}
357401

358-
// Matching braces
402+
const open = results[1];
403+
const close = results[results.length - 1];
359404

360-
if (internals.guidBrackets[results[1]] !== results[results.length - 1]) {
405+
if (internals.guidBrackets[open || ''] !== (close || '')) {
361406
return helpers.error('string.guid');
362407
}
363408

test/types/string.js

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3196,6 +3196,58 @@ describe('string', () => {
31963196
]);
31973197
});
31983198

3199+
it('validates wrapper', () => {
3200+
3201+
// Wthout wrapper all are valid GUIDs
3202+
Helper.validate(Joi.string().guid(), [
3203+
['69593D62-71EA-4548-85E4-04FC71357423', true],
3204+
['{69593D62-71EA-4548-85E4-04FC71357423}', true],
3205+
['[69593D62-71EA-4548-85E4-04FC71357423]', true],
3206+
['(69593D62-71EA-4548-85E4-04FC71357423)', true]
3207+
]);
3208+
3209+
// Wrapper false means no wrapper is allowed
3210+
Helper.validate(Joi.string().guid({ wrapper: false }), [
3211+
['69593D62-71EA-4548-85E4-04FC71357423', true],
3212+
['{69593D62-71EA-4548-85E4-04FC71357423}', false, '"value" must be a valid GUID'],
3213+
['[69593D62-71EA-4548-85E4-04FC71357423]', false, '"value" must be a valid GUID'],
3214+
['(69593D62-71EA-4548-85E4-04FC71357423)', false, '"value" must be a valid GUID']
3215+
]);
3216+
3217+
// Wrapper true means a wrapper is enforced
3218+
Helper.validate(Joi.string().guid({ wrapper: true }), [
3219+
['69593D62-71EA-4548-85E4-04FC71357423', false, '"value" must be a valid GUID'],
3220+
['{69593D62-71EA-4548-85E4-04FC71357423}', true],
3221+
['[69593D62-71EA-4548-85E4-04FC71357423]', true],
3222+
['(69593D62-71EA-4548-85E4-04FC71357423)', true]
3223+
]);
3224+
3225+
// Wrapper can be set to a specific value
3226+
Helper.validate(Joi.string().guid({ wrapper: '{' }), [
3227+
['69593D62-71EA-4548-85E4-04FC71357423', false, '"value" must be a valid GUID'],
3228+
['{69593D62-71EA-4548-85E4-04FC71357423}', true],
3229+
['[69593D62-71EA-4548-85E4-04FC71357423]', false, '"value" must be a valid GUID'],
3230+
['(69593D62-71EA-4548-85E4-04FC71357423)', false, '"value" must be a valid GUID']
3231+
]);
3232+
3233+
// Wrapper can be set to a specific value
3234+
Helper.validate(Joi.string().guid({ wrapper: '(' }), [
3235+
['69593D62-71EA-4548-85E4-04FC71357423', false, '"value" must be a valid GUID'],
3236+
['{69593D62-71EA-4548-85E4-04FC71357423}', false, '"value" must be a valid GUID'],
3237+
['[69593D62-71EA-4548-85E4-04FC71357423]', false, '"value" must be a valid GUID'],
3238+
['(69593D62-71EA-4548-85E4-04FC71357423)', true]
3239+
]);
3240+
3241+
// Wrapper can be set to a specific value
3242+
Helper.validate(Joi.string().guid({ wrapper: '[' }), [
3243+
['69593D62-71EA-4548-85E4-04FC71357423', false, '"value" must be a valid GUID'],
3244+
['{69593D62-71EA-4548-85E4-04FC71357423}', false, '"value" must be a valid GUID'],
3245+
['[69593D62-71EA-4548-85E4-04FC71357423]', true],
3246+
['(69593D62-71EA-4548-85E4-04FC71357423)', false, '"value" must be a valid GUID']
3247+
]);
3248+
3249+
});
3250+
31993251
it('validates combination of guid and min', () => {
32003252

32013253
const rule = Joi.string().guid().min(36);

0 commit comments

Comments
 (0)