@vielzeug/arsenal 1.0.1

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 (772) hide show
  1. package/README.md +104 -0
  2. package/dist/_common/_abortable.d.ts +5 -0
  3. package/dist/_common/_abortable.d.ts.map +1 -0
  4. package/dist/_common/_lruMap.cjs +2 -0
  5. package/dist/_common/_lruMap.cjs.map +1 -0
  6. package/dist/_common/_lruMap.d.ts +20 -0
  7. package/dist/_common/_lruMap.d.ts.map +1 -0
  8. package/dist/_common/_lruMap.js +18 -0
  9. package/dist/_common/_lruMap.js.map +1 -0
  10. package/dist/_common/_secureRandomIndex.cjs +2 -0
  11. package/dist/_common/_secureRandomIndex.cjs.map +1 -0
  12. package/dist/_common/_secureRandomIndex.d.ts +2 -0
  13. package/dist/_common/_secureRandomIndex.d.ts.map +1 -0
  14. package/dist/_common/_secureRandomIndex.js +9 -0
  15. package/dist/_common/_secureRandomIndex.js.map +1 -0
  16. package/dist/_common/_selectorSet.cjs +2 -0
  17. package/dist/_common/_selectorSet.cjs.map +1 -0
  18. package/dist/_common/_selectorSet.d.ts +2 -0
  19. package/dist/_common/_selectorSet.d.ts.map +1 -0
  20. package/dist/_common/_selectorSet.js +16 -0
  21. package/dist/_common/_selectorSet.js.map +1 -0
  22. package/dist/_common/unsafePaths.cjs +2 -0
  23. package/dist/_common/unsafePaths.cjs.map +1 -0
  24. package/dist/_common/unsafePaths.d.ts +25 -0
  25. package/dist/_common/unsafePaths.d.ts.map +1 -0
  26. package/dist/_common/unsafePaths.js +13 -0
  27. package/dist/_common/unsafePaths.js.map +1 -0
  28. package/dist/_dev.cjs +2 -0
  29. package/dist/_dev.cjs.map +1 -0
  30. package/dist/_dev.d.ts +2 -0
  31. package/dist/_dev.d.ts.map +1 -0
  32. package/dist/_dev.js +9 -0
  33. package/dist/_dev.js.map +1 -0
  34. package/dist/array/chunk.cjs +2 -0
  35. package/dist/array/chunk.cjs.map +1 -0
  36. package/dist/array/chunk.d.ts +19 -0
  37. package/dist/array/chunk.d.ts.map +1 -0
  38. package/dist/array/chunk.js +12 -0
  39. package/dist/array/chunk.js.map +1 -0
  40. package/dist/array/compact.cjs +2 -0
  41. package/dist/array/compact.cjs.map +1 -0
  42. package/dist/array/compact.d.ts +7 -0
  43. package/dist/array/compact.d.ts.map +1 -0
  44. package/dist/array/compact.js +8 -0
  45. package/dist/array/compact.js.map +1 -0
  46. package/dist/array/compare.cjs +2 -0
  47. package/dist/array/compare.cjs.map +1 -0
  48. package/dist/array/compare.d.ts +31 -0
  49. package/dist/array/compare.d.ts.map +1 -0
  50. package/dist/array/compare.js +20 -0
  51. package/dist/array/compare.js.map +1 -0
  52. package/dist/array/compareBy.cjs +2 -0
  53. package/dist/array/compareBy.cjs.map +1 -0
  54. package/dist/array/compareBy.d.ts +24 -0
  55. package/dist/array/compareBy.d.ts.map +1 -0
  56. package/dist/array/compareBy.js +16 -0
  57. package/dist/array/compareBy.js.map +1 -0
  58. package/dist/array/contains.cjs +2 -0
  59. package/dist/array/contains.cjs.map +1 -0
  60. package/dist/array/contains.d.ts +17 -0
  61. package/dist/array/contains.d.ts.map +1 -0
  62. package/dist/array/contains.js +9 -0
  63. package/dist/array/contains.js.map +1 -0
  64. package/dist/array/countBy.cjs +2 -0
  65. package/dist/array/countBy.cjs.map +1 -0
  66. package/dist/array/countBy.d.ts +8 -0
  67. package/dist/array/countBy.d.ts.map +1 -0
  68. package/dist/array/countBy.js +14 -0
  69. package/dist/array/countBy.js.map +1 -0
  70. package/dist/array/difference.cjs +2 -0
  71. package/dist/array/difference.cjs.map +1 -0
  72. package/dist/array/difference.d.ts +6 -0
  73. package/dist/array/difference.d.ts.map +1 -0
  74. package/dist/array/difference.js +14 -0
  75. package/dist/array/difference.js.map +1 -0
  76. package/dist/array/drop.cjs +2 -0
  77. package/dist/array/drop.cjs.map +1 -0
  78. package/dist/array/drop.d.ts +5 -0
  79. package/dist/array/drop.d.ts.map +1 -0
  80. package/dist/array/drop.js +9 -0
  81. package/dist/array/drop.js.map +1 -0
  82. package/dist/array/dropLast.cjs +2 -0
  83. package/dist/array/dropLast.cjs.map +1 -0
  84. package/dist/array/dropLast.d.ts +5 -0
  85. package/dist/array/dropLast.d.ts.map +1 -0
  86. package/dist/array/dropLast.js +9 -0
  87. package/dist/array/dropLast.js.map +1 -0
  88. package/dist/array/filterMap.cjs +2 -0
  89. package/dist/array/filterMap.cjs.map +1 -0
  90. package/dist/array/filterMap.d.ts +5 -0
  91. package/dist/array/filterMap.d.ts.map +1 -0
  92. package/dist/array/filterMap.js +13 -0
  93. package/dist/array/filterMap.js.map +1 -0
  94. package/dist/array/first.cjs +2 -0
  95. package/dist/array/first.cjs.map +1 -0
  96. package/dist/array/first.d.ts +5 -0
  97. package/dist/array/first.d.ts.map +1 -0
  98. package/dist/array/first.js +8 -0
  99. package/dist/array/first.js.map +1 -0
  100. package/dist/array/flatten.cjs +2 -0
  101. package/dist/array/flatten.cjs.map +1 -0
  102. package/dist/array/flatten.d.ts +5 -0
  103. package/dist/array/flatten.d.ts.map +1 -0
  104. package/dist/array/flatten.js +11 -0
  105. package/dist/array/flatten.js.map +1 -0
  106. package/dist/array/groupBy.cjs +2 -0
  107. package/dist/array/groupBy.cjs.map +1 -0
  108. package/dist/array/groupBy.d.ts +7 -0
  109. package/dist/array/groupBy.d.ts.map +1 -0
  110. package/dist/array/groupBy.js +14 -0
  111. package/dist/array/groupBy.js.map +1 -0
  112. package/dist/array/index.d.ts +29 -0
  113. package/dist/array/index.d.ts.map +1 -0
  114. package/dist/array/indexBy.cjs +2 -0
  115. package/dist/array/indexBy.cjs.map +1 -0
  116. package/dist/array/indexBy.d.ts +7 -0
  117. package/dist/array/indexBy.d.ts.map +1 -0
  118. package/dist/array/indexBy.js +14 -0
  119. package/dist/array/indexBy.js.map +1 -0
  120. package/dist/array/intersection.cjs +2 -0
  121. package/dist/array/intersection.cjs.map +1 -0
  122. package/dist/array/intersection.d.ts +6 -0
  123. package/dist/array/intersection.d.ts.map +1 -0
  124. package/dist/array/intersection.js +14 -0
  125. package/dist/array/intersection.js.map +1 -0
  126. package/dist/array/last.cjs +2 -0
  127. package/dist/array/last.cjs.map +1 -0
  128. package/dist/array/last.d.ts +5 -0
  129. package/dist/array/last.d.ts.map +1 -0
  130. package/dist/array/last.js +8 -0
  131. package/dist/array/last.js.map +1 -0
  132. package/dist/array/partition.cjs +2 -0
  133. package/dist/array/partition.cjs.map +1 -0
  134. package/dist/array/partition.d.ts +5 -0
  135. package/dist/array/partition.d.ts.map +1 -0
  136. package/dist/array/partition.js +10 -0
  137. package/dist/array/partition.js.map +1 -0
  138. package/dist/array/replace.cjs +2 -0
  139. package/dist/array/replace.cjs.map +1 -0
  140. package/dist/array/replace.d.ts +18 -0
  141. package/dist/array/replace.d.ts.map +1 -0
  142. package/dist/array/replace.js +13 -0
  143. package/dist/array/replace.js.map +1 -0
  144. package/dist/array/rotate.cjs +2 -0
  145. package/dist/array/rotate.cjs.map +1 -0
  146. package/dist/array/rotate.d.ts +20 -0
  147. package/dist/array/rotate.d.ts.map +1 -0
  148. package/dist/array/rotate.js +10 -0
  149. package/dist/array/rotate.js.map +1 -0
  150. package/dist/array/search.cjs +2 -0
  151. package/dist/array/search.cjs.map +1 -0
  152. package/dist/array/search.d.ts +85 -0
  153. package/dist/array/search.d.ts.map +1 -0
  154. package/dist/array/search.js +47 -0
  155. package/dist/array/search.js.map +1 -0
  156. package/dist/array/sort.cjs +2 -0
  157. package/dist/array/sort.cjs.map +1 -0
  158. package/dist/array/sort.d.ts +26 -0
  159. package/dist/array/sort.d.ts.map +1 -0
  160. package/dist/array/sort.js +16 -0
  161. package/dist/array/sort.js.map +1 -0
  162. package/dist/array/take.cjs +2 -0
  163. package/dist/array/take.cjs.map +1 -0
  164. package/dist/array/take.d.ts +5 -0
  165. package/dist/array/take.d.ts.map +1 -0
  166. package/dist/array/take.js +9 -0
  167. package/dist/array/take.js.map +1 -0
  168. package/dist/array/takeLast.cjs +2 -0
  169. package/dist/array/takeLast.cjs.map +1 -0
  170. package/dist/array/takeLast.d.ts +5 -0
  171. package/dist/array/takeLast.d.ts.map +1 -0
  172. package/dist/array/takeLast.js +9 -0
  173. package/dist/array/takeLast.js.map +1 -0
  174. package/dist/array/toggle.cjs +2 -0
  175. package/dist/array/toggle.cjs.map +1 -0
  176. package/dist/array/toggle.d.ts +29 -0
  177. package/dist/array/toggle.d.ts.map +1 -0
  178. package/dist/array/toggle.js +9 -0
  179. package/dist/array/toggle.js.map +1 -0
  180. package/dist/array/union.cjs +2 -0
  181. package/dist/array/union.cjs.map +1 -0
  182. package/dist/array/union.d.ts +6 -0
  183. package/dist/array/union.d.ts.map +1 -0
  184. package/dist/array/union.js +9 -0
  185. package/dist/array/union.js.map +1 -0
  186. package/dist/array/uniq.cjs +2 -0
  187. package/dist/array/uniq.cjs.map +1 -0
  188. package/dist/array/uniq.d.ts +18 -0
  189. package/dist/array/uniq.d.ts.map +1 -0
  190. package/dist/array/uniq.js +9 -0
  191. package/dist/array/uniq.js.map +1 -0
  192. package/dist/array/unzip.cjs +2 -0
  193. package/dist/array/unzip.cjs.map +1 -0
  194. package/dist/array/unzip.d.ts +7 -0
  195. package/dist/array/unzip.d.ts.map +1 -0
  196. package/dist/array/unzip.js +11 -0
  197. package/dist/array/unzip.js.map +1 -0
  198. package/dist/array/zip.cjs +2 -0
  199. package/dist/array/zip.cjs.map +1 -0
  200. package/dist/array/zip.d.ts +7 -0
  201. package/dist/array/zip.d.ts.map +1 -0
  202. package/dist/array/zip.js +11 -0
  203. package/dist/array/zip.js.map +1 -0
  204. package/dist/arsenal.cjs +2 -0
  205. package/dist/arsenal.cjs.map +1 -0
  206. package/dist/arsenal.iife.js +2 -0
  207. package/dist/arsenal.iife.js.map +1 -0
  208. package/dist/arsenal.js +2 -0
  209. package/dist/arsenal.js.map +1 -0
  210. package/dist/async/abortError.cjs +2 -0
  211. package/dist/async/abortError.cjs.map +1 -0
  212. package/dist/async/abortError.d.ts +23 -0
  213. package/dist/async/abortError.d.ts.map +1 -0
  214. package/dist/async/abortError.js +8 -0
  215. package/dist/async/abortError.js.map +1 -0
  216. package/dist/async/attempt.cjs +2 -0
  217. package/dist/async/attempt.cjs.map +1 -0
  218. package/dist/async/attempt.d.ts +58 -0
  219. package/dist/async/attempt.d.ts.map +1 -0
  220. package/dist/async/attempt.js +31 -0
  221. package/dist/async/attempt.js.map +1 -0
  222. package/dist/async/backoff.cjs +2 -0
  223. package/dist/async/backoff.cjs.map +1 -0
  224. package/dist/async/backoff.d.ts +20 -0
  225. package/dist/async/backoff.d.ts.map +1 -0
  226. package/dist/async/backoff.js +9 -0
  227. package/dist/async/backoff.js.map +1 -0
  228. package/dist/async/index.d.ts +9 -0
  229. package/dist/async/index.d.ts.map +1 -0
  230. package/dist/async/parallel.cjs +2 -0
  231. package/dist/async/parallel.cjs.map +1 -0
  232. package/dist/async/parallel.d.ts +42 -0
  233. package/dist/async/parallel.d.ts.map +1 -0
  234. package/dist/async/parallel.js +26 -0
  235. package/dist/async/parallel.js.map +1 -0
  236. package/dist/async/queue.cjs +2 -0
  237. package/dist/async/queue.cjs.map +1 -0
  238. package/dist/async/queue.d.ts +42 -0
  239. package/dist/async/queue.d.ts.map +1 -0
  240. package/dist/async/queue.js +72 -0
  241. package/dist/async/queue.js.map +1 -0
  242. package/dist/async/retry.cjs +2 -0
  243. package/dist/async/retry.cjs.map +1 -0
  244. package/dist/async/retry.d.ts +46 -0
  245. package/dist/async/retry.d.ts.map +1 -0
  246. package/dist/async/retry.js +26 -0
  247. package/dist/async/retry.js.map +1 -0
  248. package/dist/async/sleep.cjs +2 -0
  249. package/dist/async/sleep.cjs.map +1 -0
  250. package/dist/async/sleep.d.ts +21 -0
  251. package/dist/async/sleep.d.ts.map +1 -0
  252. package/dist/async/sleep.js +16 -0
  253. package/dist/async/sleep.js.map +1 -0
  254. package/dist/async/waitFor.cjs +2 -0
  255. package/dist/async/waitFor.cjs.map +1 -0
  256. package/dist/async/waitFor.d.ts +34 -0
  257. package/dist/async/waitFor.d.ts.map +1 -0
  258. package/dist/async/waitFor.js +13 -0
  259. package/dist/async/waitFor.js.map +1 -0
  260. package/dist/cache/index.d.ts +3 -0
  261. package/dist/cache/index.d.ts.map +1 -0
  262. package/dist/cache/memo.cjs +2 -0
  263. package/dist/cache/memo.cjs.map +1 -0
  264. package/dist/cache/memo.d.ts +40 -0
  265. package/dist/cache/memo.d.ts.map +1 -0
  266. package/dist/cache/memo.js +37 -0
  267. package/dist/cache/memo.js.map +1 -0
  268. package/dist/cache/stash.cjs +2 -0
  269. package/dist/cache/stash.cjs.map +1 -0
  270. package/dist/cache/stash.d.ts +111 -0
  271. package/dist/cache/stash.d.ts.map +1 -0
  272. package/dist/cache/stash.js +92 -0
  273. package/dist/cache/stash.js.map +1 -0
  274. package/dist/errors.cjs +2 -0
  275. package/dist/errors.cjs.map +1 -0
  276. package/dist/errors.d.ts +20 -0
  277. package/dist/errors.d.ts.map +1 -0
  278. package/dist/errors.js +13 -0
  279. package/dist/errors.js.map +1 -0
  280. package/dist/function/assert.cjs +2 -0
  281. package/dist/function/assert.cjs.map +1 -0
  282. package/dist/function/assert.d.ts +19 -0
  283. package/dist/function/assert.d.ts.map +1 -0
  284. package/dist/function/assert.js +8 -0
  285. package/dist/function/assert.js.map +1 -0
  286. package/dist/function/constant.cjs +2 -0
  287. package/dist/function/constant.cjs.map +1 -0
  288. package/dist/function/constant.d.ts +5 -0
  289. package/dist/function/constant.d.ts.map +1 -0
  290. package/dist/function/constant.js +8 -0
  291. package/dist/function/constant.js.map +1 -0
  292. package/dist/function/debounce.cjs +2 -0
  293. package/dist/function/debounce.cjs.map +1 -0
  294. package/dist/function/debounce.d.ts +31 -0
  295. package/dist/function/debounce.d.ts.map +1 -0
  296. package/dist/function/debounce.js +29 -0
  297. package/dist/function/debounce.js.map +1 -0
  298. package/dist/function/identity.cjs +2 -0
  299. package/dist/function/identity.cjs.map +1 -0
  300. package/dist/function/identity.d.ts +5 -0
  301. package/dist/function/identity.d.ts.map +1 -0
  302. package/dist/function/identity.js +8 -0
  303. package/dist/function/identity.js.map +1 -0
  304. package/dist/function/index.d.ts +10 -0
  305. package/dist/function/index.d.ts.map +1 -0
  306. package/dist/function/once.cjs +2 -0
  307. package/dist/function/once.cjs.map +1 -0
  308. package/dist/function/once.d.ts +32 -0
  309. package/dist/function/once.d.ts.map +1 -0
  310. package/dist/function/once.js +11 -0
  311. package/dist/function/once.js.map +1 -0
  312. package/dist/function/pipe.cjs +2 -0
  313. package/dist/function/pipe.cjs.map +1 -0
  314. package/dist/function/pipe.d.ts +32 -0
  315. package/dist/function/pipe.d.ts.map +1 -0
  316. package/dist/function/pipe.js +10 -0
  317. package/dist/function/pipe.js.map +1 -0
  318. package/dist/function/runAll.cjs +2 -0
  319. package/dist/function/runAll.cjs.map +1 -0
  320. package/dist/function/runAll.d.ts +15 -0
  321. package/dist/function/runAll.d.ts.map +1 -0
  322. package/dist/function/runAll.js +19 -0
  323. package/dist/function/runAll.js.map +1 -0
  324. package/dist/function/tap.cjs +2 -0
  325. package/dist/function/tap.cjs.map +1 -0
  326. package/dist/function/tap.d.ts +5 -0
  327. package/dist/function/tap.d.ts.map +1 -0
  328. package/dist/function/tap.js +8 -0
  329. package/dist/function/tap.js.map +1 -0
  330. package/dist/function/throttle.cjs +2 -0
  331. package/dist/function/throttle.cjs.map +1 -0
  332. package/dist/function/throttle.d.ts +23 -0
  333. package/dist/function/throttle.d.ts.map +1 -0
  334. package/dist/function/throttle.js +36 -0
  335. package/dist/function/throttle.js.map +1 -0
  336. package/dist/guards/combinators.cjs +2 -0
  337. package/dist/guards/combinators.cjs.map +1 -0
  338. package/dist/guards/combinators.d.ts +49 -0
  339. package/dist/guards/combinators.d.ts.map +1 -0
  340. package/dist/guards/combinators.js +17 -0
  341. package/dist/guards/combinators.js.map +1 -0
  342. package/dist/guards/index.d.ts +20 -0
  343. package/dist/guards/index.d.ts.map +1 -0
  344. package/dist/guards/isAbortError.cjs +2 -0
  345. package/dist/guards/isAbortError.cjs.map +1 -0
  346. package/dist/guards/isAbortError.d.ts +19 -0
  347. package/dist/guards/isAbortError.d.ts.map +1 -0
  348. package/dist/guards/isAbortError.js +8 -0
  349. package/dist/guards/isAbortError.js.map +1 -0
  350. package/dist/guards/isArray.cjs +2 -0
  351. package/dist/guards/isArray.cjs.map +1 -0
  352. package/dist/guards/isArray.d.ts +16 -0
  353. package/dist/guards/isArray.d.ts.map +1 -0
  354. package/dist/guards/isArray.js +8 -0
  355. package/dist/guards/isArray.js.map +1 -0
  356. package/dist/guards/isBoolean.cjs +2 -0
  357. package/dist/guards/isBoolean.cjs.map +1 -0
  358. package/dist/guards/isBoolean.d.ts +23 -0
  359. package/dist/guards/isBoolean.d.ts.map +1 -0
  360. package/dist/guards/isBoolean.js +8 -0
  361. package/dist/guards/isBoolean.js.map +1 -0
  362. package/dist/guards/isDate.cjs +2 -0
  363. package/dist/guards/isDate.cjs.map +1 -0
  364. package/dist/guards/isDate.d.ts +15 -0
  365. package/dist/guards/isDate.d.ts.map +1 -0
  366. package/dist/guards/isDate.js +8 -0
  367. package/dist/guards/isDate.js.map +1 -0
  368. package/dist/guards/isDefined.cjs +2 -0
  369. package/dist/guards/isDefined.cjs.map +1 -0
  370. package/dist/guards/isDefined.d.ts +19 -0
  371. package/dist/guards/isDefined.d.ts.map +1 -0
  372. package/dist/guards/isDefined.js +8 -0
  373. package/dist/guards/isDefined.js.map +1 -0
  374. package/dist/guards/isEmpty.cjs +2 -0
  375. package/dist/guards/isEmpty.cjs.map +1 -0
  376. package/dist/guards/isEmpty.d.ts +23 -0
  377. package/dist/guards/isEmpty.d.ts.map +1 -0
  378. package/dist/guards/isEmpty.js +10 -0
  379. package/dist/guards/isEmpty.js.map +1 -0
  380. package/dist/guards/isEqual.cjs +2 -0
  381. package/dist/guards/isEqual.cjs.map +1 -0
  382. package/dist/guards/isEqual.d.ts +24 -0
  383. package/dist/guards/isEqual.d.ts.map +1 -0
  384. package/dist/guards/isEqual.js +34 -0
  385. package/dist/guards/isEqual.js.map +1 -0
  386. package/dist/guards/isError.cjs +2 -0
  387. package/dist/guards/isError.cjs.map +1 -0
  388. package/dist/guards/isError.d.ts +15 -0
  389. package/dist/guards/isError.d.ts.map +1 -0
  390. package/dist/guards/isError.js +8 -0
  391. package/dist/guards/isError.js.map +1 -0
  392. package/dist/guards/isFunction.cjs +2 -0
  393. package/dist/guards/isFunction.cjs.map +1 -0
  394. package/dist/guards/isFunction.d.ts +16 -0
  395. package/dist/guards/isFunction.d.ts.map +1 -0
  396. package/dist/guards/isFunction.js +8 -0
  397. package/dist/guards/isFunction.js.map +1 -0
  398. package/dist/guards/isMatch.cjs +2 -0
  399. package/dist/guards/isMatch.cjs.map +1 -0
  400. package/dist/guards/isMatch.d.ts +23 -0
  401. package/dist/guards/isMatch.d.ts.map +1 -0
  402. package/dist/guards/isMatch.js +23 -0
  403. package/dist/guards/isMatch.js.map +1 -0
  404. package/dist/guards/isNil.cjs +2 -0
  405. package/dist/guards/isNil.cjs.map +1 -0
  406. package/dist/guards/isNil.d.ts +17 -0
  407. package/dist/guards/isNil.d.ts.map +1 -0
  408. package/dist/guards/isNil.js +8 -0
  409. package/dist/guards/isNil.js.map +1 -0
  410. package/dist/guards/isNumber.cjs +2 -0
  411. package/dist/guards/isNumber.cjs.map +1 -0
  412. package/dist/guards/isNumber.d.ts +15 -0
  413. package/dist/guards/isNumber.d.ts.map +1 -0
  414. package/dist/guards/isNumber.js +8 -0
  415. package/dist/guards/isNumber.js.map +1 -0
  416. package/dist/guards/isPlainObject.cjs +2 -0
  417. package/dist/guards/isPlainObject.cjs.map +1 -0
  418. package/dist/guards/isPlainObject.d.ts +16 -0
  419. package/dist/guards/isPlainObject.d.ts.map +1 -0
  420. package/dist/guards/isPlainObject.js +10 -0
  421. package/dist/guards/isPlainObject.js.map +1 -0
  422. package/dist/guards/isPrimitive.cjs +2 -0
  423. package/dist/guards/isPrimitive.cjs.map +1 -0
  424. package/dist/guards/isPrimitive.d.ts +18 -0
  425. package/dist/guards/isPrimitive.d.ts.map +1 -0
  426. package/dist/guards/isPrimitive.js +9 -0
  427. package/dist/guards/isPrimitive.js.map +1 -0
  428. package/dist/guards/isPromise.cjs +2 -0
  429. package/dist/guards/isPromise.cjs.map +1 -0
  430. package/dist/guards/isPromise.d.ts +17 -0
  431. package/dist/guards/isPromise.d.ts.map +1 -0
  432. package/dist/guards/isPromise.js +8 -0
  433. package/dist/guards/isPromise.js.map +1 -0
  434. package/dist/guards/isRegex.cjs +2 -0
  435. package/dist/guards/isRegex.cjs.map +1 -0
  436. package/dist/guards/isRegex.d.ts +21 -0
  437. package/dist/guards/isRegex.d.ts.map +1 -0
  438. package/dist/guards/isRegex.js +8 -0
  439. package/dist/guards/isRegex.js.map +1 -0
  440. package/dist/guards/isString.cjs +2 -0
  441. package/dist/guards/isString.cjs.map +1 -0
  442. package/dist/guards/isString.d.ts +15 -0
  443. package/dist/guards/isString.d.ts.map +1 -0
  444. package/dist/guards/isString.js +8 -0
  445. package/dist/guards/isString.js.map +1 -0
  446. package/dist/guards/shallowEqual.cjs +2 -0
  447. package/dist/guards/shallowEqual.cjs.map +1 -0
  448. package/dist/guards/shallowEqual.d.ts +29 -0
  449. package/dist/guards/shallowEqual.d.ts.map +1 -0
  450. package/dist/guards/shallowEqual.js +20 -0
  451. package/dist/guards/shallowEqual.js.map +1 -0
  452. package/dist/index.cjs +1 -0
  453. package/dist/index.d.ts +119 -0
  454. package/dist/index.d.ts.map +1 -0
  455. package/dist/index.js +118 -0
  456. package/dist/math/abs.cjs +2 -0
  457. package/dist/math/abs.cjs.map +1 -0
  458. package/dist/math/abs.d.ts +17 -0
  459. package/dist/math/abs.d.ts.map +1 -0
  460. package/dist/math/abs.js +8 -0
  461. package/dist/math/abs.js.map +1 -0
  462. package/dist/math/allocate.cjs +2 -0
  463. package/dist/math/allocate.cjs.map +1 -0
  464. package/dist/math/allocate.d.ts +29 -0
  465. package/dist/math/allocate.d.ts.map +1 -0
  466. package/dist/math/allocate.js +20 -0
  467. package/dist/math/allocate.js.map +1 -0
  468. package/dist/math/average.cjs +2 -0
  469. package/dist/math/average.cjs.map +1 -0
  470. package/dist/math/average.d.ts +16 -0
  471. package/dist/math/average.d.ts.map +1 -0
  472. package/dist/math/average.js +14 -0
  473. package/dist/math/average.js.map +1 -0
  474. package/dist/math/clamp.cjs +2 -0
  475. package/dist/math/clamp.cjs.map +1 -0
  476. package/dist/math/clamp.d.ts +21 -0
  477. package/dist/math/clamp.d.ts.map +1 -0
  478. package/dist/math/clamp.js +8 -0
  479. package/dist/math/clamp.js.map +1 -0
  480. package/dist/math/gcd.cjs +2 -0
  481. package/dist/math/gcd.cjs.map +1 -0
  482. package/dist/math/gcd.d.ts +18 -0
  483. package/dist/math/gcd.d.ts.map +1 -0
  484. package/dist/math/gcd.js +13 -0
  485. package/dist/math/gcd.js.map +1 -0
  486. package/dist/math/index.d.ts +20 -0
  487. package/dist/math/index.d.ts.map +1 -0
  488. package/dist/math/lcm.cjs +2 -0
  489. package/dist/math/lcm.cjs.map +1 -0
  490. package/dist/math/lcm.d.ts +15 -0
  491. package/dist/math/lcm.d.ts.map +1 -0
  492. package/dist/math/lcm.js +9 -0
  493. package/dist/math/lcm.js.map +1 -0
  494. package/dist/math/lerp.cjs +2 -0
  495. package/dist/math/lerp.cjs.map +1 -0
  496. package/dist/math/lerp.d.ts +17 -0
  497. package/dist/math/lerp.d.ts.map +1 -0
  498. package/dist/math/lerp.js +8 -0
  499. package/dist/math/lerp.js.map +1 -0
  500. package/dist/math/linspace.cjs +2 -0
  501. package/dist/math/linspace.cjs.map +1 -0
  502. package/dist/math/linspace.d.ts +19 -0
  503. package/dist/math/linspace.d.ts.map +1 -0
  504. package/dist/math/linspace.js +11 -0
  505. package/dist/math/linspace.js.map +1 -0
  506. package/dist/math/max.cjs +2 -0
  507. package/dist/math/max.cjs.map +1 -0
  508. package/dist/math/max.d.ts +21 -0
  509. package/dist/math/max.d.ts.map +1 -0
  510. package/dist/math/max.js +12 -0
  511. package/dist/math/max.js.map +1 -0
  512. package/dist/math/median.cjs +2 -0
  513. package/dist/math/median.cjs.map +1 -0
  514. package/dist/math/median.d.ts +17 -0
  515. package/dist/math/median.d.ts.map +1 -0
  516. package/dist/math/median.js +12 -0
  517. package/dist/math/median.js.map +1 -0
  518. package/dist/math/min.cjs +2 -0
  519. package/dist/math/min.cjs.map +1 -0
  520. package/dist/math/min.d.ts +21 -0
  521. package/dist/math/min.d.ts.map +1 -0
  522. package/dist/math/min.js +12 -0
  523. package/dist/math/min.js.map +1 -0
  524. package/dist/math/mod.cjs +2 -0
  525. package/dist/math/mod.cjs.map +1 -0
  526. package/dist/math/mod.d.ts +18 -0
  527. package/dist/math/mod.d.ts.map +1 -0
  528. package/dist/math/mod.js +10 -0
  529. package/dist/math/mod.js.map +1 -0
  530. package/dist/math/normalize.cjs +2 -0
  531. package/dist/math/normalize.cjs.map +1 -0
  532. package/dist/math/normalize.d.ts +18 -0
  533. package/dist/math/normalize.d.ts.map +1 -0
  534. package/dist/math/normalize.js +9 -0
  535. package/dist/math/normalize.js.map +1 -0
  536. package/dist/math/percent.cjs +2 -0
  537. package/dist/math/percent.cjs.map +1 -0
  538. package/dist/math/percent.d.ts +19 -0
  539. package/dist/math/percent.d.ts.map +1 -0
  540. package/dist/math/percent.js +8 -0
  541. package/dist/math/percent.js.map +1 -0
  542. package/dist/math/range.cjs +2 -0
  543. package/dist/math/range.cjs.map +1 -0
  544. package/dist/math/range.d.ts +37 -0
  545. package/dist/math/range.d.ts.map +1 -0
  546. package/dist/math/range.js +27 -0
  547. package/dist/math/range.js.map +1 -0
  548. package/dist/math/round.cjs +2 -0
  549. package/dist/math/round.cjs.map +1 -0
  550. package/dist/math/round.d.ts +21 -0
  551. package/dist/math/round.d.ts.map +1 -0
  552. package/dist/math/round.js +10 -0
  553. package/dist/math/round.js.map +1 -0
  554. package/dist/math/standardDeviation.cjs +2 -0
  555. package/dist/math/standardDeviation.cjs.map +1 -0
  556. package/dist/math/standardDeviation.d.ts +16 -0
  557. package/dist/math/standardDeviation.d.ts.map +1 -0
  558. package/dist/math/standardDeviation.js +9 -0
  559. package/dist/math/standardDeviation.js.map +1 -0
  560. package/dist/math/sum.cjs +2 -0
  561. package/dist/math/sum.cjs.map +1 -0
  562. package/dist/math/sum.d.ts +19 -0
  563. package/dist/math/sum.d.ts.map +1 -0
  564. package/dist/math/sum.js +13 -0
  565. package/dist/math/sum.js.map +1 -0
  566. package/dist/math/variance.cjs +2 -0
  567. package/dist/math/variance.cjs.map +1 -0
  568. package/dist/math/variance.d.ts +17 -0
  569. package/dist/math/variance.d.ts.map +1 -0
  570. package/dist/math/variance.js +11 -0
  571. package/dist/math/variance.js.map +1 -0
  572. package/dist/object/defaults.cjs +2 -0
  573. package/dist/object/defaults.cjs.map +1 -0
  574. package/dist/object/defaults.d.ts +17 -0
  575. package/dist/object/defaults.d.ts.map +1 -0
  576. package/dist/object/defaults.js +12 -0
  577. package/dist/object/defaults.js.map +1 -0
  578. package/dist/object/diff.cjs +2 -0
  579. package/dist/object/diff.cjs.map +1 -0
  580. package/dist/object/diff.d.ts +63 -0
  581. package/dist/object/diff.d.ts.map +1 -0
  582. package/dist/object/diff.js +27 -0
  583. package/dist/object/diff.js.map +1 -0
  584. package/dist/object/filterValues.cjs +2 -0
  585. package/dist/object/filterValues.cjs.map +1 -0
  586. package/dist/object/filterValues.d.ts +16 -0
  587. package/dist/object/filterValues.d.ts.map +1 -0
  588. package/dist/object/filterValues.js +11 -0
  589. package/dist/object/filterValues.js.map +1 -0
  590. package/dist/object/flattenPaths.cjs +2 -0
  591. package/dist/object/flattenPaths.cjs.map +1 -0
  592. package/dist/object/flattenPaths.d.ts +13 -0
  593. package/dist/object/flattenPaths.d.ts.map +1 -0
  594. package/dist/object/flattenPaths.js +31 -0
  595. package/dist/object/flattenPaths.js.map +1 -0
  596. package/dist/object/getPath.cjs +2 -0
  597. package/dist/object/getPath.cjs.map +1 -0
  598. package/dist/object/getPath.d.ts +48 -0
  599. package/dist/object/getPath.d.ts.map +1 -0
  600. package/dist/object/getPath.js +27 -0
  601. package/dist/object/getPath.js.map +1 -0
  602. package/dist/object/hash.cjs +2 -0
  603. package/dist/object/hash.cjs.map +1 -0
  604. package/dist/object/hash.d.ts +12 -0
  605. package/dist/object/hash.d.ts.map +1 -0
  606. package/dist/object/hash.js +28 -0
  607. package/dist/object/hash.js.map +1 -0
  608. package/dist/object/index.d.ts +15 -0
  609. package/dist/object/index.d.ts.map +1 -0
  610. package/dist/object/invert.cjs +2 -0
  611. package/dist/object/invert.cjs.map +1 -0
  612. package/dist/object/invert.d.ts +15 -0
  613. package/dist/object/invert.d.ts.map +1 -0
  614. package/dist/object/invert.js +11 -0
  615. package/dist/object/invert.js.map +1 -0
  616. package/dist/object/mapKeys.cjs +2 -0
  617. package/dist/object/mapKeys.cjs.map +1 -0
  618. package/dist/object/mapKeys.d.ts +16 -0
  619. package/dist/object/mapKeys.d.ts.map +1 -0
  620. package/dist/object/mapKeys.js +15 -0
  621. package/dist/object/mapKeys.js.map +1 -0
  622. package/dist/object/mapValues.cjs +2 -0
  623. package/dist/object/mapValues.cjs.map +1 -0
  624. package/dist/object/mapValues.d.ts +18 -0
  625. package/dist/object/mapValues.d.ts.map +1 -0
  626. package/dist/object/mapValues.js +11 -0
  627. package/dist/object/mapValues.js.map +1 -0
  628. package/dist/object/merge.cjs +2 -0
  629. package/dist/object/merge.cjs.map +1 -0
  630. package/dist/object/merge.d.ts +41 -0
  631. package/dist/object/merge.d.ts.map +1 -0
  632. package/dist/object/merge.js +27 -0
  633. package/dist/object/merge.js.map +1 -0
  634. package/dist/object/omit.cjs +2 -0
  635. package/dist/object/omit.cjs.map +1 -0
  636. package/dist/object/omit.d.ts +16 -0
  637. package/dist/object/omit.d.ts.map +1 -0
  638. package/dist/object/omit.js +11 -0
  639. package/dist/object/omit.js.map +1 -0
  640. package/dist/object/parseJSON.cjs +2 -0
  641. package/dist/object/parseJSON.cjs.map +1 -0
  642. package/dist/object/parseJSON.d.ts +32 -0
  643. package/dist/object/parseJSON.d.ts.map +1 -0
  644. package/dist/object/parseJSON.js +16 -0
  645. package/dist/object/parseJSON.js.map +1 -0
  646. package/dist/object/pick.cjs +2 -0
  647. package/dist/object/pick.cjs.map +1 -0
  648. package/dist/object/pick.d.ts +17 -0
  649. package/dist/object/pick.d.ts.map +1 -0
  650. package/dist/object/pick.js +11 -0
  651. package/dist/object/pick.js.map +1 -0
  652. package/dist/object/prune.cjs +2 -0
  653. package/dist/object/prune.cjs.map +1 -0
  654. package/dist/object/prune.d.ts +26 -0
  655. package/dist/object/prune.d.ts.map +1 -0
  656. package/dist/object/prune.js +36 -0
  657. package/dist/object/prune.js.map +1 -0
  658. package/dist/random/draw.cjs +2 -0
  659. package/dist/random/draw.cjs.map +1 -0
  660. package/dist/random/draw.d.ts +24 -0
  661. package/dist/random/draw.d.ts.map +1 -0
  662. package/dist/random/draw.js +21 -0
  663. package/dist/random/draw.js.map +1 -0
  664. package/dist/random/index.d.ts +5 -0
  665. package/dist/random/index.d.ts.map +1 -0
  666. package/dist/random/random.cjs +2 -0
  667. package/dist/random/random.cjs.map +1 -0
  668. package/dist/random/random.d.ts +14 -0
  669. package/dist/random/random.d.ts.map +1 -0
  670. package/dist/random/random.js +11 -0
  671. package/dist/random/random.js.map +1 -0
  672. package/dist/random/shuffle.cjs +2 -0
  673. package/dist/random/shuffle.cjs.map +1 -0
  674. package/dist/random/shuffle.d.ts +12 -0
  675. package/dist/random/shuffle.d.ts.map +1 -0
  676. package/dist/random/shuffle.js +14 -0
  677. package/dist/random/shuffle.js.map +1 -0
  678. package/dist/random/uuid.cjs +2 -0
  679. package/dist/random/uuid.cjs.map +1 -0
  680. package/dist/random/uuid.d.ts +12 -0
  681. package/dist/random/uuid.d.ts.map +1 -0
  682. package/dist/random/uuid.js +8 -0
  683. package/dist/random/uuid.js.map +1 -0
  684. package/dist/string/_caseUtils.cjs +2 -0
  685. package/dist/string/_caseUtils.cjs.map +1 -0
  686. package/dist/string/_caseUtils.d.ts +9 -0
  687. package/dist/string/_caseUtils.d.ts.map +1 -0
  688. package/dist/string/_caseUtils.js +13 -0
  689. package/dist/string/_caseUtils.js.map +1 -0
  690. package/dist/string/camelCase.cjs +2 -0
  691. package/dist/string/camelCase.cjs.map +1 -0
  692. package/dist/string/camelCase.d.ts +14 -0
  693. package/dist/string/camelCase.d.ts.map +1 -0
  694. package/dist/string/camelCase.js +9 -0
  695. package/dist/string/camelCase.js.map +1 -0
  696. package/dist/string/endsWith.cjs +2 -0
  697. package/dist/string/endsWith.cjs.map +1 -0
  698. package/dist/string/endsWith.d.ts +5 -0
  699. package/dist/string/endsWith.d.ts.map +1 -0
  700. package/dist/string/endsWith.js +8 -0
  701. package/dist/string/endsWith.js.map +1 -0
  702. package/dist/string/escape.cjs +2 -0
  703. package/dist/string/escape.cjs.map +1 -0
  704. package/dist/string/escape.d.ts +5 -0
  705. package/dist/string/escape.d.ts.map +1 -0
  706. package/dist/string/escape.js +15 -0
  707. package/dist/string/escape.js.map +1 -0
  708. package/dist/string/index.d.ts +14 -0
  709. package/dist/string/index.d.ts.map +1 -0
  710. package/dist/string/kebabCase.cjs +2 -0
  711. package/dist/string/kebabCase.cjs.map +1 -0
  712. package/dist/string/kebabCase.d.ts +15 -0
  713. package/dist/string/kebabCase.d.ts.map +1 -0
  714. package/dist/string/kebabCase.js +9 -0
  715. package/dist/string/kebabCase.js.map +1 -0
  716. package/dist/string/pad.cjs +2 -0
  717. package/dist/string/pad.cjs.map +1 -0
  718. package/dist/string/pad.d.ts +5 -0
  719. package/dist/string/pad.d.ts.map +1 -0
  720. package/dist/string/pad.js +10 -0
  721. package/dist/string/pad.js.map +1 -0
  722. package/dist/string/pascalCase.cjs +2 -0
  723. package/dist/string/pascalCase.cjs.map +1 -0
  724. package/dist/string/pascalCase.d.ts +15 -0
  725. package/dist/string/pascalCase.d.ts.map +1 -0
  726. package/dist/string/pascalCase.js +9 -0
  727. package/dist/string/pascalCase.js.map +1 -0
  728. package/dist/string/similarity.cjs +2 -0
  729. package/dist/string/similarity.cjs.map +1 -0
  730. package/dist/string/similarity.d.ts +2 -0
  731. package/dist/string/similarity.d.ts.map +1 -0
  732. package/dist/string/similarity.js +24 -0
  733. package/dist/string/similarity.js.map +1 -0
  734. package/dist/string/snakeCase.cjs +2 -0
  735. package/dist/string/snakeCase.cjs.map +1 -0
  736. package/dist/string/snakeCase.d.ts +15 -0
  737. package/dist/string/snakeCase.d.ts.map +1 -0
  738. package/dist/string/snakeCase.js +9 -0
  739. package/dist/string/snakeCase.js.map +1 -0
  740. package/dist/string/startsWith.cjs +2 -0
  741. package/dist/string/startsWith.cjs.map +1 -0
  742. package/dist/string/startsWith.d.ts +5 -0
  743. package/dist/string/startsWith.d.ts.map +1 -0
  744. package/dist/string/startsWith.js +8 -0
  745. package/dist/string/startsWith.js.map +1 -0
  746. package/dist/string/titleCase.cjs +2 -0
  747. package/dist/string/titleCase.cjs.map +1 -0
  748. package/dist/string/titleCase.d.ts +5 -0
  749. package/dist/string/titleCase.d.ts.map +1 -0
  750. package/dist/string/titleCase.js +9 -0
  751. package/dist/string/titleCase.js.map +1 -0
  752. package/dist/string/truncate.cjs +2 -0
  753. package/dist/string/truncate.cjs.map +1 -0
  754. package/dist/string/truncate.d.ts +27 -0
  755. package/dist/string/truncate.d.ts.map +1 -0
  756. package/dist/string/truncate.js +17 -0
  757. package/dist/string/truncate.js.map +1 -0
  758. package/dist/string/unescape.cjs +2 -0
  759. package/dist/string/unescape.cjs.map +1 -0
  760. package/dist/string/unescape.d.ts +5 -0
  761. package/dist/string/unescape.d.ts.map +1 -0
  762. package/dist/string/unescape.js +15 -0
  763. package/dist/string/unescape.js.map +1 -0
  764. package/dist/string/words.cjs +2 -0
  765. package/dist/string/words.cjs.map +1 -0
  766. package/dist/string/words.d.ts +5 -0
  767. package/dist/string/words.d.ts.map +1 -0
  768. package/dist/string/words.js +10 -0
  769. package/dist/string/words.js.map +1 -0
  770. package/dist/types.d.ts +13 -0
  771. package/dist/types.d.ts.map +1 -0
  772. package/package.json +102 -0
