@depthbomb/common 1.3.1 → 2.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (67) hide show
  1. package/README.md +286 -1
  2. package/dist/collections.cjs +1 -0
  3. package/dist/{queue.d.cts → collections.d.cts} +31 -5
  4. package/dist/{queue.d.mts → collections.d.mts} +31 -5
  5. package/dist/collections.mjs +1 -0
  6. package/dist/decorators.cjs +1 -1
  7. package/dist/decorators.d.cts +1 -1
  8. package/dist/decorators.d.mts +1 -1
  9. package/dist/decorators.mjs +1 -1
  10. package/dist/functional.cjs +1 -0
  11. package/dist/{fn.d.cts → functional.d.cts} +1 -1
  12. package/dist/{fn.d.mts → functional.d.mts} +1 -1
  13. package/dist/guards.cjs +1 -0
  14. package/dist/guards.d.cts +7 -0
  15. package/dist/guards.d.mts +7 -0
  16. package/dist/guards.mjs +1 -0
  17. package/dist/index.cjs +1 -1
  18. package/dist/index.d.cts +12 -7
  19. package/dist/index.d.mts +12 -7
  20. package/dist/index.mjs +1 -1
  21. package/dist/lazy.cjs +1 -1
  22. package/dist/lazy.d.cts +1 -5
  23. package/dist/lazy.d.mts +1 -5
  24. package/dist/lazy.mjs +1 -1
  25. package/dist/number.cjs +1 -0
  26. package/dist/number.d.cts +8 -0
  27. package/dist/number.d.mts +8 -0
  28. package/dist/number.mjs +1 -0
  29. package/dist/promise.cjs +1 -0
  30. package/dist/promise.d.cts +48 -0
  31. package/dist/promise.d.mts +48 -0
  32. package/dist/promise.mjs +1 -0
  33. package/dist/random.cjs +1 -0
  34. package/dist/random.d.cts +11 -0
  35. package/dist/random.d.mts +11 -0
  36. package/dist/random.mjs +1 -0
  37. package/dist/state.cjs +1 -0
  38. package/dist/state.d.cts +88 -0
  39. package/dist/state.d.mts +88 -0
  40. package/dist/state.mjs +1 -0
  41. package/dist/timing.cjs +1 -0
  42. package/dist/timing.d.cts +71 -0
  43. package/dist/timing.d.mts +71 -0
  44. package/dist/timing.mjs +1 -0
  45. package/dist/typing.cjs +1 -0
  46. package/dist/typing.d.cts +26 -0
  47. package/dist/typing.d.mts +26 -0
  48. package/dist/typing.mjs +1 -0
  49. package/dist/url.cjs +1 -0
  50. package/dist/{urllib.d.cts → url.d.cts} +12 -2
  51. package/dist/{urllib.d.mts → url.d.mts} +12 -2
  52. package/dist/url.mjs +1 -0
  53. package/package.json +103 -81
  54. package/dist/async.cjs +0 -1
  55. package/dist/async.d.cts +0 -44
  56. package/dist/async.d.mts +0 -44
  57. package/dist/async.mjs +0 -1
  58. package/dist/fn.cjs +0 -1
  59. package/dist/queue.cjs +0 -1
  60. package/dist/queue.mjs +0 -1
  61. package/dist/types.cjs +0 -1
  62. package/dist/types.d.cts +0 -9
  63. package/dist/types.d.mts +0 -9
  64. package/dist/types.mjs +0 -1
  65. package/dist/urllib.cjs +0 -1
  66. package/dist/urllib.mjs +0 -1
  67. /package/dist/{fn.mjs → functional.mjs} +0 -0
package/README.md CHANGED
@@ -6,4 +6,289 @@ A set of common utilities for TypeScript/JavaScript that I use in my projects.
6
6
 
7
7
  ---
8
8
 
9
- Documentation and additional TSDocs coming soon.
9
+ ## Modules
10
+
11
+ ### `timing`
12
+
13
+ Timing and timeout flow-control helpers.
14
+
15
+ ```ts
16
+ import {
17
+ timeout,
18
+ rejectionTimeout,
19
+ pollUntil,
20
+ withTimeout,
21
+ retry,
22
+ abortAfter,
23
+ withAbort,
24
+ raceSignals,
25
+ RetryJitter,
26
+ } from '@depthbomb/common/timing';
27
+
28
+ await timeout(250);
29
+ await rejectionTimeout(100).catch(() => {});
30
+
31
+ let ready = false;
32
+ setTimeout(() => { ready = true; }, 200);
33
+ await pollUntil(() => ready, 50, 1_000);
34
+
35
+ const value = await withTimeout(Promise.resolve('ok'), 500);
36
+
37
+ const data = await retry(
38
+ async (attempt) => {
39
+ const response = await fetch('https://example.com/data');
40
+ if (!response.ok) {
41
+ throw new Error(`request failed on attempt ${attempt}`);
42
+ }
43
+ return response.json();
44
+ },
45
+ {
46
+ attempts: 4,
47
+ baseMs: 100,
48
+ maxMs: 1_000,
49
+ jitter: RetryJitter.Full,
50
+ }
51
+ );
52
+
53
+ const signal = abortAfter(1_000);
54
+ await withAbort(fetch('https://example.com/slow'), signal);
55
+
56
+ const parent = new AbortController();
57
+ const child = abortAfter(500);
58
+ const combined = raceSignals(parent.signal, child);
59
+ ```
60
+
61
+ ### `promise`
62
+
63
+ Promise composition helpers, including detailed settled results and concurrency-limited execution.
64
+
65
+ ```ts
66
+ import { allSettledSuccessful, allSettledDetailed, sequential, pool, pMap } from '@depthbomb/common/promise';
67
+
68
+ const successful = await allSettledSuccessful([
69
+ Promise.resolve(1),
70
+ Promise.reject(new Error('x')),
71
+ Promise.resolve(2)
72
+ ]); // [1, 2]
73
+
74
+ const ordered = await sequential([
75
+ async () => 'first',
76
+ async () => 'second'
77
+ ]); // ['first', 'second']
78
+
79
+ const detailed = await allSettledDetailed([
80
+ Promise.resolve('ok'),
81
+ Promise.reject(new Error('x')),
82
+ ]); // { results, fulfilled: ['ok'], rejected: [Error('x')] }
83
+
84
+ const pooled = await pool([
85
+ async () => 1,
86
+ async () => 2,
87
+ async () => 3,
88
+ ], { concurrency: 2 });
89
+
90
+ const mapped = await pMap([1, 2, 3], async (v) => v * 10, { concurrency: 2 });
91
+ ```
92
+
93
+ ### `decorators`
94
+
95
+ TypeScript decorators for reusable behavior. Currently includes a TTL-based `cache` decorator for memoizing method results per instance and argument set.
96
+
97
+ ```ts
98
+ import { cache } from '@depthbomb/common/decorators';
99
+
100
+ class Service {
101
+ calls = 0;
102
+
103
+ @cache(1_000)
104
+ getUser(id: string) {
105
+ this.calls++;
106
+ return { id, calls: this.calls };
107
+ }
108
+ }
109
+
110
+ const s = new Service();
111
+ s.getUser('1');
112
+ s.getUser('1'); // cached for 1 second
113
+ ```
114
+
115
+ ### `state`
116
+
117
+ State primitives: `ResettableValue`, `Flag`, `resettableLazy`, and `resettableLazyAsync`.
118
+
119
+ ```ts
120
+ import { Flag, ResettableValue, resettableLazy, resettableLazyAsync } from '@depthbomb/common/state';
121
+
122
+ const flag = new Flag();
123
+ flag.setTrue();
124
+ flag.toggle();
125
+ flag.reset();
126
+
127
+ const retries = new ResettableValue(3);
128
+ retries.set(1);
129
+ retries.reset(); // back to 3
130
+
131
+ const counter = resettableLazy(() => Math.random());
132
+ const first = counter.get();
133
+ counter.reset();
134
+ const second = counter.get(); // recomputed
135
+
136
+ const tokenCache = resettableLazyAsync(async () => {
137
+ const response = await fetch('https://example.com/token');
138
+ return response.text();
139
+ });
140
+ const token = await tokenCache.get();
141
+ tokenCache.reset();
142
+ ```
143
+
144
+ ### `functional`
145
+
146
+ General function utilities. Currently includes `once`, which ensures a function runs only on its first invocation and then reuses the same result.
147
+
148
+ ```ts
149
+ import { once } from '@depthbomb/common/functional';
150
+
151
+ const init = once(() => ({ startedAt: Date.now() }));
152
+
153
+ const a = init();
154
+ const b = init();
155
+ console.log(a === b); // true
156
+ ```
157
+
158
+ ### `lazy`
159
+
160
+ Lazy initialization utilities for sync and async values.
161
+
162
+ ```ts
163
+ import { lazy, lazyAsync } from '@depthbomb/common/lazy';
164
+
165
+ const getConfig = lazy(() => ({ env: 'prod' }));
166
+ const config = getConfig(); // factory runs once
167
+
168
+ const getToken = lazyAsync(async () => 'token');
169
+ const token = await getToken(); // promise created once
170
+ ```
171
+
172
+ ### `collections`
173
+
174
+ A lightweight generic FIFO queue with `enqueue`, `dequeue`, `peek`, iteration support, and internal compaction to keep long-running usage efficient. Also includes `BoundedQueue` for fixed-capacity use cases.
175
+
176
+ ```ts
177
+ import { Queue, BoundedQueue, BoundedQueueOverflow } from '@depthbomb/common/collections';
178
+
179
+ const q = new Queue<number>([1, 2]);
180
+ q.enqueue(3);
181
+
182
+ console.log(q.peek()); // 1
183
+ console.log(q.dequeue()); // 1
184
+ console.log(q.toArray()); // [2, 3]
185
+
186
+ const bounded = new BoundedQueue<number>({ maxSize: 3, overflow: BoundedQueueOverflow.DropOldest }, [1, 2, 3]);
187
+ bounded.enqueue(4);
188
+ console.log(bounded.toArray()); // [2, 3, 4]
189
+ ```
190
+
191
+ ### `number`
192
+
193
+ Numeric helpers for clamping, range checks, rounding, and aggregation.
194
+
195
+ ```ts
196
+ import { clamp, inRange, roundTo, sum, average } from '@depthbomb/common/number';
197
+
198
+ const bounded = clamp(12, 0, 10); // 10
199
+ const valid = inRange(5, 1, 10); // true
200
+ const rounded = roundTo(3.14159, 2); // 3.14
201
+ const total = sum([1, 2, 3, 4]); // 10
202
+ const mean = average([1, 2, 3, 4]); // 2.5
203
+ ```
204
+
205
+ ### `random`
206
+
207
+ Cross-environment random helpers for ranges and selection.
208
+
209
+ ```ts
210
+ import { randomFloat, randomInt, pickRandom, pickWeighted } from '@depthbomb/common/random';
211
+
212
+ const f = randomFloat(5, 10); // 5 <= f < 10
213
+ const i = randomInt(1, 6); // inclusive
214
+ const choice = pickRandom(['red', 'green', 'blue']);
215
+ const weighted = pickWeighted([
216
+ { value: 'small', weight: 1 },
217
+ { value: 'medium', weight: 3 },
218
+ { value: 'large', weight: 6 },
219
+ ]);
220
+ ```
221
+
222
+ ### `guards`
223
+
224
+ Runtime type guards for common narrowing patterns.
225
+
226
+ ```ts
227
+ import { isRecord, isNonEmptyString, isNumber, isDateLike } from '@depthbomb/common/guards';
228
+
229
+ const input: unknown = { name: 'Ada', createdAt: '2026-01-01' };
230
+
231
+ if (isRecord(input) && isNonEmptyString(input.name) && isDateLike(input.createdAt)) {
232
+ // narrowed shape at runtime
233
+ }
234
+
235
+ const maybeCount: unknown = 42;
236
+ if (isNumber(maybeCount)) {
237
+ console.log(maybeCount + 1);
238
+ }
239
+ ```
240
+
241
+ ### `typing`
242
+
243
+ Shared type aliases and type-oriented helpers such as `Awaitable`, `Maybe`, `Nullable`, `Result`, `cast`, `assume`, `typedEntries`, `ok`, `err`, `isOk`, `mapOk`, `mapErr`, and `tryCatchAsync`.
244
+
245
+ ```ts
246
+ import {
247
+ cast, assume, typedEntries,
248
+ ok, err, isOk, mapOk, mapErr, tryCatchAsync,
249
+ type Awaitable, type Maybe, type Result
250
+ } from '@depthbomb/common/typing';
251
+
252
+ const v = cast<object, { id: string }>({ id: 'a' });
253
+
254
+ const unknownValue: unknown = 'hello';
255
+ assume<string>(unknownValue); // assertion helper
256
+
257
+ const entries = typedEntries({ a: 1, b: 2 }); // typed key/value tuples
258
+
259
+ const maybeName: Maybe<string> = undefined;
260
+ const task: Awaitable<number> = Promise.resolve(1);
261
+
262
+ const initial: Result<number, string> = ok(2);
263
+ const doubled = mapOk(initial, (value) => value * 2);
264
+ const message = mapErr(err('bad'), (e) => `error: ${e}`);
265
+
266
+ const parsed = await tryCatchAsync(async () => JSON.parse('{"x":1}'));
267
+ if (isOk(parsed)) {
268
+ console.log(parsed.value.x);
269
+ }
270
+ ```
271
+
272
+ ### `url`
273
+
274
+ URL-focused utilities centered around `URLPath`, an ergonomic wrapper for URL parsing, path composition, query/hash manipulation, and request dispatch via `fetch`.
275
+
276
+ ```ts
277
+ import { URLPath, url } from '@depthbomb/common/url';
278
+
279
+ const api = new URLPath('https://example.com/api');
280
+ const usersUrl = api
281
+ .joinpath('users', '42')
282
+ .withQuery({ include: ['roles', 'profile'] })
283
+ .withQueryPatch({ page: 1 })
284
+ .appendQuery({ include: 'permissions' })
285
+ .withoutEmptyQuery()
286
+ .withHash('details');
287
+
288
+ const userPath = url`/users/${'john/doe'}/posts/${'my first post'}`;
289
+
290
+ console.log(usersUrl.toString());
291
+ // https://example.com/api/users/42?include=roles&include=profile#details
292
+ console.log(userPath);
293
+ // /users/john%2Fdoe/posts/my%20first%20post
294
+ ```
@@ -0,0 +1 @@
1
+ Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});let e=function(e){return e[e.DropOldest=0]=`DropOldest`,e[e.DropNewest=1]=`DropNewest`,e[e.Throw=2]=`Throw`,e}({});var t=class{#e=[];#t=0;constructor(e){e&&(this.#e=[...e])}get size(){return this.#e.length-this.#t}get isEmpty(){return this.size===0}enqueue(e){this.#e.push(e)}dequeue(){if(this.#t>=this.#e.length)return;let e=this.#e[this.#t++];return this.#t>=64&&this.#t*2>=this.#e.length&&(this.#e=this.#e.slice(this.#t),this.#t=0),e}peek(){return this.#e[this.#t]}clear(){this.#e=[],this.#t=0}[Symbol.iterator](){return this.toArray()[Symbol.iterator]()}toArray(){return this.#e.slice(this.#t)}},n=class{#e;#t;#n;constructor(n,r){if(!Number.isInteger(n.maxSize)||n.maxSize<1)throw Error(`maxSize must be an integer >= 1`);if(this.#e=n.maxSize,this.#t=n.overflow??e.DropOldest,this.#n=new t,r)for(let e of r)this.enqueue(e)}get size(){return this.#n.size}get isEmpty(){return this.#n.isEmpty}get isFull(){return this.size>=this.#e}get maxSize(){return this.#e}get overflow(){return this.#t}enqueue(t){if(!this.isFull){this.#n.enqueue(t);return}if(this.#t!==e.DropNewest){if(this.#t===e.Throw)throw Error(`BoundedQueue overflow`);this.#n.dequeue(),this.#n.enqueue(t)}}dequeue(){return this.#n.dequeue()}peek(){return this.#n.peek()}clear(){this.#n.clear()}[Symbol.iterator](){return this.#n[Symbol.iterator]()}toArray(){return this.#n.toArray()}};exports.BoundedQueue=n,exports.BoundedQueueOverflow=e,exports.Queue=t;
@@ -1,6 +1,17 @@
1
- //#region src/queue.d.ts
1
+ import { Maybe } from "./typing.cjs";
2
+
3
+ //#region src/collections.d.ts
4
+ interface IBoundedQueueOptions {
5
+ maxSize: number;
6
+ overflow?: BoundedQueueOverflow;
7
+ }
8
+ declare const enum BoundedQueueOverflow {
9
+ DropOldest = 0,
10
+ DropNewest = 1,
11
+ Throw = 2
12
+ }
2
13
  declare class Queue<T> {
3
- private items;
14
+ #private;
4
15
  constructor(initial?: Iterable<T>);
5
16
  /**
6
17
  * Get the number of items in the queue.
@@ -21,13 +32,13 @@ declare class Queue<T> {
21
32
  *
22
33
  * @returns The item at the front of the queue, or undefined if the queue is empty
23
34
  */
24
- dequeue(): T | undefined;
35
+ dequeue(): Maybe<T>;
25
36
  /**
26
37
  * Return the item at the front of the queue without removing it.
27
38
  *
28
39
  * @returns The item at the front of the queue without removing it, or undefined if the queue is empty
29
40
  */
30
- peek(): T | undefined;
41
+ peek(): Maybe<T>;
31
42
  /**
32
43
  * Clear all items from the queue.
33
44
  */
@@ -45,5 +56,20 @@ declare class Queue<T> {
45
56
  */
46
57
  toArray(): T[];
47
58
  }
59
+ declare class BoundedQueue<T> {
60
+ #private;
61
+ constructor(options: IBoundedQueueOptions, initial?: Iterable<T>);
62
+ get size(): number;
63
+ get isEmpty(): boolean;
64
+ get isFull(): boolean;
65
+ get maxSize(): number;
66
+ get overflow(): BoundedQueueOverflow;
67
+ enqueue(item: T): void;
68
+ dequeue(): Maybe<T>;
69
+ peek(): Maybe<T>;
70
+ clear(): void;
71
+ [Symbol.iterator](): Iterator<T>;
72
+ toArray(): T[];
73
+ }
48
74
  //#endregion
49
- export { Queue };
75
+ export { BoundedQueue, BoundedQueueOverflow, IBoundedQueueOptions, Queue };
@@ -1,6 +1,17 @@
1
- //#region src/queue.d.ts
1
+ import { Maybe } from "./typing.mjs";
2
+
3
+ //#region src/collections.d.ts
4
+ interface IBoundedQueueOptions {
5
+ maxSize: number;
6
+ overflow?: BoundedQueueOverflow;
7
+ }
8
+ declare const enum BoundedQueueOverflow {
9
+ DropOldest = 0,
10
+ DropNewest = 1,
11
+ Throw = 2
12
+ }
2
13
  declare class Queue<T> {
3
- private items;
14
+ #private;
4
15
  constructor(initial?: Iterable<T>);
5
16
  /**
6
17
  * Get the number of items in the queue.
@@ -21,13 +32,13 @@ declare class Queue<T> {
21
32
  *
22
33
  * @returns The item at the front of the queue, or undefined if the queue is empty
23
34
  */
24
- dequeue(): T | undefined;
35
+ dequeue(): Maybe<T>;
25
36
  /**
26
37
  * Return the item at the front of the queue without removing it.
27
38
  *
28
39
  * @returns The item at the front of the queue without removing it, or undefined if the queue is empty
29
40
  */
30
- peek(): T | undefined;
41
+ peek(): Maybe<T>;
31
42
  /**
32
43
  * Clear all items from the queue.
33
44
  */
@@ -45,5 +56,20 @@ declare class Queue<T> {
45
56
  */
46
57
  toArray(): T[];
47
58
  }
59
+ declare class BoundedQueue<T> {
60
+ #private;
61
+ constructor(options: IBoundedQueueOptions, initial?: Iterable<T>);
62
+ get size(): number;
63
+ get isEmpty(): boolean;
64
+ get isFull(): boolean;
65
+ get maxSize(): number;
66
+ get overflow(): BoundedQueueOverflow;
67
+ enqueue(item: T): void;
68
+ dequeue(): Maybe<T>;
69
+ peek(): Maybe<T>;
70
+ clear(): void;
71
+ [Symbol.iterator](): Iterator<T>;
72
+ toArray(): T[];
73
+ }
48
74
  //#endregion
49
- export { Queue };
75
+ export { BoundedQueue, BoundedQueueOverflow, IBoundedQueueOptions, Queue };
@@ -0,0 +1 @@
1
+ let e=function(e){return e[e.DropOldest=0]=`DropOldest`,e[e.DropNewest=1]=`DropNewest`,e[e.Throw=2]=`Throw`,e}({});var t=class{#e=[];#t=0;constructor(e){e&&(this.#e=[...e])}get size(){return this.#e.length-this.#t}get isEmpty(){return this.size===0}enqueue(e){this.#e.push(e)}dequeue(){if(this.#t>=this.#e.length)return;let e=this.#e[this.#t++];return this.#t>=64&&this.#t*2>=this.#e.length&&(this.#e=this.#e.slice(this.#t),this.#t=0),e}peek(){return this.#e[this.#t]}clear(){this.#e=[],this.#t=0}[Symbol.iterator](){return this.toArray()[Symbol.iterator]()}toArray(){return this.#e.slice(this.#t)}},n=class{#e;#t;#n;constructor(n,r){if(!Number.isInteger(n.maxSize)||n.maxSize<1)throw Error(`maxSize must be an integer >= 1`);if(this.#e=n.maxSize,this.#t=n.overflow??e.DropOldest,this.#n=new t,r)for(let e of r)this.enqueue(e)}get size(){return this.#n.size}get isEmpty(){return this.#n.isEmpty}get isFull(){return this.size>=this.#e}get maxSize(){return this.#e}get overflow(){return this.#t}enqueue(t){if(!this.isFull){this.#n.enqueue(t);return}if(this.#t!==e.DropNewest){if(this.#t===e.Throw)throw Error(`BoundedQueue overflow`);this.#n.dequeue(),this.#n.enqueue(t)}}dequeue(){return this.#n.dequeue()}peek(){return this.#n.peek()}clear(){this.#n.clear()}[Symbol.iterator](){return this.#n[Symbol.iterator]()}toArray(){return this.#n.toArray()}};export{n as BoundedQueue,e as BoundedQueueOverflow,t as Queue};
@@ -1 +1 @@
1
- function e(e){let t=new WeakMap,n=0;function r(e){let i=typeof e;return e===null||i===`number`||i===`string`||i===`boolean`?e:i===`undefined`?`undefined`:i===`function`?`function:${e.name||`anon`}`:e instanceof Date?`date:${e.toISOString()}`:e instanceof RegExp?`regexp:${e.toString()}`:Array.isArray(e)?e.map(r):e instanceof Map?{map:[...e.entries()].map(([e,t])=>[r(e),r(t)])}:e instanceof Set?{set:[...e.values()].map(r).sort()}:typeof e==`object`?t.has(e)?{ref:t.get(e)}:(t.set(e,n++),{obj:Object.entries(e).sort(([e],[t])=>e<t?-1:1).map(([e,t])=>[e,r(t)])}):e}return JSON.stringify(e.map(r))}function t(t){return function(n,r){let i=new WeakMap;return async function(...r){let a=Date.now(),o=i.get(this);o||(o=new Map,i.set(this,o));let s=e(r),c=o.get(s);if(c&&c.expiry>a)return c.value;let l=n.apply(this,r),u=l instanceof Promise?await l:l;return o.set(s,{value:u,expiry:a+t}),u}}}exports.cache=t;
1
+ Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});const e=new WeakMap;let t=0;function n(n){let r=new WeakMap,i=0;function a(n){let o=typeof n;if(n===null||o===`number`||o===`string`||o===`boolean`)return n;if(o===`undefined`)return`undefined`;if(o===`bigint`)return`bigint:${n.toString()}`;if(o===`function`){let r=e.get(n);return r===void 0&&(r=t++,e.set(n,r)),{fn:r,name:n.name||`anon`}}return n instanceof Date?`date:${n.toISOString()}`:n instanceof RegExp?`regexp:${n.toString()}`:Array.isArray(n)?n.map(a):n instanceof Map?{map:[...n.entries()].map(([e,t])=>[a(e),a(t)])}:n instanceof Set?{set:[...n.values()].map(a).sort()}:typeof n==`object`?r.has(n)?{ref:r.get(n)}:(r.set(n,i++),{obj:Object.entries(n).sort(([e],[t])=>e<t?-1:1).map(([e,t])=>[e,a(t)])}):n}return JSON.stringify(n.map(a))}function r(e){return function(t,r){let i=new WeakMap;return function(...r){let a=Date.now(),o=i.get(this);if(o||(o={entries:new Map,calls:0},i.set(this,o)),o.calls++,o.calls%64==0&&o.entries.size>0)for(let[e,t]of o.entries)t.expiry<=a&&o.entries.delete(e);let s=n(r),c=o.entries.get(s);if(c&&c.expiry>a)return c.value;c&&o.entries.delete(s);let l=t.apply(this,r);if(l instanceof Promise){let t=l.catch(e=>{throw o.entries.delete(s),e});return o.entries.set(s,{value:t,expiry:a+e}),t}return o.entries.set(s,{value:l,expiry:a+e}),l}}}exports.cache=r;
@@ -5,6 +5,6 @@
5
5
  *
6
6
  * @param ttlMs How long the cached value should be returned after its last call in milliseconds.
7
7
  */
8
- declare function cache(ttlMs: number): <T extends object>(method: (this: T, ...args: any[]) => any, _ctx: ClassMethodDecoratorContext<T>) => (this: T, ...args: any[]) => Promise<any>;
8
+ declare function cache(ttlMs: number): <T extends object, Args extends any[], R>(method: (this: T, ...args: Args) => R, _ctx: ClassMethodDecoratorContext<T, (this: T, ...args: Args) => R>) => (this: T, ...args: Args) => R;
9
9
  //#endregion
10
10
  export { cache };
@@ -5,6 +5,6 @@
5
5
  *
6
6
  * @param ttlMs How long the cached value should be returned after its last call in milliseconds.
7
7
  */
8
- declare function cache(ttlMs: number): <T extends object>(method: (this: T, ...args: any[]) => any, _ctx: ClassMethodDecoratorContext<T>) => (this: T, ...args: any[]) => Promise<any>;
8
+ declare function cache(ttlMs: number): <T extends object, Args extends any[], R>(method: (this: T, ...args: Args) => R, _ctx: ClassMethodDecoratorContext<T, (this: T, ...args: Args) => R>) => (this: T, ...args: Args) => R;
9
9
  //#endregion
10
10
  export { cache };
@@ -1 +1 @@
1
- function e(e){let t=new WeakMap,n=0;function r(e){let i=typeof e;return e===null||i===`number`||i===`string`||i===`boolean`?e:i===`undefined`?`undefined`:i===`function`?`function:${e.name||`anon`}`:e instanceof Date?`date:${e.toISOString()}`:e instanceof RegExp?`regexp:${e.toString()}`:Array.isArray(e)?e.map(r):e instanceof Map?{map:[...e.entries()].map(([e,t])=>[r(e),r(t)])}:e instanceof Set?{set:[...e.values()].map(r).sort()}:typeof e==`object`?t.has(e)?{ref:t.get(e)}:(t.set(e,n++),{obj:Object.entries(e).sort(([e],[t])=>e<t?-1:1).map(([e,t])=>[e,r(t)])}):e}return JSON.stringify(e.map(r))}function t(t){return function(n,r){let i=new WeakMap;return async function(...r){let a=Date.now(),o=i.get(this);o||(o=new Map,i.set(this,o));let s=e(r),c=o.get(s);if(c&&c.expiry>a)return c.value;let l=n.apply(this,r),u=l instanceof Promise?await l:l;return o.set(s,{value:u,expiry:a+t}),u}}}export{t as cache};
1
+ const e=new WeakMap;let t=0;function n(n){let r=new WeakMap,i=0;function a(n){let o=typeof n;if(n===null||o===`number`||o===`string`||o===`boolean`)return n;if(o===`undefined`)return`undefined`;if(o===`bigint`)return`bigint:${n.toString()}`;if(o===`function`){let r=e.get(n);return r===void 0&&(r=t++,e.set(n,r)),{fn:r,name:n.name||`anon`}}return n instanceof Date?`date:${n.toISOString()}`:n instanceof RegExp?`regexp:${n.toString()}`:Array.isArray(n)?n.map(a):n instanceof Map?{map:[...n.entries()].map(([e,t])=>[a(e),a(t)])}:n instanceof Set?{set:[...n.values()].map(a).sort()}:typeof n==`object`?r.has(n)?{ref:r.get(n)}:(r.set(n,i++),{obj:Object.entries(n).sort(([e],[t])=>e<t?-1:1).map(([e,t])=>[e,a(t)])}):n}return JSON.stringify(n.map(a))}function r(e){return function(t,r){let i=new WeakMap;return function(...r){let a=Date.now(),o=i.get(this);if(o||(o={entries:new Map,calls:0},i.set(this,o)),o.calls++,o.calls%64==0&&o.entries.size>0)for(let[e,t]of o.entries)t.expiry<=a&&o.entries.delete(e);let s=n(r),c=o.entries.get(s);if(c&&c.expiry>a)return c.value;c&&o.entries.delete(s);let l=t.apply(this,r);if(l instanceof Promise){let t=l.catch(e=>{throw o.entries.delete(s),e});return o.entries.set(s,{value:t,expiry:a+e}),t}return o.entries.set(s,{value:l,expiry:a+e}),l}}}export{r as cache};
@@ -0,0 +1 @@
1
+ Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});function e(e){let t=!1,n;return((...r)=>(t||=(n=e(...r),!0),n))}exports.once=e;
@@ -1,4 +1,4 @@
1
- //#region src/fn.d.ts
1
+ //#region src/functional.d.ts
2
2
  /**
3
3
  * Creates a function that calls the given function only once.
4
4
  *
@@ -1,4 +1,4 @@
1
- //#region src/fn.d.ts
1
+ //#region src/functional.d.ts
2
2
  /**
3
3
  * Creates a function that calls the given function only once.
4
4
  *
@@ -0,0 +1 @@
1
+ Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});function e(e){return!Number.isNaN(e.getTime())}function t(e){return typeof e==`object`&&!!e&&!Array.isArray(e)}function n(e){return typeof e==`string`&&e.length>0}function r(e){return typeof e==`number`&&Number.isFinite(e)}function i(t){return t instanceof Date?e(t):typeof t==`number`?Number.isFinite(t)&&e(new Date(t)):typeof t==`string`?t.length>0&&e(new Date(t)):!1}exports.isDateLike=i,exports.isNonEmptyString=n,exports.isNumber=r,exports.isRecord=t;
@@ -0,0 +1,7 @@
1
+ //#region src/guards.d.ts
2
+ declare function isRecord(value: unknown): value is Record<string, unknown>;
3
+ declare function isNonEmptyString(value: unknown): value is string;
4
+ declare function isNumber(value: unknown): value is number;
5
+ declare function isDateLike(value: unknown): value is Date | number | string;
6
+ //#endregion
7
+ export { isDateLike, isNonEmptyString, isNumber, isRecord };
@@ -0,0 +1,7 @@
1
+ //#region src/guards.d.ts
2
+ declare function isRecord(value: unknown): value is Record<string, unknown>;
3
+ declare function isNonEmptyString(value: unknown): value is string;
4
+ declare function isNumber(value: unknown): value is number;
5
+ declare function isDateLike(value: unknown): value is Date | number | string;
6
+ //#endregion
7
+ export { isDateLike, isNonEmptyString, isNumber, isRecord };
@@ -0,0 +1 @@
1
+ function e(e){return!Number.isNaN(e.getTime())}function t(e){return typeof e==`object`&&!!e&&!Array.isArray(e)}function n(e){return typeof e==`string`&&e.length>0}function r(e){return typeof e==`number`&&Number.isFinite(e)}function i(t){return t instanceof Date?e(t):typeof t==`number`?Number.isFinite(t)&&e(new Date(t)):typeof t==`string`?t.length>0&&e(new Date(t)):!1}export{i as isDateLike,n as isNonEmptyString,r as isNumber,t as isRecord};
package/dist/index.cjs CHANGED
@@ -1 +1 @@
1
- const e=require(`./async.cjs`),t=require(`./decorators.cjs`),n=require(`./fn.cjs`),r=require(`./lazy.cjs`),i=require(`./queue.cjs`),a=require(`./types.cjs`),o=require(`./urllib.cjs`);exports.Queue=i.Queue,exports.URLPath=o.URLPath,exports.allSettledSuccessful=e.allSettledSuccessful,exports.assume=a.assume,exports.cache=t.cache,exports.cast=a.cast,exports.lazy=r.lazy,exports.lazyAsync=r.lazyAsync,exports.once=n.once,exports.pollUntil=e.pollUntil,exports.rejectionTimeout=e.rejectionTimeout,exports.resettableLazy=r.resettableLazy,exports.sequential=e.sequential,exports.timeout=e.timeout,exports.typedEntries=a.typedEntries,exports.withTimeout=e.withTimeout;
1
+ Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});const e=require(`./collections.cjs`),t=require(`./decorators.cjs`),n=require(`./functional.cjs`),r=require(`./guards.cjs`),i=require(`./timing.cjs`),a=require(`./promise.cjs`),o=require(`./lazy.cjs`),s=require(`./number.cjs`),c=require(`./random.cjs`),l=require(`./state.cjs`),u=require(`./typing.cjs`),d=require(`./url.cjs`);exports.BoundedQueue=e.BoundedQueue,exports.BoundedQueueOverflow=e.BoundedQueueOverflow,exports.Flag=l.Flag,exports.Queue=e.Queue,exports.ResettableValue=l.ResettableValue,exports.RetryJitter=i.RetryJitter,exports.URLPath=d.URLPath,exports.abortAfter=i.abortAfter,exports.allSettledDetailed=a.allSettledDetailed,exports.allSettledSuccessful=a.allSettledSuccessful,exports.assume=u.assume,exports.average=s.average,exports.cache=t.cache,exports.cast=u.cast,exports.clamp=s.clamp,exports.err=u.err,exports.inRange=s.inRange,exports.isDateLike=r.isDateLike,exports.isNonEmptyString=r.isNonEmptyString,exports.isNumber=r.isNumber,exports.isOk=u.isOk,exports.isRecord=r.isRecord,exports.lazy=o.lazy,exports.lazyAsync=o.lazyAsync,exports.mapErr=u.mapErr,exports.mapOk=u.mapOk,exports.ok=u.ok,exports.once=n.once,exports.pMap=a.pMap,exports.pickRandom=c.pickRandom,exports.pickWeighted=c.pickWeighted,exports.pollUntil=i.pollUntil,exports.pool=a.pool,exports.raceSignals=i.raceSignals,exports.randomFloat=c.randomFloat,exports.randomInt=c.randomInt,exports.rejectionTimeout=i.rejectionTimeout,exports.resettableLazy=l.resettableLazy,exports.resettableLazyAsync=l.resettableLazyAsync,exports.retry=i.retry,exports.roundTo=s.roundTo,exports.sequential=a.sequential,exports.sum=s.sum,exports.timeout=i.timeout,exports.tryCatchAsync=u.tryCatchAsync,exports.typedEntries=u.typedEntries,exports.url=d.url,exports.withAbort=i.withAbort,exports.withTimeout=i.withTimeout;
package/dist/index.d.cts CHANGED
@@ -1,8 +1,13 @@
1
- import { allSettledSuccessful, pollUntil, rejectionTimeout, sequential, timeout, withTimeout } from "./async.cjs";
1
+ import { Awaitable, Maybe, Nullable, Result, assume, cast, err, isOk, mapErr, mapOk, ok, tryCatchAsync, typedEntries } from "./typing.cjs";
2
+ import { BoundedQueue, BoundedQueueOverflow, IBoundedQueueOptions, Queue } from "./collections.cjs";
2
3
  import { cache } from "./decorators.cjs";
3
- import { once } from "./fn.cjs";
4
- import { lazy, lazyAsync, resettableLazy } from "./lazy.cjs";
5
- import { Queue } from "./queue.cjs";
6
- import { Awaitable, Maybe, Nullable, assume, cast, typedEntries } from "./types.cjs";
7
- import { QueryObject, QueryValue, URLLike, URLPath } from "./urllib.cjs";
8
- export { Awaitable, Maybe, Nullable, QueryObject, QueryValue, Queue, URLLike, URLPath, allSettledSuccessful, assume, cache, cast, lazy, lazyAsync, once, pollUntil, rejectionTimeout, resettableLazy, sequential, timeout, typedEntries, withTimeout };
4
+ import { once } from "./functional.cjs";
5
+ import { isDateLike, isNonEmptyString, isNumber, isRecord } from "./guards.cjs";
6
+ import { IRetryOptions, RetryJitter, abortAfter, pollUntil, raceSignals, rejectionTimeout, retry, timeout, withAbort, withTimeout } from "./timing.cjs";
7
+ import { IConcurrencyOptions, SettledDetailed, allSettledDetailed, allSettledSuccessful, pMap, pool, sequential } from "./promise.cjs";
8
+ import { lazy, lazyAsync } from "./lazy.cjs";
9
+ import { average, clamp, inRange, roundTo, sum } from "./number.cjs";
10
+ import { IWeightedItem, pickRandom, pickWeighted, randomFloat, randomInt } from "./random.cjs";
11
+ import { Flag, ResettableValue, resettableLazy, resettableLazyAsync } from "./state.cjs";
12
+ import { QueryObject, QueryValue, URLLike, URLPath, url } from "./url.cjs";
13
+ export { Awaitable, BoundedQueue, BoundedQueueOverflow, Flag, IBoundedQueueOptions, IConcurrencyOptions, IRetryOptions, IWeightedItem, Maybe, Nullable, QueryObject, QueryValue, Queue, ResettableValue, Result, RetryJitter, SettledDetailed, URLLike, URLPath, abortAfter, allSettledDetailed, allSettledSuccessful, assume, average, cache, cast, clamp, err, inRange, isDateLike, isNonEmptyString, isNumber, isOk, isRecord, lazy, lazyAsync, mapErr, mapOk, ok, once, pMap, pickRandom, pickWeighted, pollUntil, pool, raceSignals, randomFloat, randomInt, rejectionTimeout, resettableLazy, resettableLazyAsync, retry, roundTo, sequential, sum, timeout, tryCatchAsync, typedEntries, url, withAbort, withTimeout };
package/dist/index.d.mts CHANGED
@@ -1,8 +1,13 @@
1
- import { allSettledSuccessful, pollUntil, rejectionTimeout, sequential, timeout, withTimeout } from "./async.mjs";
1
+ import { Awaitable, Maybe, Nullable, Result, assume, cast, err, isOk, mapErr, mapOk, ok, tryCatchAsync, typedEntries } from "./typing.mjs";
2
+ import { BoundedQueue, BoundedQueueOverflow, IBoundedQueueOptions, Queue } from "./collections.mjs";
2
3
  import { cache } from "./decorators.mjs";
3
- import { once } from "./fn.mjs";
4
- import { lazy, lazyAsync, resettableLazy } from "./lazy.mjs";
5
- import { Queue } from "./queue.mjs";
6
- import { Awaitable, Maybe, Nullable, assume, cast, typedEntries } from "./types.mjs";
7
- import { QueryObject, QueryValue, URLLike, URLPath } from "./urllib.mjs";
8
- export { Awaitable, Maybe, Nullable, QueryObject, QueryValue, Queue, URLLike, URLPath, allSettledSuccessful, assume, cache, cast, lazy, lazyAsync, once, pollUntil, rejectionTimeout, resettableLazy, sequential, timeout, typedEntries, withTimeout };
4
+ import { once } from "./functional.mjs";
5
+ import { isDateLike, isNonEmptyString, isNumber, isRecord } from "./guards.mjs";
6
+ import { IRetryOptions, RetryJitter, abortAfter, pollUntil, raceSignals, rejectionTimeout, retry, timeout, withAbort, withTimeout } from "./timing.mjs";
7
+ import { IConcurrencyOptions, SettledDetailed, allSettledDetailed, allSettledSuccessful, pMap, pool, sequential } from "./promise.mjs";
8
+ import { lazy, lazyAsync } from "./lazy.mjs";
9
+ import { average, clamp, inRange, roundTo, sum } from "./number.mjs";
10
+ import { IWeightedItem, pickRandom, pickWeighted, randomFloat, randomInt } from "./random.mjs";
11
+ import { Flag, ResettableValue, resettableLazy, resettableLazyAsync } from "./state.mjs";
12
+ import { QueryObject, QueryValue, URLLike, URLPath, url } from "./url.mjs";
13
+ export { Awaitable, BoundedQueue, BoundedQueueOverflow, Flag, IBoundedQueueOptions, IConcurrencyOptions, IRetryOptions, IWeightedItem, Maybe, Nullable, QueryObject, QueryValue, Queue, ResettableValue, Result, RetryJitter, SettledDetailed, URLLike, URLPath, abortAfter, allSettledDetailed, allSettledSuccessful, assume, average, cache, cast, clamp, err, inRange, isDateLike, isNonEmptyString, isNumber, isOk, isRecord, lazy, lazyAsync, mapErr, mapOk, ok, once, pMap, pickRandom, pickWeighted, pollUntil, pool, raceSignals, randomFloat, randomInt, rejectionTimeout, resettableLazy, resettableLazyAsync, retry, roundTo, sequential, sum, timeout, tryCatchAsync, typedEntries, url, withAbort, withTimeout };
package/dist/index.mjs CHANGED
@@ -1 +1 @@
1
- import{allSettledSuccessful as e,pollUntil as t,rejectionTimeout as n,sequential as r,timeout as i,withTimeout as a}from"./async.mjs";import{cache as o}from"./decorators.mjs";import{once as s}from"./fn.mjs";import{lazy as c,lazyAsync as l,resettableLazy as u}from"./lazy.mjs";import{Queue as d}from"./queue.mjs";import{assume as f,cast as p,typedEntries as m}from"./types.mjs";import{URLPath as h}from"./urllib.mjs";export{d as Queue,h as URLPath,e as allSettledSuccessful,f as assume,o as cache,p as cast,c as lazy,l as lazyAsync,s as once,t as pollUntil,n as rejectionTimeout,u as resettableLazy,r as sequential,i as timeout,m as typedEntries,a as withTimeout};
1
+ import{BoundedQueue as e,BoundedQueueOverflow as t,Queue as n}from"./collections.mjs";import{cache as r}from"./decorators.mjs";import{once as i}from"./functional.mjs";import{isDateLike as a,isNonEmptyString as o,isNumber as s,isRecord as c}from"./guards.mjs";import{RetryJitter as l,abortAfter as u,pollUntil as d,raceSignals as f,rejectionTimeout as p,retry as m,timeout as h,withAbort as g,withTimeout as _}from"./timing.mjs";import{allSettledDetailed as v,allSettledSuccessful as y,pMap as b,pool as x,sequential as S}from"./promise.mjs";import{lazy as C,lazyAsync as w}from"./lazy.mjs";import{average as T,clamp as E,inRange as D,roundTo as O,sum as k}from"./number.mjs";import{pickRandom as A,pickWeighted as j,randomFloat as M,randomInt as N}from"./random.mjs";import{Flag as P,ResettableValue as F,resettableLazy as I,resettableLazyAsync as L}from"./state.mjs";import{assume as R,cast as z,err as B,isOk as V,mapErr as H,mapOk as U,ok as W,tryCatchAsync as G,typedEntries as K}from"./typing.mjs";import{URLPath as q,url as J}from"./url.mjs";export{e as BoundedQueue,t as BoundedQueueOverflow,P as Flag,n as Queue,F as ResettableValue,l as RetryJitter,q as URLPath,u as abortAfter,v as allSettledDetailed,y as allSettledSuccessful,R as assume,T as average,r as cache,z as cast,E as clamp,B as err,D as inRange,a as isDateLike,o as isNonEmptyString,s as isNumber,V as isOk,c as isRecord,C as lazy,w as lazyAsync,H as mapErr,U as mapOk,W as ok,i as once,b as pMap,A as pickRandom,j as pickWeighted,d as pollUntil,x as pool,f as raceSignals,M as randomFloat,N as randomInt,p as rejectionTimeout,I as resettableLazy,L as resettableLazyAsync,m as retry,O as roundTo,S as sequential,k as sum,h as timeout,G as tryCatchAsync,K as typedEntries,J as url,g as withAbort,_ as withTimeout};
package/dist/lazy.cjs CHANGED
@@ -1 +1 @@
1
- function e(e){let t,n=!1;return()=>(n||=(t=e(),!0),t)}function t(e){let t;return()=>(t||=e(),t)}function n(e){let t,n=!1;function r(){return n||=(t=e(),!0),t}function i(){n=!1,t=void 0}return{get:r,reset:i}}exports.lazy=e,exports.lazyAsync=t,exports.resettableLazy=n;
1
+ Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});function e(e){let t,n=!1;return()=>(n||=(t=e(),!0),t)}function t(e){let t;return()=>(t||=e(),t)}exports.lazy=e,exports.lazyAsync=t;
package/dist/lazy.d.cts CHANGED
@@ -1,9 +1,5 @@
1
1
  //#region src/lazy.d.ts
2
2
  declare function lazy<T>(factory: () => T): () => T;
3
3
  declare function lazyAsync<T>(factory: () => Promise<T>): () => Promise<T>;
4
- declare function resettableLazy<T>(factory: () => T): {
5
- get: () => T;
6
- reset: () => void;
7
- };
8
4
  //#endregion
9
- export { lazy, lazyAsync, resettableLazy };
5
+ export { lazy, lazyAsync };
package/dist/lazy.d.mts CHANGED
@@ -1,9 +1,5 @@
1
1
  //#region src/lazy.d.ts
2
2
  declare function lazy<T>(factory: () => T): () => T;
3
3
  declare function lazyAsync<T>(factory: () => Promise<T>): () => Promise<T>;
4
- declare function resettableLazy<T>(factory: () => T): {
5
- get: () => T;
6
- reset: () => void;
7
- };
8
4
  //#endregion
9
- export { lazy, lazyAsync, resettableLazy };
5
+ export { lazy, lazyAsync };
package/dist/lazy.mjs CHANGED
@@ -1 +1 @@
1
- function e(e){let t,n=!1;return()=>(n||=(t=e(),!0),t)}function t(e){let t;return()=>(t||=e(),t)}function n(e){let t,n=!1;function r(){return n||=(t=e(),!0),t}function i(){n=!1,t=void 0}return{get:r,reset:i}}export{e as lazy,t as lazyAsync,n as resettableLazy};
1
+ function e(e){let t,n=!1;return()=>(n||=(t=e(),!0),t)}function t(e){let t;return()=>(t||=e(),t)}export{e as lazy,t as lazyAsync};
@@ -0,0 +1 @@
1
+ Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});function e(e,t,n){if(t>n)throw Error(`min must be <= max`);return Math.min(Math.max(e,t),n)}function t(e,t,n,r=!0){if(t>n)throw Error(`min must be <= max`);return r?e>=t&&e<=n:e>t&&e<n}function n(e,t=0){if(!Number.isInteger(t)||t<0)throw Error(`decimals must be an integer >= 0`);let n=10**t;return Math.round((e+2**-52)*n)/n}function r(e){let t=0;for(let n of e)t+=n;return t}function i(e){let t=0,n=0;for(let r of e)t+=r,n++;if(n===0)throw Error(`cannot compute average of empty iterable`);return t/n}exports.average=i,exports.clamp=e,exports.inRange=t,exports.roundTo=n,exports.sum=r;
@@ -0,0 +1,8 @@
1
+ //#region src/number.d.ts
2
+ declare function clamp(value: number, min: number, max: number): number;
3
+ declare function inRange(value: number, min: number, max: number, inclusive?: boolean): boolean;
4
+ declare function roundTo(value: number, decimals?: number): number;
5
+ declare function sum(values: Iterable<number>): number;
6
+ declare function average(values: Iterable<number>): number;
7
+ //#endregion
8
+ export { average, clamp, inRange, roundTo, sum };
@@ -0,0 +1,8 @@
1
+ //#region src/number.d.ts
2
+ declare function clamp(value: number, min: number, max: number): number;
3
+ declare function inRange(value: number, min: number, max: number, inclusive?: boolean): boolean;
4
+ declare function roundTo(value: number, decimals?: number): number;
5
+ declare function sum(values: Iterable<number>): number;
6
+ declare function average(values: Iterable<number>): number;
7
+ //#endregion
8
+ export { average, clamp, inRange, roundTo, sum };
@@ -0,0 +1 @@
1
+ function e(e,t,n){if(t>n)throw Error(`min must be <= max`);return Math.min(Math.max(e,t),n)}function t(e,t,n,r=!0){if(t>n)throw Error(`min must be <= max`);return r?e>=t&&e<=n:e>t&&e<n}function n(e,t=0){if(!Number.isInteger(t)||t<0)throw Error(`decimals must be an integer >= 0`);let n=10**t;return Math.round((e+2**-52)*n)/n}function r(e){let t=0;for(let n of e)t+=n;return t}function i(e){let t=0,n=0;for(let r of e)t+=r,n++;if(n===0)throw Error(`cannot compute average of empty iterable`);return t/n}export{i as average,e as clamp,t as inRange,n as roundTo,r as sum};
@@ -0,0 +1 @@
1
+ Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});async function e(e){return(await Promise.allSettled(e)).filter(e=>e.status===`fulfilled`).map(e=>e.value)}async function t(e){let t=await Promise.allSettled(e),n=[],r=[];for(let e of t){if(e.status===`fulfilled`){n.push(e.value);continue}r.push(e.reason)}return{results:t,fulfilled:n,rejected:r}}async function n(e){let t=[];for(let n of e)t.push(await n());return t}function r(e){if(!Number.isInteger(e)||e<1)throw Error(`concurrency must be an integer >= 1`);return e}async function i(e,t={}){if(e.length===0)return[];let n=r(t.concurrency??e.length),i=Array(e.length),a=0;async function o(){for(;;){let t=a++;if(t>=e.length)return;i[t]=await e[t]()}}let s=Math.min(n,e.length),c=Array.from({length:s},()=>o());return await Promise.all(c),i}async function a(e,t,n={}){let r=[],a=0;for(let n of e){let e=a++;r.push(()=>t(n,e))}return i(r,n)}exports.allSettledDetailed=t,exports.allSettledSuccessful=e,exports.pMap=a,exports.pool=i,exports.sequential=n;