diff --git a/examples/custom.js b/examples/custom.js index fd06fde..0ff91e8 100644 --- a/examples/custom.js +++ b/examples/custom.js @@ -36,19 +36,7 @@ const schema = { return value; } },*/ - /*distribution: { - type: "array", - min: 1, - custom(val, errors) { - //I don't get this message below - console.log("distribution", val); - return val; - }, - items: { - type: "number", convert: true, - positive: true - } - },*/ + /* distribution: { type: "array", custom(val) { @@ -62,10 +50,28 @@ const schema = { return val; } } + }*/ + + /* + type: "object", + $$root: true, + properties: { + name: "string" + }, + custom(val) { + console.log("root", val); + return {a : 5 }; + },*/ + $$root: true, + type: "custom", + a: 5, + check(val) { + console.log("root", val); + return val; } }; -console.log(v.validate({ name: "John", age: 20, weight: 50, distribution: [1], a: "asd" }, schema)); +console.log(v.validate(5/*{ name: "John", age: 20, weight: 50, distribution: [1], a: "asd" }*/, schema)); // Returns: true //console.log(v.validate({ name: "John", age: 19, weight: 50 }, schema)); diff --git a/lib/validator.js b/lib/validator.js index 30d20c8..b863806 100644 --- a/lib/validator.js +++ b/lib/validator.js @@ -150,10 +150,14 @@ class Validator { const sourceCode = [ "var errors = [];", "var field;", + "var parent = null;", ]; const rule = this.getRuleFromSchema(schema); sourceCode.push(this.compileRule(rule, context, null, "context.fn[%%INDEX%%](value, field, null, errors, context);", "value")); + sourceCode.push(` + ${this.makeCustomValidator({ path: "$$root", schema: rule.schema, context, messages: rule.messages })} + `); sourceCode.push("if (errors.length) {"); sourceCode.push(` @@ -225,8 +229,9 @@ class Validator { rule.index = context.index; context.rules[context.index] = rule; - if (context.customs[path]) context.customs[path].schema = rule.schema; - else context.customs[path] = { schema: rule.schema }; + const customPath = path != null ? path : "$$root"; + if (context.customs[customPath]) context.customs[customPath].schema = rule.schema; + else context.customs[customPath] = { schema: rule.schema }; context.index++; const res = rule.ruleFunction.call(this, rule, path, context); @@ -347,12 +352,13 @@ class Validator { */ makeCustomValidator({ vName = "value", fnName = "custom", path, schema, context, messages }) { if (typeof schema[fnName] == "function") { - if (context.customs[path]) context.customs[path].messages = messages; - else context.customs[path] = { messages }; + const customPath = path != null ? path : "$$root"; + if (context.customs[customPath]) context.customs[customPath].messages = messages; + else context.customs[customPath] = { messages }; if (this.opts.useNewCustomCheckerFunction) { return ` - const rule = context.customs["${path}"]; + const rule = context.customs["${customPath}"]; const fnCustomErrors = []; ${vName} = rule.schema.${fnName}.call(this, ${vName}, fnCustomErrors, rule.schema, "${path}", parent, context); if (Array.isArray(fnCustomErrors)) { @@ -362,7 +368,7 @@ class Validator { } return ` - const rule = context.customs["${path}"]; + const rule = context.customs["${customPath}"]; const res = rule.schema.${fnName}.call(this, ${vName}, rule.schema, "${path}", parent, context); if (Array.isArray(res)) { res.forEach(err => errors.push(Object.assign({ message: rule.messages[err.type], field }, err))); diff --git a/test/rules/custom.spec.js b/test/rules/custom.spec.js index f6ffed4..772b247 100644 --- a/test/rules/custom.spec.js +++ b/test/rules/custom.spec.js @@ -52,8 +52,8 @@ describe("Test rule: custom v2", () => { useNewCustomCheckerFunction: true, }); - it("should call custom checker", () => { - const checker = jest.fn(() => true); + it("should call custom checker on $$root level", () => { + const checker = jest.fn(v => v); const schema = { $$root: true, type: "custom", a: 5, check: checker }; const check = v.compile(schema); @@ -91,4 +91,21 @@ describe("Test rule: custom v2", () => { expect(checker).toHaveBeenCalledWith(10, expect.any(Array), schema.weight, "weight", { weight: 10 }, expect.any(Object)); }); + it("should call custom checker on $$root level", () => { + const checker = jest.fn(v => v); + const schema = { + $$root: true, + type: "object", + properties: { + name: "string" + }, + custom: checker + }; + const check = v.compile(schema); + + expect(check({ name: "John" })).toEqual(true); + expect(checker).toHaveBeenCalledTimes(1); + expect(checker).toHaveBeenCalledWith({ name: "John" }, [], schema, "$$root", null, expect.any(Object)); + }); + });