index.js 35 KB

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