@vinicunca/perkakas 1.14.0 → 1.16.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (563) hide show
  1. package/dist/add-prop.cjs +1 -1
  2. package/dist/add-prop.cjs.map +1 -1
  3. package/dist/add-prop.js.map +1 -1
  4. package/dist/add.cjs +1 -1
  5. package/dist/add.cjs.map +1 -1
  6. package/dist/add.js.map +1 -1
  7. package/dist/all-pass.cjs +1 -1
  8. package/dist/all-pass.cjs.map +1 -1
  9. package/dist/all-pass.js.map +1 -1
  10. package/dist/any-pass.cjs +1 -1
  11. package/dist/any-pass.cjs.map +1 -1
  12. package/dist/any-pass.js.map +1 -1
  13. package/dist/{binary-search-cutoff-index-TJlnoie4.js → binary-search-cutoff-index-CRPy-dOJ.js} +1 -1
  14. package/dist/{binary-search-cutoff-index-TJlnoie4.js.map → binary-search-cutoff-index-CRPy-dOJ.js.map} +1 -1
  15. package/dist/binary-search-cutoff-index-CdUUMUB1.cjs +2 -0
  16. package/dist/{binary-search-cutoff-index-CLFtXYPc.cjs.map → binary-search-cutoff-index-CdUUMUB1.cjs.map} +1 -1
  17. package/dist/capitalize.cjs +1 -1
  18. package/dist/capitalize.cjs.map +1 -1
  19. package/dist/capitalize.js.map +1 -1
  20. package/dist/ceil.cjs +1 -1
  21. package/dist/ceil.cjs.map +1 -1
  22. package/dist/ceil.js +1 -1
  23. package/dist/ceil.js.map +1 -1
  24. package/dist/chunk.cjs +1 -1
  25. package/dist/chunk.cjs.map +1 -1
  26. package/dist/chunk.js.map +1 -1
  27. package/dist/clamp.cjs +1 -1
  28. package/dist/clamp.cjs.map +1 -1
  29. package/dist/clamp.js.map +1 -1
  30. package/dist/clone.cjs +1 -1
  31. package/dist/clone.cjs.map +1 -1
  32. package/dist/clone.js.map +1 -1
  33. package/dist/concat.cjs +1 -1
  34. package/dist/concat.cjs.map +1 -1
  35. package/dist/concat.js.map +1 -1
  36. package/dist/conditional.cjs +2 -1
  37. package/dist/conditional.cjs.map +1 -0
  38. package/dist/conditional.js +2 -1
  39. package/dist/conditional.js.map +1 -0
  40. package/dist/constant.cjs.map +1 -1
  41. package/dist/constant.js.map +1 -1
  42. package/dist/count-by.cjs +1 -1
  43. package/dist/count-by.cjs.map +1 -1
  44. package/dist/count-by.js.map +1 -1
  45. package/dist/{curry-from-lazy-CtH1dp14.js → curry-from-lazy-BoPMn2L_.js} +1 -1
  46. package/dist/{curry-from-lazy-CtH1dp14.js.map → curry-from-lazy-BoPMn2L_.js.map} +1 -1
  47. package/dist/{curry-from-lazy-BvN_VKlH.cjs → curry-from-lazy-mdjeRP1g.cjs} +2 -2
  48. package/dist/{curry-from-lazy-BvN_VKlH.cjs.map → curry-from-lazy-mdjeRP1g.cjs.map} +1 -1
  49. package/dist/curry-on-Et2NUOHd.js +2 -0
  50. package/dist/curry-on-Et2NUOHd.js.map +1 -0
  51. package/dist/curry-on-wBH_q-mO.cjs +2 -0
  52. package/dist/curry-on-wBH_q-mO.cjs.map +1 -0
  53. package/dist/{curry-order-rules-DsJSy3gX.cjs → curry-order-rules-CacOTzfW.cjs} +2 -2
  54. package/dist/{curry-order-rules-DsJSy3gX.cjs.map → curry-order-rules-CacOTzfW.cjs.map} +1 -1
  55. package/dist/{curry-order-rules-BLyCSMdZ.js → curry-order-rules-Dage-BeC.js} +1 -1
  56. package/dist/{curry-order-rules-BLyCSMdZ.js.map → curry-order-rules-Dage-BeC.js.map} +1 -1
  57. package/dist/curry.cjs +1 -1
  58. package/dist/curry.cjs.map +1 -1
  59. package/dist/curry.js +1 -1
  60. package/dist/curry.js.map +1 -1
  61. package/dist/debounce.cjs.map +1 -1
  62. package/dist/debounce.js.map +1 -1
  63. package/dist/default-to.cjs +1 -1
  64. package/dist/default-to.cjs.map +1 -1
  65. package/dist/default-to.js.map +1 -1
  66. package/dist/difference-with.cjs +1 -1
  67. package/dist/difference-with.cjs.map +1 -1
  68. package/dist/difference-with.js +1 -1
  69. package/dist/difference-with.js.map +1 -1
  70. package/dist/difference.cjs +1 -1
  71. package/dist/difference.cjs.map +1 -1
  72. package/dist/difference.js +1 -1
  73. package/dist/difference.js.map +1 -1
  74. package/dist/divide.cjs +1 -1
  75. package/dist/divide.cjs.map +1 -1
  76. package/dist/divide.js.map +1 -1
  77. package/dist/do-nothing.cjs.map +1 -1
  78. package/dist/do-nothing.js.map +1 -1
  79. package/dist/drop-first-by.cjs +1 -1
  80. package/dist/drop-first-by.cjs.map +1 -1
  81. package/dist/drop-first-by.js +1 -1
  82. package/dist/drop-first-by.js.map +1 -1
  83. package/dist/drop-last-while.cjs +1 -1
  84. package/dist/drop-last-while.cjs.map +1 -1
  85. package/dist/drop-last-while.js.map +1 -1
  86. package/dist/drop-last.cjs +1 -1
  87. package/dist/drop-last.cjs.map +1 -1
  88. package/dist/drop-last.js.map +1 -1
  89. package/dist/drop-while.cjs +1 -1
  90. package/dist/drop-while.cjs.map +1 -1
  91. package/dist/drop-while.js.map +1 -1
  92. package/dist/drop.cjs +1 -1
  93. package/dist/drop.cjs.map +1 -1
  94. package/dist/drop.js +1 -1
  95. package/dist/drop.js.map +1 -1
  96. package/dist/ends-with.cjs +1 -1
  97. package/dist/ends-with.cjs.map +1 -1
  98. package/dist/ends-with.js.map +1 -1
  99. package/dist/entries.cjs +1 -1
  100. package/dist/entries.cjs.map +1 -1
  101. package/dist/entries.js.map +1 -1
  102. package/dist/evolve.cjs +1 -1
  103. package/dist/evolve.cjs.map +1 -1
  104. package/dist/evolve.js.map +1 -1
  105. package/dist/filter.cjs +1 -1
  106. package/dist/filter.cjs.map +1 -1
  107. package/dist/filter.js +1 -1
  108. package/dist/filter.js.map +1 -1
  109. package/dist/find-index.cjs +1 -1
  110. package/dist/find-index.cjs.map +1 -1
  111. package/dist/find-index.js.map +1 -1
  112. package/dist/find-last-index.cjs +1 -1
  113. package/dist/find-last-index.cjs.map +1 -1
  114. package/dist/find-last-index.js.map +1 -1
  115. package/dist/find-last.cjs +1 -1
  116. package/dist/find-last.cjs.map +1 -1
  117. package/dist/find-last.js.map +1 -1
  118. package/dist/find.cjs +1 -1
  119. package/dist/find.cjs.map +1 -1
  120. package/dist/find.js +1 -1
  121. package/dist/find.js.map +1 -1
  122. package/dist/first-by.cjs +1 -1
  123. package/dist/first-by.cjs.map +1 -1
  124. package/dist/first-by.js +1 -1
  125. package/dist/first-by.js.map +1 -1
  126. package/dist/first.cjs +1 -1
  127. package/dist/first.cjs.map +1 -1
  128. package/dist/first.js +1 -1
  129. package/dist/first.js.map +1 -1
  130. package/dist/flat-map.cjs +1 -1
  131. package/dist/flat-map.cjs.map +1 -1
  132. package/dist/flat-map.js.map +1 -1
  133. package/dist/flat.cjs +1 -1
  134. package/dist/flat.cjs.map +1 -1
  135. package/dist/flat.js +1 -1
  136. package/dist/flat.js.map +1 -1
  137. package/dist/floor.cjs +1 -1
  138. package/dist/floor.cjs.map +1 -1
  139. package/dist/floor.js +1 -1
  140. package/dist/floor.js.map +1 -1
  141. package/dist/for-each-obj.cjs +1 -1
  142. package/dist/for-each-obj.cjs.map +1 -1
  143. package/dist/for-each-obj.js.map +1 -1
  144. package/dist/for-each.cjs +1 -1
  145. package/dist/for-each.cjs.map +1 -1
  146. package/dist/for-each.js.map +1 -1
  147. package/dist/from-entries.cjs +1 -1
  148. package/dist/from-entries.cjs.map +1 -1
  149. package/dist/from-entries.js.map +1 -1
  150. package/dist/from-keys.cjs +1 -1
  151. package/dist/from-keys.cjs.map +1 -1
  152. package/dist/from-keys.js.map +1 -1
  153. package/dist/funnel.cjs.map +1 -1
  154. package/dist/funnel.js.map +1 -1
  155. package/dist/group-by-prop.cjs +1 -1
  156. package/dist/group-by-prop.cjs.map +1 -1
  157. package/dist/group-by-prop.js.map +1 -1
  158. package/dist/group-by.cjs +1 -1
  159. package/dist/group-by.cjs.map +1 -1
  160. package/dist/group-by.js.map +1 -1
  161. package/dist/has-at-least.cjs +1 -1
  162. package/dist/has-at-least.cjs.map +1 -1
  163. package/dist/has-at-least.js.map +1 -1
  164. package/dist/has-prop.cjs +2 -0
  165. package/dist/has-prop.cjs.map +1 -0
  166. package/dist/has-prop.js +2 -0
  167. package/dist/has-prop.js.map +1 -0
  168. package/dist/has-sub-object.cjs +1 -1
  169. package/dist/has-sub-object.cjs.map +1 -1
  170. package/dist/has-sub-object.js.map +1 -1
  171. package/dist/heap-BK0Y5t1Y.cjs +2 -0
  172. package/dist/{heap-C0zPQGC0.cjs.map → heap-BK0Y5t1Y.cjs.map} +1 -1
  173. package/dist/{heap-M6D40vkc.js → heap-CL5ahv5n.js} +2 -2
  174. package/dist/{heap-M6D40vkc.js.map → heap-CL5ahv5n.js.map} +1 -1
  175. package/dist/human-readable-file-size.cjs.map +1 -1
  176. package/dist/human-readable-file-size.js.map +1 -1
  177. package/dist/identity.cjs.map +1 -1
  178. package/dist/identity.js.map +1 -1
  179. package/dist/index-by.cjs +1 -1
  180. package/dist/index-by.cjs.map +1 -1
  181. package/dist/index-by.js.map +1 -1
  182. package/dist/index.cjs +1 -1
  183. package/dist/index.cjs.map +1 -1
  184. package/dist/index.d.cts +174 -202
  185. package/dist/index.d.cts.map +1 -1
  186. package/dist/index.d.ts +174 -202
  187. package/dist/index.d.ts.map +1 -1
  188. package/dist/index.js +1 -1
  189. package/dist/index.js.map +1 -1
  190. package/dist/intersection-with.cjs +1 -1
  191. package/dist/intersection-with.cjs.map +1 -1
  192. package/dist/intersection-with.js +1 -1
  193. package/dist/intersection-with.js.map +1 -1
  194. package/dist/intersection.cjs +1 -1
  195. package/dist/intersection.cjs.map +1 -1
  196. package/dist/intersection.js +1 -1
  197. package/dist/intersection.js.map +1 -1
  198. package/dist/invert.cjs +1 -1
  199. package/dist/invert.cjs.map +1 -1
  200. package/dist/invert.js.map +1 -1
  201. package/dist/is-array.cjs.map +1 -1
  202. package/dist/is-array.js.map +1 -1
  203. package/dist/is-big-int.cjs.map +1 -1
  204. package/dist/is-big-int.js.map +1 -1
  205. package/dist/is-boolean.cjs.map +1 -1
  206. package/dist/is-boolean.js.map +1 -1
  207. package/dist/is-date.cjs.map +1 -1
  208. package/dist/is-date.js.map +1 -1
  209. package/dist/is-deep-equal.cjs +1 -1
  210. package/dist/is-deep-equal.cjs.map +1 -1
  211. package/dist/is-deep-equal.js +1 -1
  212. package/dist/is-deep-equal.js.map +1 -1
  213. package/dist/is-defined.cjs.map +1 -1
  214. package/dist/is-defined.js.map +1 -1
  215. package/dist/is-empty.cjs.map +1 -1
  216. package/dist/is-empty.js.map +1 -1
  217. package/dist/is-emptyish.cjs.map +1 -1
  218. package/dist/is-emptyish.js.map +1 -1
  219. package/dist/is-error.cjs.map +1 -1
  220. package/dist/is-error.js.map +1 -1
  221. package/dist/is-function.cjs.map +1 -1
  222. package/dist/is-function.js.map +1 -1
  223. package/dist/is-included-in.cjs.map +1 -1
  224. package/dist/is-included-in.js.map +1 -1
  225. package/dist/is-non-null.cjs.map +1 -1
  226. package/dist/is-non-null.js.map +1 -1
  227. package/dist/is-non-nullish.cjs.map +1 -1
  228. package/dist/is-non-nullish.js.map +1 -1
  229. package/dist/is-not.cjs.map +1 -1
  230. package/dist/is-not.js.map +1 -1
  231. package/dist/is-nullish.cjs.map +1 -1
  232. package/dist/is-nullish.js.map +1 -1
  233. package/dist/is-number.cjs.map +1 -1
  234. package/dist/is-number.js.map +1 -1
  235. package/dist/is-object-type.cjs.map +1 -1
  236. package/dist/is-object-type.js.map +1 -1
  237. package/dist/is-plain-object.cjs.map +1 -1
  238. package/dist/is-plain-object.js.map +1 -1
  239. package/dist/is-promise.cjs.map +1 -1
  240. package/dist/is-promise.js.map +1 -1
  241. package/dist/is-shallow-equal.cjs +1 -1
  242. package/dist/is-shallow-equal.cjs.map +1 -1
  243. package/dist/is-shallow-equal.js.map +1 -1
  244. package/dist/is-strict-equal.cjs +1 -1
  245. package/dist/is-strict-equal.cjs.map +1 -1
  246. package/dist/is-strict-equal.js.map +1 -1
  247. package/dist/is-string.cjs.map +1 -1
  248. package/dist/is-string.js.map +1 -1
  249. package/dist/is-symbol.cjs.map +1 -1
  250. package/dist/is-symbol.js.map +1 -1
  251. package/dist/is-truthy.cjs.map +1 -1
  252. package/dist/is-truthy.js.map +1 -1
  253. package/dist/join.cjs +1 -1
  254. package/dist/join.cjs.map +1 -1
  255. package/dist/join.js.map +1 -1
  256. package/dist/key-codes.cjs.map +1 -1
  257. package/dist/key-codes.js.map +1 -1
  258. package/dist/keys.cjs +1 -1
  259. package/dist/keys.cjs.map +1 -1
  260. package/dist/keys.js.map +1 -1
  261. package/dist/last.cjs +1 -1
  262. package/dist/last.cjs.map +1 -1
  263. package/dist/last.js.map +1 -1
  264. package/dist/{lazy-data-last-impl-Vt_M0l7X.js → lazy-data-last-impl--3B10z3s.js} +1 -1
  265. package/dist/{lazy-data-last-impl-Vt_M0l7X.js.map → lazy-data-last-impl--3B10z3s.js.map} +1 -1
  266. package/dist/lazy-data-last-impl-Dd5zjCfU.cjs +2 -0
  267. package/dist/{lazy-data-last-impl-B05ZpguF.cjs.map → lazy-data-last-impl-Dd5zjCfU.cjs.map} +1 -1
  268. package/dist/length.cjs +1 -1
  269. package/dist/length.cjs.map +1 -1
  270. package/dist/length.js.map +1 -1
  271. package/dist/map-keys.cjs +1 -1
  272. package/dist/map-keys.cjs.map +1 -1
  273. package/dist/map-keys.js.map +1 -1
  274. package/dist/map-to-obj.cjs +1 -1
  275. package/dist/map-to-obj.cjs.map +1 -1
  276. package/dist/map-to-obj.js.map +1 -1
  277. package/dist/map-values.cjs +1 -1
  278. package/dist/map-values.cjs.map +1 -1
  279. package/dist/map-values.js.map +1 -1
  280. package/dist/map-with-feedback.cjs +1 -1
  281. package/dist/map-with-feedback.cjs.map +1 -1
  282. package/dist/map-with-feedback.js +1 -1
  283. package/dist/map-with-feedback.js.map +1 -1
  284. package/dist/map.cjs +1 -1
  285. package/dist/map.cjs.map +1 -1
  286. package/dist/map.js.map +1 -1
  287. package/dist/mean-by.cjs +1 -1
  288. package/dist/mean-by.cjs.map +1 -1
  289. package/dist/mean-by.js.map +1 -1
  290. package/dist/mean.cjs +1 -1
  291. package/dist/mean.cjs.map +1 -1
  292. package/dist/mean.js.map +1 -1
  293. package/dist/median.cjs +1 -1
  294. package/dist/median.cjs.map +1 -1
  295. package/dist/median.js.map +1 -1
  296. package/dist/merge-all.cjs.map +1 -1
  297. package/dist/merge-all.js.map +1 -1
  298. package/dist/merge-deep.cjs +1 -1
  299. package/dist/merge-deep.cjs.map +1 -1
  300. package/dist/merge-deep.js.map +1 -1
  301. package/dist/merge.cjs +1 -1
  302. package/dist/merge.cjs.map +1 -1
  303. package/dist/merge.js.map +1 -1
  304. package/dist/multiply.cjs +1 -1
  305. package/dist/multiply.cjs.map +1 -1
  306. package/dist/multiply.js.map +1 -1
  307. package/dist/{nth-by-zZ3RM-mR.cjs → nth-by-BrkoqeV2.cjs} +2 -2
  308. package/dist/{nth-by-zZ3RM-mR.cjs.map → nth-by-BrkoqeV2.cjs.map} +1 -1
  309. package/dist/{nth-by-DhfNV5xd.js → nth-by-DGcGGvJX.js} +2 -2
  310. package/dist/{nth-by-DhfNV5xd.js.map → nth-by-DGcGGvJX.js.map} +1 -1
  311. package/dist/nth-by.cjs +1 -1
  312. package/dist/nth-by.js +1 -1
  313. package/dist/obj-of.cjs +1 -1
  314. package/dist/obj-of.cjs.map +1 -1
  315. package/dist/obj-of.js.map +1 -1
  316. package/dist/omit-by.cjs +1 -1
  317. package/dist/omit-by.cjs.map +1 -1
  318. package/dist/omit-by.js.map +1 -1
  319. package/dist/omit.cjs +1 -1
  320. package/dist/omit.cjs.map +1 -1
  321. package/dist/omit.js.map +1 -1
  322. package/dist/once.cjs.map +1 -1
  323. package/dist/once.js.map +1 -1
  324. package/dist/only.cjs +1 -1
  325. package/dist/only.cjs.map +1 -1
  326. package/dist/only.js.map +1 -1
  327. package/dist/partial-bind.cjs.map +1 -1
  328. package/dist/partial-bind.js.map +1 -1
  329. package/dist/partial-last-bind.cjs.map +1 -1
  330. package/dist/partial-last-bind.js.map +1 -1
  331. package/dist/partition.cjs +1 -1
  332. package/dist/partition.cjs.map +1 -1
  333. package/dist/partition.js.map +1 -1
  334. package/dist/path-or.cjs +1 -1
  335. package/dist/path-or.cjs.map +1 -1
  336. package/dist/path-or.js.map +1 -1
  337. package/dist/pick-by.cjs +1 -1
  338. package/dist/pick-by.cjs.map +1 -1
  339. package/dist/pick-by.js.map +1 -1
  340. package/dist/pick.cjs +1 -1
  341. package/dist/pick.cjs.map +1 -1
  342. package/dist/pick.js.map +1 -1
  343. package/dist/pipe.cjs +1 -1
  344. package/dist/pipe.cjs.map +1 -1
  345. package/dist/pipe.js +1 -1
  346. package/dist/pipe.js.map +1 -1
  347. package/dist/piped.cjs +1 -1
  348. package/dist/piped.cjs.map +1 -1
  349. package/dist/piped.js.map +1 -1
  350. package/dist/product.cjs +1 -1
  351. package/dist/product.cjs.map +1 -1
  352. package/dist/product.js.map +1 -1
  353. package/dist/prop.cjs.map +1 -1
  354. package/dist/prop.js.map +1 -1
  355. package/dist/pull-object.cjs +1 -1
  356. package/dist/pull-object.cjs.map +1 -1
  357. package/dist/pull-object.js.map +1 -1
  358. package/dist/random-big-int.cjs.map +1 -1
  359. package/dist/random-big-int.js.map +1 -1
  360. package/dist/random-integer.cjs.map +1 -1
  361. package/dist/random-integer.js.map +1 -1
  362. package/dist/random-string.cjs +1 -1
  363. package/dist/random-string.cjs.map +1 -1
  364. package/dist/random-string.js.map +1 -1
  365. package/dist/range.cjs +1 -1
  366. package/dist/range.cjs.map +1 -1
  367. package/dist/range.js.map +1 -1
  368. package/dist/rank-by.cjs +1 -1
  369. package/dist/rank-by.cjs.map +1 -1
  370. package/dist/rank-by.js +1 -1
  371. package/dist/rank-by.js.map +1 -1
  372. package/dist/reduce.cjs +1 -1
  373. package/dist/reduce.cjs.map +1 -1
  374. package/dist/reduce.js.map +1 -1
  375. package/dist/reverse.cjs +1 -1
  376. package/dist/reverse.cjs.map +1 -1
  377. package/dist/reverse.js.map +1 -1
  378. package/dist/round.cjs +1 -1
  379. package/dist/round.cjs.map +1 -1
  380. package/dist/round.js +1 -1
  381. package/dist/round.js.map +1 -1
  382. package/dist/sample.cjs +1 -1
  383. package/dist/sample.cjs.map +1 -1
  384. package/dist/sample.js.map +1 -1
  385. package/dist/set-path.cjs +1 -1
  386. package/dist/set-path.cjs.map +1 -1
  387. package/dist/set-path.js.map +1 -1
  388. package/dist/set.cjs +1 -1
  389. package/dist/set.cjs.map +1 -1
  390. package/dist/set.js.map +1 -1
  391. package/dist/shuffle.cjs +1 -1
  392. package/dist/shuffle.cjs.map +1 -1
  393. package/dist/shuffle.js.map +1 -1
  394. package/dist/sleep.cjs.map +1 -1
  395. package/dist/sleep.js.map +1 -1
  396. package/dist/slice-string.cjs.map +1 -1
  397. package/dist/slice-string.js.map +1 -1
  398. package/dist/slugify.cjs.map +1 -1
  399. package/dist/slugify.js.map +1 -1
  400. package/dist/sort-by.cjs +1 -1
  401. package/dist/sort-by.cjs.map +1 -1
  402. package/dist/sort-by.js +1 -1
  403. package/dist/sort-by.js.map +1 -1
  404. package/dist/sort.cjs +1 -1
  405. package/dist/sort.cjs.map +1 -1
  406. package/dist/sort.js.map +1 -1
  407. package/dist/sorted-index-by.cjs +1 -1
  408. package/dist/sorted-index-by.cjs.map +1 -1
  409. package/dist/sorted-index-by.js +1 -1
  410. package/dist/sorted-index-by.js.map +1 -1
  411. package/dist/sorted-index-with.cjs +1 -1
  412. package/dist/sorted-index-with.cjs.map +1 -1
  413. package/dist/sorted-index-with.js +1 -1
  414. package/dist/sorted-index-with.js.map +1 -1
  415. package/dist/sorted-index.cjs +1 -1
  416. package/dist/sorted-index.cjs.map +1 -1
  417. package/dist/sorted-index.js +1 -1
  418. package/dist/sorted-index.js.map +1 -1
  419. package/dist/sorted-last-index-by.cjs +1 -1
  420. package/dist/sorted-last-index-by.cjs.map +1 -1
  421. package/dist/sorted-last-index-by.js +1 -1
  422. package/dist/sorted-last-index-by.js.map +1 -1
  423. package/dist/sorted-last-index.cjs +1 -1
  424. package/dist/sorted-last-index.cjs.map +1 -1
  425. package/dist/sorted-last-index.js +1 -1
  426. package/dist/sorted-last-index.js.map +1 -1
  427. package/dist/splice.cjs +1 -1
  428. package/dist/splice.cjs.map +1 -1
  429. package/dist/splice.js +1 -1
  430. package/dist/splice.js.map +1 -1
  431. package/dist/split-at.cjs +1 -1
  432. package/dist/split-at.cjs.map +1 -1
  433. package/dist/split-at.js.map +1 -1
  434. package/dist/split-when.cjs +1 -1
  435. package/dist/split-when.cjs.map +1 -1
  436. package/dist/split-when.js.map +1 -1
  437. package/dist/split.cjs.map +1 -1
  438. package/dist/split.js.map +1 -1
  439. package/dist/starts-with.cjs +1 -1
  440. package/dist/starts-with.cjs.map +1 -1
  441. package/dist/starts-with.js.map +1 -1
  442. package/dist/string-to-path.cjs.map +1 -1
  443. package/dist/string-to-path.js.map +1 -1
  444. package/dist/subtract.cjs +1 -1
  445. package/dist/subtract.cjs.map +1 -1
  446. package/dist/subtract.js.map +1 -1
  447. package/dist/sum-by.cjs +1 -1
  448. package/dist/sum-by.cjs.map +1 -1
  449. package/dist/sum-by.js.map +1 -1
  450. package/dist/sum.cjs +1 -1
  451. package/dist/sum.cjs.map +1 -1
  452. package/dist/sum.js.map +1 -1
  453. package/dist/swap-in-place-CllcD0HG.cjs +2 -0
  454. package/dist/{swap-in-place-D1vasegg.cjs.map → swap-in-place-CllcD0HG.cjs.map} +1 -1
  455. package/dist/{swap-in-place-BzNaxwB3.js → swap-in-place-ubtnp8en.js} +1 -1
  456. package/dist/{swap-in-place-BzNaxwB3.js.map → swap-in-place-ubtnp8en.js.map} +1 -1
  457. package/dist/swap-indices.cjs +1 -1
  458. package/dist/swap-indices.cjs.map +1 -1
  459. package/dist/swap-indices.js.map +1 -1
  460. package/dist/swap-props.cjs +1 -1
  461. package/dist/swap-props.cjs.map +1 -1
  462. package/dist/swap-props.js.map +1 -1
  463. package/dist/take-first-by.cjs +1 -1
  464. package/dist/take-first-by.cjs.map +1 -1
  465. package/dist/take-first-by.js +1 -1
  466. package/dist/take-first-by.js.map +1 -1
  467. package/dist/take-last-while.cjs +1 -1
  468. package/dist/take-last-while.cjs.map +1 -1
  469. package/dist/take-last-while.js.map +1 -1
  470. package/dist/take-last.cjs +1 -1
  471. package/dist/take-last.cjs.map +1 -1
  472. package/dist/take-last.js.map +1 -1
  473. package/dist/take-while.cjs +1 -1
  474. package/dist/take-while.cjs.map +1 -1
  475. package/dist/take-while.js.map +1 -1
  476. package/dist/take.cjs +1 -1
  477. package/dist/take.cjs.map +1 -1
  478. package/dist/take.js +1 -1
  479. package/dist/take.js.map +1 -1
  480. package/dist/tap.cjs +1 -1
  481. package/dist/tap.cjs.map +1 -1
  482. package/dist/tap.js.map +1 -1
  483. package/dist/times.cjs +1 -1
  484. package/dist/times.cjs.map +1 -1
  485. package/dist/times.js.map +1 -1
  486. package/dist/to-camel-case.cjs +1 -1
  487. package/dist/to-camel-case.cjs.map +1 -1
  488. package/dist/to-camel-case.js +1 -1
  489. package/dist/to-camel-case.js.map +1 -1
  490. package/dist/to-kebab-case.cjs +1 -1
  491. package/dist/to-kebab-case.cjs.map +1 -1
  492. package/dist/to-kebab-case.js +1 -1
  493. package/dist/to-kebab-case.js.map +1 -1
  494. package/dist/to-lower-case.cjs +1 -1
  495. package/dist/to-lower-case.cjs.map +1 -1
  496. package/dist/to-lower-case.js.map +1 -1
  497. package/dist/to-single-BOkjnmkm.cjs +2 -0
  498. package/dist/{to-single-BunGuk7o.cjs.map → to-single-BOkjnmkm.cjs.map} +1 -1
  499. package/dist/{to-single-XEXXW73e.js → to-single-D6t2BxVq.js} +1 -1
  500. package/dist/{to-single-XEXXW73e.js.map → to-single-D6t2BxVq.js.map} +1 -1
  501. package/dist/to-snake-case.cjs +1 -1
  502. package/dist/to-snake-case.cjs.map +1 -1
  503. package/dist/to-snake-case.js +1 -1
  504. package/dist/to-snake-case.js.map +1 -1
  505. package/dist/to-title-case.cjs +1 -1
  506. package/dist/to-title-case.cjs.map +1 -1
  507. package/dist/to-title-case.js +1 -1
  508. package/dist/to-title-case.js.map +1 -1
  509. package/dist/to-upper-case.cjs +1 -1
  510. package/dist/to-upper-case.cjs.map +1 -1
  511. package/dist/to-upper-case.js.map +1 -1
  512. package/dist/truncate.cjs.map +1 -1
  513. package/dist/truncate.js.map +1 -1
  514. package/dist/uncapitalize.cjs +1 -1
  515. package/dist/uncapitalize.cjs.map +1 -1
  516. package/dist/uncapitalize.js.map +1 -1
  517. package/dist/unique-by.cjs +1 -1
  518. package/dist/unique-by.cjs.map +1 -1
  519. package/dist/unique-by.js +1 -1
  520. package/dist/unique-by.js.map +1 -1
  521. package/dist/unique-with.cjs +1 -1
  522. package/dist/unique-with.cjs.map +1 -1
  523. package/dist/unique-with.js +1 -1
  524. package/dist/unique-with.js.map +1 -1
  525. package/dist/unique.cjs +1 -1
  526. package/dist/unique.cjs.map +1 -1
  527. package/dist/unique.js +1 -1
  528. package/dist/unique.js.map +1 -1
  529. package/dist/utility-evaluators-BGM19SpK.cjs +2 -0
  530. package/dist/{utility-evaluators-C8koSp9T.cjs.map → utility-evaluators-BGM19SpK.cjs.map} +1 -1
  531. package/dist/{utility-evaluators-ZAaUtL2Z.js → utility-evaluators-DDW55xeL.js} +1 -1
  532. package/dist/{utility-evaluators-ZAaUtL2Z.js.map → utility-evaluators-DDW55xeL.js.map} +1 -1
  533. package/dist/values.cjs +1 -1
  534. package/dist/values.cjs.map +1 -1
  535. package/dist/values.js.map +1 -1
  536. package/dist/when.cjs.map +1 -1
  537. package/dist/when.js.map +1 -1
  538. package/dist/{with-precision-CgRuf7Wl.js → with-precision-D-84B_By.js} +1 -1
  539. package/dist/{with-precision-CgRuf7Wl.js.map → with-precision-D-84B_By.js.map} +1 -1
  540. package/dist/{with-precision-DVi9325n.cjs → with-precision-Dy5W6bdk.cjs} +2 -2
  541. package/dist/{with-precision-DVi9325n.cjs.map → with-precision-Dy5W6bdk.cjs.map} +1 -1
  542. package/dist/{words-C8Rd_80F.cjs → words-B-9EXtsW.cjs} +2 -2
  543. package/dist/{words-C8Rd_80F.cjs.map → words-B-9EXtsW.cjs.map} +1 -1
  544. package/dist/{words-CYZ0Lyko.js → words-CN1Qil5U.js} +2 -2
  545. package/dist/{words-CYZ0Lyko.js.map → words-CN1Qil5U.js.map} +1 -1
  546. package/dist/zip-with.cjs +1 -1
  547. package/dist/zip-with.cjs.map +1 -1
  548. package/dist/zip-with.js +1 -1
  549. package/dist/zip-with.js.map +1 -1
  550. package/dist/zip.cjs +1 -1
  551. package/dist/zip.cjs.map +1 -1
  552. package/dist/zip.js.map +1 -1
  553. package/package.json +11 -11
  554. package/dist/binary-search-cutoff-index-CLFtXYPc.cjs +0 -2
  555. package/dist/conditional-3wcaMG9k.cjs +0 -2
  556. package/dist/conditional-3wcaMG9k.cjs.map +0 -1
  557. package/dist/conditional-CTEJD5TX.js +0 -2
  558. package/dist/conditional-CTEJD5TX.js.map +0 -1
  559. package/dist/heap-C0zPQGC0.cjs +0 -2
  560. package/dist/lazy-data-last-impl-B05ZpguF.cjs +0 -2
  561. package/dist/swap-in-place-D1vasegg.cjs +0 -2
  562. package/dist/to-single-BunGuk7o.cjs +0 -2
  563. package/dist/utility-evaluators-C8koSp9T.cjs +0 -2
