310 lines
11 KiB
JavaScript
310 lines
11 KiB
JavaScript
import _toConsumableArray from "@babel/runtime/helpers/esm/toConsumableArray";
|
|
import _defineProperty from "@babel/runtime/helpers/esm/defineProperty";
|
|
import _regeneratorRuntime from "@babel/runtime/helpers/esm/regeneratorRuntime";
|
|
import _objectSpread from "@babel/runtime/helpers/esm/objectSpread2";
|
|
import _asyncToGenerator from "@babel/runtime/helpers/esm/asyncToGenerator";
|
|
import RawAsyncValidator from 'async-validator';
|
|
import * as React from 'react';
|
|
import warning from "rc-util/es/warning";
|
|
import { defaultValidateMessages } from "./messages";
|
|
import { merge } from "rc-util/es/utils/set";
|
|
|
|
// Remove incorrect original ts define
|
|
var AsyncValidator = RawAsyncValidator;
|
|
|
|
/**
|
|
* Replace with template.
|
|
* `I'm ${name}` + { name: 'bamboo' } = I'm bamboo
|
|
*/
|
|
function replaceMessage(template, kv) {
|
|
return template.replace(/\$\{\w+\}/g, function (str) {
|
|
var key = str.slice(2, -1);
|
|
return kv[key];
|
|
});
|
|
}
|
|
var CODE_LOGIC_ERROR = 'CODE_LOGIC_ERROR';
|
|
function validateRule(_x, _x2, _x3, _x4, _x5) {
|
|
return _validateRule.apply(this, arguments);
|
|
}
|
|
/**
|
|
* We use `async-validator` to validate the value.
|
|
* But only check one value in a time to avoid namePath validate issue.
|
|
*/
|
|
function _validateRule() {
|
|
_validateRule = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime().mark(function _callee2(name, value, rule, options, messageVariables) {
|
|
var cloneRule, originValidator, subRuleField, validator, messages, result, subResults, kv, fillVariableResult;
|
|
return _regeneratorRuntime().wrap(function _callee2$(_context2) {
|
|
while (1) switch (_context2.prev = _context2.next) {
|
|
case 0:
|
|
cloneRule = _objectSpread({}, rule); // Bug of `async-validator`
|
|
// https://github.com/react-component/field-form/issues/316
|
|
// https://github.com/react-component/field-form/issues/313
|
|
delete cloneRule.ruleIndex;
|
|
|
|
// https://github.com/ant-design/ant-design/issues/40497#issuecomment-1422282378
|
|
AsyncValidator.warning = function () {
|
|
return void 0;
|
|
};
|
|
if (cloneRule.validator) {
|
|
originValidator = cloneRule.validator;
|
|
cloneRule.validator = function () {
|
|
try {
|
|
return originValidator.apply(void 0, arguments);
|
|
} catch (error) {
|
|
console.error(error);
|
|
return Promise.reject(CODE_LOGIC_ERROR);
|
|
}
|
|
};
|
|
}
|
|
|
|
// We should special handle array validate
|
|
subRuleField = null;
|
|
if (cloneRule && cloneRule.type === 'array' && cloneRule.defaultField) {
|
|
subRuleField = cloneRule.defaultField;
|
|
delete cloneRule.defaultField;
|
|
}
|
|
validator = new AsyncValidator(_defineProperty({}, name, [cloneRule]));
|
|
messages = merge(defaultValidateMessages, options.validateMessages);
|
|
validator.messages(messages);
|
|
result = [];
|
|
_context2.prev = 10;
|
|
_context2.next = 13;
|
|
return Promise.resolve(validator.validate(_defineProperty({}, name, value), _objectSpread({}, options)));
|
|
case 13:
|
|
_context2.next = 18;
|
|
break;
|
|
case 15:
|
|
_context2.prev = 15;
|
|
_context2.t0 = _context2["catch"](10);
|
|
if (_context2.t0.errors) {
|
|
result = _context2.t0.errors.map(function (_ref4, index) {
|
|
var message = _ref4.message;
|
|
var mergedMessage = message === CODE_LOGIC_ERROR ? messages.default : message;
|
|
return /*#__PURE__*/React.isValidElement(mergedMessage) ?
|
|
/*#__PURE__*/
|
|
// Wrap ReactNode with `key`
|
|
React.cloneElement(mergedMessage, {
|
|
key: "error_".concat(index)
|
|
}) : mergedMessage;
|
|
});
|
|
}
|
|
case 18:
|
|
if (!(!result.length && subRuleField)) {
|
|
_context2.next = 23;
|
|
break;
|
|
}
|
|
_context2.next = 21;
|
|
return Promise.all(value.map(function (subValue, i) {
|
|
return validateRule("".concat(name, ".").concat(i), subValue, subRuleField, options, messageVariables);
|
|
}));
|
|
case 21:
|
|
subResults = _context2.sent;
|
|
return _context2.abrupt("return", subResults.reduce(function (prev, errors) {
|
|
return [].concat(_toConsumableArray(prev), _toConsumableArray(errors));
|
|
}, []));
|
|
case 23:
|
|
// Replace message with variables
|
|
kv = _objectSpread(_objectSpread({}, rule), {}, {
|
|
name: name,
|
|
enum: (rule.enum || []).join(', ')
|
|
}, messageVariables);
|
|
fillVariableResult = result.map(function (error) {
|
|
if (typeof error === 'string') {
|
|
return replaceMessage(error, kv);
|
|
}
|
|
return error;
|
|
});
|
|
return _context2.abrupt("return", fillVariableResult);
|
|
case 26:
|
|
case "end":
|
|
return _context2.stop();
|
|
}
|
|
}, _callee2, null, [[10, 15]]);
|
|
}));
|
|
return _validateRule.apply(this, arguments);
|
|
}
|
|
export function validateRules(namePath, value, rules, options, validateFirst, messageVariables) {
|
|
var name = namePath.join('.');
|
|
|
|
// Fill rule with context
|
|
var filledRules = rules.map(function (currentRule, ruleIndex) {
|
|
var originValidatorFunc = currentRule.validator;
|
|
var cloneRule = _objectSpread(_objectSpread({}, currentRule), {}, {
|
|
ruleIndex: ruleIndex
|
|
});
|
|
|
|
// Replace validator if needed
|
|
if (originValidatorFunc) {
|
|
cloneRule.validator = function (rule, val, callback) {
|
|
var hasPromise = false;
|
|
|
|
// Wrap callback only accept when promise not provided
|
|
var wrappedCallback = function wrappedCallback() {
|
|
for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) {
|
|
args[_key] = arguments[_key];
|
|
}
|
|
// Wait a tick to make sure return type is a promise
|
|
Promise.resolve().then(function () {
|
|
warning(!hasPromise, 'Your validator function has already return a promise. `callback` will be ignored.');
|
|
if (!hasPromise) {
|
|
callback.apply(void 0, args);
|
|
}
|
|
});
|
|
};
|
|
|
|
// Get promise
|
|
var promise = originValidatorFunc(rule, val, wrappedCallback);
|
|
hasPromise = promise && typeof promise.then === 'function' && typeof promise.catch === 'function';
|
|
|
|
/**
|
|
* 1. Use promise as the first priority.
|
|
* 2. If promise not exist, use callback with warning instead
|
|
*/
|
|
warning(hasPromise, '`callback` is deprecated. Please return a promise instead.');
|
|
if (hasPromise) {
|
|
promise.then(function () {
|
|
callback();
|
|
}).catch(function (err) {
|
|
callback(err || ' ');
|
|
});
|
|
}
|
|
};
|
|
}
|
|
return cloneRule;
|
|
}).sort(function (_ref, _ref2) {
|
|
var w1 = _ref.warningOnly,
|
|
i1 = _ref.ruleIndex;
|
|
var w2 = _ref2.warningOnly,
|
|
i2 = _ref2.ruleIndex;
|
|
if (!!w1 === !!w2) {
|
|
// Let keep origin order
|
|
return i1 - i2;
|
|
}
|
|
if (w1) {
|
|
return 1;
|
|
}
|
|
return -1;
|
|
});
|
|
|
|
// Do validate rules
|
|
var summaryPromise;
|
|
if (validateFirst === true) {
|
|
// >>>>> Validate by serialization
|
|
summaryPromise = new Promise( /*#__PURE__*/function () {
|
|
var _ref3 = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime().mark(function _callee(resolve, reject) {
|
|
var i, rule, errors;
|
|
return _regeneratorRuntime().wrap(function _callee$(_context) {
|
|
while (1) switch (_context.prev = _context.next) {
|
|
case 0:
|
|
i = 0;
|
|
case 1:
|
|
if (!(i < filledRules.length)) {
|
|
_context.next = 12;
|
|
break;
|
|
}
|
|
rule = filledRules[i];
|
|
_context.next = 5;
|
|
return validateRule(name, value, rule, options, messageVariables);
|
|
case 5:
|
|
errors = _context.sent;
|
|
if (!errors.length) {
|
|
_context.next = 9;
|
|
break;
|
|
}
|
|
reject([{
|
|
errors: errors,
|
|
rule: rule
|
|
}]);
|
|
return _context.abrupt("return");
|
|
case 9:
|
|
i += 1;
|
|
_context.next = 1;
|
|
break;
|
|
case 12:
|
|
/* eslint-enable */
|
|
|
|
resolve([]);
|
|
case 13:
|
|
case "end":
|
|
return _context.stop();
|
|
}
|
|
}, _callee);
|
|
}));
|
|
return function (_x6, _x7) {
|
|
return _ref3.apply(this, arguments);
|
|
};
|
|
}());
|
|
} else {
|
|
// >>>>> Validate by parallel
|
|
var rulePromises = filledRules.map(function (rule) {
|
|
return validateRule(name, value, rule, options, messageVariables).then(function (errors) {
|
|
return {
|
|
errors: errors,
|
|
rule: rule
|
|
};
|
|
});
|
|
});
|
|
summaryPromise = (validateFirst ? finishOnFirstFailed(rulePromises) : finishOnAllFailed(rulePromises)).then(function (errors) {
|
|
// Always change to rejection for Field to catch
|
|
return Promise.reject(errors);
|
|
});
|
|
}
|
|
|
|
// Internal catch error to avoid console error log.
|
|
summaryPromise.catch(function (e) {
|
|
return e;
|
|
});
|
|
return summaryPromise;
|
|
}
|
|
function finishOnAllFailed(_x8) {
|
|
return _finishOnAllFailed.apply(this, arguments);
|
|
}
|
|
function _finishOnAllFailed() {
|
|
_finishOnAllFailed = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime().mark(function _callee3(rulePromises) {
|
|
return _regeneratorRuntime().wrap(function _callee3$(_context3) {
|
|
while (1) switch (_context3.prev = _context3.next) {
|
|
case 0:
|
|
return _context3.abrupt("return", Promise.all(rulePromises).then(function (errorsList) {
|
|
var _ref5;
|
|
var errors = (_ref5 = []).concat.apply(_ref5, _toConsumableArray(errorsList));
|
|
return errors;
|
|
}));
|
|
case 1:
|
|
case "end":
|
|
return _context3.stop();
|
|
}
|
|
}, _callee3);
|
|
}));
|
|
return _finishOnAllFailed.apply(this, arguments);
|
|
}
|
|
function finishOnFirstFailed(_x9) {
|
|
return _finishOnFirstFailed.apply(this, arguments);
|
|
}
|
|
function _finishOnFirstFailed() {
|
|
_finishOnFirstFailed = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime().mark(function _callee4(rulePromises) {
|
|
var count;
|
|
return _regeneratorRuntime().wrap(function _callee4$(_context4) {
|
|
while (1) switch (_context4.prev = _context4.next) {
|
|
case 0:
|
|
count = 0;
|
|
return _context4.abrupt("return", new Promise(function (resolve) {
|
|
rulePromises.forEach(function (promise) {
|
|
promise.then(function (ruleError) {
|
|
if (ruleError.errors.length) {
|
|
resolve([ruleError]);
|
|
}
|
|
count += 1;
|
|
if (count === rulePromises.length) {
|
|
resolve([]);
|
|
}
|
|
});
|
|
});
|
|
}));
|
|
case 2:
|
|
case "end":
|
|
return _context4.stop();
|
|
}
|
|
}, _callee4);
|
|
}));
|
|
return _finishOnFirstFailed.apply(this, arguments);
|
|
} |