-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathindex.js
More file actions
112 lines (91 loc) · 2.54 KB
/
Copy pathindex.js
File metadata and controls
112 lines (91 loc) · 2.54 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
/**
* A validator chain
* @constructor
* @returns {ValidatorChain}
*/
function ValidatorChain() {
if (!(this instanceof ValidatorChain)) {
return new ValidatorChain();
}
this._validators = [];
}
/**
* Get/set
* @param {bool|function} [optional]
* @returns {ValidatorChain}
*/
ValidatorChain.prototype.optional = function(optional) {
if (arguments.length) {
this._optional = optional;
return this;
} else {
return this._optional;
}
};
/**
* Add a validator to the chain
* @param {function(*, [function])} fn The validator function
* @param {Object} [ctx] The validator context
* @param {function()} [when] The validator condition
* @returns {ValidatorChain}
*/
ValidatorChain.prototype.add = function(fn, ctx, when) {
this._validators.push({
fn: fn,
ctx: ctx,
when: when
});
return this;
};
/**
* Check whether a value matches the rules
* @param {*} value
* @param {function()} callback
* @returns {ValidatorChain}
*/
ValidatorChain.prototype.validate = function(value, callback) {
var self = this, count = 0, validator = null;
function next(err, valid) {
//there's an error, now we can finish
if (err) {
return callback(err, valid, validator.ctx);
}
//the value is invalid, now we can finish
if (!valid) {
return callback(err, valid, validator.ctx);
}
//check for optional
var optional = typeof(self._optional) === 'function' ? self._optional() : Boolean(self._optional);
if (optional && (value === undefined || value === null || value === [] || value === '')) {
return callback(err, valid);
}
//we've run all the validators, now we can finish
if (count >= self._validators.length) {
return callback(err, valid);
}
//get the next validator
validator = self._validators[count++];
//if the rule is conditional
if (validator.when && !validator.when()) {
return next(undefined, valid); //skip validation if the condition is not true
}
//run the validator
var fn = validator.fn;
if (fn.length > 1) {
//async
fn(value, next);
} else {
var fnError, fnValid;
try {
fnValid = fn(value); //sync
} catch(err) {
fnError = err;
}
next(fnError, fnValid);
}
}
//don't release "Zalgo" - http://blog.izs.me/post/59142742143/designing-apis-for-asynchrony
setTimeout(function() { next(undefined, true); }, 0);
return this;
};
module.exports = ValidatorChain;