@@ -1 +1 @@
1
- {"version":3,"file":"for-each.cjs","names":["curry"],"sources":["../src/for-each.ts"],"sourcesContent":["import type { Writable } from 'type-fest';\nimport type { IterableContainer } from './internal/types/iterable-container';\nimport type { LazyEvaluator } from './internal/types/lazy-evaluator';\nimport { curry } from './curry';\n\n/**\n * Executes a provided function once for each array element. Equivalent to\n * `Array.prototype.forEach`.\n *\n * The dataLast version returns the original array (instead of not returning\n * anything (`void`)) to allow using it in a pipe. When not used in a `pipe` the\n * returned array is equal to the input array (by reference), and not a shallow\n * copy of it!\n *\n * @param data - The values that would be iterated on.\n * @param callbackfn - A function to execute for each element in the array.\n * @signature\n * forEach(data, callbackfn)\n * @example\n * forEach([1, 2, 3], x => {\n * console.log(x)\n * });\n * @dataFirst\n * @lazy\n * @category Array\n */\nexport function forEach<T extends IterableContainer>(\n data: T,\n callbackfn: (value: T[number], index: number, data: T) => void,\n): void;\n\n/**\n * Executes a provided function once for each array element. Equivalent to\n * `Array.prototype.forEach`.\n *\n * The dataLast version returns the original array (instead of not returning\n * anything (`void`)) to allow using it in a pipe. The returned array is the\n * same reference as the input array, and not a shallow copy of it!\n *\n * @param callbackfn - A function to execute for each element in the array.\n * @returns The original array (the ref itself, not a shallow copy of it).\n * @signature\n * forEach(callbackfn)(data)\n * @example\n * pipe(\n * [1, 2, 3],\n * forEach(x => {\n * console.log(x)\n * })\n * ) // => [1, 2, 3]\n * @dataLast\n * @lazy\n * @category Array\n */\nexport function forEach<T extends IterableContainer>(\n callbackfn: (value: T[number], index: number, data: T) => void,\n): (data: T) => Writable<T>;\n\nexport function forEach(...args: ReadonlyArray<unknown>): unknown {\n return curry(forEachImplementation, args, lazyImplementation);\n}\n\nfunction forEachImplementation<T>(\n data: ReadonlyArray<T>,\n callbackfn: (value: T, index: number, data: ReadonlyArray<T>) => void,\n): Array<T> {\n data.forEach(callbackfn);\n // @ts-expect-error [ts4104] - Because the dataFirst signature returns void this is only a problem when the dataLast function is used **outside** of a pipe; for these cases we warn the user that this is happening.\n return data;\n}\n\nfunction lazyImplementation<T>(callbackfn: (value: T, index: number, data: ReadonlyArray<T>) => void): LazyEvaluator<T> {\n return (value, index, data) => {\n callbackfn(value, index, data);\n return { done: false, hasNext: true, next: value };\n };\n}\n"],"mappings":"kGA0DA,SAAgB,EAAQ,GAAG,EAAuC,CAChE,OAAOA,EAAAA,MAAM,EAAuB,EAAM,EAAmB,CAG/D,SAAS,EACP,EACA,EACU,CAGV,OAFA,EAAK,QAAQ,EAAW,CAEjB,EAGT,SAAS,EAAsB,EAAyF,CACtH,OAAQ,EAAO,EAAO,KACpB,EAAW,EAAO,EAAO,EAAK,CACvB,CAAE,KAAM,GAAO,QAAS,GAAM,KAAM,EAAO"}
1
+ {"version":3,"file":"for-each.cjs","names":["curry"],"sources":["../src/for-each.ts"],"sourcesContent":["import type { Writable } from 'type-fest';\nimport type { IterableContainer } from './internal/types/iterable-container';\nimport type { LazyEvaluator } from './internal/types/lazy-evaluator';\nimport { curry } from './curry';\n\n/**\n * Executes a provided function once for each array element. Equivalent to\n * `Array.prototype.forEach`.\n *\n * The dataLast version returns the original array (instead of not returning\n * anything (`void`)) to allow using it in a pipe. When not used in a `pipe` the\n * returned array is equal to the input array (by reference), and not a shallow\n * copy of it!\n *\n * @param data - The values that would be iterated on.\n * @param callbackfn - A function to execute for each element in the array.\n * @signature\n * forEach(data, callbackfn)\n * @example\n * forEach([1, 2, 3], x => {\n * console.log(x)\n * });\n * @dataFirst\n * @lazy\n * @category Array\n */\nexport function forEach<T extends IterableContainer>(\n data: T,\n callbackfn: (value: T[number], index: number, data: T) => void,\n): void;\n\n/**\n * Executes a provided function once for each array element. Equivalent to\n * `Array.prototype.forEach`.\n *\n * The dataLast version returns the original array (instead of not returning\n * anything (`void`)) to allow using it in a pipe. The returned array is the\n * same reference as the input array, and not a shallow copy of it!\n *\n * @param callbackfn - A function to execute for each element in the array.\n * @returns The original array (the ref itself, not a shallow copy of it).\n * @signature\n * forEach(callbackfn)(data)\n * @example\n * pipe(\n * [1, 2, 3],\n * forEach(x => {\n * console.log(x)\n * })\n * ) // => [1, 2, 3]\n * @dataLast\n * @lazy\n * @category Array\n */\nexport function forEach<T extends IterableContainer>(\n callbackfn: (value: T[number], index: number, data: T) => void,\n): (data: T) => Writable<T>;\n\nexport function forEach(...args: ReadonlyArray<unknown>): unknown {\n return curry(forEachImplementation, args, lazyImplementation);\n}\n\nfunction forEachImplementation<T>(\n data: ReadonlyArray<T>,\n callbackfn: (value: T, index: number, data: ReadonlyArray<T>) => void,\n): Array<T> {\n data.forEach(callbackfn);\n // @ts-expect-error [ts4104] - Because the dataFirst signature returns void this is only a problem when the dataLast function is used **outside** of a pipe; for these cases we warn the user that this is happening.\n return data;\n}\n\nfunction lazyImplementation<T>(callbackfn: (value: T, index: number, data: ReadonlyArray<T>) => void): LazyEvaluator<T> {\n return (value, index, data) => {\n callbackfn(value, index, data);\n return { done: false, hasNext: true, next: value };\n };\n}\n"],"mappings":"kGA0DA,SAAgB,EAAQ,GAAG,EAAuC,CAChE,OAAOA,EAAAA,MAAM,EAAuB,EAAM,CAAkB,CAC9D,CAEA,SAAS,EACP,EACA,EACU,CAGV,OAFA,EAAK,QAAQ,CAAU,EAEhB,CACT,CAEA,SAAS,EAAsB,EAAyF,CACtH,OAAQ,EAAO,EAAO,KACpB,EAAW,EAAO,EAAO,CAAI,EACtB,CAAE,KAAM,GAAO,QAAS,GAAM,KAAM,CAAM,EAErD"}
@@ -1 +1 @@
1
- {"version":3,"file":"for-each.js","names":[],"sources":["../src/for-each.ts"],"sourcesContent":["import type { Writable } from 'type-fest';\nimport type { IterableContainer } from './internal/types/iterable-container';\nimport type { LazyEvaluator } from './internal/types/lazy-evaluator';\nimport { curry } from './curry';\n\n/**\n * Executes a provided function once for each array element. Equivalent to\n * `Array.prototype.forEach`.\n *\n * The dataLast version returns the original array (instead of not returning\n * anything (`void`)) to allow using it in a pipe. When not used in a `pipe` the\n * returned array is equal to the input array (by reference), and not a shallow\n * copy of it!\n *\n * @param data - The values that would be iterated on.\n * @param callbackfn - A function to execute for each element in the array.\n * @signature\n * forEach(data, callbackfn)\n * @example\n * forEach([1, 2, 3], x => {\n * console.log(x)\n * });\n * @dataFirst\n * @lazy\n * @category Array\n */\nexport function forEach<T extends IterableContainer>(\n data: T,\n callbackfn: (value: T[number], index: number, data: T) => void,\n): void;\n\n/**\n * Executes a provided function once for each array element. Equivalent to\n * `Array.prototype.forEach`.\n *\n * The dataLast version returns the original array (instead of not returning\n * anything (`void`)) to allow using it in a pipe. The returned array is the\n * same reference as the input array, and not a shallow copy of it!\n *\n * @param callbackfn - A function to execute for each element in the array.\n * @returns The original array (the ref itself, not a shallow copy of it).\n * @signature\n * forEach(callbackfn)(data)\n * @example\n * pipe(\n * [1, 2, 3],\n * forEach(x => {\n * console.log(x)\n * })\n * ) // => [1, 2, 3]\n * @dataLast\n * @lazy\n * @category Array\n */\nexport function forEach<T extends IterableContainer>(\n callbackfn: (value: T[number], index: number, data: T) => void,\n): (data: T) => Writable<T>;\n\nexport function forEach(...args: ReadonlyArray<unknown>): unknown {\n return curry(forEachImplementation, args, lazyImplementation);\n}\n\nfunction forEachImplementation<T>(\n data: ReadonlyArray<T>,\n callbackfn: (value: T, index: number, data: ReadonlyArray<T>) => void,\n): Array<T> {\n data.forEach(callbackfn);\n // @ts-expect-error [ts4104] - Because the dataFirst signature returns void this is only a problem when the dataLast function is used **outside** of a pipe; for these cases we warn the user that this is happening.\n return data;\n}\n\nfunction lazyImplementation<T>(callbackfn: (value: T, index: number, data: ReadonlyArray<T>) => void): LazyEvaluator<T> {\n return (value, index, data) => {\n callbackfn(value, index, data);\n return { done: false, hasNext: true, next: value };\n };\n}\n"],"mappings":"mCA0DA,SAAgB,EAAQ,GAAG,EAAuC,CAChE,OAAO,EAAM,EAAuB,EAAM,EAAmB,CAG/D,SAAS,EACP,EACA,EACU,CAGV,OAFA,EAAK,QAAQ,EAAW,CAEjB,EAGT,SAAS,EAAsB,EAAyF,CACtH,OAAQ,EAAO,EAAO,KACpB,EAAW,EAAO,EAAO,EAAK,CACvB,CAAE,KAAM,GAAO,QAAS,GAAM,KAAM,EAAO"}
1
+ {"version":3,"file":"for-each.js","names":[],"sources":["../src/for-each.ts"],"sourcesContent":["import type { Writable } from 'type-fest';\nimport type { IterableContainer } from './internal/types/iterable-container';\nimport type { LazyEvaluator } from './internal/types/lazy-evaluator';\nimport { curry } from './curry';\n\n/**\n * Executes a provided function once for each array element. Equivalent to\n * `Array.prototype.forEach`.\n *\n * The dataLast version returns the original array (instead of not returning\n * anything (`void`)) to allow using it in a pipe. When not used in a `pipe` the\n * returned array is equal to the input array (by reference), and not a shallow\n * copy of it!\n *\n * @param data - The values that would be iterated on.\n * @param callbackfn - A function to execute for each element in the array.\n * @signature\n * forEach(data, callbackfn)\n * @example\n * forEach([1, 2, 3], x => {\n * console.log(x)\n * });\n * @dataFirst\n * @lazy\n * @category Array\n */\nexport function forEach<T extends IterableContainer>(\n data: T,\n callbackfn: (value: T[number], index: number, data: T) => void,\n): void;\n\n/**\n * Executes a provided function once for each array element. Equivalent to\n * `Array.prototype.forEach`.\n *\n * The dataLast version returns the original array (instead of not returning\n * anything (`void`)) to allow using it in a pipe. The returned array is the\n * same reference as the input array, and not a shallow copy of it!\n *\n * @param callbackfn - A function to execute for each element in the array.\n * @returns The original array (the ref itself, not a shallow copy of it).\n * @signature\n * forEach(callbackfn)(data)\n * @example\n * pipe(\n * [1, 2, 3],\n * forEach(x => {\n * console.log(x)\n * })\n * ) // => [1, 2, 3]\n * @dataLast\n * @lazy\n * @category Array\n */\nexport function forEach<T extends IterableContainer>(\n callbackfn: (value: T[number], index: number, data: T) => void,\n): (data: T) => Writable<T>;\n\nexport function forEach(...args: ReadonlyArray<unknown>): unknown {\n return curry(forEachImplementation, args, lazyImplementation);\n}\n\nfunction forEachImplementation<T>(\n data: ReadonlyArray<T>,\n callbackfn: (value: T, index: number, data: ReadonlyArray<T>) => void,\n): Array<T> {\n data.forEach(callbackfn);\n // @ts-expect-error [ts4104] - Because the dataFirst signature returns void this is only a problem when the dataLast function is used **outside** of a pipe; for these cases we warn the user that this is happening.\n return data;\n}\n\nfunction lazyImplementation<T>(callbackfn: (value: T, index: number, data: ReadonlyArray<T>) => void): LazyEvaluator<T> {\n return (value, index, data) => {\n callbackfn(value, index, data);\n return { done: false, hasNext: true, next: value };\n };\n}\n"],"mappings":"mCA0DA,SAAgB,EAAQ,GAAG,EAAuC,CAChE,OAAO,EAAM,EAAuB,EAAM,CAAkB,CAC9D,CAEA,SAAS,EACP,EACA,EACU,CAGV,OAFA,EAAK,QAAQ,CAAU,EAEhB,CACT,CAEA,SAAS,EAAsB,EAAyF,CACtH,OAAQ,EAAO,EAAO,KACpB,EAAW,EAAO,EAAO,CAAI,EACtB,CAAE,KAAM,GAAO,QAAS,GAAM,KAAM,CAAM,EAErD"}
@@ -1,2 +1,2 @@
1
- Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});const e=require(`./curry.cjs`);function t(...t){return e.curry(Object.fromEntries,t)}exports.fromEntries=t;
1
+ Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});const e=require("./curry.cjs");function t(...t){return e.curry(Object.fromEntries,t)}exports.fromEntries=t;
2
2
  //# sourceMappingURL=from-entries.cjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"from-entries.cjs","names":["curry"],"sources":["../src/from-entries.ts"],"sourcesContent":["import type { Simplify } from 'type-fest';\nimport type { IterableContainer } from './internal/types/iterable-container';\nimport type { PerkakasTypeError } from './internal/types/perkakas-type-error';\nimport { curry } from './curry';\n\ntype FromEntriesError<Message extends string> = PerkakasTypeError<\n 'fromEntries',\n Message\n>;\n\ntype Entry<Key extends PropertyKey = PropertyKey, Value = unknown> = readonly [\n key: Key,\n value: Value,\n];\n\n// The 2 kinds of arrays we accept result in different kinds of outputs:\n// 1. If the input is a *tuple*, we know exactly what entries it would hold,\n// and thus can type the result so that the keys are required. We will then run\n// recursively on the rest of the tuple.\n// 2. If the input is an *array* then any keys defined in the array might not\n// actually show up in runtime, and thus need to be optional. (e.g. if the input\n// is an empty array).\ntype FromEntries<Entries> = Entries extends readonly [\n infer First,\n ...infer Tail,\n]\n ? FromEntriesTuple<First, Tail>\n : Entries extends readonly [...infer Head, infer Last]\n ? FromEntriesTuple<Last, Head>\n : Entries extends IterableContainer<Entry>\n ? FromEntriesArray<Entries>\n : FromEntriesError<'Entries array-like could not be inferred'>;\n\n// For strict tuples we build the result by intersecting each entry as a record\n// between it's key and value, recursively. The recursion goes through our main\n// type so that we support tuples which also contain rest parts.\ntype FromEntriesTuple<E, Rest> = E extends Entry\n ? FromEntries<Rest> & Record<E[0], E[1]>\n : FromEntriesError<'Array-like contains a non-entry element'>;\n\n// For the array case we also need to handle what kind of keys it defines:\n// 1. If it defines a *broad* key (one that has an infinite set of values, like\n// number or string) then the result is a simple record.\n// 2. If the keys are *literals* then we need to make the record partial\n// (because those props are explicit), and we need to match each key it's\n// specific possible value, as defined by the entries.\n//\n// Note that this destination between keys is the result of how typescript\n// considers Record<string, unknown> to be **implicitly** partial, whereas\n// Record<\"a\", unknown> is not.\ntype FromEntriesArray<Entries extends IterableContainer<Entry>>\n = string extends AllKeys<Entries>\n ? Record<string, Entries[number][1]>\n : number extends AllKeys<Entries>\n ? Record<number, Entries[number][1]>\n : symbol extends AllKeys<Entries>\n ? Record<symbol, Entries[number][1]>\n : FromEntriesArrayWithLiteralKeys<Entries>;\n\n// This type is largely copied from `objectFromEntries` in the repo:\n// *sindresorhus/ts-extras* but makes all properties of the output optional,\n// which is more correct because we can't assure that an entry will exist for\n// every possible prop/key of the input.\n// @see https://github.com/sindresorhus/ts-extras/blob/44f57392c5f027268330771996c4fdf9260b22d6/source/object-from-entries.ts)\ntype FromEntriesArrayWithLiteralKeys<Entries extends IterableContainer<Entry>>\n = {\n [P in AllKeys<Entries>]?: ValueForKey<Entries, P>;\n };\n\ntype AllKeys<Entries extends IterableContainer<Entry>> = Extract<\n Entries[number],\n Entry\n>[0];\n\n// I tried and failed to simplify the type here! What the ternary does here is\n// to support the cases where the entries are defined by a single type that\n// defines all entries, but it defines the keys as a union of literals\n// (`['a' | 'b', number]`); which is different from the output of toPairs\n// which would define a separate tuple literal for each key (`['a', number] |\n// ['b', number]`). We need to support both cases!\ntype ValueForKey<\n Entries extends IterableContainer<Entry>,\n K extends PropertyKey,\n> = (Extract<Entries[number], Entry<K>> extends never\n ? Entries[number]\n : Extract<Entries[number], Entry<K>>)[1];\n\n/**\n * Creates a new object from an array of tuples by pairing up first and second elements as {[key]: value}.\n * If a tuple is not supplied for any element in the array, the element will be ignored\n * If duplicate keys exist, the tuple with the greatest index in the input array will be preferred.\n *\n * The strict option supports more sophisticated use-cases like those that would\n * result when calling the strict `toPairs` function.\n *\n * There are several other functions that could be used to build an object from\n * an array:\n * `fromKeys` - Builds an object from an array of *keys* and a mapper for values.\n * `indexBy` - Builds an object from an array of *values* and a mapper for keys.\n * `pullObject` - Builds an object from an array of items with mappers for *both* keys and values.\n * Refer to the docs for more details.\n *\n * @param entries - An array of key-value pairs.\n * @signature\n * fromEntries(tuples)\n * @example\n * fromEntries([['a', 'b'], ['c', 'd']]); // => {a: 'b', c: 'd'}\n * @dataFirst\n * @category Object\n */\nexport function fromEntries<Entries extends IterableContainer<Entry>>(\n entries: Entries,\n): Simplify<FromEntries<Entries>>;\n\n/**\n * Creates a new object from an array of tuples by pairing up first and second elements as {[key]: value}.\n * If a tuple is not supplied for any element in the array, the element will be ignored\n * If duplicate keys exist, the tuple with the greatest index in the input array will be preferred.\n *\n * The strict option supports more sophisticated use-cases like those that would\n * result when calling the strict `toPairs` function.\n *\n * There are several other functions that could be used to build an object from\n * an array:\n * `fromKeys` - Builds an object from an array of *keys* and a mapper for values.\n * `indexBy` - Builds an object from an array of *values* and a mapper for keys.\n * `pullObject` - Builds an object from an array of items with mappers for *both* keys and values.\n * Refer to the docs for more details.\n *\n * @signature\n * fromEntries()(tuples)\n * @example\n * pipe(\n * [['a', 'b'], ['c', 'd']] as const,\n * fromEntries(),\n * ); // => {a: 'b', c: 'd'}\n * @dataLast\n * @category Object\n */\nexport function fromEntries(): <Entries extends IterableContainer<Entry>>(\n entries: Entries,\n) => Simplify<FromEntries<Entries>>;\n\nexport function fromEntries(...args: ReadonlyArray<unknown>): unknown {\n return curry(Object.fromEntries, args);\n}\n"],"mappings":"kGA+IA,SAAgB,EAAY,GAAG,EAAuC,CACpE,OAAOA,EAAAA,MAAM,OAAO,YAAa,EAAK"}
