Repository: icebob/fastest-validator
Pull request #201 (2020-11-15 23:57:57)

feat(uuid): support Nil UUID
add nil uuid version 0 https://github.com/icebob/fastest-validator/issues/200


Patch:
diff --git a/README.md b/README.md
index 268d455..69c629a 100644
--- a/README.md
+++ b/README.md
@@ -1066,6 +1066,7 @@ const schema = {
     uuid: { type: "uuid" }
 }
 
+v.validate({ uuid: "00000000-0000-0000-0000-000000000000" }, schema); // Valid Nil UUID
 v.validate({ uuid: "10ba038e-48da-487b-96e8-8d3b99b6d18a" }, schema); // Valid UUIDv4
 v.validate({ uuid: "9a7b330a-a736-51e5-af7f-feaf819cdc9f" }, schema); // Valid UUIDv5
 v.validate({ uuid: "10ba038e-48da-487b-96e8-8d3b99b6d18a", version: 5 }, schema); // Fail
@@ -1073,7 +1074,7 @@ v.validate({ uuid: "10ba038e-48da-487b-96e8-8d3b99b6d18a", version: 5 }, schema)
 ### Properties
 Property | Default  | Description
 -------- | -------- | -----------
-`version`  | `4`   | UUID version in range 1-6.
+`version`  | `4`   | UUID version in range 0-6.
 
 ## `objectID`
 You can validate BSON/MongoDB ObjectID's
diff --git a/index.d.ts b/index.d.ts
index e3584a7..cb34663 100644
--- a/index.d.ts
+++ b/index.d.ts
@@ -471,9 +471,9 @@ declare module "fastest-validator" {
 		 */
 		type: "uuid";
 		/**
-		 * UUID version in range 1-5
+		 * UUID version in range 0-6
 		 */
-		version?: 1 | 2 | 3 | 4 | 5;
+		version?: 0 | 1 | 2 | 3 | 4 | 5 | 6;
 	}
 
 	/**
diff --git a/lib/rules/uuid.js b/lib/rules/uuid.js
index 3a80e8e..ab95f29 100644
--- a/lib/rules/uuid.js
+++ b/lib/rules/uuid.js
@@ -1,6 +1,6 @@
 "use strict";
 
-const PATTERN = /^[0-9a-f]{8}-[0-9a-f]{4}-[1-6][0-9a-f]{3}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
+const PATTERN = /^([0-9a-f]{8}-[0-9a-f]{4}-[1-6][0-9a-f]{3}-[0-9a-f]{4}-[0-9a-f]{12}|[0]{8}-[0]{4}-[0]{4}-[0]{4}-[0]{12})$/i;
 
 /**	Signature: function(value, field, parent, errors, context)
  */
