1 |
|
2 |
|
3 |
|
4 |
|
5 |
|
6 | var util = require('util');
|
7 |
|
8 |
|
9 |
|
10 |
|
11 | var Config = module.exports = {
|
12 | _errMsgs: {
|
13 | 'require': '"%s" is required',
|
14 | 'type' : 'Expect "%s" to be a typeof %s, but now is %s',
|
15 | 'regex' : 'Verify "%s" with regex failed, %s',
|
16 | 'max' : 'The maximum of "%s" is %s, but now is %s',
|
17 | 'min' : 'The minimum of "%s" is %s, but now is %s'
|
18 | },
|
19 | |
20 |
|
21 |
|
22 |
|
23 | get schema(){
|
24 |
|
25 | if (this._schema) {
|
26 | return this._schema;
|
27 | }
|
28 |
|
29 | this._schema = require('../API/schema');
|
30 | for (var k in this._schema) {
|
31 | if (k.indexOf('\\') > 0) {
|
32 | continue;
|
33 | }
|
34 | var aliases = [
|
35 | k.split('_').map(function(n, i){
|
36 | if (i != 0 && n && n.length > 1) {
|
37 | return n[0].toUpperCase() + n.slice(1);
|
38 | }
|
39 | return n;
|
40 | }).join('')
|
41 | ];
|
42 |
|
43 | if (this._schema[k].alias && Array.isArray(this._schema[k].alias)) {
|
44 |
|
45 | this._schema[k].alias.forEach(function(alias) {
|
46 | aliases.splice(0, 0, alias);
|
47 | });
|
48 | }
|
49 | else if (this._schema[k].alias)
|
50 | aliases.splice(0, 0, this._schema[k].alias);
|
51 |
|
52 | this._schema[k].alias = aliases;
|
53 | }
|
54 | return this._schema;
|
55 | }
|
56 | };
|
57 |
|
58 |
|
59 |
|
60 |
|
61 | Config.filterOptions = function(cmd) {
|
62 | var conf = {};
|
63 | var schema = this.schema;
|
64 |
|
65 | for (var key in schema) {
|
66 | var aliases = schema[key].alias;
|
67 | aliases && aliases.forEach(function(alias){
|
68 | if (typeof(cmd[alias]) !== 'undefined') {
|
69 | conf[key] || (conf[key] = cmd[alias]);
|
70 | }
|
71 | });
|
72 | }
|
73 |
|
74 | return conf;
|
75 | };
|
76 |
|
77 |
|
78 |
|
79 |
|
80 |
|
81 |
|
82 | Config.validateJSON = function(json){
|
83 |
|
84 | var conf = Object.assign({}, json),
|
85 | res = {};
|
86 | this._errors = [];
|
87 |
|
88 | var regexKeys = {}, defines = this.schema;
|
89 |
|
90 | for (var sk in defines) {
|
91 |
|
92 | if (sk.indexOf('\\') >= 0) {
|
93 | regexKeys[sk] = false;
|
94 | continue;
|
95 | }
|
96 |
|
97 | var aliases = defines[sk].alias;
|
98 |
|
99 | aliases && aliases.forEach(function(alias){
|
100 | conf[sk] || (conf[sk] = json[alias]);
|
101 | })
|
102 |
|
103 | var val = conf[sk];
|
104 | delete conf[sk];
|
105 |
|
106 |
|
107 | if (val === undefined ||
|
108 | val === null ||
|
109 | ((val = this._valid(sk, val)) === null)) {
|
110 |
|
111 |
|
112 |
|
113 | if (typeof(defines[sk].default) !== 'undefined')
|
114 | res[sk] = defines[sk].default;
|
115 | continue;
|
116 | }
|
117 |
|
118 | res[sk] = val;
|
119 | }
|
120 |
|
121 |
|
122 | var hasRegexKey = false;
|
123 | for (var k in regexKeys) {
|
124 | hasRegexKey = true;
|
125 | regexKeys[k] = new RegExp(k);
|
126 | }
|
127 | if (hasRegexKey) {
|
128 | for (var k in conf) {
|
129 | for (var rk in regexKeys) {
|
130 | if (regexKeys[rk].test(k))
|
131 | if (this._valid(k, conf[k], defines[rk])) {
|
132 | res[k] = conf[k];
|
133 | delete conf[k];
|
134 | }
|
135 | }
|
136 | }
|
137 | }
|
138 |
|
139 | return {errors: this._errors, config: res};
|
140 | };
|
141 |
|
142 |
|
143 |
|
144 |
|
145 |
|
146 |
|
147 |
|
148 |
|
149 |
|
150 | Config._valid = function(key, value, sch){
|
151 | var sch = sch || this.schema[key],
|
152 | scht = typeof sch.type == 'string' ? [sch.type] : sch.type;
|
153 |
|
154 |
|
155 | var undef = typeof value == 'undefined';
|
156 | if(this._error(sch.require && undef, 'require', key)){
|
157 | return null;
|
158 | }
|
159 |
|
160 |
|
161 | if (undef) {
|
162 | return null;
|
163 | }
|
164 |
|
165 |
|
166 | scht = scht.map(function(t){
|
167 | return '[object ' + t[0].toUpperCase() + t.slice(1) + ']'
|
168 | });
|
169 |
|
170 |
|
171 | var type = Object.prototype.toString.call(value), nt = '[object Number]';
|
172 |
|
173 |
|
174 | if (type != '[object Boolean]' && scht.indexOf(nt) >= 0 && !isNaN(value)) {
|
175 | value = parseFloat(value);
|
176 | type = nt;
|
177 | }
|
178 |
|
179 |
|
180 | if (this._error(!~scht.indexOf(type), 'type', key, scht.join(' / '), type)) {
|
181 | return null;
|
182 | }
|
183 |
|
184 |
|
185 | if (this._error(type == '[object String]' && sch.regex && !(new RegExp(sch.regex)).test(value),
|
186 | 'regex', key, sch.desc || ('should match ' + sch.regex))) {
|
187 | return null;
|
188 | }
|
189 |
|
190 |
|
191 | if (type == '[object Number]') {
|
192 | if (this._error(typeof sch.max != 'undefined' && value > sch.max, 'max', key, sch.max, value)) {
|
193 | return null;
|
194 | }
|
195 | if (this._error(typeof sch.min != 'undefined' && value < sch.min, 'min', key, sch.min, value)) {
|
196 | return null;
|
197 | }
|
198 | }
|
199 |
|
200 |
|
201 | if(scht.length > 1 && type != scht[0] && type == '[object String]'){
|
202 | if(scht[0] == '[object Array]') {
|
203 |
|
204 | value = value.split(/([\w\-]+\="[^"]*")|([\w\-]+\='[^']*')|"([^"]*)"|'([^']*)'|\s/)
|
205 | .filter(function(v){
|
206 | return v && v.trim();
|
207 | });
|
208 | }
|
209 | }
|
210 |
|
211 |
|
212 | if(sch.ext_type && type == '[object String]' && value.length >= 2) {
|
213 | var seed = {
|
214 | 'sbyte': {
|
215 | 'G': 1024 * 1024 * 1024,
|
216 | 'M': 1024 * 1024,
|
217 | 'K': 1024
|
218 | },
|
219 | 'stime': {
|
220 | 'h': 60 * 60 * 1000,
|
221 | 'm': 60 * 1000,
|
222 | 's': 1000
|
223 | }
|
224 | }[sch.ext_type];
|
225 |
|
226 | if(seed){
|
227 | value = parseFloat(value.slice(0, -1)) * (seed[value.slice(-1)]);
|
228 | }
|
229 | }
|
230 | return value;
|
231 | };
|
232 |
|
233 |
|
234 |
|
235 |
|
236 |
|
237 |
|
238 |
|
239 |
|
240 | Config._error = function(possible, type){
|
241 | if (possible) {
|
242 | var args = Array.prototype.slice.call(arguments);
|
243 | args.splice(0, 2, this._errMsgs[type]);
|
244 | this._errors && this._errors.push(util.format.apply(null, args));
|
245 | }
|
246 | return possible;
|
247 | }
|