1
+ {"version":3,"file":"from-entries.cjs","names":["curry"],"sources":["../src/from-entries.ts"],"sourcesContent":["import type { IsNever, Simplify } from 'type-fest';\nimport type { IterableContainer } from './internal/types/iterable-container';\nimport type { PerkakasTypeError } from './internal/types/perkakas-type-error';\nimport { curry } from './curry';\n\ntype FromEntriesError<Message extends string> = PerkakasTypeError<\n 'fromEntries',\n Message\n>;\n\ntype Entry<Key extends PropertyKey = PropertyKey, Value = unknown> = readonly [\n key: Key,\n value: Value,\n];\n\n// The 2 kinds of arrays we accept result in different kinds of outputs:\n// 1. If the input is a *tuple*, we know exactly what entries it would hold,\n// and thus can type the result so that the keys are required. We will then run\n// recursively on the rest of the tuple.\n// 2. If the input is an *array* then any keys defined in the array might not\n// actually show up in runtime, and thus need to be optional. (e.g. if the input\n// is an empty array).\ntype FromEntries<Entries> = Entries extends readonly [\n infer First,\n ...infer Tail,\n]\n ? FromEntriesTuple<First, Tail>\n : Entries extends readonly [...infer Head, infer Last]\n ? FromEntriesTuple<Last, Head>\n : Entries extends IterableContainer<Entry>\n ? FromEntriesArray<Entries>\n : FromEntriesError<'Entries array-like could not be inferred'>;\n\n// For strict tuples we build the result by intersecting each entry as a record\n// between it's key and value, recursively. The recursion goes through our main\n// type so that we support tuples which also contain rest parts.\ntype FromEntriesTuple<E, Rest> = E extends Entry\n ? FromEntries<Rest> & Record<E[0], E[1]>\n : FromEntriesError<'Array-like contains a non-entry element'>;\n\n// For the array case we also need to handle what kind of keys it defines:\n// 1. If it defines a *broad* key (one that has an infinite set of values, like\n// number or string) then the result is a simple record.\n// 2. If the keys are *literals* then we need to make the record partial\n// (because those props are explicit), and we need to match each key it's\n// specific possible value, as defined by the entries.\n//\n// Note that this destination between keys is the result of how typescript\n// considers Record<string, unknown> to be **implicitly** partial, whereas\n// Record<\"a\", unknown> is not.\ntype FromEntriesArray<Entries extends IterableContainer<Entry>>\n = string extends AllKeys<Entries>\n ? Record<string, Entries[number][1]>\n : number extends AllKeys<Entries>\n ? Record<number, Entries[number][1]>\n : symbol extends AllKeys<Entries>\n ? Record<symbol, Entries[number][1]>\n : FromEntriesArrayWithLiteralKeys<Entries>;\n\n// This type is largely copied from `objectFromEntries` in the repo:\n// *sindresorhus/ts-extras* but makes all properties of the output optional,\n// which is more correct because we can't assure that an entry will exist for\n// every possible prop/key of the input.\n// @see https://github.com/sindresorhus/ts-extras/blob/44f57392c5f027268330771996c4fdf9260b22d6/source/object-from-entries.ts)\ntype FromEntriesArrayWithLiteralKeys<Entries extends IterableContainer<Entry>>\n = {\n [P in AllKeys<Entries>]?: ValueForKey<Entries, P>;\n };\n\ntype AllKeys<Entries extends IterableContainer<Entry>> = Extract<\n Entries[number],\n Entry\n>[0];\n\n// I tried and failed to simplify the type here! What the ternary does here is\n// to support the cases where the entries are defined by a single type that\n// defines all entries, but it defines the keys as a union of literals\n// (`['a' | 'b', number]`); which is different from the output of toPairs\n// which would define a separate tuple literal for each key (`['a', number] |\n// ['b', number]`). We need to support both cases!\ntype ValueForKey<\n Entries extends IterableContainer<Entry>,\n K extends PropertyKey,\n> = (IsNever<Extract<Entries[number], Entry<K>>> extends true\n ? Entries[number]\n : Extract<Entries[number], Entry<K>>)[1];\n\n/**\n * Creates a new object from an array of tuples by pairing up first and second elements as {[key]: value}.\n * If a tuple is not supplied for any element in the array, the element will be ignored\n * If duplicate keys exist, the tuple with the greatest index in the input array will be preferred.\n *\n * The strict option supports more sophisticated use-cases like those that would\n * result when calling the strict `toPairs` function.\n *\n * There are several other functions that could be used to build an object from\n * an array:\n * `fromKeys` - Builds an object from an array of *keys* and a mapper for values.\n * `indexBy` - Builds an object from an array of *values* and a mapper for keys.\n * `pullObject` - Builds an object from an array of items with mappers for *both* keys and values.\n * Refer to the docs for more details.\n *\n * @param entries - An array of key-value pairs.\n * @signature\n * fromEntries(tuples)\n * @example\n * fromEntries([['a', 'b'], ['c', 'd']]); // => {a: 'b', c: 'd'}\n * @dataFirst\n * @category Object\n */\nexport function fromEntries<Entries extends IterableContainer<Entry>>(\n entries: Entries,\n): Simplify<FromEntries<Entries>>;\n\n/**\n * Creates a new object from an array of tuples by pairing up first and second elements as {[key]: value}.\n * If a tuple is not supplied for any element in the array, the element will be ignored\n * If duplicate keys exist, the tuple with the greatest index in the input array will be preferred.\n *\n * The strict option supports more sophisticated use-cases like those that would\n * result when calling the strict `toPairs` function.\n *\n * There are several other functions that could be used to build an object from\n * an array:\n * `fromKeys` - Builds an object from an array of *keys* and a mapper for values.\n * `indexBy` - Builds an object from an array of *values* and a mapper for keys.\n * `pullObject` - Builds an object from an array of items with mappers for *both* keys and values.\n * Refer to the docs for more details.\n *\n * @signature\n * fromEntries()(tuples)\n * @example\n * pipe(\n * [['a', 'b'], ['c', 'd']] as const,\n * fromEntries(),\n * ); // => {a: 'b', c: 'd'}\n * @dataLast\n * @category Object\n */\nexport function fromEntries(): <Entries extends IterableContainer<Entry>>(\n entries: Entries,\n) => Simplify<FromEntries<Entries>>;\n\nexport function fromEntries(...args: ReadonlyArray<unknown>): unknown {\n return curry(Object.fromEntries, args);\n}\n"],"mappings":"kGA+IA,SAAgB,EAAY,GAAG,EAAuC,CACpE,OAAOA,EAAAA,MAAM,OAAO,YAAa,CAAI,CACvC"}
@@ -1 +1 @@
1
- {"version":3,"file":"from-entries.js","names":[],"sources":["../src/from-entries.ts"],"sourcesContent":["import type { Simplify } from 'type-fest';\nimport type { IterableContainer } from './internal/types/iterable-container';\nimport type { PerkakasTypeError } from './internal/types/perkakas-type-error';\nimport { curry } from './curry';\n\ntype FromEntriesError<Message extends string> = PerkakasTypeError<\n 'fromEntries',\n Message\n>;\n\ntype Entry<Key extends PropertyKey = PropertyKey, Value = unknown> = readonly [\n key: Key,\n value: Value,\n];\n\n// The 2 kinds of arrays we accept result in different kinds of outputs:\n// 1. If the input is a *tuple*, we know exactly what entries it would hold,\n// and thus can type the result so that the keys are required. We will then run\n// recursively on the rest of the tuple.\n// 2. If the input is an *array* then any keys defined in the array might not\n// actually show up in runtime, and thus need to be optional. (e.g. if the input\n// is an empty array).\ntype FromEntries<Entries> = Entries extends readonly [\n infer First,\n ...infer Tail,\n]\n ? FromEntriesTuple<First, Tail>\n : Entries extends readonly [...infer Head, infer Last]\n ? FromEntriesTuple<Last, Head>\n : Entries extends IterableContainer<Entry>\n ? FromEntriesArray<Entries>\n : FromEntriesError<'Entries array-like could not be inferred'>;\n\n// For strict tuples we build the result by intersecting each entry as a record\n// between it's key and value, recursively. The recursion goes through our main\n// type so that we support tuples which also contain rest parts.\ntype FromEntriesTuple<E, Rest> = E extends Entry\n ? FromEntries<Rest> & Record<E[0], E[1]>\n : FromEntriesError<'Array-like contains a non-entry element'>;\n\n// For the array case we also need to handle what kind of keys it defines:\n// 1. If it defines a *broad* key (one that has an infinite set of values, like\n// number or string) then the result is a simple record.\n// 2. If the keys are *literals* then we need to make the record partial\n// (because those props are explicit), and we need to match each key it's\n// specific possible value, as defined by the entries.\n//\n// Note that this destination between keys is the result of how typescript\n// considers Record<string, unknown> to be **implicitly** partial, whereas\n// Record<\"a\", unknown> is not.\ntype FromEntriesArray<Entries extends IterableContainer<Entry>>\n = string extends AllKeys<Entries>\n ? Record<string, Entries[number][1]>\n : number extends AllKeys<Entries>\n ? Record<number, Entries[number][1]>\n : symbol extends AllKeys<Entries>\n ? Record<symbol, Entries[number][1]>\n : FromEntriesArrayWithLiteralKeys<Entries>;\n\n// This type is largely copied from `objectFromEntries` in the repo:\n// *sindresorhus/ts-extras* but makes all properties of the output optional,\n// which is more correct because we can't assure that an entry will exist for\n// every possible prop/key of the input.\n// @see https://github.com/sindresorhus/ts-extras/blob/44f57392c5f027268330771996c4fdf9260b22d6/source/object-from-entries.ts)\ntype FromEntriesArrayWithLiteralKeys<Entries extends IterableContainer<Entry>>\n = {\n [P in AllKeys<Entries>]?: ValueForKey<Entries, P>;\n };\n\ntype AllKeys<Entries extends IterableContainer<Entry>> = Extract<\n Entries[number],\n Entry\n>[0];\n\n// I tried and failed to simplify the type here! What the ternary does here is\n// to support the cases where the entries are defined by a single type that\n// defines all entries, but it defines the keys as a union of literals\n// (`['a' | 'b', number]`); which is different from the output of toPairs\n// which would define a separate tuple literal for each key (`['a', number] |\n// ['b', number]`). We need to support both cases!\ntype ValueForKey<\n Entries extends IterableContainer<Entry>,\n K extends PropertyKey,\n> = (Extract<Entries[number], Entry<K>> extends never\n ? Entries[number]\n : Extract<Entries[number], Entry<K>>)[1];\n\n/**\n * Creates a new object from an array of tuples by pairing up first and second elements as {[key]: value}.\n * If a tuple is not supplied for any element in the array, the element will be ignored\n * If duplicate keys exist, the tuple with the greatest index in the input array will be preferred.\n *\n * The strict option supports more sophisticated use-cases like those that would\n * result when calling the strict `toPairs` function.\n *\n * There are several other functions that could be used to build an object from\n * an array:\n * `fromKeys` - Builds an object from an array of *keys* and a mapper for values.\n * `indexBy` - Builds an object from an array of *values* and a mapper for keys.\n * `pullObject` - Builds an object from an array of items with mappers for *both* keys and values.\n * Refer to the docs for more details.\n *\n * @param entries - An array of key-value pairs.\n * @signature\n * fromEntries(tuples)\n * @example\n * fromEntries([['a', 'b'], ['c', 'd']]); // => {a: 'b', c: 'd'}\n * @dataFirst\n * @category Object\n */\nexport function fromEntries<Entries extends IterableContainer<Entry>>(\n entries: Entries,\n): Simplify<FromEntries<Entries>>;\n\n/**\n * Creates a new object from an array of tuples by pairing up first and second elements as {[key]: value}.\n * If a tuple is not supplied for any element in the array, the element will be ignored\n * If duplicate keys exist, the tuple with the greatest index in the input array will be preferred.\n *\n * The strict option supports more sophisticated use-cases like those that would\n * result when calling the strict `toPairs` function.\n *\n * There are several other functions that could be used to build an object from\n * an array:\n * `fromKeys` - Builds an object from an array of *keys* and a mapper for values.\n * `indexBy` - Builds an object from an array of *values* and a mapper for keys.\n * `pullObject` - Builds an object from an array of items with mappers for *both* keys and values.\n * Refer to the docs for more details.\n *\n * @signature\n * fromEntries()(tuples)\n * @example\n * pipe(\n * [['a', 'b'], ['c', 'd']] as const,\n * fromEntries(),\n * ); // => {a: 'b', c: 'd'}\n * @dataLast\n * @category Object\n */\nexport function fromEntries(): <Entries extends IterableContainer<Entry>>(\n entries: Entries,\n) => Simplify<FromEntries<Entries>>;\n\nexport function fromEntries(...args: ReadonlyArray<unknown>): unknown {\n return curry(Object.fromEntries, args);\n}\n"],"mappings":"mCA+IA,SAAgB,EAAY,GAAG,EAAuC,CACpE,OAAO,EAAM,OAAO,YAAa,EAAK"}
1
+ {"version":3,"file":"from-entries.js","names":[],"sources":["../src/from-entries.ts"],"sourcesContent":["import type { IsNever, Simplify } from 'type-fest';\nimport type { IterableContainer } from './internal/types/iterable-container';\nimport type { PerkakasTypeError } from './internal/types/perkakas-type-error';\nimport { curry } from './curry';\n\ntype FromEntriesError<Message extends string> = PerkakasTypeError<\n 'fromEntries',\n Message\n>;\n\ntype Entry<Key extends PropertyKey = PropertyKey, Value = unknown> = readonly [\n key: Key,\n value: Value,\n];\n\n// The 2 kinds of arrays we accept result in different kinds of outputs:\n// 1. If the input is a *tuple*, we know exactly what entries it would hold,\n// and thus can type the result so that the keys are required. We will then run\n// recursively on the rest of the tuple.\n// 2. If the input is an *array* then any keys defined in the array might not\n// actually show up in runtime, and thus need to be optional. (e.g. if the input\n// is an empty array).\ntype FromEntries<Entries> = Entries extends readonly [\n infer First,\n ...infer Tail,\n]\n ? FromEntriesTuple<First, Tail>\n : Entries extends readonly [...infer Head, infer Last]\n ? FromEntriesTuple<Last, Head>\n : Entries extends IterableContainer<Entry>\n ? FromEntriesArray<Entries>\n : FromEntriesError<'Entries array-like could not be inferred'>;\n\n// For strict tuples we build the result by intersecting each entry as a record\n// between it's key and value, recursively. The recursion goes through our main\n// type so that we support tuples which also contain rest parts.\ntype FromEntriesTuple<E, Rest> = E extends Entry\n ? FromEntries<Rest> & Record<E[0], E[1]>\n : FromEntriesError<'Array-like contains a non-entry element'>;\n\n// For the array case we also need to handle what kind of keys it defines:\n// 1. If it defines a *broad* key (one that has an infinite set of values, like\n// number or string) then the result is a simple record.\n// 2. If the keys are *literals* then we need to make the record partial\n// (because those props are explicit), and we need to match each key it's\n// specific possible value, as defined by the entries.\n//\n// Note that this destination between keys is the result of how typescript\n// considers Record<string, unknown> to be **implicitly** partial, whereas\n// Record<\"a\", unknown> is not.\ntype FromEntriesArray<Entries extends IterableContainer<Entry>>\n = string extends AllKeys<Entries>\n ? Record<string, Entries[number][1]>\n : number extends AllKeys<Entries>\n ? Record<number, Entries[number][1]>\n : symbol extends AllKeys<Entries>\n ? Record<symbol, Entries[number][1]>\n : FromEntriesArrayWithLiteralKeys<Entries>;\n\n// This type is largely copied from `objectFromEntries` in the repo:\n// *sindresorhus/ts-extras* but makes all properties of the output optional,\n// which is more correct because we can't assure that an entry will exist for\n// every possible prop/key of the input.\n// @see https://github.com/sindresorhus/ts-extras/blob/44f57392c5f027268330771996c4fdf9260b22d6/source/object-from-entries.ts)\ntype FromEntriesArrayWithLiteralKeys<Entries extends IterableContainer<Entry>>\n = {\n [P in AllKeys<Entries>]?: ValueForKey<Entries, P>;\n };\n\ntype AllKeys<Entries extends IterableContainer<Entry>> = Extract<\n Entries[number],\n Entry\n>[0];\n\n// I tried and failed to simplify the type here! What the ternary does here is\n// to support the cases where the entries are defined by a single type that\n// defines all entries, but it defines the keys as a union of literals\n// (`['a' | 'b', number]`); which is different from the output of toPairs\n// which would define a separate tuple literal for each key (`['a', number] |\n// ['b', number]`). We need to support both cases!\ntype ValueForKey<\n Entries extends IterableContainer<Entry>,\n K extends PropertyKey,\n> = (IsNever<Extract<Entries[number], Entry<K>>> extends true\n ? Entries[number]\n : Extract<Entries[number], Entry<K>>)[1];\n\n/**\n * Creates a new object from an array of tuples by pairing up first and second elements as {[key]: value}.\n * If a tuple is not supplied for any element in the array, the element will be ignored\n * If duplicate keys exist, the tuple with the greatest index in the input array will be preferred.\n *\n * The strict option supports more sophisticated use-cases like those that would\n * result when calling the strict `toPairs` function.\n *\n * There are several other functions that could be used to build an object from\n * an array:\n * `fromKeys` - Builds an object from an array of *keys* and a mapper for values.\n * `indexBy` - Builds an object from an array of *values* and a mapper for keys.\n * `pullObject` - Builds an object from an array of items with mappers for *both* keys and values.\n * Refer to the docs for more details.\n *\n * @param entries - An array of key-value pairs.\n * @signature\n * fromEntries(tuples)\n * @example\n * fromEntries([['a', 'b'], ['c', 'd']]); // => {a: 'b', c: 'd'}\n * @dataFirst\n * @category Object\n */\nexport function fromEntries<Entries extends IterableContainer<Entry>>(\n entries: Entries,\n): Simplify<FromEntries<Entries>>;\n\n/**\n * Creates a new object from an array of tuples by pairing up first and second elements as {[key]: value}.\n * If a tuple is not supplied for any element in the array, the element will be ignored\n * If duplicate keys exist, the tuple with the greatest index in the input array will be preferred.\n *\n * The strict option supports more sophisticated use-cases like those that would\n * result when calling the strict `toPairs` function.\n *\n * There are several other functions that could be used to build an object from\n * an array:\n * `fromKeys` - Builds an object from an array of *keys* and a mapper for values.\n * `indexBy` - Builds an object from an array of *values* and a mapper for keys.\n * `pullObject` - Builds an object from an array of items with mappers for *both* keys and values.\n * Refer to the docs for more details.\n *\n * @signature\n * fromEntries()(tuples)\n * @example\n * pipe(\n * [['a', 'b'], ['c', 'd']] as const,\n * fromEntries(),\n * ); // => {a: 'b', c: 'd'}\n * @dataLast\n * @category Object\n */\nexport function fromEntries(): <Entries extends IterableContainer<Entry>>(\n entries: Entries,\n) => Simplify<FromEntries<Entries>>;\n\nexport function fromEntries(...args: ReadonlyArray<unknown>): unknown {\n return curry(Object.fromEntries, args);\n}\n"],"mappings":"mCA+IA,SAAgB,EAAY,GAAG,EAAuC,CACpE,OAAO,EAAM,OAAO,YAAa,CAAI,CACvC"}
@@ -1,2 +1,2 @@
1
- Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});const e=require(`./curry.cjs`);function t(...t){return e.curry(n,t)}function n(e,t){let n={};for(let[r,i]of e.entries())n[i]=t(i,r,e);return n}exports.fromKeys=t;
1
+ Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});const e=require("./curry.cjs");function t(...t){return e.curry(n,t)}function n(e,t){let n={};for(let[r,i]of e.entries())n[i]=t(i,r,e);return n}exports.fromKeys=t;
2
2
  //# sourceMappingURL=from-keys.cjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"from-keys.cjs","names":["curry"],"sources":["../src/from-keys.ts"],"sourcesContent":["import type { Simplify } from 'type-fest';\nimport type { BoundedPartial } from './internal/types/bounded-partial';\nimport type { IterableContainer } from './internal/types/iterable-container';\nimport { curry } from './curry';\n\n// Takes a union of literals and creates a union of records with the value V for\n// each key **separately**\n// @example ExactlyOneKey<\"cat\" | \"dog\", boolean> // { cat: boolean } | { dog: boolean }\ntype ExactlyOneKey<T, V> = T extends PropertyKey ? Record<T, V> : never;\n\ntype FromKeys<T extends IterableContainer, V> = T extends readonly []\n ? // eslint-disable-next-line ts/no-empty-object-type -- We want to return an empty object type here, but it's not trivial to build that in Typescript, other fixer suggestions like Record<PropertyKey, never> or Record<PropertyKey, unknown> both break our type tests so they don't do what we need here. Because the result is mutable this might be the correct type after all...\n {}\n : T extends readonly [infer Head, ...infer Rest]\n ? ExactlyOneKey<Head, V> & FromKeys<Rest, V>\n : T[number] extends PropertyKey\n ? BoundedPartial<Record<T[number], V>>\n : never;\n\n/**\n * Creates an object that maps each key in `data` to the result of `mapper` for\n * that key. Duplicate keys are overwritten, guaranteeing that `mapper` is run\n * for each item in `data`.\n *\n * There are several other functions that could be used to build an object from\n * an array:\n * `indexBy` - Builds an object from an array of *values* and a mapper for keys.\n * `pullObject` - Builds an object from an array of items with mappers for *both* keys and values.\n * `fromEntries` - Builds an object from an array of key-value pairs.\n * Refer to the docs for more details.\n *\n * @param data - An array of keys of the output object. All items in the array\n * would be keys in the output array.\n * @param mapper - Takes a key and returns the value that would be associated\n * with that key.\n * @signature\n * fromKeys(data, mapper);\n * @example\n * fromKeys([\"cat\", \"dog\"], length()); // { cat: 3, dog: 3 } (typed as Partial<Record<\"cat\" | \"dog\", number>>)\n * fromKeys([1, 2], add(1)); // { 1: 2, 2: 3 } (typed as Partial<Record<1 | 2, number>>)\n * @dataFirst\n * @category Object\n */\nexport function fromKeys<T extends IterableContainer<PropertyKey>, V>(\n data: T,\n mapper: (item: T[number], index: number, data: T) => V,\n): Simplify<FromKeys<T, V>>;\n\n/**\n * Creates an object that maps each key in `data` to the result of `mapper` for\n * that key. Duplicate keys are overwritten, guaranteeing that `mapper` is run\n * for each item in `data`.\n *\n * There are several other functions that could be used to build an object from\n * an array:\n * `indexBy` - Builds an object from an array of *values* and a mapper for keys.\n * `pullObject` - Builds an object from an array of items with mappers for *both* keys and values.\n * `fromEntries` - Builds an object from an array of key-value pairs.\n * Refer to the docs for more details.\n *\n * @param mapper - Takes a key and returns the value that would be associated\n * with that key.\n * @signature\n * fromKeys(mapper)(data);\n * @example\n * pipe([\"cat\", \"dog\"], fromKeys(length())); // { cat: 3, dog: 3 } (typed as Partial<Record<\"cat\" | \"dog\", number>>)\n * pipe([1, 2], fromKeys(add(1))); // { 1: 2, 2: 3 } (typed as Partial<Record<1 | 2, number>>)\n * @dataLast\n * @category Object\n */\nexport function fromKeys<T extends IterableContainer<PropertyKey>, V>(\n mapper: (item: T[number], index: number, data: T) => V,\n): (data: T) => Simplify<FromKeys<T, V>>;\n\nexport function fromKeys(...args: ReadonlyArray<unknown>): unknown {\n return curry(fromKeysImplementation, args);\n}\n\nfunction fromKeysImplementation<T extends IterableContainer<PropertyKey>, V>(\n data: T,\n mapper: (item: T[number], index: number, data: T) => V,\n): FromKeys<T, V> {\n const result: Partial<FromKeys<T, V>> = {};\n\n for (const [index, key] of data.entries()) {\n // @ts-expect-error [ts7053] - There's no easy way to make Typescript aware that the items in T would be keys in the output object because it's type is built recursively and the \"being an item of an array\" property of a type is not \"carried over\" in the recursive type definition.\n result[key] = mapper(key, index, data);\n }\n\n return result as FromKeys<T, V>;\n}\n"],"mappings":"kGA0EA,SAAgB,EAAS,GAAG,EAAuC,CACjE,OAAOA,EAAAA,MAAM,EAAwB,EAAK,CAG5C,SAAS,EACP,EACA,EACgB,CAChB,IAAM,EAAkC,EAAE,CAE1C,IAAK,GAAM,CAAC,EAAO,KAAQ,EAAK,SAAS,CAEvC,EAAO,GAAO,EAAO,EAAK,EAAO,EAAK,CAGxC,OAAO"}
