index.js 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734
  1. 'use strict';
  2. Object.defineProperty(exports, '__esModule', { value: true });
  3. /**
  4. * Flatten array, one level deep.
  5. *
  6. * @param {Array<?>} arr
  7. *
  8. * @return {Array<?>}
  9. */
  10. function flatten(arr) {
  11. return Array.prototype.concat.apply([], arr);
  12. }
  13. var nativeToString = Object.prototype.toString;
  14. var nativeHasOwnProperty = Object.prototype.hasOwnProperty;
  15. function isUndefined(obj) {
  16. return obj === undefined;
  17. }
  18. function isDefined(obj) {
  19. return obj !== undefined;
  20. }
  21. function isNil(obj) {
  22. return obj == null;
  23. }
  24. function isArray(obj) {
  25. return nativeToString.call(obj) === '[object Array]';
  26. }
  27. function isObject(obj) {
  28. return nativeToString.call(obj) === '[object Object]';
  29. }
  30. function isNumber(obj) {
  31. return nativeToString.call(obj) === '[object Number]';
  32. }
  33. function isFunction(obj) {
  34. var tag = nativeToString.call(obj);
  35. return tag === '[object Function]' || tag === '[object AsyncFunction]' || tag === '[object GeneratorFunction]' || tag === '[object AsyncGeneratorFunction]' || tag === '[object Proxy]';
  36. }
  37. function isString(obj) {
  38. return nativeToString.call(obj) === '[object String]';
  39. }
  40. /**
  41. * Ensure collection is an array.
  42. *
  43. * @param {Object} obj
  44. */
  45. function ensureArray(obj) {
  46. if (isArray(obj)) {
  47. return;
  48. }
  49. throw new Error('must supply array');
  50. }
  51. /**
  52. * Return true, if target owns a property with the given key.
  53. *
  54. * @param {Object} target
  55. * @param {String} key
  56. *
  57. * @return {Boolean}
  58. */
  59. function has(target, key) {
  60. return nativeHasOwnProperty.call(target, key);
  61. }
  62. /**
  63. * Find element in collection.
  64. *
  65. * @param {Array|Object} collection
  66. * @param {Function|Object} matcher
  67. *
  68. * @return {Object}
  69. */
  70. function find(collection, matcher) {
  71. matcher = toMatcher(matcher);
  72. var match;
  73. forEach(collection, function (val, key) {
  74. if (matcher(val, key)) {
  75. match = val;
  76. return false;
  77. }
  78. });
  79. return match;
  80. }
  81. /**
  82. * Find element index in collection.
  83. *
  84. * @param {Array|Object} collection
  85. * @param {Function} matcher
  86. *
  87. * @return {Object}
  88. */
  89. function findIndex(collection, matcher) {
  90. matcher = toMatcher(matcher);
  91. var idx = isArray(collection) ? -1 : undefined;
  92. forEach(collection, function (val, key) {
  93. if (matcher(val, key)) {
  94. idx = key;
  95. return false;
  96. }
  97. });
  98. return idx;
  99. }
  100. /**
  101. * Find element in collection.
  102. *
  103. * @param {Array|Object} collection
  104. * @param {Function} matcher
  105. *
  106. * @return {Array} result
  107. */
  108. function filter(collection, matcher) {
  109. var result = [];
  110. forEach(collection, function (val, key) {
  111. if (matcher(val, key)) {
  112. result.push(val);
  113. }
  114. });
  115. return result;
  116. }
  117. /**
  118. * Iterate over collection; returning something
  119. * (non-undefined) will stop iteration.
  120. *
  121. * @param {Array|Object} collection
  122. * @param {Function} iterator
  123. *
  124. * @return {Object} return result that stopped the iteration
  125. */
  126. function forEach(collection, iterator) {
  127. var val, result;
  128. if (isUndefined(collection)) {
  129. return;
  130. }
  131. var convertKey = isArray(collection) ? toNum : identity;
  132. for (var key in collection) {
  133. if (has(collection, key)) {
  134. val = collection[key];
  135. result = iterator(val, convertKey(key));
  136. if (result === false) {
  137. return val;
  138. }
  139. }
  140. }
  141. }
  142. /**
  143. * Return collection without element.
  144. *
  145. * @param {Array} arr
  146. * @param {Function} matcher
  147. *
  148. * @return {Array}
  149. */
  150. function without(arr, matcher) {
  151. if (isUndefined(arr)) {
  152. return [];
  153. }
  154. ensureArray(arr);
  155. matcher = toMatcher(matcher);
  156. return arr.filter(function (el, idx) {
  157. return !matcher(el, idx);
  158. });
  159. }
  160. /**
  161. * Reduce collection, returning a single result.
  162. *
  163. * @param {Object|Array} collection
  164. * @param {Function} iterator
  165. * @param {Any} result
  166. *
  167. * @return {Any} result returned from last iterator
  168. */
  169. function reduce(collection, iterator, result) {
  170. forEach(collection, function (value, idx) {
  171. result = iterator(result, value, idx);
  172. });
  173. return result;
  174. }
  175. /**
  176. * Return true if every element in the collection
  177. * matches the criteria.
  178. *
  179. * @param {Object|Array} collection
  180. * @param {Function} matcher
  181. *
  182. * @return {Boolean}
  183. */
  184. function every(collection, matcher) {
  185. return !!reduce(collection, function (matches, val, key) {
  186. return matches && matcher(val, key);
  187. }, true);
  188. }
  189. /**
  190. * Return true if some elements in the collection
  191. * match the criteria.
  192. *
  193. * @param {Object|Array} collection
  194. * @param {Function} matcher
  195. *
  196. * @return {Boolean}
  197. */
  198. function some(collection, matcher) {
  199. return !!find(collection, matcher);
  200. }
  201. /**
  202. * Transform a collection into another collection
  203. * by piping each member through the given fn.
  204. *
  205. * @param {Object|Array} collection
  206. * @param {Function} fn
  207. *
  208. * @return {Array} transformed collection
  209. */
  210. function map(collection, fn) {
  211. var result = [];
  212. forEach(collection, function (val, key) {
  213. result.push(fn(val, key));
  214. });
  215. return result;
  216. }
  217. /**
  218. * Get the collections keys.
  219. *
  220. * @param {Object|Array} collection
  221. *
  222. * @return {Array}
  223. */
  224. function keys(collection) {
  225. return collection && Object.keys(collection) || [];
  226. }
  227. /**
  228. * Shorthand for `keys(o).length`.
  229. *
  230. * @param {Object|Array} collection
  231. *
  232. * @return {Number}
  233. */
  234. function size(collection) {
  235. return keys(collection).length;
  236. }
  237. /**
  238. * Get the values in the collection.
  239. *
  240. * @param {Object|Array} collection
  241. *
  242. * @return {Array}
  243. */
  244. function values(collection) {
  245. return map(collection, function (val) {
  246. return val;
  247. });
  248. }
  249. /**
  250. * Group collection members by attribute.
  251. *
  252. * @param {Object|Array} collection
  253. * @param {Function} extractor
  254. *
  255. * @return {Object} map with { attrValue => [ a, b, c ] }
  256. */
  257. function groupBy(collection, extractor) {
  258. var grouped = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {};
  259. extractor = toExtractor(extractor);
  260. forEach(collection, function (val) {
  261. var discriminator = extractor(val) || '_';
  262. var group = grouped[discriminator];
  263. if (!group) {
  264. group = grouped[discriminator] = [];
  265. }
  266. group.push(val);
  267. });
  268. return grouped;
  269. }
  270. function uniqueBy(extractor) {
  271. extractor = toExtractor(extractor);
  272. var grouped = {};
  273. for (var _len = arguments.length, collections = new Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) {
  274. collections[_key - 1] = arguments[_key];
  275. }
  276. forEach(collections, function (c) {
  277. return groupBy(c, extractor, grouped);
  278. });
  279. var result = map(grouped, function (val, key) {
  280. return val[0];
  281. });
  282. return result;
  283. }
  284. var unionBy = uniqueBy;
  285. /**
  286. * Sort collection by criteria.
  287. *
  288. * @param {Object|Array} collection
  289. * @param {String|Function} extractor
  290. *
  291. * @return {Array}
  292. */
  293. function sortBy(collection, extractor) {
  294. extractor = toExtractor(extractor);
  295. var sorted = [];
  296. forEach(collection, function (value, key) {
  297. var disc = extractor(value, key);
  298. var entry = {
  299. d: disc,
  300. v: value
  301. };
  302. for (var idx = 0; idx < sorted.length; idx++) {
  303. var d = sorted[idx].d;
  304. if (disc < d) {
  305. sorted.splice(idx, 0, entry);
  306. return;
  307. }
  308. } // not inserted, append (!)
  309. sorted.push(entry);
  310. });
  311. return map(sorted, function (e) {
  312. return e.v;
  313. });
  314. }
  315. /**
  316. * Create an object pattern matcher.
  317. *
  318. * @example
  319. *
  320. * const matcher = matchPattern({ id: 1 });
  321. *
  322. * let element = find(elements, matcher);
  323. *
  324. * @param {Object} pattern
  325. *
  326. * @return {Function} matcherFn
  327. */
  328. function matchPattern(pattern) {
  329. return function (el) {
  330. return every(pattern, function (val, key) {
  331. return el[key] === val;
  332. });
  333. };
  334. }
  335. function toExtractor(extractor) {
  336. return isFunction(extractor) ? extractor : function (e) {
  337. return e[extractor];
  338. };
  339. }
  340. function toMatcher(matcher) {
  341. return isFunction(matcher) ? matcher : function (e) {
  342. return e === matcher;
  343. };
  344. }
  345. function identity(arg) {
  346. return arg;
  347. }
  348. function toNum(arg) {
  349. return Number(arg);
  350. }
  351. /**
  352. * Debounce fn, calling it only once if the given time
  353. * elapsed between calls.
  354. *
  355. * Lodash-style the function exposes methods to `#clear`
  356. * and `#flush` to control internal behavior.
  357. *
  358. * @param {Function} fn
  359. * @param {Number} timeout
  360. *
  361. * @return {Function} debounced function
  362. */
  363. function debounce(fn, timeout) {
  364. var timer;
  365. var lastArgs;
  366. var lastThis;
  367. var lastNow;
  368. function fire(force) {
  369. var now = Date.now();
  370. var scheduledDiff = force ? 0 : lastNow + timeout - now;
  371. if (scheduledDiff > 0) {
  372. return schedule(scheduledDiff);
  373. }
  374. fn.apply(lastThis, lastArgs);
  375. clear();
  376. }
  377. function schedule(timeout) {
  378. timer = setTimeout(fire, timeout);
  379. }
  380. function clear() {
  381. if (timer) {
  382. clearTimeout(timer);
  383. }
  384. timer = lastNow = lastArgs = lastThis = undefined;
  385. }
  386. function flush() {
  387. if (timer) {
  388. fire(true);
  389. }
  390. clear();
  391. }
  392. function callback() {
  393. lastNow = Date.now();
  394. for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) {
  395. args[_key] = arguments[_key];
  396. }
  397. lastArgs = args;
  398. lastThis = this; // ensure an execution is scheduled
  399. if (!timer) {
  400. schedule(timeout);
  401. }
  402. }
  403. callback.flush = flush;
  404. callback.cancel = clear;
  405. return callback;
  406. }
  407. /**
  408. * Throttle fn, calling at most once
  409. * in the given interval.
  410. *
  411. * @param {Function} fn
  412. * @param {Number} interval
  413. *
  414. * @return {Function} throttled function
  415. */
  416. function throttle(fn, interval) {
  417. var throttling = false;
  418. return function () {
  419. if (throttling) {
  420. return;
  421. }
  422. fn.apply(void 0, arguments);
  423. throttling = true;
  424. setTimeout(function () {
  425. throttling = false;
  426. }, interval);
  427. };
  428. }
  429. /**
  430. * Bind function against target <this>.
  431. *
  432. * @param {Function} fn
  433. * @param {Object} target
  434. *
  435. * @return {Function} bound function
  436. */
  437. function bind(fn, target) {
  438. return fn.bind(target);
  439. }
  440. function _typeof(obj) {
  441. "@babel/helpers - typeof";
  442. if (typeof Symbol === "function" && typeof Symbol.iterator === "symbol") {
  443. _typeof = function (obj) {
  444. return typeof obj;
  445. };
  446. } else {
  447. _typeof = function (obj) {
  448. return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj;
  449. };
  450. }
  451. return _typeof(obj);
  452. }
  453. function _extends() {
  454. _extends = Object.assign || function (target) {
  455. for (var i = 1; i < arguments.length; i++) {
  456. var source = arguments[i];
  457. for (var key in source) {
  458. if (Object.prototype.hasOwnProperty.call(source, key)) {
  459. target[key] = source[key];
  460. }
  461. }
  462. }
  463. return target;
  464. };
  465. return _extends.apply(this, arguments);
  466. }
  467. /**
  468. * Convenience wrapper for `Object.assign`.
  469. *
  470. * @param {Object} target
  471. * @param {...Object} others
  472. *
  473. * @return {Object} the target
  474. */
  475. function assign(target) {
  476. for (var _len = arguments.length, others = new Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) {
  477. others[_key - 1] = arguments[_key];
  478. }
  479. return _extends.apply(void 0, [target].concat(others));
  480. }
  481. /**
  482. * Sets a nested property of a given object to the specified value.
  483. *
  484. * This mutates the object and returns it.
  485. *
  486. * @param {Object} target The target of the set operation.
  487. * @param {(string|number)[]} path The path to the nested value.
  488. * @param {any} value The value to set.
  489. */
  490. function set(target, path, value) {
  491. var currentTarget = target;
  492. forEach(path, function (key, idx) {
  493. if (typeof key !== 'number' && typeof key !== 'string') {
  494. throw new Error('illegal key type: ' + _typeof(key) + '. Key should be of type number or string.');
  495. }
  496. if (key === 'constructor') {
  497. throw new Error('illegal key: constructor');
  498. }
  499. if (key === '__proto__') {
  500. throw new Error('illegal key: __proto__');
  501. }
  502. var nextKey = path[idx + 1];
  503. var nextTarget = currentTarget[key];
  504. if (isDefined(nextKey) && isNil(nextTarget)) {
  505. nextTarget = currentTarget[key] = isNaN(+nextKey) ? {} : [];
  506. }
  507. if (isUndefined(nextKey)) {
  508. if (isUndefined(value)) {
  509. delete currentTarget[key];
  510. } else {
  511. currentTarget[key] = value;
  512. }
  513. } else {
  514. currentTarget = nextTarget;
  515. }
  516. });
  517. return target;
  518. }
  519. /**
  520. * Gets a nested property of a given object.
  521. *
  522. * @param {Object} target The target of the get operation.
  523. * @param {(string|number)[]} path The path to the nested value.
  524. * @param {any} [defaultValue] The value to return if no value exists.
  525. */
  526. function get(target, path, defaultValue) {
  527. var currentTarget = target;
  528. forEach(path, function (key) {
  529. // accessing nil property yields <undefined>
  530. if (isNil(currentTarget)) {
  531. currentTarget = undefined;
  532. return false;
  533. }
  534. currentTarget = currentTarget[key];
  535. });
  536. return isUndefined(currentTarget) ? defaultValue : currentTarget;
  537. }
  538. /**
  539. * Pick given properties from the target object.
  540. *
  541. * @param {Object} target
  542. * @param {Array} properties
  543. *
  544. * @return {Object} target
  545. */
  546. function pick(target, properties) {
  547. var result = {};
  548. var obj = Object(target);
  549. forEach(properties, function (prop) {
  550. if (prop in obj) {
  551. result[prop] = target[prop];
  552. }
  553. });
  554. return result;
  555. }
  556. /**
  557. * Pick all target properties, excluding the given ones.
  558. *
  559. * @param {Object} target
  560. * @param {Array} properties
  561. *
  562. * @return {Object} target
  563. */
  564. function omit(target, properties) {
  565. var result = {};
  566. var obj = Object(target);
  567. forEach(obj, function (prop, key) {
  568. if (properties.indexOf(key) === -1) {
  569. result[key] = prop;
  570. }
  571. });
  572. return result;
  573. }
  574. /**
  575. * Recursively merge `...sources` into given target.
  576. *
  577. * Does support merging objects; does not support merging arrays.
  578. *
  579. * @param {Object} target
  580. * @param {...Object} sources
  581. *
  582. * @return {Object} the target
  583. */
  584. function merge(target) {
  585. for (var _len2 = arguments.length, sources = new Array(_len2 > 1 ? _len2 - 1 : 0), _key2 = 1; _key2 < _len2; _key2++) {
  586. sources[_key2 - 1] = arguments[_key2];
  587. }
  588. if (!sources.length) {
  589. return target;
  590. }
  591. forEach(sources, function (source) {
  592. // skip non-obj sources, i.e. null
  593. if (!source || !isObject(source)) {
  594. return;
  595. }
  596. forEach(source, function (sourceVal, key) {
  597. if (key === '__proto__') {
  598. return;
  599. }
  600. var targetVal = target[key];
  601. if (isObject(sourceVal)) {
  602. if (!isObject(targetVal)) {
  603. // override target[key] with object
  604. targetVal = {};
  605. }
  606. target[key] = merge(targetVal, sourceVal);
  607. } else {
  608. target[key] = sourceVal;
  609. }
  610. });
  611. });
  612. return target;
  613. }
  614. exports.assign = assign;
  615. exports.bind = bind;
  616. exports.debounce = debounce;
  617. exports.ensureArray = ensureArray;
  618. exports.every = every;
  619. exports.filter = filter;
  620. exports.find = find;
  621. exports.findIndex = findIndex;
  622. exports.flatten = flatten;
  623. exports.forEach = forEach;
  624. exports.get = get;
  625. exports.groupBy = groupBy;
  626. exports.has = has;
  627. exports.isArray = isArray;
  628. exports.isDefined = isDefined;
  629. exports.isFunction = isFunction;
  630. exports.isNil = isNil;
  631. exports.isNumber = isNumber;
  632. exports.isObject = isObject;
  633. exports.isString = isString;
  634. exports.isUndefined = isUndefined;
  635. exports.keys = keys;
  636. exports.map = map;
  637. exports.matchPattern = matchPattern;
  638. exports.merge = merge;
  639. exports.omit = omit;
  640. exports.pick = pick;
  641. exports.reduce = reduce;
  642. exports.set = set;
  643. exports.size = size;
  644. exports.some = some;
  645. exports.sortBy = sortBy;
  646. exports.throttle = throttle;
  647. exports.unionBy = unionBy;
  648. exports.uniqueBy = uniqueBy;
  649. exports.values = values;
  650. exports.without = without;