From 6419649e6ca5749ceb11761b33d53df0697ade08 Mon Sep 17 00:00:00 2001 From: Joseph Mearman Date: Thu, 3 Dec 2020 12:52:42 +0000 Subject: [PATCH] feat: per-version uuid validation adds specific validation for all uuid versions should be 100% backward compatible --- README.md | 80 ++++++++++++++++++++++++++++++++++++++ README_js.md | 80 ++++++++++++++++++++++++++++++++++++++ src/index.js | 2 +- src/regex.js | 8 +++- src/validate.js | 27 +++++++++++-- test/unit/validate.test.js | 45 ++++++++++++++++++--- 6 files changed, 231 insertions(+), 11 deletions(-) diff --git a/README.md b/README.md index 11b7cc7e..a34274f8 100644 --- a/README.md +++ b/README.md @@ -57,6 +57,10 @@ For timestamp UUIDs, namespace UUIDs, and other options read on ... | [`uuid.v4()`](#uuidv4options-buffer-offset) | Create a version 4 (random) UUID | | | [`uuid.v5()`](#uuidv5name-namespace-buffer-offset) | Create a version 5 (namespace w/ SHA-1) UUID | | | [`uuid.validate()`](#uuidvalidatestr) | Test a string to see if it is a valid UUID | New in `uuid@8.3` | +| [`uuid.isV1()`](#uuidisv1str) | Test a string to see if it is a valid V1 UUID | | +| [`uuid.isV3()`](#uuidisv3str) | Test a string to see if it is a valid V3 UUID | | +| [`uuid.isV4()`](#uuidisv4str) | Test a string to see if it is a valid V4 UUID | | +| [`uuid.isV5()`](#uuidisv5str) | Test a string to see if it is a valid V5 UUID | | | [`uuid.version()`](#uuidversionstr) | Detect RFC version of a UUID | New in `uuid@8.3` | ## API @@ -296,6 +300,82 @@ uuidValidate('not a UUID'); // ⇨ false uuidValidate('6ec0bd7f-11c0-43da-975e-2a8ad9ebae0b'); // ⇨ true ``` +### uuid.isV1(str) + +Test a string to see if it is a valid V1 UUID + +| | | +| --------- | ------------------------------------------------------ | +| `str` | `String` to validate | +| _returns_ | `true` if string is a valid V1 UUID, `false` otherwise | + +Example: + +```javascript +import { isV1 as uuidIsV1 } from 'uuid'; + +uuidIsV1('not a UUID'); // ⇨ false +uuidIsV1('d9428888-122b-11e1-b85c-61cd3cbb3210'); // ⇨ true +uuidIsV1('a981a0c2-68b1-35dc-bcfc-296e52ab01ec'); // ⇨ false +``` + +### uuid.isV3(str) + +Test a string to see if it is a valid V3 UUID + +| | | +| --------- | ------------------------------------------------------ | +| `str` | `String` to validate | +| _returns_ | `true` if string is a valid V3 UUID, `false` otherwise | + +Example: + +```javascript +import { isV3 as uuidIsV3 } from 'uuid'; + +uuidIsV3('not a UUID'); // ⇨ false +uuidIsV3('a981a0c2-68b1-35dc-bcfc-296e52ab01ec'); // ⇨ true +uuidIsV3('109156be-c4fb-41ea-b1b4-efe1671c5836'); // ⇨ false +``` + +### uuid.isV4(str) + +Test a string to see if it is a valid V4 UUID + +| | | +| --------- | ------------------------------------------------------ | +| `str` | `String` to validate | +| _returns_ | `true` if string is a valid V4 UUID, `false` otherwise | + +Example: + +```javascript +import { isV4 as uuidIsV4 } from 'uuid'; + +uuidIsV4('not a UUID'); // ⇨ false +uuidIsV4('109156be-c4fb-41ea-b1b4-efe1671c5836'); // ⇨ true +uuidIsV4('90123e1c-7512-523e-bb28-76fab9f2f73d'); // ⇨ false +``` + +### uuid.isV5(str) + +Test a string to see if it is a valid V5 UUID + +| | | +| --------- | ------------------------------------------------------ | +| `str` | `String` to validate | +| _returns_ | `true` if string is a valid V5 UUID, `false` otherwise | + +Example: + +```javascript +import { isV5 as uuidIsV5 } from 'uuid'; + +uuidIsV5('not a UUID'); // ⇨ false +uuidIsV5('90123e1c-7512-523e-bb28-76fab9f2f73d'); // ⇨ true +uuidIsV5('109156be-c4fb-41ea-b1b4-efe1671c5836'); // ⇨ false +``` + ### uuid.version(str) Detect RFC version of a UUID diff --git a/README_js.md b/README_js.md index a2769a22..c4fddc31 100644 --- a/README_js.md +++ b/README_js.md @@ -69,6 +69,10 @@ For timestamp UUIDs, namespace UUIDs, and other options read on ... | [`uuid.v4()`](#uuidv4options-buffer-offset) | Create a version 4 (random) UUID | | | [`uuid.v5()`](#uuidv5name-namespace-buffer-offset) | Create a version 5 (namespace w/ SHA-1) UUID | | | [`uuid.validate()`](#uuidvalidatestr) | Test a string to see if it is a valid UUID | New in `uuid@8.3` | +| [`uuid.isV1()`](#uuidisv1str) | Test a string to see if it is a valid V1 UUID | | +| [`uuid.isV3()`](#uuidisv3str) | Test a string to see if it is a valid V3 UUID | | +| [`uuid.isV4()`](#uuidisv4str) | Test a string to see if it is a valid V4 UUID | | +| [`uuid.isV5()`](#uuidisv5str) | Test a string to see if it is a valid V5 UUID | | | [`uuid.version()`](#uuidversionstr) | Detect RFC version of a UUID | New in `uuid@8.3` | ## API @@ -302,6 +306,82 @@ uuidValidate('not a UUID'); // RESULT uuidValidate('6ec0bd7f-11c0-43da-975e-2a8ad9ebae0b'); // RESULT ``` +### uuid.isV1(str) + +Test a string to see if it is a valid V1 UUID + +| | | +| --------- | ------------------------------------------------------ | +| `str` | `String` to validate | +| _returns_ | `true` if string is a valid V1 UUID, `false` otherwise | + +Example: + +```javascript --run +import { isV1 as uuidIsV1 } from 'uuid'; + +uuidIsV1('not a UUID'); // RESULT +uuidIsV1('d9428888-122b-11e1-b85c-61cd3cbb3210'); // RESULT +uuidIsV1('a981a0c2-68b1-35dc-bcfc-296e52ab01ec'); // RESULT +``` + +### uuid.isV3(str) + +Test a string to see if it is a valid V3 UUID + +| | | +| --------- | ------------------------------------------------------ | +| `str` | `String` to validate | +| _returns_ | `true` if string is a valid V3 UUID, `false` otherwise | + +Example: + +```javascript --run +import { isV3 as uuidIsV3 } from 'uuid'; + +uuidIsV3('not a UUID'); // RESULT +uuidIsV3('a981a0c2-68b1-35dc-bcfc-296e52ab01ec'); // RESULT +uuidIsV3('109156be-c4fb-41ea-b1b4-efe1671c5836'); // RESULT +``` + +### uuid.isV4(str) + +Test a string to see if it is a valid V4 UUID + +| | | +| --------- | ------------------------------------------------------ | +| `str` | `String` to validate | +| _returns_ | `true` if string is a valid V4 UUID, `false` otherwise | + +Example: + +```javascript --run +import { isV4 as uuidIsV4 } from 'uuid'; + +uuidIsV4('not a UUID'); // RESULT +uuidIsV4('109156be-c4fb-41ea-b1b4-efe1671c5836'); // RESULT +uuidIsV4('90123e1c-7512-523e-bb28-76fab9f2f73d'); // RESULT +``` + +### uuid.isV5(str) + +Test a string to see if it is a valid V5 UUID + +| | | +| --------- | ------------------------------------------------------ | +| `str` | `String` to validate | +| _returns_ | `true` if string is a valid V5 UUID, `false` otherwise | + +Example: + +```javascript --run +import { isV5 as uuidIsV5 } from 'uuid'; + +uuidIsV5('not a UUID'); // RESULT +uuidIsV5('90123e1c-7512-523e-bb28-76fab9f2f73d'); // RESULT +uuidIsV5('109156be-c4fb-41ea-b1b4-efe1671c5836'); // RESULT +``` + ### uuid.version(str) Detect RFC version of a UUID diff --git a/src/index.js b/src/index.js index 142ce9e4..55af5838 100644 --- a/src/index.js +++ b/src/index.js @@ -3,7 +3,7 @@ export { default as v3 } from './v3.js'; export { default as v4 } from './v4.js'; export { default as v5 } from './v5.js'; export { default as NIL } from './nil.js'; +export { default as validate, isV1, isV3, isV4, isV5 } from './validate.js'; export { default as version } from './version.js'; -export { default as validate } from './validate.js'; export { default as stringify } from './stringify.js'; export { default as parse } from './parse.js'; diff --git a/src/regex.js b/src/regex.js index 92f79a1e..3e8159fb 100644 --- a/src/regex.js +++ b/src/regex.js @@ -1 +1,7 @@ -export default /^(?:[0-9a-f]{8}-[0-9a-f]{4}-[1-5][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}|00000000-0000-0000-0000-000000000000)$/i; +const genericUuid = /^(?:[0-9a-f]{8}-[0-9a-f]{4}-[1-5][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}|00000000-0000-0000-0000-000000000000)$/i; +const v1 = /^[0-9a-f]{8}-[0-9a-f]{4}-[1][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i; +const v3 = /^[0-9a-f]{8}-[0-9a-f]{4}-[3][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i; +const v4 = /^[0-9a-f]{8}-[0-9a-f]{4}-[4][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i; +const v5 = /^[0-9a-f]{8}-[0-9a-f]{4}-[5][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i; +export default genericUuid; +export { genericUuid, v1, v3, v4, v5 }; diff --git a/src/validate.js b/src/validate.js index 22a1217e..accfc90d 100644 --- a/src/validate.js +++ b/src/validate.js @@ -1,7 +1,26 @@ -import REGEX from './regex.js'; +import { genericUuid, v1, v3, v4, v5 } from './regex.js'; -function validate(uuid) { - return typeof uuid === 'string' && REGEX.test(uuid); +function validateByVersion(uuid, expression) { + return typeof uuid === 'string' && expression.test(uuid); } -export default validate; +function isUuid(uuid) { + return validateByVersion(uuid, genericUuid); +} +export default isUuid; + +export function isV1(uuid) { + return validateByVersion(uuid, v1); +} + +export function isV3(uuid) { + return validateByVersion(uuid, v3); +} + +export function isV4(uuid) { + return validateByVersion(uuid, v4); +} + +export function isV5(uuid) { + return validateByVersion(uuid, v5); +} diff --git a/test/unit/validate.test.js b/test/unit/validate.test.js index 3ed9a948..012b452f 100644 --- a/test/unit/validate.test.js +++ b/test/unit/validate.test.js @@ -1,18 +1,25 @@ import assert from 'assert'; -import validate from '../../src/validate.js'; +import validate, { isV1, isV3, isV4, isV5 } from '../../src/validate.js'; import NIL from '../../src/nil.js'; +const validUuids = { + v1: 'd9428888-122b-11e1-b85c-61cd3cbb3210', + v3: 'a981a0c2-68b1-35dc-bcfc-296e52ab01ec', + v4: '109156be-c4fb-41ea-b1b4-efe1671c5836', + v5: '90123e1c-7512-523e-bb28-76fab9f2f73d', +}; + describe('validate', () => { test('validate uuid', () => { assert.strictEqual(validate(NIL), true); - assert.strictEqual(validate('d9428888-122b-11e1-b85c-61cd3cbb3210'), true); + assert.strictEqual(validate(validUuids.v1), true); - assert.strictEqual(validate('109156be-c4fb-41ea-b1b4-efe1671c5836'), true); + assert.strictEqual(validate(validUuids.v3), true); - assert.strictEqual(validate('a981a0c2-68b1-35dc-bcfc-296e52ab01ec'), true); + assert.strictEqual(validate(validUuids.v3), true); - assert.strictEqual(validate('90123e1c-7512-523e-bb28-76fab9f2f73d'), true); + assert.strictEqual(validate(validUuids.v5), true); assert.strictEqual(validate(), false); @@ -29,4 +36,32 @@ describe('validate', () => { false ); }); + + test('validate v1 uuid', () => { + assert.strictEqual(isV1(validUuids.v1), true); + assert.strictEqual(isV1(validUuids.v3), false); + assert.strictEqual(isV1(validUuids.v4), false); + assert.strictEqual(isV1(validUuids.v5), false); + }); + + test('validate v3 uuid', () => { + assert.strictEqual(isV3(validUuids.v1), false); + assert.strictEqual(isV3(validUuids.v3), true); + assert.strictEqual(isV3(validUuids.v4), false); + assert.strictEqual(isV3(validUuids.v5), false); + }); + + test('validate v4 uuid', () => { + assert.strictEqual(isV4(validUuids.v1), false); + assert.strictEqual(isV4(validUuids.v3), false); + assert.strictEqual(isV4(validUuids.v4), true); + assert.strictEqual(isV4(validUuids.v5), false); + }); + + test('validate v5 uuid', () => { + assert.strictEqual(isV5(validUuids.v1), false); + assert.strictEqual(isV5(validUuids.v3), false); + assert.strictEqual(isV5(validUuids.v4), false); + assert.strictEqual(isV5(validUuids.v5), true); + }); });