1
+ {"version":3,"file":"from-keys.cjs","names":["curry"],"sources":["../src/from-keys.ts"],"sourcesContent":["import type { Simplify } from 'type-fest';\nimport type { BoundedPartial } from './internal/types/bounded-partial';\nimport type { IterableContainer } from './internal/types/iterable-container';\nimport { curry } from './curry';\n\n// Takes a union of literals and creates a union of records with the value V for\n// each key **separately**\n// @example ExactlyOneKey<\"cat\" | \"dog\", boolean> // { cat: boolean } | { dog: boolean }\ntype ExactlyOneKey<T, V> = T extends PropertyKey ? Record<T, V> : never;\n\ntype FromKeys<T extends IterableContainer, V> = T extends readonly []\n ? // eslint-disable-next-line ts/no-empty-object-type -- We want to return an empty object type here, but it's not trivial to build that in Typescript, other fixer suggestions like Record<PropertyKey, never> or Record<PropertyKey, unknown> both break our type tests so they don't do what we need here. Because the result is mutable this might be the correct type after all...\n {}\n : T extends readonly [infer Head, ...infer Rest]\n ? ExactlyOneKey<Head, V> & FromKeys<Rest, V>\n : T[number] extends PropertyKey\n ? BoundedPartial<Record<T[number], V>>\n : never;\n\n/**\n * Creates an object that maps each key in `data` to the result of `mapper` for\n * that key. Duplicate keys are overwritten, guaranteeing that `mapper` is run\n * for each item in `data`.\n *\n * There are several other functions that could be used to build an object from\n * an array:\n * `indexBy` - Builds an object from an array of *values* and a mapper for keys.\n * `pullObject` - Builds an object from an array of items with mappers for *both* keys and values.\n * `fromEntries` - Builds an object from an array of key-value pairs.\n * Refer to the docs for more details.\n *\n * @param data - An array of keys of the output object. All items in the array\n * would be keys in the output array.\n * @param mapper - Takes a key and returns the value that would be associated\n * with that key.\n * @signature\n * fromKeys(data, mapper);\n * @example\n * fromKeys([\"cat\", \"dog\"], length()); // { cat: 3, dog: 3 } (typed as Partial<Record<\"cat\" | \"dog\", number>>)\n * fromKeys([1, 2], add(1)); // { 1: 2, 2: 3 } (typed as Partial<Record<1 | 2, number>>)\n * @dataFirst\n * @category Object\n */\nexport function fromKeys<T extends IterableContainer<PropertyKey>, V>(\n data: T,\n mapper: (item: T[number], index: number, data: T) => V,\n): Simplify<FromKeys<T, V>>;\n\n/**\n * Creates an object that maps each key in `data` to the result of `mapper` for\n * that key. Duplicate keys are overwritten, guaranteeing that `mapper` is run\n * for each item in `data`.\n *\n * There are several other functions that could be used to build an object from\n * an array:\n * `indexBy` - Builds an object from an array of *values* and a mapper for keys.\n * `pullObject` - Builds an object from an array of items with mappers for *both* keys and values.\n * `fromEntries` - Builds an object from an array of key-value pairs.\n * Refer to the docs for more details.\n *\n * @param mapper - Takes a key and returns the value that would be associated\n * with that key.\n * @signature\n * fromKeys(mapper)(data);\n * @example\n * pipe([\"cat\", \"dog\"], fromKeys(length())); // { cat: 3, dog: 3 } (typed as Partial<Record<\"cat\" | \"dog\", number>>)\n * pipe([1, 2], fromKeys(add(1))); // { 1: 2, 2: 3 } (typed as Partial<Record<1 | 2, number>>)\n * @dataLast\n * @category Object\n */\nexport function fromKeys<T extends IterableContainer<PropertyKey>, V>(\n mapper: (item: T[number], index: number, data: T) => V,\n): (data: T) => Simplify<FromKeys<T, V>>;\n\nexport function fromKeys(...args: ReadonlyArray<unknown>): unknown {\n return curry(fromKeysImplementation, args);\n}\n\nfunction fromKeysImplementation<T extends IterableContainer<PropertyKey>, V>(\n data: T,\n mapper: (item: T[number], index: number, data: T) => V,\n): FromKeys<T, V> {\n const result: Partial<FromKeys<T, V>> = {};\n\n for (const [index, key] of data.entries()) {\n // @ts-expect-error [ts7053] - There's no easy way to make Typescript aware that the items in T would be keys in the output object because it's type is built recursively and the \"being an item of an array\" property of a type is not \"carried over\" in the recursive type definition.\n result[key] = mapper(key, index, data);\n }\n\n return result as FromKeys<T, V>;\n}\n"],"mappings":"kGA0EA,SAAgB,EAAS,GAAG,EAAuC,CACjE,OAAOA,EAAAA,MAAM,EAAwB,CAAI,CAC3C,CAEA,SAAS,EACP,EACA,EACgB,CAChB,IAAM,EAAkC,CAAC,EAEzC,IAAK,GAAM,CAAC,EAAO,KAAQ,EAAK,QAAQ,EAEtC,EAAO,GAAO,EAAO,EAAK,EAAO,CAAI,EAGvC,OAAO,CACT"}
@@ -1 +1 @@
1
- {"version":3,"file":"from-keys.js","names":[],"sources":["../src/from-keys.ts"],"sourcesContent":["import type { Simplify } from 'type-fest';\nimport type { BoundedPartial } from './internal/types/bounded-partial';\nimport type { IterableContainer } from './internal/types/iterable-container';\nimport { curry } from './curry';\n\n// Takes a union of literals and creates a union of records with the value V for\n// each key **separately**\n// @example ExactlyOneKey<\"cat\" | \"dog\", boolean> // { cat: boolean } | { dog: boolean }\ntype ExactlyOneKey<T, V> = T extends PropertyKey ? Record<T, V> : never;\n\ntype FromKeys<T extends IterableContainer, V> = T extends readonly []\n ? // eslint-disable-next-line ts/no-empty-object-type -- We want to return an empty object type here, but it's not trivial to build that in Typescript, other fixer suggestions like Record<PropertyKey, never> or Record<PropertyKey, unknown> both break our type tests so they don't do what we need here. Because the result is mutable this might be the correct type after all...\n {}\n : T extends readonly [infer Head, ...infer Rest]\n ? ExactlyOneKey<Head, V> & FromKeys<Rest, V>\n : T[number] extends PropertyKey\n ? BoundedPartial<Record<T[number], V>>\n : never;\n\n/**\n * Creates an object that maps each key in `data` to the result of `mapper` for\n * that key. Duplicate keys are overwritten, guaranteeing that `mapper` is run\n * for each item in `data`.\n *\n * There are several other functions that could be used to build an object from\n * an array:\n * `indexBy` - Builds an object from an array of *values* and a mapper for keys.\n * `pullObject` - Builds an object from an array of items with mappers for *both* keys and values.\n * `fromEntries` - Builds an object from an array of key-value pairs.\n * Refer to the docs for more details.\n *\n * @param data - An array of keys of the output object. All items in the array\n * would be keys in the output array.\n * @param mapper - Takes a key and returns the value that would be associated\n * with that key.\n * @signature\n * fromKeys(data, mapper);\n * @example\n * fromKeys([\"cat\", \"dog\"], length()); // { cat: 3, dog: 3 } (typed as Partial<Record<\"cat\" | \"dog\", number>>)\n * fromKeys([1, 2], add(1)); // { 1: 2, 2: 3 } (typed as Partial<Record<1 | 2, number>>)\n * @dataFirst\n * @category Object\n */\nexport function fromKeys<T extends IterableContainer<PropertyKey>, V>(\n data: T,\n mapper: (item: T[number], index: number, data: T) => V,\n): Simplify<FromKeys<T, V>>;\n\n/**\n * Creates an object that maps each key in `data` to the result of `mapper` for\n * that key. Duplicate keys are overwritten, guaranteeing that `mapper` is run\n * for each item in `data`.\n *\n * There are several other functions that could be used to build an object from\n * an array:\n * `indexBy` - Builds an object from an array of *values* and a mapper for keys.\n * `pullObject` - Builds an object from an array of items with mappers for *both* keys and values.\n * `fromEntries` - Builds an object from an array of key-value pairs.\n * Refer to the docs for more details.\n *\n * @param mapper - Takes a key and returns the value that would be associated\n * with that key.\n * @signature\n * fromKeys(mapper)(data);\n * @example\n * pipe([\"cat\", \"dog\"], fromKeys(length())); // { cat: 3, dog: 3 } (typed as Partial<Record<\"cat\" | \"dog\", number>>)\n * pipe([1, 2], fromKeys(add(1))); // { 1: 2, 2: 3 } (typed as Partial<Record<1 | 2, number>>)\n * @dataLast\n * @category Object\n */\nexport function fromKeys<T extends IterableContainer<PropertyKey>, V>(\n mapper: (item: T[number], index: number, data: T) => V,\n): (data: T) => Simplify<FromKeys<T, V>>;\n\nexport function fromKeys(...args: ReadonlyArray<unknown>): unknown {\n return curry(fromKeysImplementation, args);\n}\n\nfunction fromKeysImplementation<T extends IterableContainer<PropertyKey>, V>(\n data: T,\n mapper: (item: T[number], index: number, data: T) => V,\n): FromKeys<T, V> {\n const result: Partial<FromKeys<T, V>> = {};\n\n for (const [index, key] of data.entries()) {\n // @ts-expect-error [ts7053] - There's no easy way to make Typescript aware that the items in T would be keys in the output object because it's type is built recursively and the \"being an item of an array\" property of a type is not \"carried over\" in the recursive type definition.\n result[key] = mapper(key, index, data);\n }\n\n return result as FromKeys<T, V>;\n}\n"],"mappings":"mCA0EA,SAAgB,EAAS,GAAG,EAAuC,CACjE,OAAO,EAAM,EAAwB,EAAK,CAG5C,SAAS,EACP,EACA,EACgB,CAChB,IAAM,EAAkC,EAAE,CAE1C,IAAK,GAAM,CAAC,EAAO,KAAQ,EAAK,SAAS,CAEvC,EAAO,GAAO,EAAO,EAAK,EAAO,EAAK,CAGxC,OAAO"}
1
+ {"version":3,"file":"from-keys.js","names":[],"sources":["../src/from-keys.ts"],"sourcesContent":["import type { Simplify } from 'type-fest';\nimport type { BoundedPartial } from './internal/types/bounded-partial';\nimport type { IterableContainer } from './internal/types/iterable-container';\nimport { curry } from './curry';\n\n// Takes a union of literals and creates a union of records with the value V for\n// each key **separately**\n// @example ExactlyOneKey<\"cat\" | \"dog\", boolean> // { cat: boolean } | { dog: boolean }\ntype ExactlyOneKey<T, V> = T extends PropertyKey ? Record<T, V> : never;\n\ntype FromKeys<T extends IterableContainer, V> = T extends readonly []\n ? // eslint-disable-next-line ts/no-empty-object-type -- We want to return an empty object type here, but it's not trivial to build that in Typescript, other fixer suggestions like Record<PropertyKey, never> or Record<PropertyKey, unknown> both break our type tests so they don't do what we need here. Because the result is mutable this might be the correct type after all...\n {}\n : T extends readonly [infer Head, ...infer Rest]\n ? ExactlyOneKey<Head, V> & FromKeys<Rest, V>\n : T[number] extends PropertyKey\n ? BoundedPartial<Record<T[number], V>>\n : never;\n\n/**\n * Creates an object that maps each key in `data` to the result of `mapper` for\n * that key. Duplicate keys are overwritten, guaranteeing that `mapper` is run\n * for each item in `data`.\n *\n * There are several other functions that could be used to build an object from\n * an array:\n * `indexBy` - Builds an object from an array of *values* and a mapper for keys.\n * `pullObject` - Builds an object from an array of items with mappers for *both* keys and values.\n * `fromEntries` - Builds an object from an array of key-value pairs.\n * Refer to the docs for more details.\n *\n * @param data - An array of keys of the output object. All items in the array\n * would be keys in the output array.\n * @param mapper - Takes a key and returns the value that would be associated\n * with that key.\n * @signature\n * fromKeys(data, mapper);\n * @example\n * fromKeys([\"cat\", \"dog\"], length()); // { cat: 3, dog: 3 } (typed as Partial<Record<\"cat\" | \"dog\", number>>)\n * fromKeys([1, 2], add(1)); // { 1: 2, 2: 3 } (typed as Partial<Record<1 | 2, number>>)\n * @dataFirst\n * @category Object\n */\nexport function fromKeys<T extends IterableContainer<PropertyKey>, V>(\n data: T,\n mapper: (item: T[number], index: number, data: T) => V,\n): Simplify<FromKeys<T, V>>;\n\n/**\n * Creates an object that maps each key in `data` to the result of `mapper` for\n * that key. Duplicate keys are overwritten, guaranteeing that `mapper` is run\n * for each item in `data`.\n *\n * There are several other functions that could be used to build an object from\n * an array:\n * `indexBy` - Builds an object from an array of *values* and a mapper for keys.\n * `pullObject` - Builds an object from an array of items with mappers for *both* keys and values.\n * `fromEntries` - Builds an object from an array of key-value pairs.\n * Refer to the docs for more details.\n *\n * @param mapper - Takes a key and returns the value that would be associated\n * with that key.\n * @signature\n * fromKeys(mapper)(data);\n * @example\n * pipe([\"cat\", \"dog\"], fromKeys(length())); // { cat: 3, dog: 3 } (typed as Partial<Record<\"cat\" | \"dog\", number>>)\n * pipe([1, 2], fromKeys(add(1))); // { 1: 2, 2: 3 } (typed as Partial<Record<1 | 2, number>>)\n * @dataLast\n * @category Object\n */\nexport function fromKeys<T extends IterableContainer<PropertyKey>, V>(\n mapper: (item: T[number], index: number, data: T) => V,\n): (data: T) => Simplify<FromKeys<T, V>>;\n\nexport function fromKeys(...args: ReadonlyArray<unknown>): unknown {\n return curry(fromKeysImplementation, args);\n}\n\nfunction fromKeysImplementation<T extends IterableContainer<PropertyKey>, V>(\n data: T,\n mapper: (item: T[number], index: number, data: T) => V,\n): FromKeys<T, V> {\n const result: Partial<FromKeys<T, V>> = {};\n\n for (const [index, key] of data.entries()) {\n // @ts-expect-error [ts7053] - There's no easy way to make Typescript aware that the items in T would be keys in the output object because it's type is built recursively and the \"being an item of an array\" property of a type is not \"carried over\" in the recursive type definition.\n result[key] = mapper(key, index, data);\n }\n\n return result as FromKeys<T, V>;\n}\n"],"mappings":"mCA0EA,SAAgB,EAAS,GAAG,EAAuC,CACjE,OAAO,EAAM,EAAwB,CAAI,CAC3C,CAEA,SAAS,EACP,EACA,EACgB,CAChB,IAAM,EAAkC,CAAC,EAEzC,IAAK,GAAM,CAAC,EAAO,KAAQ,EAAK,QAAQ,EAEtC,EAAO,GAAO,EAAO,EAAK,EAAO,CAAI,EAGvC,OAAO,CACT"}
@@ -1 +1 @@
1
- {"version":3,"file":"funnel.cjs","names":[],"sources":["../src/funnel.ts"],"sourcesContent":["import type { RequireAtLeastOne } from 'type-fest';\n\n// We use the value provided by the reducer to also determine if a call\n// was done during a timeout period. This means that even when no reducer\n// is provided, we still need a dummy reducer that would return something\n// other than `undefined`. It is safe to cast this to R (which might be\n// anything) because the callback would never use it as it would be typed\n// as a zero-args function.\nconst VOID_REDUCER_SYMBOL = Symbol('funnel/voidReducer');\nconst voidReducer = <R>(): R => VOID_REDUCER_SYMBOL as R;\n\ntype FunnelOptions<Args extends RestArguments, R> = {\n readonly reducer?: (accumulator: R | undefined, ...params: Args) => R;\n} & FunnelTimingOptions;\n\n// Not all combinations of timing options are valid, there are dependencies\n// between them to ensure users can't configure the funnel in a way which would\n// cause it to never trigger.\ntype FunnelTimingOptions\n = | ({ readonly triggerAt?: 'end' } & (\n | ({ readonly minGapMs: number } & RequireAtLeastOne<{\n readonly minQuietPeriodMs: number;\n readonly maxBurstDurationMs: number;\n }>)\n | {\n readonly minQuietPeriodMs?: number;\n readonly maxBurstDurationMs?: number;\n readonly minGapMs?: never;\n }\n ))\n | {\n readonly triggerAt: 'start' | 'both';\n readonly minQuietPeriodMs?: number;\n readonly maxBurstDurationMs?: number;\n readonly minGapMs?: number;\n };\n\n// eslint-disable-next-line ts/no-explicit-any -- TypeScript has some quirks with generic function types, and works best with `any` and not `unknown`. This follows the typing of built-in utilities like `ReturnType` and `Parameters`.\ntype RestArguments = Array<any>;\n\ninterface Funnel<Args extends RestArguments = []> {\n /**\n * Call the function. This might result in the `execute` function being called\n * now or later, depending on it's configuration and it's current state.\n *\n * @param args - The args are defined by the `reducer` function.\n */\n\n readonly call: (...args: Args) => void;\n\n /**\n * Resets the funnel to it's initial state. Any calls made since the last\n * invocation will be discarded.\n */\n readonly cancel: () => void;\n\n /**\n * Triggers an invocation regardless of the current state of the funnel.\n * Like any other invocation, The funnel will also be reset to it's initial\n * state afterwards.\n */\n readonly flush: () => void;\n\n /**\n * The funnel is in it's initial state (there are no active timeouts).\n */\n readonly isIdle: boolean;\n}\n\n/**\n * Creates a funnel that controls the timing and execution of `callback`. Its\n * main purpose is to manage multiple consecutive (usually fast-paced) calls,\n * reshaping them according to a defined batching strategy and timing policy.\n * This is useful when handling uncontrolled call rates, such as DOM events or\n * network traffic. It can implement strategies like debouncing, throttling,\n * batching, and more.\n *\n * An optional `reducer` function can be provided to allow passing data to the\n * callback via calls to `call` (otherwise the signature of `call` takes no\n * arguments).\n *\n * Typing is inferred from `callback`s param, and from the rest params that\n * the optional `reducer` function accepts. Use **explicit** types for these\n * to ensure that everything _else_ is well-typed.\n *\n * Notice that this function constructs a funnel **object**, and does **not**\n * execute anything when called. The returned object should be used to execute\n * the funnel via the its `call` method.\n *\n * - Debouncing: use `minQuietPeriodMs` and any `triggerAt`.\n * - Throttling: use `minGapMs` and `triggerAt: \"start\"` or `\"both\"`.\n * - Batching: See the reference implementation in [`funnel.reference-batch.test.ts`](https://github.com/vinicunca/perkakas/blob/main/src/funnel.reference-batch.test.ts).\n *\n * @param callback - The main function that would be invoked periodically based\n * on `options`. The function would take the latest result of the `reducer`; if\n * no calls where made since the last time it was invoked it will not be\n * invoked. (If a return value is needed, it should be passed via a reference or\n * via closure to the outer scope of the funnel).\n * @param options - An object that defines when `execute` should be invoked,\n * relative to the calls of `call`. An empty/missing options object is\n * equivalent to setting `minQuietPeriodMs` to `0`.\n * @param options.reducer - Combines the arguments passed to `call` with the\n * value computed on the previous call (or `undefined` on the first time). The\n * goal of the function is to extract and summarize the data needed for\n * `callback`. It should be fast and simple as it is called often and should\n * defer heavy operations to the `execute` function. If the final value\n * is `undefined`, `callback` will not be called.\n * @param options.triggerAt - At what \"edges\" of the funnel's burst window\n * would `execute` invoke:\n * - `start` - the function will be invoked immediately (within the **same**\n * execution frame!), and any subsequent calls would be ignored until the funnel\n * is idle again. During this period `reducer` will also not be called.\n * - `end` - the function will **not** be invoked initially but the timer will\n * be started. Any calls during this time would be passed to the reducer, and\n * when the timers are done, the reduced result would trigger an invocation.\n * - `both` - the function will be invoked immediately, and then the funnel\n * would behave as if it was in the 'end' state. Default: 'end'.\n * @param options.minQuietPeriodMs - The burst timer prevents subsequent calls\n * in short succession to cause excessive invocations (aka \"debounce\"). This\n * duration represents the **minimum** amount of time that needs to pass\n * between calls (the \"quiet\" part) in order for the subsequent call to **not**\n * be considered part of the burst. In other words, as long as calls are faster\n * than this, they are considered part of the burst and the burst is extended.\n * @param options.maxBurstDurationMs - Bursts are extended every time a call is\n * made within the burst period. This means that the burst period could be\n * extended indefinitely. To prevent such cases, a maximum burst duration could\n * be defined. When `minQuietPeriodMs` is not defined and this option is, they\n * will both share the same value.\n * @param options.minGapMs - A minimum duration between calls of `execute`.\n * This is maintained regardless of the shape of the burst and is ensured even\n * if the `maxBurstDurationMs` is reached before it. (aka \"throttle\").\n * @returns A funnel with a `call` function that is used to trigger invocations.\n * In addition to it the funnel also comes with the following functions and\n * properties:\n * - `cancel` - Resets the funnel to it's initial state, discarding the current\n * `reducer` result without calling `execute` on it.\n * - `flush` - Triggers an invocation even if there are active timeouts, and\n * then resets the funnel to it's initial state.\n * - `isIdle` - Checks if there are any active timeouts.\n * @signature\n * funnel(callback, options);\n * @example\n * const debouncer = funnel(\n * () => {\n * console.log(\"Callback executed!\");\n * },\n * { minQuietPeriodMs: 100 },\n * );\n * debouncer.call();\n * debouncer.call();\n *\n * const throttle = funnel(\n * () => {\n * console.log(\"Callback executed!\");\n * },\n * { minGapMs: 100, triggerAt: \"start\" },\n * );\n * throttle.call();\n * throttle.call();\n * @category Function\n */\nexport function funnel<Args extends RestArguments = [], R = never>(\n callback: (data: R) => void,\n {\n triggerAt = 'end',\n minQuietPeriodMs,\n maxBurstDurationMs,\n minGapMs,\n reducer = voidReducer,\n }: FunnelOptions<Args, R>,\n): Funnel<Args> {\n // We manage execution via 2 timeouts, one to track bursts of calls, and one\n // to track the interval between invocations. Together we refer to the period\n // where any of these are active as a \"cool-down period\".\n let burstTimeoutId: ReturnType<typeof setTimeout> | undefined;\n let intervalTimeoutId: ReturnType<typeof setTimeout> | undefined;\n\n // Until invoked, all calls are reduced into a single value that would be sent\n // to the executor on invocation.\n let preparedData: R | undefined;\n\n // In order to be able to limit the total size of the burst (when\n // `maxBurstDurationMs` is used) we need to track when the burst started.\n let burstStartTimestamp: number | undefined;\n\n const invoke = (): void => {\n const param = preparedData;\n if (param === undefined) {\n // There were no calls during both cool-down periods.\n return;\n }\n\n // Make sure the args aren't accidentally used again\n preparedData = undefined;\n\n if (param === VOID_REDUCER_SYMBOL) {\n // @ts-expect-error [ts2554] -- R is typed as `never` because we hide the\n // symbol that `voidReducer` returns; there's no way to make TypeScript\n // aware of this.\n callback();\n } else {\n callback(param);\n }\n\n if (minGapMs !== undefined) {\n intervalTimeoutId = setTimeout(handleIntervalEnd, minGapMs);\n }\n };\n\n function handleIntervalEnd(): void {\n // When called via a timeout the timeout is already cleared, but when called\n // via `flush` we need to manually clear it.\n clearTimeout(intervalTimeoutId);\n intervalTimeoutId = undefined;\n\n if (burstTimeoutId !== undefined) {\n // As long as one of the timeouts is active we don't invoke the function.\n // Each timeout's end event handler has a call to invoke, so we are\n // guaranteed to invoke the function eventually.\n return;\n }\n\n invoke();\n }\n\n const handleBurstEnd = (): void => {\n // When called via a timeout the timeout is already cleared, but when called\n // via `flush` we need to manually clear it.\n clearTimeout(burstTimeoutId);\n burstTimeoutId = undefined;\n burstStartTimestamp = undefined;\n\n if (intervalTimeoutId !== undefined) {\n // As long as one of the timeouts is active we don't invoke the function.\n // Each timeout's end event handler has a call to invoke, so we are\n // guaranteed to invoke the function eventually.\n return;\n }\n\n invoke();\n };\n\n return {\n call: (...args) => {\n // We act based on the initial state of the timeouts before the call is\n // handled and causes the timeouts to change.\n const wasIdle\n = burstTimeoutId === undefined && intervalTimeoutId === undefined;\n\n if (triggerAt !== 'start' || wasIdle) {\n preparedData = reducer(preparedData, ...args);\n }\n\n if (burstTimeoutId === undefined && !wasIdle) {\n // We are not in an active burst period but in an interval period. We\n // don't start a new burst window until the next invoke.\n return;\n }\n\n if (\n minQuietPeriodMs !== undefined\n || maxBurstDurationMs !== undefined\n || minGapMs === undefined\n ) {\n // The timeout tracking the burst period needs to be reset every time\n // another call is made so that it waits the full cool-down duration\n // before it is released.\n clearTimeout(burstTimeoutId);\n\n const now = Date.now();\n\n burstStartTimestamp ??= now;\n\n const burstRemainingMs\n = maxBurstDurationMs === undefined\n ? (minQuietPeriodMs ?? 0)\n : Math.min(\n minQuietPeriodMs ?? maxBurstDurationMs,\n // We need to account for the time already spent so that we\n // don't wait longer than the maxDelay.\n Math.max(0, maxBurstDurationMs - (now - burstStartTimestamp)),\n );\n\n burstTimeoutId = setTimeout(handleBurstEnd, burstRemainingMs);\n }\n\n if (triggerAt !== 'end' && wasIdle) {\n invoke();\n }\n },\n\n cancel: () => {\n clearTimeout(burstTimeoutId);\n burstTimeoutId = undefined;\n burstStartTimestamp = undefined;\n\n clearTimeout(intervalTimeoutId);\n intervalTimeoutId = undefined;\n\n preparedData = undefined;\n },\n\n flush: () => {\n handleBurstEnd();\n handleIntervalEnd();\n },\n\n get isIdle() {\n return burstTimeoutId === undefined && intervalTimeoutId === undefined;\n },\n };\n}\n"],"mappings":"mEAQA,MAAM,EAAsB,OAAO,qBAAqB,CAClD,MAA0B,EAwJhC,SAAgB,EACd,EACA,CACE,YAAY,MACZ,mBACA,qBACA,WACA,UAAU,GAEE,CAId,IAAI,EACA,EAIA,EAIA,EAEE,MAAqB,CACzB,IAAM,EAAQ,EACV,IAAU,IAAA,KAMd,EAAe,IAAA,GAEX,IAAU,EAIZ,GAAU,CAEV,EAAS,EAAM,CAGb,IAAa,IAAA,KACf,EAAoB,WAAW,EAAmB,EAAS,IAI/D,SAAS,GAA0B,CAGjC,aAAa,EAAkB,CAC/B,EAAoB,IAAA,GAEhB,IAAmB,IAAA,IAOvB,GAAQ,CAGV,IAAM,MAA6B,CAGjC,aAAa,EAAe,CAC5B,EAAiB,IAAA,GACjB,EAAsB,IAAA,GAElB,IAAsB,IAAA,IAO1B,GAAQ,EAGV,MAAO,CACL,MAAO,GAAG,IAAS,CAGjB,IAAM,EACF,IAAmB,IAAA,IAAa,IAAsB,IAAA,GAE1D,IAAI,IAAc,SAAW,KAC3B,EAAe,EAAQ,EAAc,GAAG,EAAK,EAG3C,MAAmB,IAAA,IAAa,CAAC,GAMrC,IACE,IAAqB,IAAA,IAClB,IAAuB,IAAA,IACvB,IAAa,IAAA,GAChB,CAIA,aAAa,EAAe,CAE5B,IAAM,EAAM,KAAK,KAAK,CAEtB,IAAwB,EAExB,IAAM,EACF,IAAuB,IAAA,GACpB,GAAoB,EACrB,KAAK,IACH,GAAoB,EAGpB,KAAK,IAAI,EAAG,GAAsB,EAAM,GAAqB,CAC9D,CAEP,EAAiB,WAAW,EAAgB,EAAiB,CAG3D,IAAc,OAAS,GACzB,GAAQ,GAIZ,WAAc,CACZ,aAAa,EAAe,CAC5B,EAAiB,IAAA,GACjB,EAAsB,IAAA,GAEtB,aAAa,EAAkB,CAC/B,EAAoB,IAAA,GAEpB,EAAe,IAAA,IAGjB,UAAa,CACX,GAAgB,CAChB,GAAmB,EAGrB,IAAI,QAAS,CACX,OAAO,IAAmB,IAAA,IAAa,IAAsB,IAAA,IAEhE"}
1
+ {"version":3,"file":"funnel.cjs","names":[],"sources":["../src/funnel.ts"],"sourcesContent":["import type { RequireAtLeastOne } from 'type-fest';\n\n// We use the value provided by the reducer to also determine if a call\n// was done during a timeout period. This means that even when no reducer\n// is provided, we still need a dummy reducer that would return something\n// other than `undefined`. It is safe to cast this to R (which might be\n// anything) because the callback would never use it as it would be typed\n// as a zero-args function.\nconst VOID_REDUCER_SYMBOL = Symbol('funnel/voidReducer');\nconst voidReducer = <R>(): R => VOID_REDUCER_SYMBOL as R;\n\ntype FunnelOptions<Args extends RestArguments, R> = {\n readonly reducer?: (accumulator: R | undefined, ...params: Args) => R;\n} & FunnelTimingOptions;\n\n// Not all combinations of timing options are valid, there are dependencies\n// between them to ensure users can't configure the funnel in a way which would\n// cause it to never trigger.\ntype FunnelTimingOptions\n = | ({ readonly triggerAt?: 'end' } & (\n | ({ readonly minGapMs: number } & RequireAtLeastOne<{\n readonly minQuietPeriodMs: number;\n readonly maxBurstDurationMs: number;\n }>)\n | {\n readonly minQuietPeriodMs?: number;\n readonly maxBurstDurationMs?: number;\n readonly minGapMs?: never;\n }\n ))\n | {\n readonly triggerAt: 'start' | 'both';\n readonly minQuietPeriodMs?: number;\n readonly maxBurstDurationMs?: number;\n readonly minGapMs?: number;\n };\n\n// eslint-disable-next-line ts/no-explicit-any -- TypeScript has some quirks with generic function types, and works best with `any` and not `unknown`. This follows the typing of built-in utilities like `ReturnType` and `Parameters`.\ntype RestArguments = Array<any>;\n\ninterface Funnel<Args extends RestArguments = []> {\n /**\n * Call the function. This might result in the `execute` function being called\n * now or later, depending on it's configuration and it's current state.\n *\n * @param args - The args are defined by the `reducer` function.\n */\n\n readonly call: (...args: Args) => void;\n\n /**\n * Resets the funnel to it's initial state. Any calls made since the last\n * invocation will be discarded.\n */\n readonly cancel: () => void;\n\n /**\n * Triggers an invocation regardless of the current state of the funnel.\n * Like any other invocation, The funnel will also be reset to it's initial\n * state afterwards.\n */\n readonly flush: () => void;\n\n /**\n * The funnel is in it's initial state (there are no active timeouts).\n */\n readonly isIdle: boolean;\n}\n\n/**\n * Creates a funnel that controls the timing and execution of `callback`. Its\n * main purpose is to manage multiple consecutive (usually fast-paced) calls,\n * reshaping them according to a defined batching strategy and timing policy.\n * This is useful when handling uncontrolled call rates, such as DOM events or\n * network traffic. It can implement strategies like debouncing, throttling,\n * batching, and more.\n *\n * An optional `reducer` function can be provided to allow passing data to the\n * callback via calls to `call` (otherwise the signature of `call` takes no\n * arguments).\n *\n * Typing is inferred from `callback`s param, and from the rest params that\n * the optional `reducer` function accepts. Use **explicit** types for these\n * to ensure that everything _else_ is well-typed.\n *\n * Notice that this function constructs a funnel **object**, and does **not**\n * execute anything when called. The returned object should be used to execute\n * the funnel via the its `call` method.\n *\n * - Debouncing: use `minQuietPeriodMs` and any `triggerAt`.\n * - Throttling: use `minGapMs` and `triggerAt: \"start\"` or `\"both\"`.\n * - Batching: See the reference implementation in [`funnel.reference-batch.test.ts`](https://github.com/vinicunca/perkakas/blob/main/src/funnel.reference-batch.test.ts).\n *\n * @param callback - The main function that would be invoked periodically based\n * on `options`. The function would take the latest result of the `reducer`; if\n * no calls where made since the last time it was invoked it will not be\n * invoked. (If a return value is needed, it should be passed via a reference or\n * via closure to the outer scope of the funnel).\n * @param options - An object that defines when `execute` should be invoked,\n * relative to the calls of `call`. An empty/missing options object is\n * equivalent to setting `minQuietPeriodMs` to `0`.\n * @param options.reducer - Combines the arguments passed to `call` with the\n * value computed on the previous call (or `undefined` on the first time). The\n * goal of the function is to extract and summarize the data needed for\n * `callback`. It should be fast and simple as it is called often and should\n * defer heavy operations to the `execute` function. If the final value\n * is `undefined`, `callback` will not be called.\n * @param options.triggerAt - At what \"edges\" of the funnel's burst window\n * would `execute` invoke:\n * - `start` - the function will be invoked immediately (within the **same**\n * execution frame!), and any subsequent calls would be ignored until the funnel\n * is idle again. During this period `reducer` will also not be called.\n * - `end` - the function will **not** be invoked initially but the timer will\n * be started. Any calls during this time would be passed to the reducer, and\n * when the timers are done, the reduced result would trigger an invocation.\n * - `both` - the function will be invoked immediately, and then the funnel\n * would behave as if it was in the 'end' state. Default: 'end'.\n * @param options.minQuietPeriodMs - The burst timer prevents subsequent calls\n * in short succession to cause excessive invocations (aka \"debounce\"). This\n * duration represents the **minimum** amount of time that needs to pass\n * between calls (the \"quiet\" part) in order for the subsequent call to **not**\n * be considered part of the burst. In other words, as long as calls are faster\n * than this, they are considered part of the burst and the burst is extended.\n * @param options.maxBurstDurationMs - Bursts are extended every time a call is\n * made within the burst period. This means that the burst period could be\n * extended indefinitely. To prevent such cases, a maximum burst duration could\n * be defined. When `minQuietPeriodMs` is not defined and this option is, they\n * will both share the same value.\n * @param options.minGapMs - A minimum duration between calls of `execute`.\n * This is maintained regardless of the shape of the burst and is ensured even\n * if the `maxBurstDurationMs` is reached before it. (aka \"throttle\").\n * @returns A funnel with a `call` function that is used to trigger invocations.\n * In addition to it the funnel also comes with the following functions and\n * properties:\n * - `cancel` - Resets the funnel to it's initial state, discarding the current\n * `reducer` result without calling `execute` on it.\n * - `flush` - Triggers an invocation even if there are active timeouts, and\n * then resets the funnel to it's initial state.\n * - `isIdle` - Checks if there are any active timeouts.\n * @signature\n * funnel(callback, options);\n * @example\n * const debouncer = funnel(\n * () => {\n * console.log(\"Callback executed!\");\n * },\n * { minQuietPeriodMs: 100 },\n * );\n * debouncer.call();\n * debouncer.call();\n *\n * const throttle = funnel(\n * () => {\n * console.log(\"Callback executed!\");\n * },\n * { minGapMs: 100, triggerAt: \"start\" },\n * );\n * throttle.call();\n * throttle.call();\n * @category Function\n */\nexport function funnel<Args extends RestArguments = [], R = never>(\n callback: (data: R) => void,\n {\n triggerAt = 'end',\n minQuietPeriodMs,\n maxBurstDurationMs,\n minGapMs,\n reducer = voidReducer,\n }: FunnelOptions<Args, R>,\n): Funnel<Args> {\n // We manage execution via 2 timeouts, one to track bursts of calls, and one\n // to track the interval between invocations. Together we refer to the period\n // where any of these are active as a \"cool-down period\".\n let burstTimeoutId: ReturnType<typeof setTimeout> | undefined;\n let intervalTimeoutId: ReturnType<typeof setTimeout> | undefined;\n\n // Until invoked, all calls are reduced into a single value that would be sent\n // to the executor on invocation.\n let preparedData: R | undefined;\n\n // In order to be able to limit the total size of the burst (when\n // `maxBurstDurationMs` is used) we need to track when the burst started.\n let burstStartTimestamp: number | undefined;\n\n const invoke = (): void => {\n const param = preparedData;\n if (param === undefined) {\n // There were no calls during both cool-down periods.\n return;\n }\n\n // Make sure the args aren't accidentally used again\n preparedData = undefined;\n\n if (param === VOID_REDUCER_SYMBOL) {\n // @ts-expect-error [ts2554] -- R is typed as `never` because we hide the\n // symbol that `voidReducer` returns; there's no way to make TypeScript\n // aware of this.\n callback();\n } else {\n callback(param);\n }\n\n if (minGapMs !== undefined) {\n intervalTimeoutId = setTimeout(handleIntervalEnd, minGapMs);\n }\n };\n\n function handleIntervalEnd(): void {\n // When called via a timeout the timeout is already cleared, but when called\n // via `flush` we need to manually clear it.\n clearTimeout(intervalTimeoutId);\n intervalTimeoutId = undefined;\n\n if (burstTimeoutId !== undefined) {\n // As long as one of the timeouts is active we don't invoke the function.\n // Each timeout's end event handler has a call to invoke, so we are\n // guaranteed to invoke the function eventually.\n return;\n }\n\n invoke();\n }\n\n const handleBurstEnd = (): void => {\n // When called via a timeout the timeout is already cleared, but when called\n // via `flush` we need to manually clear it.\n clearTimeout(burstTimeoutId);\n burstTimeoutId = undefined;\n burstStartTimestamp = undefined;\n\n if (intervalTimeoutId !== undefined) {\n // As long as one of the timeouts is active we don't invoke the function.\n // Each timeout's end event handler has a call to invoke, so we are\n // guaranteed to invoke the function eventually.\n return;\n }\n\n invoke();\n };\n\n return {\n call: (...args) => {\n // We act based on the initial state of the timeouts before the call is\n // handled and causes the timeouts to change.\n const wasIdle\n = burstTimeoutId === undefined && intervalTimeoutId === undefined;\n\n if (triggerAt !== 'start' || wasIdle) {\n preparedData = reducer(preparedData, ...args);\n }\n\n if (burstTimeoutId === undefined && !wasIdle) {\n // We are not in an active burst period but in an interval period. We\n // don't start a new burst window until the next invoke.\n return;\n }\n\n if (\n minQuietPeriodMs !== undefined\n || maxBurstDurationMs !== undefined\n || minGapMs === undefined\n ) {\n // The timeout tracking the burst period needs to be reset every time\n // another call is made so that it waits the full cool-down duration\n // before it is released.\n clearTimeout(burstTimeoutId);\n\n const now = Date.now();\n\n burstStartTimestamp ??= now;\n\n const burstRemainingMs\n = maxBurstDurationMs === undefined\n ? (minQuietPeriodMs ?? 0)\n : Math.min(\n minQuietPeriodMs ?? maxBurstDurationMs,\n // We need to account for the time already spent so that we\n // don't wait longer than the maxDelay.\n Math.max(0, maxBurstDurationMs - (now - burstStartTimestamp)),\n );\n\n burstTimeoutId = setTimeout(handleBurstEnd, burstRemainingMs);\n }\n\n if (triggerAt !== 'end' && wasIdle) {\n invoke();\n }\n },\n\n cancel: () => {\n clearTimeout(burstTimeoutId);\n burstTimeoutId = undefined;\n burstStartTimestamp = undefined;\n\n clearTimeout(intervalTimeoutId);\n intervalTimeoutId = undefined;\n\n preparedData = undefined;\n },\n\n flush: () => {\n handleBurstEnd();\n handleIntervalEnd();\n },\n\n get isIdle() {\n return burstTimeoutId === undefined && intervalTimeoutId === undefined;\n },\n };\n}\n"],"mappings":"mEAQA,MAAM,EAAsB,OAAO,oBAAoB,EACjD,MAA0B,EAwJhC,SAAgB,EACd,EACA,CACE,YAAY,MACZ,mBACA,qBACA,WACA,UAAU,GAEE,CAId,IAAI,EACA,EAIA,EAIA,EAEE,MAAqB,CACzB,IAAM,EAAQ,EACV,IAAU,IAAA,KAMd,EAAe,IAAA,GAEX,IAAU,EAIZ,EAAS,EAET,EAAS,CAAK,EAGZ,IAAa,IAAA,KACf,EAAoB,WAAW,EAAmB,CAAQ,GAE9D,EAEA,SAAS,GAA0B,CAGjC,aAAa,CAAiB,EAC9B,EAAoB,IAAA,GAEhB,IAAmB,IAAA,IAOvB,EAAO,CACT,CAEA,IAAM,MAA6B,CAGjC,aAAa,CAAc,EAC3B,EAAiB,IAAA,GACjB,EAAsB,IAAA,GAElB,IAAsB,IAAA,IAO1B,EAAO,CACT,EAEA,MAAO,CACL,MAAO,GAAG,IAAS,CAGjB,IAAM,EACF,IAAmB,IAAA,IAAa,IAAsB,IAAA,GAE1D,IAAI,IAAc,SAAW,KAC3B,EAAe,EAAQ,EAAc,GAAG,CAAI,GAG1C,MAAmB,IAAA,IAAa,CAAC,GAMrC,IACE,IAAqB,IAAA,IAClB,IAAuB,IAAA,IACvB,IAAa,IAAA,GAChB,CAIA,aAAa,CAAc,EAE3B,IAAM,EAAM,KAAK,IAAI,EAErB,IAAwB,EAExB,IAAM,EACF,IAAuB,IAAA,GACpB,GAAoB,EACrB,KAAK,IACH,GAAoB,EAGpB,KAAK,IAAI,EAAG,GAAsB,EAAM,EAAoB,CAC9D,EAEN,EAAiB,WAAW,EAAgB,CAAgB,CAC9D,CAEI,IAAc,OAAS,GACzB,EAAO,CAHT,CAKF,EAEA,WAAc,CACZ,aAAa,CAAc,EAC3B,EAAiB,IAAA,GACjB,EAAsB,IAAA,GAEtB,aAAa,CAAiB,EAC9B,EAAoB,IAAA,GAEpB,EAAe,IAAA,EACjB,EAEA,UAAa,CACX,EAAe,EACf,EAAkB,CACpB,EAEA,IAAI,QAAS,CACX,OAAO,IAAmB,IAAA,IAAa,IAAsB,IAAA,EAC/D,CACF,CACF"}
@@ -1 +1 @@
1
- {"version":3,"file":"funnel.js","names":[],"sources":["../src/funnel.ts"],"sourcesContent":["import type { RequireAtLeastOne } from 'type-fest';\n\n// We use the value provided by the reducer to also determine if a call\n// was done during a timeout period. This means that even when no reducer\n// is provided, we still need a dummy reducer that would return something\n// other than `undefined`. It is safe to cast this to R (which might be\n// anything) because the callback would never use it as it would be typed\n// as a zero-args function.\nconst VOID_REDUCER_SYMBOL = Symbol('funnel/voidReducer');\nconst voidReducer = <R>(): R => VOID_REDUCER_SYMBOL as R;\n\ntype FunnelOptions<Args extends RestArguments, R> = {\n readonly reducer?: (accumulator: R | undefined, ...params: Args) => R;\n} & FunnelTimingOptions;\n\n// Not all combinations of timing options are valid, there are dependencies\n// between them to ensure users can't configure the funnel in a way which would\n// cause it to never trigger.\ntype FunnelTimingOptions\n = | ({ readonly triggerAt?: 'end' } & (\n | ({ readonly minGapMs: number } & RequireAtLeastOne<{\n readonly minQuietPeriodMs: number;\n readonly maxBurstDurationMs: number;\n }>)\n | {\n readonly minQuietPeriodMs?: number;\n readonly maxBurstDurationMs?: number;\n readonly minGapMs?: never;\n }\n ))\n | {\n readonly triggerAt: 'start' | 'both';\n readonly minQuietPeriodMs?: number;\n readonly maxBurstDurationMs?: number;\n readonly minGapMs?: number;\n };\n\n// eslint-disable-next-line ts/no-explicit-any -- TypeScript has some quirks with generic function types, and works best with `any` and not `unknown`. This follows the typing of built-in utilities like `ReturnType` and `Parameters`.\ntype RestArguments = Array<any>;\n\ninterface Funnel<Args extends RestArguments = []> {\n /**\n * Call the function. This might result in the `execute` function being called\n * now or later, depending on it's configuration and it's current state.\n *\n * @param args - The args are defined by the `reducer` function.\n */\n\n readonly call: (...args: Args) => void;\n\n /**\n * Resets the funnel to it's initial state. Any calls made since the last\n * invocation will be discarded.\n */\n readonly cancel: () => void;\n\n /**\n * Triggers an invocation regardless of the current state of the funnel.\n * Like any other invocation, The funnel will also be reset to it's initial\n * state afterwards.\n */\n readonly flush: () => void;\n\n /**\n * The funnel is in it's initial state (there are no active timeouts).\n */\n readonly isIdle: boolean;\n}\n\n/**\n * Creates a funnel that controls the timing and execution of `callback`. Its\n * main purpose is to manage multiple consecutive (usually fast-paced) calls,\n * reshaping them according to a defined batching strategy and timing policy.\n * This is useful when handling uncontrolled call rates, such as DOM events or\n * network traffic. It can implement strategies like debouncing, throttling,\n * batching, and more.\n *\n * An optional `reducer` function can be provided to allow passing data to the\n * callback via calls to `call` (otherwise the signature of `call` takes no\n * arguments).\n *\n * Typing is inferred from `callback`s param, and from the rest params that\n * the optional `reducer` function accepts. Use **explicit** types for these\n * to ensure that everything _else_ is well-typed.\n *\n * Notice that this function constructs a funnel **object**, and does **not**\n * execute anything when called. The returned object should be used to execute\n * the funnel via the its `call` method.\n *\n * - Debouncing: use `minQuietPeriodMs` and any `triggerAt`.\n * - Throttling: use `minGapMs` and `triggerAt: \"start\"` or `\"both\"`.\n * - Batching: See the reference implementation in [`funnel.reference-batch.test.ts`](https://github.com/vinicunca/perkakas/blob/main/src/funnel.reference-batch.test.ts).\n *\n * @param callback - The main function that would be invoked periodically based\n * on `options`. The function would take the latest result of the `reducer`; if\n * no calls where made since the last time it was invoked it will not be\n * invoked. (If a return value is needed, it should be passed via a reference or\n * via closure to the outer scope of the funnel).\n * @param options - An object that defines when `execute` should be invoked,\n * relative to the calls of `call`. An empty/missing options object is\n * equivalent to setting `minQuietPeriodMs` to `0`.\n * @param options.reducer - Combines the arguments passed to `call` with the\n * value computed on the previous call (or `undefined` on the first time). The\n * goal of the function is to extract and summarize the data needed for\n * `callback`. It should be fast and simple as it is called often and should\n * defer heavy operations to the `execute` function. If the final value\n * is `undefined`, `callback` will not be called.\n * @param options.triggerAt - At what \"edges\" of the funnel's burst window\n * would `execute` invoke:\n * - `start` - the function will be invoked immediately (within the **same**\n * execution frame!), and any subsequent calls would be ignored until the funnel\n * is idle again. During this period `reducer` will also not be called.\n * - `end` - the function will **not** be invoked initially but the timer will\n * be started. Any calls during this time would be passed to the reducer, and\n * when the timers are done, the reduced result would trigger an invocation.\n * - `both` - the function will be invoked immediately, and then the funnel\n * would behave as if it was in the 'end' state. Default: 'end'.\n * @param options.minQuietPeriodMs - The burst timer prevents subsequent calls\n * in short succession to cause excessive invocations (aka \"debounce\"). This\n * duration represents the **minimum** amount of time that needs to pass\n * between calls (the \"quiet\" part) in order for the subsequent call to **not**\n * be considered part of the burst. In other words, as long as calls are faster\n * than this, they are considered part of the burst and the burst is extended.\n * @param options.maxBurstDurationMs - Bursts are extended every time a call is\n * made within the burst period. This means that the burst period could be\n * extended indefinitely. To prevent such cases, a maximum burst duration could\n * be defined. When `minQuietPeriodMs` is not defined and this option is, they\n * will both share the same value.\n * @param options.minGapMs - A minimum duration between calls of `execute`.\n * This is maintained regardless of the shape of the burst and is ensured even\n * if the `maxBurstDurationMs` is reached before it. (aka \"throttle\").\n * @returns A funnel with a `call` function that is used to trigger invocations.\n * In addition to it the funnel also comes with the following functions and\n * properties:\n * - `cancel` - Resets the funnel to it's initial state, discarding the current\n * `reducer` result without calling `execute` on it.\n * - `flush` - Triggers an invocation even if there are active timeouts, and\n * then resets the funnel to it's initial state.\n * - `isIdle` - Checks if there are any active timeouts.\n * @signature\n * funnel(callback, options);\n * @example\n * const debouncer = funnel(\n * () => {\n * console.log(\"Callback executed!\");\n * },\n * { minQuietPeriodMs: 100 },\n * );\n * debouncer.call();\n * debouncer.call();\n *\n * const throttle = funnel(\n * () => {\n * console.log(\"Callback executed!\");\n * },\n * { minGapMs: 100, triggerAt: \"start\" },\n * );\n * throttle.call();\n * throttle.call();\n * @category Function\n */\nexport function funnel<Args extends RestArguments = [], R = never>(\n callback: (data: R) => void,\n {\n triggerAt = 'end',\n minQuietPeriodMs,\n maxBurstDurationMs,\n minGapMs,\n reducer = voidReducer,\n }: FunnelOptions<Args, R>,\n): Funnel<Args> {\n // We manage execution via 2 timeouts, one to track bursts of calls, and one\n // to track the interval between invocations. Together we refer to the period\n // where any of these are active as a \"cool-down period\".\n let burstTimeoutId: ReturnType<typeof setTimeout> | undefined;\n let intervalTimeoutId: ReturnType<typeof setTimeout> | undefined;\n\n // Until invoked, all calls are reduced into a single value that would be sent\n // to the executor on invocation.\n let preparedData: R | undefined;\n\n // In order to be able to limit the total size of the burst (when\n // `maxBurstDurationMs` is used) we need to track when the burst started.\n let burstStartTimestamp: number | undefined;\n\n const invoke = (): void => {\n const param = preparedData;\n if (param === undefined) {\n // There were no calls during both cool-down periods.\n return;\n }\n\n // Make sure the args aren't accidentally used again\n preparedData = undefined;\n\n if (param === VOID_REDUCER_SYMBOL) {\n // @ts-expect-error [ts2554] -- R is typed as `never` because we hide the\n // symbol that `voidReducer` returns; there's no way to make TypeScript\n // aware of this.\n callback();\n } else {\n callback(param);\n }\n\n if (minGapMs !== undefined) {\n intervalTimeoutId = setTimeout(handleIntervalEnd, minGapMs);\n }\n };\n\n function handleIntervalEnd(): void {\n // When called via a timeout the timeout is already cleared, but when called\n // via `flush` we need to manually clear it.\n clearTimeout(intervalTimeoutId);\n intervalTimeoutId = undefined;\n\n if (burstTimeoutId !== undefined) {\n // As long as one of the timeouts is active we don't invoke the function.\n // Each timeout's end event handler has a call to invoke, so we are\n // guaranteed to invoke the function eventually.\n return;\n }\n\n invoke();\n }\n\n const handleBurstEnd = (): void => {\n // When called via a timeout the timeout is already cleared, but when called\n // via `flush` we need to manually clear it.\n clearTimeout(burstTimeoutId);\n burstTimeoutId = undefined;\n burstStartTimestamp = undefined;\n\n if (intervalTimeoutId !== undefined) {\n // As long as one of the timeouts is active we don't invoke the function.\n // Each timeout's end event handler has a call to invoke, so we are\n // guaranteed to invoke the function eventually.\n return;\n }\n\n invoke();\n };\n\n return {\n call: (...args) => {\n // We act based on the initial state of the timeouts before the call is\n // handled and causes the timeouts to change.\n const wasIdle\n = burstTimeoutId === undefined && intervalTimeoutId === undefined;\n\n if (triggerAt !== 'start' || wasIdle) {\n preparedData = reducer(preparedData, ...args);\n }\n\n if (burstTimeoutId === undefined && !wasIdle) {\n // We are not in an active burst period but in an interval period. We\n // don't start a new burst window until the next invoke.\n return;\n }\n\n if (\n minQuietPeriodMs !== undefined\n || maxBurstDurationMs !== undefined\n || minGapMs === undefined\n ) {\n // The timeout tracking the burst period needs to be reset every time\n // another call is made so that it waits the full cool-down duration\n // before it is released.\n clearTimeout(burstTimeoutId);\n\n const now = Date.now();\n\n burstStartTimestamp ??= now;\n\n const burstRemainingMs\n = maxBurstDurationMs === undefined\n ? (minQuietPeriodMs ?? 0)\n : Math.min(\n minQuietPeriodMs ?? maxBurstDurationMs,\n // We need to account for the time already spent so that we\n // don't wait longer than the maxDelay.\n Math.max(0, maxBurstDurationMs - (now - burstStartTimestamp)),\n );\n\n burstTimeoutId = setTimeout(handleBurstEnd, burstRemainingMs);\n }\n\n if (triggerAt !== 'end' && wasIdle) {\n invoke();\n }\n },\n\n cancel: () => {\n clearTimeout(burstTimeoutId);\n burstTimeoutId = undefined;\n burstStartTimestamp = undefined;\n\n clearTimeout(intervalTimeoutId);\n intervalTimeoutId = undefined;\n\n preparedData = undefined;\n },\n\n flush: () => {\n handleBurstEnd();\n handleIntervalEnd();\n },\n\n get isIdle() {\n return burstTimeoutId === undefined && intervalTimeoutId === undefined;\n },\n };\n}\n"],"mappings":"AAQA,MAAM,EAAsB,OAAO,qBAAqB,CAClD,MAA0B,EAwJhC,SAAgB,EACd,EACA,CACE,YAAY,MACZ,mBACA,qBACA,WACA,UAAU,GAEE,CAId,IAAI,EACA,EAIA,EAIA,EAEE,MAAqB,CACzB,IAAM,EAAQ,EACV,IAAU,IAAA,KAMd,EAAe,IAAA,GAEX,IAAU,EAIZ,GAAU,CAEV,EAAS,EAAM,CAGb,IAAa,IAAA,KACf,EAAoB,WAAW,EAAmB,EAAS,IAI/D,SAAS,GAA0B,CAGjC,aAAa,EAAkB,CAC/B,EAAoB,IAAA,GAEhB,IAAmB,IAAA,IAOvB,GAAQ,CAGV,IAAM,MAA6B,CAGjC,aAAa,EAAe,CAC5B,EAAiB,IAAA,GACjB,EAAsB,IAAA,GAElB,IAAsB,IAAA,IAO1B,GAAQ,EAGV,MAAO,CACL,MAAO,GAAG,IAAS,CAGjB,IAAM,EACF,IAAmB,IAAA,IAAa,IAAsB,IAAA,GAE1D,IAAI,IAAc,SAAW,KAC3B,EAAe,EAAQ,EAAc,GAAG,EAAK,EAG3C,MAAmB,IAAA,IAAa,CAAC,GAMrC,IACE,IAAqB,IAAA,IAClB,IAAuB,IAAA,IACvB,IAAa,IAAA,GAChB,CAIA,aAAa,EAAe,CAE5B,IAAM,EAAM,KAAK,KAAK,CAEtB,IAAwB,EAExB,IAAM,EACF,IAAuB,IAAA,GACpB,GAAoB,EACrB,KAAK,IACH,GAAoB,EAGpB,KAAK,IAAI,EAAG,GAAsB,EAAM,GAAqB,CAC9D,CAEP,EAAiB,WAAW,EAAgB,EAAiB,CAG3D,IAAc,OAAS,GACzB,GAAQ,GAIZ,WAAc,CACZ,aAAa,EAAe,CAC5B,EAAiB,IAAA,GACjB,EAAsB,IAAA,GAEtB,aAAa,EAAkB,CAC/B,EAAoB,IAAA,GAEpB,EAAe,IAAA,IAGjB,UAAa,CACX,GAAgB,CAChB,GAAmB,EAGrB,IAAI,QAAS,CACX,OAAO,IAAmB,IAAA,IAAa,IAAsB,IAAA,IAEhE"}
1
+ {"version":3,"file":"funnel.js","names":[],"sources":["../src/funnel.ts"],"sourcesContent":["import type { RequireAtLeastOne } from 'type-fest';\n\n// We use the value provided by the reducer to also determine if a call\n// was done during a timeout period. This means that even when no reducer\n// is provided, we still need a dummy reducer that would return something\n// other than `undefined`. It is safe to cast this to R (which might be\n// anything) because the callback would never use it as it would be typed\n// as a zero-args function.\nconst VOID_REDUCER_SYMBOL = Symbol('funnel/voidReducer');\nconst voidReducer = <R>(): R => VOID_REDUCER_SYMBOL as R;\n\ntype FunnelOptions<Args extends RestArguments, R> = {\n readonly reducer?: (accumulator: R | undefined, ...params: Args) => R;\n} & FunnelTimingOptions;\n\n// Not all combinations of timing options are valid, there are dependencies\n// between them to ensure users can't configure the funnel in a way which would\n// cause it to never trigger.\ntype FunnelTimingOptions\n = | ({ readonly triggerAt?: 'end' } & (\n | ({ readonly minGapMs: number } & RequireAtLeastOne<{\n readonly minQuietPeriodMs: number;\n readonly maxBurstDurationMs: number;\n }>)\n | {\n readonly minQuietPeriodMs?: number;\n readonly maxBurstDurationMs?: number;\n readonly minGapMs?: never;\n }\n ))\n | {\n readonly triggerAt: 'start' | 'both';\n readonly minQuietPeriodMs?: number;\n readonly maxBurstDurationMs?: number;\n readonly minGapMs?: number;\n };\n\n// eslint-disable-next-line ts/no-explicit-any -- TypeScript has some quirks with generic function types, and works best with `any` and not `unknown`. This follows the typing of built-in utilities like `ReturnType` and `Parameters`.\ntype RestArguments = Array<any>;\n\ninterface Funnel<Args extends RestArguments = []> {\n /**\n * Call the function. This might result in the `execute` function being called\n * now or later, depending on it's configuration and it's current state.\n *\n * @param args - The args are defined by the `reducer` function.\n */\n\n readonly call: (...args: Args) => void;\n\n /**\n * Resets the funnel to it's initial state. Any calls made since the last\n * invocation will be discarded.\n */\n readonly cancel: () => void;\n\n /**\n * Triggers an invocation regardless of the current state of the funnel.\n * Like any other invocation, The funnel will also be reset to it's initial\n * state afterwards.\n */\n readonly flush: () => void;\n\n /**\n * The funnel is in it's initial state (there are no active timeouts).\n */\n readonly isIdle: boolean;\n}\n\n/**\n * Creates a funnel that controls the timing and execution of `callback`. Its\n * main purpose is to manage multiple consecutive (usually fast-paced) calls,\n * reshaping them according to a defined batching strategy and timing policy.\n * This is useful when handling uncontrolled call rates, such as DOM events or\n * network traffic. It can implement strategies like debouncing, throttling,\n * batching, and more.\n *\n * An optional `reducer` function can be provided to allow passing data to the\n * callback via calls to `call` (otherwise the signature of `call` takes no\n * arguments).\n *\n * Typing is inferred from `callback`s param, and from the rest params that\n * the optional `reducer` function accepts. Use **explicit** types for these\n * to ensure that everything _else_ is well-typed.\n *\n * Notice that this function constructs a funnel **object**, and does **not**\n * execute anything when called. The returned object should be used to execute\n * the funnel via the its `call` method.\n *\n * - Debouncing: use `minQuietPeriodMs` and any `triggerAt`.\n * - Throttling: use `minGapMs` and `triggerAt: \"start\"` or `\"both\"`.\n * - Batching: See the reference implementation in [`funnel.reference-batch.test.ts`](https://github.com/vinicunca/perkakas/blob/main/src/funnel.reference-batch.test.ts).\n *\n * @param callback - The main function that would be invoked periodically based\n * on `options`. The function would take the latest result of the `reducer`; if\n * no calls where made since the last time it was invoked it will not be\n * invoked. (If a return value is needed, it should be passed via a reference or\n * via closure to the outer scope of the funnel).\n * @param options - An object that defines when `execute` should be invoked,\n * relative to the calls of `call`. An empty/missing options object is\n * equivalent to setting `minQuietPeriodMs` to `0`.\n * @param options.reducer - Combines the arguments passed to `call` with the\n * value computed on the previous call (or `undefined` on the first time). The\n * goal of the function is to extract and summarize the data needed for\n * `callback`. It should be fast and simple as it is called often and should\n * defer heavy operations to the `execute` function. If the final value\n * is `undefined`, `callback` will not be called.\n * @param options.triggerAt - At what \"edges\" of the funnel's burst window\n * would `execute` invoke:\n * - `start` - the function will be invoked immediately (within the **same**\n * execution frame!), and any subsequent calls would be ignored until the funnel\n * is idle again. During this period `reducer` will also not be called.\n * - `end` - the function will **not** be invoked initially but the timer will\n * be started. Any calls during this time would be passed to the reducer, and\n * when the timers are done, the reduced result would trigger an invocation.\n * - `both` - the function will be invoked immediately, and then the funnel\n * would behave as if it was in the 'end' state. Default: 'end'.\n * @param options.minQuietPeriodMs - The burst timer prevents subsequent calls\n * in short succession to cause excessive invocations (aka \"debounce\"). This\n * duration represents the **minimum** amount of time that needs to pass\n * between calls (the \"quiet\" part) in order for the subsequent call to **not**\n * be considered part of the burst. In other words, as long as calls are faster\n * than this, they are considered part of the burst and the burst is extended.\n * @param options.maxBurstDurationMs - Bursts are extended every time a call is\n * made within the burst period. This means that the burst period could be\n * extended indefinitely. To prevent such cases, a maximum burst duration could\n * be defined. When `minQuietPeriodMs` is not defined and this option is, they\n * will both share the same value.\n * @param options.minGapMs - A minimum duration between calls of `execute`.\n * This is maintained regardless of the shape of the burst and is ensured even\n * if the `maxBurstDurationMs` is reached before it. (aka \"throttle\").\n * @returns A funnel with a `call` function that is used to trigger invocations.\n * In addition to it the funnel also comes with the following functions and\n * properties:\n * - `cancel` - Resets the funnel to it's initial state, discarding the current\n * `reducer` result without calling `execute` on it.\n * - `flush` - Triggers an invocation even if there are active timeouts, and\n * then resets the funnel to it's initial state.\n * - `isIdle` - Checks if there are any active timeouts.\n * @signature\n * funnel(callback, options);\n * @example\n * const debouncer = funnel(\n * () => {\n * console.log(\"Callback executed!\");\n * },\n * { minQuietPeriodMs: 100 },\n * );\n * debouncer.call();\n * debouncer.call();\n *\n * const throttle = funnel(\n * () => {\n * console.log(\"Callback executed!\");\n * },\n * { minGapMs: 100, triggerAt: \"start\" },\n * );\n * throttle.call();\n * throttle.call();\n * @category Function\n */\nexport function funnel<Args extends RestArguments = [], R = never>(\n callback: (data: R) => void,\n {\n triggerAt = 'end',\n minQuietPeriodMs,\n maxBurstDurationMs,\n minGapMs,\n reducer = voidReducer,\n }: FunnelOptions<Args, R>,\n): Funnel<Args> {\n // We manage execution via 2 timeouts, one to track bursts of calls, and one\n // to track the interval between invocations. Together we refer to the period\n // where any of these are active as a \"cool-down period\".\n let burstTimeoutId: ReturnType<typeof setTimeout> | undefined;\n let intervalTimeoutId: ReturnType<typeof setTimeout> | undefined;\n\n // Until invoked, all calls are reduced into a single value that would be sent\n // to the executor on invocation.\n let preparedData: R | undefined;\n\n // In order to be able to limit the total size of the burst (when\n // `maxBurstDurationMs` is used) we need to track when the burst started.\n let burstStartTimestamp: number | undefined;\n\n const invoke = (): void => {\n const param = preparedData;\n if (param === undefined) {\n // There were no calls during both cool-down periods.\n return;\n }\n\n // Make sure the args aren't accidentally used again\n preparedData = undefined;\n\n if (param === VOID_REDUCER_SYMBOL) {\n // @ts-expect-error [ts2554] -- R is typed as `never` because we hide the\n // symbol that `voidReducer` returns; there's no way to make TypeScript\n // aware of this.\n callback();\n } else {\n callback(param);\n }\n\n if (minGapMs !== undefined) {\n intervalTimeoutId = setTimeout(handleIntervalEnd, minGapMs);\n }\n };\n\n function handleIntervalEnd(): void {\n // When called via a timeout the timeout is already cleared, but when called\n // via `flush` we need to manually clear it.\n clearTimeout(intervalTimeoutId);\n intervalTimeoutId = undefined;\n\n if (burstTimeoutId !== undefined) {\n // As long as one of the timeouts is active we don't invoke the function.\n // Each timeout's end event handler has a call to invoke, so we are\n // guaranteed to invoke the function eventually.\n return;\n }\n\n invoke();\n }\n\n const handleBurstEnd = (): void => {\n // When called via a timeout the timeout is already cleared, but when called\n // via `flush` we need to manually clear it.\n clearTimeout(burstTimeoutId);\n burstTimeoutId = undefined;\n burstStartTimestamp = undefined;\n\n if (intervalTimeoutId !== undefined) {\n // As long as one of the timeouts is active we don't invoke the function.\n // Each timeout's end event handler has a call to invoke, so we are\n // guaranteed to invoke the function eventually.\n return;\n }\n\n invoke();\n };\n\n return {\n call: (...args) => {\n // We act based on the initial state of the timeouts before the call is\n // handled and causes the timeouts to change.\n const wasIdle\n = burstTimeoutId === undefined && intervalTimeoutId === undefined;\n\n if (triggerAt !== 'start' || wasIdle) {\n preparedData = reducer(preparedData, ...args);\n }\n\n if (burstTimeoutId === undefined && !wasIdle) {\n // We are not in an active burst period but in an interval period. We\n // don't start a new burst window until the next invoke.\n return;\n }\n\n if (\n minQuietPeriodMs !== undefined\n || maxBurstDurationMs !== undefined\n || minGapMs === undefined\n ) {\n // The timeout tracking the burst period needs to be reset every time\n // another call is made so that it waits the full cool-down duration\n // before it is released.\n clearTimeout(burstTimeoutId);\n\n const now = Date.now();\n\n burstStartTimestamp ??= now;\n\n const burstRemainingMs\n = maxBurstDurationMs === undefined\n ? (minQuietPeriodMs ?? 0)\n : Math.min(\n minQuietPeriodMs ?? maxBurstDurationMs,\n // We need to account for the time already spent so that we\n // don't wait longer than the maxDelay.\n Math.max(0, maxBurstDurationMs - (now - burstStartTimestamp)),\n );\n\n burstTimeoutId = setTimeout(handleBurstEnd, burstRemainingMs);\n }\n\n if (triggerAt !== 'end' && wasIdle) {\n invoke();\n }\n },\n\n cancel: () => {\n clearTimeout(burstTimeoutId);\n burstTimeoutId = undefined;\n burstStartTimestamp = undefined;\n\n clearTimeout(intervalTimeoutId);\n intervalTimeoutId = undefined;\n\n preparedData = undefined;\n },\n\n flush: () => {\n handleBurstEnd();\n handleIntervalEnd();\n },\n\n get isIdle() {\n return burstTimeoutId === undefined && intervalTimeoutId === undefined;\n },\n };\n}\n"],"mappings":"AAQA,MAAM,EAAsB,OAAO,oBAAoB,EACjD,MAA0B,EAwJhC,SAAgB,EACd,EACA,CACE,YAAY,MACZ,mBACA,qBACA,WACA,UAAU,GAEE,CAId,IAAI,EACA,EAIA,EAIA,EAEE,MAAqB,CACzB,IAAM,EAAQ,EACV,IAAU,IAAA,KAMd,EAAe,IAAA,GAEX,IAAU,EAIZ,EAAS,EAET,EAAS,CAAK,EAGZ,IAAa,IAAA,KACf,EAAoB,WAAW,EAAmB,CAAQ,GAE9D,EAEA,SAAS,GAA0B,CAGjC,aAAa,CAAiB,EAC9B,EAAoB,IAAA,GAEhB,IAAmB,IAAA,IAOvB,EAAO,CACT,CAEA,IAAM,MAA6B,CAGjC,aAAa,CAAc,EAC3B,EAAiB,IAAA,GACjB,EAAsB,IAAA,GAElB,IAAsB,IAAA,IAO1B,EAAO,CACT,EAEA,MAAO,CACL,MAAO,GAAG,IAAS,CAGjB,IAAM,EACF,IAAmB,IAAA,IAAa,IAAsB,IAAA,GAE1D,IAAI,IAAc,SAAW,KAC3B,EAAe,EAAQ,EAAc,GAAG,CAAI,GAG1C,MAAmB,IAAA,IAAa,CAAC,GAMrC,IACE,IAAqB,IAAA,IAClB,IAAuB,IAAA,IACvB,IAAa,IAAA,GAChB,CAIA,aAAa,CAAc,EAE3B,IAAM,EAAM,KAAK,IAAI,EAErB,IAAwB,EAExB,IAAM,EACF,IAAuB,IAAA,GACpB,GAAoB,EACrB,KAAK,IACH,GAAoB,EAGpB,KAAK,IAAI,EAAG,GAAsB,EAAM,EAAoB,CAC9D,EAEN,EAAiB,WAAW,EAAgB,CAAgB,CAC9D,CAEI,IAAc,OAAS,GACzB,EAAO,CAHT,CAKF,EAEA,WAAc,CACZ,aAAa,CAAc,EAC3B,EAAiB,IAAA,GACjB,EAAsB,IAAA,GAEtB,aAAa,CAAiB,EAC9B,EAAoB,IAAA,GAEpB,EAAe,IAAA,EACjB,EAEA,UAAa,CACX,EAAe,EACf,EAAkB,CACpB,EAEA,IAAI,QAAS,CACX,OAAO,IAAmB,IAAA,IAAa,IAAsB,IAAA,EAC/D,CACF,CACF"}
@@ -1,2 +1,2 @@
1
- Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});const e=require(`./curry.cjs`);function t(...t){return e.curry(n,t)}function n(e,t){let n=Object.create(null);for(let r of e){let e=r?.[t];if(e!==void 0){let t=n[e];t===void 0?n[e]=[r]:t.push(r)}}return Object.setPrototypeOf(n,Object.prototype),n}exports.groupByProp=t;
1
+ Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});const e=require("./curry.cjs");function t(...t){return e.curry(n,t)}function n(e,t){let n=Object.create(null);for(let r of e){let e=r?.[t];if(e!==void 0){let t=n[e];t===void 0?n[e]=[r]:t.push(r)}}return Object.setPrototypeOf(n,Object.prototype),n}exports.groupByProp=t;
2
2
  //# sourceMappingURL=group-by-prop.cjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"group-by-prop.cjs","names":["curry"],"sources":["../src/group-by-prop.ts"],"sourcesContent":["import type {\n AllUnionFields,\n ConditionalKeys,\n EmptyObject,\n IsNever,\n Or,\n Simplify,\n} from 'type-fest';\nimport type { ArrayRequiredPrefix } from './internal/types/array-required-prefix';\nimport type { BoundedPartial } from './internal/types/bounded-partial';\nimport type { FilteredArray } from './internal/types/filtered-array';\nimport type { IterableContainer } from './internal/types/iterable-container';\nimport type { TupleParts } from './internal/types/tuple-parts';\nimport { curry } from './curry';\n\ntype GroupByProp<T extends IterableContainer, Prop extends GroupableProps<T>>\n // Distribute unions.\n = T extends unknown\n ? FixEmptyObject<EnsureValuesAreNonEmpty<GroupByPropRaw<T, Prop>>>\n : never;\n\n// For each possible value of the prop we filter the input tuple with the prop\n// assigned to the value, e.g. `{ type: \"cat\" }`\ntype GroupByPropRaw<\n T extends IterableContainer,\n Prop extends GroupableProps<T>,\n> = {\n [Value in AllPropValues<T, Prop>]: FilteredArray<T, Record<Prop, Value>>;\n};\n\n// We can only group by props that only have values that could be used to key\n// an object (i.e. PropertyKey), or if they are undefined (which would filter\n// them out of the grouping).\ntype GroupableProps<T extends IterableContainer> = ConditionalKeys<\n ItemsSuperObject<T>,\n PropertyKey | undefined\n>;\n\n// The union of all possible values that the prop could have within the tuple.\ntype AllPropValues<\n T extends IterableContainer,\n Prop extends GroupableProps<T>,\n> = Extract<ItemsSuperObject<T>[Prop], PropertyKey>;\n\n// Creates a singular object type that all items in the tuple would extend. This\n// provides us a way to check, for each prop, what are all values it would\n// have within the tuple. We use this to map which props are candidates for\n// grouping, and when a prop is selected, the full list of values that would\n// exist in the output. For example:\n// `{ a: number, b: \"cat\", c: string } | { b: \"dog\", c: Date }` is groupable\n// by 'a' and 'b', but not 'c', and when selecting by 'b', the output would\n// have a prop for \"cat\" and a prop for \"dog\".\ntype ItemsSuperObject<T extends IterableContainer> = AllUnionFields<\n // If the input tuple contains optional elements they would add `undefined` to\n // T[number] (and could technically show up in the array itself). Because\n // undefined breaks AllUnionFields we need to remove it from the union. This\n // is OK because we handle this in the implementation too.\n Exclude<T[number], undefined>\n>;\n\n// When the input array is empty the constructed result type would be `{}`\n// because our mapped type would never run; but this doesn't represent the\n// semantics of the return value for that case, because it effectively means\n// \"any object\" and not \"empty object\". This can happen in 2 situations:\n// A union of tuples where one of the tuples doesn't have any item with the\n// groupable prop, or when the groupable prop has a value of `undefined` for\n// all items. The former is extra problematic because it would add `| {}` to the\n// result type which effectively cancels out all other parts of the union.\ntype FixEmptyObject<T> = IsNever<keyof T> extends true ? EmptyObject : T;\n\n// Group by can never return an empty tuple but our filtered arrays might not\n// represent that. We need to reshape the tuples so that they always have at\n// least one item in them.\ntype EnsureValuesAreNonEmpty<T extends Record<PropertyKey, IterableContainer>>\n = Simplify<\n Omit<T, PossiblyEmptyArrayKeys<T>>\n & BoundedPartial<CoercedNonEmptyValues<Pick<T, PossiblyEmptyArrayKeys<T>>>>\n >;\n\n// Go over the keys the object and return those that their value can accept an\n// empty array.\ntype PossiblyEmptyArrayKeys<T extends Record<PropertyKey, IterableContainer>>\n = keyof T extends infer Key extends unknown\n ? Key extends keyof T\n ? IsNonEmptyArray<T[Key]> extends true\n ? never\n : Key\n : never\n : never;\n\n// An array is non-empty if any of the fixed parts are non-empty.\ntype IsNonEmptyArray<T extends IterableContainer> = Or<\n IsNonEmptyFixedTuple<TupleParts<T>['required']>,\n IsNonEmptyFixedTuple<TupleParts<T>['suffix']>\n>;\n\n// A fixed tuple (one without optional or a rest element in it) is non-empty if\n// we can't extract the empty tuple from it.\ntype IsNonEmptyFixedTuple<T> = IsNever<Extract<T, readonly []>>;\n\n// We coerce the arbitrary array values to have a prefix of at least one item.\ntype CoercedNonEmptyValues<T extends Record<PropertyKey, IterableContainer>> = {\n [P in keyof T]: ArrayRequiredPrefix<T[P], 1>;\n};\n\n/**\n * Groups the elements of an array of objects based on the values of a\n * specified property of those objects. The result would contain a property for\n * each unique value of the specific property, with it's value being the input\n * array filtered to only items that have that property set to that value.\n * For any object where the property is missing, or if it's value is\n * `undefined` the item would be filtered out.\n *\n * The grouping property is enforced at the type level to exist in at least one\n * item and to never have a value that cannot be used as an object key (e.g. it\n * must be `PropertyKey | undefined`).\n *\n * The resulting arrays are filtered with the prop and it's value as a\n * type-guard, effectively narrowing the items in each output arrays. This\n * means that when the grouping property is the discriminator of a\n * discriminated union type each output array would contain just the subtype for\n * that value.\n *\n * If you need more control over the grouping you should use `groupBy` instead.\n *\n * @param data - The items to group.\n * @param prop - The property name to group by.\n * @signature\n * groupByProp(data, prop)\n * @example\n * const result = groupByProp(\n * // ^? { cat: [{ a: 'cat' }], dog: [{ a: 'dog' }] }\n * [{ a: 'cat' }, { a: 'dog' }] as const,\n * 'a',\n * );\n * @dataFirst\n * @category Array\n */\nexport function groupByProp<\n T extends IterableContainer,\n const Prop extends GroupableProps<T>,\n>(data: T, prop: Prop): GroupByProp<T, Prop>;\n\n/**\n * Groups the elements of an array of objects based on the values of a\n * specified property of those objects. The result would contain a property for\n * each unique value of the specific property, with it's value being the input\n * array filtered to only items that have that property set to that value.\n * For any object where the property is missing, or if it's value is\n * `undefined` the item would be filtered out.\n *\n * The grouping property is enforced at the type level to exist in at least one\n * item and to never have a value that cannot be used as an object key (e.g. it\n * must be `PropertyKey | undefined`).\n *\n * The resulting arrays are filtered with the prop and it's value as a\n * type-guard, effectively narrowing the items in each output arrays. This\n * means that when the grouping property is the discriminator of a\n * discriminated union type each output array would contain just the subtype for\n * that value.\n *\n * If you need more control over the grouping you should use `groupBy` instead.\n *\n * @param prop - The property name to group by.\n * @signature\n * groupByProp(prop)(data);\n * @example\n * const result = pipe(\n * // ^? { cat: [{ a: 'cat' }], dog: [{ a: 'dog' }] }\n * [{ a: 'cat' }, { a: 'dog' }] as const,\n * groupByProp('a'),\n * );\n * @dataLast\n * @category Array\n */\nexport function groupByProp<\n T extends IterableContainer,\n const Prop extends GroupableProps<T>,\n>(prop: Prop): (data: T) => GroupByProp<T, Prop>;\n\nexport function groupByProp(...args: ReadonlyArray<unknown>): unknown {\n return curry(groupByPropImplementation, args);\n}\n\nfunction groupByPropImplementation<\n T extends IterableContainer,\n Prop extends GroupableProps<T>,\n>(data: T, prop: Prop): GroupByProp<T, Prop> {\n const output: BoundedPartial<Record<AllPropValues<T, Prop>, Array<T[number]>>>\n = Object.create(null);\n\n for (const item of data) {\n const key = item?.[prop];\n if (key !== undefined) {\n // Once the prototype chain is fixed, it is safe to access the prop\n // directly without needing to check existence or types.\n const items = output[key];\n\n if (items === undefined) {\n // It is more performant to create a 1-element array over creating an\n // empty array and falling through to a unified the push. It is also\n // more performant to mutate the existing object over using spread to\n // continually create new objects on every unique key.\n // @ts-expect-error [ts7053] -- For the same reasons as mentioned above, TypeScript isn't inferring `key` correctly, and therefore is erroring when trying to access the output object using it.\n output[key] = [item];\n } else {\n // It is more performant to add the items to an existing array instead\n // of creating a new array via spreading every time we add an item to\n // it (e.g., `[...current, item]`).\n // @ts-expect-error [ts2339] -- And again here `items` is still `never`.\n items.push(item);\n }\n }\n }\n\n // Set the prototype as if we initialized our object as a normal object (e.g.\n // `{}`). Without this none of the built-in object methods like `toString`\n // would work on this object and it would act differently than expected.\n Object.setPrototypeOf(output, Object.prototype);\n\n // @ts-expect-error [ts2322] -- This is fine! We use a broader type for output while we build it because it more accurately represents the shape of the object *while it is being built*. TypeScript can't tell that we finished building the object so can't ensure that output matches the expected output at this point.\n return output;\n}\n"],"mappings":"kGAoLA,SAAgB,EAAY,GAAG,EAAuC,CACpE,OAAOA,EAAAA,MAAM,EAA2B,EAAK,CAG/C,SAAS,EAGP,EAAS,EAAkC,CAC3C,IAAM,EACF,OAAO,OAAO,KAAK,CAEvB,IAAK,IAAM,KAAQ,EAAM,CACvB,IAAM,EAAM,IAAO,GACnB,GAAI,IAAQ,IAAA,GAAW,CAGrB,IAAM,EAAQ,EAAO,GAEjB,IAAU,IAAA,GAMZ,EAAO,GAAO,CAAC,EAAK,CAMpB,EAAM,KAAK,EAAK,EAWtB,OAHA,OAAO,eAAe,EAAQ,OAAO,UAAU,CAGxC"}