@@ -21,7 +21,7 @@ module.exports = function({ schema, messages }, path) {
 		const version = val.charAt(14) | 0;
 	`);
 
-	if(schema.version) {
+	if(parseInt(schema.version) < 7) {
 		src.push(`
 			if (${schema.version} !== version) {
 				${this.makeError({ type: "uuidVersion", expected: schema.version, actual: "version", messages })}
@@ -32,6 +32,7 @@ module.exports = function({ schema, messages }, path) {
 
 	src.push(`
 		switch (version) {
+		case 0:
 		case 1:
 		case 2:
 		case 6:


Test patch:
diff --git a/test/rules/uuid.spec.js b/test/rules/uuid.spec.js
index 4425489..c6ae616 100644
--- a/test/rules/uuid.spec.js
+++ b/test/rules/uuid.spec.js
@@ -19,7 +19,7 @@ describe("Test rule: uuid", () => {
 		message = "The '' field must be a valid UUID.";
 		expect(check("")).toEqual([{ type: "uuid", actual: "", message }]);
 		expect(check("true")).toEqual([{ type: "uuid", actual: "true", message }]);
-		expect(check("00000000-0000-0000-0000-000000000000")).toEqual([{ type: "uuid", actual: "00000000-0000-0000-0000-000000000000", message }]);
+		expect(check("10000000-0000-0000-0000-000000000000")).toEqual([{ type: "uuid", actual: "10000000-0000-0000-0000-000000000000", message }]);
 		expect(check("1234567-1234-1234-1234-1234567890ab")).toEqual([{ type: "uuid", actual: "1234567-1234-1234-1234-1234567890ab", message }]);
 		expect(check("12345678-1234-1234-1234-1234567890ab")).toEqual(true);
 	});
@@ -31,14 +31,15 @@ describe("Test rule: uuid", () => {
 		expect(check("00000000-0000-7000-0000-000000000000")).toEqual([{ type: "uuid", actual: "00000000-0000-7000-0000-000000000000", message }]);
 		expect(check("fdda765f-fc57-5604-c269-52a7df8164ec")).toEqual([{ type: "uuid", actual: "fdda765f-fc57-5604-c269-52a7df8164ec", message }]);
 
+		const check0 = v.compile({ $$root: true, type: "uuid", version: 0 });
 		const check1 = v.compile({ $$root: true, type: "uuid", version: 1 });
 		const check2 = v.compile({ $$root: true, type: "uuid", version: 2 });
 		const check3 = v.compile({ $$root: true, type: "uuid", version: 3 });
 		const check4 = v.compile({ $$root: true, type: "uuid", version: 4 });
 		const check5 = v.compile({ $$root: true, type: "uuid", version: 5 });
-		const check6 = v.compile({ $$root: true, type: "uuid", version: 6 });
 		message = "The '' field must be a valid UUID version provided.";
 
+		expect(check0("00000000-0000-1000-0000-000000000000")).toEqual([{"actual": 1, "expected": 0, "type": "uuidVersion", message}]);
 		expect(check1("9a7b330a-a736-51e5-af7f-feaf819cdc9f")).toEqual([{"actual": 5, "expected": 1, "type": "uuidVersion", message}]);
 		expect(check1("9a7b330a-a736-61e5-af7f-feaf819cdc9f")).toEqual([{"actual": 6, "expected": 1, "type": "uuidVersion", message}]);
 		expect(check1("9a7b330a-a736-51e5-af7f-feaf819cdc9f")).toEqual([{"actual": 5, "expected": 1, "type": "uuidVersion", message}]);
@@ -49,6 +50,7 @@ describe("Test rule: uuid", () => {
 	});
 
 	it("check valid version", () => {
+		const check0 = v.compile({ $$root: true, type: "uuid", version: 0 });
 		const check1 = v.compile({ $$root: true, type: "uuid", version: 1 });
 		const check2 = v.compile({ $$root: true, type: "uuid", version: 2 });
 		const check3 = v.compile({ $$root: true, type: "uuid", version: 3 });
@@ -56,13 +58,13 @@ describe("Test rule: uuid", () => {
 		const check5 = v.compile({ $$root: true, type: "uuid", version: 5 });
 		const check6 = v.compile({ $$root: true, type: "uuid", version: 6 });
 
+		expect(check0("00000000-0000-0000-0000-000000000000")).toEqual(true);
 		expect(check1("45745c60-7b1a-11e8-9c9c-2d42b21b1a3e")).toEqual(true);
 		expect(check2("9a7b330a-a736-21e5-af7f-feaf819cdc9f")).toEqual(true);
 		expect(check3("9125a8dc-52ee-365b-a5aa-81b0b3681cf6")).toEqual(true);
 		expect(check4("10ba038e-48da-487b-96e8-8d3b99b6d18a")).toEqual(true);
 		expect(check5("fdda765f-fc57-5604-a269-52a7df8164ec")).toEqual(true);
 		expect(check6("a9030619-8514-6970-e0f9-81b9ceb08a5f")).toEqual(true);
-
 	});
 
 	it("should not be case insensitive", () => {
@@ -79,7 +81,7 @@ describe("Test rule: uuid", () => {
 		expect(check4("10ba038e-48da-487b-96e8-8d3b99b6d18a")).toEqual(true);
 		expect(check5("fdda765f-fc57-5604-a269-52a7df8164ec")).toEqual(true);
 		expect(check6("a9030619-8514-6970-e0f9-81b9ceb08a5f")).toEqual(true);
-		
+
 		expect(check1("45745C60-7B1A-11E8-9C9C-2D42B21B1A3E")).toEqual(true);
 		expect(check2("9A7B330A-A736-21E5-AF7F-FEAF819CDC9F")).toEqual(true);
 		expect(check3("9125A8DC-52EE-365B-A5AA-81B0B3681CF6")).toEqual(true);
diff --git a/test/typescript/rules/uuid.spec.ts b/test/typescript/rules/uuid.spec.ts
index 2633e63..1faf417 100644
--- a/test/typescript/rules/uuid.spec.ts
+++ b/test/typescript/rules/uuid.spec.ts
@@ -20,7 +20,7 @@ describe('TypeScript Definitions', () => {
             message = 'The \'\' field must be a valid UUID.';
             expect(check('')).toEqual([{ type: 'uuid', actual: '', message }]);
             expect(check('true')).toEqual([{ type: 'uuid', actual: 'true', message }]);
-            expect(check('00000000-0000-0000-0000-000000000000')).toEqual([{ type: 'uuid', actual: '00000000-0000-0000-0000-000000000000', message }]);
+            expect(check('10000000-0000-0000-0000-000000000000')).toEqual([{ type: 'uuid', actual: '10000000-0000-0000-0000-000000000000', message }]);
             expect(check('1234567-1234-1234-1234-1234567890ab')).toEqual([{ type: 'uuid', actual: '1234567-1234-1234-1234-1234567890ab', message }]);
             expect(check('12345678-1234-1234-1234-1234567890ab')).toEqual(true);
         });
@@ -32,6 +32,7 @@ describe('TypeScript Definitions', () => {
             expect(check('00000000-0000-7000-0000-000000000000')).toEqual([{ type: 'uuid', actual: '00000000-0000-7000-0000-000000000000', message }]);
             expect(check('fdda765f-fc57-5604-c269-52a7df8164ec')).toEqual([{ type: 'uuid', actual: 'fdda765f-fc57-5604-c269-52a7df8164ec', message }]);
 
+			const check0 = v.compile({ $$root: true, type: "uuid", version: 0 } as RuleUUID);
             const check1 = v.compile({ $$root: true, type: 'uuid', version: 1 } as RuleUUID);
             const check2 = v.compile({ $$root: true, type: 'uuid', version: 2 } as RuleUUID);
             const check3 = v.compile({ $$root: true, type: 'uuid', version: 3 } as RuleUUID);
@@ -39,6 +40,7 @@ describe('TypeScript Definitions', () => {
             const check5 = v.compile({ $$root: true, type: 'uuid', version: 5 } as RuleUUID);
             message = 'The \'\' field must be a valid UUID version provided.';
 
+			expect(check0("00000000-0000-1000-0000-000000000000")).toEqual([{"actual": 1, "expected": 0, "type": "uuidVersion", message}]);
             expect(check1('9a7b330a-a736-51e5-af7f-feaf819cdc9f')).toEqual([{ 'actual': 5, 'expected': 1, 'type': 'uuidVersion', message }]);
             expect(check1('9a7b330a-a736-51e5-af7f-feaf819cdc9f')).toEqual([{ 'actual': 5, 'expected': 1, 'type': 'uuidVersion', message }]);
             expect(check2('9a7b330a-a736-41e5-af7f-feaf819cdc9f')).toEqual([{ 'actual': 4, 'expected': 2, 'type': 'uuidVersion', message }]);
@@ -48,18 +50,42 @@ describe('TypeScript Definitions', () => {
         });
 
         it('check valid version', () => {
+			const check0 = v.compile({ $$root: true, type: "uuid", version: 0 } as RuleUUID);
             const check1 = v.compile({ $$root: true, type: 'uuid', version: 1 } as RuleUUID);
             const check2 = v.compile({ $$root: true, type: 'uuid', version: 2 } as RuleUUID);
             const check3 = v.compile({ $$root: true, type: 'uuid', version: 3 } as RuleUUID);
             const check4 = v.compile({ $$root: true, type: 'uuid', version: 4 } as RuleUUID);
             const check5 = v.compile({ $$root: true, type: 'uuid', version: 5 } as RuleUUID);
 
+			expect(check0("00000000-0000-0000-0000-000000000000")).toEqual(true);
             expect(check1('45745c60-7b1a-11e8-9c9c-2d42b21b1a3e')).toEqual(true);
             expect(check2('9a7b330a-a736-21e5-af7f-feaf819cdc9f')).toEqual(true);
             expect(check3('9125a8dc-52ee-365b-a5aa-81b0b3681cf6')).toEqual(true);
             expect(check4('10ba038e-48da-487b-96e8-8d3b99b6d18a')).toEqual(true);
             expect(check5('fdda765f-fc57-5604-a269-52a7df8164ec')).toEqual(true);
-
         });
+
+		it("should not be case insensitive", () => {
+			const check1 = v.compile({ $$root: true, type: "uuid", version: 1 } as RuleUUID);
+			const check2 = v.compile({ $$root: true, type: "uuid", version: 2 } as RuleUUID);
+			const check3 = v.compile({ $$root: true, type: "uuid", version: 3 } as RuleUUID);
+			const check4 = v.compile({ $$root: true, type: "uuid", version: 4 } as RuleUUID);
+			const check5 = v.compile({ $$root: true, type: "uuid", version: 5 } as RuleUUID);
+			const check6 = v.compile({ $$root: true, type: "uuid", version: 6 } as RuleUUID);
+
+			expect(check1("45745c60-7b1a-11e8-9c9c-2d42b21b1a3e")).toEqual(true);
+			expect(check2("9a7b330a-a736-21e5-af7f-feaf819cdc9f")).toEqual(true);
+			expect(check3("9125a8dc-52ee-365b-a5aa-81b0b3681cf6")).toEqual(true);
+			expect(check4("10ba038e-48da-487b-96e8-8d3b99b6d18a")).toEqual(true);
+			expect(check5("fdda765f-fc57-5604-a269-52a7df8164ec")).toEqual(true);
+			expect(check6("a9030619-8514-6970-e0f9-81b9ceb08a5f")).toEqual(true);
+
+			expect(check1("45745C60-7B1A-11E8-9C9C-2D42B21B1A3E")).toEqual(true);
+			expect(check2("9A7B330A-A736-21E5-AF7F-FEAF819CDC9F")).toEqual(true);
+			expect(check3("9125A8DC-52EE-365B-A5AA-81B0B3681CF6")).toEqual(true);
+			expect(check4("10BA038E-48DA-487B-96E8-8D3B99B6D18A")).toEqual(true);
+			expect(check5("FDDA765F-FC57-5604-A269-52A7DF8164EC")).toEqual(true);
+			expect(check6("A9030619-8514-6970-E0F9-81B9CEB08A5F")).toEqual(true);
+		});
     });
 });