node-data-validator
Version:
Validate object data in JS based on a given data model
206 lines (168 loc) • 6.01 kB
JavaScript
/**
* Checks if object is valid with model
* @param {object} input object to check
* @param {object} model model to check against
* @returns {boolean} is object valid
*/
const Validator = (input, model) => {
/**
* Recursively check if object is valid
* @param {object} input object to check
* @param {object} model model to check against
*/
function recursion(input, model) {
// Check if input or model is null
if (!input || !model) {
return false;
}
// Loop through model
for(let key in model) {
// Check if key is in object if not detailed value
if(!(model[key] instanceof DetailedValue)) {
if(!input.hasOwnProperty(key)) {
// If not, set validity to false and abort
return false;
}
}
// Get type of key
let type = model[key];
let data = input[key];
// Check model type
switch(type) {
// Is String?
case String:
if(typeof data !== "string") return false;
break;
// Is Number?
case Number:
if(isNaN(data) || typeof data !== "number") return false;
break;
// Is Boolean?
case Boolean:
if(typeof data !== "boolean") return false;
break;
// Is Array?
case Array:
if(!Array.isArray(data)) return false;
break;
// Is Object?
case Object:
if(!(data instanceof Object)) return false;
break;
default:
// Check if is detailed value
if(type instanceof DetailedValue) {
const result = type.validate(data);
if(typeof result !== "undefined") return false;
break;
}
// Check if object
if(typeof type !== "object") return false;
// Check if array
if(Array.isArray(type) && !Array.isArray(data)) return false;
// recursion on array
if(Array.isArray(type) && Array.isArray(data)) {
// loop data
for(let key in data) {
// loop the data with the first entry of the model
const result = recursion([data[key]], [type[0]]);
// Return if not valid
if(typeof result !== "undefined") return false;
}
} else {
// Check recursively
const result = recursion(data, type);
// Return if not valid
if(typeof result !== "undefined") return false;
}
break;
}
}
}
// Start recursion & get result
const result = (typeof recursion(input, model) === "undefined" ? true : false);
// Return result
return result;
}
/**
* Detailed Value Class for validating data
*/
class DetailedValue {
/**
* Create a new DetailedValue
* @param {primitive} type primitive type of value
* @param {*} options options for value
*/
constructor(type, { required = true, min = null, max = null, isEmail = false} = {}) {
this.type = type;
this.required = required;
this.min = min;
this.max = max;
this.isEmail = isEmail;
}
/**
* Validates the object against the detailed value
* @param {object} input object to check
*/
validate(input) {
// Validate input as usual
const validation = Validator([input], [this.type]);
// Check if required
if(!this.required && !input && !validation) {
return;
}
if(this.required && !input && !validation) {
return false;
}
// check length by type
let length = 0;
if([String, Array].includes(this.type) || Array.isArray(this.type)) {
length = input.length;
} else if(this.type === Number) {
length = input;
}
// Check if length is min valid
if(this.min != undefined && length < this.min) {
return false;
}
// Check if length is max valid
if(this.max != undefined && length > this.max) {
return false;
}
// Check if is email
if(this.isEmail) {
if(this.required || input) {
if(!this.validateEmail(input, true)) {
return false;
}
}
}
// Return result
if(!validation) {
return false;
}
}
/**
* Checks if the value is valid email
* @param {string} email email to check
* @param {boolean} unicode use unicode
* @returns {boolean} is the email valid
*/
validateEmail(email, unicode = false) {
// Create Regex
let re = /^(([^<>()[\]\\.,;:\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,}))$/;
// Change Regex if unicode is allowed
if(unicode) re = /^(([^<>()[\]\.,;:\s@\"]+(\.[^<>()[\]\.,;:\s@\"]+)*)|(\".+\"))@(([^<>()[\]\.,;:\s@\"]+\.)+[^<>()[\]\.,;:\s@\"]{2,})$/i;
// Return result of check
return re.test(String(email).toLowerCase());
}
}
/*
EXPORT CLASS IF NODE ENV
*/
if (typeof module !== "undefined" && module.exports){
module.exports = {
Validator: Validator,
DetailedValue: DetailedValue
}
}