UNPKG

validify.js

Version:

Flexible validation framework

987 lines (886 loc) 35.4 kB
!function(e){if("object"==typeof exports)module.exports=e();else if("function"==typeof define&&define.amd)define(e);else{var f;"undefined"!=typeof window?f=window:"undefined"!=typeof global?f=global:"undefined"!=typeof self&&(f=self),f.validify=e()}}(function(){var define,module,exports;return (function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);throw new Error("Cannot find module '"+o+"'")}var f=n[o]={exports:{}};t[o][0].call(f.exports,function(e){var n=t[o][1][e];return s(n?n:e)},f,f.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(_dereq_,module,exports){ /*jshint maxlen: 130 */ module.exports = [ { name: 'present', aliases: ['notNull'], description: 'Determine if a value is present/not null', type: 'mixed', args: [ { name: 'test', description: 'The test for presence should match this (e.g. present==true)', type: 'boolean', default: true } ], evaluate: function(v, test) { //console.log('present()', v, test); return test ? v != null : v == null; } }, { name: 'defined', description: 'Determine if a value is defined (may still be null)', type: 'mixed', evaluate: function(v) { return v !== undefined; } }, { name: 'empty', aliases: ['blank'], description: 'Determine if a value is empty/blank (includes null & undefined)', type: 'mixed', evaluate: function(v) { return (v == null || (v + '').replace(/ /g, '') === ''); } }, { name: 'null', description: 'Determine if a value is null', type: 'mixed', evaluate: function(v) { return v == null; } }, { name: 'undefined', description: 'Determine if a value is undefined', type: 'mixed', evaluate: function(v) { return v === undefined; } }, { name: 'equals', aliases: ['eq'], description: 'Determine if a value is equal to the specified value. Equivalent to a simple === javascript comparison.', type: 'mixed', args: [ { name: 'value', aliases: ['val'], description: 'The target value to match the provided value against', type: 'mixed' } ], evaluate: function(v, value) { // TODO - provide a robust eq comparison for objects as well //console.log('equals() comparing', v, value); return v === value; } }, { name: 'in', description: 'Determine if a value is in the specified array', type: 'mixed', args: [ { name: 'list', aliases: ['array', 'val', 'value'], description: 'The target list to lookup the value in', type: 'mixed' } ], evaluate: function(v, list) { // TODO - provide a robust eq comparison for objects as well //console.log('in() finding', v, 'in', list); if (list == null || list.length === 0) { return false; } for (var i=0; i < list.length; i++) { if (v === list[i]) { return true; } } return false; } } ]; },{}],2:[function(_dereq_,module,exports){ /*jshint maxlen: 130 */ (function () { var emailUserRe = '[a-z0-9\\u007F-\\uffff!#$%&\'*+\\/=?^_`{|}~-]+(?:\\.[a-z0-9\\u007F-\\uffff!#$%&\'*+\\/=?^_`{|}~-]+)*'; var emailDomainRe = '(?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\\.)+'; var emailTldRe = '[a-z0-9](?:[a-z0-9-]*[a-z0-9])?'; module.exports = [{ name: 'email', aliases: ['isEmail'], description: 'Determine if a value is a valid email address', type: 'string', args: [ { name: 'tlds', description: 'List of valid Top Level Domains', type: '[string]', default: [] } ], evaluate: function (v, tlds) { //console.log('email', value, tlds); var re = '^' + emailUserRe + '@' + emailDomainRe; /*jshint -W110*/ if (tlds != null && tlds.length > 0) { re += "(" + tlds.join("|") + ")"; } else { re += emailTldRe; } re += '$'; //console.log("using email regex", re); return v.match(new RegExp(re)) != null; } }]; })(); },{}],3:[function(_dereq_,module,exports){ // Load all validators exports.basic = _dereq_('./basic'); exports.number = _dereq_('./number'); exports.string = _dereq_('./string'); exports.email = _dereq_('./email'); },{"./basic":1,"./email":2,"./number":4,"./string":5}],4:[function(_dereq_,module,exports){ /*jshint maxlen: 130 */ module.exports = [ { name: 'number', aliases: ['isNumber'], description: 'Determine if a value is a number', type: 'mixed', evaluate: function(v) { return typeof v === 'number'; } }, { name: 'integer', aliases: ['int', 'isInt', 'isInteger'], description: 'Determine if a value is an integer', type: 'number', args: [ { name: 'radix', description: 'The radix for the number to parse', type: 'number', default: 10 } ], evaluate: function (v, radix) { return !isNaN(v) && parseInt(Number(v), radix) === v && (v + '').replace(/ /g, '') !== ''; } }, { name: 'float', aliases: ['isFloat'], description: 'Determine if a value is a float', type: 'number', evaluate: function (v) { //console.log(v, typeof v, Number(v), parseFloat(Number(v))); return !isNaN(v) && parseInt(Number(v), 10) !== v && (v + '').replace(/ /g, '') !== ''; } }, { name: 'between', aliases: ['range', 'min', 'max', 'lessThan', 'greaterThan', 'lessThanOrEqualTo', 'greaterThanOrEqualTo'], description: 'Determine if a numeric value is within the specified range', type: 'number', failureMessages: { default: { between: 'The value \'%{value}\' is not %{name} %{min} and %{max} (inclusive %{inclusive})', range: 'The value \'%{value}\' is not %{name} %{min} and %{max} (inclusive %{inclusive})', min: 'The value \'%{value}\' is not %{name} %{min}', greaterThan: 'The value \'%{value}\' is not %{name} %{min}', greaterThanOrEqualTo: 'The value \'%{value}\' is not %{name} %{min}', max: 'The value \'%{value}\' is not %{name} %{max}', lessThan: 'The value \'%{value}\' is not %{name} %{max}', lessThanOrEqualTo: 'The value \'%{value}\' is not %{name} %{max}' } }, args: [ { name: 'min', aliases: ['minimum'], description: 'The number the value must be greater than or equal to', type: 'number' }, { name: 'max', aliases: ['maximum'], description: 'The number the value must be less than or equal to', type: 'number' }, { name: 'inclusive', description: 'Whether or not the min & max are inclusive as valid values', default: true, aliasDefaults: { 'greaterThan': false, 'lessThan': false }, type: 'boolean' } ], evaluate: function (v, min, max, inclusive) { //console.log('between value', v, 'min', min, 'max', max, 'inclusive', inclusive); return ((min == null || (inclusive && v >= min) || (!inclusive && v > min)) && (max == null || (inclusive && v <= max) || (!inclusive && v < max))); } }, { name: 'odd', description: 'Determine if a value is an odd integer', type: 'number', evaluate: function (v) { return !isNaN(v) && v != null && v % 2 === 1; } }, { name: 'even', description: 'Determine if a value is an even integer', type: 'number', evaluate: function (v) { return !isNaN(v) && v != null && v % 2 === 0; } }, { name: 'multipleOf', description: 'Determine if a value is a multiple of another integer', type: 'number', args: [ { name: 'factor', description: 'The number the value must be a multiple of', type: 'number' } ], evaluate: function (v, factor) { return !isNaN(v) && v % factor === 0; } }, { name: 'factor', description: 'Determine if a value is a factor of another integer', type: 'number', args: [ { name: 'multiple', description: 'The number the value must be a factor of', type: 'number' } ], evaluate: function (v, multiple) { return !isNaN(v) && multiple % v === 0; } } ]; },{}],5:[function(_dereq_,module,exports){ /*jshint maxlen: 130 */ module.exports = [ { name: 'length', aliases: ['strlen'], description: 'Ensure the length of the string is within range', type: 'string', args: [ { name: 'length', aliases: ['len'], description: 'The length must be exactly this many characters long', type: 'number' }, { name: 'min', description: 'The length must be at least min characters long', type: 'number' }, { name: 'max', description: 'The length must be at least max characters long', type: 'number' }, { name: 'inclusive', description: 'Whether or not the min & max length are inclusive as valid values', default: true, type: 'boolean' } ], /*jshint -W074 */ /*jshint -W072 */ evaluate: function (v, length, min, max, inclusive) { //console.log('length value', v, 'length', length, 'min', min, 'max', max, 'inclusive', inclusive); // empty is length 0, set to empty string to prevent undefined errors if (v == null) { v = ''; } // if length is specified, set min and max & inclusive must be true if (length != null) { min = max = length; inclusive = true; } return ((min == null || (inclusive && v.toString().length >= min) || (!inclusive && v.toString().length > min)) && (max == null || (inclusive && v.toString().length <= max) || (!inclusive && v.toString().length < max))); } }, { name: 'matches', aliases: ['format'], description: 'Ensure the string matches the given pattern', type: 'string', args: [ { name: 'pattern', aliases: ['format'], description: 'The pattern the string must match', type: 'string' } ], evaluate: function (v, pattern) { if (v == null) { v = ''; } return v.match(pattern) == null ? false : true; } } ]; },{}],6:[function(_dereq_,module,exports){ /*jshint maxlen: 130 */ 'use strict'; (function () { var STRIP_COMMENTS = /((\/\/.*$)|(\/\*[\s\S]*?\*\/))/mg; var ARGUMENT_NAMES = /([^\s,]+)/g; // shim for testing, since PhantomJS doesn't support bind yet Function.prototype.bind = Function.prototype.bind || function (thisp) { var fn = this; return function () { return fn.apply(thisp, arguments); }; }; /** * Helper method to get the list of parameter names for a function * @param func the function to introspect and retrieve parameter name for * @returns {*} */ function getParamNames(func) { if (func) { var fnStr = func.toString().replace(STRIP_COMMENTS, ''); var result = fnStr.slice(fnStr.indexOf('(') + 1, fnStr.indexOf(')')).match(ARGUMENT_NAMES); if (result === null) { result = []; } return result; } return []; } /*jshint -W055 */ function validify() { } // reference to the instance we return, so we can pass it into validators that need it var validifyInstance; /** * Class the represents a validator * @param validator * @constructor */ function Validator(validator) { this.name = validator.name; this.description = validator.description; this.type = validator.type; this.args = validator.args; this.evaluate = validator.evaluate; this.aliases = validator.aliases; this.failureMessages = validator.failureMessages; } /** * Prototype that wraps the evaluate call to provide argument injection * @param name the name/alias of the function * @param value the value being validated * @param options the map of named options for the validation. Refer to the specific validator for details. * @returns boolean whether or not the validate */ Validator.prototype.validate = /*jshint -W074*/function (name, value, options) { var i, j; //console.log('validate(proto): name', name, 'value', value, 'options', options); if (this.evaluate == null) { //console.error('validate for', name, 'has no evaluate', this.evaluate); throw new Error('no evaluate function found for '+name); } // validator options var type = this.type ? this.type : 'mixed'; var failOnWrongType = (options && options.failOnWrongType != null) ? options.failOnWrongType: this.failOnWrongType; var failOnMissing = (options && options.failOnMissing != null) ? options.failOnMissing: this.failOnMissing; var failOnEmpty = (options && options.failOnEmpty != null) ? options.failOnEmpty: this.failOnEmpty; var trimStrings = (options && options.trimStrings != null) ? options.trimStrings: this.trimStrings; // test the value for correct type if (failOnWrongType && typeof value !== type) { //console.error(failOnWrongType, options, this.failOnWrongType); //console.error('invalid type \'' + typeof value + '\' for value \'' + value + '\' (should be \'' + type + '\')'); //console.log('process failure for invalidType', name); processFailure(this, 'invalidType', name, value, options); return false; } // fail of the value is missing if (failOnMissing && value === undefined) { processFailure(this, 'missingValue', name, value, options); return false; } // fail if the value is empty if (failOnEmpty && (value === undefined || value === null || value === '' || (typeof value === 'object' && Object.keys(value).length === 0) || Array.isArray(value) && value.length === 0)) { processFailure(this, 'emptyValue', name, value, options); return false; } // TODO - cache these, so that we don't re-parse every single time we do a validation var args = [ trimStrings && type === 'string' && typeof value === 'string' ? value.trim() : value ]; var params = getParamNames(this.evaluate); // start past the value and inject values for (i = 1; i < params.length; i++) { var param = params[i], option = options ? options[param] : undefined; if (param === 'validify') { option = validifyInstance; } else if (this.args[i-1]) { // validator arg options var arg = this.args[i-1]; var argType = arg ? arg.type : 'undefined'; var argFailOnWrongType = arg.failOnWrongType || failOnWrongType; var argFailOnMissing = arg.failOnMissing || failOnMissing; var argFailOnEmpty = arg.failOnEmpty || failOnEmpty; var argTrimStrings = arg.trimStrings || trimStrings; // if we have an option, check it against type //console.log('option', option, 'expected type', type, 'type', typeof option); if (option && argFailOnWrongType && argType !== 'mixed' && typeof option !== argType) { //console.log('option', option, 'expected type', type, 'type', typeof option); // check to see if perhaps it's a complex type like array of objects var match; if ((match = argType.match(/^\[([^\]]+)\]$/)) && Array.isArray(option)) { var subType = match[1]; //console.log('found array of', subType); /*jshint -W073 */ if (subType !== 'mixed') { // verify the array values are of the right type for (j=0; j < option.length; j++) { if (typeof option[j] !== subType) { //throw new Error('invalid sub-type \'' + typeof option[j] + '\' for array item \'' + // param + '[' + j + ']=\'' + option[j] + '\' (should be \'' + subType + '\')'); //console.error('invalid sub-type \'' + typeof option[j] + '\' for array item \'' + // param + '[' + j + ']=\'' + option[j] + '\' (should be \'' + subType + '\')'); return false; } } } // else it doesn't matter } else { /*jshint -W101 */ //throw new Error('invalid type \'' + typeof option + '\' for param \'' + param + '\' (should be \'' + argType + '\')'); //console.error('invalid type \'' + typeof option + '\' for param \'' + param + '\' (should be \'' + argType + '\')'); return false; } } // check aliases for values if not specified as default name (e.g. gt for min) var argumentAliases = arg.aliases; if (option === undefined && argumentAliases && options != null) { for (j=0; j < argumentAliases.length; j++) { //console.log('checking argument aliases', argumentAliases[j], options[argumentAliases[j]]); // if we find an alias in the options, then use that /*jshint -W073 */ if (options[argumentAliases[j]] !== undefined) { option = options[argumentAliases[j]]; break; } } } //console.log('option', param, 'value', option, 'args', arg, 'aliasDefaults', arg.aliasDefaults); // if we have alias defaults, use that if (option === undefined && arg != null && arg.aliasDefaults != null && arg.aliasDefaults[name] != null) { // pull from alias defaults option = arg.aliasDefaults[name]; //console.log('using alias default'); // if we have args, use that } else if (option === undefined && arg) { //console.log('using default value for param', param); option = arg.default; //console.log('using arg default'); } if (failOnMissing && option == null) { throw new Error('parameter \'' + param + '\' is missing'); } else if (failOnEmpty && (option === '' || (option + '').replace(/ /g, '') !== '')) { throw new Error('parameter \'' + param + '\' is empty'); } } args.push(option); } //console.log('validate', this.evaluate, params, args, options); var res = this.evaluate.apply(this, args); // if result not true, then we have a list of failures if (res !== true) { //console.log('process failure for method', name); processFailures(this, res, name, value, options); return false; } return res; }; var validatorMap = {}; /** * Register a validator with validify * * Validator definition: * { * name: 'equals', // name of the validator * aliases: ['eq'], // alternate validator names * description: 'Match value against arg1', // helpful description for user * type: 'string', // expected JS value type (string, number, boolean, date, array, object) * failOnWrongType: true, // error if value is any other JS type * failOnMissing: false, // if true, null/undefined values will always be considered invalid * failOnEmpty: false, // if true, empty values will be considered invalid ('', "", []) * trimStrings: false, // if true, strings with be trimmed before being validated * failureMessages: { // contains validator failure messages, keyed by error code * default: 'Validator failed for value '%{value}' * } * args: [ // argument definitions (first param, 'value' is ignored * { * name: 'arg1', // the name of the argument, which will be matched to evaluate function * aliases: ['arg2'], // alternate names for the argument, useful combined with validator aliases * description: 'The first argument', // helpful description for user * type: 'string', // the type of the argument * failOnWrongType: true, // error if value is any other JS type * failOnMissing: false, // if true, null/undefined values will always be considered invalid * failOnEmpty: false, // if true, empty values will be considered invalid ('', "", []) * trimStrings: false, // if true, strings with be trimmed before being validated * default: null, // default value for argument, if none provided * aliasDefaults: { // default value for argument when called by alias, and if none provided * eq: 'blah' // default for arg1 is 'blah' when validator called as 'eq' * } * } * ] * evaluate: function (value, arg1) { // a function, which accepts a value and any additional parameters * return value === arg1; * } * } * * @param validator see definition above * @api public */ function registerValidator(validator) { try { var v = new Validator(validator); var name = validator.name; //console.log('generating validator', name, 'func', v); validatorMap[name] = v; validify.prototype[name] = function() { //console.log('registerValidator(): name', name, 'arguments', arguments); var args = [name]; var value = arguments && arguments.length >= 1 ? arguments[0] : null; var options = arguments && arguments.length >= 2 ? arguments[1] : null; // add the rest of the arguments to the list for (var i=0; i < arguments.length; i++) { args.push(arguments[i]); } //console.error('running validator', name, 'options', options); // validate and get the result return Validator.prototype.validate.apply(this, args); }.bind(v); // process aliases if (validator.aliases && validator.aliases.length > 0) { for (var j=0; j < validator.aliases.length; j++) { var alias = validator.aliases[j]; validatorMap[alias] = v; /*jshint -W083 */ validify.prototype[alias] = function() { //console.log('registerValidator(): alias', this.alias, 'this', this, 'arguments', arguments); var args = [this.alias]; var value = arguments && arguments.length >= 1 ? arguments[0] : null; var options = arguments && arguments.length >= 2 ? arguments[1] : null; // add the rest of the arguments to the list for (var i=0; i < arguments.length; i++) { args.push(arguments[i]); } // validate and get the result return Validator.prototype.validate.apply(this.validator, args); }.bind({validator: v, alias: alias}); } } } catch (ex) { //console.error('error generating validator', validator.name); } } function processFailures(/*jshint -W072 */v, failureKeys, name, value, options) { // if this validator failed to validate and there are no existing failure messages, generate a default if (options && options.failures) { // determine if we have a list of failures to loop through or should just use the default if (failureKeys !== false && failureKeys && failureKeys.length > 0) { // for each of the failures that occurred, we need to determine the right failure message template to use for (var i=0; i < failureKeys.length; i++) { var failureKey = failureKeys[i]; //console.log('failure key in list', failureKey); processFailure(v, failureKey, name, value, options); } } else { // else we use the default //console.log('failure key default'); processFailure(v, 'default', name, value, options); } } } function processFailure(/*jshint -W072 */v, failureKey, name, value, options) { //console.log('processFailure(): name', name, 'failureKey', failureKey); // set a generic default failure message var failureMessage; switch (failureKey) { case 'invalidType': failureMessage = 'Validator %{name} failed for value \'%{value}\' due to invalid type \'%{type}\''; break; case 'missingValue': failureMessage = 'Validator %{name} value missing'; break; case 'emptyValue': failureMessage = 'Validator %{name} value empty'; break; default: failureMessage = 'Validator %{name} failed for value \'%{value}\''; } // first, check for failure messages in the options object var failureMessages; if (options.failureMessages && options.failureMessages[failureKey]) { //console.log('using failure messages from options'); failureMessages = options.failureMessages; } else if (v.failureMessages && v.failureMessages[failureKey]) { //console.log('using failure messages from validator definition'); failureMessages = v.failureMessages; //} else { //console.log('using default failure message'); } // this may be a string or a map of aliases to strings if (failureMessages && typeof failureMessages[failureKey] === 'string') { failureMessage = failureMessages[failureKey]; //console.log('using failure message for all aliases'); } else if (failureMessages && failureMessages[failureKey] && failureMessages[failureKey][name]) { failureMessage = failureMessages[failureKey][name]; //console.log('using failure message for specific alias'); } // else we're sticking with the default /*jshint -W101 */ //console.error('validator failed, validator.args', v.args, 'options', options, 'failureMessage', failureMessage, 'validator', v); // substitute value failureMessage = failureMessage.replace(new RegExp('%{value}', 'g'), value); // substitute validator name failureMessage = failureMessage.replace(new RegExp('%{name}', 'g'), name); // substitute value failureMessage = failureMessage.replace(new RegExp('%{type}', 'g'), typeof value); /*jshint -W073 */ // substitute all arguments if (v.args) { for (var j=0; j < v.args.length; j++) { var arg = v.args[j]; var val = arg.default; // override default with the specified value if (options[arg.name]) { val = options[arg.name]; } //console.log('replacing', arg.name, 'with', val, 'in failure token'); failureMessage = failureMessage.replace(new RegExp('%{'+arg.name+'}', 'g'), val); } } if (Array.isArray(options.failures)) { var o = {}; o.validatorName = name; o.code = failureKey; o.message = failureMessage; //console.error('adding failure to list', o); options.failures.push(o); } //console.error('substituted failureMessage', failureMessage); } /** * Register a list of validators. See registerValidator for more information on validator format * * @param validators an array of validators * @see registerValidator */ function registerValidators(validators) { //console.log('have', validators.length, 'validators to register'); for (var i = 0; i < validators.length; i++) { var validator = validators[i]; //console.log('registering validator', validator); registerValidator(validator); } } // validator registration validify.prototype.registerValidator = registerValidator; validify.prototype.registerValidators = registerValidators; // validator retrieval function getValidator(name) { return validatorMap[name]; } validify.prototype.getValidator = getValidator; /** * Validation given set of declarative constraints * * { * // constraints * boolField: { // field * equals: true // validator * }, * floatField: { // field * present: true // validator * }, * intField: { // field * between: { // validator * min: 1, // option * max: 2, // option * inclusive: true // option * } * }, * objectArrayField.name: { // field 'name' for objects in array objectArrayField, or field 'name' in object * present: true // validator (if value is not an object, value is the only param for the function) * } * } * * @param value the value to validate * @param constraints the constraints with which to validate the specified value, array or single object * @param [operator] if an array of constraints, require all, some or only one constraint object to be valid (and, or, xor) */ function validate(value, constraints, operator) { //console.log('validate(): value', value, 'constraints', constraints, 'operator', operator); var invalidCount = 0; if (operator == null) { operator = 'and'; } // make the constraints an array if not already if (!Array.isArray(constraints)) { constraints = [constraints]; } // loop through constraints for (var i=0; i < constraints.length; i++) { var constraint = constraints[i]; //console.log('validate(): processing constraint', constraint); // loop through each property, which will be a field name mapped to a validator config for (var field in constraint) { if (constraint.hasOwnProperty(field)) { // get the validators for the given field var validatorMap = constraint[field]; // get any fields with '.' in them, referencing sub-fields / arrays var path; if (field.indexOf('.') !== -1) { path = field.split('.'); field = path.shift(); } //console.log('processing constraint with field', field, 'path', path, 'value', value); /** * 'objectArrayField.name': { * present: true, * length: 7 * } */ // determine if the field is an array & has complex objects, and if so loop through it if (value.hasOwnProperty(field) && Array.isArray(value[field])) { //console.log('processing an array field', field); // TODO, handle multiple levels of nesting, for now only 1 will really work /*jshint -W073 */ var p = path != null ? path.join('.') : '*'; var res = true; // loop through each of the array elements for (var j=0; j < value[field].length; j++) { var item = value[field][j]; // use the validator map wrapped with this field var cc = {}; cc[p] = validatorMap; //console.log('validating item', item, cc); // and validate them if (validate(item, cc) === false) { //console.log('failed to validate array element', j, 'item', item, validatorMap); res = false; break; } } // if any of the items in the array failed, then mark this constraint invalid if (res === false) { invalidCount++; //console.log('invalidCount', invalidCount); } } else { //console.log('processing a simple field', field, 'validatorMap', validatorMap); // run all the validators for (var validatorName in validatorMap) { if (validatorMap.hasOwnProperty(validatorName)) { // get the validator constraints var validatorConstraints = validatorMap[validatorName]; // lookup the validator function var validator = validifyInstance[validatorName]; // lookup the validator definition var validatorDef = getValidator(validatorName); /*jshint -W073 */ if (validator == null) { throw new Error('Validator ' + validatorName + ' not found'); } // if the constraints are a simple type instead of an object, then simply pass the value through as the // first argument switch (typeof validatorConstraints) { /*jshint -W110 */ case "boolean": case "string": case "number": case "date": //console.log('validator', validatorName, 'constraints', validatorConstraints, 'type', // typeof validatorConstraints); /*jshint -W073 */ // set the first argument to this value if (validatorDef.args && validatorDef.args.length > 0) { var firstArgName = validatorDef.args[0].name; //console.log('populating first arg with primitive', firstArgName, validatorDef.args[0].name); var c = {}; c[firstArgName] = validatorConstraints; validatorConstraints = c; } break; } //console.log('running validator', validatorName, 'constraints', validatorConstraints, 'field', field, 'value', // field === '*' ? value : value[field]); /*jshint -W073 */ if (!validator(field === '*' ? value : value[field], validatorConstraints)) { //console.log('validator failed'); invalidCount++; break; } } } } } } } //console.log('invalid count', invalidCount, 'constraint.length', constraints.length, 'operator', operator); if ((invalidCount === 0 && (operator === 'and' || operator === 'all')) || ((invalidCount === 0 || invalidCount < constraints.length) && (operator === 'or' || operator === 'any')) || (invalidCount === constraints.length - 1 && (operator === 'xor' || operator === 'one'))) { return true; } return false; } // expose the validate method validify.prototype.validate = validate; // expose validator class validify.prototype.Validator = Validator; /*jshint -W055 */ validifyInstance = new validify(); // Load all the validator groups var validatorGroups = _dereq_('./lib/validators'); // Register all the validators from the groups for (var validatorGroupName in validatorGroups) { if (validatorGroups.hasOwnProperty(validatorGroupName)) { //console.log('validatorGroupName', validatorGroupName); var validatorGroup = validatorGroups[validatorGroupName]; registerValidators(validatorGroup); } } module.exports = validifyInstance; })(); },{"./lib/validators":3}]},{},[6]) (6) });