Skip to content

Commit

Permalink
feat: string UUID validation via a regex (#909)
Browse files Browse the repository at this point in the history
  • Loading branch information
LFabre authored Jun 16, 2020
1 parent ca0fe10 commit 8f2bd2b
Show file tree
Hide file tree
Showing 4 changed files with 43 additions and 0 deletions.
5 changes: 5 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@ Yup's API is heavily inspired by [Joi](https://github.com/hapijs/joi), but leane
- [`string.matches(regex: Regex, options: { message: string, excludeEmptyString: bool }): Schema`](#stringmatchesregex-regex-options--message-string-excludeemptystring-bool--schema)
- [`string.email(message?: string | function): Schema`](#stringemailmessage-string--function-schema)
- [`string.url(message?: string | function): Schema`](#stringurlmessage-string--function-schema)
- [`string.uuid(message?: string | function): Schema`](#stringuuidmessage-string--function-schema)
- [`string.ensure(): Schema`](#stringensure-schema)
- [`string.trim(message?: string | function): Schema`](#stringtrimmessage-string--function-schema)
- [`string.lowercase(message?: string | function): Schema`](#stringlowercasemessage-string--function-schema)
Expand Down Expand Up @@ -862,6 +863,10 @@ Validates the value as an email address via a regex.

Validates the value as a valid URL via a regex.

#### `string.uuid(message?: string | function): Schema`

Validates the value as a valid UUID via a regex.

#### `string.ensure(): Schema`

Transforms `undefined` and `null` values to an empty string along with
Expand Down
1 change: 1 addition & 0 deletions src/locale.js
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ export let string = {
matches: '${path} must match the following: "${regex}"',
email: '${path} must be a valid email',
url: '${path} must be a valid URL',
uuid: '${path} must be a valid UUID',
trim: '${path} must be a trimmed string',
lowercase: '${path} must be a lowercase string',
uppercase: '${path} must be a upper case string',
Expand Down
10 changes: 10 additions & 0 deletions src/string.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@ import isAbsent from './util/isAbsent';
let rEmail = /^((([a-z]|\d|[!#\$%&'\*\+\-\/=\?\^_`{\|}~]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])+(\.([a-z]|\d|[!#\$%&'\*\+\-\/=\?\^_`{\|}~]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])+)*)|((\x22)((((\x20|\x09)*(\x0d\x0a))?(\x20|\x09)+)?(([\x01-\x08\x0b\x0c\x0e-\x1f\x7f]|\x21|[\x23-\x5b]|[\x5d-\x7e]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(\\([\x01-\x09\x0b\x0c\x0d-\x7f]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF]))))*(((\x20|\x09)*(\x0d\x0a))?(\x20|\x09)+)?(\x22)))@((([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.)+(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))$/i;
// eslint-disable-next-line
let rUrl = /^((https?|ftp):)?\/\/(((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:)*@)?(((\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])\.(\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])\.(\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])\.(\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5]))|((([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.)+(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.?)(:\d*)?)(\/((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)+(\/(([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)*)*)?)?(\?((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)|[\uE000-\uF8FF]|\/|\?)*)?(\#((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)|\/|\?)*)?$/i;
// eslint-disable-next-line
let rUUID = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-5][0-9a-f]{3}-[089ab][0-9a-f]{3}-[0-9a-f]{12}$/i

let isTrimmed = (value) => isAbsent(value) || value === value.trim();

Expand Down Expand Up @@ -112,6 +114,14 @@ inherits(StringSchema, MixedSchema, {
});
},

uuid(message = locale.uuid) {
return this.matches(rUUID, {
name: 'uuid',
message,
excludeEmptyString: false,
});
},

//-- transforms --
ensure() {
return this.default('').transform((val) => (val === null ? '' : val));
Expand Down
27 changes: 27 additions & 0 deletions test/string.js
Original file line number Diff line number Diff line change
Expand Up @@ -324,6 +324,33 @@ describe('String types', () => {
]);
});

it('should check UUID correctly', function() {
var v = string().uuid();

return Promise.all([
v
.isValid('0c40428c-d88d-4ff0-a5dc-a6755cb4f4d1')
.should.eventually()
.equal(true),
v
.isValid('42c4a747-3e3e-42be-af30-469cfb9c1913')
.should.eventually()
.equal(true),
v
.isValid('42c4a747-3e3e-zzzz-af30-469cfb9c1913')
.should.eventually()
.equal(false),
v
.isValid('this is not a uuid')
.should.eventually()
.equal(false),
v
.isValid('')
.should.eventually()
.equal(false),
]);
});

it('should validate transforms', function() {
return Promise.all([
string()
Expand Down

0 comments on commit 8f2bd2b

Please sign in to comment.