async-validate
Advanced tools
Comparing version 0.4.1 to 0.4.2
@@ -7,2 +7,31 @@ var iterator = require('./iterator') | ||
function clone(source, target) { | ||
var k | ||
, v; | ||
function isComplex(obj) { | ||
return Array.isArray(obj) | ||
|| (obj && typeof obj === 'object') && !(obj instanceof RegExp); | ||
} | ||
// simple source object | ||
if(!isComplex(source)) { | ||
return source; | ||
} | ||
target = target || (Array.isArray(source) ? [] : {}); | ||
for(k in source) { | ||
v = source[k]; | ||
if(isComplex(v)) { | ||
target[k] = Array.isArray(v) ? [] : {}; | ||
clone(v, target[k]); | ||
}else{ | ||
target[k] = v; | ||
} | ||
} | ||
return target; | ||
} | ||
/** | ||
@@ -53,3 +82,3 @@ * Encapsulates a validation schema. | ||
for(z in rules) { | ||
item = rules[z]; | ||
item = clone(rules[z]); | ||
this.rules[z] = Array.isArray(item) ? item : [item]; | ||
@@ -68,12 +97,4 @@ } | ||
function add(e) { | ||
if((e instanceof Error)) { | ||
errors.push(e); | ||
}else if(Array.isArray(e)) { | ||
errors = errors.concat.apply(errors, e); | ||
} | ||
} | ||
for(i = 0;i < results.length;i++) { | ||
add(results[i]); | ||
errors = errors.concat(results[i]); | ||
} | ||
@@ -119,9 +140,25 @@ | ||
var messages = options.messages || this.messages(); | ||
var i | ||
, j | ||
, z | ||
, arr | ||
, value | ||
, rule | ||
, validator | ||
, series = [] | ||
, keys | ||
, func | ||
, messages; | ||
// configure messages to use defaults where necessary | ||
messages = options.messages || this.messages(); | ||
options.messages = messages; | ||
var j, z, arr, value, i, rule, validator, series = []; | ||
var keys = options.keys || Object.keys(this.rules); | ||
var func = options.parallel ? iterator.map : iterator.mapSeries; | ||
keys = options.keys || Object.keys(this.rules); | ||
// iterator function series/parallel | ||
func = options.parallel ? iterator.map : iterator.mapSeries; | ||
// convert map into iterable array | ||
// assigning field name to rule and perform transform | ||
for(j = 0;j < keys.length;j++) { | ||
@@ -148,15 +185,18 @@ z = keys[j]; | ||
rule.validator = this.getValidationMethod(rule); | ||
series.push({rule: rule, value: value, source: source, field: z}); | ||
rule.value = value; | ||
rule.source = source; | ||
series.push(rule); | ||
} | ||
} | ||
func(series, function(data, callback) { | ||
var rule = data.rule; | ||
var deep = (rule.type == 'object' || rule.type == 'array') | ||
&& typeof(rule.fields) == 'object'; | ||
deep = deep && (rule.required || (!rule.required && data.value)); | ||
rule.field = data.field; | ||
// iterate list data | ||
func(series, function(rule, callback) { | ||
var validator = getValidationOptions(rule, options); | ||
var deep = (rule.type === 'object' || rule.type === 'array') | ||
&& typeof(rule.fields) === 'object'; | ||
deep = deep && (rule.required || (!rule.required && rule.value)); | ||
//rule.field = data.field; | ||
function onValidate(errors) { | ||
// bail on first error | ||
@@ -179,3 +219,3 @@ if(options.first && errors && errors.length) { | ||
// go deeper | ||
if(rule.required && !data.value) { | ||
if(rule.required && !rule.value) { | ||
return callback(null, [ | ||
@@ -187,15 +227,16 @@ new ValidationError( | ||
var schema = new Schema(data.rule.fields); | ||
var schema = new Schema(rule.fields); | ||
schema.messages(options.messages); | ||
if(data.rule.options) { | ||
data.rule.options.messages = options.messages; | ||
if(rule.options) { | ||
rule.options.messages = options.messages; | ||
} | ||
schema.validate( | ||
data.value, data.rule.options || options, function(errs, fields) { | ||
callback(null, errs && errs.length ? errors.concat(errs) : errs); | ||
rule.value, rule.options || options, function(errs, fields) { | ||
errors = errors.concat(errs || []); | ||
callback(null, errors); | ||
}); | ||
} | ||
} | ||
rule.validator.call(validator, onValidate); | ||
rule.validator.call(getValidationOptions(rule, data, options), onValidate); | ||
}, function(err, results) { | ||
@@ -206,9 +247,9 @@ complete(results, options, cb); | ||
function getValidationOptions(rule, data, options) { | ||
function getValidationOptions(rule, options) { | ||
return Validator({ | ||
rule: rule, | ||
field: rule.field, | ||
value: data.value, | ||
source: data.source, | ||
data: data, | ||
value: rule.value, | ||
source: rule.source, | ||
data: options.data, | ||
errors: [], | ||
@@ -260,2 +301,3 @@ options: options, | ||
Schema.clone = clone; | ||
Schema.Validator = Validator; | ||
@@ -262,0 +304,0 @@ Schema.plugin = Validator.plugin; |
@@ -10,2 +10,3 @@ var plugin = require('zephyr') | ||
length: 'length', | ||
additional: 'additional', | ||
enumerable: 'enum', | ||
@@ -214,2 +215,22 @@ date: 'date', | ||
function hasAdditionalFields(expected, received) { | ||
var i | ||
, results = received.slice(0); | ||
for(i = 0;i < results.length;i++) { | ||
if(~expected.indexOf(results[i])) { | ||
results.splice(i, 1); | ||
i--; | ||
} | ||
} | ||
// no additional fields found | ||
if(results.length === 0) { | ||
return false; | ||
} | ||
// return diff array | ||
return results; | ||
} | ||
Validator.prototype.error = error; | ||
@@ -219,3 +240,2 @@ Validator.prototype.raise = raise; | ||
Validator.prototype.required = required; | ||
Validator.prototype.shouldValidate = shouldValidate; | ||
Validator.prototype.whitespace = whitespace; | ||
@@ -227,5 +247,9 @@ Validator.prototype.enumerable = enumerable; | ||
// static error access | ||
Validator.prototype.shouldValidate = shouldValidate; | ||
Validator.prototype.hasAdditionalFields = hasAdditionalFields; | ||
// static access | ||
Validator.error = error; | ||
Validator.hasAdditionalFields = hasAdditionalFields; | ||
module.exports = plugin({type: Validator}); |
@@ -9,2 +9,3 @@ /** | ||
whitespace: '%s cannot be empty', | ||
additional: 'extraneous fields (%s) found in %s', | ||
date: { | ||
@@ -45,9 +46,4 @@ format: "%s date %s is invalid for format %s", | ||
mismatch: '%s value %s does not match pattern %s' | ||
}, | ||
clone: function() { | ||
var cloned = JSON.parse(JSON.stringify(this)); | ||
cloned.clone = this.clone; | ||
return cloned; | ||
} | ||
} | ||
module.exports = messages; |
{ | ||
"name": "async-validate", | ||
"description": "Asynchronous validation for object properties.", | ||
"version": "0.4.1", | ||
"version": "0.4.2", | ||
"author": "muji <noop@xpm.io>", | ||
@@ -6,0 +6,0 @@ "license": "MIT", |
@@ -7,6 +7,23 @@ /** | ||
function object(cb) { | ||
var additional; | ||
if(this.shouldValidate()) { | ||
this.required(); | ||
this.type(); | ||
if(this.rule.additional === false | ||
&& this.rule.fields | ||
&& typeof this.rule.fields === 'object') { | ||
additional = this.hasAdditionalFields( | ||
Object.keys(this.rule.fields), Object.keys(this.value)); | ||
if(additional) { | ||
//console.dir('additional error'); | ||
this.reason(this.reasons.additional); | ||
this.raise(this.messages.additional, additional.join(', '), this.field); | ||
} | ||
} | ||
} | ||
cb(this.errors); | ||
@@ -13,0 +30,0 @@ } |
@@ -1,9 +0,7 @@ | ||
var util = require('util'); | ||
var assert = require('chai').assert; | ||
var schema = require('../../index'); | ||
var msg = require('../../messages'); | ||
var expect = require('chai').expect | ||
, schema = require('../../index'); | ||
describe("async-validate:", function() { | ||
it("should validate using a custom error message", function(done) { | ||
it("should validate using a custom error message as min", function(done) { | ||
var descriptor = { | ||
@@ -14,3 +12,3 @@ num: { | ||
min: 'Number may not be below zero', | ||
max: 'Number may not be above 10', | ||
max: 'Number may not be above ten', | ||
} | ||
@@ -21,4 +19,3 @@ } | ||
validator.validate({num: -1}, function(errors, fields) { | ||
assert.equal(errors.length, 1); | ||
assert.equal(errors[0].message, "Number may not be below zero"); | ||
expect(errors[0].message).to.eql("Number may not be below zero"); | ||
done(); | ||
@@ -28,2 +25,19 @@ }); | ||
it("should validate using a custom error message as max", function(done) { | ||
var descriptor = { | ||
num: { | ||
type: "number", min: 0, max: 10, | ||
message: { | ||
min: 'Number may not be below zero', | ||
max: 'Number may not be above ten', | ||
} | ||
} | ||
} | ||
var validator = new schema(descriptor); | ||
validator.validate({num: 11}, function(errors, fields) { | ||
expect(errors[0].message).to.eql("Number may not be above ten"); | ||
done(); | ||
}); | ||
}); | ||
}); |
@@ -1,2 +0,1 @@ | ||
var util = require('util'); | ||
var assert = require('chai').assert; | ||
@@ -20,6 +19,8 @@ var schema = require('../../index'); | ||
// quick and dirty clone of the default messages | ||
var clone = msg.clone(); | ||
// clone of the default messages | ||
var clone = schema.clone(msg); | ||
// change a message | ||
clone.required = "%s is a required field"; | ||
it("should validate using custom messages", function(done) { | ||
@@ -30,4 +31,6 @@ var descriptor = { | ||
var validator = new schema(descriptor); | ||
// assign to the schema | ||
// assign updated messages to the schema | ||
validator.messages(clone); | ||
validator.validate({}, function(errors, fields) { | ||
@@ -39,2 +42,3 @@ assert.equal(errors.length, 1); | ||
}); | ||
it("should verify custom error message helper", function(done) { | ||
@@ -54,2 +58,3 @@ var descriptor = { | ||
}); | ||
}); |
106889
67
2397