/
Validator.js
145 lines (136 loc) · 4.35 KB
/
Validator.js
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
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
/**
* @function CustomValidateFunction
*
* @param {*} value the value you want to validated
* @param {http.IncomingMessage=} req the req object of express
* @returns {*} the validate result, when none error, you can return `false` `undefined` `null` or anything can transform to false,
* when the value is not suitable, you can return a string or an object.
*/
/**
* @typedef ValidateElement
*
* If the value of `required` or `type` is an Array,
* the second value of the array is the error message that describe the error reason,
* it can be a string or an object,
* and the first value is normal value as used without array.
*
* @property {Boolean|Array} required indicate whether the current field necessary
* @property {Number|JSON|Date|Array} type declare the current field's type.
* @property {FuncCustomValidateFunctiontion} custom the custom validate function
*/
/**
* @typedef Schema
* @example
* ```javascript
* {
* numberFiled : {
* required:true,
* type : Number
* }
* }
* ```
* @example
* ```javascript
* {
* dateField:{
* required:[true,'the dateField can not be empty']
* type:[Date,'the dataField must be a Date']
* }
* }
* ```
* @property {ValidateElement} filedName
*/
/**
* The class of Validator
*
* @class Validator
*/
class Validator {
/**
* Creates an instance of Validator.
* @param {Schema} schema
* @memberof Validator
*/
constructor(schema) {
this.schema = schema;
this._req = null;
this.schemaKeys = Object.keys(this.schema);
this.expectedErrorMsg = {};
for (const key of this.schemaKeys) {
const validateElement = this.schema[key];
this.expectedErrorMsg[key] = {};
for (const checkItem in validateElement) {
const checkContent = validateElement[checkItem];
if (Array.isArray(checkContent)) {
this.expectedErrorMsg[key][checkItem] = checkContent[1];//the custom error message
}
}
}
}
setReq(req) {
this._req = req;
}
_isEmptyValue(value) {
return typeof(value) === 'undefined' || value === '' || value === null;
}
/**
* To do a validation.
*
* @param {Object} params
* @returns {null|Object|String}
* @memberof Validator
*/
doValidate(params) {
for (const key of this.schemaKeys) {
const validateElement = this.schema[key];
let value = params[key];
if (this._isEmptyValue(value)) {
const required = validateElement.required;
if ((Array.isArray(required) && required[0]) || required) {
return this.expectedErrorMsg[key].required || `${key} can't be empty`;
} else {
continue;
}
}
let needType = validateElement.type;
if (Array.isArray(needType)) {
needType = needType[0];
}
if (needType && needType !== String) {
switch(needType) {
case Number:
value = Number(value);
if (isNaN(value)) {
return this.expectedErrorMsg[key].type || `${key} must be a Number`;
}
params[key] = value;
break;
case Date:
value = new Date(value);
if (isNaN(value.getTime())) {
return this.expectedErrorMsg[key].type || `${key} must be a Date`
}
params[key] = value;
break;
case JSON:
try {
value = JSON.parse(value);
} catch (e) {
return this.expectedErrorMsg[key].type || `${key} must be a JSON string`
}
params[key] = value;
}
}
const customValidator = validateElement.custom;
if (customValidator) {
const result = customValidator(value,this._req);
if (!result) {
continue;
}
return result;
}
}//end of for
return null;
}
}
module.exports = Validator;