1
+ {"version":3,"file":"group-by-prop.cjs","names":["curry"],"sources":["../src/group-by-prop.ts"],"sourcesContent":["import type {\n AllUnionFields,\n ConditionalKeys,\n EmptyObject,\n IsNever,\n Simplify,\n} from 'type-fest';\nimport type { ArrayRequiredPrefix } from './internal/types/array-required-prefix';\nimport type { BoundedPartial } from './internal/types/bounded-partial';\nimport type { FilteredArray } from './internal/types/filtered-array';\nimport type { IterableContainer } from './internal/types/iterable-container';\nimport type { TupleParts } from './internal/types/tuple-parts';\nimport { curry } from './curry';\n\ntype GroupByProp<T extends IterableContainer, Prop extends GroupableProps<T>>\n // Distribute unions.\n = T extends unknown\n ? FixEmptyObject<EnsureValuesAreNonEmpty<GroupByPropRaw<T, Prop>>>\n : never;\n\n// For each possible value of the prop we filter the input tuple with the prop\n// assigned to the value, e.g. `{ type: \"cat\" }`\ntype GroupByPropRaw<\n T extends IterableContainer,\n Prop extends GroupableProps<T>,\n> = {\n [Value in AllPropValues<T, Prop>]: FilteredArray<T, Record<Prop, Value>>;\n};\n\n// We can only group by props that only have values that could be used to key\n// an object (i.e. PropertyKey), or if they are undefined (which would filter\n// them out of the grouping).\ntype GroupableProps<T extends IterableContainer> = ConditionalKeys<\n ItemsSuperObject<T>,\n PropertyKey | undefined\n>;\n\n// The union of all possible values that the prop could have within the tuple.\ntype AllPropValues<\n T extends IterableContainer,\n Prop extends GroupableProps<T>,\n> = Extract<ItemsSuperObject<T>[Prop], PropertyKey>;\n\n// Creates a singular object type that all items in the tuple would extend. This\n// provides us a way to check, for each prop, what are all values it would\n// have within the tuple. We use this to map which props are candidates for\n// grouping, and when a prop is selected, the full list of values that would\n// exist in the output. For example:\n// `{ a: number, b: \"cat\", c: string } | { b: \"dog\", c: Date }` is groupable\n// by 'a' and 'b', but not 'c', and when selecting by 'b', the output would\n// have a prop for \"cat\" and a prop for \"dog\".\ntype ItemsSuperObject<T extends IterableContainer> = AllUnionFields<\n // If the input tuple contains optional elements they would add `undefined` to\n // T[number] (and could technically show up in the array itself). Because\n // undefined breaks AllUnionFields we need to remove it from the union. This\n // is OK because we handle this in the implementation too.\n Exclude<T[number], undefined>\n>;\n\n// When the input array is empty the constructed result type would be `{}`\n// because our mapped type would never run; but this doesn't represent the\n// semantics of the return value for that case, because it effectively means\n// \"any object\" and not \"empty object\". This can happen in 2 situations:\n// A union of tuples where one of the tuples doesn't have any item with the\n// groupable prop, or when the groupable prop has a value of `undefined` for\n// all items. The former is extra problematic because it would add `| {}` to the\n// result type which effectively cancels out all other parts of the union.\ntype FixEmptyObject<T> = IsNever<keyof T> extends true ? EmptyObject : T;\n\n// Group by can never return an empty tuple but our filtered arrays might not\n// represent that. We need to reshape the tuples so that they always have at\n// least one item in them.\ntype EnsureValuesAreNonEmpty<T extends Record<PropertyKey, IterableContainer>>\n = Simplify<\n Omit<T, PossiblyEmptyArrayKeys<T>>\n & BoundedPartial<CoercedNonEmptyValues<Pick<T, PossiblyEmptyArrayKeys<T>>>>\n >;\n\n// Go over the keys the object and return those that their value can accept an\n// empty array.\ntype PossiblyEmptyArrayKeys<T extends Record<PropertyKey, IterableContainer>>\n = keyof T extends infer Key extends unknown\n ? Key extends keyof T\n ? IsNonEmptyArray<T[Key]> extends true\n ? never\n : Key\n : never\n : never;\n\n// An array is non-empty if any of the fixed parts are non-empty.\ntype IsNonEmptyArray<T extends IterableContainer>\n = IsNonEmptyFixedTuple<TupleParts<T>['required']> extends true\n ? true\n : IsNonEmptyFixedTuple<TupleParts<T>['suffix']> extends true\n ? true\n : false;\n\n// A fixed tuple (one without optional or a rest element in it) is non-empty if\n// we can't extract the empty tuple from it.\ntype IsNonEmptyFixedTuple<T> = IsNever<Extract<T, readonly []>>;\n\n// We coerce the arbitrary array values to have a prefix of at least one item.\ntype CoercedNonEmptyValues<T extends Record<PropertyKey, IterableContainer>> = {\n [P in keyof T]: ArrayRequiredPrefix<T[P], 1>;\n};\n\n/**\n * Groups the elements of an array of objects based on the values of a\n * specified property of those objects. The result would contain a property for\n * each unique value of the specific property, with it's value being the input\n * array filtered to only items that have that property set to that value.\n * For any object where the property is missing, or if it's value is\n * `undefined` the item would be filtered out.\n *\n * The grouping property is enforced at the type level to exist in at least one\n * item and to never have a value that cannot be used as an object key (e.g. it\n * must be `PropertyKey | undefined`).\n *\n * The resulting arrays are filtered with the prop and it's value as a\n * type-guard, effectively narrowing the items in each output arrays. This\n * means that when the grouping property is the discriminator of a\n * discriminated union type each output array would contain just the subtype for\n * that value.\n *\n * If you need more control over the grouping you should use `groupBy` instead.\n *\n * @param data - The items to group.\n * @param prop - The property name to group by.\n * @signature\n * groupByProp(data, prop)\n * @example\n * const result = groupByProp(\n * // ^? { cat: [{ a: 'cat' }], dog: [{ a: 'dog' }] }\n * [{ a: 'cat' }, { a: 'dog' }] as const,\n * 'a',\n * );\n * @dataFirst\n * @category Array\n */\nexport function groupByProp<\n T extends IterableContainer,\n const Prop extends GroupableProps<T>,\n>(data: T, prop: Prop): GroupByProp<T, Prop>;\n\n/**\n * Groups the elements of an array of objects based on the values of a\n * specified property of those objects. The result would contain a property for\n * each unique value of the specific property, with it's value being the input\n * array filtered to only items that have that property set to that value.\n * For any object where the property is missing, or if it's value is\n * `undefined` the item would be filtered out.\n *\n * The grouping property is enforced at the type level to exist in at least one\n * item and to never have a value that cannot be used as an object key (e.g. it\n * must be `PropertyKey | undefined`).\n *\n * The resulting arrays are filtered with the prop and it's value as a\n * type-guard, effectively narrowing the items in each output arrays. This\n * means that when the grouping property is the discriminator of a\n * discriminated union type each output array would contain just the subtype for\n * that value.\n *\n * If you need more control over the grouping you should use `groupBy` instead.\n *\n * @param prop - The property name to group by.\n * @signature\n * groupByProp(prop)(data);\n * @example\n * const result = pipe(\n * // ^? { cat: [{ a: 'cat' }], dog: [{ a: 'dog' }] }\n * [{ a: 'cat' }, { a: 'dog' }] as const,\n * groupByProp('a'),\n * );\n * @dataLast\n * @category Array\n */\nexport function groupByProp<\n T extends IterableContainer,\n const Prop extends GroupableProps<T>,\n>(prop: Prop): (data: T) => GroupByProp<T, Prop>;\n\nexport function groupByProp(...args: ReadonlyArray<unknown>): unknown {\n return curry(groupByPropImplementation, args);\n}\n\nfunction groupByPropImplementation<\n T extends IterableContainer,\n Prop extends GroupableProps<T>,\n>(data: T, prop: Prop): GroupByProp<T, Prop> {\n const output: BoundedPartial<Record<AllPropValues<T, Prop>, Array<T[number]>>>\n = Object.create(null);\n\n for (const item of data) {\n const key = item?.[prop];\n if (key !== undefined) {\n // Once the prototype chain is fixed, it is safe to access the prop\n // directly without needing to check existence or types.\n const items = output[key];\n\n if (items === undefined) {\n // It is more performant to create a 1-element array over creating an\n // empty array and falling through to a unified the push. It is also\n // more performant to mutate the existing object over using spread to\n // continually create new objects on every unique key.\n // @ts-expect-error [ts7053] -- For the same reasons as mentioned above, TypeScript isn't inferring `key` correctly, and therefore is erroring when trying to access the output object using it.\n output[key] = [item];\n } else {\n // It is more performant to add the items to an existing array instead\n // of creating a new array via spreading every time we add an item to\n // it (e.g., `[...current, item]`).\n // @ts-expect-error [ts2339] -- And again here `items` is still `never`.\n items.push(item);\n }\n }\n }\n\n // Set the prototype as if we initialized our object as a normal object (e.g.\n // `{}`). Without this none of the built-in object methods like `toString`\n // would work on this object and it would act differently than expected.\n Object.setPrototypeOf(output, Object.prototype);\n\n // @ts-expect-error [ts2322] -- This is fine! We use a broader type for output while we build it because it more accurately represents the shape of the object *while it is being built*. TypeScript can't tell that we finished building the object so can't ensure that output matches the expected output at this point.\n return output;\n}\n"],"mappings":"kGAqLA,SAAgB,EAAY,GAAG,EAAuC,CACpE,OAAOA,EAAAA,MAAM,EAA2B,CAAI,CAC9C,CAEA,SAAS,EAGP,EAAS,EAAkC,CAC3C,IAAM,EACF,OAAO,OAAO,IAAI,EAEtB,IAAK,IAAM,KAAQ,EAAM,CACvB,IAAM,EAAM,IAAO,GACnB,GAAI,IAAQ,IAAA,GAAW,CAGrB,IAAM,EAAQ,EAAO,GAEjB,IAAU,IAAA,GAMZ,EAAO,GAAO,CAAC,CAAI,EAMnB,EAAM,KAAK,CAAI,CAEnB,CACF,CAQA,OAHA,OAAO,eAAe,EAAQ,OAAO,SAAS,EAGvC,CACT"}
@@ -1 +1 @@
1
- {"version":3,"file":"group-by-prop.js","names":[],"sources":["../src/group-by-prop.ts"],"sourcesContent":["import type {\n AllUnionFields,\n ConditionalKeys,\n EmptyObject,\n IsNever,\n Or,\n Simplify,\n} from 'type-fest';\nimport type { ArrayRequiredPrefix } from './internal/types/array-required-prefix';\nimport type { BoundedPartial } from './internal/types/bounded-partial';\nimport type { FilteredArray } from './internal/types/filtered-array';\nimport type { IterableContainer } from './internal/types/iterable-container';\nimport type { TupleParts } from './internal/types/tuple-parts';\nimport { curry } from './curry';\n\ntype GroupByProp<T extends IterableContainer, Prop extends GroupableProps<T>>\n // Distribute unions.\n = T extends unknown\n ? FixEmptyObject<EnsureValuesAreNonEmpty<GroupByPropRaw<T, Prop>>>\n : never;\n\n// For each possible value of the prop we filter the input tuple with the prop\n// assigned to the value, e.g. `{ type: \"cat\" }`\ntype GroupByPropRaw<\n T extends IterableContainer,\n Prop extends GroupableProps<T>,\n> = {\n [Value in AllPropValues<T, Prop>]: FilteredArray<T, Record<Prop, Value>>;\n};\n\n// We can only group by props that only have values that could be used to key\n// an object (i.e. PropertyKey), or if they are undefined (which would filter\n// them out of the grouping).\ntype GroupableProps<T extends IterableContainer> = ConditionalKeys<\n ItemsSuperObject<T>,\n PropertyKey | undefined\n>;\n\n// The union of all possible values that the prop could have within the tuple.\ntype AllPropValues<\n T extends IterableContainer,\n Prop extends GroupableProps<T>,\n> = Extract<ItemsSuperObject<T>[Prop], PropertyKey>;\n\n// Creates a singular object type that all items in the tuple would extend. This\n// provides us a way to check, for each prop, what are all values it would\n// have within the tuple. We use this to map which props are candidates for\n// grouping, and when a prop is selected, the full list of values that would\n// exist in the output. For example:\n// `{ a: number, b: \"cat\", c: string } | { b: \"dog\", c: Date }` is groupable\n// by 'a' and 'b', but not 'c', and when selecting by 'b', the output would\n// have a prop for \"cat\" and a prop for \"dog\".\ntype ItemsSuperObject<T extends IterableContainer> = AllUnionFields<\n // If the input tuple contains optional elements they would add `undefined` to\n // T[number] (and could technically show up in the array itself). Because\n // undefined breaks AllUnionFields we need to remove it from the union. This\n // is OK because we handle this in the implementation too.\n Exclude<T[number], undefined>\n>;\n\n// When the input array is empty the constructed result type would be `{}`\n// because our mapped type would never run; but this doesn't represent the\n// semantics of the return value for that case, because it effectively means\n// \"any object\" and not \"empty object\". This can happen in 2 situations:\n// A union of tuples where one of the tuples doesn't have any item with the\n// groupable prop, or when the groupable prop has a value of `undefined` for\n// all items. The former is extra problematic because it would add `| {}` to the\n// result type which effectively cancels out all other parts of the union.\ntype FixEmptyObject<T> = IsNever<keyof T> extends true ? EmptyObject : T;\n\n// Group by can never return an empty tuple but our filtered arrays might not\n// represent that. We need to reshape the tuples so that they always have at\n// least one item in them.\ntype EnsureValuesAreNonEmpty<T extends Record<PropertyKey, IterableContainer>>\n = Simplify<\n Omit<T, PossiblyEmptyArrayKeys<T>>\n & BoundedPartial<CoercedNonEmptyValues<Pick<T, PossiblyEmptyArrayKeys<T>>>>\n >;\n\n// Go over the keys the object and return those that their value can accept an\n// empty array.\ntype PossiblyEmptyArrayKeys<T extends Record<PropertyKey, IterableContainer>>\n = keyof T extends infer Key extends unknown\n ? Key extends keyof T\n ? IsNonEmptyArray<T[Key]> extends true\n ? never\n : Key\n : never\n : never;\n\n// An array is non-empty if any of the fixed parts are non-empty.\ntype IsNonEmptyArray<T extends IterableContainer> = Or<\n IsNonEmptyFixedTuple<TupleParts<T>['required']>,\n IsNonEmptyFixedTuple<TupleParts<T>['suffix']>\n>;\n\n// A fixed tuple (one without optional or a rest element in it) is non-empty if\n// we can't extract the empty tuple from it.\ntype IsNonEmptyFixedTuple<T> = IsNever<Extract<T, readonly []>>;\n\n// We coerce the arbitrary array values to have a prefix of at least one item.\ntype CoercedNonEmptyValues<T extends Record<PropertyKey, IterableContainer>> = {\n [P in keyof T]: ArrayRequiredPrefix<T[P], 1>;\n};\n\n/**\n * Groups the elements of an array of objects based on the values of a\n * specified property of those objects. The result would contain a property for\n * each unique value of the specific property, with it's value being the input\n * array filtered to only items that have that property set to that value.\n * For any object where the property is missing, or if it's value is\n * `undefined` the item would be filtered out.\n *\n * The grouping property is enforced at the type level to exist in at least one\n * item and to never have a value that cannot be used as an object key (e.g. it\n * must be `PropertyKey | undefined`).\n *\n * The resulting arrays are filtered with the prop and it's value as a\n * type-guard, effectively narrowing the items in each output arrays. This\n * means that when the grouping property is the discriminator of a\n * discriminated union type each output array would contain just the subtype for\n * that value.\n *\n * If you need more control over the grouping you should use `groupBy` instead.\n *\n * @param data - The items to group.\n * @param prop - The property name to group by.\n * @signature\n * groupByProp(data, prop)\n * @example\n * const result = groupByProp(\n * // ^? { cat: [{ a: 'cat' }], dog: [{ a: 'dog' }] }\n * [{ a: 'cat' }, { a: 'dog' }] as const,\n * 'a',\n * );\n * @dataFirst\n * @category Array\n */\nexport function groupByProp<\n T extends IterableContainer,\n const Prop extends GroupableProps<T>,\n>(data: T, prop: Prop): GroupByProp<T, Prop>;\n\n/**\n * Groups the elements of an array of objects based on the values of a\n * specified property of those objects. The result would contain a property for\n * each unique value of the specific property, with it's value being the input\n * array filtered to only items that have that property set to that value.\n * For any object where the property is missing, or if it's value is\n * `undefined` the item would be filtered out.\n *\n * The grouping property is enforced at the type level to exist in at least one\n * item and to never have a value that cannot be used as an object key (e.g. it\n * must be `PropertyKey | undefined`).\n *\n * The resulting arrays are filtered with the prop and it's value as a\n * type-guard, effectively narrowing the items in each output arrays. This\n * means that when the grouping property is the discriminator of a\n * discriminated union type each output array would contain just the subtype for\n * that value.\n *\n * If you need more control over the grouping you should use `groupBy` instead.\n *\n * @param prop - The property name to group by.\n * @signature\n * groupByProp(prop)(data);\n * @example\n * const result = pipe(\n * // ^? { cat: [{ a: 'cat' }], dog: [{ a: 'dog' }] }\n * [{ a: 'cat' }, { a: 'dog' }] as const,\n * groupByProp('a'),\n * );\n * @dataLast\n * @category Array\n */\nexport function groupByProp<\n T extends IterableContainer,\n const Prop extends GroupableProps<T>,\n>(prop: Prop): (data: T) => GroupByProp<T, Prop>;\n\nexport function groupByProp(...args: ReadonlyArray<unknown>): unknown {\n return curry(groupByPropImplementation, args);\n}\n\nfunction groupByPropImplementation<\n T extends IterableContainer,\n Prop extends GroupableProps<T>,\n>(data: T, prop: Prop): GroupByProp<T, Prop> {\n const output: BoundedPartial<Record<AllPropValues<T, Prop>, Array<T[number]>>>\n = Object.create(null);\n\n for (const item of data) {\n const key = item?.[prop];\n if (key !== undefined) {\n // Once the prototype chain is fixed, it is safe to access the prop\n // directly without needing to check existence or types.\n const items = output[key];\n\n if (items === undefined) {\n // It is more performant to create a 1-element array over creating an\n // empty array and falling through to a unified the push. It is also\n // more performant to mutate the existing object over using spread to\n // continually create new objects on every unique key.\n // @ts-expect-error [ts7053] -- For the same reasons as mentioned above, TypeScript isn't inferring `key` correctly, and therefore is erroring when trying to access the output object using it.\n output[key] = [item];\n } else {\n // It is more performant to add the items to an existing array instead\n // of creating a new array via spreading every time we add an item to\n // it (e.g., `[...current, item]`).\n // @ts-expect-error [ts2339] -- And again here `items` is still `never`.\n items.push(item);\n }\n }\n }\n\n // Set the prototype as if we initialized our object as a normal object (e.g.\n // `{}`). Without this none of the built-in object methods like `toString`\n // would work on this object and it would act differently than expected.\n Object.setPrototypeOf(output, Object.prototype);\n\n // @ts-expect-error [ts2322] -- This is fine! We use a broader type for output while we build it because it more accurately represents the shape of the object *while it is being built*. TypeScript can't tell that we finished building the object so can't ensure that output matches the expected output at this point.\n return output;\n}\n"],"mappings":"mCAoLA,SAAgB,EAAY,GAAG,EAAuC,CACpE,OAAO,EAAM,EAA2B,EAAK,CAG/C,SAAS,EAGP,EAAS,EAAkC,CAC3C,IAAM,EACF,OAAO,OAAO,KAAK,CAEvB,IAAK,IAAM,KAAQ,EAAM,CACvB,IAAM,EAAM,IAAO,GACnB,GAAI,IAAQ,IAAA,GAAW,CAGrB,IAAM,EAAQ,EAAO,GAEjB,IAAU,IAAA,GAMZ,EAAO,GAAO,CAAC,EAAK,CAMpB,EAAM,KAAK,EAAK,EAWtB,OAHA,OAAO,eAAe,EAAQ,OAAO,UAAU,CAGxC"}
1
+ {"version":3,"file":"group-by-prop.js","names":[],"sources":["../src/group-by-prop.ts"],"sourcesContent":["import type {\n AllUnionFields,\n ConditionalKeys,\n EmptyObject,\n IsNever,\n Simplify,\n} from 'type-fest';\nimport type { ArrayRequiredPrefix } from './internal/types/array-required-prefix';\nimport type { BoundedPartial } from './internal/types/bounded-partial';\nimport type { FilteredArray } from './internal/types/filtered-array';\nimport type { IterableContainer } from './internal/types/iterable-container';\nimport type { TupleParts } from './internal/types/tuple-parts';\nimport { curry } from './curry';\n\ntype GroupByProp<T extends IterableContainer, Prop extends GroupableProps<T>>\n // Distribute unions.\n = T extends unknown\n ? FixEmptyObject<EnsureValuesAreNonEmpty<GroupByPropRaw<T, Prop>>>\n : never;\n\n// For each possible value of the prop we filter the input tuple with the prop\n// assigned to the value, e.g. `{ type: \"cat\" }`\ntype GroupByPropRaw<\n T extends IterableContainer,\n Prop extends GroupableProps<T>,\n> = {\n [Value in AllPropValues<T, Prop>]: FilteredArray<T, Record<Prop, Value>>;\n};\n\n// We can only group by props that only have values that could be used to key\n// an object (i.e. PropertyKey), or if they are undefined (which would filter\n// them out of the grouping).\ntype GroupableProps<T extends IterableContainer> = ConditionalKeys<\n ItemsSuperObject<T>,\n PropertyKey | undefined\n>;\n\n// The union of all possible values that the prop could have within the tuple.\ntype AllPropValues<\n T extends IterableContainer,\n Prop extends GroupableProps<T>,\n> = Extract<ItemsSuperObject<T>[Prop], PropertyKey>;\n\n// Creates a singular object type that all items in the tuple would extend. This\n// provides us a way to check, for each prop, what are all values it would\n// have within the tuple. We use this to map which props are candidates for\n// grouping, and when a prop is selected, the full list of values that would\n// exist in the output. For example:\n// `{ a: number, b: \"cat\", c: string } | { b: \"dog\", c: Date }` is groupable\n// by 'a' and 'b', but not 'c', and when selecting by 'b', the output would\n// have a prop for \"cat\" and a prop for \"dog\".\ntype ItemsSuperObject<T extends IterableContainer> = AllUnionFields<\n // If the input tuple contains optional elements they would add `undefined` to\n // T[number] (and could technically show up in the array itself). Because\n // undefined breaks AllUnionFields we need to remove it from the union. This\n // is OK because we handle this in the implementation too.\n Exclude<T[number], undefined>\n>;\n\n// When the input array is empty the constructed result type would be `{}`\n// because our mapped type would never run; but this doesn't represent the\n// semantics of the return value for that case, because it effectively means\n// \"any object\" and not \"empty object\". This can happen in 2 situations:\n// A union of tuples where one of the tuples doesn't have any item with the\n// groupable prop, or when the groupable prop has a value of `undefined` for\n// all items. The former is extra problematic because it would add `| {}` to the\n// result type which effectively cancels out all other parts of the union.\ntype FixEmptyObject<T> = IsNever<keyof T> extends true ? EmptyObject : T;\n\n// Group by can never return an empty tuple but our filtered arrays might not\n// represent that. We need to reshape the tuples so that they always have at\n// least one item in them.\ntype EnsureValuesAreNonEmpty<T extends Record<PropertyKey, IterableContainer>>\n = Simplify<\n Omit<T, PossiblyEmptyArrayKeys<T>>\n & BoundedPartial<CoercedNonEmptyValues<Pick<T, PossiblyEmptyArrayKeys<T>>>>\n >;\n\n// Go over the keys the object and return those that their value can accept an\n// empty array.\ntype PossiblyEmptyArrayKeys<T extends Record<PropertyKey, IterableContainer>>\n = keyof T extends infer Key extends unknown\n ? Key extends keyof T\n ? IsNonEmptyArray<T[Key]> extends true\n ? never\n : Key\n : never\n : never;\n\n// An array is non-empty if any of the fixed parts are non-empty.\ntype IsNonEmptyArray<T extends IterableContainer>\n = IsNonEmptyFixedTuple<TupleParts<T>['required']> extends true\n ? true\n : IsNonEmptyFixedTuple<TupleParts<T>['suffix']> extends true\n ? true\n : false;\n\n// A fixed tuple (one without optional or a rest element in it) is non-empty if\n// we can't extract the empty tuple from it.\ntype IsNonEmptyFixedTuple<T> = IsNever<Extract<T, readonly []>>;\n\n// We coerce the arbitrary array values to have a prefix of at least one item.\ntype CoercedNonEmptyValues<T extends Record<PropertyKey, IterableContainer>> = {\n [P in keyof T]: ArrayRequiredPrefix<T[P], 1>;\n};\n\n/**\n * Groups the elements of an array of objects based on the values of a\n * specified property of those objects. The result would contain a property for\n * each unique value of the specific property, with it's value being the input\n * array filtered to only items that have that property set to that value.\n * For any object where the property is missing, or if it's value is\n * `undefined` the item would be filtered out.\n *\n * The grouping property is enforced at the type level to exist in at least one\n * item and to never have a value that cannot be used as an object key (e.g. it\n * must be `PropertyKey | undefined`).\n *\n * The resulting arrays are filtered with the prop and it's value as a\n * type-guard, effectively narrowing the items in each output arrays. This\n * means that when the grouping property is the discriminator of a\n * discriminated union type each output array would contain just the subtype for\n * that value.\n *\n * If you need more control over the grouping you should use `groupBy` instead.\n *\n * @param data - The items to group.\n * @param prop - The property name to group by.\n * @signature\n * groupByProp(data, prop)\n * @example\n * const result = groupByProp(\n * // ^? { cat: [{ a: 'cat' }], dog: [{ a: 'dog' }] }\n * [{ a: 'cat' }, { a: 'dog' }] as const,\n * 'a',\n * );\n * @dataFirst\n * @category Array\n */\nexport function groupByProp<\n T extends IterableContainer,\n const Prop extends GroupableProps<T>,\n>(data: T, prop: Prop): GroupByProp<T, Prop>;\n\n/**\n * Groups the elements of an array of objects based on the values of a\n * specified property of those objects. The result would contain a property for\n * each unique value of the specific property, with it's value being the input\n * array filtered to only items that have that property set to that value.\n * For any object where the property is missing, or if it's value is\n * `undefined` the item would be filtered out.\n *\n * The grouping property is enforced at the type level to exist in at least one\n * item and to never have a value that cannot be used as an object key (e.g. it\n * must be `PropertyKey | undefined`).\n *\n * The resulting arrays are filtered with the prop and it's value as a\n * type-guard, effectively narrowing the items in each output arrays. This\n * means that when the grouping property is the discriminator of a\n * discriminated union type each output array would contain just the subtype for\n * that value.\n *\n * If you need more control over the grouping you should use `groupBy` instead.\n *\n * @param prop - The property name to group by.\n * @signature\n * groupByProp(prop)(data);\n * @example\n * const result = pipe(\n * // ^? { cat: [{ a: 'cat' }], dog: [{ a: 'dog' }] }\n * [{ a: 'cat' }, { a: 'dog' }] as const,\n * groupByProp('a'),\n * );\n * @dataLast\n * @category Array\n */\nexport function groupByProp<\n T extends IterableContainer,\n const Prop extends GroupableProps<T>,\n>(prop: Prop): (data: T) => GroupByProp<T, Prop>;\n\nexport function groupByProp(...args: ReadonlyArray<unknown>): unknown {\n return curry(groupByPropImplementation, args);\n}\n\nfunction groupByPropImplementation<\n T extends IterableContainer,\n Prop extends GroupableProps<T>,\n>(data: T, prop: Prop): GroupByProp<T, Prop> {\n const output: BoundedPartial<Record<AllPropValues<T, Prop>, Array<T[number]>>>\n = Object.create(null);\n\n for (const item of data) {\n const key = item?.[prop];\n if (key !== undefined) {\n // Once the prototype chain is fixed, it is safe to access the prop\n // directly without needing to check existence or types.\n const items = output[key];\n\n if (items === undefined) {\n // It is more performant to create a 1-element array over creating an\n // empty array and falling through to a unified the push. It is also\n // more performant to mutate the existing object over using spread to\n // continually create new objects on every unique key.\n // @ts-expect-error [ts7053] -- For the same reasons as mentioned above, TypeScript isn't inferring `key` correctly, and therefore is erroring when trying to access the output object using it.\n output[key] = [item];\n } else {\n // It is more performant to add the items to an existing array instead\n // of creating a new array via spreading every time we add an item to\n // it (e.g., `[...current, item]`).\n // @ts-expect-error [ts2339] -- And again here `items` is still `never`.\n items.push(item);\n }\n }\n }\n\n // Set the prototype as if we initialized our object as a normal object (e.g.\n // `{}`). Without this none of the built-in object methods like `toString`\n // would work on this object and it would act differently than expected.\n Object.setPrototypeOf(output, Object.prototype);\n\n // @ts-expect-error [ts2322] -- This is fine! We use a broader type for output while we build it because it more accurately represents the shape of the object *while it is being built*. TypeScript can't tell that we finished building the object so can't ensure that output matches the expected output at this point.\n return output;\n}\n"],"mappings":"mCAqLA,SAAgB,EAAY,GAAG,EAAuC,CACpE,OAAO,EAAM,EAA2B,CAAI,CAC9C,CAEA,SAAS,EAGP,EAAS,EAAkC,CAC3C,IAAM,EACF,OAAO,OAAO,IAAI,EAEtB,IAAK,IAAM,KAAQ,EAAM,CACvB,IAAM,EAAM,IAAO,GACnB,GAAI,IAAQ,IAAA,GAAW,CAGrB,IAAM,EAAQ,EAAO,GAEjB,IAAU,IAAA,GAMZ,EAAO,GAAO,CAAC,CAAI,EAMnB,EAAM,KAAK,CAAI,CAEnB,CACF,CAQA,OAHA,OAAO,eAAe,EAAQ,OAAO,SAAS,EAGvC,CACT"}
package/dist/group-by.cjs CHANGED
@@ -1,2 +1,2 @@
1
- Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});const e=require(`./curry.cjs`);function t(...t){return e.curry(n,t)}function n(e,t){let n=Object.create(null);for(let r=0;r<e.length;r++){let i=e[r],a=t(i,r,e);if(a!==void 0){let e=n[a];e===void 0?n[a]=[i]:e.push(i)}}return Object.setPrototypeOf(n,Object.prototype),n}exports.groupBy=t;
1
+ Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});const e=require("./curry.cjs");function t(...t){return e.curry(n,t)}function n(e,t){let n=Object.create(null);for(let r=0;r<e.length;r++){let i=e[r],a=t(i,r,e);if(a!==void 0){let e=n[a];e===void 0?n[a]=[i]:e.push(i)}}return Object.setPrototypeOf(n,Object.prototype),n}exports.groupBy=t;
2
2
  //# sourceMappingURL=group-by.cjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"group-by.cjs","names":["curry"],"sources":["../src/group-by.ts"],"sourcesContent":["import type { BoundedPartial } from './internal/types/bounded-partial';\nimport type { NonEmptyArray } from './internal/types/non-empty-array';\nimport { curry } from './curry';\n\n/**\n * Groups the elements of a given iterable according to the string values\n * returned by a provided callback function. The returned object has separate\n * properties for each group, containing arrays with the elements in the group.\n * Unlike the built in `Object.groupBy` this function also allows the callback to\n * return `undefined` in order to exclude the item from being added to any\n * group.\n *\n * If you are grouping objects by a property of theirs (e.g.\n * `groupBy(data, ({ myProp }) => myProp)` or `groupBy(data, prop('myProp'))`)\n * consider using `groupByProp` (e.g. `groupByProp(data, 'myProp')`) instead,\n * as it would provide better typing.\n *\n * @param data - The items to group.\n * @param callbackfn - A function to execute for each element in the iterable.\n * It should return a value indicating the group of the current element, or\n * `undefined` when the item should be excluded from any group.\n * @returns An object with properties for all groups, each assigned to an array\n * containing the elements of the associated group.\n * @signature\n * groupBy(data, callbackfn)\n * @example\n * groupBy([{a: 'cat'}, {a: 'dog'}] as const, prop('a')) // => {cat: [{a: 'cat'}], dog: [{a: 'dog'}]}\n * groupBy([0, 1], x => x % 2 === 0 ? 'even' : undefined) // => {even: [0]}\n * @dataFirst\n * @category Array\n */\nexport function groupBy<T, Key extends PropertyKey = PropertyKey>(\n data: ReadonlyArray<T>,\n callbackfn: (value: T, index: number, data: ReadonlyArray<T>) => Key | undefined,\n): BoundedPartial<Record<Key, NonEmptyArray<T>>>;\n\n/**\n * Groups the elements of a given iterable according to the string values\n * returned by a provided callback function. The returned object has separate\n * properties for each group, containing arrays with the elements in the group.\n * Unlike the built in `Object.groupBy` this function also allows the callback to\n * return `undefined` in order to exclude the item from being added to any\n * group.\n *\n * If you are grouping objects by a property of theirs (e.g.\n * `groupBy(data, ({ myProp }) => myProp)` or `groupBy(data, prop('myProp'))`)\n * consider using `groupByProp` (e.g. `groupByProp(data, 'myProp')`) instead,\n * as it would provide better typing.\n *\n * @param callbackfn - A function to execute for each element in the iterable.\n * It should return a value indicating the group of the current element, or\n * `undefined` when the item should be excluded from any group.\n * @returns An object with properties for all groups, each assigned to an array\n * containing the elements of the associated group.\n * @signature\n * groupBy(callbackfn)(data);\n * @example\n * pipe(\n * [{a: 'cat'}, {a: 'dog'}] as const,\n * groupBy(prop('a')),\n * ); // => {cat: [{a: 'cat'}], dog: [{a: 'dog'}]}\n * pipe(\n * [0, 1],\n * groupBy(x => x % 2 === 0 ? 'even' : undefined),\n * ); // => {even: [0]}\n * @dataLast\n * @category Array\n */\nexport function groupBy<T, Key extends PropertyKey = PropertyKey>(\n callbackfn: (value: T, index: number, data: ReadonlyArray<T>) => Key | undefined,\n): (items: ReadonlyArray<T>) => BoundedPartial<Record<Key, NonEmptyArray<T>>>;\n\nexport function groupBy(...args: ReadonlyArray<unknown>): unknown {\n return curry(groupByImplementation, args);\n}\n\nfunction groupByImplementation<T, Key extends PropertyKey = PropertyKey>(data: ReadonlyArray<T>, callbackfn: (value: T, index: number, data: ReadonlyArray<T>) => Key | undefined): BoundedPartial<Record<Key, NonEmptyArray<T>>> {\n const output: BoundedPartial<Record<Key, NonEmptyArray<T>>>\n = Object.create(null);\n\n for (let index = 0; index < data.length; index++) {\n // Accessing the object directly instead of via an iterator on the `entries` showed significant performance benefits while benchmarking.\n const item = data[index];\n\n // @ts-expect-error [ts2345] -- TypeScript is not able to infer that the index wouldn't overflow the array and that it shouldn't add `undefined` to the type. We don't want to use the `!` operator here because it's semantics are different because it changes the type of `item` to `NonNullable<T>` which is inaccurate because T itself could have `undefined` as a valid value.\n const key = callbackfn(item, index, data);\n if (key !== undefined) {\n // Once the prototype chain is fixed, it is safe to access the prop directly without needing to check existence or types.\n const items = output[key];\n\n if (items === undefined) {\n // It is more performant to create a 1-element array over creating an empty array and falling through to a unified the push. It is also more performant to mutate the existing object over using spread to continually create new objects on every unique key.\n // @ts-expect-error [ts2322] -- In addition to the typing issue we have for `item`, this line also creates a typing issue for the whole object, as TypeScript is having a hard time inferring what values could be adding to the object.\n output[key] = [item];\n } else {\n // It is more performant to add the items to an existing array over continually creating a new array every time we add an item to it.\n // @ts-expect-error [ts2345] -- See comment above about the effective typing for `item` here.\n items.push(item);\n }\n }\n }\n\n // Set the prototype as if we initialized our object as a normal object (e.g. `{}`). Without this none of the built-in object methods like `toString` would work on this object and it would act differently than expected.\n Object.setPrototypeOf(output, Object.prototype);\n\n return output;\n}\n"],"mappings":"kGAwEA,SAAgB,EAAQ,GAAG,EAAuC,CAChE,OAAOA,EAAAA,MAAM,EAAuB,EAAK,CAG3C,SAAS,EAAgE,EAAwB,EAAiI,CAChO,IAAM,EACF,OAAO,OAAO,KAAK,CAEvB,IAAK,IAAI,EAAQ,EAAG,EAAQ,EAAK,OAAQ,IAAS,CAEhD,IAAM,EAAO,EAAK,GAGZ,EAAM,EAAW,EAAM,EAAO,EAAK,CACzC,GAAI,IAAQ,IAAA,GAAW,CAErB,IAAM,EAAQ,EAAO,GAEjB,IAAU,IAAA,GAGZ,EAAO,GAAO,CAAC,EAAK,CAIpB,EAAM,KAAK,EAAK,EAQtB,OAFA,OAAO,eAAe,EAAQ,OAAO,UAAU,CAExC"}
