diff --git a/bin/schema-web.js b/bin/schema-web.js deleted file mode 100644 index f2530a7..0000000 --- a/bin/schema-web.js +++ /dev/null @@ -1,420 +0,0 @@ -(function() -{ - var Rules = function(param, rules) - { - this.param = param; - this.rules = rules; - }; - - Rules.prototype.Error = function(message, rule, value) - { - switch(typeof(this.rules.error)) - { - case 'string': - message = this.rules.error; - break; - - case 'object': - - if(this.rules.error[rule]) - { - message = this.rules.error[rule]; - } - else if(this.rules.error['default']) - { - message = this.rules.error['default']; - } - - break; - } - - if(_.isString(value)) - message = message.replace(/%v/, value.toString()); - - if(_.isString(rule)) - message = message.replace(/%r/, rule); - - return message.replace(/%p/, this.param).replace(/%v/, "value").replace(/%r/, "rule"); - }; - - Rules.prototype.apply = function(value) - { - if(_.isEmpty(value) && !_.isUndefined(this.rules['default'])) - { - value = this.rules['default']; - } - - if(this.rules.required) - { - if(this.rules.required && _.isUndefined(value)) - { - throw this.Error("%p is a required parameter", "required", value); - } - } - // if value is not required and is undefined, no more rules need to be run - else if(_.isUndefined(value)) - return value; - - if(this.rules.filters) - { - value = this.filter(value); - } - - if(this.rules.type) - { - if(typeof(this.rules.type) == "string" && typeof(is[this.rules.type]) == "function") - { - if(!is[this.rules.type](value)) - throw this.Error("%p is not a " + this.rules.type, "type", value); - } - else if(typeof(this.rules.type == "function")) - { - if(!this.rules.type(value)) - throw this.Error("%p is not a valid type", "type", value); - } - else - { - throw this.Error("%p is not a valid type", "type", value); - } - } - - if(this.rules.properties) - { - this.check(value); - } - - return value; - }; - - Rules.prototype.filter = function(value) - { - switch(typeof(this.rules.filters)) - { - case 'function': - value = this.rules.filters(value); - break; - - case 'string': - - if(typeof(filters[this.rules.filters]) === 'function') - { - value = filters[this.rules.filters](value); - } - - break; - - case 'object': - - if(_.isArray(this.rules.filters)) - { - this.rules.filters.forEach(function(filter) { value = filters[filter](value); }); - } - - break; - } - - return value; - }; - - Rules.prototype.check = function(value) - { - switch(typeof(this.rules.properties)) - { - case 'function': - - if(!this.rules.properties(value)) - throw this.Error("%p is not valid"); - - break; - - case 'object': - - var properties = _.keys(this.rules.properties); - - for(var i = 0; i < properties.length; i++) - { - var property = properties[i]; - - if(typeof(checks[property]) === "function") - { - var args = this.rules.properties[property]; - - if(!checks[property].apply(null, [value, args])) - throw this.Error("%p failed %r with %v", property); - } - else if(typeof(this.rules.properties[property]) === "function") - { - if(!this.rules.properties[property].apply(null, [value])) - throw this.Error("%p failed on %r with %v", property); - } - } - - break; - } - }; - - var checks = - { - 'max': function(value, length) - { - if(_.isArray(value) || typeof(value) == "string") - { - return value.length <= length; - } - else if(typeof(value) == "number") - { - return value <= length; - } - else - { - return false; - } - }, - - 'min': function(value, length) - { - if(_.isArray(value) || typeof(value) == "string") - { - return value.length >= length; - } - else if(typeof(value) == "number") - { - return value >= length; - } - else - { - return false; - } - }, - - 'regex': function(value, regex) - { - return regex.test(value); - }, - - 'in': function(value, list) - { - return list.indexOf(value) != -1; - } - }; - - var is = - { - 'string+': function(value) - { - return typeof(value) == 'string' && value !== ""; - }, - - 'string': function(value) - { - return typeof(value) == 'string'; - }, - - 'alphanum': function(value) - { - return (/^[a-zA-Z0-9]+$/i).test(value); - }, - - 'alpha': function(value) - { - return (/^[a-zA-Z]+$/i).test(value); - }, - - 'object': function(value) - { - return typeof(value) == 'object' && !_.isArray(value); - }, - - 'array': function(value) - { - return _.isArray(value); - }, - - 'date': function(value) - { - // getTime() allows us to check if date is valid - return _.isDate(value) && !isNaN(value.getTime()); - }, - - 'number': function(value) - { - return typeof(value) == 'number' && !isNaN(value); - }, - - 'int': function(value) - { - return typeof(value) == 'number' && value % 1 === 0 && !isNaN(value); - }, - - 'boolean': function(value) - { - return _.isBoolean(value); - }, - - 'float': function(value) - { - return typeof(value) == 'number' && !isNaN(value); - }, - - 'email': function(value) - { - return (/[a-z0-9!#$%&'*+\/=?\^_`{|}~\-]+(?:\.[a-z0-9!#$%&'*+\/=?\^_`{|}~\-]+)*@(?:[a-z0-9](?:[a-z0-9\-]*[a-z0-9])?\.)+[a-z0-9](?:[a-z0-9\-]*[a-z0-9])?/).test(value); - }, - - 'url': function(value) - { - return (/^(http(s)?:\/\/)?([\w\-]+\.{1})*(([\w\-]*){1}(\.{1}[A-Za-z]{2,4}){1}){1}(\:{1}\d*)?([\?\/|\#]+[\@\~\;\+\'\#\,\.\%\-\/\&\?\=\w\$\s]*)*$/i).test(value); - }, - - 'zipcode': function(value) - { - return (/\d{5}/).test(value); - } - }; - - var filters = - { - 'toInt': function(value) - { - return parseInt(value, 10); - }, - - 'toFloat': function(value) - { - return parseFloat(value, 10); - }, - - 'toString': function(value) - { - return value.toString(); - }, - - 'toDate': function(value) - { - return new Date(value); - }, - - 'toBoolean': function(value) - { - if(value === 1 || value === true || /true|on|yes|1/.test(value)) - return true; - else if(value === 0 || value === false || /false|off|no|0/.test(value)) - return false; - else - return value; - }, - - 'trim': function(value) - { - return _.isString(value) ? value.replace(/^\s\s*/, '').replace(/\s\s*$/, '') : value; - }, - - 'lowercase': function(value) - { - return _.isString(value) ? value.toLowerCase() : value; - }, - - 'uppercase': function(value) - { - return _.isString(value) ? value.toUpperCase() : value; - } - }; - - var rules = - { - create: function(param, rules) { return new Rules(param, rules); }, - types: is, - filters: filters, - properties: checks - }; - - var Schema = function(schema) - { - this.schema = schema; - }; - - Schema.prototype.validate = function(data) - { - var params = _.keys(this.schema); - var errors = {}; - var values = {}; - var value; - var get = typeof(data) == "function" ? data : function(p) { return data[p]; }; - - for(var i = 0; i < params.length; i++) - { - var schema = this.schema[params[i]]; - - try - { - // if undefined, don't store it. - value = rules.create(params[i], schema).apply(get(params[i])); - - if(!_.isUndefined(value)) - { - values[params[i]] = value; - } - - // does this rule contain embedded schemas - if(typeof(schema.schema) == "object" && !_.isArray(schema.schema) && _.keys(schema.schema).length && !_.isUndefined(values[params[i]])) - { - if(schema.type == "object") - { - _.keys(schema.schema).forEach(function(param) - { - try - { - // if undefined, don't store it - value = rules.create(params[i] + "." + param, schema.schema[param]).apply(get(params[i])[param]); - - if(!_.isUndefined(value)) - { - values[params[i]][param] = value; - } - } - catch(error) - { - if(!errors[params[i]] || typeof(errors[params[i]]) != 'object') - errors[params[i]] = {}; - - errors[params[i]][param] = error; - } - }); - } - else if(schema.type == "array") - { - values[params[i]].forEach(function(value, index) - { - try - { - // if not required and undefined, don't store in values! - values[params[i]][index] = rules.create(params[i] + "[" + index + "]", schema.schema).apply(value); - } - catch(error) - { - if(!_.isArray(errors[params[i]])) - errors[params[i]] = []; - - errors[params[i]][index] = error; - } - }); - } - } - } - catch(error) - { - errors[params[i]] = error; - } - } - - return {data:values, errors:errors, valid:_.keys(errors).length === 0}; - }; - - _.schema = - { - test: function(value, schema) { return (new Schema({input:schema})).validate({input:value}); }, - create: function(schema) { return new Schema(schema);}, - rules: rules - }; - -})(); diff --git a/lib/rules.js b/lib/rules.js index 23e9200..bba05cb 100644 --- a/lib/rules.js +++ b/lib/rules.js @@ -2,31 +2,31 @@ var _ = require('underscore'); var Rules = function(param, rules) { - this.param = param; - this.rules = rules; + this.param = param; + this.rules = rules; }; Rules.prototype.Error = function(message, rule, value) { - switch(typeof(this.rules.error)) - { - case 'string': - message = this.rules.error; - break; + switch(typeof(this.rules.error)) + { + case 'string': + message = this.rules.error; + break; - case 'object': + case 'object': - if(this.rules.error[rule]) - { - message = this.rules.error[rule]; - } - else if(this.rules.error['default']) - { - message = this.rules.error['default']; - } + if(this.rules.error[rule]) + { + message = this.rules.error[rule]; + } + else if(this.rules.error['default']) + { + message = this.rules.error['default']; + } - break; - } + break; + } if(_.isString(value)) message = message.replace(/%v/, value.toString()); @@ -34,34 +34,34 @@ Rules.prototype.Error = function(message, rule, value) if(_.isString(rule)) message = message.replace(/%r/, rule); - return message.replace(/%p/, this.param).replace(/%v/, "value").replace(/%r/, "rule"); + return message.replace(/%p/, this.param).replace(/%v/, "value").replace(/%r/, "rule"); }; Rules.prototype.apply = function(value) { - if(_.isEmpty(value) && !_.isUndefined(this.rules['default'])) - { - value = this.rules['default']; - } + if(_.isEmpty(value) && !_.isUndefined(this.rules['default'])) + { + value = this.rules['default']; + } - if(this.rules.required) - { - if(this.rules.required && _.isUndefined(value)) - { - throw this.Error("%p is a required parameter", "required", value); - } - } + if(this.rules.required) + { + if(this.rules.required && _.isUndefined(value)) + { + throw this.Error("%p is a required parameter", "required", value); + } + } // if value is not required and is undefined, no more rules need to be run else if(_.isUndefined(value)) return value; - if(this.rules.filters) - { - value = this.filter(value); - } + if(this.rules.filters) + { + value = this.filter(value); + } - if(this.rules.type) - { + if(this.rules.type) + { if(typeof(this.rules.type) == "string" && typeof(is[this.rules.type]) == "function") { if(!is[this.rules.type](value)) @@ -76,87 +76,87 @@ Rules.prototype.apply = function(value) { throw this.Error("%p is not a valid type", "type", value); } - } + } - if(this.rules.properties) - { - this.check(value); - } + if(this.rules.properties) + { + this.check(value); + } - return value; + return value; }; Rules.prototype.filter = function(value) { - switch(typeof(this.rules.filters)) - { - case 'function': - value = this.rules.filters(value); - break; + switch(typeof(this.rules.filters)) + { + case 'function': + value = this.rules.filters(value); + break; - case 'string': + case 'string': - if(typeof(filters[this.rules.filters]) === 'function') - { - value = filters[this.rules.filters](value); - } + if(typeof(filters[this.rules.filters]) === 'function') + { + value = filters[this.rules.filters](value); + } - break; + break; - case 'object': + case 'object': - if(_.isArray(this.rules.filters)) - { - this.rules.filters.forEach(function(filter) { value = filters[filter](value); }); - } + if(_.isArray(this.rules.filters)) + { + this.rules.filters.forEach(function(filter) { value = filters[filter](value); }); + } - break; - } + break; + } - return value; + return value; }; Rules.prototype.check = function(value) { - switch(typeof(this.rules.properties)) - { - case 'function': + switch(typeof(this.rules.properties)) + { + case 'function': - if(!this.rules.properties(value)) - throw this.Error("%p is not valid"); + if(!this.rules.properties(value)) + throw this.Error("%p is not valid"); - break; + break; - case 'object': - - var properties = _.keys(this.rules.properties); + case 'object': + + var properties = _.keys(this.rules.properties); - for(var i = 0; i < properties.length; i++) - { - var property = properties[i]; + for(var i = 0; i < properties.length; i++) + { + var property = properties[i]; - if(typeof(checks[property]) === "function") - { - var args = this.rules.properties[property]; + if(typeof(checks[property]) === "function") + { + var args = this.rules.properties[property]; - if(!checks[property].apply(null, [value, args])) - throw this.Error("%p failed %r with %v", property); - } - else if(typeof(this.rules.properties[property]) === "function") - { - if(!this.rules.properties[property].apply(null, [value])) - throw this.Error("%p failed on %r with %v", property); - } - } + if(!checks[property].apply(null, [value, args])) + throw this.Error("%p failed %r with %v", property); + } + else if(typeof(this.rules.properties[property]) === "function") + { + if(!this.rules.properties[property].apply(null, [value])) + throw this.Error("%p failed on %r with %v", property); + } + } - break; - } + break; + } }; var checks = { - 'max': function(value, length) - { + 'max': function(value, length) + { if(_.isArray(value) || typeof(value) == "string") { return value.length <= length; @@ -169,10 +169,10 @@ var checks = { return false; } - }, + }, - 'min': function(value, length) - { + 'min': function(value, length) + { if(_.isArray(value) || typeof(value) == "string") { return value.length >= length; @@ -185,30 +185,30 @@ var checks = { return false; } - }, + }, - 'regex': function(value, regex) - { - return regex.test(value); - }, + 'regex': function(value, regex) + { + return regex.test(value); + }, - 'in': function(value, list) - { - return list.indexOf(value) != -1; - } + 'in': function(value, list) + { + return list.indexOf(value) != -1; + } }; var is = { - 'string+': function(value) - { - return typeof(value) == 'string' && value !== ""; - }, + 'string+': function(value) + { + return typeof(value) == 'string' && value.length && !(/\s+/.test(value)); + }, 'string': function(value) - { - return typeof(value) == 'string'; - }, + { + return typeof(value) == 'string'; + }, 'alphanum': function(value) { @@ -220,104 +220,104 @@ var is = return (/^[a-zA-Z]+$/i).test(value); }, - 'object': function(value) - { - return typeof(value) == 'object' && !_.isArray(value); - }, + 'object': function(value) + { + return typeof(value) == 'object' && !_.isArray(value); + }, - 'array': function(value) - { - return _.isArray(value); - }, + 'array': function(value) + { + return _.isArray(value); + }, - 'date': function(value) - { + 'date': function(value) + { // getTime() allows us to check if date is valid - return _.isDate(value) && !isNaN(value.getTime()); - }, + return _.isDate(value) && !isNaN(value.getTime()); + }, - 'number': function(value) - { + 'number': function(value) + { return typeof(value) == 'number' && !isNaN(value); - }, + }, - 'int': function(value) - { - return typeof(value) == 'number' && value % 1 === 0 && !isNaN(value); - }, + 'int': function(value) + { + return typeof(value) == 'number' && value % 1 === 0 && !isNaN(value); + }, - 'boolean': function(value) - { - return _.isBoolean(value); - }, + 'boolean': function(value) + { + return _.isBoolean(value); + }, - 'float': function(value) - { - return typeof(value) == 'number' && !isNaN(value); - }, + 'float': function(value) + { + return typeof(value) == 'number' && !isNaN(value); + }, - 'email': function(value) - { - return (/[a-zA-Z0-9!#$%&'*+\/=?\^_`{|}~\-]+(?:\.[a-zA-Z0-9!#$%&'*+\/=?\^_`{|}~\-]+)*@(?:[a-zA-Z0-9](?:[a-zA-Z0-9\-]*[a-zA-Z0-9])?\.)+[a-zA-Z0-9](?:[a-zA-Z0-9\-]*[a-zA-Z0-9])?/).test(value); - }, + 'email': function(value) + { + return (/[a-zA-Z0-9!#$%&'*+\/=?\^_`{|}~\-]+(?:\.[a-zA-Z0-9!#$%&'*+\/=?\^_`{|}~\-]+)*@(?:[a-zA-Z0-9](?:[a-zA-Z0-9\-]*[a-zA-Z0-9])?\.)+[a-zA-Z0-9](?:[a-zA-Z0-9\-]*[a-zA-Z0-9])?/).test(value); + }, - 'url': function(value) - { - return (/^(http(s)?:\/\/)?([\w\-]+\.{1})*(([\w\-]*){1}(\.{1}[A-Za-z]{2,4}){1}){1}(\:{1}\d*)?([\?\/|\#]+[\@\~\;\+\'\#\,\.\%\-\/\&\?\=\w\$\s]*)*$/i).test(value); - }, + 'url': function(value) + { + return (/^(http(s)?:\/\/)?([\w\-]+\.{1})*(([\w\-]*){1}(\.{1}[A-Za-z]{2,4}){1}){1}(\:{1}\d*)?([\?\/|\#]+[\@\~\;\+\'\#\,\.\%\-\/\&\?\=\w\$\s]*)*$/i).test(value); + }, - 'zipcode': function(value) - { - return (/\d{5}/).test(value); - } + 'zipcode': function(value) + { + return (/\d{5}/).test(value); + } }; var filters = { - 'toInt': function(value) - { - return parseInt(value, 10); - }, + 'toInt': function(value) + { + return parseInt(value, 10); + }, - 'toFloat': function(value) - { - return parseFloat(value, 10); - }, + 'toFloat': function(value) + { + return parseFloat(value, 10); + }, - 'toString': function(value) - { - return value.toString(); - }, + 'toString': function(value) + { + return value.toString(); + }, - 'toDate': function(value) - { - return new Date(value); - }, + 'toDate': function(value) + { + return new Date(value); + }, - 'toBoolean': function(value) - { - if(value === 1 || value === true || /true|on|yes|1/.test(value)) - return true; - else if(value === 0 || value === false || /false|off|no|0/.test(value)) - return false; - else - return value; - }, + 'toBoolean': function(value) + { + if(value === 1 || value === true || /true|on|yes|1/.test(value)) + return true; + else if(value === 0 || value === false || /false|off|no|0/.test(value)) + return false; + else + return value; + }, - 'trim': function(value) - { - return _.isString(value) ? value.replace(/^\s\s*/, '').replace(/\s\s*$/, '') : value; - }, + 'trim': function(value) + { + return _.isString(value) ? value.replace(/^\s\s*/, '').replace(/\s\s*$/, '') : value; + }, - 'lowercase': function(value) - { - return _.isString(value) ? value.toLowerCase() : value; - }, + 'lowercase': function(value) + { + return _.isString(value) ? value.toLowerCase() : value; + }, - 'uppercase': function(value) - { - return _.isString(value) ? value.toUpperCase() : value; - } + 'uppercase': function(value) + { + return _.isString(value) ? value.toUpperCase() : value; + } }; exports.create = function(param, rules) { return new Rules(param, rules); }; diff --git a/schema.js b/schema.js index 5a834b6..98b55bb 100644 --- a/schema.js +++ b/schema.js @@ -1,6 +1 @@ -var schema = require("./lib/schema.js"); - -Object.keys(schema).forEach(function(one) -{ - exports[one] = schema[one]; -}); +module.exports = require("./lib/schema.js"); diff --git a/test/default.js b/test/default.js index 2dcde72..f7476ad 100644 --- a/test/default.js +++ b/test/default.js @@ -1,7 +1,7 @@ describe("default schemas", function() { - var schemajs = require('../schema'); - var expect = require('chai').expect; + var schemajs = require('../schema'); + var expect = require('chai').expect; it("default values", function() { diff --git a/test/types.js b/test/types.js index 882659c..84dcf79 100644 --- a/test/types.js +++ b/test/types.js @@ -29,12 +29,14 @@ describe("schema types", function() var input1 = schema.validate({input: 'username'}); var input2 = schema.validate({input: 112390123}); var input3 = schema.validate({input: ''}); - var input4 = schema.validate({}); + var input4 = schema.validate({input: " "}); + var input5 = schema.validate({}); expect(input1.valid).to.be.ok; expect(!input2.valid).to.be.ok; expect(!input3.valid).to.be.ok; - expect(input4.valid).to.be.ok; + expect(!input4.valid).to.be.ok; + expect(input5.valid).to.be.ok; }); it("number", function()