@vielzeug/arsenal 1.1.2 → 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.
- package/README.md +31 -75
- package/dist/_dev.cjs +1 -1
- package/dist/_dev.cjs.map +1 -1
- package/dist/_dev.js +2 -5
- package/dist/_dev.js.map +1 -1
- package/dist/array/chunk.cjs +1 -1
- package/dist/array/chunk.cjs.map +1 -1
- package/dist/array/chunk.d.ts +2 -1
- package/dist/array/chunk.d.ts.map +1 -1
- package/dist/array/chunk.js +5 -7
- package/dist/array/chunk.js.map +1 -1
- package/dist/array/compare.cjs +1 -1
- package/dist/array/compare.cjs.map +1 -1
- package/dist/array/compare.d.ts.map +1 -1
- package/dist/array/compare.js +13 -14
- package/dist/array/compare.js.map +1 -1
- package/dist/array/index.cjs +1 -0
- package/dist/array/index.js +29 -0
- package/dist/array/search.cjs +1 -1
- package/dist/array/search.cjs.map +1 -1
- package/dist/array/search.d.ts +8 -77
- package/dist/array/search.d.ts.map +1 -1
- package/dist/array/search.js +21 -38
- package/dist/array/search.js.map +1 -1
- package/dist/array/sort.cjs +1 -1
- package/dist/array/sort.cjs.map +1 -1
- package/dist/array/sort.d.ts +1 -1
- package/dist/array/sort.d.ts.map +1 -1
- package/dist/array/sort.js +9 -10
- package/dist/array/sort.js.map +1 -1
- package/dist/arsenal.cjs +1 -1
- package/dist/arsenal.cjs.map +1 -1
- package/dist/arsenal.iife.js +1 -1
- package/dist/arsenal.iife.js.map +1 -1
- package/dist/arsenal.js +1 -1
- package/dist/arsenal.js.map +1 -1
- package/dist/async/attempt.cjs +1 -1
- package/dist/async/attempt.cjs.map +1 -1
- package/dist/async/attempt.d.ts +3 -8
- package/dist/async/attempt.d.ts.map +1 -1
- package/dist/async/attempt.js +3 -10
- package/dist/async/attempt.js.map +1 -1
- package/dist/async/index.cjs +1 -0
- package/dist/async/index.d.ts +1 -1
- package/dist/async/index.d.ts.map +1 -1
- package/dist/async/index.js +9 -0
- package/dist/async/parallel.cjs +1 -1
- package/dist/async/parallel.cjs.map +1 -1
- package/dist/async/parallel.d.ts +1 -1
- package/dist/async/parallel.d.ts.map +1 -1
- package/dist/async/parallel.js +15 -16
- package/dist/async/parallel.js.map +1 -1
- package/dist/async/retry.cjs +1 -1
- package/dist/async/retry.cjs.map +1 -1
- package/dist/async/retry.d.ts +1 -1
- package/dist/async/retry.d.ts.map +1 -1
- package/dist/async/retry.js +14 -15
- package/dist/async/retry.js.map +1 -1
- package/dist/async/taskPool.cjs +2 -0
- package/dist/async/taskPool.cjs.map +1 -0
- package/dist/async/taskPool.d.ts +14 -0
- package/dist/async/taskPool.d.ts.map +1 -0
- package/dist/async/taskPool.js +51 -0
- package/dist/async/taskPool.js.map +1 -0
- package/dist/cache/cache.cjs +2 -0
- package/dist/cache/cache.cjs.map +1 -0
- package/dist/cache/cache.d.ts +17 -0
- package/dist/cache/cache.d.ts.map +1 -0
- package/dist/cache/cache.js +59 -0
- package/dist/cache/cache.js.map +1 -0
- package/dist/cache/index.cjs +1 -0
- package/dist/cache/index.d.ts +1 -1
- package/dist/cache/index.d.ts.map +1 -1
- package/dist/cache/index.js +3 -0
- package/dist/cache/memo.cjs +1 -1
- package/dist/cache/memo.cjs.map +1 -1
- package/dist/cache/memo.d.ts +2 -2
- package/dist/cache/memo.js +24 -23
- package/dist/cache/memo.js.map +1 -1
- package/dist/errors.cjs +1 -1
- package/dist/errors.cjs.map +1 -1
- package/dist/errors.d.ts +0 -7
- package/dist/errors.d.ts.map +1 -1
- package/dist/errors.js +2 -2
- package/dist/errors.js.map +1 -1
- package/dist/function/debounce.cjs +1 -1
- package/dist/function/debounce.cjs.map +1 -1
- package/dist/function/debounce.js +15 -17
- package/dist/function/debounce.js.map +1 -1
- package/dist/function/index.cjs +1 -0
- package/dist/function/index.d.ts +0 -2
- package/dist/function/index.d.ts.map +1 -1
- package/dist/function/index.js +8 -0
- package/dist/function/pipe.cjs +1 -1
- package/dist/function/pipe.cjs.map +1 -1
- package/dist/function/pipe.js +1 -1
- package/dist/function/pipe.js.map +1 -1
- package/dist/guards/index.cjs +1 -0
- package/dist/guards/index.d.ts +0 -3
- package/dist/guards/index.d.ts.map +1 -1
- package/dist/guards/index.js +17 -0
- package/dist/guards/isEqual.cjs.map +1 -1
- package/dist/guards/isEqual.js.map +1 -1
- package/dist/index.cjs +1 -1
- package/dist/index.d.ts +2 -91
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +30 -118
- package/dist/math/allocate.cjs +1 -1
- package/dist/math/allocate.cjs.map +1 -1
- package/dist/math/allocate.d.ts +1 -1
- package/dist/math/allocate.d.ts.map +1 -1
- package/dist/math/allocate.js +13 -14
- package/dist/math/allocate.js.map +1 -1
- package/dist/math/index.cjs +1 -0
- package/dist/math/index.d.ts +0 -3
- package/dist/math/index.d.ts.map +1 -1
- package/dist/math/index.js +17 -0
- package/dist/math/mod.cjs +1 -1
- package/dist/math/mod.cjs.map +1 -1
- package/dist/math/mod.d.ts +1 -1
- package/dist/math/mod.d.ts.map +1 -1
- package/dist/math/mod.js +4 -5
- package/dist/math/mod.js.map +1 -1
- package/dist/math/range.cjs +1 -1
- package/dist/math/range.cjs.map +1 -1
- package/dist/math/range.d.ts +1 -1
- package/dist/math/range.d.ts.map +1 -1
- package/dist/math/range.js +14 -15
- package/dist/math/range.js.map +1 -1
- package/dist/math/sum.cjs +1 -1
- package/dist/math/sum.cjs.map +1 -1
- package/dist/math/sum.d.ts +2 -2
- package/dist/math/sum.d.ts.map +1 -1
- package/dist/math/sum.js +6 -7
- package/dist/math/sum.js.map +1 -1
- package/dist/object/getPath.cjs +1 -1
- package/dist/object/getPath.cjs.map +1 -1
- package/dist/object/getPath.d.ts +12 -42
- package/dist/object/getPath.d.ts.map +1 -1
- package/dist/object/getPath.js +21 -22
- package/dist/object/getPath.js.map +1 -1
- package/dist/object/index.cjs +1 -0
- package/dist/object/index.d.ts +1 -1
- package/dist/object/index.d.ts.map +1 -1
- package/dist/object/index.js +15 -0
- package/dist/object/merge.cjs +1 -1
- package/dist/object/merge.cjs.map +1 -1
- package/dist/object/merge.d.ts +1 -1
- package/dist/object/merge.d.ts.map +1 -1
- package/dist/object/merge.js +2 -3
- package/dist/object/merge.js.map +1 -1
- package/dist/object/prune.cjs +1 -1
- package/dist/object/prune.cjs.map +1 -1
- package/dist/object/prune.d.ts.map +1 -1
- package/dist/object/prune.js +22 -23
- package/dist/object/prune.js.map +1 -1
- package/dist/object/tryParseJson.cjs +2 -0
- package/dist/object/tryParseJson.cjs.map +1 -0
- package/dist/object/tryParseJson.d.ts +9 -0
- package/dist/object/tryParseJson.d.ts.map +1 -0
- package/dist/object/tryParseJson.js +18 -0
- package/dist/object/tryParseJson.js.map +1 -0
- package/dist/random/_index.cjs +2 -0
- package/dist/random/_index.cjs.map +1 -0
- package/dist/random/_index.d.ts +3 -0
- package/dist/random/_index.d.ts.map +1 -0
- package/dist/random/_index.js +10 -0
- package/dist/random/_index.js.map +1 -0
- package/dist/random/draw.cjs +1 -1
- package/dist/random/draw.cjs.map +1 -1
- package/dist/random/draw.d.ts +3 -2
- package/dist/random/draw.d.ts.map +1 -1
- package/dist/random/draw.js +12 -12
- package/dist/random/draw.js.map +1 -1
- package/dist/random/index.cjs +1 -0
- package/dist/random/index.d.ts +1 -0
- package/dist/random/index.d.ts.map +1 -1
- package/dist/random/index.js +5 -0
- package/dist/random/random.cjs +1 -1
- package/dist/random/random.cjs.map +1 -1
- package/dist/random/random.d.ts +2 -1
- package/dist/random/random.d.ts.map +1 -1
- package/dist/random/random.js +5 -6
- package/dist/random/random.js.map +1 -1
- package/dist/random/shuffle.cjs +1 -1
- package/dist/random/shuffle.cjs.map +1 -1
- package/dist/random/shuffle.d.ts +2 -1
- package/dist/random/shuffle.d.ts.map +1 -1
- package/dist/random/shuffle.js +7 -7
- package/dist/random/shuffle.js.map +1 -1
- package/dist/random/source.d.ts +4 -0
- package/dist/random/source.d.ts.map +1 -0
- package/dist/string/index.cjs +1 -0
- package/dist/string/index.d.ts +0 -2
- package/dist/string/index.d.ts.map +1 -1
- package/dist/string/index.js +12 -0
- package/dist/string/similarity.cjs +1 -1
- package/dist/string/similarity.cjs.map +1 -1
- package/dist/string/similarity.d.ts.map +1 -1
- package/dist/string/similarity.js +16 -17
- package/dist/string/similarity.js.map +1 -1
- package/dist/string/truncate.cjs +1 -1
- package/dist/string/truncate.cjs.map +1 -1
- package/dist/string/truncate.d.ts +2 -1
- package/dist/string/truncate.d.ts.map +1 -1
- package/dist/string/truncate.js +10 -11
- package/dist/string/truncate.js.map +1 -1
- package/dist/types.d.ts +1 -1
- package/dist/types.d.ts.map +1 -1
- package/package.json +11 -16
- package/dist/_common/_secureRandomIndex.cjs +0 -2
- package/dist/_common/_secureRandomIndex.cjs.map +0 -1
- package/dist/_common/_secureRandomIndex.d.ts +0 -2
- package/dist/_common/_secureRandomIndex.d.ts.map +0 -1
- package/dist/_common/_secureRandomIndex.js +0 -9
- package/dist/_common/_secureRandomIndex.js.map +0 -1
- package/dist/async/queue.cjs +0 -2
- package/dist/async/queue.cjs.map +0 -1
- package/dist/async/queue.d.ts +0 -42
- package/dist/async/queue.d.ts.map +0 -1
- package/dist/async/queue.js +0 -72
- package/dist/async/queue.js.map +0 -1
- package/dist/cache/stash.cjs +0 -2
- package/dist/cache/stash.cjs.map +0 -1
- package/dist/cache/stash.d.ts +0 -111
- package/dist/cache/stash.d.ts.map +0 -1
- package/dist/cache/stash.js +0 -92
- package/dist/cache/stash.js.map +0 -1
- package/dist/function/constant.cjs +0 -2
- package/dist/function/constant.cjs.map +0 -1
- package/dist/function/constant.d.ts +0 -5
- package/dist/function/constant.d.ts.map +0 -1
- package/dist/function/constant.js +0 -8
- package/dist/function/constant.js.map +0 -1
- package/dist/function/identity.cjs +0 -2
- package/dist/function/identity.cjs.map +0 -1
- package/dist/function/identity.d.ts +0 -5
- package/dist/function/identity.d.ts.map +0 -1
- package/dist/function/identity.js +0 -8
- package/dist/function/identity.js.map +0 -1
- package/dist/guards/isArray.cjs +0 -2
- package/dist/guards/isArray.cjs.map +0 -1
- package/dist/guards/isArray.d.ts +0 -16
- package/dist/guards/isArray.d.ts.map +0 -1
- package/dist/guards/isArray.js +0 -8
- package/dist/guards/isArray.js.map +0 -1
- package/dist/guards/isBoolean.cjs +0 -2
- package/dist/guards/isBoolean.cjs.map +0 -1
- package/dist/guards/isBoolean.d.ts +0 -23
- package/dist/guards/isBoolean.d.ts.map +0 -1
- package/dist/guards/isBoolean.js +0 -8
- package/dist/guards/isBoolean.js.map +0 -1
- package/dist/guards/isString.cjs +0 -2
- package/dist/guards/isString.cjs.map +0 -1
- package/dist/guards/isString.d.ts +0 -15
- package/dist/guards/isString.d.ts.map +0 -1
- package/dist/guards/isString.js +0 -8
- package/dist/guards/isString.js.map +0 -1
- package/dist/math/abs.cjs +0 -2
- package/dist/math/abs.cjs.map +0 -1
- package/dist/math/abs.d.ts +0 -17
- package/dist/math/abs.d.ts.map +0 -1
- package/dist/math/abs.js +0 -8
- package/dist/math/abs.js.map +0 -1
- package/dist/math/max.cjs +0 -2
- package/dist/math/max.cjs.map +0 -1
- package/dist/math/max.d.ts +0 -21
- package/dist/math/max.d.ts.map +0 -1
- package/dist/math/max.js +0 -12
- package/dist/math/max.js.map +0 -1
- package/dist/math/min.cjs +0 -2
- package/dist/math/min.cjs.map +0 -1
- package/dist/math/min.d.ts +0 -21
- package/dist/math/min.d.ts.map +0 -1
- package/dist/math/min.js +0 -12
- package/dist/math/min.js.map +0 -1
- package/dist/object/parseJSON.cjs +0 -2
- package/dist/object/parseJSON.cjs.map +0 -1
- package/dist/object/parseJSON.d.ts +0 -32
- package/dist/object/parseJSON.d.ts.map +0 -1
- package/dist/object/parseJSON.js +0 -16
- package/dist/object/parseJSON.js.map +0 -1
- package/dist/string/endsWith.cjs +0 -2
- package/dist/string/endsWith.cjs.map +0 -1
- package/dist/string/endsWith.d.ts +0 -5
- package/dist/string/endsWith.d.ts.map +0 -1
- package/dist/string/endsWith.js +0 -8
- package/dist/string/endsWith.js.map +0 -1
- package/dist/string/startsWith.cjs +0 -2
- package/dist/string/startsWith.cjs.map +0 -1
- package/dist/string/startsWith.d.ts +0 -5
- package/dist/string/startsWith.d.ts.map +0 -1
- package/dist/string/startsWith.js +0 -8
- package/dist/string/startsWith.js.map +0 -1
package/dist/async/attempt.cjs
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
function e(e){return e.ok===!0}function t(e){return e.ok===!1}function n(e){try{
|
|
1
|
+
function e(e){return e.ok===!0}function t(e){return e.ok===!1}async function n(e){try{return{ok:!0,value:await e()}}catch(e){return{error:e,ok:!1}}}exports.attempt=n,exports.isFail=t,exports.isOk=e;
|
|
2
2
|
//# sourceMappingURL=attempt.cjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"attempt.cjs","names":[],"sources":["../../src/async/attempt.ts"],"sourcesContent":["export type AttemptResult<T> =\n | { ok: true; value: T }\n // eslint-disable-next-line perfectionist/sort-object-types\n | { ok: false; error: unknown };\n\n/**\n * Narrows an `AttemptResult` to the success branch.\n * @example\n * ```ts\n * const result = await attempt(() => fetch('/api').then(r => r.json()));\n * if (isOk(result)) console.log(result.value);\n * ```\n */\n\nexport function isOk<T>(result: AttemptResult<T>): result is { ok: true; value: T } {\n return result.ok === true;\n}\n\n/**\n * Narrows an `AttemptResult` to the failure branch.\n * @example\n * ```ts\n * const result = await attempt(() => fetch('/api').then(r => r.json()));\n * if (isFail(result)) console.error(result.error);\n * ```\n */\n// eslint-disable-next-line perfectionist/sort-object-types\nexport function isFail<T>(result: AttemptResult<T>): result is { ok: false; error: unknown } {\n return result.ok === false;\n}\n\n/**\n * Executes a function — sync or async — and
|
|
1
|
+
{"version":3,"file":"attempt.cjs","names":[],"sources":["../../src/async/attempt.ts"],"sourcesContent":["export type AttemptResult<T> =\n | { ok: true; value: T }\n // eslint-disable-next-line perfectionist/sort-object-types\n | { ok: false; error: unknown };\n\n/**\n * Narrows an `AttemptResult` to the success branch.\n * @example\n * ```ts\n * const result = await attempt(() => fetch('/api').then(r => r.json()));\n * if (isOk(result)) console.log(result.value);\n * ```\n */\n\nexport function isOk<T>(result: AttemptResult<T>): result is { ok: true; value: T } {\n return result.ok === true;\n}\n\n/**\n * Narrows an `AttemptResult` to the failure branch.\n * @example\n * ```ts\n * const result = await attempt(() => fetch('/api').then(r => r.json()));\n * if (isFail(result)) console.error(result.error);\n * ```\n */\n// eslint-disable-next-line perfectionist/sort-object-types\nexport function isFail<T>(result: AttemptResult<T>): result is { ok: false; error: unknown } {\n return result.ok === false;\n}\n\n/**\n * Executes a function — sync or async — and resolves to an `AttemptResult`.\n * Never throws.\n *\n * @example\n * ```ts\n * // Sync\n * const parsed = attempt(() => JSON.parse(rawJson));\n * if (parsed.ok) console.log(parsed.value);\n * else console.error(parsed.error);\n *\n * // Async\n * const result = await attempt(() => fetch('/api').then(r => r.json()));\n * if (result.ok) console.log(result.value);\n * else console.error(result.error);\n *\n * // Combined with retry()\n * const result = await attempt(() => retry(fn, { times: 3 }));\n * ```\n */\nexport async function attempt<T>(fn: () => T | Promise<T>): Promise<AttemptResult<T>> {\n try {\n return { ok: true, value: await fn() };\n } catch (error) {\n return { error, ok: false };\n }\n}\n"],"mappings":"AAcA,SAAgB,EAAQ,EAA4D,CAClF,OAAO,EAAO,KAAO,EACvB,CAWA,SAAgB,EAAU,EAAmE,CAC3F,OAAO,EAAO,KAAO,EACvB,CAsBA,eAAsB,EAAW,EAAqD,CACpF,GAAI,CACF,MAAO,CAAE,GAAI,GAAM,MAAO,MAAM,EAAG,CAAE,CACvC,OAAS,EAAO,CACd,MAAO,CAAE,QAAO,GAAI,EAAM,CAC5B,CACF"}
|
package/dist/async/attempt.d.ts
CHANGED
|
@@ -30,12 +30,8 @@ export declare function isFail<T>(result: AttemptResult<T>): result is {
|
|
|
30
30
|
error: unknown;
|
|
31
31
|
};
|
|
32
32
|
/**
|
|
33
|
-
* Executes a function — sync or async — and
|
|
34
|
-
*
|
|
35
|
-
*
|
|
36
|
-
* TypeScript infers the return type from the factory:
|
|
37
|
-
* - sync factory → `AttemptResult<T>`
|
|
38
|
-
* - async factory → `Promise<AttemptResult<T>>`
|
|
33
|
+
* Executes a function — sync or async — and resolves to an `AttemptResult`.
|
|
34
|
+
* Never throws.
|
|
39
35
|
*
|
|
40
36
|
* @example
|
|
41
37
|
* ```ts
|
|
@@ -53,6 +49,5 @@ export declare function isFail<T>(result: AttemptResult<T>): result is {
|
|
|
53
49
|
* const result = await attempt(() => retry(fn, { times: 3 }));
|
|
54
50
|
* ```
|
|
55
51
|
*/
|
|
56
|
-
export declare function attempt<T>(fn: () => Promise<T>): Promise<AttemptResult<T>>;
|
|
57
|
-
export declare function attempt<T>(fn: () => T): AttemptResult<T>;
|
|
52
|
+
export declare function attempt<T>(fn: () => T | Promise<T>): Promise<AttemptResult<T>>;
|
|
58
53
|
//# sourceMappingURL=attempt.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"attempt.d.ts","sourceRoot":"","sources":["../../src/async/attempt.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,aAAa,CAAC,CAAC,IACvB;IAAE,EAAE,EAAE,IAAI,CAAC;IAAC,KAAK,EAAE,CAAC,CAAA;CAAE,GAEtB;IAAE,EAAE,EAAE,KAAK,CAAC;IAAC,KAAK,EAAE,OAAO,CAAA;CAAE,CAAC;AAElC;;;;;;;GAOG;AAEH,wBAAgB,IAAI,CAAC,CAAC,EAAE,MAAM,EAAE,aAAa,CAAC,CAAC,CAAC,GAAG,MAAM,IAAI;IAAE,EAAE,EAAE,IAAI,CAAC;IAAC,KAAK,EAAE,CAAC,CAAA;CAAE,CAElF;AAED;;;;;;;GAOG;AAEH,wBAAgB,MAAM,CAAC,CAAC,EAAE,MAAM,EAAE,aAAa,CAAC,CAAC,CAAC,GAAG,MAAM,IAAI;IAAE,EAAE,EAAE,KAAK,CAAC;IAAC,KAAK,EAAE,OAAO,CAAA;CAAE,CAE3F;AAED
|
|
1
|
+
{"version":3,"file":"attempt.d.ts","sourceRoot":"","sources":["../../src/async/attempt.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,aAAa,CAAC,CAAC,IACvB;IAAE,EAAE,EAAE,IAAI,CAAC;IAAC,KAAK,EAAE,CAAC,CAAA;CAAE,GAEtB;IAAE,EAAE,EAAE,KAAK,CAAC;IAAC,KAAK,EAAE,OAAO,CAAA;CAAE,CAAC;AAElC;;;;;;;GAOG;AAEH,wBAAgB,IAAI,CAAC,CAAC,EAAE,MAAM,EAAE,aAAa,CAAC,CAAC,CAAC,GAAG,MAAM,IAAI;IAAE,EAAE,EAAE,IAAI,CAAC;IAAC,KAAK,EAAE,CAAC,CAAA;CAAE,CAElF;AAED;;;;;;;GAOG;AAEH,wBAAgB,MAAM,CAAC,CAAC,EAAE,MAAM,EAAE,aAAa,CAAC,CAAC,CAAC,GAAG,MAAM,IAAI;IAAE,EAAE,EAAE,KAAK,CAAC;IAAC,KAAK,EAAE,OAAO,CAAA;CAAE,CAE3F;AAED;;;;;;;;;;;;;;;;;;;GAmBG;AACH,wBAAsB,OAAO,CAAC,CAAC,EAAE,EAAE,EAAE,MAAM,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,aAAa,CAAC,CAAC,CAAC,CAAC,CAMpF"}
|
package/dist/async/attempt.js
CHANGED
|
@@ -5,18 +5,11 @@ function e(e) {
|
|
|
5
5
|
function t(e) {
|
|
6
6
|
return e.ok === !1;
|
|
7
7
|
}
|
|
8
|
-
function n(e) {
|
|
8
|
+
async function n(e) {
|
|
9
9
|
try {
|
|
10
|
-
|
|
11
|
-
return typeof t?.then == "function" ? t.then((e) => ({
|
|
12
|
-
ok: !0,
|
|
13
|
-
value: e
|
|
14
|
-
}), (e) => ({
|
|
15
|
-
error: e,
|
|
16
|
-
ok: !1
|
|
17
|
-
})) : {
|
|
10
|
+
return {
|
|
18
11
|
ok: !0,
|
|
19
|
-
value:
|
|
12
|
+
value: await e()
|
|
20
13
|
};
|
|
21
14
|
} catch (e) {
|
|
22
15
|
return {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"attempt.js","names":[],"sources":["../../src/async/attempt.ts"],"sourcesContent":["export type AttemptResult<T> =\n | { ok: true; value: T }\n // eslint-disable-next-line perfectionist/sort-object-types\n | { ok: false; error: unknown };\n\n/**\n * Narrows an `AttemptResult` to the success branch.\n * @example\n * ```ts\n * const result = await attempt(() => fetch('/api').then(r => r.json()));\n * if (isOk(result)) console.log(result.value);\n * ```\n */\n\nexport function isOk<T>(result: AttemptResult<T>): result is { ok: true; value: T } {\n return result.ok === true;\n}\n\n/**\n * Narrows an `AttemptResult` to the failure branch.\n * @example\n * ```ts\n * const result = await attempt(() => fetch('/api').then(r => r.json()));\n * if (isFail(result)) console.error(result.error);\n * ```\n */\n// eslint-disable-next-line perfectionist/sort-object-types\nexport function isFail<T>(result: AttemptResult<T>): result is { ok: false; error: unknown } {\n return result.ok === false;\n}\n\n/**\n * Executes a function — sync or async — and
|
|
1
|
+
{"version":3,"file":"attempt.js","names":[],"sources":["../../src/async/attempt.ts"],"sourcesContent":["export type AttemptResult<T> =\n | { ok: true; value: T }\n // eslint-disable-next-line perfectionist/sort-object-types\n | { ok: false; error: unknown };\n\n/**\n * Narrows an `AttemptResult` to the success branch.\n * @example\n * ```ts\n * const result = await attempt(() => fetch('/api').then(r => r.json()));\n * if (isOk(result)) console.log(result.value);\n * ```\n */\n\nexport function isOk<T>(result: AttemptResult<T>): result is { ok: true; value: T } {\n return result.ok === true;\n}\n\n/**\n * Narrows an `AttemptResult` to the failure branch.\n * @example\n * ```ts\n * const result = await attempt(() => fetch('/api').then(r => r.json()));\n * if (isFail(result)) console.error(result.error);\n * ```\n */\n// eslint-disable-next-line perfectionist/sort-object-types\nexport function isFail<T>(result: AttemptResult<T>): result is { ok: false; error: unknown } {\n return result.ok === false;\n}\n\n/**\n * Executes a function — sync or async — and resolves to an `AttemptResult`.\n * Never throws.\n *\n * @example\n * ```ts\n * // Sync\n * const parsed = attempt(() => JSON.parse(rawJson));\n * if (parsed.ok) console.log(parsed.value);\n * else console.error(parsed.error);\n *\n * // Async\n * const result = await attempt(() => fetch('/api').then(r => r.json()));\n * if (result.ok) console.log(result.value);\n * else console.error(result.error);\n *\n * // Combined with retry()\n * const result = await attempt(() => retry(fn, { times: 3 }));\n * ```\n */\nexport async function attempt<T>(fn: () => T | Promise<T>): Promise<AttemptResult<T>> {\n try {\n return { ok: true, value: await fn() };\n } catch (error) {\n return { error, ok: false };\n }\n}\n"],"mappings":";AAcA,SAAgB,EAAQ,GAA4D;CAClF,OAAO,EAAO,OAAO;AACvB;AAWA,SAAgB,EAAU,GAAmE;CAC3F,OAAO,EAAO,OAAO;AACvB;AAsBA,eAAsB,EAAW,GAAqD;CACpF,IAAI;EACF,OAAO;GAAE,IAAI;GAAM,OAAO,MAAM,EAAG;EAAE;CACvC,SAAS,GAAO;EACd,OAAO;GAAE;GAAO,IAAI;EAAM;CAC5B;AACF"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});const e=require("./abortError.cjs"),t=require("./attempt.cjs"),n=require("./backoff.cjs"),r=require("./parallel.cjs"),i=require("./sleep.cjs"),a=require("./retry.cjs"),o=require("./taskPool.cjs"),s=require("./waitFor.cjs");exports.abortError=e.abortError,exports.attempt=t.attempt,exports.backoff=n.backoff,exports.isFail=t.isFail,exports.isOk=t.isOk,exports.parallel=r.parallel,exports.retry=a.retry,exports.sleep=i.sleep,exports.taskPool=o.taskPool,exports.waitFor=s.waitFor;
|
package/dist/async/index.d.ts
CHANGED
|
@@ -2,8 +2,8 @@ export * from './abortError';
|
|
|
2
2
|
export * from './attempt';
|
|
3
3
|
export * from './backoff';
|
|
4
4
|
export * from './parallel';
|
|
5
|
-
export * from './queue';
|
|
6
5
|
export * from './retry';
|
|
7
6
|
export * from './sleep';
|
|
7
|
+
export * from './taskPool';
|
|
8
8
|
export * from './waitFor';
|
|
9
9
|
//# sourceMappingURL=index.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/async/index.ts"],"names":[],"mappings":"AAAA,cAAc,cAAc,CAAC;AAC7B,cAAc,WAAW,CAAC;AAC1B,cAAc,WAAW,CAAC;AAC1B,cAAc,YAAY,CAAC;AAC3B,cAAc,SAAS,CAAC;AACxB,cAAc,SAAS,CAAC;AACxB,cAAc,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/async/index.ts"],"names":[],"mappings":"AAAA,cAAc,cAAc,CAAC;AAC7B,cAAc,WAAW,CAAC;AAC1B,cAAc,WAAW,CAAC;AAC1B,cAAc,YAAY,CAAC;AAC3B,cAAc,SAAS,CAAC;AACxB,cAAc,SAAS,CAAC;AACxB,cAAc,YAAY,CAAC;AAC3B,cAAc,WAAW,CAAC"}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { abortError as e } from "./abortError.js";
|
|
2
|
+
import { attempt as t, isFail as n, isOk as r } from "./attempt.js";
|
|
3
|
+
import { backoff as i } from "./backoff.js";
|
|
4
|
+
import { parallel as a } from "./parallel.js";
|
|
5
|
+
import { sleep as o } from "./sleep.js";
|
|
6
|
+
import { retry as s } from "./retry.js";
|
|
7
|
+
import { taskPool as c } from "./taskPool.js";
|
|
8
|
+
import { waitFor as l } from "./waitFor.js";
|
|
9
|
+
export { e as abortError, t as attempt, i as backoff, n as isFail, r as isOk, a as parallel, s as retry, o as sleep, c as taskPool, l as waitFor };
|
package/dist/async/parallel.cjs
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
const e=require("
|
|
1
|
+
const e=require("./abortError.cjs");async function t(t,n,r={}){let{abortOnError:i=!1,limit:a=1/0,signal:o}=r;if(a<1)throw RangeError(`parallel: limit must be at least 1, got ${a}`);if(o?.aborted)throw e.abortError(o);if(t.length===0)return[];let s=Array(t.length),c=0,l=i?new AbortController:void 0,u=async()=>{for(;;){if(o?.aborted)throw e.abortError(o);if(l?.signal.aborted||c>=t.length)return;let r=c++;try{s[r]=await n(t[r],r,t)}catch(e){throw l?.abort(),e}}},d=Math.min(a,t.length),f=Array.from({length:d},()=>u());return await Promise.all(f),s}exports.parallel=t;
|
|
2
2
|
//# sourceMappingURL=parallel.cjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"parallel.cjs","names":[],"sources":["../../src/async/parallel.ts"],"sourcesContent":["import {
|
|
1
|
+
{"version":3,"file":"parallel.cjs","names":[],"sources":["../../src/async/parallel.ts"],"sourcesContent":["import { abortError } from './abortError';\n\n/**\n * Processes an array with an async callback with controlled parallelism.\n * Similar to Promise.all, but limits how many items are processed concurrently.\n * Returns an ordered array of results.\n *\n * @example\n * ```ts\n * // Process 3 items at a time\n * const results = await parallel([1, 2, 3, 4, 5], async (n) => {\n * await delay(100);\n * return n * 2;\n * }, { limit: 3 });\n * // [2, 4, 6, 8, 10]\n *\n * // With abort signal\n * const controller = new AbortController();\n * const results = await parallel(items, async (item) => {\n * return processItem(item);\n * }, { limit: 2, signal: controller.signal });\n *\n * // Stop other workers as soon as one item fails\n * await parallel(items, riskyOperation, { abortOnError: true, limit: 3 });\n * ```\n *\n * @param array - Array of items to process\n * @param callback - Async function to process each item\n * @param options - Optional options for concurrency and cancellation\n * @param [options.limit=Infinity] - Maximum number of concurrent operations. Defaults to unbounded.\n * @param [options.signal] - Optional AbortSignal to cancel processing\n * @param [options.abortOnError=false] - When `true`, stops other in-flight workers as soon as any\n * callback throws, instead of letting them keep running to completion unobserved. Default\n * preserves the existing best-effort-completion behavior.\n * @returns Promise resolving to an ordered array of results\n * @throws {RangeError} If limit is less than 1\n * @throws {DOMException} If aborted via signal\n */\nexport async function parallel<T, R>(\n array: readonly T[],\n callback: (item: T, index: number, array: readonly T[]) => Promise<R> | R,\n options: { abortOnError?: boolean; limit?: number; signal?: AbortSignal } = {},\n): Promise<R[]> {\n const { abortOnError = false, limit = Infinity, signal } = options;\n\n if (limit < 1) {\n throw new RangeError(`parallel: limit must be at least 1, got ${limit}`);\n }\n\n if (signal?.aborted) {\n throw abortError(signal);\n }\n\n if (array.length === 0) {\n return [];\n }\n\n const results: R[] = new Array(array.length);\n let currentIndex = 0;\n const failFastController = abortOnError ? new AbortController() : undefined;\n\n const worker = async (): Promise<void> => {\n while (true) {\n if (signal?.aborted) {\n throw abortError(signal);\n }\n\n if (failFastController?.signal.aborted) {\n return;\n }\n\n if (currentIndex >= array.length) {\n return;\n }\n\n const index = currentIndex++;\n\n try {\n results[index] = await callback(array[index]!, index, array);\n } catch (err) {\n failFastController?.abort();\n throw err;\n }\n }\n };\n\n const workerCount = Math.min(limit, array.length);\n const workers = Array.from({ length: workerCount }, () => worker());\n\n await Promise.all(workers);\n\n return results;\n}\n"],"mappings":"oCAsCA,eAAsB,EACpB,EACA,EACA,EAA4E,CAAC,EAC/D,CACd,GAAM,CAAE,eAAe,GAAO,QAAQ,IAAU,UAAW,EAE3D,GAAI,EAAQ,EACV,MAAU,WAAW,2CAA2C,GAAO,EAGzE,GAAI,GAAQ,QACV,MAAM,EAAA,WAAW,CAAM,EAGzB,GAAI,EAAM,SAAW,EACnB,MAAO,CAAC,EAGV,IAAM,EAAmB,MAAM,EAAM,MAAM,EACvC,EAAe,EACb,EAAqB,EAAe,IAAI,gBAAoB,IAAA,GAE5D,EAAS,SAA2B,CACxC,OAAa,CACX,GAAI,GAAQ,QACV,MAAM,EAAA,WAAW,CAAM,EAOzB,GAJI,GAAoB,OAAO,SAI3B,GAAgB,EAAM,OACxB,OAGF,IAAM,EAAQ,IAEd,GAAI,CACF,EAAQ,GAAS,MAAM,EAAS,EAAM,GAAS,EAAO,CAAK,CAC7D,OAAS,EAAK,CAEZ,MADA,GAAoB,MAAM,EACpB,CACR,CACF,CACF,EAEM,EAAc,KAAK,IAAI,EAAO,EAAM,MAAM,EAC1C,EAAU,MAAM,KAAK,CAAE,OAAQ,CAAY,MAAS,EAAO,CAAC,EAIlE,OAFA,MAAM,QAAQ,IAAI,CAAO,EAElB,CACT"}
|
package/dist/async/parallel.d.ts
CHANGED
|
@@ -31,7 +31,7 @@
|
|
|
31
31
|
* callback throws, instead of letting them keep running to completion unobserved. Default
|
|
32
32
|
* preserves the existing best-effort-completion behavior.
|
|
33
33
|
* @returns Promise resolving to an ordered array of results
|
|
34
|
-
* @throws {
|
|
34
|
+
* @throws {RangeError} If limit is less than 1
|
|
35
35
|
* @throws {DOMException} If aborted via signal
|
|
36
36
|
*/
|
|
37
37
|
export declare function parallel<T, R>(array: readonly T[], callback: (item: T, index: number, array: readonly T[]) => Promise<R> | R, options?: {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"parallel.d.ts","sourceRoot":"","sources":["../../src/async/parallel.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"parallel.d.ts","sourceRoot":"","sources":["../../src/async/parallel.ts"],"names":[],"mappings":"AAEA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAmCG;AACH,wBAAsB,QAAQ,CAAC,CAAC,EAAE,CAAC,EACjC,KAAK,EAAE,SAAS,CAAC,EAAE,EACnB,QAAQ,EAAE,CAAC,IAAI,EAAE,CAAC,EAAE,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,SAAS,CAAC,EAAE,KAAK,OAAO,CAAC,CAAC,CAAC,GAAG,CAAC,EACzE,OAAO,GAAE;IAAE,YAAY,CAAC,EAAE,OAAO,CAAC;IAAC,KAAK,CAAC,EAAE,MAAM,CAAC;IAAC,MAAM,CAAC,EAAE,WAAW,CAAA;CAAO,GAC7E,OAAO,CAAC,CAAC,EAAE,CAAC,CAkDd"}
|
package/dist/async/parallel.js
CHANGED
|
@@ -1,26 +1,25 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { abortError as t } from "./abortError.js";
|
|
1
|
+
import { abortError as e } from "./abortError.js";
|
|
3
2
|
//#region src/async/parallel.ts
|
|
4
|
-
async function
|
|
5
|
-
let { abortOnError:
|
|
6
|
-
if (
|
|
7
|
-
if (
|
|
8
|
-
if (
|
|
9
|
-
let
|
|
3
|
+
async function t(t, n, r = {}) {
|
|
4
|
+
let { abortOnError: i = !1, limit: a = Infinity, signal: o } = r;
|
|
5
|
+
if (a < 1) throw RangeError(`parallel: limit must be at least 1, got ${a}`);
|
|
6
|
+
if (o?.aborted) throw e(o);
|
|
7
|
+
if (t.length === 0) return [];
|
|
8
|
+
let s = Array(t.length), c = 0, l = i ? new AbortController() : void 0, u = async () => {
|
|
10
9
|
for (;;) {
|
|
11
|
-
if (
|
|
12
|
-
if (
|
|
13
|
-
let
|
|
10
|
+
if (o?.aborted) throw e(o);
|
|
11
|
+
if (l?.signal.aborted || c >= t.length) return;
|
|
12
|
+
let r = c++;
|
|
14
13
|
try {
|
|
15
|
-
|
|
14
|
+
s[r] = await n(t[r], r, t);
|
|
16
15
|
} catch (e) {
|
|
17
|
-
throw
|
|
16
|
+
throw l?.abort(), e;
|
|
18
17
|
}
|
|
19
18
|
}
|
|
20
|
-
},
|
|
21
|
-
return await Promise.all(
|
|
19
|
+
}, d = Math.min(a, t.length), f = Array.from({ length: d }, () => u());
|
|
20
|
+
return await Promise.all(f), s;
|
|
22
21
|
}
|
|
23
22
|
//#endregion
|
|
24
|
-
export {
|
|
23
|
+
export { t as parallel };
|
|
25
24
|
|
|
26
25
|
//# sourceMappingURL=parallel.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"parallel.js","names":[],"sources":["../../src/async/parallel.ts"],"sourcesContent":["import {
|
|
1
|
+
{"version":3,"file":"parallel.js","names":[],"sources":["../../src/async/parallel.ts"],"sourcesContent":["import { abortError } from './abortError';\n\n/**\n * Processes an array with an async callback with controlled parallelism.\n * Similar to Promise.all, but limits how many items are processed concurrently.\n * Returns an ordered array of results.\n *\n * @example\n * ```ts\n * // Process 3 items at a time\n * const results = await parallel([1, 2, 3, 4, 5], async (n) => {\n * await delay(100);\n * return n * 2;\n * }, { limit: 3 });\n * // [2, 4, 6, 8, 10]\n *\n * // With abort signal\n * const controller = new AbortController();\n * const results = await parallel(items, async (item) => {\n * return processItem(item);\n * }, { limit: 2, signal: controller.signal });\n *\n * // Stop other workers as soon as one item fails\n * await parallel(items, riskyOperation, { abortOnError: true, limit: 3 });\n * ```\n *\n * @param array - Array of items to process\n * @param callback - Async function to process each item\n * @param options - Optional options for concurrency and cancellation\n * @param [options.limit=Infinity] - Maximum number of concurrent operations. Defaults to unbounded.\n * @param [options.signal] - Optional AbortSignal to cancel processing\n * @param [options.abortOnError=false] - When `true`, stops other in-flight workers as soon as any\n * callback throws, instead of letting them keep running to completion unobserved. Default\n * preserves the existing best-effort-completion behavior.\n * @returns Promise resolving to an ordered array of results\n * @throws {RangeError} If limit is less than 1\n * @throws {DOMException} If aborted via signal\n */\nexport async function parallel<T, R>(\n array: readonly T[],\n callback: (item: T, index: number, array: readonly T[]) => Promise<R> | R,\n options: { abortOnError?: boolean; limit?: number; signal?: AbortSignal } = {},\n): Promise<R[]> {\n const { abortOnError = false, limit = Infinity, signal } = options;\n\n if (limit < 1) {\n throw new RangeError(`parallel: limit must be at least 1, got ${limit}`);\n }\n\n if (signal?.aborted) {\n throw abortError(signal);\n }\n\n if (array.length === 0) {\n return [];\n }\n\n const results: R[] = new Array(array.length);\n let currentIndex = 0;\n const failFastController = abortOnError ? new AbortController() : undefined;\n\n const worker = async (): Promise<void> => {\n while (true) {\n if (signal?.aborted) {\n throw abortError(signal);\n }\n\n if (failFastController?.signal.aborted) {\n return;\n }\n\n if (currentIndex >= array.length) {\n return;\n }\n\n const index = currentIndex++;\n\n try {\n results[index] = await callback(array[index]!, index, array);\n } catch (err) {\n failFastController?.abort();\n throw err;\n }\n }\n };\n\n const workerCount = Math.min(limit, array.length);\n const workers = Array.from({ length: workerCount }, () => worker());\n\n await Promise.all(workers);\n\n return results;\n}\n"],"mappings":";;AAsCA,eAAsB,EACpB,GACA,GACA,IAA4E,CAAC,GAC/D;CACd,IAAM,EAAE,kBAAe,IAAO,WAAQ,UAAU,cAAW;CAE3D,IAAI,IAAQ,GACV,MAAU,WAAW,2CAA2C,GAAO;CAGzE,IAAI,GAAQ,SACV,MAAM,EAAW,CAAM;CAGzB,IAAI,EAAM,WAAW,GACnB,OAAO,CAAC;CAGV,IAAM,IAAmB,MAAM,EAAM,MAAM,GACvC,IAAe,GACb,IAAqB,IAAe,IAAI,gBAAgB,IAAI,KAAA,GAE5D,IAAS,YAA2B;EACxC,SAAa;GACX,IAAI,GAAQ,SACV,MAAM,EAAW,CAAM;GAOzB,IAJI,GAAoB,OAAO,WAI3B,KAAgB,EAAM,QACxB;GAGF,IAAM,IAAQ;GAEd,IAAI;IACF,EAAQ,KAAS,MAAM,EAAS,EAAM,IAAS,GAAO,CAAK;GAC7D,SAAS,GAAK;IAEZ,MADA,GAAoB,MAAM,GACpB;GACR;EACF;CACF,GAEM,IAAc,KAAK,IAAI,GAAO,EAAM,MAAM,GAC1C,IAAU,MAAM,KAAK,EAAE,QAAQ,EAAY,SAAS,EAAO,CAAC;CAIlE,OAFA,MAAM,QAAQ,IAAI,CAAO,GAElB;AACT"}
|
package/dist/async/retry.cjs
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
const e=require("
|
|
1
|
+
const e=require("./abortError.cjs"),t=require("./sleep.cjs");function n(e,t){let n=[e===void 0?void 0:AbortSignal.timeout(e),t].filter(e=>e!=null);if(n.length!==0)return n.length===1?n[0]:AbortSignal.any(n)}async function r(r,{delay:i=250,onError:a,shouldRetry:o,signal:s,timeout:c,times:l=3}={}){if(!Number.isInteger(l)||l<1)throw RangeError(`retry: times must be a positive integer, got ${l}`);for(let u=1;u<=l;u++){if(s?.aborted)throw e.abortError(s);let d=n(c,s);try{return await r(d)}catch(e){if(u===l||o&&!o(e,u-1))throw a?.(e),e;let n=typeof i==`function`?i(u-1):i;n>0&&await t.sleep(n,s)}}}exports.retry=r;
|
|
2
2
|
//# sourceMappingURL=retry.cjs.map
|
package/dist/async/retry.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"retry.cjs","names":[],"sources":["../../src/async/retry.ts"],"sourcesContent":["import {
|
|
1
|
+
{"version":3,"file":"retry.cjs","names":[],"sources":["../../src/async/retry.ts"],"sourcesContent":["import { abortError } from './abortError';\nimport { sleep } from './sleep';\n\nexport type RetryOptions = {\n delay?: number | ((attempt: number) => number);\n onError?: (error: unknown) => void;\n shouldRetry?: (error: unknown, attempt: number) => boolean;\n signal?: AbortSignal;\n timeout?: number;\n times?: number;\n};\n\nfunction buildSignal(timeout: number | undefined, signal: AbortSignal | undefined): AbortSignal | undefined {\n const parts = [timeout !== undefined ? AbortSignal.timeout(timeout) : undefined, signal].filter(\n (s): s is AbortSignal => s != null,\n );\n\n if (parts.length === 0) return undefined;\n\n if (parts.length === 1) return parts[0];\n\n return AbortSignal.any(parts);\n}\n\n/**\n * Retries an async function with optional per-attempt timeout, delay strategy, and abort support.\n * The function receives a merged AbortSignal from the per-attempt timeout and any external signal.\n * On total failure, throws the last error (use `attempt()` to get an `AttemptResult` without throwing).\n *\n * @example\n * ```ts\n * // Basic retry\n * const data = await retry(() => fetch('/api').then(r => r.json()), { times: 3 });\n *\n * // With per-attempt timeout and cancellation\n * const data = await retry(\n * async (signal) => fetch('/api', { signal }).then(r => r.json()),\n * { times: 3, timeout: 5000 },\n * );\n *\n * // As AttemptResult (never throws) — combine with attempt()\n * const result = await attempt(() => retry(fn, { times: 3 }));\n * ```\n *\n * @param fn - Async function to retry. Receives a merged AbortSignal when timeout or signal is set.\n * @param options - Retry configuration.\n * @param [options.times=3] - Total attempts including the first.\n * @param [options.delay=250] - Delay between retries in ms, or a function of (attemptIndex).\n * @param [options.timeout] - Per-attempt timeout in milliseconds.\n * @param [options.signal] - External AbortSignal to cancel all retries.\n * @param [options.shouldRetry] - Predicate called after each non-final failure.\n * Receives the error and the number of failures so far (0-indexed: `0` on the first failure,\n * `1` on the second, etc.). Return `false` to abort immediately. **Not called on the final attempt**\n * (use `onError` to observe the final error unconditionally).\n * @param [options.onError] - Called with the last error before rethrowing — both on final attempt exhaustion\n * and when `shouldRetry` returns `false` to abort early.\n * @returns The resolved value.\n * @throws {RangeError} If `times` is not a positive integer.\n * @throws The last error if all attempts fail.\n */\nexport async function retry<T>(\n fn: (signal?: AbortSignal) => Promise<T>,\n { delay = 250, onError, shouldRetry, signal, timeout, times = 3 }: RetryOptions = {},\n): Promise<T> {\n if (!Number.isInteger(times) || times < 1) {\n throw new RangeError(`retry: times must be a positive integer, got ${times}`);\n }\n\n for (let tryCount = 1; tryCount <= times; tryCount++) {\n if (signal?.aborted) throw abortError(signal);\n\n const callSignal = buildSignal(timeout, signal);\n\n try {\n return await fn(callSignal);\n } catch (err) {\n if (tryCount === times) {\n onError?.(err);\n throw err;\n }\n\n if (shouldRetry && !shouldRetry(err, tryCount - 1)) {\n onError?.(err);\n throw err;\n }\n\n const ms = typeof delay === 'function' ? delay(tryCount - 1) : delay;\n\n if (ms > 0) await sleep(ms, signal);\n }\n }\n\n /* unreachable — the loop always returns or throws before exhausting all attempts */\n return undefined as never;\n}\n"],"mappings":"6DAYA,SAAS,EAAY,EAA6B,EAA0D,CAC1G,IAAM,EAAQ,CAAC,IAAY,IAAA,GAA2C,IAAA,GAA/B,YAAY,QAAQ,CAAO,EAAe,CAAM,CAAC,CAAC,OACtF,GAAwB,GAAK,IAChC,EAEI,KAAM,SAAW,EAIrB,OAFI,EAAM,SAAW,EAAU,EAAM,GAE9B,YAAY,IAAI,CAAK,CAC9B,CAsCA,eAAsB,EACpB,EACA,CAAE,QAAQ,IAAK,UAAS,cAAa,SAAQ,UAAS,QAAQ,GAAoB,CAAC,EACvE,CACZ,GAAI,CAAC,OAAO,UAAU,CAAK,GAAK,EAAQ,EACtC,MAAU,WAAW,gDAAgD,GAAO,EAG9E,IAAK,IAAI,EAAW,EAAG,GAAY,EAAO,IAAY,CACpD,GAAI,GAAQ,QAAS,MAAM,EAAA,WAAW,CAAM,EAE5C,IAAM,EAAa,EAAY,EAAS,CAAM,EAE9C,GAAI,CACF,OAAO,MAAM,EAAG,CAAU,CAC5B,OAAS,EAAK,CAMZ,GALI,IAAa,GAKb,GAAe,CAAC,EAAY,EAAK,EAAW,CAAC,EAE/C,MADA,IAAU,CAAG,EACP,EAGR,IAAM,EAAK,OAAO,GAAU,WAAa,EAAM,EAAW,CAAC,EAAI,EAE3D,EAAK,GAAG,MAAM,EAAA,MAAM,EAAI,CAAM,CACpC,CACF,CAIF"}
|
package/dist/async/retry.d.ts
CHANGED
|
@@ -39,7 +39,7 @@ export type RetryOptions = {
|
|
|
39
39
|
* @param [options.onError] - Called with the last error before rethrowing — both on final attempt exhaustion
|
|
40
40
|
* and when `shouldRetry` returns `false` to abort early.
|
|
41
41
|
* @returns The resolved value.
|
|
42
|
-
* @throws {
|
|
42
|
+
* @throws {RangeError} If `times` is not a positive integer.
|
|
43
43
|
* @throws The last error if all attempts fail.
|
|
44
44
|
*/
|
|
45
45
|
export declare function retry<T>(fn: (signal?: AbortSignal) => Promise<T>, { delay, onError, shouldRetry, signal, timeout, times }?: RetryOptions): Promise<T>;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"retry.d.ts","sourceRoot":"","sources":["../../src/async/retry.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"retry.d.ts","sourceRoot":"","sources":["../../src/async/retry.ts"],"names":[],"mappings":"AAGA,MAAM,MAAM,YAAY,GAAG;IACzB,KAAK,CAAC,EAAE,MAAM,GAAG,CAAC,CAAC,OAAO,EAAE,MAAM,KAAK,MAAM,CAAC,CAAC;IAC/C,OAAO,CAAC,EAAE,CAAC,KAAK,EAAE,OAAO,KAAK,IAAI,CAAC;IACnC,WAAW,CAAC,EAAE,CAAC,KAAK,EAAE,OAAO,EAAE,OAAO,EAAE,MAAM,KAAK,OAAO,CAAC;IAC3D,MAAM,CAAC,EAAE,WAAW,CAAC;IACrB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB,CAAC;AAcF;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAmCG;AACH,wBAAsB,KAAK,CAAC,CAAC,EAC3B,EAAE,EAAE,CAAC,MAAM,CAAC,EAAE,WAAW,KAAK,OAAO,CAAC,CAAC,CAAC,EACxC,EAAE,KAAW,EAAE,OAAO,EAAE,WAAW,EAAE,MAAM,EAAE,OAAO,EAAE,KAAS,EAAE,GAAE,YAAiB,GACnF,OAAO,CAAC,CAAC,CAAC,CA+BZ"}
|
package/dist/async/retry.js
CHANGED
|
@@ -1,26 +1,25 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
3
|
-
import { sleep as n } from "./sleep.js";
|
|
1
|
+
import { abortError as e } from "./abortError.js";
|
|
2
|
+
import { sleep as t } from "./sleep.js";
|
|
4
3
|
//#region src/async/retry.ts
|
|
5
|
-
function
|
|
4
|
+
function n(e, t) {
|
|
6
5
|
let n = [e === void 0 ? void 0 : AbortSignal.timeout(e), t].filter((e) => e != null);
|
|
7
6
|
if (n.length !== 0) return n.length === 1 ? n[0] : AbortSignal.any(n);
|
|
8
7
|
}
|
|
9
|
-
async function
|
|
10
|
-
if (!Number.isInteger(
|
|
11
|
-
for (let
|
|
12
|
-
if (
|
|
13
|
-
let d =
|
|
8
|
+
async function r(r, { delay: i = 250, onError: a, shouldRetry: o, signal: s, timeout: c, times: l = 3 } = {}) {
|
|
9
|
+
if (!Number.isInteger(l) || l < 1) throw RangeError(`retry: times must be a positive integer, got ${l}`);
|
|
10
|
+
for (let u = 1; u <= l; u++) {
|
|
11
|
+
if (s?.aborted) throw e(s);
|
|
12
|
+
let d = n(c, s);
|
|
14
13
|
try {
|
|
15
|
-
return await
|
|
16
|
-
} catch (
|
|
17
|
-
if (
|
|
18
|
-
let
|
|
19
|
-
|
|
14
|
+
return await r(d);
|
|
15
|
+
} catch (e) {
|
|
16
|
+
if (u === l || o && !o(e, u - 1)) throw a?.(e), e;
|
|
17
|
+
let n = typeof i == "function" ? i(u - 1) : i;
|
|
18
|
+
n > 0 && await t(n, s);
|
|
20
19
|
}
|
|
21
20
|
}
|
|
22
21
|
}
|
|
23
22
|
//#endregion
|
|
24
|
-
export {
|
|
23
|
+
export { r as retry };
|
|
25
24
|
|
|
26
25
|
//# sourceMappingURL=retry.js.map
|
package/dist/async/retry.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"retry.js","names":[],"sources":["../../src/async/retry.ts"],"sourcesContent":["import {
|
|
1
|
+
{"version":3,"file":"retry.js","names":[],"sources":["../../src/async/retry.ts"],"sourcesContent":["import { abortError } from './abortError';\nimport { sleep } from './sleep';\n\nexport type RetryOptions = {\n delay?: number | ((attempt: number) => number);\n onError?: (error: unknown) => void;\n shouldRetry?: (error: unknown, attempt: number) => boolean;\n signal?: AbortSignal;\n timeout?: number;\n times?: number;\n};\n\nfunction buildSignal(timeout: number | undefined, signal: AbortSignal | undefined): AbortSignal | undefined {\n const parts = [timeout !== undefined ? AbortSignal.timeout(timeout) : undefined, signal].filter(\n (s): s is AbortSignal => s != null,\n );\n\n if (parts.length === 0) return undefined;\n\n if (parts.length === 1) return parts[0];\n\n return AbortSignal.any(parts);\n}\n\n/**\n * Retries an async function with optional per-attempt timeout, delay strategy, and abort support.\n * The function receives a merged AbortSignal from the per-attempt timeout and any external signal.\n * On total failure, throws the last error (use `attempt()` to get an `AttemptResult` without throwing).\n *\n * @example\n * ```ts\n * // Basic retry\n * const data = await retry(() => fetch('/api').then(r => r.json()), { times: 3 });\n *\n * // With per-attempt timeout and cancellation\n * const data = await retry(\n * async (signal) => fetch('/api', { signal }).then(r => r.json()),\n * { times: 3, timeout: 5000 },\n * );\n *\n * // As AttemptResult (never throws) — combine with attempt()\n * const result = await attempt(() => retry(fn, { times: 3 }));\n * ```\n *\n * @param fn - Async function to retry. Receives a merged AbortSignal when timeout or signal is set.\n * @param options - Retry configuration.\n * @param [options.times=3] - Total attempts including the first.\n * @param [options.delay=250] - Delay between retries in ms, or a function of (attemptIndex).\n * @param [options.timeout] - Per-attempt timeout in milliseconds.\n * @param [options.signal] - External AbortSignal to cancel all retries.\n * @param [options.shouldRetry] - Predicate called after each non-final failure.\n * Receives the error and the number of failures so far (0-indexed: `0` on the first failure,\n * `1` on the second, etc.). Return `false` to abort immediately. **Not called on the final attempt**\n * (use `onError` to observe the final error unconditionally).\n * @param [options.onError] - Called with the last error before rethrowing — both on final attempt exhaustion\n * and when `shouldRetry` returns `false` to abort early.\n * @returns The resolved value.\n * @throws {RangeError} If `times` is not a positive integer.\n * @throws The last error if all attempts fail.\n */\nexport async function retry<T>(\n fn: (signal?: AbortSignal) => Promise<T>,\n { delay = 250, onError, shouldRetry, signal, timeout, times = 3 }: RetryOptions = {},\n): Promise<T> {\n if (!Number.isInteger(times) || times < 1) {\n throw new RangeError(`retry: times must be a positive integer, got ${times}`);\n }\n\n for (let tryCount = 1; tryCount <= times; tryCount++) {\n if (signal?.aborted) throw abortError(signal);\n\n const callSignal = buildSignal(timeout, signal);\n\n try {\n return await fn(callSignal);\n } catch (err) {\n if (tryCount === times) {\n onError?.(err);\n throw err;\n }\n\n if (shouldRetry && !shouldRetry(err, tryCount - 1)) {\n onError?.(err);\n throw err;\n }\n\n const ms = typeof delay === 'function' ? delay(tryCount - 1) : delay;\n\n if (ms > 0) await sleep(ms, signal);\n }\n }\n\n /* unreachable — the loop always returns or throws before exhausting all attempts */\n return undefined as never;\n}\n"],"mappings":";;;AAYA,SAAS,EAAY,GAA6B,GAA0D;CAC1G,IAAM,IAAQ,CAAC,MAAY,KAAA,IAA2C,KAAA,IAA/B,YAAY,QAAQ,CAAO,GAAe,CAAM,CAAC,CAAC,QACtF,MAAwB,KAAK,IAChC;CAEI,MAAM,WAAW,GAIrB,OAFI,EAAM,WAAW,IAAU,EAAM,KAE9B,YAAY,IAAI,CAAK;AAC9B;AAsCA,eAAsB,EACpB,GACA,EAAE,WAAQ,KAAK,YAAS,gBAAa,WAAQ,YAAS,WAAQ,MAAoB,CAAC,GACvE;CACZ,IAAI,CAAC,OAAO,UAAU,CAAK,KAAK,IAAQ,GACtC,MAAU,WAAW,gDAAgD,GAAO;CAG9E,KAAK,IAAI,IAAW,GAAG,KAAY,GAAO,KAAY;EACpD,IAAI,GAAQ,SAAS,MAAM,EAAW,CAAM;EAE5C,IAAM,IAAa,EAAY,GAAS,CAAM;EAE9C,IAAI;GACF,OAAO,MAAM,EAAG,CAAU;EAC5B,SAAS,GAAK;GAMZ,IALI,MAAa,KAKb,KAAe,CAAC,EAAY,GAAK,IAAW,CAAC,GAE/C,MADA,IAAU,CAAG,GACP;GAGR,IAAM,IAAK,OAAO,KAAU,aAAa,EAAM,IAAW,CAAC,IAAI;GAE/D,AAAI,IAAK,KAAG,MAAM,EAAM,GAAI,CAAM;EACpC;CACF;AAIF"}
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
function e({concurrency:e=1}={}){if(!Number.isInteger(e)||e<1)throw RangeError(`taskPool: concurrency must be a positive integer`);let t=new AbortController,n=[],r=0,i=!1,a,o=()=>{r===0&&n.length===0&&(a?.resolve(),a=void 0)},s=()=>{for(;r<e&&n.length>0;){let e=n.shift();r++,Promise.resolve().then(()=>e.run(t.signal)).then(e.resolve,e.reject).finally(()=>{r--,s(),o()})}};return{get active(){return r},get disposalSignal(){return t.signal},dispose:(e=new DOMException(`Task pool disposed`,`AbortError`))=>{if(!i){i=!0,t.abort(e);for(let t of n.splice(0))t.reject(e);o()}},get disposed(){return i},idle:()=>r===0&&n.length===0?Promise.resolve():(a??=Promise.withResolvers(),a.promise),get pending(){return n.length},run:e=>{let r=Promise.withResolvers();return i?(r.reject(t.signal.reason),r.promise):(n.push({reject:r.reject,resolve:r.resolve,run:e}),s(),r.promise)},[Symbol.dispose](){this.dispose()}}}exports.taskPool=e;
|
|
2
|
+
//# sourceMappingURL=taskPool.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"taskPool.cjs","names":[],"sources":["../../src/async/taskPool.ts"],"sourcesContent":["export interface TaskPool {\n dispose(reason?: unknown): void;\n idle(): Promise<void>;\n run<T>(task: (signal: AbortSignal) => Promise<T>): Promise<T>;\n readonly active: number;\n readonly disposed: boolean;\n readonly disposalSignal: AbortSignal;\n readonly pending: number;\n [Symbol.dispose](): void;\n}\n\ntype PendingTask = {\n reject: (reason?: unknown) => void;\n resolve: (value: unknown) => void;\n run: (signal: AbortSignal) => Promise<unknown>;\n};\n\nexport function taskPool({ concurrency = 1 }: { concurrency?: number } = {}): TaskPool {\n if (!Number.isInteger(concurrency) || concurrency < 1) {\n throw new RangeError('taskPool: concurrency must be a positive integer');\n }\n\n const controller = new AbortController();\n const pending: PendingTask[] = [];\n let active = 0;\n let disposed = false;\n let idleDeferred: ReturnType<typeof Promise.withResolvers<void>> | undefined;\n\n const resolveIdle = (): void => {\n if (active === 0 && pending.length === 0) {\n idleDeferred?.resolve();\n idleDeferred = undefined;\n }\n };\n\n const start = (): void => {\n while (active < concurrency && pending.length > 0) {\n const next = pending.shift()!;\n\n active++;\n void Promise.resolve()\n .then(() => next.run(controller.signal))\n .then(next.resolve, next.reject)\n .finally(() => {\n active--;\n start();\n resolveIdle();\n });\n }\n };\n\n return {\n get active(): number {\n return active;\n },\n get disposalSignal(): AbortSignal {\n return controller.signal;\n },\n dispose: (reason: unknown = new DOMException('Task pool disposed', 'AbortError')): void => {\n if (disposed) return;\n\n disposed = true;\n controller.abort(reason);\n\n for (const task of pending.splice(0)) task.reject(reason);\n\n resolveIdle();\n },\n get disposed(): boolean {\n return disposed;\n },\n idle: (): Promise<void> => {\n if (active === 0 && pending.length === 0) return Promise.resolve();\n\n idleDeferred ??= Promise.withResolvers<void>();\n\n return idleDeferred.promise;\n },\n get pending(): number {\n return pending.length;\n },\n run: <T>(task: (signal: AbortSignal) => Promise<T>): Promise<T> => {\n const deferred = Promise.withResolvers<T>();\n\n if (disposed) {\n deferred.reject(controller.signal.reason);\n\n return deferred.promise;\n }\n\n pending.push({\n reject: deferred.reject,\n resolve: deferred.resolve as (value: unknown) => void,\n run: task as (signal: AbortSignal) => Promise<unknown>,\n });\n start();\n\n return deferred.promise;\n },\n [Symbol.dispose](): void {\n this.dispose();\n },\n };\n}\n"],"mappings":"AAiBA,SAAgB,EAAS,CAAE,cAAc,GAAgC,CAAC,EAAa,CACrF,GAAI,CAAC,OAAO,UAAU,CAAW,GAAK,EAAc,EAClD,MAAU,WAAW,kDAAkD,EAGzE,IAAM,EAAa,IAAI,gBACjB,EAAyB,CAAC,EAC5B,EAAS,EACT,EAAW,GACX,EAEE,MAA0B,CAC1B,IAAW,GAAK,EAAQ,SAAW,IACrC,GAAc,QAAQ,EACtB,EAAe,IAAA,GAEnB,EAEM,MAAoB,CACxB,KAAO,EAAS,GAAe,EAAQ,OAAS,GAAG,CACjD,IAAM,EAAO,EAAQ,MAAM,EAE3B,IACA,QAAa,QAAQ,CAAC,CACnB,SAAW,EAAK,IAAI,EAAW,MAAM,CAAC,CAAC,CACvC,KAAK,EAAK,QAAS,EAAK,MAAM,CAAC,CAC/B,YAAc,CACb,IACA,EAAM,EACN,EAAY,CACd,CAAC,CACL,CACF,EAEA,MAAO,CACL,IAAI,QAAiB,CACnB,OAAO,CACT,EACA,IAAI,gBAA8B,CAChC,OAAO,EAAW,MACpB,EACA,SAAU,EAAkB,IAAI,aAAa,qBAAsB,YAAY,IAAY,CACrF,MAGJ,CADA,EAAW,GACX,EAAW,MAAM,CAAM,EAEvB,IAAK,IAAM,KAAQ,EAAQ,OAAO,CAAC,EAAG,EAAK,OAAO,CAAM,EAExD,EAAY,CAJW,CAKzB,EACA,IAAI,UAAoB,CACtB,OAAO,CACT,EACA,SACM,IAAW,GAAK,EAAQ,SAAW,EAAU,QAAQ,QAAQ,GAEjE,IAAiB,QAAQ,cAAoB,EAEtC,EAAa,SAEtB,IAAI,SAAkB,CACpB,OAAO,EAAQ,MACjB,EACA,IAAS,GAA0D,CACjE,IAAM,EAAW,QAAQ,cAAiB,EAe1C,OAbI,GACF,EAAS,OAAO,EAAW,OAAO,MAAM,EAEjC,EAAS,UAGlB,EAAQ,KAAK,CACX,OAAQ,EAAS,OACjB,QAAS,EAAS,QAClB,IAAK,CACP,CAAC,EACD,EAAM,EAEC,EAAS,QAClB,EACA,CAAC,OAAO,UAAiB,CACvB,KAAK,QAAQ,CACf,CACF,CACF"}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
export interface TaskPool {
|
|
2
|
+
dispose(reason?: unknown): void;
|
|
3
|
+
idle(): Promise<void>;
|
|
4
|
+
run<T>(task: (signal: AbortSignal) => Promise<T>): Promise<T>;
|
|
5
|
+
readonly active: number;
|
|
6
|
+
readonly disposed: boolean;
|
|
7
|
+
readonly disposalSignal: AbortSignal;
|
|
8
|
+
readonly pending: number;
|
|
9
|
+
[Symbol.dispose](): void;
|
|
10
|
+
}
|
|
11
|
+
export declare function taskPool({ concurrency }?: {
|
|
12
|
+
concurrency?: number;
|
|
13
|
+
}): TaskPool;
|
|
14
|
+
//# sourceMappingURL=taskPool.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"taskPool.d.ts","sourceRoot":"","sources":["../../src/async/taskPool.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,QAAQ;IACvB,OAAO,CAAC,MAAM,CAAC,EAAE,OAAO,GAAG,IAAI,CAAC;IAChC,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;IACtB,GAAG,CAAC,CAAC,EAAE,IAAI,EAAE,CAAC,MAAM,EAAE,WAAW,KAAK,OAAO,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC,CAAC;IAC9D,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,QAAQ,EAAE,OAAO,CAAC;IAC3B,QAAQ,CAAC,cAAc,EAAE,WAAW,CAAC;IACrC,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,CAAC,MAAM,CAAC,OAAO,CAAC,IAAI,IAAI,CAAC;CAC1B;AAQD,wBAAgB,QAAQ,CAAC,EAAE,WAAe,EAAE,GAAE;IAAE,WAAW,CAAC,EAAE,MAAM,CAAA;CAAO,GAAG,QAAQ,CAsFrF"}
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
//#region src/async/taskPool.ts
|
|
2
|
+
function e({ concurrency: e = 1 } = {}) {
|
|
3
|
+
if (!Number.isInteger(e) || e < 1) throw RangeError("taskPool: concurrency must be a positive integer");
|
|
4
|
+
let t = new AbortController(), n = [], r = 0, i = !1, a, o = () => {
|
|
5
|
+
r === 0 && n.length === 0 && (a?.resolve(), a = void 0);
|
|
6
|
+
}, s = () => {
|
|
7
|
+
for (; r < e && n.length > 0;) {
|
|
8
|
+
let e = n.shift();
|
|
9
|
+
r++, Promise.resolve().then(() => e.run(t.signal)).then(e.resolve, e.reject).finally(() => {
|
|
10
|
+
r--, s(), o();
|
|
11
|
+
});
|
|
12
|
+
}
|
|
13
|
+
};
|
|
14
|
+
return {
|
|
15
|
+
get active() {
|
|
16
|
+
return r;
|
|
17
|
+
},
|
|
18
|
+
get disposalSignal() {
|
|
19
|
+
return t.signal;
|
|
20
|
+
},
|
|
21
|
+
dispose: (e = new DOMException("Task pool disposed", "AbortError")) => {
|
|
22
|
+
if (!i) {
|
|
23
|
+
i = !0, t.abort(e);
|
|
24
|
+
for (let t of n.splice(0)) t.reject(e);
|
|
25
|
+
o();
|
|
26
|
+
}
|
|
27
|
+
},
|
|
28
|
+
get disposed() {
|
|
29
|
+
return i;
|
|
30
|
+
},
|
|
31
|
+
idle: () => r === 0 && n.length === 0 ? Promise.resolve() : (a ??= Promise.withResolvers(), a.promise),
|
|
32
|
+
get pending() {
|
|
33
|
+
return n.length;
|
|
34
|
+
},
|
|
35
|
+
run: (e) => {
|
|
36
|
+
let r = Promise.withResolvers();
|
|
37
|
+
return i ? (r.reject(t.signal.reason), r.promise) : (n.push({
|
|
38
|
+
reject: r.reject,
|
|
39
|
+
resolve: r.resolve,
|
|
40
|
+
run: e
|
|
41
|
+
}), s(), r.promise);
|
|
42
|
+
},
|
|
43
|
+
[Symbol.dispose]() {
|
|
44
|
+
this.dispose();
|
|
45
|
+
}
|
|
46
|
+
};
|
|
47
|
+
}
|
|
48
|
+
//#endregion
|
|
49
|
+
export { e as taskPool };
|
|
50
|
+
|
|
51
|
+
//# sourceMappingURL=taskPool.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"taskPool.js","names":[],"sources":["../../src/async/taskPool.ts"],"sourcesContent":["export interface TaskPool {\n dispose(reason?: unknown): void;\n idle(): Promise<void>;\n run<T>(task: (signal: AbortSignal) => Promise<T>): Promise<T>;\n readonly active: number;\n readonly disposed: boolean;\n readonly disposalSignal: AbortSignal;\n readonly pending: number;\n [Symbol.dispose](): void;\n}\n\ntype PendingTask = {\n reject: (reason?: unknown) => void;\n resolve: (value: unknown) => void;\n run: (signal: AbortSignal) => Promise<unknown>;\n};\n\nexport function taskPool({ concurrency = 1 }: { concurrency?: number } = {}): TaskPool {\n if (!Number.isInteger(concurrency) || concurrency < 1) {\n throw new RangeError('taskPool: concurrency must be a positive integer');\n }\n\n const controller = new AbortController();\n const pending: PendingTask[] = [];\n let active = 0;\n let disposed = false;\n let idleDeferred: ReturnType<typeof Promise.withResolvers<void>> | undefined;\n\n const resolveIdle = (): void => {\n if (active === 0 && pending.length === 0) {\n idleDeferred?.resolve();\n idleDeferred = undefined;\n }\n };\n\n const start = (): void => {\n while (active < concurrency && pending.length > 0) {\n const next = pending.shift()!;\n\n active++;\n void Promise.resolve()\n .then(() => next.run(controller.signal))\n .then(next.resolve, next.reject)\n .finally(() => {\n active--;\n start();\n resolveIdle();\n });\n }\n };\n\n return {\n get active(): number {\n return active;\n },\n get disposalSignal(): AbortSignal {\n return controller.signal;\n },\n dispose: (reason: unknown = new DOMException('Task pool disposed', 'AbortError')): void => {\n if (disposed) return;\n\n disposed = true;\n controller.abort(reason);\n\n for (const task of pending.splice(0)) task.reject(reason);\n\n resolveIdle();\n },\n get disposed(): boolean {\n return disposed;\n },\n idle: (): Promise<void> => {\n if (active === 0 && pending.length === 0) return Promise.resolve();\n\n idleDeferred ??= Promise.withResolvers<void>();\n\n return idleDeferred.promise;\n },\n get pending(): number {\n return pending.length;\n },\n run: <T>(task: (signal: AbortSignal) => Promise<T>): Promise<T> => {\n const deferred = Promise.withResolvers<T>();\n\n if (disposed) {\n deferred.reject(controller.signal.reason);\n\n return deferred.promise;\n }\n\n pending.push({\n reject: deferred.reject,\n resolve: deferred.resolve as (value: unknown) => void,\n run: task as (signal: AbortSignal) => Promise<unknown>,\n });\n start();\n\n return deferred.promise;\n },\n [Symbol.dispose](): void {\n this.dispose();\n },\n };\n}\n"],"mappings":";AAiBA,SAAgB,EAAS,EAAE,iBAAc,MAAgC,CAAC,GAAa;CACrF,IAAI,CAAC,OAAO,UAAU,CAAW,KAAK,IAAc,GAClD,MAAU,WAAW,kDAAkD;CAGzE,IAAM,IAAa,IAAI,gBAAgB,GACjC,IAAyB,CAAC,GAC5B,IAAS,GACT,IAAW,IACX,GAEE,UAA0B;EAC9B,AAAI,MAAW,KAAK,EAAQ,WAAW,MACrC,GAAc,QAAQ,GACtB,IAAe,KAAA;CAEnB,GAEM,UAAoB;EACxB,OAAO,IAAS,KAAe,EAAQ,SAAS,IAAG;GACjD,IAAM,IAAO,EAAQ,MAAM;GAG3B,AADA,KACA,QAAa,QAAQ,CAAC,CACnB,WAAW,EAAK,IAAI,EAAW,MAAM,CAAC,CAAC,CACvC,KAAK,EAAK,SAAS,EAAK,MAAM,CAAC,CAC/B,cAAc;IAGb,AAFA,KACA,EAAM,GACN,EAAY;GACd,CAAC;EACL;CACF;CAEA,OAAO;EACL,IAAI,SAAiB;GACnB,OAAO;EACT;EACA,IAAI,iBAA8B;GAChC,OAAO,EAAW;EACpB;EACA,UAAU,IAAkB,IAAI,aAAa,sBAAsB,YAAY,MAAY;GACrF,QAGJ;IADA,IAAW,IACX,EAAW,MAAM,CAAM;IAEvB,KAAK,IAAM,KAAQ,EAAQ,OAAO,CAAC,GAAG,EAAK,OAAO,CAAM;IAExD,EAAY;GAJW;EAKzB;EACA,IAAI,WAAoB;GACtB,OAAO;EACT;EACA,YACM,MAAW,KAAK,EAAQ,WAAW,IAAU,QAAQ,QAAQ,KAEjE,MAAiB,QAAQ,cAAoB,GAEtC,EAAa;EAEtB,IAAI,UAAkB;GACpB,OAAO,EAAQ;EACjB;EACA,MAAS,MAA0D;GACjE,IAAM,IAAW,QAAQ,cAAiB;GAe1C,OAbI,KACF,EAAS,OAAO,EAAW,OAAO,MAAM,GAEjC,EAAS,YAGlB,EAAQ,KAAK;IACX,QAAQ,EAAS;IACjB,SAAS,EAAS;IAClB,KAAK;GACP,CAAC,GACD,EAAM,GAEC,EAAS;EAClB;EACA,CAAC,OAAO,WAAiB;GACvB,KAAK,QAAQ;EACf;CACF;AACF"}
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
function e({capacity:e=1/0,now:t=Date.now,ttlMs:n}={}){if(e!==1/0&&(!Number.isInteger(e)||e<1))throw RangeError(`cache: capacity must be a positive integer or Infinity, got ${e}`);let r=new Map,i=new Map,a=new Map,o=0,s=e=>{let t=(a.get(e)??0)+1;return a.set(e,t),t},c=e=>{if(e!==void 0&&e!==1/0){if(!Number.isFinite(e)||e<0)throw RangeError(`cache: ttlMs must be a non-negative finite number or Infinity, got ${e}`);return t()+e}},l=e=>{let n=r.get(e);if(n){if(n.expiresAt!==void 0&&n.expiresAt<=t()){r.delete(e);return}return n.value}},u=()=>{for(let[e,n]of r)n.expiresAt!==void 0&&n.expiresAt<=t()&&r.delete(e);for(;r.size>e;){let e=r.keys().next().value;if(e===void 0)return;r.delete(e)}},d=(e,t,i={})=>{s(e),r.delete(e),r.set(e,{expiresAt:c(i.ttlMs??n),value:t}),u()};return{clear:()=>{o++,r.clear(),i.clear(),a.clear()},delete:e=>(i.delete(e),s(e),r.delete(e)),get:l,getOrLoad:(e,t)=>{let n=l(e);if(n!==void 0||r.has(e))return Promise.resolve(n);let c=i.get(e);if(c)return c;let u=o,f=s(e),p=t().then(t=>(i.get(e)===p&&i.delete(e),o===u&&a.get(e)===f&&d(e,t),t),t=>{throw i.get(e)===p&&i.delete(e),t});return i.set(e,p),p},set:d,get size(){return u(),r.size}}}exports.cache=e;
|
|
2
|
+
//# sourceMappingURL=cache.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cache.cjs","names":[],"sources":["../../src/cache/cache.ts"],"sourcesContent":["export type CacheOptions = {\n capacity?: number;\n now?: () => number;\n ttlMs?: number;\n};\n\ntype Entry<T> = {\n expiresAt: number | undefined;\n value: T;\n};\n\nexport interface Cache<K, T> {\n clear(): void;\n delete(key: K): boolean;\n get(key: K): T | undefined;\n getOrLoad(key: K, load: () => Promise<T>): Promise<T>;\n set(key: K, value: T, options?: { ttlMs?: number }): void;\n readonly size: number;\n}\n\nexport function cache<K, T>({ capacity = Infinity, now = Date.now, ttlMs }: CacheOptions = {}): Cache<K, T> {\n if (capacity !== Infinity && (!Number.isInteger(capacity) || capacity < 1)) {\n throw new RangeError(`cache: capacity must be a positive integer or Infinity, got ${capacity}`);\n }\n\n const entries = new Map<K, Entry<T>>();\n const pending = new Map<K, Promise<T>>();\n const revisions = new Map<K, number>();\n let generation = 0;\n\n const advanceRevision = (key: K): number => {\n const revision = (revisions.get(key) ?? 0) + 1;\n\n revisions.set(key, revision);\n\n return revision;\n };\n\n const expiresAt = (duration: number | undefined): number | undefined => {\n if (duration === undefined || duration === Infinity) return undefined;\n\n if (!Number.isFinite(duration) || duration < 0) {\n throw new RangeError(`cache: ttlMs must be a non-negative finite number or Infinity, got ${duration}`);\n }\n\n return now() + duration;\n };\n\n const read = (key: K): T | undefined => {\n const entry = entries.get(key);\n\n if (!entry) return undefined;\n\n if (entry.expiresAt !== undefined && entry.expiresAt <= now()) {\n entries.delete(key);\n\n return undefined;\n }\n\n return entry.value;\n };\n\n const trim = (): void => {\n for (const [key, entry] of entries) {\n if (entry.expiresAt !== undefined && entry.expiresAt <= now()) entries.delete(key);\n }\n\n while (entries.size > capacity) {\n const oldest = entries.keys().next().value;\n\n if (oldest === undefined) return;\n\n entries.delete(oldest);\n }\n };\n\n const set = (key: K, value: T, options: { ttlMs?: number } = {}): void => {\n advanceRevision(key);\n entries.delete(key);\n entries.set(key, { expiresAt: expiresAt(options.ttlMs ?? ttlMs), value });\n trim();\n };\n\n const getOrLoad = (key: K, load: () => Promise<T>): Promise<T> => {\n const cached = read(key);\n\n if (cached !== undefined || entries.has(key)) return Promise.resolve(cached as T);\n\n const existing = pending.get(key);\n\n if (existing) return existing;\n\n const capturedGeneration = generation;\n const capturedRevision = advanceRevision(key);\n const result = load().then(\n (value) => {\n if (pending.get(key) === result) pending.delete(key);\n\n if (generation === capturedGeneration && revisions.get(key) === capturedRevision) {\n set(key, value);\n }\n\n return value;\n },\n (error: unknown) => {\n if (pending.get(key) === result) pending.delete(key);\n\n throw error;\n },\n );\n\n pending.set(key, result);\n\n return result;\n };\n\n return {\n clear: () => {\n generation++;\n entries.clear();\n pending.clear();\n revisions.clear();\n },\n delete: (key) => {\n pending.delete(key);\n advanceRevision(key);\n\n return entries.delete(key);\n },\n get: read,\n getOrLoad,\n set,\n get size() {\n trim();\n\n return entries.size;\n },\n };\n}\n"],"mappings":"AAoBA,SAAgB,EAAY,CAAE,WAAW,IAAU,MAAM,KAAK,IAAK,SAAwB,CAAC,EAAgB,CAC1G,GAAI,IAAa,MAAa,CAAC,OAAO,UAAU,CAAQ,GAAK,EAAW,GACtE,MAAU,WAAW,+DAA+D,GAAU,EAGhG,IAAM,EAAU,IAAI,IACd,EAAU,IAAI,IACd,EAAY,IAAI,IAClB,EAAa,EAEX,EAAmB,GAAmB,CAC1C,IAAM,GAAY,EAAU,IAAI,CAAG,GAAK,GAAK,EAI7C,OAFA,EAAU,IAAI,EAAK,CAAQ,EAEpB,CACT,EAEM,EAAa,GAAqD,CAClE,OAAa,IAAA,IAAa,IAAa,IAE3C,IAAI,CAAC,OAAO,SAAS,CAAQ,GAAK,EAAW,EAC3C,MAAU,WAAW,sEAAsE,GAAU,EAGvG,OAAO,EAAI,EAAI,CAHwF,CAIzG,EAEM,EAAQ,GAA0B,CACtC,IAAM,EAAQ,EAAQ,IAAI,CAAG,EAExB,KAEL,IAAI,EAAM,YAAc,IAAA,IAAa,EAAM,WAAa,EAAI,EAAG,CAC7D,EAAQ,OAAO,CAAG,EAElB,MACF,CAEA,OAAO,EAAM,KAFb,CAGF,EAEM,MAAmB,CACvB,IAAK,GAAM,CAAC,EAAK,KAAU,EACrB,EAAM,YAAc,IAAA,IAAa,EAAM,WAAa,EAAI,GAAG,EAAQ,OAAO,CAAG,EAGnF,KAAO,EAAQ,KAAO,GAAU,CAC9B,IAAM,EAAS,EAAQ,KAAK,CAAC,CAAC,KAAK,CAAC,CAAC,MAErC,GAAI,IAAW,IAAA,GAAW,OAE1B,EAAQ,OAAO,CAAM,CACvB,CACF,EAEM,GAAO,EAAQ,EAAU,EAA8B,CAAC,IAAY,CACxE,EAAgB,CAAG,EACnB,EAAQ,OAAO,CAAG,EAClB,EAAQ,IAAI,EAAK,CAAE,UAAW,EAAU,EAAQ,OAAS,CAAK,EAAG,OAAM,CAAC,EACxE,EAAK,CACP,EAmCA,MAAO,CACL,UAAa,CACX,IACA,EAAQ,MAAM,EACd,EAAQ,MAAM,EACd,EAAU,MAAM,CAClB,EACA,OAAS,IACP,EAAQ,OAAO,CAAG,EAClB,EAAgB,CAAG,EAEZ,EAAQ,OAAO,CAAG,GAE3B,IAAK,EACL,WA/CiB,EAAQ,IAAuC,CAChE,IAAM,EAAS,EAAK,CAAG,EAEvB,GAAI,IAAW,IAAA,IAAa,EAAQ,IAAI,CAAG,EAAG,OAAO,QAAQ,QAAQ,CAAW,EAEhF,IAAM,EAAW,EAAQ,IAAI,CAAG,EAEhC,GAAI,EAAU,OAAO,EAErB,IAAM,EAAqB,EACrB,EAAmB,EAAgB,CAAG,EACtC,EAAS,EAAK,CAAC,CAAC,KACnB,IACK,EAAQ,IAAI,CAAG,IAAM,GAAQ,EAAQ,OAAO,CAAG,EAE/C,IAAe,GAAsB,EAAU,IAAI,CAAG,IAAM,GAC9D,EAAI,EAAK,CAAK,EAGT,GAER,GAAmB,CAGlB,MAFI,EAAQ,IAAI,CAAG,IAAM,GAAQ,EAAQ,OAAO,CAAG,EAE7C,CACR,CACF,EAIA,OAFA,EAAQ,IAAI,EAAK,CAAM,EAEhB,CACT,EAiBE,MACA,IAAI,MAAO,CAGT,OAFA,EAAK,EAEE,EAAQ,IACjB,CACF,CACF"}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
export type CacheOptions = {
|
|
2
|
+
capacity?: number;
|
|
3
|
+
now?: () => number;
|
|
4
|
+
ttlMs?: number;
|
|
5
|
+
};
|
|
6
|
+
export interface Cache<K, T> {
|
|
7
|
+
clear(): void;
|
|
8
|
+
delete(key: K): boolean;
|
|
9
|
+
get(key: K): T | undefined;
|
|
10
|
+
getOrLoad(key: K, load: () => Promise<T>): Promise<T>;
|
|
11
|
+
set(key: K, value: T, options?: {
|
|
12
|
+
ttlMs?: number;
|
|
13
|
+
}): void;
|
|
14
|
+
readonly size: number;
|
|
15
|
+
}
|
|
16
|
+
export declare function cache<K, T>({ capacity, now, ttlMs }?: CacheOptions): Cache<K, T>;
|
|
17
|
+
//# sourceMappingURL=cache.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cache.d.ts","sourceRoot":"","sources":["../../src/cache/cache.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,YAAY,GAAG;IACzB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,GAAG,CAAC,EAAE,MAAM,MAAM,CAAC;IACnB,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB,CAAC;AAOF,MAAM,WAAW,KAAK,CAAC,CAAC,EAAE,CAAC;IACzB,KAAK,IAAI,IAAI,CAAC;IACd,MAAM,CAAC,GAAG,EAAE,CAAC,GAAG,OAAO,CAAC;IACxB,GAAG,CAAC,GAAG,EAAE,CAAC,GAAG,CAAC,GAAG,SAAS,CAAC;IAC3B,SAAS,CAAC,GAAG,EAAE,CAAC,EAAE,IAAI,EAAE,MAAM,OAAO,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC,CAAC;IACtD,GAAG,CAAC,GAAG,EAAE,CAAC,EAAE,KAAK,EAAE,CAAC,EAAE,OAAO,CAAC,EAAE;QAAE,KAAK,CAAC,EAAE,MAAM,CAAA;KAAE,GAAG,IAAI,CAAC;IAC1D,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;CACvB;AAED,wBAAgB,KAAK,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,QAAmB,EAAE,GAAc,EAAE,KAAK,EAAE,GAAE,YAAiB,GAAG,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAsH1G"}
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
//#region src/cache/cache.ts
|
|
2
|
+
function e({ capacity: e = Infinity, now: t = Date.now, ttlMs: n } = {}) {
|
|
3
|
+
if (e !== Infinity && (!Number.isInteger(e) || e < 1)) throw RangeError(`cache: capacity must be a positive integer or Infinity, got ${e}`);
|
|
4
|
+
let r = /* @__PURE__ */ new Map(), i = /* @__PURE__ */ new Map(), a = /* @__PURE__ */ new Map(), o = 0, s = (e) => {
|
|
5
|
+
let t = (a.get(e) ?? 0) + 1;
|
|
6
|
+
return a.set(e, t), t;
|
|
7
|
+
}, c = (e) => {
|
|
8
|
+
if (e !== void 0 && e !== Infinity) {
|
|
9
|
+
if (!Number.isFinite(e) || e < 0) throw RangeError(`cache: ttlMs must be a non-negative finite number or Infinity, got ${e}`);
|
|
10
|
+
return t() + e;
|
|
11
|
+
}
|
|
12
|
+
}, l = (e) => {
|
|
13
|
+
let n = r.get(e);
|
|
14
|
+
if (n) {
|
|
15
|
+
if (n.expiresAt !== void 0 && n.expiresAt <= t()) {
|
|
16
|
+
r.delete(e);
|
|
17
|
+
return;
|
|
18
|
+
}
|
|
19
|
+
return n.value;
|
|
20
|
+
}
|
|
21
|
+
}, u = () => {
|
|
22
|
+
for (let [e, n] of r) n.expiresAt !== void 0 && n.expiresAt <= t() && r.delete(e);
|
|
23
|
+
for (; r.size > e;) {
|
|
24
|
+
let e = r.keys().next().value;
|
|
25
|
+
if (e === void 0) return;
|
|
26
|
+
r.delete(e);
|
|
27
|
+
}
|
|
28
|
+
}, d = (e, t, i = {}) => {
|
|
29
|
+
s(e), r.delete(e), r.set(e, {
|
|
30
|
+
expiresAt: c(i.ttlMs ?? n),
|
|
31
|
+
value: t
|
|
32
|
+
}), u();
|
|
33
|
+
};
|
|
34
|
+
return {
|
|
35
|
+
clear: () => {
|
|
36
|
+
o++, r.clear(), i.clear(), a.clear();
|
|
37
|
+
},
|
|
38
|
+
delete: (e) => (i.delete(e), s(e), r.delete(e)),
|
|
39
|
+
get: l,
|
|
40
|
+
getOrLoad: (e, t) => {
|
|
41
|
+
let n = l(e);
|
|
42
|
+
if (n !== void 0 || r.has(e)) return Promise.resolve(n);
|
|
43
|
+
let c = i.get(e);
|
|
44
|
+
if (c) return c;
|
|
45
|
+
let u = o, f = s(e), p = t().then((t) => (i.get(e) === p && i.delete(e), o === u && a.get(e) === f && d(e, t), t), (t) => {
|
|
46
|
+
throw i.get(e) === p && i.delete(e), t;
|
|
47
|
+
});
|
|
48
|
+
return i.set(e, p), p;
|
|
49
|
+
},
|
|
50
|
+
set: d,
|
|
51
|
+
get size() {
|
|
52
|
+
return u(), r.size;
|
|
53
|
+
}
|
|
54
|
+
};
|
|
55
|
+
}
|
|
56
|
+
//#endregion
|
|
57
|
+
export { e as cache };
|
|
58
|
+
|
|
59
|
+
//# sourceMappingURL=cache.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cache.js","names":[],"sources":["../../src/cache/cache.ts"],"sourcesContent":["export type CacheOptions = {\n capacity?: number;\n now?: () => number;\n ttlMs?: number;\n};\n\ntype Entry<T> = {\n expiresAt: number | undefined;\n value: T;\n};\n\nexport interface Cache<K, T> {\n clear(): void;\n delete(key: K): boolean;\n get(key: K): T | undefined;\n getOrLoad(key: K, load: () => Promise<T>): Promise<T>;\n set(key: K, value: T, options?: { ttlMs?: number }): void;\n readonly size: number;\n}\n\nexport function cache<K, T>({ capacity = Infinity, now = Date.now, ttlMs }: CacheOptions = {}): Cache<K, T> {\n if (capacity !== Infinity && (!Number.isInteger(capacity) || capacity < 1)) {\n throw new RangeError(`cache: capacity must be a positive integer or Infinity, got ${capacity}`);\n }\n\n const entries = new Map<K, Entry<T>>();\n const pending = new Map<K, Promise<T>>();\n const revisions = new Map<K, number>();\n let generation = 0;\n\n const advanceRevision = (key: K): number => {\n const revision = (revisions.get(key) ?? 0) + 1;\n\n revisions.set(key, revision);\n\n return revision;\n };\n\n const expiresAt = (duration: number | undefined): number | undefined => {\n if (duration === undefined || duration === Infinity) return undefined;\n\n if (!Number.isFinite(duration) || duration < 0) {\n throw new RangeError(`cache: ttlMs must be a non-negative finite number or Infinity, got ${duration}`);\n }\n\n return now() + duration;\n };\n\n const read = (key: K): T | undefined => {\n const entry = entries.get(key);\n\n if (!entry) return undefined;\n\n if (entry.expiresAt !== undefined && entry.expiresAt <= now()) {\n entries.delete(key);\n\n return undefined;\n }\n\n return entry.value;\n };\n\n const trim = (): void => {\n for (const [key, entry] of entries) {\n if (entry.expiresAt !== undefined && entry.expiresAt <= now()) entries.delete(key);\n }\n\n while (entries.size > capacity) {\n const oldest = entries.keys().next().value;\n\n if (oldest === undefined) return;\n\n entries.delete(oldest);\n }\n };\n\n const set = (key: K, value: T, options: { ttlMs?: number } = {}): void => {\n advanceRevision(key);\n entries.delete(key);\n entries.set(key, { expiresAt: expiresAt(options.ttlMs ?? ttlMs), value });\n trim();\n };\n\n const getOrLoad = (key: K, load: () => Promise<T>): Promise<T> => {\n const cached = read(key);\n\n if (cached !== undefined || entries.has(key)) return Promise.resolve(cached as T);\n\n const existing = pending.get(key);\n\n if (existing) return existing;\n\n const capturedGeneration = generation;\n const capturedRevision = advanceRevision(key);\n const result = load().then(\n (value) => {\n if (pending.get(key) === result) pending.delete(key);\n\n if (generation === capturedGeneration && revisions.get(key) === capturedRevision) {\n set(key, value);\n }\n\n return value;\n },\n (error: unknown) => {\n if (pending.get(key) === result) pending.delete(key);\n\n throw error;\n },\n );\n\n pending.set(key, result);\n\n return result;\n };\n\n return {\n clear: () => {\n generation++;\n entries.clear();\n pending.clear();\n revisions.clear();\n },\n delete: (key) => {\n pending.delete(key);\n advanceRevision(key);\n\n return entries.delete(key);\n },\n get: read,\n getOrLoad,\n set,\n get size() {\n trim();\n\n return entries.size;\n },\n };\n}\n"],"mappings":";AAoBA,SAAgB,EAAY,EAAE,cAAW,UAAU,SAAM,KAAK,KAAK,aAAwB,CAAC,GAAgB;CAC1G,IAAI,MAAa,aAAa,CAAC,OAAO,UAAU,CAAQ,KAAK,IAAW,IACtE,MAAU,WAAW,+DAA+D,GAAU;CAGhG,IAAM,oBAAU,IAAI,IAAiB,GAC/B,oBAAU,IAAI,IAAmB,GACjC,oBAAY,IAAI,IAAe,GACjC,IAAa,GAEX,KAAmB,MAAmB;EAC1C,IAAM,KAAY,EAAU,IAAI,CAAG,KAAK,KAAK;EAI7C,OAFA,EAAU,IAAI,GAAK,CAAQ,GAEpB;CACT,GAEM,KAAa,MAAqD;EAClE,UAAa,KAAA,KAAa,MAAa,UAE3C;OAAI,CAAC,OAAO,SAAS,CAAQ,KAAK,IAAW,GAC3C,MAAU,WAAW,sEAAsE,GAAU;GAGvG,OAAO,EAAI,IAAI;EAHwF;CAIzG,GAEM,KAAQ,MAA0B;EACtC,IAAM,IAAQ,EAAQ,IAAI,CAAG;EAExB,OAEL;OAAI,EAAM,cAAc,KAAA,KAAa,EAAM,aAAa,EAAI,GAAG;IAC7D,EAAQ,OAAO,CAAG;IAElB;GACF;GAEA,OAAO,EAAM;EAFb;CAGF,GAEM,UAAmB;EACvB,KAAK,IAAM,CAAC,GAAK,MAAU,GACzB,AAAI,EAAM,cAAc,KAAA,KAAa,EAAM,aAAa,EAAI,KAAG,EAAQ,OAAO,CAAG;EAGnF,OAAO,EAAQ,OAAO,IAAU;GAC9B,IAAM,IAAS,EAAQ,KAAK,CAAC,CAAC,KAAK,CAAC,CAAC;GAErC,IAAI,MAAW,KAAA,GAAW;GAE1B,EAAQ,OAAO,CAAM;EACvB;CACF,GAEM,KAAO,GAAQ,GAAU,IAA8B,CAAC,MAAY;EAIxE,AAHA,EAAgB,CAAG,GACnB,EAAQ,OAAO,CAAG,GAClB,EAAQ,IAAI,GAAK;GAAE,WAAW,EAAU,EAAQ,SAAS,CAAK;GAAG;EAAM,CAAC,GACxE,EAAK;CACP;CAmCA,OAAO;EACL,aAAa;GAIX,AAHA,KACA,EAAQ,MAAM,GACd,EAAQ,MAAM,GACd,EAAU,MAAM;EAClB;EACA,SAAS,OACP,EAAQ,OAAO,CAAG,GAClB,EAAgB,CAAG,GAEZ,EAAQ,OAAO,CAAG;EAE3B,KAAK;EACL,YA/CiB,GAAQ,MAAuC;GAChE,IAAM,IAAS,EAAK,CAAG;GAEvB,IAAI,MAAW,KAAA,KAAa,EAAQ,IAAI,CAAG,GAAG,OAAO,QAAQ,QAAQ,CAAW;GAEhF,IAAM,IAAW,EAAQ,IAAI,CAAG;GAEhC,IAAI,GAAU,OAAO;GAErB,IAAM,IAAqB,GACrB,IAAmB,EAAgB,CAAG,GACtC,IAAS,EAAK,CAAC,CAAC,MACnB,OACK,EAAQ,IAAI,CAAG,MAAM,KAAQ,EAAQ,OAAO,CAAG,GAE/C,MAAe,KAAsB,EAAU,IAAI,CAAG,MAAM,KAC9D,EAAI,GAAK,CAAK,GAGT,KAER,MAAmB;IAGlB,MAFI,EAAQ,IAAI,CAAG,MAAM,KAAQ,EAAQ,OAAO,CAAG,GAE7C;GACR,CACF;GAIA,OAFA,EAAQ,IAAI,GAAK,CAAM,GAEhB;EACT;EAiBE;EACA,IAAI,OAAO;GAGT,OAFA,EAAK,GAEE,EAAQ;EACjB;CACF;AACF"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});const e=require("./cache.cjs"),t=require("./memo.cjs");exports.cache=e.cache,exports.memo=t.memo;
|
package/dist/cache/index.d.ts
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/cache/index.ts"],"names":[],"mappings":"AAAA,cAAc,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/cache/index.ts"],"names":[],"mappings":"AAAA,cAAc,SAAS,CAAC;AACxB,cAAc,QAAQ,CAAC"}
|