1
+ {"version":3,"file":"group-by.cjs","names":["curry"],"sources":["../src/group-by.ts"],"sourcesContent":["import type { BoundedPartial } from './internal/types/bounded-partial';\nimport type { NonEmptyArray } from './internal/types/non-empty-array';\nimport { curry } from './curry';\n\n/**\n * Groups the elements of a given iterable according to the string values\n * returned by a provided callback function. The returned object has separate\n * properties for each group, containing arrays with the elements in the group.\n * Unlike the built in `Object.groupBy` this function also allows the callback to\n * return `undefined` in order to exclude the item from being added to any\n * group.\n *\n * If you are grouping objects by a property of theirs (e.g.\n * `groupBy(data, ({ myProp }) => myProp)` or `groupBy(data, prop('myProp'))`)\n * consider using `groupByProp` (e.g. `groupByProp(data, 'myProp')`) instead,\n * as it would provide better typing.\n *\n * @param data - The items to group.\n * @param callbackfn - A function to execute for each element in the iterable.\n * It should return a value indicating the group of the current element, or\n * `undefined` when the item should be excluded from any group.\n * @returns An object with properties for all groups, each assigned to an array\n * containing the elements of the associated group.\n * @signature\n * groupBy(data, callbackfn)\n * @example\n * groupBy([{a: 'cat'}, {a: 'dog'}] as const, prop('a')) // => {cat: [{a: 'cat'}], dog: [{a: 'dog'}]}\n * groupBy([0, 1], x => x % 2 === 0 ? 'even' : undefined) // => {even: [0]}\n * @dataFirst\n * @category Array\n */\nexport function groupBy<T, Key extends PropertyKey = PropertyKey>(\n data: ReadonlyArray<T>,\n callbackfn: (value: T, index: number, data: ReadonlyArray<T>) => Key | undefined,\n): BoundedPartial<Record<Key, NonEmptyArray<T>>>;\n\n/**\n * Groups the elements of a given iterable according to the string values\n * returned by a provided callback function. The returned object has separate\n * properties for each group, containing arrays with the elements in the group.\n * Unlike the built in `Object.groupBy` this function also allows the callback to\n * return `undefined` in order to exclude the item from being added to any\n * group.\n *\n * If you are grouping objects by a property of theirs (e.g.\n * `groupBy(data, ({ myProp }) => myProp)` or `groupBy(data, prop('myProp'))`)\n * consider using `groupByProp` (e.g. `groupByProp(data, 'myProp')`) instead,\n * as it would provide better typing.\n *\n * @param callbackfn - A function to execute for each element in the iterable.\n * It should return a value indicating the group of the current element, or\n * `undefined` when the item should be excluded from any group.\n * @returns An object with properties for all groups, each assigned to an array\n * containing the elements of the associated group.\n * @signature\n * groupBy(callbackfn)(data);\n * @example\n * pipe(\n * [{a: 'cat'}, {a: 'dog'}] as const,\n * groupBy(prop('a')),\n * ); // => {cat: [{a: 'cat'}], dog: [{a: 'dog'}]}\n * pipe(\n * [0, 1],\n * groupBy(x => x % 2 === 0 ? 'even' : undefined),\n * ); // => {even: [0]}\n * @dataLast\n * @category Array\n */\nexport function groupBy<T, Key extends PropertyKey = PropertyKey>(\n callbackfn: (value: T, index: number, data: ReadonlyArray<T>) => Key | undefined,\n): (items: ReadonlyArray<T>) => BoundedPartial<Record<Key, NonEmptyArray<T>>>;\n\nexport function groupBy(...args: ReadonlyArray<unknown>): unknown {\n return curry(groupByImplementation, args);\n}\n\nfunction groupByImplementation<T, Key extends PropertyKey = PropertyKey>(data: ReadonlyArray<T>, callbackfn: (value: T, index: number, data: ReadonlyArray<T>) => Key | undefined): BoundedPartial<Record<Key, NonEmptyArray<T>>> {\n const output: BoundedPartial<Record<Key, NonEmptyArray<T>>>\n = Object.create(null);\n\n for (let index = 0; index < data.length; index++) {\n // Accessing the object directly instead of via an iterator on the `entries` showed significant performance benefits while benchmarking.\n const item = data[index];\n\n // @ts-expect-error [ts2345] -- TypeScript is not able to infer that the index wouldn't overflow the array and that it shouldn't add `undefined` to the type. We don't want to use the `!` operator here because it's semantics are different because it changes the type of `item` to `NonNullable<T>` which is inaccurate because T itself could have `undefined` as a valid value.\n const key = callbackfn(item, index, data);\n if (key !== undefined) {\n // Once the prototype chain is fixed, it is safe to access the prop directly without needing to check existence or types.\n const items = output[key];\n\n if (items === undefined) {\n // It is more performant to create a 1-element array over creating an empty array and falling through to a unified the push. It is also more performant to mutate the existing object over using spread to continually create new objects on every unique key.\n // @ts-expect-error [ts2322] -- In addition to the typing issue we have for `item`, this line also creates a typing issue for the whole object, as TypeScript is having a hard time inferring what values could be adding to the object.\n output[key] = [item];\n } else {\n // It is more performant to add the items to an existing array over continually creating a new array every time we add an item to it.\n // @ts-expect-error [ts2345] -- See comment above about the effective typing for `item` here.\n items.push(item);\n }\n }\n }\n\n // Set the prototype as if we initialized our object as a normal object (e.g. `{}`). Without this none of the built-in object methods like `toString` would work on this object and it would act differently than expected.\n Object.setPrototypeOf(output, Object.prototype);\n\n return output;\n}\n"],"mappings":"kGAwEA,SAAgB,EAAQ,GAAG,EAAuC,CAChE,OAAOA,EAAAA,MAAM,EAAuB,CAAI,CAC1C,CAEA,SAAS,EAAgE,EAAwB,EAAiI,CAChO,IAAM,EACF,OAAO,OAAO,IAAI,EAEtB,IAAK,IAAI,EAAQ,EAAG,EAAQ,EAAK,OAAQ,IAAS,CAEhD,IAAM,EAAO,EAAK,GAGZ,EAAM,EAAW,EAAM,EAAO,CAAI,EACxC,GAAI,IAAQ,IAAA,GAAW,CAErB,IAAM,EAAQ,EAAO,GAEjB,IAAU,IAAA,GAGZ,EAAO,GAAO,CAAC,CAAI,EAInB,EAAM,KAAK,CAAI,CAEnB,CACF,CAKA,OAFA,OAAO,eAAe,EAAQ,OAAO,SAAS,EAEvC,CACT"}
@@ -1 +1 @@
1
- {"version":3,"file":"group-by.js","names":[],"sources":["../src/group-by.ts"],"sourcesContent":["import type { BoundedPartial } from './internal/types/bounded-partial';\nimport type { NonEmptyArray } from './internal/types/non-empty-array';\nimport { curry } from './curry';\n\n/**\n * Groups the elements of a given iterable according to the string values\n * returned by a provided callback function. The returned object has separate\n * properties for each group, containing arrays with the elements in the group.\n * Unlike the built in `Object.groupBy` this function also allows the callback to\n * return `undefined` in order to exclude the item from being added to any\n * group.\n *\n * If you are grouping objects by a property of theirs (e.g.\n * `groupBy(data, ({ myProp }) => myProp)` or `groupBy(data, prop('myProp'))`)\n * consider using `groupByProp` (e.g. `groupByProp(data, 'myProp')`) instead,\n * as it would provide better typing.\n *\n * @param data - The items to group.\n * @param callbackfn - A function to execute for each element in the iterable.\n * It should return a value indicating the group of the current element, or\n * `undefined` when the item should be excluded from any group.\n * @returns An object with properties for all groups, each assigned to an array\n * containing the elements of the associated group.\n * @signature\n * groupBy(data, callbackfn)\n * @example\n * groupBy([{a: 'cat'}, {a: 'dog'}] as const, prop('a')) // => {cat: [{a: 'cat'}], dog: [{a: 'dog'}]}\n * groupBy([0, 1], x => x % 2 === 0 ? 'even' : undefined) // => {even: [0]}\n * @dataFirst\n * @category Array\n */\nexport function groupBy<T, Key extends PropertyKey = PropertyKey>(\n data: ReadonlyArray<T>,\n callbackfn: (value: T, index: number, data: ReadonlyArray<T>) => Key | undefined,\n): BoundedPartial<Record<Key, NonEmptyArray<T>>>;\n\n/**\n * Groups the elements of a given iterable according to the string values\n * returned by a provided callback function. The returned object has separate\n * properties for each group, containing arrays with the elements in the group.\n * Unlike the built in `Object.groupBy` this function also allows the callback to\n * return `undefined` in order to exclude the item from being added to any\n * group.\n *\n * If you are grouping objects by a property of theirs (e.g.\n * `groupBy(data, ({ myProp }) => myProp)` or `groupBy(data, prop('myProp'))`)\n * consider using `groupByProp` (e.g. `groupByProp(data, 'myProp')`) instead,\n * as it would provide better typing.\n *\n * @param callbackfn - A function to execute for each element in the iterable.\n * It should return a value indicating the group of the current element, or\n * `undefined` when the item should be excluded from any group.\n * @returns An object with properties for all groups, each assigned to an array\n * containing the elements of the associated group.\n * @signature\n * groupBy(callbackfn)(data);\n * @example\n * pipe(\n * [{a: 'cat'}, {a: 'dog'}] as const,\n * groupBy(prop('a')),\n * ); // => {cat: [{a: 'cat'}], dog: [{a: 'dog'}]}\n * pipe(\n * [0, 1],\n * groupBy(x => x % 2 === 0 ? 'even' : undefined),\n * ); // => {even: [0]}\n * @dataLast\n * @category Array\n */\nexport function groupBy<T, Key extends PropertyKey = PropertyKey>(\n callbackfn: (value: T, index: number, data: ReadonlyArray<T>) => Key | undefined,\n): (items: ReadonlyArray<T>) => BoundedPartial<Record<Key, NonEmptyArray<T>>>;\n\nexport function groupBy(...args: ReadonlyArray<unknown>): unknown {\n return curry(groupByImplementation, args);\n}\n\nfunction groupByImplementation<T, Key extends PropertyKey = PropertyKey>(data: ReadonlyArray<T>, callbackfn: (value: T, index: number, data: ReadonlyArray<T>) => Key | undefined): BoundedPartial<Record<Key, NonEmptyArray<T>>> {\n const output: BoundedPartial<Record<Key, NonEmptyArray<T>>>\n = Object.create(null);\n\n for (let index = 0; index < data.length; index++) {\n // Accessing the object directly instead of via an iterator on the `entries` showed significant performance benefits while benchmarking.\n const item = data[index];\n\n // @ts-expect-error [ts2345] -- TypeScript is not able to infer that the index wouldn't overflow the array and that it shouldn't add `undefined` to the type. We don't want to use the `!` operator here because it's semantics are different because it changes the type of `item` to `NonNullable<T>` which is inaccurate because T itself could have `undefined` as a valid value.\n const key = callbackfn(item, index, data);\n if (key !== undefined) {\n // Once the prototype chain is fixed, it is safe to access the prop directly without needing to check existence or types.\n const items = output[key];\n\n if (items === undefined) {\n // It is more performant to create a 1-element array over creating an empty array and falling through to a unified the push. It is also more performant to mutate the existing object over using spread to continually create new objects on every unique key.\n // @ts-expect-error [ts2322] -- In addition to the typing issue we have for `item`, this line also creates a typing issue for the whole object, as TypeScript is having a hard time inferring what values could be adding to the object.\n output[key] = [item];\n } else {\n // It is more performant to add the items to an existing array over continually creating a new array every time we add an item to it.\n // @ts-expect-error [ts2345] -- See comment above about the effective typing for `item` here.\n items.push(item);\n }\n }\n }\n\n // Set the prototype as if we initialized our object as a normal object (e.g. `{}`). Without this none of the built-in object methods like `toString` would work on this object and it would act differently than expected.\n Object.setPrototypeOf(output, Object.prototype);\n\n return output;\n}\n"],"mappings":"mCAwEA,SAAgB,EAAQ,GAAG,EAAuC,CAChE,OAAO,EAAM,EAAuB,EAAK,CAG3C,SAAS,EAAgE,EAAwB,EAAiI,CAChO,IAAM,EACF,OAAO,OAAO,KAAK,CAEvB,IAAK,IAAI,EAAQ,EAAG,EAAQ,EAAK,OAAQ,IAAS,CAEhD,IAAM,EAAO,EAAK,GAGZ,EAAM,EAAW,EAAM,EAAO,EAAK,CACzC,GAAI,IAAQ,IAAA,GAAW,CAErB,IAAM,EAAQ,EAAO,GAEjB,IAAU,IAAA,GAGZ,EAAO,GAAO,CAAC,EAAK,CAIpB,EAAM,KAAK,EAAK,EAQtB,OAFA,OAAO,eAAe,EAAQ,OAAO,UAAU,CAExC"}
1
+ {"version":3,"file":"group-by.js","names":[],"sources":["../src/group-by.ts"],"sourcesContent":["import type { BoundedPartial } from './internal/types/bounded-partial';\nimport type { NonEmptyArray } from './internal/types/non-empty-array';\nimport { curry } from './curry';\n\n/**\n * Groups the elements of a given iterable according to the string values\n * returned by a provided callback function. The returned object has separate\n * properties for each group, containing arrays with the elements in the group.\n * Unlike the built in `Object.groupBy` this function also allows the callback to\n * return `undefined` in order to exclude the item from being added to any\n * group.\n *\n * If you are grouping objects by a property of theirs (e.g.\n * `groupBy(data, ({ myProp }) => myProp)` or `groupBy(data, prop('myProp'))`)\n * consider using `groupByProp` (e.g. `groupByProp(data, 'myProp')`) instead,\n * as it would provide better typing.\n *\n * @param data - The items to group.\n * @param callbackfn - A function to execute for each element in the iterable.\n * It should return a value indicating the group of the current element, or\n * `undefined` when the item should be excluded from any group.\n * @returns An object with properties for all groups, each assigned to an array\n * containing the elements of the associated group.\n * @signature\n * groupBy(data, callbackfn)\n * @example\n * groupBy([{a: 'cat'}, {a: 'dog'}] as const, prop('a')) // => {cat: [{a: 'cat'}], dog: [{a: 'dog'}]}\n * groupBy([0, 1], x => x % 2 === 0 ? 'even' : undefined) // => {even: [0]}\n * @dataFirst\n * @category Array\n */\nexport function groupBy<T, Key extends PropertyKey = PropertyKey>(\n data: ReadonlyArray<T>,\n callbackfn: (value: T, index: number, data: ReadonlyArray<T>) => Key | undefined,\n): BoundedPartial<Record<Key, NonEmptyArray<T>>>;\n\n/**\n * Groups the elements of a given iterable according to the string values\n * returned by a provided callback function. The returned object has separate\n * properties for each group, containing arrays with the elements in the group.\n * Unlike the built in `Object.groupBy` this function also allows the callback to\n * return `undefined` in order to exclude the item from being added to any\n * group.\n *\n * If you are grouping objects by a property of theirs (e.g.\n * `groupBy(data, ({ myProp }) => myProp)` or `groupBy(data, prop('myProp'))`)\n * consider using `groupByProp` (e.g. `groupByProp(data, 'myProp')`) instead,\n * as it would provide better typing.\n *\n * @param callbackfn - A function to execute for each element in the iterable.\n * It should return a value indicating the group of the current element, or\n * `undefined` when the item should be excluded from any group.\n * @returns An object with properties for all groups, each assigned to an array\n * containing the elements of the associated group.\n * @signature\n * groupBy(callbackfn)(data);\n * @example\n * pipe(\n * [{a: 'cat'}, {a: 'dog'}] as const,\n * groupBy(prop('a')),\n * ); // => {cat: [{a: 'cat'}], dog: [{a: 'dog'}]}\n * pipe(\n * [0, 1],\n * groupBy(x => x % 2 === 0 ? 'even' : undefined),\n * ); // => {even: [0]}\n * @dataLast\n * @category Array\n */\nexport function groupBy<T, Key extends PropertyKey = PropertyKey>(\n callbackfn: (value: T, index: number, data: ReadonlyArray<T>) => Key | undefined,\n): (items: ReadonlyArray<T>) => BoundedPartial<Record<Key, NonEmptyArray<T>>>;\n\nexport function groupBy(...args: ReadonlyArray<unknown>): unknown {\n return curry(groupByImplementation, args);\n}\n\nfunction groupByImplementation<T, Key extends PropertyKey = PropertyKey>(data: ReadonlyArray<T>, callbackfn: (value: T, index: number, data: ReadonlyArray<T>) => Key | undefined): BoundedPartial<Record<Key, NonEmptyArray<T>>> {\n const output: BoundedPartial<Record<Key, NonEmptyArray<T>>>\n = Object.create(null);\n\n for (let index = 0; index < data.length; index++) {\n // Accessing the object directly instead of via an iterator on the `entries` showed significant performance benefits while benchmarking.\n const item = data[index];\n\n // @ts-expect-error [ts2345] -- TypeScript is not able to infer that the index wouldn't overflow the array and that it shouldn't add `undefined` to the type. We don't want to use the `!` operator here because it's semantics are different because it changes the type of `item` to `NonNullable<T>` which is inaccurate because T itself could have `undefined` as a valid value.\n const key = callbackfn(item, index, data);\n if (key !== undefined) {\n // Once the prototype chain is fixed, it is safe to access the prop directly without needing to check existence or types.\n const items = output[key];\n\n if (items === undefined) {\n // It is more performant to create a 1-element array over creating an empty array and falling through to a unified the push. It is also more performant to mutate the existing object over using spread to continually create new objects on every unique key.\n // @ts-expect-error [ts2322] -- In addition to the typing issue we have for `item`, this line also creates a typing issue for the whole object, as TypeScript is having a hard time inferring what values could be adding to the object.\n output[key] = [item];\n } else {\n // It is more performant to add the items to an existing array over continually creating a new array every time we add an item to it.\n // @ts-expect-error [ts2345] -- See comment above about the effective typing for `item` here.\n items.push(item);\n }\n }\n }\n\n // Set the prototype as if we initialized our object as a normal object (e.g. `{}`). Without this none of the built-in object methods like `toString` would work on this object and it would act differently than expected.\n Object.setPrototypeOf(output, Object.prototype);\n\n return output;\n}\n"],"mappings":"mCAwEA,SAAgB,EAAQ,GAAG,EAAuC,CAChE,OAAO,EAAM,EAAuB,CAAI,CAC1C,CAEA,SAAS,EAAgE,EAAwB,EAAiI,CAChO,IAAM,EACF,OAAO,OAAO,IAAI,EAEtB,IAAK,IAAI,EAAQ,EAAG,EAAQ,EAAK,OAAQ,IAAS,CAEhD,IAAM,EAAO,EAAK,GAGZ,EAAM,EAAW,EAAM,EAAO,CAAI,EACxC,GAAI,IAAQ,IAAA,GAAW,CAErB,IAAM,EAAQ,EAAO,GAEjB,IAAU,IAAA,GAGZ,EAAO,GAAO,CAAC,CAAI,EAInB,EAAM,KAAK,CAAI,CAEnB,CACF,CAKA,OAFA,OAAO,eAAe,EAAQ,OAAO,SAAS,EAEvC,CACT"}
@@ -1,2 +1,2 @@
1
- Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});const e=require(`./curry.cjs`);function t(...t){return e.curry(n,t)}function n(e,t){return e.length>=t}exports.hasAtLeast=t;
1
+ Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});const e=require("./curry.cjs");function t(...t){return e.curry(n,t)}function n(e,t){return e.length>=t}exports.hasAtLeast=t;
2
2
  //# sourceMappingURL=has-at-least.cjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"has-at-least.cjs","names":["curry"],"sources":["../src/has-at-least.ts"],"sourcesContent":["import type { IsNumericLiteral } from 'type-fest';\nimport type { ArrayRequiredPrefix } from './internal/types/array-required-prefix';\nimport type { IterableContainer } from './internal/types/iterable-container';\nimport { curry } from './curry';\n\n/**\n * Checks if the given array has at least the defined number of elements. When\n * the minimum used is a literal (e.g. `3`) the output is refined accordingly so\n * that those indices are defined when accessing the array even when using\n * typescript's 'noUncheckedIndexAccess'.\n *\n * @param data - The input array.\n * @param minimum - The minimum number of elements the array must have.\n * @returns True if the array's length is *at least* `minimum`. When `minimum`\n * is a literal value, the output is narrowed to ensure the first items are\n * guaranteed.\n * @signature\n * hasAtLeast(data, minimum)\n * @example\n * hasAtLeast([], 4); // => false\n *\n * const data: number[] = [1,2,3,4];\n * hasAtLeast(data, 1); // => true\n * data[0]; // 1, with type `number`\n * @dataFirst\n * @category Array\n */\nexport function hasAtLeast<T extends IterableContainer, N extends number>(\n data: IterableContainer | T,\n minimum: IsNumericLiteral<N> extends true ? N : never,\n): data is ArrayRequiredPrefix<T, N>;\nexport function hasAtLeast(data: IterableContainer, minimum: number): boolean;\n\n/**\n * Checks if the given array has at least the defined number of elements. When\n * the minimum used is a literal (e.g. `3`) the output is refined accordingly so\n * that those indices are defined when accessing the array even when using\n * typescript's 'noUncheckedIndexAccess'.\n *\n * @param minimum - The minimum number of elements the array must have.\n * @returns True if the array's length is *at least* `minimum`. When `minimum`\n * is a literal value, the output is narrowed to ensure the first items are\n * guaranteed.\n * @signature\n * hasAtLeast(minimum)(data)\n * @example\n * pipe([], hasAtLeast(4)); // => false\n *\n * const data = [[1,2], [3], [4,5]];\n * pipe(\n * data,\n * filter(hasAtLeast(2)),\n * map(([, second]) => second),\n * ); // => [2,5], with type `number[]`\n * @dataLast\n * @category Array\n */\nexport function hasAtLeast<N extends number>(\n minimum: IsNumericLiteral<N> extends true ? N : never,\n): <T extends IterableContainer>(\n data: IterableContainer | T,\n) => data is ArrayRequiredPrefix<T, N>;\nexport function hasAtLeast(\n minimum: number,\n): (data: IterableContainer) => boolean;\n\nexport function hasAtLeast(...args: ReadonlyArray<unknown>): unknown {\n return curry(hasAtLeastImplementation, args);\n}\n\nfunction hasAtLeastImplementation(data: IterableContainer, minimum: number): boolean {\n return data.length >= minimum;\n}\n"],"mappings":"kGAkEA,SAAgB,EAAW,GAAG,EAAuC,CACnE,OAAOA,EAAAA,MAAM,EAA0B,EAAK,CAG9C,SAAS,EAAyB,EAAyB,EAA0B,CACnF,OAAO,EAAK,QAAU"}
