From e45c6f734b753de58e7eb05db23027aa086f07a1 Mon Sep 17 00:00:00 2001 From: ERFANIUM Date: Mon, 7 Jun 2021 17:05:25 +0430 Subject: [PATCH 1/3] feat: shorthand for regex --- index.d.ts | 3 ++- lib/validator.js | 5 +++++ test/validator.spec.js | 6 ++++++ 3 files changed, 13 insertions(+), 1 deletion(-) diff --git a/index.d.ts b/index.d.ts index 46c964f..04da259 100644 --- a/index.d.ts +++ b/index.d.ts @@ -785,7 +785,8 @@ declare module "fastest-validator" { export type ValidationRule = | ValidationRuleObject | ValidationRuleObject[] - | ValidationRuleName; + | ValidationRuleName + | RegExp; /** * Definition for validation schema based on validation rules diff --git a/lib/validator.js b/lib/validator.js index cd93da9..1c67fa3 100644 --- a/lib/validator.js +++ b/lib/validator.js @@ -315,6 +315,11 @@ class Validator { .every(rule => rule.schema.optional == true); if (isOptional) schema.optional = true; + } else if (schema instanceof RegExp) { + schema = { + type: "string", + pattern: schema + }; } if (schema.$$type) { diff --git a/test/validator.spec.js b/test/validator.spec.js index af8396a..bf9d1e0 100644 --- a/test/validator.spec.js +++ b/test/validator.spec.js @@ -251,6 +251,12 @@ describe("Test getRuleFromSchema method", () => { expect(res2.schema).toEqual({ type: "array", optional: true, items: "string", min: 1 }); }); + it("should convert RegExp", () => { + const regex = /(foo)/; + const res = v.getRuleFromSchema(regex); + expect(res.schema).toEqual({ type: "string", pattern: regex }); + }); + }); describe("Test objects shorthand rule ($$type)", () => { From f7072ac461369dca2b11a49dae2ac849fb433a83 Mon Sep 17 00:00:00 2001 From: Erfan Safari Date: Mon, 14 Jun 2021 11:17:03 +0430 Subject: [PATCH 2/3] fix issue #235 (#239) * fix issue 235 --- lib/helpers/replace.js | 8 ++++++++ lib/validator.js | 17 ++++++++++------- test/helpers/replace.spec.js | 21 +++++++++++++++++++++ test/integration.spec.js | 17 +++++++++++++++++ test/typescript/validator.spec.ts | 4 ++-- test/validator.spec.js | 4 ++-- 6 files changed, 60 insertions(+), 11 deletions(-) create mode 100644 lib/helpers/replace.js create mode 100644 test/helpers/replace.spec.js diff --git a/lib/helpers/replace.js b/lib/helpers/replace.js new file mode 100644 index 0000000..d4b2096 --- /dev/null +++ b/lib/helpers/replace.js @@ -0,0 +1,8 @@ +function convertible(value) { + if (value === undefined) return ""; + if (value === null) return ""; + if (typeof value.toString === "function") return value; + return typeof value; +} + +module.exports = (string, searchValue, newValue) => string.replace(searchValue, convertible(newValue)); diff --git a/lib/validator.js b/lib/validator.js index cd93da9..47896f9 100644 --- a/lib/validator.js +++ b/lib/validator.js @@ -5,8 +5,8 @@ try { AsyncFunction = (new Function("return Object.getPrototypeOf(async function(){}).constructor"))(); } catch(err) { /* async is not supported */} -//const flatten = require("./helpers/flatten"); const deepExtend = require("./helpers/deep-extend"); +const replace = require("./helpers/replace"); function loadMessages() { return Object.assign({} , require("./messages")); @@ -167,7 +167,10 @@ class Validator { async: schema.$$async === true, rules: [], fn: [], - customs: {} + customs: {}, + utils: { + replace, + }, }; this.cache.clear(); delete schema.$$async; @@ -205,11 +208,11 @@ class Validator { sourceCode.push("if (errors.length) {"); sourceCode.push(` return errors.map(err => { - if (err.message) - err.message = err.message - .replace(/\\{field\\}/g, err.field || "") - .replace(/\\{expected\\}/g, err.expected != null ? err.expected : "") - .replace(/\\{actual\\}/g, err.actual != null ? err.actual : ""); + if (err.message) { + err.message = context.utils.replace(err.message, /\\{field\\}/g, err.field); + err.message = context.utils.replace(err.message, /\\{expected\\}/g, err.expected); + err.message = context.utils.replace(err.message, /\\{actual\\}/g, err.actual); + } return err; }); diff --git a/test/helpers/replace.spec.js b/test/helpers/replace.spec.js new file mode 100644 index 0000000..dac5935 --- /dev/null +++ b/test/helpers/replace.spec.js @@ -0,0 +1,21 @@ +const replace = require("../../lib/helpers/replace"); + +describe("replace", () => { + it("should replace string", () => { + expect(replace("foo bar", "foo", "zoo")).toBe("zoo bar"); + }); + + it("should replace if newValue is null or undefined", () => { + expect(replace("foo bar", "foo", undefined)).toBe(" bar"); + expect(replace("foo bar", "foo", null)).toBe(" bar"); + }); + + it("should replace if newValue has valid toString prototype", () => { + expect(replace("foo bar", "foo", { a: "b" })).toBe("[object Object] bar"); + expect(replace("foo bar", "foo", ["a", "b"])).toBe("a,b bar"); + }); + + it("should replace if newValue has invalid toString prototype", () => { + expect(replace("foo bar", "foo", { toString: 1 })).toBe("object bar"); + }); +}); diff --git a/test/integration.spec.js b/test/integration.spec.js index adfa637..b10f7b4 100644 --- a/test/integration.spec.js +++ b/test/integration.spec.js @@ -1285,3 +1285,20 @@ describe("Test context meta", () => { expect(obj).toEqual({ name: "from-meta" }); }); }); + +describe("edge cases", () => { + const v = new Validator({ useNewCustomCheckerFunction: true }); + + it("issue #235 bug", () => { + const schema = { name: { type: "string" } }; + const check = v.compile(schema); + expect(check({ name: { toString: 1 } })).toEqual([ + { + actual: { toString: 1 }, + field: "name", + message: "The 'name' field must be a string.", + type: "string", + }, + ]); + }); +}); diff --git a/test/typescript/validator.spec.ts b/test/typescript/validator.spec.ts index 3ef59fc..e17cc0b 100644 --- a/test/typescript/validator.spec.ts +++ b/test/typescript/validator.spec.ts @@ -116,13 +116,13 @@ describe('TypeScript Definitions', () => { check = v.compile(schema); - const context = { + const context = expect.objectContaining({ customs: expect.any(Object), rules: expect.any(Array), fn: expect.any(Array), index: 2, async: false - }; + }); expect(validFn).toHaveBeenCalledTimes(1); expect(validFn).toHaveBeenCalledWith(expect.any(Object), 'a', context); diff --git a/test/validator.spec.js b/test/validator.spec.js index af8396a..74044c4 100644 --- a/test/validator.spec.js +++ b/test/validator.spec.js @@ -154,13 +154,13 @@ describe("Test add", () => { check = v.compile(schema); - const context = { + const context = expect.objectContaining({ customs: expect.any(Object), rules: expect.any(Array), fn: expect.any(Array), index: 2, async: false - }; + }); expect(validFn).toHaveBeenCalledTimes(1); From da9e69a24d75cd0435220a2414b2ea1215d6595b Mon Sep 17 00:00:00 2001 From: ERFANIUM Date: Wed, 7 Jul 2021 22:08:41 +0430 Subject: [PATCH 3/3] doc: add regex shorthand --- README.md | 9 +++++++++ index.d.ts | 2 +- 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index be9ab80..96935f7 100644 --- a/README.md +++ b/README.md @@ -275,6 +275,14 @@ check({ foo: ["bar"] }) // true ### Nested objects +```js +const schema = { + code: /^[0-9]{6}$/, + phone: /^\+9\d{11}$/, +}; +``` + +### Regex ```js const schema = { dot: { @@ -294,6 +302,7 @@ const schema = { }; ``` + # Alias definition You can define custom aliases. diff --git a/index.d.ts b/index.d.ts index 04da259..8a10e4a 100644 --- a/index.d.ts +++ b/index.d.ts @@ -786,7 +786,7 @@ declare module "fastest-validator" { | ValidationRuleObject | ValidationRuleObject[] | ValidationRuleName - | RegExp; + | RegExp; /** * Definition for validation schema based on validation rules