Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

fastest-validator

Package Overview
Dependencies
Maintainers
1
Versions
59
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

fastest-validator - npm Package Compare versions

Comparing version 0.2.0 to 0.3.0

benchmark/suites/email.js

2

.eslintrc.js

@@ -32,3 +32,3 @@ module.exports = {

"no-console": [
"off"
"error"
],

@@ -35,0 +35,0 @@ "no-unused-vars": [

@@ -6,20 +6,6 @@ "use strict";

messages: {
stringMin: "A '{name}' mező túl rövid. Minimum: {0}, Jelenleg: {1}"
stringMin: "A(z) '{name}' mező túl rövid. Minimum: {0}, Jelenleg: {1}"
}
});
/*
v.add("url", (value, schema) => {
const PATTERN = /https?:\/\/(www\.)?[-a-zA-Z0-9@:%._\+~#=]{2,256}\.[a-z]{2,4}\b([-a-zA-Z0-9@:%_\+.~#?&//=]*)/g;
if (typeof value !== "string") {
return { msg: "string" };
}
if (!PATTERN.test(value)) {
return { msg: "url" }
}
return true;
});*/
const schema = {

@@ -33,4 +19,14 @@ id: { type: "number", min: 1, max: 100 },

sex: { type: "string", enum: ["male", "female"] },
roles: { type: "array", enum: ["admin", "user"] },
//comments: { type: "array", items: { type: "object" } },
roles: { type: "array", items: { type: "string" }, enum: ["admin", "user"] },
friends: { type: "array", items: { type: "number", positive: true }},
comments: { type: "array", items: { type: "object", props: {
user: { type: "number", positive: true, integer: true },
content: { type: "string" },
voters: { type: "array", optional: true, items: { type: "number", optional: true }}
} } },
multiarray: { type: "array", empty: false, items: {
type: "array", empty: true, items: {
type: "number"
}
}},
email: { type: "email", optional: true },

@@ -55,2 +51,25 @@ homepage: { type: "url", optional: true },

],
friends: [
5,
10,
2
],
comments: [
{ user: 1, content: "Cool!" },
{ user: 2, content: "Very fast!" },
{ user: 1, content: "", voters: [1] }
],
multiarray: [
[
],
[
5,
10,
"a"
]
],
email: "john.doe@clipboard.space",

@@ -57,0 +76,0 @@ homepage: "http://google.com",

