validateUtil.js 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292
  1. import _toConsumableArray from "@babel/runtime/helpers/esm/toConsumableArray";
  2. import _defineProperty from "@babel/runtime/helpers/esm/defineProperty";
  3. import _objectSpread from "@babel/runtime/helpers/esm/objectSpread2";
  4. import _asyncToGenerator from "@babel/runtime/helpers/esm/asyncToGenerator";
  5. import _regeneratorRuntime from "@babel/runtime/regenerator";
  6. import RawAsyncValidator from 'async-validator';
  7. import { cloneVNode } from 'vue';
  8. import { warning } from '../../vc-util/warning';
  9. import { setValues } from './valueUtil';
  10. import { defaultValidateMessages } from './messages';
  11. import { isValidElement } from '../../_util/props-util';
  12. // Remove incorrect original ts define
  13. var AsyncValidator = RawAsyncValidator;
  14. /**
  15. * Replace with template.
  16. * `I'm ${name}` + { name: 'bamboo' } = I'm bamboo
  17. */
  18. function replaceMessage(template, kv) {
  19. return template.replace(/\$\{\w+\}/g, function (str) {
  20. var key = str.slice(2, -1);
  21. return kv[key];
  22. });
  23. }
  24. function validateRule(_x, _x2, _x3, _x4, _x5) {
  25. return _validateRule.apply(this, arguments);
  26. }
  27. /**
  28. * We use `async-validator` to validate the value.
  29. * But only check one value in a time to avoid namePath validate issue.
  30. */
  31. function _validateRule() {
  32. _validateRule = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime.mark(function _callee2(name, value, rule, options, messageVariables) {
  33. var cloneRule, subRuleField, validator, messages, result, subResults, kv, fillVariableResult;
  34. return _regeneratorRuntime.wrap(function _callee2$(_context2) {
  35. while (1) {
  36. switch (_context2.prev = _context2.next) {
  37. case 0:
  38. cloneRule = _objectSpread({}, rule); // Bug of `async-validator`
  39. delete cloneRule.ruleIndex;
  40. delete cloneRule.trigger;
  41. // We should special handle array validate
  42. subRuleField = null;
  43. if (cloneRule && cloneRule.type === 'array' && cloneRule.defaultField) {
  44. subRuleField = cloneRule.defaultField;
  45. delete cloneRule.defaultField;
  46. }
  47. validator = new AsyncValidator(_defineProperty({}, name, [cloneRule]));
  48. messages = setValues({}, defaultValidateMessages, options.validateMessages);
  49. validator.messages(messages);
  50. result = [];
  51. _context2.prev = 9;
  52. _context2.next = 12;
  53. return Promise.resolve(validator.validate(_defineProperty({}, name, value), _objectSpread({}, options)));
  54. case 12:
  55. _context2.next = 17;
  56. break;
  57. case 14:
  58. _context2.prev = 14;
  59. _context2.t0 = _context2["catch"](9);
  60. if (_context2.t0.errors) {
  61. result = _context2.t0.errors.map(function (_ref4, index) {
  62. var message = _ref4.message;
  63. return (
  64. // Wrap VueNode with `key`
  65. isValidElement(message) ? cloneVNode(message, {
  66. key: "error_".concat(index)
  67. }) : message
  68. );
  69. });
  70. } else {
  71. console.error(_context2.t0);
  72. result = [messages.default()];
  73. }
  74. case 17:
  75. if (!(!result.length && subRuleField)) {
  76. _context2.next = 22;
  77. break;
  78. }
  79. _context2.next = 20;
  80. return Promise.all(value.map(function (subValue, i) {
  81. return validateRule("".concat(name, ".").concat(i), subValue, subRuleField, options, messageVariables);
  82. }));
  83. case 20:
  84. subResults = _context2.sent;
  85. return _context2.abrupt("return", subResults.reduce(function (prev, errors) {
  86. return [].concat(_toConsumableArray(prev), _toConsumableArray(errors));
  87. }, []));
  88. case 22:
  89. // Replace message with variables
  90. kv = _objectSpread(_objectSpread({}, rule), {}, {
  91. name: name,
  92. enum: (rule.enum || []).join(', ')
  93. }, messageVariables);
  94. fillVariableResult = result.map(function (error) {
  95. if (typeof error === 'string') {
  96. return replaceMessage(error, kv);
  97. }
  98. return error;
  99. });
  100. return _context2.abrupt("return", fillVariableResult);
  101. case 25:
  102. case "end":
  103. return _context2.stop();
  104. }
  105. }
  106. }, _callee2, null, [[9, 14]]);
  107. }));
  108. return _validateRule.apply(this, arguments);
  109. }
  110. export function validateRules(namePath, value, rules, options, validateFirst, messageVariables) {
  111. var name = namePath.join('.');
  112. // Fill rule with context
  113. var filledRules = rules.map(function (currentRule, ruleIndex) {
  114. var originValidatorFunc = currentRule.validator;
  115. var cloneRule = _objectSpread(_objectSpread({}, currentRule), {}, {
  116. ruleIndex: ruleIndex
  117. });
  118. // Replace validator if needed
  119. if (originValidatorFunc) {
  120. cloneRule.validator = function (rule, val, callback) {
  121. var hasPromise = false;
  122. // Wrap callback only accept when promise not provided
  123. var wrappedCallback = function wrappedCallback() {
  124. for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) {
  125. args[_key] = arguments[_key];
  126. }
  127. // Wait a tick to make sure return type is a promise
  128. Promise.resolve().then(function () {
  129. warning(!hasPromise, 'Your validator function has already return a promise. `callback` will be ignored.');
  130. if (!hasPromise) {
  131. callback.apply(void 0, args);
  132. }
  133. });
  134. };
  135. // Get promise
  136. var promise = originValidatorFunc(rule, val, wrappedCallback);
  137. hasPromise = promise && typeof promise.then === 'function' && typeof promise.catch === 'function';
  138. /**
  139. * 1. Use promise as the first priority.
  140. * 2. If promise not exist, use callback with warning instead
  141. */
  142. warning(hasPromise, '`callback` is deprecated. Please return a promise instead.');
  143. if (hasPromise) {
  144. promise.then(function () {
  145. callback();
  146. }).catch(function (err) {
  147. callback(err || ' ');
  148. });
  149. }
  150. };
  151. }
  152. return cloneRule;
  153. }).sort(function (_ref, _ref2) {
  154. var w1 = _ref.warningOnly,
  155. i1 = _ref.ruleIndex;
  156. var w2 = _ref2.warningOnly,
  157. i2 = _ref2.ruleIndex;
  158. if (!!w1 === !!w2) {
  159. // Let keep origin order
  160. return i1 - i2;
  161. }
  162. if (w1) {
  163. return 1;
  164. }
  165. return -1;
  166. });
  167. // Do validate rules
  168. var summaryPromise;
  169. if (validateFirst === true) {
  170. // >>>>> Validate by serialization
  171. summaryPromise = new Promise( /*#__PURE__*/function () {
  172. var _ref3 = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime.mark(function _callee(resolve, reject) {
  173. var i, rule, errors;
  174. return _regeneratorRuntime.wrap(function _callee$(_context) {
  175. while (1) {
  176. switch (_context.prev = _context.next) {
  177. case 0:
  178. i = 0;
  179. case 1:
  180. if (!(i < filledRules.length)) {
  181. _context.next = 12;
  182. break;
  183. }
  184. rule = filledRules[i];
  185. _context.next = 5;
  186. return validateRule(name, value, rule, options, messageVariables);
  187. case 5:
  188. errors = _context.sent;
  189. if (!errors.length) {
  190. _context.next = 9;
  191. break;
  192. }
  193. reject([{
  194. errors: errors,
  195. rule: rule
  196. }]);
  197. return _context.abrupt("return");
  198. case 9:
  199. i += 1;
  200. _context.next = 1;
  201. break;
  202. case 12:
  203. /* eslint-enable */
  204. resolve([]);
  205. case 13:
  206. case "end":
  207. return _context.stop();
  208. }
  209. }
  210. }, _callee);
  211. }));
  212. return function (_x6, _x7) {
  213. return _ref3.apply(this, arguments);
  214. };
  215. }());
  216. } else {
  217. // >>>>> Validate by parallel
  218. var rulePromises = filledRules.map(function (rule) {
  219. return validateRule(name, value, rule, options, messageVariables).then(function (errors) {
  220. return {
  221. errors: errors,
  222. rule: rule
  223. };
  224. });
  225. });
  226. summaryPromise = (validateFirst ? finishOnFirstFailed(rulePromises) : finishOnAllFailed(rulePromises)).then(function (errors) {
  227. // Always change to rejection for Field to catch
  228. return Promise.reject(errors);
  229. });
  230. }
  231. // Internal catch error to avoid console error log.
  232. summaryPromise.catch(function (e) {
  233. return e;
  234. });
  235. return summaryPromise;
  236. }
  237. function finishOnAllFailed(_x8) {
  238. return _finishOnAllFailed.apply(this, arguments);
  239. }
  240. function _finishOnAllFailed() {
  241. _finishOnAllFailed = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime.mark(function _callee3(rulePromises) {
  242. return _regeneratorRuntime.wrap(function _callee3$(_context3) {
  243. while (1) {
  244. switch (_context3.prev = _context3.next) {
  245. case 0:
  246. return _context3.abrupt("return", Promise.all(rulePromises).then(function (errorsList) {
  247. var _ref5;
  248. var errors = (_ref5 = []).concat.apply(_ref5, _toConsumableArray(errorsList));
  249. return errors;
  250. }));
  251. case 1:
  252. case "end":
  253. return _context3.stop();
  254. }
  255. }
  256. }, _callee3);
  257. }));
  258. return _finishOnAllFailed.apply(this, arguments);
  259. }
  260. function finishOnFirstFailed(_x9) {
  261. return _finishOnFirstFailed.apply(this, arguments);
  262. }
  263. function _finishOnFirstFailed() {
  264. _finishOnFirstFailed = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime.mark(function _callee4(rulePromises) {
  265. var count;
  266. return _regeneratorRuntime.wrap(function _callee4$(_context4) {
  267. while (1) {
  268. switch (_context4.prev = _context4.next) {
  269. case 0:
  270. count = 0;
  271. return _context4.abrupt("return", new Promise(function (resolve) {
  272. rulePromises.forEach(function (promise) {
  273. promise.then(function (ruleError) {
  274. if (ruleError.errors.length) {
  275. resolve([ruleError]);
  276. }
  277. count += 1;
  278. if (count === rulePromises.length) {
  279. resolve([]);
  280. }
  281. });
  282. });
  283. }));
  284. case 2:
  285. case "end":
  286. return _context4.stop();
  287. }
  288. }
  289. }, _callee4);
  290. }));
  291. return _finishOnFirstFailed.apply(this, arguments);
  292. }