UNPKG

13.5 kBJavaScriptView Raw
1"use strict";
2
3Object.defineProperty(exports, "__esModule", {
4 value: true
5});
6exports.validateRules = validateRules;
7
8var _regenerator = _interopRequireDefault(require("@babel/runtime/regenerator"));
9
10var _asyncValidator = _interopRequireDefault(require("async-validator"));
11
12var _vue = require("vue");
13
14var _warning = require("../../vc-util/warning");
15
16var _valueUtil = require("./valueUtil");
17
18var _messages = require("./messages");
19
20var _propsUtil = require("../../_util/props-util");
21
22function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
23
24function _toConsumableArray(arr) { return _arrayWithoutHoles(arr) || _iterableToArray(arr) || _unsupportedIterableToArray(arr) || _nonIterableSpread(); }
25
26function _nonIterableSpread() { throw new TypeError("Invalid attempt to spread non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); }
27
28function _unsupportedIterableToArray(o, minLen) { if (!o) return; if (typeof o === "string") return _arrayLikeToArray(o, minLen); var n = Object.prototype.toString.call(o).slice(8, -1); if (n === "Object" && o.constructor) n = o.constructor.name; if (n === "Map" || n === "Set") return Array.from(o); if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _arrayLikeToArray(o, minLen); }
29
30function _iterableToArray(iter) { if (typeof Symbol !== "undefined" && Symbol.iterator in Object(iter)) return Array.from(iter); }
31
32function _arrayWithoutHoles(arr) { if (Array.isArray(arr)) return _arrayLikeToArray(arr); }
33
34function _arrayLikeToArray(arr, len) { if (len == null || len > arr.length) len = arr.length; for (var i = 0, arr2 = new Array(len); i < len; i++) { arr2[i] = arr[i]; } return arr2; }
35
36function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }
37
38function _typeof(obj) { "@babel/helpers - typeof"; if (typeof Symbol === "function" && typeof Symbol.iterator === "symbol") { _typeof = function _typeof(obj) { return typeof obj; }; } else { _typeof = function _typeof(obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }; } return _typeof(obj); }
39
40function _extends() { _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; return _extends.apply(this, arguments); }
41
42var __awaiter = void 0 && (void 0).__awaiter || function (thisArg, _arguments, P, generator) {
43 function adopt(value) {
44 return value instanceof P ? value : new P(function (resolve) {
45 resolve(value);
46 });
47 }
48
49 return new (P || (P = Promise))(function (resolve, reject) {
50 function fulfilled(value) {
51 try {
52 step(generator.next(value));
53 } catch (e) {
54 reject(e);
55 }
56 }
57
58 function rejected(value) {
59 try {
60 step(generator["throw"](value));
61 } catch (e) {
62 reject(e);
63 }
64 }
65
66 function step(result) {
67 result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected);
68 }
69
70 step((generator = generator.apply(thisArg, _arguments || [])).next());
71 });
72};
73
74// Remove incorrect original ts define
75var AsyncValidator = _asyncValidator.default;
76/**
77 * Replace with template.
78 * `I'm ${name}` + { name: 'bamboo' } = I'm bamboo
79 */
80
81function replaceMessage(template, kv) {
82 return template.replace(/\$\{\w+\}/g, function (str) {
83 var key = str.slice(2, -1);
84 return kv[key];
85 });
86}
87/**
88 * We use `async-validator` to validate rules. So have to hot replace the message with validator.
89 * { required: '${name} is required' } => { required: () => 'field is required' }
90 */
91
92
93function convertMessages(messages, name, rule, messageVariables) {
94 var kv = _extends(_extends({}, rule), {
95 name: name,
96 enum: (rule.enum || []).join(', ')
97 });
98
99 var replaceFunc = function replaceFunc(template, additionalKV) {
100 return function () {
101 return replaceMessage(template, _extends(_extends({}, kv), additionalKV));
102 };
103 };
104 /* eslint-disable no-param-reassign */
105
106
107 function fillTemplate(source) {
108 var target = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
109 Object.keys(source).forEach(function (ruleName) {
110 var value = source[ruleName];
111
112 if (typeof value === 'string') {
113 target[ruleName] = replaceFunc(value, messageVariables);
114 } else if (value && _typeof(value) === 'object') {
115 target[ruleName] = {};
116 fillTemplate(value, target[ruleName]);
117 } else {
118 target[ruleName] = value;
119 }
120 });
121 return target;
122 }
123 /* eslint-enable */
124
125
126 return fillTemplate((0, _valueUtil.setValues)({}, _messages.defaultValidateMessages, messages));
127}
128
129function validateRule(name, value, rule, options, messageVariables) {
130 return __awaiter(this, void 0, void 0, /*#__PURE__*/_regenerator.default.mark(function _callee() {
131 var cloneRule, subRuleField, validator, messages, result, subResults;
132 return _regenerator.default.wrap(function _callee$(_context) {
133 while (1) {
134 switch (_context.prev = _context.next) {
135 case 0:
136 cloneRule = _extends({}, rule); // We should special handle array validate
137
138 subRuleField = null;
139
140 if (cloneRule && cloneRule.type === 'array' && cloneRule.defaultField) {
141 subRuleField = cloneRule.defaultField;
142 delete cloneRule.defaultField;
143 }
144
145 if (!rule.type && typeof rule.validator !== 'function' && typeof value !== 'string' && typeof value !== 'undefined') {
146 (0, _warning.warning)(false, "Form rules must provide type property when validating the form item named [".concat(name, "] which is not string type"));
147 }
148
149 validator = new AsyncValidator(_defineProperty({}, name, [cloneRule]));
150 messages = convertMessages(options.validateMessages, name, cloneRule, messageVariables);
151 validator.messages(messages);
152 result = [];
153 _context.prev = 8;
154 _context.next = 11;
155 return Promise.resolve(validator.validate(_defineProperty({}, name, value), _extends({}, options)));
156
157 case 11:
158 _context.next = 16;
159 break;
160
161 case 13:
162 _context.prev = 13;
163 _context.t0 = _context["catch"](8);
164
165 if (_context.t0.errors) {
166 result = _context.t0.errors.map(function (_ref, index) {
167 var message = _ref.message;
168 return (// Wrap VueNode with `key`
169 (0, _propsUtil.isValidElement)(message) ? (0, _vue.cloneVNode)(message, {
170 key: "error_".concat(index)
171 }) : message
172 );
173 });
174 } else {
175 console.error(_context.t0);
176 result = [messages.default()];
177 }
178
179 case 16:
180 if (!(!result.length && subRuleField)) {
181 _context.next = 21;
182 break;
183 }
184
185 _context.next = 19;
186 return Promise.all(value.map(function (subValue, i) {
187 return validateRule("".concat(name, ".").concat(i), subValue, subRuleField, options, messageVariables);
188 }));
189
190 case 19:
191 subResults = _context.sent;
192 return _context.abrupt("return", subResults.reduce(function (prev, errors) {
193 return [].concat(_toConsumableArray(prev), _toConsumableArray(errors));
194 }, []));
195
196 case 21:
197 return _context.abrupt("return", result);
198
199 case 22:
200 case "end":
201 return _context.stop();
202 }
203 }
204 }, _callee, null, [[8, 13]]);
205 }));
206}
207/**
208 * We use `async-validator` to validate the value.
209 * But only check one value in a time to avoid namePath validate issue.
210 */
211
212
213function validateRules(namePath, value, rules, options, validateFirst, messageVariables) {
214 var _this = this;
215
216 var name = namePath.join('.'); // Fill rule with context
217
218 var filledRules = rules.map(function (currentRule) {
219 var originValidatorFunc = currentRule.validator;
220
221 if (!originValidatorFunc) {
222 return currentRule;
223 }
224
225 return _extends(_extends({}, currentRule), {
226 validator: function validator(rule, val, callback) {
227 var hasPromise = false; // Wrap callback only accept when promise not provided
228
229 var wrappedCallback = function wrappedCallback() {
230 for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) {
231 args[_key] = arguments[_key];
232 }
233
234 // Wait a tick to make sure return type is a promise
235 Promise.resolve().then(function () {
236 (0, _warning.warning)(!hasPromise, 'Your validator function has already return a promise. `callback` will be ignored.');
237
238 if (!hasPromise) {
239 callback.apply(void 0, args);
240 }
241 });
242 }; // Get promise
243
244
245 var promise = originValidatorFunc(rule, val, wrappedCallback);
246 hasPromise = promise && typeof promise.then === 'function' && typeof promise.catch === 'function';
247 /**
248 * 1. Use promise as the first priority.
249 * 2. If promise not exist, use callback with warning instead
250 */
251
252 (0, _warning.warning)(hasPromise, '`callback` is deprecated. Please return a promise instead.');
253
254 if (hasPromise) {
255 promise.then(function () {
256 callback();
257 }).catch(function (err) {
258 callback(err);
259 });
260 }
261 }
262 });
263 });
264 var summaryPromise;
265
266 if (validateFirst === true) {
267 // >>>>> Validate by serialization
268 summaryPromise = new Promise(function (resolve) {
269 return __awaiter(_this, void 0, void 0, /*#__PURE__*/_regenerator.default.mark(function _callee2() {
270 var i, errors;
271 return _regenerator.default.wrap(function _callee2$(_context2) {
272 while (1) {
273 switch (_context2.prev = _context2.next) {
274 case 0:
275 i = 0;
276
277 case 1:
278 if (!(i < filledRules.length)) {
279 _context2.next = 11;
280 break;
281 }
282
283 _context2.next = 4;
284 return validateRule(name, value, filledRules[i], options, messageVariables);
285
286 case 4:
287 errors = _context2.sent;
288
289 if (!errors.length) {
290 _context2.next = 8;
291 break;
292 }
293
294 resolve(errors);
295 return _context2.abrupt("return");
296
297 case 8:
298 i += 1;
299 _context2.next = 1;
300 break;
301
302 case 11:
303 /* eslint-enable */
304 resolve([]);
305
306 case 12:
307 case "end":
308 return _context2.stop();
309 }
310 }
311 }, _callee2);
312 }));
313 });
314 } else {
315 // >>>>> Validate by parallel
316 var rulePromises = filledRules.map(function (rule) {
317 return validateRule(name, value, rule, options, messageVariables);
318 });
319 summaryPromise = (validateFirst ? finishOnFirstFailed(rulePromises) : finishOnAllFailed(rulePromises)).then(function (errors) {
320 if (!errors.length) {
321 return [];
322 }
323
324 return Promise.reject(errors);
325 });
326 } // Internal catch error to avoid console error log.
327
328
329 summaryPromise.catch(function (e) {
330 return e;
331 });
332 return summaryPromise;
333}
334
335function finishOnAllFailed(rulePromises) {
336 return __awaiter(this, void 0, void 0, /*#__PURE__*/_regenerator.default.mark(function _callee3() {
337 return _regenerator.default.wrap(function _callee3$(_context3) {
338 while (1) {
339 switch (_context3.prev = _context3.next) {
340 case 0:
341 return _context3.abrupt("return", Promise.all(rulePromises).then(function (errorsList) {
342 var _ref2;
343
344 var errors = (_ref2 = []).concat.apply(_ref2, _toConsumableArray(errorsList));
345
346 return errors;
347 }));
348
349 case 1:
350 case "end":
351 return _context3.stop();
352 }
353 }
354 }, _callee3);
355 }));
356}
357
358function finishOnFirstFailed(rulePromises) {
359 return __awaiter(this, void 0, void 0, /*#__PURE__*/_regenerator.default.mark(function _callee4() {
360 var count;
361 return _regenerator.default.wrap(function _callee4$(_context4) {
362 while (1) {
363 switch (_context4.prev = _context4.next) {
364 case 0:
365 count = 0;
366 return _context4.abrupt("return", new Promise(function (resolve) {
367 rulePromises.forEach(function (promise) {
368 promise.then(function (errors) {
369 if (errors.length) {
370 resolve(errors);
371 }
372
373 count += 1;
374
375 if (count === rulePromises.length) {
376 resolve([]);
377 }
378 });
379 });
380 }));
381
382 case 2:
383 case "end":
384 return _context4.stop();
385 }
386 }
387 }, _callee4);
388 }));
389}
\No newline at end of file