@@ -0,0 +1,16 @@
1
+ import { abortError as e } from "./abortError.js";
2
+ //#region src/async/sleep.ts
3
+ async function t(t, n) {
4
+ return n ? n.aborted ? Promise.reject(e(n)) : new Promise((r, i) => {
5
+ let a = setTimeout(() => {
6
+ n.removeEventListener("abort", o), r();
7
+ }, t), o = () => {
8
+ clearTimeout(a), n.removeEventListener("abort", o), i(e(n));
9
+ };
10
+ n.addEventListener("abort", o);
11
+ }) : new Promise((e) => setTimeout(e, t));
12
+ }
13
+ //#endregion
14
+ export { t as sleep };
15
+
16
+ //# sourceMappingURL=sleep.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sleep.js","names":[],"sources":["../../src/async/sleep.ts"],"sourcesContent":["import { abortError } from './abortError';\n\n/**\n * Creates a Promise that resolves after a specified amount of time.\n * If an `AbortSignal` is provided and fires before the delay elapses, the promise rejects with\n * the signal's reason (or a generic `DOMException('Aborted', 'AbortError')`).\n *\n * @example\n * ```ts\n * sleep(1000).then(() => console.log('Hello, world!')); // logs after 1 second\n *\n * // With abort support\n * const controller = new AbortController();\n * await sleep(5000, controller.signal); // rejects immediately when aborted\n * ```\n *\n * @param timeout - The number of milliseconds to wait before resolving the Promise.\n * @param signal - Optional AbortSignal to cancel the sleep early.\n *\n * @returns A Promise that resolves after the specified time.\n */\nexport async function sleep(timeout: number, signal?: AbortSignal): Promise<void> {\n if (!signal) {\n return new Promise((resolve) => setTimeout(resolve, timeout));\n }\n\n if (signal.aborted) {\n return Promise.reject(abortError(signal));\n }\n\n return new Promise<void>((resolve, reject) => {\n const id = setTimeout(() => {\n signal.removeEventListener('abort', onAbort);\n resolve();\n }, timeout);\n\n const onAbort = () => {\n clearTimeout(id);\n signal.removeEventListener('abort', onAbort);\n reject(abortError(signal));\n };\n\n signal.addEventListener('abort', onAbort);\n });\n}\n"],"mappings":";;AAqBA,eAAsB,EAAM,GAAiB,GAAqC;CAShF,OARK,IAID,EAAO,UACF,QAAQ,OAAO,EAAW,CAAM,CAAC,IAGnC,IAAI,SAAe,GAAS,MAAW;EAC5C,IAAM,IAAK,iBAAiB;GAE1B,AADA,EAAO,oBAAoB,SAAS,CAAO,GAC3C,EAAQ;EACV,GAAG,CAAO,GAEJ,UAAgB;GAGpB,AAFA,aAAa,CAAE,GACf,EAAO,oBAAoB,SAAS,CAAO,GAC3C,EAAO,EAAW,CAAM,CAAC;EAC3B;EAEA,EAAO,iBAAiB,SAAS,CAAO;CAC1C,CAAC,IApBQ,IAAI,SAAS,MAAY,WAAW,GAAS,CAAO,CAAC;AAqBhE"}
@@ -0,0 +1,2 @@
1
+ const e=require("./sleep.cjs");async function t(t,{interval:n=100,signal:r,timeout:i=5e3}={}){let a=AbortSignal.timeout(i),o=r?AbortSignal.any([r,a]):a;for(o.throwIfAborted();;){if(o.throwIfAborted(),await t(o))return;await e.sleep(n,o)}}exports.waitFor=t;
2
+ //# sourceMappingURL=waitFor.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"waitFor.cjs","names":[],"sources":["../../src/async/waitFor.ts"],"sourcesContent":["import { sleep } from './sleep';\n\nexport type WaitForOptions = {\n interval?: number;\n signal?: AbortSignal;\n timeout?: number;\n};\n\n/**\n * Waits for a condition to become true by polling.\n * Useful for waiting for DOM elements, API states, or other conditions.\n *\n * @example\n * ```ts\n * // Wait for an element to appear\n * await waitFor(() => document.querySelector('#myElement') !== null);\n *\n * // Wait for API to be ready with cancellation support\n * await waitFor(\n * async (signal) => {\n * const res = await fetch('/api/health', { signal });\n * return res.ok;\n * },\n * { timeout: 30000, interval: 1000 },\n * );\n * ```\n *\n * @param condition - Polling function that receives the merged AbortSignal and returns true when the condition is met\n * @param options - Configuration options\n * @param [options.timeout=5000] - Maximum time to wait in ms\n * @param [options.interval=100] - Polling interval in ms\n * @param [options.signal] - AbortSignal to cancel waiting\n * @returns Promise that resolves when condition becomes true\n * @throws Rejects with the abort reason when timed out or cancelled\n */\nexport async function waitFor(\n condition: (signal: AbortSignal) => boolean | Promise<boolean>,\n { interval = 100, signal, timeout: ms = 5000 }: WaitForOptions = {},\n): Promise<void> {\n const deadline = AbortSignal.timeout(ms);\n const merged = signal ? AbortSignal.any([signal, deadline]) : deadline;\n\n merged.throwIfAborted();\n\n while (true) {\n merged.throwIfAborted();\n\n if (await condition(merged)) return;\n\n await sleep(interval, merged);\n }\n}\n"],"mappings":"+BAmCA,eAAsB,EACpB,EACA,CAAE,WAAW,IAAK,SAAQ,QAAS,EAAK,KAAyB,CAAC,EACnD,CACf,IAAM,EAAW,YAAY,QAAQ,CAAE,EACjC,EAAS,EAAS,YAAY,IAAI,CAAC,EAAQ,CAAQ,CAAC,EAAI,EAI9D,IAFA,EAAO,eAAe,IAET,CAGX,GAFA,EAAO,eAAe,EAElB,MAAM,EAAU,CAAM,EAAG,OAE7B,MAAM,EAAA,MAAM,EAAU,CAAM,CAC9B,CACF"}
@@ -0,0 +1,34 @@
1
+ export type WaitForOptions = {
2
+ interval?: number;
3
+ signal?: AbortSignal;
4
+ timeout?: number;
5
+ };
6
+ /**
7
+ * Waits for a condition to become true by polling.
8
+ * Useful for waiting for DOM elements, API states, or other conditions.
9
+ *
10
+ * @example
11
+ * ```ts
12
+ * // Wait for an element to appear
13
+ * await waitFor(() => document.querySelector('#myElement') !== null);
14
+ *
15
+ * // Wait for API to be ready with cancellation support
16
+ * await waitFor(
17
+ * async (signal) => {
18
+ * const res = await fetch('/api/health', { signal });
19
+ * return res.ok;
20
+ * },
21
+ * { timeout: 30000, interval: 1000 },
22
+ * );
23
+ * ```
24
+ *
25
+ * @param condition - Polling function that receives the merged AbortSignal and returns true when the condition is met
26
+ * @param options - Configuration options
27
+ * @param [options.timeout=5000] - Maximum time to wait in ms
28
+ * @param [options.interval=100] - Polling interval in ms
29
+ * @param [options.signal] - AbortSignal to cancel waiting
30
+ * @returns Promise that resolves when condition becomes true
31
+ * @throws Rejects with the abort reason when timed out or cancelled
32
+ */
33
+ export declare function waitFor(condition: (signal: AbortSignal) => boolean | Promise<boolean>, { interval, signal, timeout: ms }?: WaitForOptions): Promise<void>;
34
+ //# sourceMappingURL=waitFor.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"waitFor.d.ts","sourceRoot":"","sources":["../../src/async/waitFor.ts"],"names":[],"mappings":"AAEA,MAAM,MAAM,cAAc,GAAG;IAC3B,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,MAAM,CAAC,EAAE,WAAW,CAAC;IACrB,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB,CAAC;AAEF;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AACH,wBAAsB,OAAO,CAC3B,SAAS,EAAE,CAAC,MAAM,EAAE,WAAW,KAAK,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC,EAC9D,EAAE,QAAc,EAAE,MAAM,EAAE,OAAO,EAAE,EAAS,EAAE,GAAE,cAAmB,GAClE,OAAO,CAAC,IAAI,CAAC,CAaf"}
@@ -0,0 +1,13 @@
1
+ import { sleep as e } from "./sleep.js";
2
+ //#region src/async/waitFor.ts
3
+ async function t(t, { interval: n = 100, signal: r, timeout: i = 5e3 } = {}) {
4
+ let a = AbortSignal.timeout(i), o = r ? AbortSignal.any([r, a]) : a;
5
+ for (o.throwIfAborted();;) {
6
+ if (o.throwIfAborted(), await t(o)) return;
7
+ await e(n, o);
8
+ }
9
+ }
10
+ //#endregion
11
+ export { t as waitFor };
12
+
13
+ //# sourceMappingURL=waitFor.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"waitFor.js","names":[],"sources":["../../src/async/waitFor.ts"],"sourcesContent":["import { sleep } from './sleep';\n\nexport type WaitForOptions = {\n interval?: number;\n signal?: AbortSignal;\n timeout?: number;\n};\n\n/**\n * Waits for a condition to become true by polling.\n * Useful for waiting for DOM elements, API states, or other conditions.\n *\n * @example\n * ```ts\n * // Wait for an element to appear\n * await waitFor(() => document.querySelector('#myElement') !== null);\n *\n * // Wait for API to be ready with cancellation support\n * await waitFor(\n * async (signal) => {\n * const res = await fetch('/api/health', { signal });\n * return res.ok;\n * },\n * { timeout: 30000, interval: 1000 },\n * );\n * ```\n *\n * @param condition - Polling function that receives the merged AbortSignal and returns true when the condition is met\n * @param options - Configuration options\n * @param [options.timeout=5000] - Maximum time to wait in ms\n * @param [options.interval=100] - Polling interval in ms\n * @param [options.signal] - AbortSignal to cancel waiting\n * @returns Promise that resolves when condition becomes true\n * @throws Rejects with the abort reason when timed out or cancelled\n */\nexport async function waitFor(\n condition: (signal: AbortSignal) => boolean | Promise<boolean>,\n { interval = 100, signal, timeout: ms = 5000 }: WaitForOptions = {},\n): Promise<void> {\n const deadline = AbortSignal.timeout(ms);\n const merged = signal ? AbortSignal.any([signal, deadline]) : deadline;\n\n merged.throwIfAborted();\n\n while (true) {\n merged.throwIfAborted();\n\n if (await condition(merged)) return;\n\n await sleep(interval, merged);\n }\n}\n"],"mappings":";;AAmCA,eAAsB,EACpB,GACA,EAAE,cAAW,KAAK,WAAQ,SAAS,IAAK,QAAyB,CAAC,GACnD;CACf,IAAM,IAAW,YAAY,QAAQ,CAAE,GACjC,IAAS,IAAS,YAAY,IAAI,CAAC,GAAQ,CAAQ,CAAC,IAAI;CAI9D,KAFA,EAAO,eAAe,KAET;EAGX,IAFA,EAAO,eAAe,GAElB,MAAM,EAAU,CAAM,GAAG;EAE7B,MAAM,EAAM,GAAU,CAAM;CAC9B;AACF"}
@@ -0,0 +1,3 @@
1
+ export * from './memo';
2
+ export * from './stash';
3
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/cache/index.ts"],"names":[],"mappings":"AAAA,cAAc,QAAQ,CAAC;AACvB,cAAc,SAAS,CAAC"}
@@ -0,0 +1,2 @@
1
+ const e=require("../errors.cjs"),t=require("../_common/_lruMap.cjs");var n=`\0undefined\0`,r=`\0NaN\0`,i=`\0+Infinity\0`,a=`\0-Infinity\0`,o=`\0function\0`,s=0,c=new WeakMap;function l(e){let t=c.get(e);return t===void 0&&(t=s++,c.set(e,t)),t}var u=t=>{try{return JSON.stringify(t,(e,t)=>t===void 0?n:typeof t==`number`&&Number.isNaN(t)?r:t===1/0?i:t===-1/0?a:typeof t==`function`?`${o}${l(t)}`:t)}catch(t){throw new e.ArsenalSerializationError(`[arsenal/memo] Failed to serialize memo arguments. Provide options.key for non-serializable arguments.${t instanceof Error&&t.message?` Reason: ${t.message}`:``}`,{cause:t})}};function d(n,{key:r,maxSize:i=1/0}={}){if(i!==1/0&&(!Number.isInteger(i)||i<1))throw new e.ArsenalValidationError(`memo: maxSize must be a positive integer or Infinity, got ${i}`);let a=new t.LruMap(i),o=(...e)=>r?r(...e):u(e),s=Object.assign((...e)=>{let t=o(...e);if(a.has(t)){let e=a.get(t);return a.set(t,e),e}let r=n(...e);return a.set(t,r),r},{clear:()=>a.clear(),invalidate:(...e)=>{a.delete(o(...e))}});return Object.defineProperty(s,"size",{get:()=>a.size}),s}exports.memo=d;
2
+ //# sourceMappingURL=memo.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"memo.cjs","names":[],"sources":["../../src/cache/memo.ts"],"sourcesContent":["import type { Fn } from '../types';\n\nimport { LruMap } from '../_common/_lruMap';\nimport { ArsenalSerializationError, ArsenalValidationError } from '../errors';\n\nexport type MemoOptions<T extends Fn> = {\n key?: (...args: Parameters<T>) => PropertyKey;\n maxSize?: number;\n};\n\nexport type Memoized<T extends Fn> = ((...args: Parameters<T>) => ReturnType<T>) & {\n clear(): void;\n invalidate(...args: Parameters<T>): void;\n readonly size: number;\n};\n\nconst UNDEFINED_SENTINEL = '\\x00undefined\\x00';\nconst NAN_SENTINEL = '\\x00NaN\\x00';\nconst POSITIVE_INFINITY_SENTINEL = '\\x00+Infinity\\x00';\nconst NEGATIVE_INFINITY_SENTINEL = '\\x00-Infinity\\x00';\nconst FUNCTION_SENTINEL = '\\x00function\\x00';\n\nlet functionIdCounter = 0;\nconst functionIds = new WeakMap<Fn, number>();\n\n/** Returns a stable per-identity id for a function so distinct functions never collide as cache keys. */\nfunction idForFunction(fn: Fn): number {\n let id = functionIds.get(fn);\n\n if (id === undefined) {\n id = functionIdCounter++;\n functionIds.set(fn, id);\n }\n\n return id;\n}\n\nconst defaultKey = (args: unknown[]): string => {\n try {\n return JSON.stringify(args, (_, value) => {\n if (value === undefined) return UNDEFINED_SENTINEL;\n\n if (typeof value === 'number' && Number.isNaN(value)) return NAN_SENTINEL;\n\n if (value === Number.POSITIVE_INFINITY) return POSITIVE_INFINITY_SENTINEL;\n\n if (value === Number.NEGATIVE_INFINITY) return NEGATIVE_INFINITY_SENTINEL;\n\n if (typeof value === 'function') return `${FUNCTION_SENTINEL}${idForFunction(value as Fn)}`;\n\n return value;\n });\n } catch (error) {\n const reason = error instanceof Error && error.message ? ` Reason: ${error.message}` : '';\n\n throw new ArsenalSerializationError(\n `[arsenal/memo] Failed to serialize memo arguments. Provide options.key for non-serializable arguments.${reason}`,\n { cause: error },\n );\n }\n};\n\n/** Excludes async functions at the type level so callers cannot accidentally memoize a Promise. */\ntype SyncFn<T extends Fn> = ReturnType<T> extends Promise<unknown> ? never : T;\n\n/**\n * Memoizes a **sync** function with optional LRU eviction by cache size.\n * The returned function exposes `.clear()` and `.invalidate(...args)` methods.\n *\n * **Do not pass async functions.** `memo` caches the raw `Promise` object, not\n * the resolved value — subsequent calls return the same stale Promise. Use\n * `stash.getOrSet` for async caching with TTL and stampede prevention.\n *\n * @example\n * ```ts\n * const add = (x: number, y: number) => x + y;\n * const memoAdd = memo(add, { maxSize: 100 });\n *\n * memoAdd(1, 2); // 3 (computed)\n * memoAdd(1, 2); // 3 (from cache)\n * memoAdd.invalidate(1, 2); // remove specific entry\n * memoAdd.clear(); // wipe entire cache\n * ```\n *\n * @param fn - The sync function to memoize. Must not return a Promise.\n * @param [options.maxSize] - Maximum cache size. Oldest entries evicted when exceeded (LRU). Default: `Infinity`.\n * @param [options.key] - Custom cache key function. Defaults to `JSON.stringify(args)`.\n *\n * @throws {ArsenalValidationError} If `maxSize` is not a positive integer or `Infinity`.\n */\nexport function memo<T extends Fn>(fn: SyncFn<T>, { key, maxSize = Infinity }: MemoOptions<T> = {}): Memoized<T> {\n if (maxSize !== Infinity && (!Number.isInteger(maxSize) || maxSize < 1)) {\n throw new ArsenalValidationError(`memo: maxSize must be a positive integer or Infinity, got ${maxSize}`);\n }\n\n const cache = new LruMap<PropertyKey, ReturnType<T>>(maxSize);\n\n const resolveKey = (...args: Parameters<T>): PropertyKey => (key ? key(...args) : defaultKey(args));\n\n const memoized = (...args: Parameters<T>): ReturnType<T> => {\n const cacheKey = resolveKey(...args);\n\n if (cache.has(cacheKey)) {\n const cached = cache.get(cacheKey)!;\n\n cache.set(cacheKey, cached);\n\n return cached;\n }\n\n const value = fn(...args) as ReturnType<T>;\n\n cache.set(cacheKey, value);\n\n return value;\n };\n\n const result = Object.assign(memoized, {\n clear: () => cache.clear(),\n invalidate: (...args: Parameters<T>): void => {\n cache.delete(resolveKey(...args));\n },\n });\n\n Object.defineProperty(result, 'size', { get: () => cache.size });\n\n return result as Memoized<T>;\n}\n"],"mappings":"qEAgBA,IAAM,EAAqB,gBACrB,EAAe,UACf,EAA6B,gBAC7B,EAA6B,gBAC7B,EAAoB,eAEtB,EAAoB,EAClB,EAAc,IAAI,QAGxB,SAAS,EAAc,EAAgB,CACrC,IAAI,EAAK,EAAY,IAAI,CAAE,EAO3B,OALI,IAAO,IAAA,KACT,EAAK,IACL,EAAY,IAAI,EAAI,CAAE,GAGjB,CACT,CAEA,IAAM,EAAc,GAA4B,CAC9C,GAAI,CACF,OAAO,KAAK,UAAU,GAAO,EAAG,IAC1B,IAAU,IAAA,GAAkB,EAE5B,OAAO,GAAU,UAAY,OAAO,MAAM,CAAK,EAAU,EAEzD,IAAU,IAAiC,EAE3C,IAAU,KAAiC,EAE3C,OAAO,GAAU,WAAmB,GAAG,IAAoB,EAAc,CAAW,IAEjF,CACR,CACH,OAAS,EAAO,CAGd,MAAM,IAAI,EAAA,0BACR,yGAHa,aAAiB,OAAS,EAAM,QAAU,YAAY,EAAM,UAAY,KAIrF,CAAE,MAAO,CAAM,CACjB,CACF,CACF,EA8BA,SAAgB,EAAmB,EAAe,CAAE,MAAK,UAAU,KAA6B,CAAC,EAAgB,CAC/G,GAAI,IAAY,MAAa,CAAC,OAAO,UAAU,CAAO,GAAK,EAAU,GACnE,MAAM,IAAI,EAAA,uBAAuB,6DAA6D,GAAS,EAGzG,IAAM,EAAQ,IAAI,EAAA,OAAmC,CAAO,EAEtD,GAAc,GAAG,IAAsC,EAAM,EAAI,GAAG,CAAI,EAAI,EAAW,CAAI,EAoB3F,EAAS,OAAO,QAlBJ,GAAG,IAAuC,CAC1D,IAAM,EAAW,EAAW,GAAG,CAAI,EAEnC,GAAI,EAAM,IAAI,CAAQ,EAAG,CACvB,IAAM,EAAS,EAAM,IAAI,CAAQ,EAIjC,OAFA,EAAM,IAAI,EAAU,CAAM,EAEnB,CACT,CAEA,IAAM,EAAQ,EAAG,GAAG,CAAI,EAIxB,OAFA,EAAM,IAAI,EAAU,CAAK,EAElB,CACT,EAEuC,CACrC,UAAa,EAAM,MAAM,EACzB,YAAa,GAAG,IAA8B,CAC5C,EAAM,OAAO,EAAW,GAAG,CAAI,CAAC,CAClC,CACF,CAAC,EAID,OAFA,OAAO,eAAe,EAAQ,OAAQ,CAAE,QAAW,EAAM,IAAK,CAAC,EAExD,CACT"}
@@ -0,0 +1,40 @@
1
+ import type { Fn } from '../types';
2
+ export type MemoOptions<T extends Fn> = {
3
+ key?: (...args: Parameters<T>) => PropertyKey;
4
+ maxSize?: number;
5
+ };
6
+ export type Memoized<T extends Fn> = ((...args: Parameters<T>) => ReturnType<T>) & {
7
+ clear(): void;
8
+ invalidate(...args: Parameters<T>): void;
9
+ readonly size: number;
10
+ };
11
+ /** Excludes async functions at the type level so callers cannot accidentally memoize a Promise. */
12
+ type SyncFn<T extends Fn> = ReturnType<T> extends Promise<unknown> ? never : T;
13
+ /**
14
+ * Memoizes a **sync** function with optional LRU eviction by cache size.
15
+ * The returned function exposes `.clear()` and `.invalidate(...args)` methods.
16
+ *
17
+ * **Do not pass async functions.** `memo` caches the raw `Promise` object, not
18
+ * the resolved value — subsequent calls return the same stale Promise. Use
19
+ * `stash.getOrSet` for async caching with TTL and stampede prevention.
20
+ *
21
+ * @example
22
+ * ```ts
23
+ * const add = (x: number, y: number) => x + y;
24
+ * const memoAdd = memo(add, { maxSize: 100 });
25
+ *
26
+ * memoAdd(1, 2); // 3 (computed)
27
+ * memoAdd(1, 2); // 3 (from cache)
28
+ * memoAdd.invalidate(1, 2); // remove specific entry
29
+ * memoAdd.clear(); // wipe entire cache
30
+ * ```
31
+ *
32
+ * @param fn - The sync function to memoize. Must not return a Promise.
33
+ * @param [options.maxSize] - Maximum cache size. Oldest entries evicted when exceeded (LRU). Default: `Infinity`.
34
+ * @param [options.key] - Custom cache key function. Defaults to `JSON.stringify(args)`.
35
+ *
36
+ * @throws {ArsenalValidationError} If `maxSize` is not a positive integer or `Infinity`.
37
+ */
38
+ export declare function memo<T extends Fn>(fn: SyncFn<T>, { key, maxSize }?: MemoOptions<T>): Memoized<T>;
39
+ export {};
40
+ //# sourceMappingURL=memo.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"memo.d.ts","sourceRoot":"","sources":["../../src/cache/memo.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,EAAE,EAAE,MAAM,UAAU,CAAC;AAKnC,MAAM,MAAM,WAAW,CAAC,CAAC,SAAS,EAAE,IAAI;IACtC,GAAG,CAAC,EAAE,CAAC,GAAG,IAAI,EAAE,UAAU,CAAC,CAAC,CAAC,KAAK,WAAW,CAAC;IAC9C,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB,CAAC;AAEF,MAAM,MAAM,QAAQ,CAAC,CAAC,SAAS,EAAE,IAAI,CAAC,CAAC,GAAG,IAAI,EAAE,UAAU,CAAC,CAAC,CAAC,KAAK,UAAU,CAAC,CAAC,CAAC,CAAC,GAAG;IACjF,KAAK,IAAI,IAAI,CAAC;IACd,UAAU,CAAC,GAAG,IAAI,EAAE,UAAU,CAAC,CAAC,CAAC,GAAG,IAAI,CAAC;IACzC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;CACvB,CAAC;AAgDF,mGAAmG;AACnG,KAAK,MAAM,CAAC,CAAC,SAAS,EAAE,IAAI,UAAU,CAAC,CAAC,CAAC,SAAS,OAAO,CAAC,OAAO,CAAC,GAAG,KAAK,GAAG,CAAC,CAAC;AAE/E;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AACH,wBAAgB,IAAI,CAAC,CAAC,SAAS,EAAE,EAAE,EAAE,EAAE,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,GAAG,EAAE,OAAkB,EAAE,GAAE,WAAW,CAAC,CAAC,CAAM,GAAG,QAAQ,CAAC,CAAC,CAAC,CAqC/G"}
@@ -0,0 +1,37 @@
1
+ import { ArsenalSerializationError as e, ArsenalValidationError as t } from "../errors.js";
2
+ import { LruMap as n } from "../_common/_lruMap.js";
3
+ //#region src/cache/memo.ts
4
+ var r = "\0undefined\0", i = "\0NaN\0", a = "\0+Infinity\0", o = "\0-Infinity\0", s = "\0function\0", c = 0, l = /* @__PURE__ */ new WeakMap();
5
+ function u(e) {
6
+ let t = l.get(e);
7
+ return t === void 0 && (t = c++, l.set(e, t)), t;
8
+ }
9
+ var d = (t) => {
10
+ try {
11
+ return JSON.stringify(t, (e, t) => t === void 0 ? r : typeof t == "number" && Number.isNaN(t) ? i : t === Infinity ? a : t === -Infinity ? o : typeof t == "function" ? `${s}${u(t)}` : t);
12
+ } catch (t) {
13
+ throw new e(`[arsenal/memo] Failed to serialize memo arguments. Provide options.key for non-serializable arguments.${t instanceof Error && t.message ? ` Reason: ${t.message}` : ""}`, { cause: t });
14
+ }
15
+ };
16
+ function f(e, { key: r, maxSize: i = Infinity } = {}) {
17
+ if (i !== Infinity && (!Number.isInteger(i) || i < 1)) throw new t(`memo: maxSize must be a positive integer or Infinity, got ${i}`);
18
+ let a = new n(i), o = (...e) => r ? r(...e) : d(e), s = Object.assign((...t) => {
19
+ let n = o(...t);
20
+ if (a.has(n)) {
21
+ let e = a.get(n);
22
+ return a.set(n, e), e;
23
+ }
24
+ let r = e(...t);
25
+ return a.set(n, r), r;
26
+ }, {
27
+ clear: () => a.clear(),
28
+ invalidate: (...e) => {
29
+ a.delete(o(...e));
30
+ }
31
+ });
32
+ return Object.defineProperty(s, "size", { get: () => a.size }), s;
33
+ }
34
+ //#endregion
35
+ export { f as memo };
36
+
37
+ //# sourceMappingURL=memo.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"memo.js","names":[],"sources":["../../src/cache/memo.ts"],"sourcesContent":["import type { Fn } from '../types';\n\nimport { LruMap } from '../_common/_lruMap';\nimport { ArsenalSerializationError, ArsenalValidationError } from '../errors';\n\nexport type MemoOptions<T extends Fn> = {\n key?: (...args: Parameters<T>) => PropertyKey;\n maxSize?: number;\n};\n\nexport type Memoized<T extends Fn> = ((...args: Parameters<T>) => ReturnType<T>) & {\n clear(): void;\n invalidate(...args: Parameters<T>): void;\n readonly size: number;\n};\n\nconst UNDEFINED_SENTINEL = '\\x00undefined\\x00';\nconst NAN_SENTINEL = '\\x00NaN\\x00';\nconst POSITIVE_INFINITY_SENTINEL = '\\x00+Infinity\\x00';\nconst NEGATIVE_INFINITY_SENTINEL = '\\x00-Infinity\\x00';\nconst FUNCTION_SENTINEL = '\\x00function\\x00';\n\nlet functionIdCounter = 0;\nconst functionIds = new WeakMap<Fn, number>();\n\n/** Returns a stable per-identity id for a function so distinct functions never collide as cache keys. */\nfunction idForFunction(fn: Fn): number {\n let id = functionIds.get(fn);\n\n if (id === undefined) {\n id = functionIdCounter++;\n functionIds.set(fn, id);\n }\n\n return id;\n}\n\nconst defaultKey = (args: unknown[]): string => {\n try {\n return JSON.stringify(args, (_, value) => {\n if (value === undefined) return UNDEFINED_SENTINEL;\n\n if (typeof value === 'number' && Number.isNaN(value)) return NAN_SENTINEL;\n\n if (value === Number.POSITIVE_INFINITY) return POSITIVE_INFINITY_SENTINEL;\n\n if (value === Number.NEGATIVE_INFINITY) return NEGATIVE_INFINITY_SENTINEL;\n\n if (typeof value === 'function') return `${FUNCTION_SENTINEL}${idForFunction(value as Fn)}`;\n\n return value;\n });\n } catch (error) {\n const reason = error instanceof Error && error.message ? ` Reason: ${error.message}` : '';\n\n throw new ArsenalSerializationError(\n `[arsenal/memo] Failed to serialize memo arguments. Provide options.key for non-serializable arguments.${reason}`,\n { cause: error },\n );\n }\n};\n\n/** Excludes async functions at the type level so callers cannot accidentally memoize a Promise. */\ntype SyncFn<T extends Fn> = ReturnType<T> extends Promise<unknown> ? never : T;\n\n/**\n * Memoizes a **sync** function with optional LRU eviction by cache size.\n * The returned function exposes `.clear()` and `.invalidate(...args)` methods.\n *\n * **Do not pass async functions.** `memo` caches the raw `Promise` object, not\n * the resolved value — subsequent calls return the same stale Promise. Use\n * `stash.getOrSet` for async caching with TTL and stampede prevention.\n *\n * @example\n * ```ts\n * const add = (x: number, y: number) => x + y;\n * const memoAdd = memo(add, { maxSize: 100 });\n *\n * memoAdd(1, 2); // 3 (computed)\n * memoAdd(1, 2); // 3 (from cache)\n * memoAdd.invalidate(1, 2); // remove specific entry\n * memoAdd.clear(); // wipe entire cache\n * ```\n *\n * @param fn - The sync function to memoize. Must not return a Promise.\n * @param [options.maxSize] - Maximum cache size. Oldest entries evicted when exceeded (LRU). Default: `Infinity`.\n * @param [options.key] - Custom cache key function. Defaults to `JSON.stringify(args)`.\n *\n * @throws {ArsenalValidationError} If `maxSize` is not a positive integer or `Infinity`.\n */\nexport function memo<T extends Fn>(fn: SyncFn<T>, { key, maxSize = Infinity }: MemoOptions<T> = {}): Memoized<T> {\n if (maxSize !== Infinity && (!Number.isInteger(maxSize) || maxSize < 1)) {\n throw new ArsenalValidationError(`memo: maxSize must be a positive integer or Infinity, got ${maxSize}`);\n }\n\n const cache = new LruMap<PropertyKey, ReturnType<T>>(maxSize);\n\n const resolveKey = (...args: Parameters<T>): PropertyKey => (key ? key(...args) : defaultKey(args));\n\n const memoized = (...args: Parameters<T>): ReturnType<T> => {\n const cacheKey = resolveKey(...args);\n\n if (cache.has(cacheKey)) {\n const cached = cache.get(cacheKey)!;\n\n cache.set(cacheKey, cached);\n\n return cached;\n }\n\n const value = fn(...args) as ReturnType<T>;\n\n cache.set(cacheKey, value);\n\n return value;\n };\n\n const result = Object.assign(memoized, {\n clear: () => cache.clear(),\n invalidate: (...args: Parameters<T>): void => {\n cache.delete(resolveKey(...args));\n },\n });\n\n Object.defineProperty(result, 'size', { get: () => cache.size });\n\n return result as Memoized<T>;\n}\n"],"mappings":";;;AAgBA,IAAM,IAAqB,iBACrB,IAAe,WACf,IAA6B,iBAC7B,IAA6B,iBAC7B,IAAoB,gBAEtB,IAAoB,GAClB,oBAAc,IAAI,QAAoB;AAG5C,SAAS,EAAc,GAAgB;CACrC,IAAI,IAAK,EAAY,IAAI,CAAE;CAO3B,OALI,MAAO,KAAA,MACT,IAAK,KACL,EAAY,IAAI,GAAI,CAAE,IAGjB;AACT;AAEA,IAAM,KAAc,MAA4B;CAC9C,IAAI;EACF,OAAO,KAAK,UAAU,IAAO,GAAG,MAC1B,MAAU,KAAA,IAAkB,IAE5B,OAAO,KAAU,YAAY,OAAO,MAAM,CAAK,IAAU,IAEzD,MAAU,WAAiC,IAE3C,MAAU,YAAiC,IAE3C,OAAO,KAAU,aAAmB,GAAG,IAAoB,EAAc,CAAW,MAEjF,CACR;CACH,SAAS,GAAO;EAGd,MAAM,IAAI,EACR,yGAHa,aAAiB,SAAS,EAAM,UAAU,YAAY,EAAM,YAAY,MAIrF,EAAE,OAAO,EAAM,CACjB;CACF;AACF;AA8BA,SAAgB,EAAmB,GAAe,EAAE,QAAK,aAAU,aAA6B,CAAC,GAAgB;CAC/G,IAAI,MAAY,aAAa,CAAC,OAAO,UAAU,CAAO,KAAK,IAAU,IACnE,MAAM,IAAI,EAAuB,6DAA6D,GAAS;CAGzG,IAAM,IAAQ,IAAI,EAAmC,CAAO,GAEtD,KAAc,GAAG,MAAsC,IAAM,EAAI,GAAG,CAAI,IAAI,EAAW,CAAI,GAoB3F,IAAS,OAAO,QAlBJ,GAAG,MAAuC;EAC1D,IAAM,IAAW,EAAW,GAAG,CAAI;EAEnC,IAAI,EAAM,IAAI,CAAQ,GAAG;GACvB,IAAM,IAAS,EAAM,IAAI,CAAQ;GAIjC,OAFA,EAAM,IAAI,GAAU,CAAM,GAEnB;EACT;EAEA,IAAM,IAAQ,EAAG,GAAG,CAAI;EAIxB,OAFA,EAAM,IAAI,GAAU,CAAK,GAElB;CACT,GAEuC;EACrC,aAAa,EAAM,MAAM;EACzB,aAAa,GAAG,MAA8B;GAC5C,EAAM,OAAO,EAAW,GAAG,CAAI,CAAC;EAClC;CACF,CAAC;CAID,OAFA,OAAO,eAAe,GAAQ,QAAQ,EAAE,WAAW,EAAM,KAAK,CAAC,GAExD;AACT"}
@@ -0,0 +1,2 @@
1
+ const e=require("../errors.cjs"),t=require("../guards/isPromise.cjs");function n(n={}){let r=n.maxSize??1/0;if(r!==1/0&&(!Number.isInteger(r)||r<1))throw new e.ArsenalValidationError(`stash: maxSize must be a positive integer or Infinity, got ${r}`);let i=new Map,a=new Map,o=new Map,s=n.hash??(e=>String(e)),c=n.onEvict,l=n.ttlMs,u=n.persistence,d=0,f=new Set;function p(){if(i.size>r){let[e]=i.keys();e!==void 0&&h(e)}}function m(e){let t=a.get(e);t!==void 0&&(clearTimeout(t),a.delete(e))}function h(e){let t=i.get(e);return m(e),t&&(c?.(t.key,t.value),i.delete(e)),o.has(e)&&f.add(e),t!==void 0}function g(t,n){if(m(t),n===1/0)return;if(!Number.isFinite(n))throw new e.ArsenalValidationError(`stash: ttlMs must be a finite number or Infinity`);if(n<=0){h(t);return}if(!i.has(t))return;let r=setTimeout(()=>{a.delete(t),h(t)},n);a.set(t,r)}function _(e){return u&&typeof e==`string`?u.deserialize(e):e}function v(e){let t=i.get(s(e));return t?_(t.value):void 0}function y(e,t,n){let r=s(e),a=u?u.serialize(t):t;m(r),i.set(r,{key:e,value:a}),p();let o=n?.ttlMs??l;o!==void 0&&g(r,o)}function b(e,n,r){let a=s(e);if(i.has(a)&&!r?.forceRefresh)return v(e);let c=o.get(a);if(c&&!r?.forceRefresh)return c;let l=n();if(t.isPromise(l)){let t=d,n=l.then(i=>(o.get(a)===n&&o.delete(a),d===t&&!f.has(a)&&y(e,i,r),f.delete(a),i)).catch(e=>{throw o.get(a)===n&&o.delete(a),f.delete(a),e});return o.set(a,n),n}return y(e,l,r),l}function x(e){return h(s(e))}function S(){d++;for(let e of a.values())clearTimeout(e);if(c)for(let e of i.values())c(e.key,e.value);i.clear(),a.clear(),o.clear(),f.clear()}function*C(){for(let e of i.values())yield[e.key,_(e.value)]}return{clear:S,delete:x,entries:C,get:v,getOrSet:b,set:y,get size(){return i.size}}}exports.stash=n;
2
+ //# sourceMappingURL=stash.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"stash.cjs","names":[],"sources":["../../src/cache/stash.ts"],"sourcesContent":["import { ArsenalValidationError } from '../errors';\nimport { isPromise } from '../guards/isPromise';\n\ntype CacheRecord<K, T> = {\n key: K;\n value: T;\n};\n\nexport type CachePersistence<T> = {\n /** Deserializes a stored string back into a value of type `T`. */\n deserialize: (raw: string) => T;\n /** Serializes a value to a string for internal storage. */\n serialize: (value: T) => string;\n};\n\nexport type CacheOptions<K = string, T = unknown> = {\n /**\n * Converts a key to its canonical string representation for internal storage.\n * Defaults to `String(key)` — suitable for all string, number, and symbol keys.\n * Provide a custom function for object keys or composite keys.\n */\n hash?: (key: K) => string;\n /**\n * Maximum number of entries to hold. When the store reaches capacity, the oldest\n * entry is evicted (FIFO) before inserting the new one. `onEvict` is called on\n * capacity evictions just like TTL evictions.\n *\n * Default: `Infinity` (unbounded).\n */\n maxSize?: number;\n onEvict?: (key: K, value: T) => void;\n /**\n * Optional serialization pair for persistent caches (e.g. localStorage, cross-process IPC).\n * Both `serialize` and `deserialize` must be provided together.\n *\n * @example\n * ```ts\n * const cache = stash<User>({\n * persistence: {\n * serialize: (u) => JSON.stringify(u),\n * deserialize: (raw) => JSON.parse(raw) as User,\n * },\n * });\n * ```\n */\n persistence?: CachePersistence<T>;\n /**\n * Default time-to-live for all entries in milliseconds.\n * Applied automatically to every `set()` and `getOrSet()` call unless\n * overridden per-entry via `CacheSetOptions.ttlMs`.\n *\n * Default: `undefined` (entries do not expire).\n */\n ttlMs?: number;\n};\n\nexport type CacheSetOptions = {\n /**\n * When `true`, bypasses both the cache and any in-flight promise for this key,\n * and always calls the factory. The new value replaces the old cache entry.\n * **Note:** if a prior in-flight is still pending when `forceRefresh` resolves,\n * whichever `.then` runs last will write the cache slot — ensure prior in-flight\n * tasks have settled if ordering matters.\n */\n forceRefresh?: boolean;\n ttlMs?: number;\n};\n\nexport type Stash<T, K = string> = {\n clear: () => void;\n delete: (key: K) => boolean;\n entries: () => IterableIterator<[K, T]>;\n get: (key: K) => T | undefined;\n /**\n * Returns the cached value for `key`, or invokes `factory` to produce and cache it.\n * Pass `{ forceRefresh: true }` to skip the cache and always call `factory`.\n */\n getOrSet(key: K, factory: () => T, options?: CacheSetOptions): T;\n getOrSet(key: K, factory: () => Promise<T>, options?: CacheSetOptions): Promise<T>;\n set: (key: K, value: T, options?: CacheSetOptions) => void;\n readonly size: number;\n};\n\n/**\n * Creates a generic key-value cache with TTL-based garbage collection, optional capacity\n * limit (FIFO eviction), async stampede prevention, and optional eviction callback.\n *\n * This is the single caching primitive in arsenal — use it for simple bounded caches,\n * TTL caches, or async deduplication/stampede prevention.\n *\n * @example\n * ```ts\n * // Simple string cache — no options needed for string keys\n * const myCache = stash<string>();\n * myCache.set('user:1', 'John Doe');\n * const value = myCache.get('user:1'); // 'John Doe'\n *\n * // Global TTL — all entries expire after 60 seconds unless overridden\n * const apiCache = stash<Response>({ ttlMs: 60_000 });\n * apiCache.set('data', response); // expires in 60s\n * apiCache.set('data', response, { ttlMs: 5_000 }); // override: expires in 5s\n *\n * // Async getOrSet prevents stampedes — concurrent callers share one in-flight promise\n * const user = await myCache.getOrSet('user:1', () => fetchUser(1));\n *\n * // Bounded FIFO cache\n * const fmtCache = stash<Intl.NumberFormat>({ maxSize: 64 });\n * const fmt = fmtCache.getOrSet('en-US', () => new Intl.NumberFormat('en-US'));\n *\n * // Custom key type — provide a hash function\n * const objCache = stash<Result, { id: number }>({ hash: (k) => String(k.id) });\n *\n * // Note: `undefined` is a valid cached value — if a key is set to `undefined`,\n * // `getOrSet` returns it without invoking the factory again.\n * ```\n *\n * @template T - The type of values stored in the cache.\n * @template K - The key type. Defaults to `string`.\n *\n * @throws {ArsenalValidationError} If `options.maxSize` is provided and is not a positive integer or `Infinity`.\n */\nexport function stash<T, K = string>(options: CacheOptions<K, T> = {}): Stash<T, K> {\n const maxSize = options.maxSize ?? Infinity;\n\n if (maxSize !== Infinity && (!Number.isInteger(maxSize) || maxSize < 1)) {\n throw new ArsenalValidationError(`stash: maxSize must be a positive integer or Infinity, got ${maxSize}`);\n }\n\n const store = new Map<string, CacheRecord<K, T>>();\n const gcTimers = new Map<string, ReturnType<typeof setTimeout>>();\n const inFlight = new Map<string, Promise<T>>();\n const hash = options.hash ?? ((key: K) => String(key));\n const onEvict = options.onEvict;\n const defaultTtlMs = options.ttlMs;\n const persistence = options.persistence;\n let generation = 0;\n const deletedWhileInFlight = new Set<string>();\n\n function evictOldestIfOverCapacity(): void {\n if (store.size > maxSize) {\n const [firstHash] = store.keys();\n\n if (firstHash !== undefined) {\n deleteByHash(firstHash);\n }\n }\n }\n\n function cancelGcByHash(keyHash: string): void {\n const id = gcTimers.get(keyHash);\n\n if (id !== undefined) {\n clearTimeout(id);\n gcTimers.delete(keyHash);\n }\n }\n\n function deleteByHash(keyHash: string): boolean {\n const record = store.get(keyHash);\n\n cancelGcByHash(keyHash);\n\n if (record) {\n onEvict?.(record.key, record.value);\n store.delete(keyHash);\n }\n\n if (inFlight.has(keyHash)) deletedWhileInFlight.add(keyHash);\n\n return record !== undefined;\n }\n\n function scheduleGcByHash(keyHash: string, delayMs: number): void {\n cancelGcByHash(keyHash);\n\n if (delayMs === Number.POSITIVE_INFINITY) return;\n\n if (!Number.isFinite(delayMs)) {\n throw new ArsenalValidationError('stash: ttlMs must be a finite number or Infinity');\n }\n\n if (delayMs <= 0) {\n deleteByHash(keyHash);\n\n return;\n }\n\n if (!store.has(keyHash)) return;\n\n const id = setTimeout(() => {\n gcTimers.delete(keyHash);\n deleteByHash(keyHash);\n }, delayMs);\n\n gcTimers.set(keyHash, id);\n }\n\n function deserializeValue(raw: T): T {\n if (persistence && typeof raw === 'string') return persistence.deserialize(raw);\n\n return raw;\n }\n\n function get(key: K): T | undefined {\n const record = store.get(hash(key));\n\n return record ? deserializeValue(record.value) : undefined;\n }\n\n function set(key: K, value: T, opts?: CacheSetOptions): void {\n const keyHash = hash(key);\n const stored = persistence ? (persistence.serialize(value) as unknown as T) : value;\n\n cancelGcByHash(keyHash);\n store.set(keyHash, { key, value: stored });\n evictOldestIfOverCapacity();\n\n const ttl = opts?.ttlMs ?? defaultTtlMs;\n\n if (ttl !== undefined) {\n scheduleGcByHash(keyHash, ttl);\n }\n }\n\n function getOrSet(key: K, factory: () => T | Promise<T>, opts?: CacheSetOptions): T | Promise<T> {\n const keyHash = hash(key);\n\n if (store.has(keyHash) && !opts?.forceRefresh) return get(key) as T;\n\n const pending = inFlight.get(keyHash);\n\n if (pending && !opts?.forceRefresh) return pending;\n\n const value = factory();\n\n if (isPromise(value)) {\n const capturedGeneration = generation;\n const promise: Promise<T> = value\n .then((resolved) => {\n // Only clear the in-flight slot if it's still *this* promise — an overlapping\n // `forceRefresh` call may have already replaced it with a newer in-flight promise.\n if (inFlight.get(keyHash) === promise) inFlight.delete(keyHash);\n\n if (generation === capturedGeneration && !deletedWhileInFlight.has(keyHash)) {\n set(key, resolved, opts);\n }\n\n deletedWhileInFlight.delete(keyHash);\n\n return resolved;\n })\n .catch((err: unknown) => {\n if (inFlight.get(keyHash) === promise) inFlight.delete(keyHash);\n\n deletedWhileInFlight.delete(keyHash);\n throw err;\n });\n\n inFlight.set(keyHash, promise);\n\n return promise;\n }\n\n set(key, value, opts);\n\n return value;\n }\n\n function del(key: K): boolean {\n return deleteByHash(hash(key));\n }\n\n function clear(): void {\n generation++;\n for (const id of gcTimers.values()) clearTimeout(id);\n\n if (onEvict) {\n for (const record of store.values()) {\n onEvict(record.key, record.value);\n }\n }\n\n store.clear();\n gcTimers.clear();\n inFlight.clear();\n deletedWhileInFlight.clear();\n }\n\n function* entries(): IterableIterator<[K, T]> {\n for (const record of store.values()) {\n yield [record.key, deserializeValue(record.value)];\n }\n }\n\n return {\n clear,\n delete: del,\n entries,\n get,\n getOrSet: getOrSet as Stash<T, K>['getOrSet'],\n set,\n get size() {\n return store.size;\n },\n };\n}\n"],"mappings":"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"}
@@ -0,0 +1,111 @@
1
+ export type CachePersistence<T> = {
2
+ /** Deserializes a stored string back into a value of type `T`. */
3
+ deserialize: (raw: string) => T;
4
+ /** Serializes a value to a string for internal storage. */
5
+ serialize: (value: T) => string;
6
+ };
7
+ export type CacheOptions<K = string, T = unknown> = {
8
+ /**
9
+ * Converts a key to its canonical string representation for internal storage.
10
+ * Defaults to `String(key)` — suitable for all string, number, and symbol keys.
11
+ * Provide a custom function for object keys or composite keys.
12
+ */
13
+ hash?: (key: K) => string;
14
+ /**
15
+ * Maximum number of entries to hold. When the store reaches capacity, the oldest
16
+ * entry is evicted (FIFO) before inserting the new one. `onEvict` is called on
17
+ * capacity evictions just like TTL evictions.
18
+ *
19
+ * Default: `Infinity` (unbounded).
20
+ */
21
+ maxSize?: number;
22
+ onEvict?: (key: K, value: T) => void;
23
+ /**
24
+ * Optional serialization pair for persistent caches (e.g. localStorage, cross-process IPC).
25
+ * Both `serialize` and `deserialize` must be provided together.
26
+ *
27
+ * @example
28
+ * ```ts
29
+ * const cache = stash<User>({
30
+ * persistence: {
31
+ * serialize: (u) => JSON.stringify(u),
32
+ * deserialize: (raw) => JSON.parse(raw) as User,
33
+ * },
34
+ * });
35
+ * ```
36
+ */
37
+ persistence?: CachePersistence<T>;
38
+ /**
39
+ * Default time-to-live for all entries in milliseconds.
40
+ * Applied automatically to every `set()` and `getOrSet()` call unless
41
+ * overridden per-entry via `CacheSetOptions.ttlMs`.
42
+ *
43
+ * Default: `undefined` (entries do not expire).
44
+ */
45
+ ttlMs?: number;
46
+ };
47
+ export type CacheSetOptions = {
48
+ /**
49
+ * When `true`, bypasses both the cache and any in-flight promise for this key,
50
+ * and always calls the factory. The new value replaces the old cache entry.
51
+ * **Note:** if a prior in-flight is still pending when `forceRefresh` resolves,
52
+ * whichever `.then` runs last will write the cache slot — ensure prior in-flight
53
+ * tasks have settled if ordering matters.
54
+ */
55
+ forceRefresh?: boolean;
56
+ ttlMs?: number;
57
+ };
58
+ export type Stash<T, K = string> = {
59
+ clear: () => void;
60
+ delete: (key: K) => boolean;
61
+ entries: () => IterableIterator<[K, T]>;
62
+ get: (key: K) => T | undefined;
63
+ /**
64
+ * Returns the cached value for `key`, or invokes `factory` to produce and cache it.
65
+ * Pass `{ forceRefresh: true }` to skip the cache and always call `factory`.
66
+ */
67
+ getOrSet(key: K, factory: () => T, options?: CacheSetOptions): T;
68
+ getOrSet(key: K, factory: () => Promise<T>, options?: CacheSetOptions): Promise<T>;
69
+ set: (key: K, value: T, options?: CacheSetOptions) => void;
70
+ readonly size: number;
71
+ };
72
+ /**
73
+ * Creates a generic key-value cache with TTL-based garbage collection, optional capacity
74
+ * limit (FIFO eviction), async stampede prevention, and optional eviction callback.
75
+ *
76
+ * This is the single caching primitive in arsenal — use it for simple bounded caches,
77
+ * TTL caches, or async deduplication/stampede prevention.
78
+ *
79
+ * @example
80
+ * ```ts
81
+ * // Simple string cache — no options needed for string keys
82
+ * const myCache = stash<string>();
83
+ * myCache.set('user:1', 'John Doe');
84
+ * const value = myCache.get('user:1'); // 'John Doe'
85
+ *
86
+ * // Global TTL — all entries expire after 60 seconds unless overridden
87
+ * const apiCache = stash<Response>({ ttlMs: 60_000 });
88
+ * apiCache.set('data', response); // expires in 60s
89
+ * apiCache.set('data', response, { ttlMs: 5_000 }); // override: expires in 5s
90
+ *
91
+ * // Async getOrSet prevents stampedes — concurrent callers share one in-flight promise
92
+ * const user = await myCache.getOrSet('user:1', () => fetchUser(1));
93
+ *
94
+ * // Bounded FIFO cache
95
+ * const fmtCache = stash<Intl.NumberFormat>({ maxSize: 64 });
96
+ * const fmt = fmtCache.getOrSet('en-US', () => new Intl.NumberFormat('en-US'));
97
+ *
98
+ * // Custom key type — provide a hash function
99
+ * const objCache = stash<Result, { id: number }>({ hash: (k) => String(k.id) });
100
+ *
101
+ * // Note: `undefined` is a valid cached value — if a key is set to `undefined`,
102
+ * // `getOrSet` returns it without invoking the factory again.
103
+ * ```
104
+ *
105
+ * @template T - The type of values stored in the cache.
106
+ * @template K - The key type. Defaults to `string`.
107
+ *
108
+ * @throws {ArsenalValidationError} If `options.maxSize` is provided and is not a positive integer or `Infinity`.
109
+ */
110
+ export declare function stash<T, K = string>(options?: CacheOptions<K, T>): Stash<T, K>;
111
+ //# sourceMappingURL=stash.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"stash.d.ts","sourceRoot":"","sources":["../../src/cache/stash.ts"],"names":[],"mappings":"AAQA,MAAM,MAAM,gBAAgB,CAAC,CAAC,IAAI;IAChC,kEAAkE;IAClE,WAAW,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,CAAC,CAAC;IAChC,2DAA2D;IAC3D,SAAS,EAAE,CAAC,KAAK,EAAE,CAAC,KAAK,MAAM,CAAC;CACjC,CAAC;AAEF,MAAM,MAAM,YAAY,CAAC,CAAC,GAAG,MAAM,EAAE,CAAC,GAAG,OAAO,IAAI;IAClD;;;;OAIG;IACH,IAAI,CAAC,EAAE,CAAC,GAAG,EAAE,CAAC,KAAK,MAAM,CAAC;IAC1B;;;;;;OAMG;IACH,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,OAAO,CAAC,EAAE,CAAC,GAAG,EAAE,CAAC,EAAE,KAAK,EAAE,CAAC,KAAK,IAAI,CAAC;IACrC;;;;;;;;;;;;;OAaG;IACH,WAAW,CAAC,EAAE,gBAAgB,CAAC,CAAC,CAAC,CAAC;IAClC;;;;;;OAMG;IACH,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB,CAAC;AAEF,MAAM,MAAM,eAAe,GAAG;IAC5B;;;;;;OAMG;IACH,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB,CAAC;AAEF,MAAM,MAAM,KAAK,CAAC,CAAC,EAAE,CAAC,GAAG,MAAM,IAAI;IACjC,KAAK,EAAE,MAAM,IAAI,CAAC;IAClB,MAAM,EAAE,CAAC,GAAG,EAAE,CAAC,KAAK,OAAO,CAAC;IAC5B,OAAO,EAAE,MAAM,gBAAgB,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC;IACxC,GAAG,EAAE,CAAC,GAAG,EAAE,CAAC,KAAK,CAAC,GAAG,SAAS,CAAC;IAC/B;;;OAGG;IACH,QAAQ,CAAC,GAAG,EAAE,CAAC,EAAE,OAAO,EAAE,MAAM,CAAC,EAAE,OAAO,CAAC,EAAE,eAAe,GAAG,CAAC,CAAC;IACjE,QAAQ,CAAC,GAAG,EAAE,CAAC,EAAE,OAAO,EAAE,MAAM,OAAO,CAAC,CAAC,CAAC,EAAE,OAAO,CAAC,EAAE,eAAe,GAAG,OAAO,CAAC,CAAC,CAAC,CAAC;IACnF,GAAG,EAAE,CAAC,GAAG,EAAE,CAAC,EAAE,KAAK,EAAE,CAAC,EAAE,OAAO,CAAC,EAAE,eAAe,KAAK,IAAI,CAAC;IAC3D,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;CACvB,CAAC;AAEF;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAqCG;AACH,wBAAgB,KAAK,CAAC,CAAC,EAAE,CAAC,GAAG,MAAM,EAAE,OAAO,GAAE,YAAY,CAAC,CAAC,EAAE,CAAC,CAAM,GAAG,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAwLlF"}
@@ -0,0 +1,92 @@
1
+ import { ArsenalValidationError as e } from "../errors.js";
2
+ import { isPromise as t } from "../guards/isPromise.js";
3
+ //#region src/cache/stash.ts
4
+ function n(n = {}) {
5
+ let r = n.maxSize ?? Infinity;
6
+ if (r !== Infinity && (!Number.isInteger(r) || r < 1)) throw new e(`stash: maxSize must be a positive integer or Infinity, got ${r}`);
7
+ let i = /* @__PURE__ */ new Map(), a = /* @__PURE__ */ new Map(), o = /* @__PURE__ */ new Map(), s = n.hash ?? ((e) => String(e)), c = n.onEvict, l = n.ttlMs, u = n.persistence, d = 0, f = /* @__PURE__ */ new Set();
8
+ function p() {
9
+ if (i.size > r) {
10
+ let [e] = i.keys();
11
+ e !== void 0 && h(e);
12
+ }
13
+ }
14
+ function m(e) {
15
+ let t = a.get(e);
16
+ t !== void 0 && (clearTimeout(t), a.delete(e));
17
+ }
18
+ function h(e) {
19
+ let t = i.get(e);
20
+ return m(e), t && (c?.(t.key, t.value), i.delete(e)), o.has(e) && f.add(e), t !== void 0;
21
+ }
22
+ function g(t, n) {
23
+ if (m(t), n === Infinity) return;
24
+ if (!Number.isFinite(n)) throw new e("stash: ttlMs must be a finite number or Infinity");
25
+ if (n <= 0) {
26
+ h(t);
27
+ return;
28
+ }
29
+ if (!i.has(t)) return;
30
+ let r = setTimeout(() => {
31
+ a.delete(t), h(t);
32
+ }, n);
33
+ a.set(t, r);
34
+ }
35
+ function _(e) {
36
+ return u && typeof e == "string" ? u.deserialize(e) : e;
37
+ }
38
+ function v(e) {
39
+ let t = i.get(s(e));
40
+ return t ? _(t.value) : void 0;
41
+ }
42
+ function y(e, t, n) {
43
+ let r = s(e), a = u ? u.serialize(t) : t;
44
+ m(r), i.set(r, {
45
+ key: e,
46
+ value: a
47
+ }), p();
48
+ let o = n?.ttlMs ?? l;
49
+ o !== void 0 && g(r, o);
50
+ }
51
+ function b(e, n, r) {
52
+ let a = s(e);
53
+ if (i.has(a) && !r?.forceRefresh) return v(e);
54
+ let c = o.get(a);
55
+ if (c && !r?.forceRefresh) return c;
56
+ let l = n();
57
+ if (t(l)) {
58
+ let t = d, n = l.then((i) => (o.get(a) === n && o.delete(a), d === t && !f.has(a) && y(e, i, r), f.delete(a), i)).catch((e) => {
59
+ throw o.get(a) === n && o.delete(a), f.delete(a), e;
60
+ });
61
+ return o.set(a, n), n;
62
+ }
63
+ return y(e, l, r), l;
64
+ }
65
+ function x(e) {
66
+ return h(s(e));
67
+ }
68
+ function S() {
69
+ d++;
70
+ for (let e of a.values()) clearTimeout(e);
71
+ if (c) for (let e of i.values()) c(e.key, e.value);
72
+ i.clear(), a.clear(), o.clear(), f.clear();
73
+ }
74
+ function* C() {
75
+ for (let e of i.values()) yield [e.key, _(e.value)];
76
+ }
77
+ return {
78
+ clear: S,
79
+ delete: x,
80
+ entries: C,
81
+ get: v,
82
+ getOrSet: b,
83
+ set: y,
84
+ get size() {
85
+ return i.size;
86
+ }
87
+ };
88
+ }
89
+ //#endregion
90
+ export { n as stash };
91
+
92
+ //# sourceMappingURL=stash.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"stash.js","names":[],"sources":["../../src/cache/stash.ts"],"sourcesContent":["import { ArsenalValidationError } from '../errors';\nimport { isPromise } from '../guards/isPromise';\n\ntype CacheRecord<K, T> = {\n key: K;\n value: T;\n};\n\nexport type CachePersistence<T> = {\n /** Deserializes a stored string back into a value of type `T`. */\n deserialize: (raw: string) => T;\n /** Serializes a value to a string for internal storage. */\n serialize: (value: T) => string;\n};\n\nexport type CacheOptions<K = string, T = unknown> = {\n /**\n * Converts a key to its canonical string representation for internal storage.\n * Defaults to `String(key)` — suitable for all string, number, and symbol keys.\n * Provide a custom function for object keys or composite keys.\n */\n hash?: (key: K) => string;\n /**\n * Maximum number of entries to hold. When the store reaches capacity, the oldest\n * entry is evicted (FIFO) before inserting the new one. `onEvict` is called on\n * capacity evictions just like TTL evictions.\n *\n * Default: `Infinity` (unbounded).\n */\n maxSize?: number;\n onEvict?: (key: K, value: T) => void;\n /**\n * Optional serialization pair for persistent caches (e.g. localStorage, cross-process IPC).\n * Both `serialize` and `deserialize` must be provided together.\n *\n * @example\n * ```ts\n * const cache = stash<User>({\n * persistence: {\n * serialize: (u) => JSON.stringify(u),\n * deserialize: (raw) => JSON.parse(raw) as User,\n * },\n * });\n * ```\n */\n persistence?: CachePersistence<T>;\n /**\n * Default time-to-live for all entries in milliseconds.\n * Applied automatically to every `set()` and `getOrSet()` call unless\n * overridden per-entry via `CacheSetOptions.ttlMs`.\n *\n * Default: `undefined` (entries do not expire).\n */\n ttlMs?: number;\n};\n\nexport type CacheSetOptions = {\n /**\n * When `true`, bypasses both the cache and any in-flight promise for this key,\n * and always calls the factory. The new value replaces the old cache entry.\n * **Note:** if a prior in-flight is still pending when `forceRefresh` resolves,\n * whichever `.then` runs last will write the cache slot — ensure prior in-flight\n * tasks have settled if ordering matters.\n */\n forceRefresh?: boolean;\n ttlMs?: number;\n};\n\nexport type Stash<T, K = string> = {\n clear: () => void;\n delete: (key: K) => boolean;\n entries: () => IterableIterator<[K, T]>;\n get: (key: K) => T | undefined;\n /**\n * Returns the cached value for `key`, or invokes `factory` to produce and cache it.\n * Pass `{ forceRefresh: true }` to skip the cache and always call `factory`.\n */\n getOrSet(key: K, factory: () => T, options?: CacheSetOptions): T;\n getOrSet(key: K, factory: () => Promise<T>, options?: CacheSetOptions): Promise<T>;\n set: (key: K, value: T, options?: CacheSetOptions) => void;\n readonly size: number;\n};\n\n/**\n * Creates a generic key-value cache with TTL-based garbage collection, optional capacity\n * limit (FIFO eviction), async stampede prevention, and optional eviction callback.\n *\n * This is the single caching primitive in arsenal — use it for simple bounded caches,\n * TTL caches, or async deduplication/stampede prevention.\n *\n * @example\n * ```ts\n * // Simple string cache — no options needed for string keys\n * const myCache = stash<string>();\n * myCache.set('user:1', 'John Doe');\n * const value = myCache.get('user:1'); // 'John Doe'\n *\n * // Global TTL — all entries expire after 60 seconds unless overridden\n * const apiCache = stash<Response>({ ttlMs: 60_000 });\n * apiCache.set('data', response); // expires in 60s\n * apiCache.set('data', response, { ttlMs: 5_000 }); // override: expires in 5s\n *\n * // Async getOrSet prevents stampedes — concurrent callers share one in-flight promise\n * const user = await myCache.getOrSet('user:1', () => fetchUser(1));\n *\n * // Bounded FIFO cache\n * const fmtCache = stash<Intl.NumberFormat>({ maxSize: 64 });\n * const fmt = fmtCache.getOrSet('en-US', () => new Intl.NumberFormat('en-US'));\n *\n * // Custom key type — provide a hash function\n * const objCache = stash<Result, { id: number }>({ hash: (k) => String(k.id) });\n *\n * // Note: `undefined` is a valid cached value — if a key is set to `undefined`,\n * // `getOrSet` returns it without invoking the factory again.\n * ```\n *\n * @template T - The type of values stored in the cache.\n * @template K - The key type. Defaults to `string`.\n *\n * @throws {ArsenalValidationError} If `options.maxSize` is provided and is not a positive integer or `Infinity`.\n */\nexport function stash<T, K = string>(options: CacheOptions<K, T> = {}): Stash<T, K> {\n const maxSize = options.maxSize ?? Infinity;\n\n if (maxSize !== Infinity && (!Number.isInteger(maxSize) || maxSize < 1)) {\n throw new ArsenalValidationError(`stash: maxSize must be a positive integer or Infinity, got ${maxSize}`);\n }\n\n const store = new Map<string, CacheRecord<K, T>>();\n const gcTimers = new Map<string, ReturnType<typeof setTimeout>>();\n const inFlight = new Map<string, Promise<T>>();\n const hash = options.hash ?? ((key: K) => String(key));\n const onEvict = options.onEvict;\n const defaultTtlMs = options.ttlMs;\n const persistence = options.persistence;\n let generation = 0;\n const deletedWhileInFlight = new Set<string>();\n\n function evictOldestIfOverCapacity(): void {\n if (store.size > maxSize) {\n const [firstHash] = store.keys();\n\n if (firstHash !== undefined) {\n deleteByHash(firstHash);\n }\n }\n }\n\n function cancelGcByHash(keyHash: string): void {\n const id = gcTimers.get(keyHash);\n\n if (id !== undefined) {\n clearTimeout(id);\n gcTimers.delete(keyHash);\n }\n }\n\n function deleteByHash(keyHash: string): boolean {\n const record = store.get(keyHash);\n\n cancelGcByHash(keyHash);\n\n if (record) {\n onEvict?.(record.key, record.value);\n store.delete(keyHash);\n }\n\n if (inFlight.has(keyHash)) deletedWhileInFlight.add(keyHash);\n\n return record !== undefined;\n }\n\n function scheduleGcByHash(keyHash: string, delayMs: number): void {\n cancelGcByHash(keyHash);\n\n if (delayMs === Number.POSITIVE_INFINITY) return;\n\n if (!Number.isFinite(delayMs)) {\n throw new ArsenalValidationError('stash: ttlMs must be a finite number or Infinity');\n }\n\n if (delayMs <= 0) {\n deleteByHash(keyHash);\n\n return;\n }\n\n if (!store.has(keyHash)) return;\n\n const id = setTimeout(() => {\n gcTimers.delete(keyHash);\n deleteByHash(keyHash);\n }, delayMs);\n\n gcTimers.set(keyHash, id);\n }\n\n function deserializeValue(raw: T): T {\n if (persistence && typeof raw === 'string') return persistence.deserialize(raw);\n\n return raw;\n }\n\n function get(key: K): T | undefined {\n const record = store.get(hash(key));\n\n return record ? deserializeValue(record.value) : undefined;\n }\n\n function set(key: K, value: T, opts?: CacheSetOptions): void {\n const keyHash = hash(key);\n const stored = persistence ? (persistence.serialize(value) as unknown as T) : value;\n\n cancelGcByHash(keyHash);\n store.set(keyHash, { key, value: stored });\n evictOldestIfOverCapacity();\n\n const ttl = opts?.ttlMs ?? defaultTtlMs;\n\n if (ttl !== undefined) {\n scheduleGcByHash(keyHash, ttl);\n }\n }\n\n function getOrSet(key: K, factory: () => T | Promise<T>, opts?: CacheSetOptions): T | Promise<T> {\n const keyHash = hash(key);\n\n if (store.has(keyHash) && !opts?.forceRefresh) return get(key) as T;\n\n const pending = inFlight.get(keyHash);\n\n if (pending && !opts?.forceRefresh) return pending;\n\n const value = factory();\n\n if (isPromise(value)) {\n const capturedGeneration = generation;\n const promise: Promise<T> = value\n .then((resolved) => {\n // Only clear the in-flight slot if it's still *this* promise — an overlapping\n // `forceRefresh` call may have already replaced it with a newer in-flight promise.\n if (inFlight.get(keyHash) === promise) inFlight.delete(keyHash);\n\n if (generation === capturedGeneration && !deletedWhileInFlight.has(keyHash)) {\n set(key, resolved, opts);\n }\n\n deletedWhileInFlight.delete(keyHash);\n\n return resolved;\n })\n .catch((err: unknown) => {\n if (inFlight.get(keyHash) === promise) inFlight.delete(keyHash);\n\n deletedWhileInFlight.delete(keyHash);\n throw err;\n });\n\n inFlight.set(keyHash, promise);\n\n return promise;\n }\n\n set(key, value, opts);\n\n return value;\n }\n\n function del(key: K): boolean {\n return deleteByHash(hash(key));\n }\n\n function clear(): void {\n generation++;\n for (const id of gcTimers.values()) clearTimeout(id);\n\n if (onEvict) {\n for (const record of store.values()) {\n onEvict(record.key, record.value);\n }\n }\n\n store.clear();\n gcTimers.clear();\n inFlight.clear();\n deletedWhileInFlight.clear();\n }\n\n function* entries(): IterableIterator<[K, T]> {\n for (const record of store.values()) {\n yield [record.key, deserializeValue(record.value)];\n }\n }\n\n return {\n clear,\n delete: del,\n entries,\n get,\n getOrSet: getOrSet as Stash<T, K>['getOrSet'],\n set,\n get size() {\n return store.size;\n },\n };\n}\n"],"mappings":";;;AAyHA,SAAgB,EAAqB,IAA8B,CAAC,GAAgB;CAClF,IAAM,IAAU,EAAQ,WAAW;CAEnC,IAAI,MAAY,aAAa,CAAC,OAAO,UAAU,CAAO,KAAK,IAAU,IACnE,MAAM,IAAI,EAAuB,8DAA8D,GAAS;CAG1G,IAAM,oBAAQ,IAAI,IAA+B,GAC3C,oBAAW,IAAI,IAA2C,GAC1D,oBAAW,IAAI,IAAwB,GACvC,IAAO,EAAQ,UAAU,MAAW,OAAO,CAAG,IAC9C,IAAU,EAAQ,SAClB,IAAe,EAAQ,OACvB,IAAc,EAAQ,aACxB,IAAa,GACX,oBAAuB,IAAI,IAAY;CAE7C,SAAS,IAAkC;EACzC,IAAI,EAAM,OAAO,GAAS;GACxB,IAAM,CAAC,KAAa,EAAM,KAAK;GAE/B,AAAI,MAAc,KAAA,KAChB,EAAa,CAAS;EAE1B;CACF;CAEA,SAAS,EAAe,GAAuB;EAC7C,IAAM,IAAK,EAAS,IAAI,CAAO;EAE/B,AAAI,MAAO,KAAA,MACT,aAAa,CAAE,GACf,EAAS,OAAO,CAAO;CAE3B;CAEA,SAAS,EAAa,GAA0B;EAC9C,IAAM,IAAS,EAAM,IAAI,CAAO;EAWhC,OATA,EAAe,CAAO,GAElB,MACF,IAAU,EAAO,KAAK,EAAO,KAAK,GAClC,EAAM,OAAO,CAAO,IAGlB,EAAS,IAAI,CAAO,KAAG,EAAqB,IAAI,CAAO,GAEpD,MAAW,KAAA;CACpB;CAEA,SAAS,EAAiB,GAAiB,GAAuB;EAGhE,IAFA,EAAe,CAAO,GAElB,MAAY,UAA0B;EAE1C,IAAI,CAAC,OAAO,SAAS,CAAO,GAC1B,MAAM,IAAI,EAAuB,kDAAkD;EAGrF,IAAI,KAAW,GAAG;GAChB,EAAa,CAAO;GAEpB;EACF;EAEA,IAAI,CAAC,EAAM,IAAI,CAAO,GAAG;EAEzB,IAAM,IAAK,iBAAiB;GAE1B,AADA,EAAS,OAAO,CAAO,GACvB,EAAa,CAAO;EACtB,GAAG,CAAO;EAEV,EAAS,IAAI,GAAS,CAAE;CAC1B;CAEA,SAAS,EAAiB,GAAW;EAGnC,OAFI,KAAe,OAAO,KAAQ,WAAiB,EAAY,YAAY,CAAG,IAEvE;CACT;CAEA,SAAS,EAAI,GAAuB;EAClC,IAAM,IAAS,EAAM,IAAI,EAAK,CAAG,CAAC;EAElC,OAAO,IAAS,EAAiB,EAAO,KAAK,IAAI,KAAA;CACnD;CAEA,SAAS,EAAI,GAAQ,GAAU,GAA8B;EAC3D,IAAM,IAAU,EAAK,CAAG,GAClB,IAAS,IAAe,EAAY,UAAU,CAAK,IAAqB;EAI9E,AAFA,EAAe,CAAO,GACtB,EAAM,IAAI,GAAS;GAAE;GAAK,OAAO;EAAO,CAAC,GACzC,EAA0B;EAE1B,IAAM,IAAM,GAAM,SAAS;EAE3B,AAAI,MAAQ,KAAA,KACV,EAAiB,GAAS,CAAG;CAEjC;CAEA,SAAS,EAAS,GAAQ,GAA+B,GAAwC;EAC/F,IAAM,IAAU,EAAK,CAAG;EAExB,IAAI,EAAM,IAAI,CAAO,KAAK,CAAC,GAAM,cAAc,OAAO,EAAI,CAAG;EAE7D,IAAM,IAAU,EAAS,IAAI,CAAO;EAEpC,IAAI,KAAW,CAAC,GAAM,cAAc,OAAO;EAE3C,IAAM,IAAQ,EAAQ;EAEtB,IAAI,EAAU,CAAK,GAAG;GACpB,IAAM,IAAqB,GACrB,IAAsB,EACzB,MAAM,OAGD,EAAS,IAAI,CAAO,MAAM,KAAS,EAAS,OAAO,CAAO,GAE1D,MAAe,KAAsB,CAAC,EAAqB,IAAI,CAAO,KACxE,EAAI,GAAK,GAAU,CAAI,GAGzB,EAAqB,OAAO,CAAO,GAE5B,EACR,CAAC,CACD,OAAO,MAAiB;IAIvB,MAHI,EAAS,IAAI,CAAO,MAAM,KAAS,EAAS,OAAO,CAAO,GAE9D,EAAqB,OAAO,CAAO,GAC7B;GACR,CAAC;GAIH,OAFA,EAAS,IAAI,GAAS,CAAO,GAEtB;EACT;EAIA,OAFA,EAAI,GAAK,GAAO,CAAI,GAEb;CACT;CAEA,SAAS,EAAI,GAAiB;EAC5B,OAAO,EAAa,EAAK,CAAG,CAAC;CAC/B;CAEA,SAAS,IAAc;EACrB;EACA,KAAK,IAAM,KAAM,EAAS,OAAO,GAAG,aAAa,CAAE;EAEnD,IAAI,GACF,KAAK,IAAM,KAAU,EAAM,OAAO,GAChC,EAAQ,EAAO,KAAK,EAAO,KAAK;EAOpC,AAHA,EAAM,MAAM,GACZ,EAAS,MAAM,GACf,EAAS,MAAM,GACf,EAAqB,MAAM;CAC7B;CAEA,UAAU,IAAoC;EAC5C,KAAK,IAAM,KAAU,EAAM,OAAO,GAChC,MAAM,CAAC,EAAO,KAAK,EAAiB,EAAO,KAAK,CAAC;CAErD;CAEA,OAAO;EACL;EACA,QAAQ;EACR;EACA;EACU;EACV;EACA,IAAI,OAAO;GACT,OAAO,EAAM;EACf;CACF;AACF"}
@@ -0,0 +1,2 @@
1
+ var e=class e extends Error{constructor(e,t){super(e,t),this.name=new.target.name,Object.setPrototypeOf(this,new.target.prototype)}static is(t){return t instanceof e}},t=class extends e{},n=class extends e{};exports.ArsenalError=e,exports.ArsenalSerializationError=n,exports.ArsenalValidationError=t;
2
+ //# sourceMappingURL=errors.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"errors.cjs","names":[],"sources":["../src/errors.ts"],"sourcesContent":["/** Base class for all arsenal errors. Use `instanceof ArsenalError` to catch any arsenal-originated error. */\nexport class ArsenalError extends Error {\n constructor(message: string, opts?: ErrorOptions) {\n super(message, opts);\n this.name = new.target.name;\n Object.setPrototypeOf(this, new.target.prototype);\n }\n\n static is(err: unknown): err is ArsenalError {\n return err instanceof ArsenalError;\n }\n}\n\n/**\n * Thrown when a function argument or option is invalid — wrong type, out of range, or an\n * otherwise-unusable value (e.g. a negative `concurrency`, a non-finite `range` bound, an\n * oversized `similarity` input).\n */\nexport class ArsenalValidationError extends ArsenalError {}\n\n/**\n * Thrown when converting a value to or from its serialized form fails — e.g. `memo`'s default\n * cache key (`JSON.stringify`) encountering a circular reference, or `hash` encountering an\n * unsupported class instance with `{ onClassInstance: 'throw' }`.\n */\nexport class ArsenalSerializationError extends ArsenalError {}\n"],"mappings":"AACA,IAAa,EAAb,MAAa,UAAqB,KAAM,CACtC,YAAY,EAAiB,EAAqB,CAChD,MAAM,EAAS,CAAI,EACnB,KAAK,KAAO,IAAI,OAAO,KACvB,OAAO,eAAe,KAAM,IAAI,OAAO,SAAS,CAClD,CAEA,OAAO,GAAG,EAAmC,CAC3C,OAAO,aAAe,CACxB,CACF,EAOa,EAAb,cAA4C,CAAa,CAAC,EAO7C,EAAb,cAA+C,CAAa,CAAC"}
@@ -0,0 +1,20 @@
1
+ /** Base class for all arsenal errors. Use `instanceof ArsenalError` to catch any arsenal-originated error. */
2
+ export declare class ArsenalError extends Error {
3
+ constructor(message: string, opts?: ErrorOptions);
4
+ static is(err: unknown): err is ArsenalError;
5
+ }
6
+ /**
7
+ * Thrown when a function argument or option is invalid — wrong type, out of range, or an
8
+ * otherwise-unusable value (e.g. a negative `concurrency`, a non-finite `range` bound, an
9
+ * oversized `similarity` input).
10
+ */
11
+ export declare class ArsenalValidationError extends ArsenalError {
12
+ }
13
+ /**
14
+ * Thrown when converting a value to or from its serialized form fails — e.g. `memo`'s default
15
+ * cache key (`JSON.stringify`) encountering a circular reference, or `hash` encountering an
16
+ * unsupported class instance with `{ onClassInstance: 'throw' }`.
17
+ */
18
+ export declare class ArsenalSerializationError extends ArsenalError {
19
+ }
20
+ //# sourceMappingURL=errors.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"errors.d.ts","sourceRoot":"","sources":["../src/errors.ts"],"names":[],"mappings":"AAAA,8GAA8G;AAC9G,qBAAa,YAAa,SAAQ,KAAK;gBACzB,OAAO,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,YAAY;IAMhD,MAAM,CAAC,EAAE,CAAC,GAAG,EAAE,OAAO,GAAG,GAAG,IAAI,YAAY;CAG7C;AAED;;;;GAIG;AACH,qBAAa,sBAAuB,SAAQ,YAAY;CAAG;AAE3D;;;;GAIG;AACH,qBAAa,yBAA0B,SAAQ,YAAY;CAAG"}
package/dist/errors.js ADDED
@@ -0,0 +1,13 @@
1
+ //#region src/errors.ts
2
+ var e = class e extends Error {
3
+ constructor(e, t) {
4
+ super(e, t), this.name = new.target.name, Object.setPrototypeOf(this, new.target.prototype);
5
+ }
6
+ static is(t) {
7
+ return t instanceof e;
8
+ }
9
+ }, t = class extends e {}, n = class extends e {};
10
+ //#endregion
11
+ export { e as ArsenalError, n as ArsenalSerializationError, t as ArsenalValidationError };
12
+
13
+ //# sourceMappingURL=errors.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"errors.js","names":[],"sources":["../src/errors.ts"],"sourcesContent":["/** Base class for all arsenal errors. Use `instanceof ArsenalError` to catch any arsenal-originated error. */\nexport class ArsenalError extends Error {\n constructor(message: string, opts?: ErrorOptions) {\n super(message, opts);\n this.name = new.target.name;\n Object.setPrototypeOf(this, new.target.prototype);\n }\n\n static is(err: unknown): err is ArsenalError {\n return err instanceof ArsenalError;\n }\n}\n\n/**\n * Thrown when a function argument or option is invalid — wrong type, out of range, or an\n * otherwise-unusable value (e.g. a negative `concurrency`, a non-finite `range` bound, an\n * oversized `similarity` input).\n */\nexport class ArsenalValidationError extends ArsenalError {}\n\n/**\n * Thrown when converting a value to or from its serialized form fails — e.g. `memo`'s default\n * cache key (`JSON.stringify`) encountering a circular reference, or `hash` encountering an\n * unsupported class instance with `{ onClassInstance: 'throw' }`.\n */\nexport class ArsenalSerializationError extends ArsenalError {}\n"],"mappings":";AACA,IAAa,IAAb,MAAa,UAAqB,MAAM;CACtC,YAAY,GAAiB,GAAqB;EAGhD,AAFA,MAAM,GAAS,CAAI,GACnB,KAAK,OAAO,IAAI,OAAO,MACvB,OAAO,eAAe,MAAM,IAAI,OAAO,SAAS;CAClD;CAEA,OAAO,GAAG,GAAmC;EAC3C,OAAO,aAAe;CACxB;AACF,GAOa,IAAb,cAA4C,EAAa,CAAC,GAO7C,IAAb,cAA+C,EAAa,CAAC"}
@@ -0,0 +1,2 @@
1
+ function e(e,t,n){if(!e)throw new((n?.type)??Error)(t??`Assertion failed`)}exports.assert=e;
2
+ //# sourceMappingURL=assert.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"assert.cjs","names":[],"sources":["../../src/function/assert.ts"],"sourcesContent":["/**\n * Asserts that a condition is true. Throws with `message` if false.\n *\n * @example\n * ```ts\n * assert(Array.isArray(x));\n * assert(x > 0, 'x must be positive');\n * assert(n >= 1, 'must be at least 1', { type: RangeError });\n * ```\n *\n * @param condition - The boolean condition to assert.\n * @param [message] - Error message (default: `'Assertion failed'`).\n * @param [options.type] - Error class to throw (default: `Error`).\n * @throws {Error} If `condition` is false.\n */\nexport function assert(condition: boolean, message?: string, options?: { type?: ErrorConstructor }): asserts condition {\n if (!condition) throw new (options?.type ?? Error)(message ?? 'Assertion failed');\n}\n"],"mappings":"AAeA,SAAgB,EAAO,EAAoB,EAAkB,EAA0D,CACrH,GAAI,CAAC,EAAW,MAAM,KAAK,GAAS,OAAQ,OAAO,GAAW,kBAAkB,CAClF"}
@@ -0,0 +1,19 @@
1
+ /**
2
+ * Asserts that a condition is true. Throws with `message` if false.
3
+ *
4
+ * @example
5
+ * ```ts
6
+ * assert(Array.isArray(x));
7
+ * assert(x > 0, 'x must be positive');
8
+ * assert(n >= 1, 'must be at least 1', { type: RangeError });
9
+ * ```
10
+ *
11
+ * @param condition - The boolean condition to assert.
12
+ * @param [message] - Error message (default: `'Assertion failed'`).
13
+ * @param [options.type] - Error class to throw (default: `Error`).
14
+ * @throws {Error} If `condition` is false.
15
+ */
16
+ export declare function assert(condition: boolean, message?: string, options?: {
17
+ type?: ErrorConstructor;
18
+ }): asserts condition;
19
+ //# sourceMappingURL=assert.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"assert.d.ts","sourceRoot":"","sources":["../../src/function/assert.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,MAAM,CAAC,SAAS,EAAE,OAAO,EAAE,OAAO,CAAC,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE;IAAE,IAAI,CAAC,EAAE,gBAAgB,CAAA;CAAE,GAAG,OAAO,CAAC,SAAS,CAErH"}
@@ -0,0 +1,8 @@
1
+ //#region src/function/assert.ts
2
+ function e(e, t, n) {
3
+ if (!e) throw new ((n?.type) ?? Error)(t ?? "Assertion failed");
4
+ }
5
+ //#endregion
6
+ export { e as assert };
7
+
8
+ //# sourceMappingURL=assert.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"assert.js","names":[],"sources":["../../src/function/assert.ts"],"sourcesContent":["/**\n * Asserts that a condition is true. Throws with `message` if false.\n *\n * @example\n * ```ts\n * assert(Array.isArray(x));\n * assert(x > 0, 'x must be positive');\n * assert(n >= 1, 'must be at least 1', { type: RangeError });\n * ```\n *\n * @param condition - The boolean condition to assert.\n * @param [message] - Error message (default: `'Assertion failed'`).\n * @param [options.type] - Error class to throw (default: `Error`).\n * @throws {Error} If `condition` is false.\n */\nexport function assert(condition: boolean, message?: string, options?: { type?: ErrorConstructor }): asserts condition {\n if (!condition) throw new (options?.type ?? Error)(message ?? 'Assertion failed');\n}\n"],"mappings":";AAeA,SAAgB,EAAO,GAAoB,GAAkB,GAA0D;CACrH,IAAI,CAAC,GAAW,MAAM,MAAK,GAAS,SAAQ,OAAO,KAAW,kBAAkB;AAClF"}
@@ -0,0 +1,2 @@
1
+ function e(e){return()=>e}exports.constant=e;
2
+ //# sourceMappingURL=constant.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"constant.cjs","names":[],"sources":["../../src/function/constant.ts"],"sourcesContent":["/**\n * Returns a function that always returns the same value.\n */\nexport function constant<T>(value: T): () => T {\n return () => value;\n}\n"],"mappings":"AAGA,SAAgB,EAAY,EAAmB,CAC7C,UAAa,CACf"}