index.js 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292
  1. import _objectSpread from "@babel/runtime/helpers/esm/objectSpread2";
  2. import _toConsumableArray from "@babel/runtime/helpers/esm/toConsumableArray";
  3. import _typeof from "@babel/runtime/helpers/esm/typeof";
  4. import _classCallCheck from "@babel/runtime/helpers/esm/classCallCheck";
  5. import _createClass from "@babel/runtime/helpers/esm/createClass";
  6. import _defineProperty from "@babel/runtime/helpers/esm/defineProperty";
  7. import { messages as defaultMessages, newMessages } from "./messages";
  8. import { asyncMap, complementError, convertFieldsError, deepMerge, format, warning } from "./util";
  9. import validators from "./validator/index";
  10. export * from "./interface";
  11. /**
  12. * Encapsulates a validation schema.
  13. *
  14. * @param descriptor An object declaring validation rules
  15. * for this schema.
  16. */
  17. var Schema = /*#__PURE__*/function () {
  18. function Schema(descriptor) {
  19. _classCallCheck(this, Schema);
  20. // ======================== Instance ========================
  21. _defineProperty(this, "rules", null);
  22. _defineProperty(this, "_messages", defaultMessages);
  23. this.define(descriptor);
  24. }
  25. _createClass(Schema, [{
  26. key: "define",
  27. value: function define(rules) {
  28. var _this = this;
  29. if (!rules) {
  30. throw new Error('Cannot configure a schema with no rules');
  31. }
  32. if (_typeof(rules) !== 'object' || Array.isArray(rules)) {
  33. throw new Error('Rules must be an object');
  34. }
  35. this.rules = {};
  36. Object.keys(rules).forEach(function (name) {
  37. var item = rules[name];
  38. _this.rules[name] = Array.isArray(item) ? item : [item];
  39. });
  40. }
  41. }, {
  42. key: "messages",
  43. value: function messages(_messages) {
  44. if (_messages) {
  45. this._messages = deepMerge(newMessages(), _messages);
  46. }
  47. return this._messages;
  48. }
  49. }, {
  50. key: "validate",
  51. value: function validate(source_) {
  52. var _this2 = this;
  53. var o = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
  54. var oc = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : function () {};
  55. var source = source_;
  56. var options = o;
  57. var callback = oc;
  58. if (typeof options === 'function') {
  59. callback = options;
  60. options = {};
  61. }
  62. if (!this.rules || Object.keys(this.rules).length === 0) {
  63. if (callback) {
  64. callback(null, source);
  65. }
  66. return Promise.resolve(source);
  67. }
  68. function complete(results) {
  69. var errors = [];
  70. var fields = {};
  71. function add(e) {
  72. if (Array.isArray(e)) {
  73. var _errors;
  74. errors = (_errors = errors).concat.apply(_errors, _toConsumableArray(e));
  75. } else {
  76. errors.push(e);
  77. }
  78. }
  79. for (var i = 0; i < results.length; i++) {
  80. add(results[i]);
  81. }
  82. if (!errors.length) {
  83. callback(null, source);
  84. } else {
  85. fields = convertFieldsError(errors);
  86. callback(errors, fields);
  87. }
  88. }
  89. if (options.messages) {
  90. var messages = this.messages();
  91. if (messages === defaultMessages) {
  92. messages = newMessages();
  93. }
  94. deepMerge(messages, options.messages);
  95. options.messages = messages;
  96. } else {
  97. options.messages = this.messages();
  98. }
  99. var series = {};
  100. var keys = options.keys || Object.keys(this.rules);
  101. keys.forEach(function (z) {
  102. var arr = _this2.rules[z];
  103. var value = source[z];
  104. arr.forEach(function (r) {
  105. var rule = r;
  106. if (typeof rule.transform === 'function') {
  107. if (source === source_) {
  108. source = _objectSpread({}, source);
  109. }
  110. value = source[z] = rule.transform(value);
  111. if (value !== undefined && value !== null) {
  112. rule.type = rule.type || (Array.isArray(value) ? 'array' : _typeof(value));
  113. }
  114. }
  115. if (typeof rule === 'function') {
  116. rule = {
  117. validator: rule
  118. };
  119. } else {
  120. rule = _objectSpread({}, rule);
  121. }
  122. // Fill validator. Skip if nothing need to validate
  123. rule.validator = _this2.getValidationMethod(rule);
  124. if (!rule.validator) {
  125. return;
  126. }
  127. rule.field = z;
  128. rule.fullField = rule.fullField || z;
  129. rule.type = _this2.getType(rule);
  130. series[z] = series[z] || [];
  131. series[z].push({
  132. rule: rule,
  133. value: value,
  134. source: source,
  135. field: z
  136. });
  137. });
  138. });
  139. var errorFields = {};
  140. return asyncMap(series, options, function (data, doIt) {
  141. var rule = data.rule;
  142. var deep = (rule.type === 'object' || rule.type === 'array') && (_typeof(rule.fields) === 'object' || _typeof(rule.defaultField) === 'object');
  143. deep = deep && (rule.required || !rule.required && data.value);
  144. rule.field = data.field;
  145. function addFullField(key, schema) {
  146. return _objectSpread(_objectSpread({}, schema), {}, {
  147. fullField: "".concat(rule.fullField, ".").concat(key),
  148. fullFields: rule.fullFields ? [].concat(_toConsumableArray(rule.fullFields), [key]) : [key]
  149. });
  150. }
  151. function cb() {
  152. var e = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : [];
  153. var errorList = Array.isArray(e) ? e : [e];
  154. if (!options.suppressWarning && errorList.length) {
  155. Schema.warning('async-validator:', errorList);
  156. }
  157. if (errorList.length && rule.message !== undefined) {
  158. errorList = [].concat(rule.message);
  159. }
  160. // Fill error info
  161. var filledErrors = errorList.map(complementError(rule, source));
  162. if (options.first && filledErrors.length) {
  163. errorFields[rule.field] = 1;
  164. return doIt(filledErrors);
  165. }
  166. if (!deep) {
  167. doIt(filledErrors);
  168. } else {
  169. // if rule is required but the target object
  170. // does not exist fail at the rule level and don't
  171. // go deeper
  172. if (rule.required && !data.value) {
  173. if (rule.message !== undefined) {
  174. filledErrors = [].concat(rule.message).map(complementError(rule, source));
  175. } else if (options.error) {
  176. filledErrors = [options.error(rule, format(options.messages.required, rule.field))];
  177. }
  178. return doIt(filledErrors);
  179. }
  180. var fieldsSchema = {};
  181. if (rule.defaultField) {
  182. Object.keys(data.value).map(function (key) {
  183. fieldsSchema[key] = rule.defaultField;
  184. });
  185. }
  186. fieldsSchema = _objectSpread(_objectSpread({}, fieldsSchema), data.rule.fields);
  187. var paredFieldsSchema = {};
  188. Object.keys(fieldsSchema).forEach(function (field) {
  189. var fieldSchema = fieldsSchema[field];
  190. var fieldSchemaList = Array.isArray(fieldSchema) ? fieldSchema : [fieldSchema];
  191. paredFieldsSchema[field] = fieldSchemaList.map(addFullField.bind(null, field));
  192. });
  193. var schema = new Schema(paredFieldsSchema);
  194. schema.messages(options.messages);
  195. if (data.rule.options) {
  196. data.rule.options.messages = options.messages;
  197. data.rule.options.error = options.error;
  198. }
  199. schema.validate(data.value, data.rule.options || options, function (errs) {
  200. var finalErrors = [];
  201. if (filledErrors && filledErrors.length) {
  202. finalErrors.push.apply(finalErrors, _toConsumableArray(filledErrors));
  203. }
  204. if (errs && errs.length) {
  205. finalErrors.push.apply(finalErrors, _toConsumableArray(errs));
  206. }
  207. doIt(finalErrors.length ? finalErrors : null);
  208. });
  209. }
  210. }
  211. var res;
  212. if (rule.asyncValidator) {
  213. res = rule.asyncValidator(rule, data.value, cb, data.source, options);
  214. } else if (rule.validator) {
  215. try {
  216. res = rule.validator(rule, data.value, cb, data.source, options);
  217. } catch (error) {
  218. var _console$error, _console;
  219. (_console$error = (_console = console).error) === null || _console$error === void 0 || _console$error.call(_console, error);
  220. // rethrow to report error
  221. if (!options.suppressValidatorError) {
  222. setTimeout(function () {
  223. throw error;
  224. }, 0);
  225. }
  226. cb(error.message);
  227. }
  228. if (res === true) {
  229. cb();
  230. } else if (res === false) {
  231. cb(typeof rule.message === 'function' ? rule.message(rule.fullField || rule.field) : rule.message || "".concat(rule.fullField || rule.field, " fails"));
  232. } else if (res instanceof Array) {
  233. cb(res);
  234. } else if (res instanceof Error) {
  235. cb(res.message);
  236. }
  237. }
  238. if (res && res.then) {
  239. res.then(function () {
  240. return cb();
  241. }, function (e) {
  242. return cb(e);
  243. });
  244. }
  245. }, function (results) {
  246. complete(results);
  247. }, source);
  248. }
  249. }, {
  250. key: "getType",
  251. value: function getType(rule) {
  252. if (rule.type === undefined && rule.pattern instanceof RegExp) {
  253. rule.type = 'pattern';
  254. }
  255. if (typeof rule.validator !== 'function' && rule.type && !validators.hasOwnProperty(rule.type)) {
  256. throw new Error(format('Unknown rule type %s', rule.type));
  257. }
  258. return rule.type || 'string';
  259. }
  260. }, {
  261. key: "getValidationMethod",
  262. value: function getValidationMethod(rule) {
  263. if (typeof rule.validator === 'function') {
  264. return rule.validator;
  265. }
  266. var keys = Object.keys(rule);
  267. var messageIndex = keys.indexOf('message');
  268. if (messageIndex !== -1) {
  269. keys.splice(messageIndex, 1);
  270. }
  271. if (keys.length === 1 && keys[0] === 'required') {
  272. return validators.required;
  273. }
  274. return validators[this.getType(rule)] || undefined;
  275. }
  276. }]);
  277. return Schema;
  278. }();
  279. // ========================= Static =========================
  280. _defineProperty(Schema, "register", function register(type, validator) {
  281. if (typeof validator !== 'function') {
  282. throw new Error('Cannot register a validator by type, validator is not a function');
  283. }
  284. validators[type] = validator;
  285. });
  286. _defineProperty(Schema, "warning", warning);
  287. _defineProperty(Schema, "messages", defaultMessages);
  288. _defineProperty(Schema, "validators", validators);
  289. export default Schema;