Repository: icebob/fastest-validator
Pull request #118 (2020-03-11 21:42:52)

Implement Aliases
Sometime I need use a same validation rule in some places, aliases (or whatever name is better) are great for this case.
For example, I define an alias for my username validation rule:

```js
v.alias('username', {
   type: 'string',
   min: 4,
   max: 30
   regex: ...
  ....
})
``` 
Then, I can use this alias everywhere I want: 

```js
v.compile({
   firstName: 'string',
   email: 'email',
   username: 'username'  // using alias 
}) 
``` 
also, extending aliases!

```js
v.compile({
   firstName: 'string',
   email: 'email',
   username: {
      type: 'username',
      optional: true,
      max: 60
   }
}) 
``` 





coveralls: 
[![Coverage Status](https://coveralls.io/builds/29287870/badge)](https://coveralls.io/builds/29287870)

Coverage remained the same at 100.0% when pulling **55dd0f8d8121e168a03a0692e1d29b825daad63f on erfanium:master** into **ddd8ec295f6b879fd0186ef5abe0f31b1d7f1b1c on icebob:master**.


Patch:
diff --git a/index.d.ts b/index.d.ts
index 4e31828..fb1d3f4 100644
--- a/index.d.ts
+++ b/index.d.ts
@@ -749,6 +749,11 @@ declare module 'fastest-validator' {
 		 */
 		rules: { [key: string]: ValidationRuleObject };
 
+		/**
+		 * List of aliases attached to current validator
+		 */
+		aliases: { [key: string]: ValidationRule }
+
 		/**
 		 * Constructor of validation class
 		 * @param {ValidatorConstructorOptions} opts List of possible validator constructor options
@@ -762,6 +767,13 @@ declare module 'fastest-validator' {
 		 */
 		add(type: string, fn: any): void;
 
+		/**
+	 	* Register a custom validation rule in validation object
+	 	* @param {string} name
+	 	* @param validationRule
+	 	*/
+		 alias(name: string, validationRule: ValidationRule): void;
+
 		/**
 		 * Build error message
 		 * @return {ValidationError}
diff --git a/lib/validator.js b/lib/validator.js
index 79b3a5d..3bfeded 100644
--- a/lib/validator.js
+++ b/lib/validator.js
@@ -49,6 +49,7 @@ class Validator {
 
 		// Load rules
 		this.rules = loadRules();
+		this.aliases = {};
 		this.cache = new Map();
 	}
 
@@ -281,6 +282,13 @@ class Validator {
 				schema.optional = true;
 		}
 
+		const alias = this.aliases[schema.type];
+
+		if (alias) {
+			delete schema.type;
+			schema = Object.assign({}, alias, schema);
+		}
+
 		const ruleFunction = this.rules[schema.type];
 		if (!ruleFunction)
 			throw new Error("Invalid '" + schema.type + "' type in validator schema.");
@@ -329,6 +337,17 @@ class Validator {
 	add(type, fn) {
 		this.rules[type] = fn;
 	}
+
+	/**
+	 * create alias name for a rule
+	 *
+	 * @param {String} name
+	 * @param validationRule
+	 */
+	alias(name, validationRule) {
+		if (this.rules[name]) throw new Error("Alias name must not be a rule name");
+		this.aliases[name] = validationRule;
+	}
 }
 
 module.exports = Validator;


Test patch:
diff --git a/test/validator.spec.js b/test/validator.spec.js
index f4dcfd9..0be3919 100644
--- a/test/validator.spec.js
+++ b/test/validator.spec.js
@@ -312,5 +312,57 @@ describe("Test compile (integration test)", () => {
 			expect(res).toBe(true);
 			expect(customValidator.mock.calls[0][2]).toBe("customValue");
 		});
-	}); */
+	}); */	
 });
+
+describe("Test aliases", () => {
+	const v = new Validator();
+
+	const aliasName = "username";
+	const aliasTo = {
+		type: "string",
+		min: 4,
+		max: 10
+	};
+
+	it("should add alias", () => {
+		v.alias(aliasName, aliasTo);
+
+		expect(v.rules[aliasName]).toBeUndefined();
+		expect(v.aliases[aliasName]).toEqual(aliasTo);
+	});
+
+	it("should throw an error when alias name is the same with one of rule name", () => {
+		expect(() => v.alias("string", { type: "bar" })).toThrowError();
+		expect(v.rules.string).toBeTruthy();
+		expect(v.aliases.string).toBeUndefined();
+	});
+
+	it("should work with simple alias", () => {
+		const check = v.compile({
+			username: "username"
+		});
+
+		expect(check({ username: "abcdef" })).toEqual(true);
+		expect(check({})[0].type).toEqual("required");
+		expect(check({ username: "aef" })[0].type).toBe("stringMin");
+		expect(check({ username: "abcdabcdabcd" })[0].type).toBe("stringMax");
+	});
+
+	it("should extend the original alias", () => {
+		const check = v.compile({
+			username: {
+				type: "username",
+				optional: true,
+				min: 2
+			}
+		});
+
+		expect(check({ username: "abcdef" })).toEqual(true);
+		expect(check({})).toEqual(true);
+		expect(check({ username: "aef" })).toBe(true);
+		expect(check({ username: "a" })[0].type).toBe("stringMin");
+	});
+});
+
+