1
+ {"version":3,"file":"has-at-least.cjs","names":["curry"],"sources":["../src/has-at-least.ts"],"sourcesContent":["import type { IsNumericLiteral } from 'type-fest';\nimport type { ArrayRequiredPrefix } from './internal/types/array-required-prefix';\nimport type { IterableContainer } from './internal/types/iterable-container';\nimport { curry } from './curry';\n\n/**\n * Checks if the given array has at least the defined number of elements. When\n * the minimum used is a literal (e.g. `3`) the output is refined accordingly so\n * that those indices are defined when accessing the array even when using\n * typescript's 'noUncheckedIndexAccess'.\n *\n * @param data - The input array.\n * @param minimum - The minimum number of elements the array must have.\n * @returns True if the array's length is *at least* `minimum`. When `minimum`\n * is a literal value, the output is narrowed to ensure the first items are\n * guaranteed.\n * @signature\n * hasAtLeast(data, minimum)\n * @example\n * hasAtLeast([], 4); // => false\n *\n * const data: number[] = [1,2,3,4];\n * hasAtLeast(data, 1); // => true\n * data[0]; // 1, with type `number`\n * @dataFirst\n * @category Array\n */\nexport function hasAtLeast<T extends IterableContainer, N extends number>(\n data: IterableContainer | T,\n minimum: IsNumericLiteral<N> extends true ? N : never,\n): data is ArrayRequiredPrefix<T, N>;\nexport function hasAtLeast(data: IterableContainer, minimum: number): boolean;\n\n/**\n * Checks if the given array has at least the defined number of elements. When\n * the minimum used is a literal (e.g. `3`) the output is refined accordingly so\n * that those indices are defined when accessing the array even when using\n * typescript's 'noUncheckedIndexAccess'.\n *\n * @param minimum - The minimum number of elements the array must have.\n * @returns True if the array's length is *at least* `minimum`. When `minimum`\n * is a literal value, the output is narrowed to ensure the first items are\n * guaranteed.\n * @signature\n * hasAtLeast(minimum)(data)\n * @example\n * pipe([], hasAtLeast(4)); // => false\n *\n * const data = [[1,2], [3], [4,5]];\n * pipe(\n * data,\n * filter(hasAtLeast(2)),\n * map(([, second]) => second),\n * ); // => [2,5], with type `number[]`\n * @dataLast\n * @category Array\n */\nexport function hasAtLeast<N extends number>(\n minimum: IsNumericLiteral<N> extends true ? N : never,\n): <T extends IterableContainer>(\n data: IterableContainer | T,\n) => data is ArrayRequiredPrefix<T, N>;\nexport function hasAtLeast(\n minimum: number,\n): (data: IterableContainer) => boolean;\n\nexport function hasAtLeast(...args: ReadonlyArray<unknown>): unknown {\n return curry(hasAtLeastImplementation, args);\n}\n\nfunction hasAtLeastImplementation(data: IterableContainer, minimum: number): boolean {\n return data.length >= minimum;\n}\n"],"mappings":"kGAkEA,SAAgB,EAAW,GAAG,EAAuC,CACnE,OAAOA,EAAAA,MAAM,EAA0B,CAAI,CAC7C,CAEA,SAAS,EAAyB,EAAyB,EAA0B,CACnF,OAAO,EAAK,QAAU,CACxB"}
@@ -1 +1 @@
1
- {"version":3,"file":"has-at-least.js","names":[],"sources":["../src/has-at-least.ts"],"sourcesContent":["import type { IsNumericLiteral } from 'type-fest';\nimport type { ArrayRequiredPrefix } from './internal/types/array-required-prefix';\nimport type { IterableContainer } from './internal/types/iterable-container';\nimport { curry } from './curry';\n\n/**\n * Checks if the given array has at least the defined number of elements. When\n * the minimum used is a literal (e.g. `3`) the output is refined accordingly so\n * that those indices are defined when accessing the array even when using\n * typescript's 'noUncheckedIndexAccess'.\n *\n * @param data - The input array.\n * @param minimum - The minimum number of elements the array must have.\n * @returns True if the array's length is *at least* `minimum`. When `minimum`\n * is a literal value, the output is narrowed to ensure the first items are\n * guaranteed.\n * @signature\n * hasAtLeast(data, minimum)\n * @example\n * hasAtLeast([], 4); // => false\n *\n * const data: number[] = [1,2,3,4];\n * hasAtLeast(data, 1); // => true\n * data[0]; // 1, with type `number`\n * @dataFirst\n * @category Array\n */\nexport function hasAtLeast<T extends IterableContainer, N extends number>(\n data: IterableContainer | T,\n minimum: IsNumericLiteral<N> extends true ? N : never,\n): data is ArrayRequiredPrefix<T, N>;\nexport function hasAtLeast(data: IterableContainer, minimum: number): boolean;\n\n/**\n * Checks if the given array has at least the defined number of elements. When\n * the minimum used is a literal (e.g. `3`) the output is refined accordingly so\n * that those indices are defined when accessing the array even when using\n * typescript's 'noUncheckedIndexAccess'.\n *\n * @param minimum - The minimum number of elements the array must have.\n * @returns True if the array's length is *at least* `minimum`. When `minimum`\n * is a literal value, the output is narrowed to ensure the first items are\n * guaranteed.\n * @signature\n * hasAtLeast(minimum)(data)\n * @example\n * pipe([], hasAtLeast(4)); // => false\n *\n * const data = [[1,2], [3], [4,5]];\n * pipe(\n * data,\n * filter(hasAtLeast(2)),\n * map(([, second]) => second),\n * ); // => [2,5], with type `number[]`\n * @dataLast\n * @category Array\n */\nexport function hasAtLeast<N extends number>(\n minimum: IsNumericLiteral<N> extends true ? N : never,\n): <T extends IterableContainer>(\n data: IterableContainer | T,\n) => data is ArrayRequiredPrefix<T, N>;\nexport function hasAtLeast(\n minimum: number,\n): (data: IterableContainer) => boolean;\n\nexport function hasAtLeast(...args: ReadonlyArray<unknown>): unknown {\n return curry(hasAtLeastImplementation, args);\n}\n\nfunction hasAtLeastImplementation(data: IterableContainer, minimum: number): boolean {\n return data.length >= minimum;\n}\n"],"mappings":"mCAkEA,SAAgB,EAAW,GAAG,EAAuC,CACnE,OAAO,EAAM,EAA0B,EAAK,CAG9C,SAAS,EAAyB,EAAyB,EAA0B,CACnF,OAAO,EAAK,QAAU"}
1
+ {"version":3,"file":"has-at-least.js","names":[],"sources":["../src/has-at-least.ts"],"sourcesContent":["import type { IsNumericLiteral } from 'type-fest';\nimport type { ArrayRequiredPrefix } from './internal/types/array-required-prefix';\nimport type { IterableContainer } from './internal/types/iterable-container';\nimport { curry } from './curry';\n\n/**\n * Checks if the given array has at least the defined number of elements. When\n * the minimum used is a literal (e.g. `3`) the output is refined accordingly so\n * that those indices are defined when accessing the array even when using\n * typescript's 'noUncheckedIndexAccess'.\n *\n * @param data - The input array.\n * @param minimum - The minimum number of elements the array must have.\n * @returns True if the array's length is *at least* `minimum`. When `minimum`\n * is a literal value, the output is narrowed to ensure the first items are\n * guaranteed.\n * @signature\n * hasAtLeast(data, minimum)\n * @example\n * hasAtLeast([], 4); // => false\n *\n * const data: number[] = [1,2,3,4];\n * hasAtLeast(data, 1); // => true\n * data[0]; // 1, with type `number`\n * @dataFirst\n * @category Array\n */\nexport function hasAtLeast<T extends IterableContainer, N extends number>(\n data: IterableContainer | T,\n minimum: IsNumericLiteral<N> extends true ? N : never,\n): data is ArrayRequiredPrefix<T, N>;\nexport function hasAtLeast(data: IterableContainer, minimum: number): boolean;\n\n/**\n * Checks if the given array has at least the defined number of elements. When\n * the minimum used is a literal (e.g. `3`) the output is refined accordingly so\n * that those indices are defined when accessing the array even when using\n * typescript's 'noUncheckedIndexAccess'.\n *\n * @param minimum - The minimum number of elements the array must have.\n * @returns True if the array's length is *at least* `minimum`. When `minimum`\n * is a literal value, the output is narrowed to ensure the first items are\n * guaranteed.\n * @signature\n * hasAtLeast(minimum)(data)\n * @example\n * pipe([], hasAtLeast(4)); // => false\n *\n * const data = [[1,2], [3], [4,5]];\n * pipe(\n * data,\n * filter(hasAtLeast(2)),\n * map(([, second]) => second),\n * ); // => [2,5], with type `number[]`\n * @dataLast\n * @category Array\n */\nexport function hasAtLeast<N extends number>(\n minimum: IsNumericLiteral<N> extends true ? N : never,\n): <T extends IterableContainer>(\n data: IterableContainer | T,\n) => data is ArrayRequiredPrefix<T, N>;\nexport function hasAtLeast(\n minimum: number,\n): (data: IterableContainer) => boolean;\n\nexport function hasAtLeast(...args: ReadonlyArray<unknown>): unknown {\n return curry(hasAtLeastImplementation, args);\n}\n\nfunction hasAtLeastImplementation(data: IterableContainer, minimum: number): boolean {\n return data.length >= minimum;\n}\n"],"mappings":"mCAkEA,SAAgB,EAAW,GAAG,EAAuC,CACnE,OAAO,EAAM,EAA0B,CAAI,CAC7C,CAEA,SAAS,EAAyB,EAAyB,EAA0B,CACnF,OAAO,EAAK,QAAU,CACxB"}
@@ -0,0 +1,2 @@
1
+ Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});const e=require("./curry.cjs");function t(...t){return e.curry(n,t)}function n(e,t){return Object.hasOwn(e,t)}exports.hasProp=t;
2
+ //# sourceMappingURL=has-prop.cjs.map