legitjs
Version:
Lightweight objects and strings validation for Node.js
358 lines (299 loc) • 7.21 kB
JavaScript
/************************
* Legit.js
*
* Lightweight objects and strings validation for Node.js
*
* Copyright (c) 2013 Daniel R. Salvadori
*/
"use strict";
/************************
* Anything Legitimizer
*/
function Any() {}
Any.prototype.test = function(value) {
return null
}
/************************
* Null Legitimizer
*/
function Null() {}
Null.prototype.test = function(value) {
if (value === null) {
return null;
}
return "Not null";
}
/************************
* Bool Legitimizer
*/
function Boolean() {
this._none = false;
}
Boolean.prototype.none = function(state) {
state = (state == undefined) ? true : state;
this._none = state;
return this;
}
Boolean.prototype.test = function(value) {
if (value == null) {
if (this._none) {
return null;
}
return "Boolean is null or undefined";
}
if (typeof(value) != "boolean") {
return "Not a boolean";
}
return null;
}
/************************
* Number Legitimizer
*/
function Number() {
this._none = false;
this._min = null;
this._max = null;
}
Number.prototype.none = function(state) {
state = (state == undefined) ? true : state;
this._none = state;
return this;
}
Number.prototype.min = function(min) {
this._min = min;
return this;
}
Number.prototype.max = function(max) {
this._max = max;
return this;
}
Number.prototype.test = function(value) {
if (value == null) {
if (this._none) {
return null;
}
return "Number is null or undefined";
}
if (typeof(value) != "number") {
return "Not a number";
}
if (this._min !== null && value < this._min) {
return "Less than minimum";
}
if (this._max !== null && value > this._max) {
return "Greater than maximum";
}
return null;
}
/************************
* String Legitimizer
*/
function String() {
this._none = false;
this._min = null;
this._max = null;
this._re = null;
}
String.prototype.none = function(state) {
state = (state == undefined) ? true : state;
this._none = state;
return this;
}
String.prototype.min = function(min) {
this._min = min;
return this;
}
String.prototype.max = function(max) {
this._max = max;
return this;
}
String.prototype.regex = function(patt) {
this._re = new RegExp(patt);
return this;
}
String.prototype.test = function(value) {
var i, l;
if (value == null) {
if (this._none) {
return null;
}
return "String is null or undefined";
}
if (typeof(value) != "string") {
return "Not a string";
}
if (this._min !== null && value.length < this._min) {
return "Less than minimum";
}
if (this._max !== null && value.length > this._max) {
return "Greater than maximum";
}
if (this._re && this._re.test(value) == false) {
return "Regular expression didn't match"
}
return null;
}
/************************
* Array Legitimizer
*/
function Array() {
this._none = false;
this._min = null;
this._max = null;
this._items = [];
this._type = null;
this._strict = false;
}
Array.prototype.none = function(state) {
state = (state == undefined) ? true : state;
this._none = state;
return this;
}
Array.prototype.min = function(min) {
this._min = min;
return this;
}
Array.prototype.max = function(max) {
this._max = max;
return this;
}
Array.prototype.item = function(schema) {
this._items.push(schema);
return this;
}
Array.prototype.type = function(schema) {
this._type = schema;
return this;
}
Array.prototype.strict = function(state) {
state = (state == undefined) ? true : state;
this._strict = state;
return this;
}
Array.prototype.test = function(value) {
var errs = [];
var error = false;
var err, i, l;
if (value == null) {
if (this._none) {
return null;
}
return "Array is null or undefined";
}
if (typeof(value) != "object") {
return "Not an array";
}
l = value.length;
if (this._type) { // If Array has same-type items
if (this._min !== null && l < this._min) {
return "Less than minimum";
}
if (this._max !== null && l > this._max) {
return "Greater than maximum";
}
for (i = 0; i < l; i++) {
err = this._type.test(value[i]);
errs.push(err);
if (err != null) {
error = true;
}
}
} else { // If Array has different-type items
for (i = 0; i < l; i++) {
if (this._items[i] == undefined) {
if (this._strict == true) {
error = true;
err = "More items than expected (Array in strict mode)"
errs.push(err);
}
break
} else {
err = this._items[i].test(value[i]);
errs.push(err);
if (err != null) {
error = true;
}
}
}
}
if (error) {return errs}
else {return null};
}
/************************
* Map Legitimizer
*/
function Map() {
this._none = false;
this._strict = false;
this._keys = {};
}
Map.prototype.none = function(state) {
state = (state == undefined) ? true : state;
this._none = state;
return this;
}
Map.prototype.strict = function(state) {
state = (state == undefined) ? true : state;
this._strict = state;
return this;
}
Map.prototype.key = function(name, schema, req) {
if (req === undefined) {
req = true;
}
this._keys[name] = {schema: schema, req: req};
return this;
}
Map.prototype.test = function(value) {
var errs = {};
var error = false;
var err, el;
var kinfo;
if (value == null) {
if (this._none) {
return null;
}
return "Map is null or undefined";
}
if (typeof(value) != "object") {
return "Not a map";
}
for (el in this._keys) {
kinfo = this._keys[el];
if (value[el] === undefined) {
if (kinfo.req) {
err = "Missing this key";
}
} else {
err = kinfo.schema.test(value[el]);
}
errs[el] = err;
if (err != null) {
error = true;
}
}
if (this._strict) {
for (el in value) {
if (this._keys[el] == undefined) {
err = "Unexpected key (Map in strict mode)"
errs[el] = err;
error = true;
}
}
}
if (error) {return errs}
else {return null};
}
/************************
* Node.js module exports
*/
module.exports = {
Null : function() {return new Null()},
Any : function() {return new Any()},
Boolean : function() {return new Boolean()},
Number : function() {return new Number()},
String : function() {return new String()},
Array : function() {return new Array()},
Map : function() {return new Map()},
mize : function(l, v) {return l.test(v)}
}