UNPKG

37.5 kBJavaScriptView Raw
1function _extends() {
2 _extends = Object.assign ? Object.assign.bind() : function (target) {
3 for (var i = 1; i < arguments.length; i++) {
4 var source = arguments[i];
5
6 for (var key in source) {
7 if (Object.prototype.hasOwnProperty.call(source, key)) {
8 target[key] = source[key];
9 }
10 }
11 }
12
13 return target;
14 };
15 return _extends.apply(this, arguments);
16}
17
18function _inheritsLoose(subClass, superClass) {
19 subClass.prototype = Object.create(superClass.prototype);
20 subClass.prototype.constructor = subClass;
21
22 _setPrototypeOf(subClass, superClass);
23}
24
25function _getPrototypeOf(o) {
26 _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf.bind() : function _getPrototypeOf(o) {
27 return o.__proto__ || Object.getPrototypeOf(o);
28 };
29 return _getPrototypeOf(o);
30}
31
32function _setPrototypeOf(o, p) {
33 _setPrototypeOf = Object.setPrototypeOf ? Object.setPrototypeOf.bind() : function _setPrototypeOf(o, p) {
34 o.__proto__ = p;
35 return o;
36 };
37 return _setPrototypeOf(o, p);
38}
39
40function _isNativeReflectConstruct() {
41 if (typeof Reflect === "undefined" || !Reflect.construct) return false;
42 if (Reflect.construct.sham) return false;
43 if (typeof Proxy === "function") return true;
44
45 try {
46 Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {}));
47 return true;
48 } catch (e) {
49 return false;
50 }
51}
52
53function _construct(Parent, args, Class) {
54 if (_isNativeReflectConstruct()) {
55 _construct = Reflect.construct.bind();
56 } else {
57 _construct = function _construct(Parent, args, Class) {
58 var a = [null];
59 a.push.apply(a, args);
60 var Constructor = Function.bind.apply(Parent, a);
61 var instance = new Constructor();
62 if (Class) _setPrototypeOf(instance, Class.prototype);
63 return instance;
64 };
65 }
66
67 return _construct.apply(null, arguments);
68}
69
70function _isNativeFunction(fn) {
71 return Function.toString.call(fn).indexOf("[native code]") !== -1;
72}
73
74function _wrapNativeSuper(Class) {
75 var _cache = typeof Map === "function" ? new Map() : undefined;
76
77 _wrapNativeSuper = function _wrapNativeSuper(Class) {
78 if (Class === null || !_isNativeFunction(Class)) return Class;
79
80 if (typeof Class !== "function") {
81 throw new TypeError("Super expression must either be null or a function");
82 }
83
84 if (typeof _cache !== "undefined") {
85 if (_cache.has(Class)) return _cache.get(Class);
86
87 _cache.set(Class, Wrapper);
88 }
89
90 function Wrapper() {
91 return _construct(Class, arguments, _getPrototypeOf(this).constructor);
92 }
93
94 Wrapper.prototype = Object.create(Class.prototype, {
95 constructor: {
96 value: Wrapper,
97 enumerable: false,
98 writable: true,
99 configurable: true
100 }
101 });
102 return _setPrototypeOf(Wrapper, Class);
103 };
104
105 return _wrapNativeSuper(Class);
106}
107
108/* eslint no-console:0 */
109var formatRegExp = /%[sdj%]/g;
110var warning = function warning() {}; // don't print warning message when in production env or node runtime
111
112if (typeof process !== 'undefined' && process.env && process.env.NODE_ENV !== 'production' && typeof window !== 'undefined' && typeof document !== 'undefined') {
113 warning = function warning(type, errors) {
114 if (typeof console !== 'undefined' && console.warn && typeof ASYNC_VALIDATOR_NO_WARNING === 'undefined') {
115 if (errors.every(function (e) {
116 return typeof e === 'string';
117 })) {
118 console.warn(type, errors);
119 }
120 }
121 };
122}
123
124function convertFieldsError(errors) {
125 if (!errors || !errors.length) return null;
126 var fields = {};
127 errors.forEach(function (error) {
128 var field = error.field;
129 fields[field] = fields[field] || [];
130 fields[field].push(error);
131 });
132 return fields;
133}
134function format(template) {
135 for (var _len = arguments.length, args = new Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) {
136 args[_key - 1] = arguments[_key];
137 }
138
139 var i = 0;
140 var len = args.length;
141
142 if (typeof template === 'function') {
143 return template.apply(null, args);
144 }
145
146 if (typeof template === 'string') {
147 var str = template.replace(formatRegExp, function (x) {
148 if (x === '%%') {
149 return '%';
150 }
151
152 if (i >= len) {
153 return x;
154 }
155
156 switch (x) {
157 case '%s':
158 return String(args[i++]);
159
160 case '%d':
161 return Number(args[i++]);
162
163 case '%j':
164 try {
165 return JSON.stringify(args[i++]);
166 } catch (_) {
167 return '[Circular]';
168 }
169
170 break;
171
172 default:
173 return x;
174 }
175 });
176 return str;
177 }
178
179 return template;
180}
181
182function isNativeStringType(type) {
183 return type === 'string' || type === 'url' || type === 'hex' || type === 'email' || type === 'date' || type === 'pattern';
184}
185
186function isEmptyValue(value, type) {
187 if (value === undefined || value === null) {
188 return true;
189 }
190
191 if (type === 'array' && Array.isArray(value) && !value.length) {
192 return true;
193 }
194
195 if (isNativeStringType(type) && typeof value === 'string' && !value) {
196 return true;
197 }
198
199 return false;
200}
201
202function asyncParallelArray(arr, func, callback) {
203 var results = [];
204 var total = 0;
205 var arrLength = arr.length;
206
207 function count(errors) {
208 results.push.apply(results, errors || []);
209 total++;
210
211 if (total === arrLength) {
212 callback(results);
213 }
214 }
215
216 arr.forEach(function (a) {
217 func(a, count);
218 });
219}
220
221function asyncSerialArray(arr, func, callback) {
222 var index = 0;
223 var arrLength = arr.length;
224
225 function next(errors) {
226 if (errors && errors.length) {
227 callback(errors);
228 return;
229 }
230
231 var original = index;
232 index = index + 1;
233
234 if (original < arrLength) {
235 func(arr[original], next);
236 } else {
237 callback([]);
238 }
239 }
240
241 next([]);
242}
243
244function flattenObjArr(objArr) {
245 var ret = [];
246 Object.keys(objArr).forEach(function (k) {
247 ret.push.apply(ret, objArr[k] || []);
248 });
249 return ret;
250}
251
252var AsyncValidationError = /*#__PURE__*/function (_Error) {
253 _inheritsLoose(AsyncValidationError, _Error);
254
255 function AsyncValidationError(errors, fields) {
256 var _this;
257
258 _this = _Error.call(this, 'Async Validation Error') || this;
259 _this.errors = errors;
260 _this.fields = fields;
261 return _this;
262 }
263
264 return AsyncValidationError;
265}( /*#__PURE__*/_wrapNativeSuper(Error));
266function asyncMap(objArr, option, func, callback, source) {
267 if (option.first) {
268 var _pending = new Promise(function (resolve, reject) {
269 var next = function next(errors) {
270 callback(errors);
271 return errors.length ? reject(new AsyncValidationError(errors, convertFieldsError(errors))) : resolve(source);
272 };
273
274 var flattenArr = flattenObjArr(objArr);
275 asyncSerialArray(flattenArr, func, next);
276 });
277
278 _pending["catch"](function (e) {
279 return e;
280 });
281
282 return _pending;
283 }
284
285 var firstFields = option.firstFields === true ? Object.keys(objArr) : option.firstFields || [];
286 var objArrKeys = Object.keys(objArr);
287 var objArrLength = objArrKeys.length;
288 var total = 0;
289 var results = [];
290 var pending = new Promise(function (resolve, reject) {
291 var next = function next(errors) {
292 results.push.apply(results, errors);
293 total++;
294
295 if (total === objArrLength) {
296 callback(results);
297 return results.length ? reject(new AsyncValidationError(results, convertFieldsError(results))) : resolve(source);
298 }
299 };
300
301 if (!objArrKeys.length) {
302 callback(results);
303 resolve(source);
304 }
305
306 objArrKeys.forEach(function (key) {
307 var arr = objArr[key];
308
309 if (firstFields.indexOf(key) !== -1) {
310 asyncSerialArray(arr, func, next);
311 } else {
312 asyncParallelArray(arr, func, next);
313 }
314 });
315 });
316 pending["catch"](function (e) {
317 return e;
318 });
319 return pending;
320}
321
322function isErrorObj(obj) {
323 return !!(obj && obj.message !== undefined);
324}
325
326function getValue(value, path) {
327 var v = value;
328
329 for (var i = 0; i < path.length; i++) {
330 if (v == undefined) {
331 return v;
332 }
333
334 v = v[path[i]];
335 }
336
337 return v;
338}
339
340function complementError(rule, source) {
341 return function (oe) {
342 var fieldValue;
343
344 if (rule.fullFields) {
345 fieldValue = getValue(source, rule.fullFields);
346 } else {
347 fieldValue = source[oe.field || rule.fullField];
348 }
349
350 if (isErrorObj(oe)) {
351 oe.field = oe.field || rule.fullField;
352 oe.fieldValue = fieldValue;
353 return oe;
354 }
355
356 return {
357 message: typeof oe === 'function' ? oe() : oe,
358 fieldValue: fieldValue,
359 field: oe.field || rule.fullField
360 };
361 };
362}
363function deepMerge(target, source) {
364 if (source) {
365 for (var s in source) {
366 if (source.hasOwnProperty(s)) {
367 var value = source[s];
368
369 if (typeof value === 'object' && typeof target[s] === 'object') {
370 target[s] = _extends({}, target[s], value);
371 } else {
372 target[s] = value;
373 }
374 }
375 }
376 }
377
378 return target;
379}
380
381var required$1 = function required(rule, value, source, errors, options, type) {
382 if (rule.required && (!source.hasOwnProperty(rule.field) || isEmptyValue(value, type || rule.type))) {
383 errors.push(format(options.messages.required, rule.fullField));
384 }
385};
386
387/**
388 * Rule for validating whitespace.
389 *
390 * @param rule The validation rule.
391 * @param value The value of the field on the source object.
392 * @param source The source object being validated.
393 * @param errors An array of errors that this rule may add
394 * validation errors to.
395 * @param options The validation options.
396 * @param options.messages The validation messages.
397 */
398
399var whitespace = function whitespace(rule, value, source, errors, options) {
400 if (/^\s+$/.test(value) || value === '') {
401 errors.push(format(options.messages.whitespace, rule.fullField));
402 }
403};
404
405// https://github.com/kevva/url-regex/blob/master/index.js
406var urlReg;
407var getUrlRegex = (function () {
408 if (urlReg) {
409 return urlReg;
410 }
411
412 var word = '[a-fA-F\\d:]';
413
414 var b = function b(options) {
415 return options && options.includeBoundaries ? "(?:(?<=\\s|^)(?=" + word + ")|(?<=" + word + ")(?=\\s|$))" : '';
416 };
417
418 var v4 = '(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]\\d|\\d)(?:\\.(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]\\d|\\d)){3}';
419 var v6seg = '[a-fA-F\\d]{1,4}';
420 var v6 = ("\n(?:\n(?:" + v6seg + ":){7}(?:" + v6seg + "|:)| // 1:2:3:4:5:6:7:: 1:2:3:4:5:6:7:8\n(?:" + v6seg + ":){6}(?:" + v4 + "|:" + v6seg + "|:)| // 1:2:3:4:5:6:: 1:2:3:4:5:6::8 1:2:3:4:5:6::8 1:2:3:4:5:6::1.2.3.4\n(?:" + v6seg + ":){5}(?::" + v4 + "|(?::" + v6seg + "){1,2}|:)| // 1:2:3:4:5:: 1:2:3:4:5::7:8 1:2:3:4:5::8 1:2:3:4:5::7:1.2.3.4\n(?:" + v6seg + ":){4}(?:(?::" + v6seg + "){0,1}:" + v4 + "|(?::" + v6seg + "){1,3}|:)| // 1:2:3:4:: 1:2:3:4::6:7:8 1:2:3:4::8 1:2:3:4::6:7:1.2.3.4\n(?:" + v6seg + ":){3}(?:(?::" + v6seg + "){0,2}:" + v4 + "|(?::" + v6seg + "){1,4}|:)| // 1:2:3:: 1:2:3::5:6:7:8 1:2:3::8 1:2:3::5:6:7:1.2.3.4\n(?:" + v6seg + ":){2}(?:(?::" + v6seg + "){0,3}:" + v4 + "|(?::" + v6seg + "){1,5}|:)| // 1:2:: 1:2::4:5:6:7:8 1:2::8 1:2::4:5:6:7:1.2.3.4\n(?:" + v6seg + ":){1}(?:(?::" + v6seg + "){0,4}:" + v4 + "|(?::" + v6seg + "){1,6}|:)| // 1:: 1::3:4:5:6:7:8 1::8 1::3:4:5:6:7:1.2.3.4\n(?::(?:(?::" + v6seg + "){0,5}:" + v4 + "|(?::" + v6seg + "){1,7}|:)) // ::2:3:4:5:6:7:8 ::2:3:4:5:6:7:8 ::8 ::1.2.3.4\n)(?:%[0-9a-zA-Z]{1,})? // %eth0 %1\n").replace(/\s*\/\/.*$/gm, '').replace(/\n/g, '').trim(); // Pre-compile only the exact regexes because adding a global flag make regexes stateful
421
422 var v46Exact = new RegExp("(?:^" + v4 + "$)|(?:^" + v6 + "$)");
423 var v4exact = new RegExp("^" + v4 + "$");
424 var v6exact = new RegExp("^" + v6 + "$");
425
426 var ip = function ip(options) {
427 return options && options.exact ? v46Exact : new RegExp("(?:" + b(options) + v4 + b(options) + ")|(?:" + b(options) + v6 + b(options) + ")", 'g');
428 };
429
430 ip.v4 = function (options) {
431 return options && options.exact ? v4exact : new RegExp("" + b(options) + v4 + b(options), 'g');
432 };
433
434 ip.v6 = function (options) {
435 return options && options.exact ? v6exact : new RegExp("" + b(options) + v6 + b(options), 'g');
436 };
437
438 var protocol = "(?:(?:[a-z]+:)?//)";
439 var auth = '(?:\\S+(?::\\S*)?@)?';
440 var ipv4 = ip.v4().source;
441 var ipv6 = ip.v6().source;
442 var host = "(?:(?:[a-z\\u00a1-\\uffff0-9][-_]*)*[a-z\\u00a1-\\uffff0-9]+)";
443 var domain = "(?:\\.(?:[a-z\\u00a1-\\uffff0-9]-*)*[a-z\\u00a1-\\uffff0-9]+)*";
444 var tld = "(?:\\.(?:[a-z\\u00a1-\\uffff]{2,}))";
445 var port = '(?::\\d{2,5})?';
446 var path = '(?:[/?#][^\\s"]*)?';
447 var regex = "(?:" + protocol + "|www\\.)" + auth + "(?:localhost|" + ipv4 + "|" + ipv6 + "|" + host + domain + tld + ")" + port + path;
448 urlReg = new RegExp("(?:^" + regex + "$)", 'i');
449 return urlReg;
450});
451
452/* eslint max-len:0 */
453
454var pattern$2 = {
455 // http://emailregex.com/
456 email: /^(([^<>()\[\]\\.,;:\s@"]+(\.[^<>()\[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}])|(([a-zA-Z\-0-9\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF]+\.)+[a-zA-Z\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF]{2,}))$/,
457 // url: new RegExp(
458 // '^(?!mailto:)(?:(?:http|https|ftp)://|//)(?:\\S+(?::\\S*)?@)?(?:(?:(?:[1-9]\\d?|1\\d\\d|2[01]\\d|22[0-3])(?:\\.(?:1?\\d{1,2}|2[0-4]\\d|25[0-5])){2}(?:\\.(?:[0-9]\\d?|1\\d\\d|2[0-4]\\d|25[0-4]))|(?:(?:[a-z\\u00a1-\\uffff0-9]+-*)*[a-z\\u00a1-\\uffff0-9]+)(?:\\.(?:[a-z\\u00a1-\\uffff0-9]+-*)*[a-z\\u00a1-\\uffff0-9]+)*(?:\\.(?:[a-z\\u00a1-\\uffff]{2,})))|localhost)(?::\\d{2,5})?(?:(/|\\?|#)[^\\s]*)?$',
459 // 'i',
460 // ),
461 hex: /^#?([a-f0-9]{6}|[a-f0-9]{3})$/i
462};
463var types = {
464 integer: function integer(value) {
465 return types.number(value) && parseInt(value, 10) === value;
466 },
467 "float": function float(value) {
468 return types.number(value) && !types.integer(value);
469 },
470 array: function array(value) {
471 return Array.isArray(value);
472 },
473 regexp: function regexp(value) {
474 if (value instanceof RegExp) {
475 return true;
476 }
477
478 try {
479 return !!new RegExp(value);
480 } catch (e) {
481 return false;
482 }
483 },
484 date: function date(value) {
485 return typeof value.getTime === 'function' && typeof value.getMonth === 'function' && typeof value.getYear === 'function' && !isNaN(value.getTime());
486 },
487 number: function number(value) {
488 if (isNaN(value)) {
489 return false;
490 }
491
492 return typeof value === 'number';
493 },
494 object: function object(value) {
495 return typeof value === 'object' && !types.array(value);
496 },
497 method: function method(value) {
498 return typeof value === 'function';
499 },
500 email: function email(value) {
501 return typeof value === 'string' && value.length <= 320 && !!value.match(pattern$2.email);
502 },
503 url: function url(value) {
504 return typeof value === 'string' && value.length <= 2048 && !!value.match(getUrlRegex());
505 },
506 hex: function hex(value) {
507 return typeof value === 'string' && !!value.match(pattern$2.hex);
508 }
509};
510
511var type$1 = function type(rule, value, source, errors, options) {
512 if (rule.required && value === undefined) {
513 required$1(rule, value, source, errors, options);
514 return;
515 }
516
517 var custom = ['integer', 'float', 'array', 'regexp', 'object', 'method', 'email', 'number', 'date', 'url', 'hex'];
518 var ruleType = rule.type;
519
520 if (custom.indexOf(ruleType) > -1) {
521 if (!types[ruleType](value)) {
522 errors.push(format(options.messages.types[ruleType], rule.fullField, rule.type));
523 } // straight typeof check
524
525 } else if (ruleType && typeof value !== rule.type) {
526 errors.push(format(options.messages.types[ruleType], rule.fullField, rule.type));
527 }
528};
529
530var range = function range(rule, value, source, errors, options) {
531 var len = typeof rule.len === 'number';
532 var min = typeof rule.min === 'number';
533 var max = typeof rule.max === 'number'; // 正则匹配码点范围从U+010000一直到U+10FFFF的文字(补充平面Supplementary Plane)
534
535 var spRegexp = /[\uD800-\uDBFF][\uDC00-\uDFFF]/g;
536 var val = value;
537 var key = null;
538 var num = typeof value === 'number';
539 var str = typeof value === 'string';
540 var arr = Array.isArray(value);
541
542 if (num) {
543 key = 'number';
544 } else if (str) {
545 key = 'string';
546 } else if (arr) {
547 key = 'array';
548 } // if the value is not of a supported type for range validation
549 // the validation rule rule should use the
550 // type property to also test for a particular type
551
552
553 if (!key) {
554 return false;
555 }
556
557 if (arr) {
558 val = value.length;
559 }
560
561 if (str) {
562 // 处理码点大于U+010000的文字length属性不准确的bug,如"𠮷𠮷𠮷".lenght !== 3
563 val = value.replace(spRegexp, '_').length;
564 }
565
566 if (len) {
567 if (val !== rule.len) {
568 errors.push(format(options.messages[key].len, rule.fullField, rule.len));
569 }
570 } else if (min && !max && val < rule.min) {
571 errors.push(format(options.messages[key].min, rule.fullField, rule.min));
572 } else if (max && !min && val > rule.max) {
573 errors.push(format(options.messages[key].max, rule.fullField, rule.max));
574 } else if (min && max && (val < rule.min || val > rule.max)) {
575 errors.push(format(options.messages[key].range, rule.fullField, rule.min, rule.max));
576 }
577};
578
579var ENUM$1 = 'enum';
580
581var enumerable$1 = function enumerable(rule, value, source, errors, options) {
582 rule[ENUM$1] = Array.isArray(rule[ENUM$1]) ? rule[ENUM$1] : [];
583
584 if (rule[ENUM$1].indexOf(value) === -1) {
585 errors.push(format(options.messages[ENUM$1], rule.fullField, rule[ENUM$1].join(', ')));
586 }
587};
588
589var pattern$1 = function pattern(rule, value, source, errors, options) {
590 if (rule.pattern) {
591 if (rule.pattern instanceof RegExp) {
592 // if a RegExp instance is passed, reset `lastIndex` in case its `global`
593 // flag is accidentally set to `true`, which in a validation scenario
594 // is not necessary and the result might be misleading
595 rule.pattern.lastIndex = 0;
596
597 if (!rule.pattern.test(value)) {
598 errors.push(format(options.messages.pattern.mismatch, rule.fullField, value, rule.pattern));
599 }
600 } else if (typeof rule.pattern === 'string') {
601 var _pattern = new RegExp(rule.pattern);
602
603 if (!_pattern.test(value)) {
604 errors.push(format(options.messages.pattern.mismatch, rule.fullField, value, rule.pattern));
605 }
606 }
607 }
608};
609
610var rules = {
611 required: required$1,
612 whitespace: whitespace,
613 type: type$1,
614 range: range,
615 "enum": enumerable$1,
616 pattern: pattern$1
617};
618
619var string = function string(rule, value, callback, source, options) {
620 var errors = [];
621 var validate = rule.required || !rule.required && source.hasOwnProperty(rule.field);
622
623 if (validate) {
624 if (isEmptyValue(value, 'string') && !rule.required) {
625 return callback();
626 }
627
628 rules.required(rule, value, source, errors, options, 'string');
629
630 if (!isEmptyValue(value, 'string')) {
631 rules.type(rule, value, source, errors, options);
632 rules.range(rule, value, source, errors, options);
633 rules.pattern(rule, value, source, errors, options);
634
635 if (rule.whitespace === true) {
636 rules.whitespace(rule, value, source, errors, options);
637 }
638 }
639 }
640
641 callback(errors);
642};
643
644var method = function method(rule, value, callback, source, options) {
645 var errors = [];
646 var validate = rule.required || !rule.required && source.hasOwnProperty(rule.field);
647
648 if (validate) {
649 if (isEmptyValue(value) && !rule.required) {
650 return callback();
651 }
652
653 rules.required(rule, value, source, errors, options);
654
655 if (value !== undefined) {
656 rules.type(rule, value, source, errors, options);
657 }
658 }
659
660 callback(errors);
661};
662
663var number = function number(rule, value, callback, source, options) {
664 var errors = [];
665 var validate = rule.required || !rule.required && source.hasOwnProperty(rule.field);
666
667 if (validate) {
668 if (value === '') {
669 value = undefined;
670 }
671
672 if (isEmptyValue(value) && !rule.required) {
673 return callback();
674 }
675
676 rules.required(rule, value, source, errors, options);
677
678 if (value !== undefined) {
679 rules.type(rule, value, source, errors, options);
680 rules.range(rule, value, source, errors, options);
681 }
682 }
683
684 callback(errors);
685};
686
687var _boolean = function _boolean(rule, value, callback, source, options) {
688 var errors = [];
689 var validate = rule.required || !rule.required && source.hasOwnProperty(rule.field);
690
691 if (validate) {
692 if (isEmptyValue(value) && !rule.required) {
693 return callback();
694 }
695
696 rules.required(rule, value, source, errors, options);
697
698 if (value !== undefined) {
699 rules.type(rule, value, source, errors, options);
700 }
701 }
702
703 callback(errors);
704};
705
706var regexp = function regexp(rule, value, callback, source, options) {
707 var errors = [];
708 var validate = rule.required || !rule.required && source.hasOwnProperty(rule.field);
709
710 if (validate) {
711 if (isEmptyValue(value) && !rule.required) {
712 return callback();
713 }
714
715 rules.required(rule, value, source, errors, options);
716
717 if (!isEmptyValue(value)) {
718 rules.type(rule, value, source, errors, options);
719 }
720 }
721
722 callback(errors);
723};
724
725var integer = function integer(rule, value, callback, source, options) {
726 var errors = [];
727 var validate = rule.required || !rule.required && source.hasOwnProperty(rule.field);
728
729 if (validate) {
730 if (isEmptyValue(value) && !rule.required) {
731 return callback();
732 }
733
734 rules.required(rule, value, source, errors, options);
735
736 if (value !== undefined) {
737 rules.type(rule, value, source, errors, options);
738 rules.range(rule, value, source, errors, options);
739 }
740 }
741
742 callback(errors);
743};
744
745var floatFn = function floatFn(rule, value, callback, source, options) {
746 var errors = [];
747 var validate = rule.required || !rule.required && source.hasOwnProperty(rule.field);
748
749 if (validate) {
750 if (isEmptyValue(value) && !rule.required) {
751 return callback();
752 }
753
754 rules.required(rule, value, source, errors, options);
755
756 if (value !== undefined) {
757 rules.type(rule, value, source, errors, options);
758 rules.range(rule, value, source, errors, options);
759 }
760 }
761
762 callback(errors);
763};
764
765var array = function array(rule, value, callback, source, options) {
766 var errors = [];
767 var validate = rule.required || !rule.required && source.hasOwnProperty(rule.field);
768
769 if (validate) {
770 if ((value === undefined || value === null) && !rule.required) {
771 return callback();
772 }
773
774 rules.required(rule, value, source, errors, options, 'array');
775
776 if (value !== undefined && value !== null) {
777 rules.type(rule, value, source, errors, options);
778 rules.range(rule, value, source, errors, options);
779 }
780 }
781
782 callback(errors);
783};
784
785var object = function object(rule, value, callback, source, options) {
786 var errors = [];
787 var validate = rule.required || !rule.required && source.hasOwnProperty(rule.field);
788
789 if (validate) {
790 if (isEmptyValue(value) && !rule.required) {
791 return callback();
792 }
793
794 rules.required(rule, value, source, errors, options);
795
796 if (value !== undefined) {
797 rules.type(rule, value, source, errors, options);
798 }
799 }
800
801 callback(errors);
802};
803
804var ENUM = 'enum';
805
806var enumerable = function enumerable(rule, value, callback, source, options) {
807 var errors = [];
808 var validate = rule.required || !rule.required && source.hasOwnProperty(rule.field);
809
810 if (validate) {
811 if (isEmptyValue(value) && !rule.required) {
812 return callback();
813 }
814
815 rules.required(rule, value, source, errors, options);
816
817 if (value !== undefined) {
818 rules[ENUM](rule, value, source, errors, options);
819 }
820 }
821
822 callback(errors);
823};
824
825var pattern = function pattern(rule, value, callback, source, options) {
826 var errors = [];
827 var validate = rule.required || !rule.required && source.hasOwnProperty(rule.field);
828
829 if (validate) {
830 if (isEmptyValue(value, 'string') && !rule.required) {
831 return callback();
832 }
833
834 rules.required(rule, value, source, errors, options);
835
836 if (!isEmptyValue(value, 'string')) {
837 rules.pattern(rule, value, source, errors, options);
838 }
839 }
840
841 callback(errors);
842};
843
844var date = function date(rule, value, callback, source, options) {
845 // console.log('integer rule called %j', rule);
846 var errors = [];
847 var validate = rule.required || !rule.required && source.hasOwnProperty(rule.field); // console.log('validate on %s value', value);
848
849 if (validate) {
850 if (isEmptyValue(value, 'date') && !rule.required) {
851 return callback();
852 }
853
854 rules.required(rule, value, source, errors, options);
855
856 if (!isEmptyValue(value, 'date')) {
857 var dateObject;
858
859 if (value instanceof Date) {
860 dateObject = value;
861 } else {
862 dateObject = new Date(value);
863 }
864
865 rules.type(rule, dateObject, source, errors, options);
866
867 if (dateObject) {
868 rules.range(rule, dateObject.getTime(), source, errors, options);
869 }
870 }
871 }
872
873 callback(errors);
874};
875
876var required = function required(rule, value, callback, source, options) {
877 var errors = [];
878 var type = Array.isArray(value) ? 'array' : typeof value;
879 rules.required(rule, value, source, errors, options, type);
880 callback(errors);
881};
882
883var type = function type(rule, value, callback, source, options) {
884 var ruleType = rule.type;
885 var errors = [];
886 var validate = rule.required || !rule.required && source.hasOwnProperty(rule.field);
887
888 if (validate) {
889 if (isEmptyValue(value, ruleType) && !rule.required) {
890 return callback();
891 }
892
893 rules.required(rule, value, source, errors, options, ruleType);
894
895 if (!isEmptyValue(value, ruleType)) {
896 rules.type(rule, value, source, errors, options);
897 }
898 }
899
900 callback(errors);
901};
902
903var any = function any(rule, value, callback, source, options) {
904 var errors = [];
905 var validate = rule.required || !rule.required && source.hasOwnProperty(rule.field);
906
907 if (validate) {
908 if (isEmptyValue(value) && !rule.required) {
909 return callback();
910 }
911
912 rules.required(rule, value, source, errors, options);
913 }
914
915 callback(errors);
916};
917
918var validators = {
919 string: string,
920 method: method,
921 number: number,
922 "boolean": _boolean,
923 regexp: regexp,
924 integer: integer,
925 "float": floatFn,
926 array: array,
927 object: object,
928 "enum": enumerable,
929 pattern: pattern,
930 date: date,
931 url: type,
932 hex: type,
933 email: type,
934 required: required,
935 any: any
936};
937
938function newMessages() {
939 return {
940 "default": 'Validation error on field %s',
941 required: '%s is required',
942 "enum": '%s must be one of %s',
943 whitespace: '%s cannot be empty',
944 date: {
945 format: '%s date %s is invalid for format %s',
946 parse: '%s date could not be parsed, %s is invalid ',
947 invalid: '%s date %s is invalid'
948 },
949 types: {
950 string: '%s is not a %s',
951 method: '%s is not a %s (function)',
952 array: '%s is not an %s',
953 object: '%s is not an %s',
954 number: '%s is not a %s',
955 date: '%s is not a %s',
956 "boolean": '%s is not a %s',
957 integer: '%s is not an %s',
958 "float": '%s is not a %s',
959 regexp: '%s is not a valid %s',
960 email: '%s is not a valid %s',
961 url: '%s is not a valid %s',
962 hex: '%s is not a valid %s'
963 },
964 string: {
965 len: '%s must be exactly %s characters',
966 min: '%s must be at least %s characters',
967 max: '%s cannot be longer than %s characters',
968 range: '%s must be between %s and %s characters'
969 },
970 number: {
971 len: '%s must equal %s',
972 min: '%s cannot be less than %s',
973 max: '%s cannot be greater than %s',
974 range: '%s must be between %s and %s'
975 },
976 array: {
977 len: '%s must be exactly %s in length',
978 min: '%s cannot be less than %s in length',
979 max: '%s cannot be greater than %s in length',
980 range: '%s must be between %s and %s in length'
981 },
982 pattern: {
983 mismatch: '%s value %s does not match pattern %s'
984 },
985 clone: function clone() {
986 var cloned = JSON.parse(JSON.stringify(this));
987 cloned.clone = this.clone;
988 return cloned;
989 }
990 };
991}
992var messages = newMessages();
993
994/**
995 * Encapsulates a validation schema.
996 *
997 * @param descriptor An object declaring validation rules
998 * for this schema.
999 */
1000
1001var Schema = /*#__PURE__*/function () {
1002 // ========================= Static =========================
1003 // ======================== Instance ========================
1004 function Schema(descriptor) {
1005 this.rules = null;
1006 this._messages = messages;
1007 this.define(descriptor);
1008 }
1009
1010 var _proto = Schema.prototype;
1011
1012 _proto.define = function define(rules) {
1013 var _this = this;
1014
1015 if (!rules) {
1016 throw new Error('Cannot configure a schema with no rules');
1017 }
1018
1019 if (typeof rules !== 'object' || Array.isArray(rules)) {
1020 throw new Error('Rules must be an object');
1021 }
1022
1023 this.rules = {};
1024 Object.keys(rules).forEach(function (name) {
1025 var item = rules[name];
1026 _this.rules[name] = Array.isArray(item) ? item : [item];
1027 });
1028 };
1029
1030 _proto.messages = function messages(_messages) {
1031 if (_messages) {
1032 this._messages = deepMerge(newMessages(), _messages);
1033 }
1034
1035 return this._messages;
1036 };
1037
1038 _proto.validate = function validate(source_, o, oc) {
1039 var _this2 = this;
1040
1041 if (o === void 0) {
1042 o = {};
1043 }
1044
1045 if (oc === void 0) {
1046 oc = function oc() {};
1047 }
1048
1049 var source = source_;
1050 var options = o;
1051 var callback = oc;
1052
1053 if (typeof options === 'function') {
1054 callback = options;
1055 options = {};
1056 }
1057
1058 if (!this.rules || Object.keys(this.rules).length === 0) {
1059 if (callback) {
1060 callback(null, source);
1061 }
1062
1063 return Promise.resolve(source);
1064 }
1065
1066 function complete(results) {
1067 var errors = [];
1068 var fields = {};
1069
1070 function add(e) {
1071 if (Array.isArray(e)) {
1072 var _errors;
1073
1074 errors = (_errors = errors).concat.apply(_errors, e);
1075 } else {
1076 errors.push(e);
1077 }
1078 }
1079
1080 for (var i = 0; i < results.length; i++) {
1081 add(results[i]);
1082 }
1083
1084 if (!errors.length) {
1085 callback(null, source);
1086 } else {
1087 fields = convertFieldsError(errors);
1088 callback(errors, fields);
1089 }
1090 }
1091
1092 if (options.messages) {
1093 var messages$1 = this.messages();
1094
1095 if (messages$1 === messages) {
1096 messages$1 = newMessages();
1097 }
1098
1099 deepMerge(messages$1, options.messages);
1100 options.messages = messages$1;
1101 } else {
1102 options.messages = this.messages();
1103 }
1104
1105 var series = {};
1106 var keys = options.keys || Object.keys(this.rules);
1107 keys.forEach(function (z) {
1108 var arr = _this2.rules[z];
1109 var value = source[z];
1110 arr.forEach(function (r) {
1111 var rule = r;
1112
1113 if (typeof rule.transform === 'function') {
1114 if (source === source_) {
1115 source = _extends({}, source);
1116 }
1117
1118 value = source[z] = rule.transform(value);
1119 }
1120
1121 if (typeof rule === 'function') {
1122 rule = {
1123 validator: rule
1124 };
1125 } else {
1126 rule = _extends({}, rule);
1127 } // Fill validator. Skip if nothing need to validate
1128
1129
1130 rule.validator = _this2.getValidationMethod(rule);
1131
1132 if (!rule.validator) {
1133 return;
1134 }
1135
1136 rule.field = z;
1137 rule.fullField = rule.fullField || z;
1138 rule.type = _this2.getType(rule);
1139 series[z] = series[z] || [];
1140 series[z].push({
1141 rule: rule,
1142 value: value,
1143 source: source,
1144 field: z
1145 });
1146 });
1147 });
1148 var errorFields = {};
1149 return asyncMap(series, options, function (data, doIt) {
1150 var rule = data.rule;
1151 var deep = (rule.type === 'object' || rule.type === 'array') && (typeof rule.fields === 'object' || typeof rule.defaultField === 'object');
1152 deep = deep && (rule.required || !rule.required && data.value);
1153 rule.field = data.field;
1154
1155 function addFullField(key, schema) {
1156 return _extends({}, schema, {
1157 fullField: rule.fullField + "." + key,
1158 fullFields: rule.fullFields ? [].concat(rule.fullFields, [key]) : [key]
1159 });
1160 }
1161
1162 function cb(e) {
1163 if (e === void 0) {
1164 e = [];
1165 }
1166
1167 var errorList = Array.isArray(e) ? e : [e];
1168
1169 if (!options.suppressWarning && errorList.length) {
1170 Schema.warning('async-validator:', errorList);
1171 }
1172
1173 if (errorList.length && rule.message !== undefined) {
1174 errorList = [].concat(rule.message);
1175 } // Fill error info
1176
1177
1178 var filledErrors = errorList.map(complementError(rule, source));
1179
1180 if (options.first && filledErrors.length) {
1181 errorFields[rule.field] = 1;
1182 return doIt(filledErrors);
1183 }
1184
1185 if (!deep) {
1186 doIt(filledErrors);
1187 } else {
1188 // if rule is required but the target object
1189 // does not exist fail at the rule level and don't
1190 // go deeper
1191 if (rule.required && !data.value) {
1192 if (rule.message !== undefined) {
1193 filledErrors = [].concat(rule.message).map(complementError(rule, source));
1194 } else if (options.error) {
1195 filledErrors = [options.error(rule, format(options.messages.required, rule.field))];
1196 }
1197
1198 return doIt(filledErrors);
1199 }
1200
1201 var fieldsSchema = {};
1202
1203 if (rule.defaultField) {
1204 Object.keys(data.value).map(function (key) {
1205 fieldsSchema[key] = rule.defaultField;
1206 });
1207 }
1208
1209 fieldsSchema = _extends({}, fieldsSchema, data.rule.fields);
1210 var paredFieldsSchema = {};
1211 Object.keys(fieldsSchema).forEach(function (field) {
1212 var fieldSchema = fieldsSchema[field];
1213 var fieldSchemaList = Array.isArray(fieldSchema) ? fieldSchema : [fieldSchema];
1214 paredFieldsSchema[field] = fieldSchemaList.map(addFullField.bind(null, field));
1215 });
1216 var schema = new Schema(paredFieldsSchema);
1217 schema.messages(options.messages);
1218
1219 if (data.rule.options) {
1220 data.rule.options.messages = options.messages;
1221 data.rule.options.error = options.error;
1222 }
1223
1224 schema.validate(data.value, data.rule.options || options, function (errs) {
1225 var finalErrors = [];
1226
1227 if (filledErrors && filledErrors.length) {
1228 finalErrors.push.apply(finalErrors, filledErrors);
1229 }
1230
1231 if (errs && errs.length) {
1232 finalErrors.push.apply(finalErrors, errs);
1233 }
1234
1235 doIt(finalErrors.length ? finalErrors : null);
1236 });
1237 }
1238 }
1239
1240 var res;
1241
1242 if (rule.asyncValidator) {
1243 res = rule.asyncValidator(rule, data.value, cb, data.source, options);
1244 } else if (rule.validator) {
1245 try {
1246 res = rule.validator(rule, data.value, cb, data.source, options);
1247 } catch (error) {
1248 console.error == null ? void 0 : console.error(error); // rethrow to report error
1249
1250 if (!options.suppressValidatorError) {
1251 setTimeout(function () {
1252 throw error;
1253 }, 0);
1254 }
1255
1256 cb(error.message);
1257 }
1258
1259 if (res === true) {
1260 cb();
1261 } else if (res === false) {
1262 cb(typeof rule.message === 'function' ? rule.message(rule.fullField || rule.field) : rule.message || (rule.fullField || rule.field) + " fails");
1263 } else if (res instanceof Array) {
1264 cb(res);
1265 } else if (res instanceof Error) {
1266 cb(res.message);
1267 }
1268 }
1269
1270 if (res && res.then) {
1271 res.then(function () {
1272 return cb();
1273 }, function (e) {
1274 return cb(e);
1275 });
1276 }
1277 }, function (results) {
1278 complete(results);
1279 }, source);
1280 };
1281
1282 _proto.getType = function getType(rule) {
1283 if (rule.type === undefined && rule.pattern instanceof RegExp) {
1284 rule.type = 'pattern';
1285 }
1286
1287 if (typeof rule.validator !== 'function' && rule.type && !validators.hasOwnProperty(rule.type)) {
1288 throw new Error(format('Unknown rule type %s', rule.type));
1289 }
1290
1291 return rule.type || 'string';
1292 };
1293
1294 _proto.getValidationMethod = function getValidationMethod(rule) {
1295 if (typeof rule.validator === 'function') {
1296 return rule.validator;
1297 }
1298
1299 var keys = Object.keys(rule);
1300 var messageIndex = keys.indexOf('message');
1301
1302 if (messageIndex !== -1) {
1303 keys.splice(messageIndex, 1);
1304 }
1305
1306 if (keys.length === 1 && keys[0] === 'required') {
1307 return validators.required;
1308 }
1309
1310 return validators[this.getType(rule)] || undefined;
1311 };
1312
1313 return Schema;
1314}();
1315
1316Schema.register = function register(type, validator) {
1317 if (typeof validator !== 'function') {
1318 throw new Error('Cannot register a validator by type, validator is not a function');
1319 }
1320
1321 validators[type] = validator;
1322};
1323
1324Schema.warning = warning;
1325Schema.messages = messages;
1326Schema.validators = validators;
1327
1328export { Schema as default };
1329//# sourceMappingURL=index.js.map