"use strict";
const PRECISE_PATTERN = /^(([^<>()[\]\\.,;:\s@\"]+(\.[^<>()[\]\\.,;:\s@\"]+)*)|(\".+\"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/;
const QUICK_PATTERN = /^\S+@\S+\.\S+$/;
const BASIC_PATTERN = /^\S+@\S+\.\S+$/;
/*
Alternative:
http://codereview.stackexchange.com/questions/38305/validating-email-without-regex
*/
module.exports = function checkEmail(value, schema) {

@@ -17,7 +12,6 @@ if (typeof value !== "string") {

let pattern;
if (schema.mode == "precise")
pattern = PRECISE_PATTERN;
else
pattern = QUICK_PATTERN;
pattern = BASIC_PATTERN;

@@ -29,2 +23,2 @@ if (!pattern.test(value)) {

return true;
};
};
"use strict";
let defaultsDeep = require("lodash/defaultsDeep");
let flatten = require("lodash/flatten");
let defaultMessages = require("./messages");

@@ -46,53 +47,104 @@ let glob = require("glob");

*/
Validator.prototype.compile = function(schema, parentPath) {
Validator.prototype.compile = function(schema) {
const self = this;
let rules;
// Process the whole schema
if (Array.isArray(schema)) {
if (schema.length !== 1)
throw new Error("If the schema is an Array, must be only one element!");
rules = self._processRule(schema[0], null, false);
} else if (schema != null && typeof schema === "object") {
rules = flatten(Object.keys(schema).map(name => self._processRule(schema[name], name, false)));
} else
throw new Error("Invalid schema!");
return this._checkWrapper(rules);
};
/**
* Process a rule item & return checker functions
*
* @param {Object} rule
* @param {String} name
* @param {Boolean} iterate
*/
Validator.prototype._processRule = function(rule, name, iterate) {
let checks = [];
Object.keys(schema).forEach(name => {
const path = parentPath ? [parentPath, name].join(".") : name;
let rule = schema[name];
if (typeof rule === "string") {
rule = {
type: rule
};
}
if (typeof rule === "string") {
rule = {
type: rule
};
}
if (this.rules[rule.type]) {
checks.push({
fn: this.rules[rule.type],
type: rule.type,
name: name,
schema: rule,
path: path
});
} else
throw new Error("Invalid '" + rule.type + "' type in validator schema!");
if (this.rules[rule.type]) {
checks.push({
fn: this.rules[rule.type],
type: rule.type,
name: name,
schema: rule,
iterate: iterate
});
} else
throw new Error("Invalid '" + rule.type + "' type in validator schema!");
// Nested schema
if (rule.type === "object" && rule.props) {
// Compile the child schema
checks.push({
fn: this.compile(rule.props, path),
type: rule.type,
name: name,
schema: rule,
path: path
});
}
});
// Nested schema
if (rule.type === "object" && rule.props) {
// Compile the child schema
checks.push({
fn: this.compile(rule.props),
type: rule.type,
name: name,
schema: rule,
iterate: iterate
});
}
// Array schema
if (rule.type === "array" && rule.items) {
// Compile the array schema
checks.push({
fn: this._checkWrapper(this._processRule(rule.items, null, false)),
type: rule.type,
name: name,
schema: rule,
iterate: true
});
}
return checks;
};
/**
* Create a wrapper function for compiled schema.
*
* @param {Array} rules
*/
Validator.prototype._checkWrapper = function(rules) {
const self = this;
// Compiled validator function
return function(obj) {
return function(obj, _schema, pathStack) {
let errors = [];
const count = checks.length;
const count = rules.length;
for (let i = 0; i < count; i++) {
const check = checks[i];
const check = rules[i];
const schema = check.schema;
const value = obj[check.name];
let value;
let stack;
if (check.name) {
value = obj[check.name];
stack = (pathStack ? pathStack + "." : "") + check.name;
} else {
value = obj;
stack = pathStack ? pathStack : "";
}
// Check required fields
if ((value === undefined || value === null) && check.type !== "forbidden") {
if (schema.optional !== true) {
self.handleResult(errors, check.path, self.makeError("required"));
self.handleResult(errors, stack, self.makeError("required"));
} else

@@ -103,5 +155,15 @@ continue;

// Call the checker function
let res = check.fn.call(self, value, schema);
if (res !== true)
self.handleResult(errors, check.path, res);
if (check.iterate) {
const l = value.length;
for (let i = 0; i < l; i++) {
let _stack = stack + "[" + i + "]";
let res = check.fn.call(self, value[i], schema, _stack);
if (res !== true)
self.handleResult(errors, _stack, res);
}
} else {
let res = check.fn.call(self, value, schema, stack);
if (res !== true)
self.handleResult(errors, stack, res);
}
}

@@ -108,0 +170,0 @@ }

{
"name": "fastest-validator",
"version": "0.1.0",
"version": "0.3.0",
"dependencies": {

@@ -5,0 +5,0 @@ "balanced-match": {

{
"name": "fastest-validator",
"version": "0.2.0",
"version": "0.3.0",
"description": "The fastest JS validator library for NodeJS",

@@ -5,0 +5,0 @@ "main": "index.js",

@@ -14,2 +14,4 @@ "use strict";

expect(v.add).toBeInstanceOf(Function);
expect(Object.keys(v.rules).length).toBe(11);
});

@@ -79,3 +81,3 @@

expect(validFn).toHaveBeenCalledTimes(1);
expect(validFn).toHaveBeenCalledWith(5, schema.a);
expect(validFn).toHaveBeenCalledWith(5, schema.a, "a");
});

@@ -86,3 +88,2 @@

describe("Test resolveMessage", () => {
const v = new Validator();

@@ -103,5 +104,139 @@

describe("Test compile (unit test)", () => {
describe("Test compile", () => {
const v = new Validator();
v._processRule = jest.fn();
it("should call processRule", () => {
v.compile({
id: { type: "number" },
name: { type: "string", min: 5},
status: "boolean"
});
expect(v._processRule).toHaveBeenCalledTimes(3);
expect(v._processRule).toHaveBeenCalledWith({"type": "number"}, "id", false);
expect(v._processRule).toHaveBeenCalledWith({"type": "string", "min": 5}, "name", false);
expect(v._processRule).toHaveBeenCalledWith("boolean", "status", false);
});
it("should call processRule for root-level array", () => {
v._processRule.mockClear();
v.compile([{ type: "array", items: "number" }]);
expect(v._processRule).toHaveBeenCalledTimes(1);
expect(v._processRule).toHaveBeenCalledWith({"type": "array", items: "number"}, null, false);
});
it("should throw error is the schema is null", () => {
expect(() => {
v.compile();
}).toThrowError("Invalid schema!");
expect(() => {
v.compile(null);
}).toThrowError("Invalid schema!");
expect(() => {
v.compile("Nothing");
}).toThrowError("Invalid schema!");
expect(() => {
v.compile(1);
}).toThrowError("Invalid schema!");
});
it("should throw error is the schema array element count is not 1", () => {
expect(() => {
v.compile([]);
}).toThrowError();
expect(() => {
v.compile([], []);
}).toThrowError();
});
});
describe("Test _processRule", () => {
const v = new Validator();
v.compile = jest.fn();
v._checkWrapper = jest.fn();
it("should return array of rules", () => {
let res = v._processRule({ type: "number", positive: true }, "id", false);
expect(res).toBeInstanceOf(Array);
expect(res.length).toBe(1);
expect(res[0].fn).toBeInstanceOf(Function);
expect(res[0].type).toBe("number");
expect(res[0].name).toBe("id");
expect(res[0].schema).toEqual({ type: "number", positive: true });
expect(res[0].iterate).toBe(false);
});
it("should convert shorthand definition", () => {
let res = v._processRule("string", "name", false);
expect(res).toBeInstanceOf(Array);
expect(res.length).toBe(1);
expect(res[0].fn).toBeInstanceOf(Function);
expect(res[0].type).toBe("string");
expect(res[0].name).toBe("name");
expect(res[0].schema).toEqual({ type: "string" });
expect(res[0].iterate).toBe(false);
});
it("should throw error if the type is invalid", () => {
expect(() => {
v._processRule({ type: "unknow" }, "id", false);
}).toThrowError("Invalid 'unknow' type in validator schema!");
});
it("should call compile if type is object", () => {
let res = v._processRule({ type: "object", props: {
id: "number"
} }, "item", false);
expect(res).toBeInstanceOf(Array);
expect(res.length).toBe(2);
expect(res[0].fn).toBeInstanceOf(Function);
expect(res[0].type).toBe("object");
expect(res[0].name).toBe("item");
expect(res[0].iterate).toBe(false);
//expect(res[1].fn).toBeInstanceOf(Function);
expect(res[1].type).toBe("object");
expect(res[1].name).toBe("item");
expect(res[1].iterate).toBe(false);
expect(v.compile).toHaveBeenCalledTimes(1);
expect(v.compile).toHaveBeenCalledWith({id: "number"});
});
it("should call checkWrapper & processRule if type is Array", () => {
let res = v._processRule({ type: "array", items: "number" }, "list", false);
expect(res).toBeInstanceOf(Array);
expect(res.length).toBe(2);
expect(res[0].fn).toBeInstanceOf(Function);
expect(res[0].type).toBe("array");
expect(res[0].name).toBe("list");
expect(res[0].iterate).toBe(false);
//expect(res[1].fn).toBeInstanceOf(Function);
expect(res[1].type).toBe("array");
expect(res[1].name).toBe("list");
expect(res[1].iterate).toBe(true);
expect(v._checkWrapper).toHaveBeenCalledTimes(1);
expect(v._checkWrapper).toHaveBeenCalledWith([{"fn": expect.any(Function), "iterate": false, "name": null, "schema": {"type": "number"}, "type": "number"}]);
});
});
describe("Test compile (integration test)", () => {
describe("Test check generator with good obj", () => {

@@ -131,6 +266,6 @@

expect(v.rules.number).toHaveBeenCalledTimes(1);
expect(v.rules.number).toHaveBeenCalledWith(5, schema.id);
expect(v.rules.number).toHaveBeenCalledWith(5, schema.id, "id");
expect(v.rules.string).toHaveBeenCalledTimes(1);
expect(v.rules.string).toHaveBeenCalledWith("John", schema.name);
expect(v.rules.string).toHaveBeenCalledWith("John", schema.name, "name");
});

@@ -140,3 +275,3 @@

describe("Test check generator with simple def schema", () => {
describe("Test check generator with shorthand schema", () => {

@@ -165,6 +300,6 @@ const v = new Validator();

expect(v.rules.number).toHaveBeenCalledTimes(1);
expect(v.rules.number).toHaveBeenCalledWith(5, { type: "number" });
expect(v.rules.number).toHaveBeenCalledWith(5, { type: "number" }, "id");
expect(v.rules.string).toHaveBeenCalledTimes(1);
expect(v.rules.string).toHaveBeenCalledWith("John", { type: "string" });
expect(v.rules.string).toHaveBeenCalledWith("John", { type: "string" }, "name");
});

@@ -210,17 +345,2 @@

describe("Test exception for unknow types", () => {
const v = new Validator();
const schema = {
name: { type: "unknow" }
};
it("should throw exception", () => {
expect(() => {
v.compile(schema);
}).toThrowError("Invalid 'unknow' type in validator schema!");
});
});
});

@@ -325,2 +445,182 @@

});
describe("Test nested array", () => {
const v = new Validator();
let schema = {
arr1: { type: "array", items: {
type: "array", empty: false, items: {
type: "number"
}
}}
};
let check = v.compile(schema);
it("should give true if obj is valid", () => {
let obj = {
arr1: [
[
5,
10
],
[
1,
2
]
]
};
let res = check(obj);
expect(res).toBe(true);
});
it("should give error 'not a number'", () => {
let obj = {
arr1: [
[
5,
10
],
[
"1",
2
]
]
};
let res = check(obj);
expect(res.length).toBe(1);
expect(res[0].type).toBe("number");
expect(res[0].field).toBe("arr1[1][0]");
});
it("should give error 'empty array'", () => {
let obj = {
arr1: [
[
],
[
1,
2
]
]
};
let res = check(obj);
expect(res.length).toBe(1);
expect(res[0].type).toBe("arrayEmpty");
expect(res[0].field).toBe("arr1[0]");
});
});
describe("Test 3-level array", () => {
const v = new Validator();
let schema = {
arr1: { type: "array", items: {
type: "array", items: {
type: "array", items: "string"
}
}}
};
let check = v.compile(schema);
it("should give true if obj is valid", () => {
let obj = {
arr1: [
[
[ "apple", "peach" ],
[ "pineapple", "plum" ]
],
[
[ "orange", "lemon", "lime"]
]
]
};
let res = check(obj);
expect(res).toBe(true);
});
it("should give error 'not a string'", () => {
let obj = {
arr1: [
[
[ "apple", "peach" ],
[ "pineapple", "plum" ]
],
[
[ "orange", {}, "lime"]
]
]
};
let res = check(obj);
expect(res.length).toBe(1);
expect(res[0].type).toBe("string");
expect(res[0].field).toBe("arr1[1][0][1]");
});
});
describe("Test root-level array", () => {
const v = new Validator();
let schema = [{ type: "array", items: {
type: "object", props: {
id: "number",
name: "string"
}
}}];
let check = v.compile(schema);
it("should give true if obj is valid", () => {
let obj = [
{ id: 1, name: "John" },
{ id: 2, name: "Jane" },
{ id: 3, name: "James" }
];
let res = check(obj);
expect(res).toBe(true);
});
it("should give error if an element is not object", () => {
let obj = [
{ id: 1, name: "John" },
{ id: 2, name: "Jane" },
123
];
let res = check(obj);
expect(res.length).toBe(3);
expect(res[0].type).toBe("object");
expect(res[0].field).toBe("[2]");
});
it("should give error if an element is not object", () => {
let obj = [
{ id: 1, name: "John" },
{ id: 2, _name: "Jane" }
];
let res = check(obj);
expect(res.length).toBe(1);
expect(res[0].type).toBe("required");
expect(res[0].field).toBe("[1].name");
});
});
SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc