bind.js 6.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238
  1. 'use strict';
  2. Object.defineProperty(exports, '__esModule', {
  3. value: true
  4. });
  5. var _util;
  6. function _load_util() {
  7. return (_util = _interopRequireDefault(require('util')));
  8. }
  9. var _chalk;
  10. function _load_chalk() {
  11. return (_chalk = _interopRequireDefault(require('chalk')));
  12. }
  13. var _prettyFormat;
  14. function _load_prettyFormat() {
  15. return (_prettyFormat = _interopRequireDefault(require('pretty-format')));
  16. }
  17. function _interopRequireDefault(obj) {
  18. return obj && obj.__esModule ? obj : {default: obj};
  19. }
  20. function _toArray(arr) {
  21. return Array.isArray(arr) ? arr : Array.from(arr);
  22. }
  23. function _toConsumableArray(arr) {
  24. if (Array.isArray(arr)) {
  25. for (var i = 0, arr2 = Array(arr.length); i < arr.length; i++)
  26. arr2[i] = arr[i];
  27. return arr2;
  28. } else {
  29. return Array.from(arr);
  30. }
  31. }
  32. /**
  33. * Copyright (c) 2018-present, Facebook, Inc. All rights reserved.
  34. *
  35. * This source code is licensed under the MIT license found in the
  36. * LICENSE file in the root directory of this source tree.
  37. *
  38. *
  39. */
  40. const EXPECTED_COLOR = (_chalk || _load_chalk()).default.green;
  41. const RECEIVED_COLOR = (_chalk || _load_chalk()).default.red;
  42. const SUPPORTED_PLACEHOLDERS = /%[sdifjoOp%]/g;
  43. const PRETTY_PLACEHOLDER = '%p';
  44. const INDEX_PLACEHOLDER = '%#';
  45. exports.default = function(cb) {
  46. let supportsDone =
  47. arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : true;
  48. return function() {
  49. for (
  50. var _len = arguments.length, args = Array(_len), _key = 0;
  51. _key < _len;
  52. _key++
  53. ) {
  54. args[_key] = arguments[_key];
  55. }
  56. return function eachBind(title, test, timeout) {
  57. if (args.length === 1) {
  58. const table = args[0].every(Array.isArray)
  59. ? args[0]
  60. : args[0].map(entry => [entry]);
  61. return table.forEach((row, i) =>
  62. cb(
  63. arrayFormat.apply(
  64. undefined,
  65. [title, i].concat(_toConsumableArray(row))
  66. ),
  67. applyRestParams(supportsDone, row, test),
  68. timeout
  69. )
  70. );
  71. }
  72. const templateStrings = args[0];
  73. const data = args.slice(1);
  74. const keys = getHeadingKeys(templateStrings[0]);
  75. const table = buildTable(data, keys.length, keys);
  76. const missingData = data.length % keys.length;
  77. if (missingData > 0) {
  78. const error = new Error(
  79. 'Not enough arguments supplied for given headings:\n' +
  80. EXPECTED_COLOR(keys.join(' | ')) +
  81. '\n\n' +
  82. 'Received:\n' +
  83. RECEIVED_COLOR(
  84. (0, (_prettyFormat || _load_prettyFormat()).default)(data)
  85. ) +
  86. '\n\n' +
  87. `Missing ${RECEIVED_COLOR(missingData.toString())} ${pluralize(
  88. 'argument',
  89. missingData
  90. )}`
  91. );
  92. if (Error.captureStackTrace) {
  93. Error.captureStackTrace(error, eachBind);
  94. }
  95. return cb(title, () => {
  96. throw error;
  97. });
  98. }
  99. return table.forEach(row =>
  100. cb(
  101. interpolate(title, row),
  102. applyObjectParams(supportsDone, row, test),
  103. timeout
  104. )
  105. );
  106. };
  107. };
  108. };
  109. const getPrettyIndexes = placeholders =>
  110. placeholders.reduce(
  111. (indexes, placeholder, index) =>
  112. placeholder === PRETTY_PLACEHOLDER ? indexes.concat(index) : indexes,
  113. []
  114. );
  115. const arrayFormat = function(title, rowIndex) {
  116. for (
  117. var _len2 = arguments.length,
  118. args = Array(_len2 > 2 ? _len2 - 2 : 0),
  119. _key2 = 2;
  120. _key2 < _len2;
  121. _key2++
  122. ) {
  123. args[_key2 - 2] = arguments[_key2];
  124. }
  125. const placeholders = title.match(SUPPORTED_PLACEHOLDERS) || [];
  126. const prettyIndexes = getPrettyIndexes(placeholders);
  127. var _args$reduce = args.reduce(
  128. (acc, arg, index) => {
  129. if (prettyIndexes.indexOf(index) !== -1) {
  130. return {
  131. args: acc.args,
  132. title: acc.title.replace(
  133. PRETTY_PLACEHOLDER,
  134. (0, (_prettyFormat || _load_prettyFormat()).default)(arg, {
  135. maxDepth: 1,
  136. min: true
  137. })
  138. )
  139. };
  140. }
  141. return {
  142. args: acc.args.concat([arg]),
  143. title: acc.title
  144. };
  145. },
  146. {args: [], title: title}
  147. );
  148. const prettyTitle = _args$reduce.title,
  149. remainingArgs = _args$reduce.args;
  150. return (_util || _load_util()).default.format.apply(
  151. (_util || _load_util()).default,
  152. [prettyTitle.replace(INDEX_PLACEHOLDER, rowIndex.toString())].concat(
  153. _toConsumableArray(
  154. remainingArgs.slice(0, placeholders.length - prettyIndexes.length)
  155. )
  156. )
  157. );
  158. };
  159. const applyRestParams = (supportsDone, params, test) =>
  160. supportsDone && params.length < test.length
  161. ? done => test.apply(undefined, _toConsumableArray(params).concat([done]))
  162. : () => test.apply(undefined, _toConsumableArray(params));
  163. const getHeadingKeys = headings => headings.replace(/\s/g, '').split('|');
  164. const buildTable = (data, rowSize, keys) =>
  165. Array.from({length: data.length / rowSize})
  166. .map((_, index) => data.slice(index * rowSize, index * rowSize + rowSize))
  167. .map(row =>
  168. row.reduce(
  169. (acc, value, index) => Object.assign({}, acc, {[keys[index]]: value}),
  170. {}
  171. )
  172. );
  173. const getMatchingKeyPaths = title => (matches, key) =>
  174. matches.concat(title.match(new RegExp(`\\$${key}[\\.\\w]*`, 'g')) || []);
  175. const replaceKeyPathWithValue = data => (title, match) => {
  176. const keyPath = match.replace('$', '').split('.');
  177. const value = getPath(data, keyPath);
  178. return title.replace(
  179. match,
  180. (0, (_prettyFormat || _load_prettyFormat()).default)(value, {
  181. maxDepth: 1,
  182. min: true
  183. })
  184. );
  185. };
  186. const interpolate = (title, data) =>
  187. Object.keys(data)
  188. .reduce(getMatchingKeyPaths(title), []) // aka flatMap
  189. .reduce(replaceKeyPathWithValue(data), title);
  190. const applyObjectParams = (supportsDone, obj, test) =>
  191. supportsDone && test.length > 1 ? done => test(obj, done) : () => test(obj);
  192. const pluralize = (word, count) => word + (count === 1 ? '' : 's');
  193. const getPath = (o, _ref) => {
  194. var _ref2 = _toArray(_ref);
  195. let head = _ref2[0],
  196. tail = _ref2.slice(1);
  197. if (!head || !o.hasOwnProperty || !o.hasOwnProperty(head)) return o;
  198. return getPath(o[head], tail);
  199. };