flowx-control 1.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 +443 -0
- package/dist/batch.d.mts +37 -0
- package/dist/batch.d.ts +37 -0
- package/dist/batch.js +75 -0
- package/dist/batch.js.map +1 -0
- package/dist/batch.mjs +73 -0
- package/dist/batch.mjs.map +1 -0
- package/dist/bulkhead.d.mts +30 -0
- package/dist/bulkhead.d.ts +30 -0
- package/dist/bulkhead.js +85 -0
- package/dist/bulkhead.js.map +1 -0
- package/dist/bulkhead.mjs +83 -0
- package/dist/bulkhead.mjs.map +1 -0
- package/dist/circuit-breaker.d.mts +44 -0
- package/dist/circuit-breaker.d.ts +44 -0
- package/dist/circuit-breaker.js +132 -0
- package/dist/circuit-breaker.js.map +1 -0
- package/dist/circuit-breaker.mjs +130 -0
- package/dist/circuit-breaker.mjs.map +1 -0
- package/dist/debounce.d.mts +30 -0
- package/dist/debounce.d.ts +30 -0
- package/dist/debounce.js +96 -0
- package/dist/debounce.js.map +1 -0
- package/dist/debounce.mjs +94 -0
- package/dist/debounce.mjs.map +1 -0
- package/dist/deferred.d.mts +27 -0
- package/dist/deferred.d.ts +27 -0
- package/dist/deferred.js +42 -0
- package/dist/deferred.js.map +1 -0
- package/dist/deferred.mjs +40 -0
- package/dist/deferred.mjs.map +1 -0
- package/dist/fallback.d.mts +33 -0
- package/dist/fallback.d.ts +33 -0
- package/dist/fallback.js +43 -0
- package/dist/fallback.js.map +1 -0
- package/dist/fallback.mjs +40 -0
- package/dist/fallback.mjs.map +1 -0
- package/dist/hedge.d.mts +18 -0
- package/dist/hedge.d.ts +18 -0
- package/dist/hedge.js +47 -0
- package/dist/hedge.js.map +1 -0
- package/dist/hedge.mjs +45 -0
- package/dist/hedge.mjs.map +1 -0
- package/dist/index.d.mts +18 -0
- package/dist/index.d.ts +18 -0
- package/dist/index.js +1151 -0
- package/dist/index.js.map +1 -0
- package/dist/index.mjs +1122 -0
- package/dist/index.mjs.map +1 -0
- package/dist/memo.d.mts +35 -0
- package/dist/memo.d.ts +35 -0
- package/dist/memo.js +74 -0
- package/dist/memo.js.map +1 -0
- package/dist/memo.mjs +72 -0
- package/dist/memo.mjs.map +1 -0
- package/dist/mutex.d.mts +24 -0
- package/dist/mutex.d.ts +24 -0
- package/dist/mutex.js +46 -0
- package/dist/mutex.js.map +1 -0
- package/dist/mutex.mjs +44 -0
- package/dist/mutex.mjs.map +1 -0
- package/dist/pipeline.d.mts +42 -0
- package/dist/pipeline.d.ts +42 -0
- package/dist/pipeline.js +30 -0
- package/dist/pipeline.js.map +1 -0
- package/dist/pipeline.mjs +27 -0
- package/dist/pipeline.mjs.map +1 -0
- package/dist/poll.d.mts +35 -0
- package/dist/poll.d.ts +35 -0
- package/dist/poll.js +111 -0
- package/dist/poll.js.map +1 -0
- package/dist/poll.mjs +109 -0
- package/dist/poll.mjs.map +1 -0
- package/dist/queue.d.mts +47 -0
- package/dist/queue.d.ts +47 -0
- package/dist/queue.js +121 -0
- package/dist/queue.js.map +1 -0
- package/dist/queue.mjs +119 -0
- package/dist/queue.mjs.map +1 -0
- package/dist/rate-limit.d.mts +28 -0
- package/dist/rate-limit.d.ts +28 -0
- package/dist/rate-limit.js +94 -0
- package/dist/rate-limit.js.map +1 -0
- package/dist/rate-limit.mjs +92 -0
- package/dist/rate-limit.mjs.map +1 -0
- package/dist/retry.d.mts +45 -0
- package/dist/retry.d.ts +45 -0
- package/dist/retry.js +111 -0
- package/dist/retry.js.map +1 -0
- package/dist/retry.mjs +108 -0
- package/dist/retry.mjs.map +1 -0
- package/dist/semaphore.d.mts +27 -0
- package/dist/semaphore.d.ts +27 -0
- package/dist/semaphore.js +47 -0
- package/dist/semaphore.js.map +1 -0
- package/dist/semaphore.mjs +45 -0
- package/dist/semaphore.mjs.map +1 -0
- package/dist/throttle.d.mts +25 -0
- package/dist/throttle.d.ts +25 -0
- package/dist/throttle.js +97 -0
- package/dist/throttle.js.map +1 -0
- package/dist/throttle.mjs +95 -0
- package/dist/throttle.mjs.map +1 -0
- package/dist/timeout.d.mts +19 -0
- package/dist/timeout.d.ts +19 -0
- package/dist/timeout.js +79 -0
- package/dist/timeout.js.map +1 -0
- package/dist/timeout.mjs +77 -0
- package/dist/timeout.mjs.map +1 -0
- package/dist/types-BsCO2J40.d.mts +35 -0
- package/dist/types-BsCO2J40.d.ts +35 -0
- package/package.json +167 -0
package/dist/fallback.js
ADDED
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
// src/fallback.ts
|
|
4
|
+
async function withFallback(fn, fallback, options) {
|
|
5
|
+
try {
|
|
6
|
+
return await fn();
|
|
7
|
+
} catch (error) {
|
|
8
|
+
const err = error instanceof Error ? error : new Error(String(error));
|
|
9
|
+
if (options?.shouldFallback && !options.shouldFallback(err)) {
|
|
10
|
+
throw err;
|
|
11
|
+
}
|
|
12
|
+
options?.onFallback?.(err, 0);
|
|
13
|
+
if (typeof fallback === "function") {
|
|
14
|
+
return await fallback();
|
|
15
|
+
}
|
|
16
|
+
return fallback;
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
async function fallbackChain(fns, options) {
|
|
20
|
+
if (fns.length === 0) {
|
|
21
|
+
throw new Error("fallbackChain requires at least one function");
|
|
22
|
+
}
|
|
23
|
+
let lastError;
|
|
24
|
+
for (let i = 0; i < fns.length; i++) {
|
|
25
|
+
try {
|
|
26
|
+
return await fns[i]();
|
|
27
|
+
} catch (error) {
|
|
28
|
+
lastError = error instanceof Error ? error : new Error(String(error));
|
|
29
|
+
if (options?.shouldFallback && !options.shouldFallback(lastError)) {
|
|
30
|
+
throw lastError;
|
|
31
|
+
}
|
|
32
|
+
if (i < fns.length - 1) {
|
|
33
|
+
options?.onFallback?.(lastError, i + 1);
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
throw lastError;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
exports.fallbackChain = fallbackChain;
|
|
41
|
+
exports.withFallback = withFallback;
|
|
42
|
+
//# sourceMappingURL=fallback.js.map
|
|
43
|
+
//# sourceMappingURL=fallback.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/fallback.ts"],"names":[],"mappings":";;;AAsBA,eAAsB,YAAA,CACpB,EAAA,EACA,QAAA,EACA,OAAA,EACY;AACZ,EAAA,IAAI;AACF,IAAA,OAAO,MAAM,EAAA,EAAG;AAAA,EAClB,SAAS,KAAA,EAAO;AACd,IAAA,MAAM,GAAA,GAAM,iBAAiB,KAAA,GAAQ,KAAA,GAAQ,IAAI,KAAA,CAAM,MAAA,CAAO,KAAK,CAAC,CAAA;AAEpE,IAAA,IAAI,SAAS,cAAA,IAAkB,CAAC,OAAA,CAAQ,cAAA,CAAe,GAAG,CAAA,EAAG;AAC3D,MAAA,MAAM,GAAA;AAAA,IACR;AAEA,IAAA,OAAA,EAAS,UAAA,GAAa,KAAK,CAAC,CAAA;AAE5B,IAAA,IAAI,OAAO,aAAa,UAAA,EAAY;AAClC,MAAA,OAAO,MAAO,QAAA,EAAkC;AAAA,IAClD;AACA,IAAA,OAAO,QAAA;AAAA,EACT;AACF;AAcA,eAAsB,aAAA,CACpB,KACA,OAAA,EACY;AACZ,EAAA,IAAI,GAAA,CAAI,WAAW,CAAA,EAAG;AACpB,IAAA,MAAM,IAAI,MAAM,8CAA8C,CAAA;AAAA,EAChE;AAEA,EAAA,IAAI,SAAA;AAEJ,EAAA,KAAA,IAAS,CAAA,GAAI,CAAA,EAAG,CAAA,GAAI,GAAA,CAAI,QAAQ,CAAA,EAAA,EAAK;AACnC,IAAA,IAAI;AACF,MAAA,OAAO,MAAM,GAAA,CAAI,CAAC,CAAA,EAAE;AAAA,IACtB,SAAS,KAAA,EAAO;AACd,MAAA,SAAA,GAAY,iBAAiB,KAAA,GAAQ,KAAA,GAAQ,IAAI,KAAA,CAAM,MAAA,CAAO,KAAK,CAAC,CAAA;AAEpE,MAAA,IAAI,SAAS,cAAA,IAAkB,CAAC,OAAA,CAAQ,cAAA,CAAe,SAAS,CAAA,EAAG;AACjE,QAAA,MAAM,SAAA;AAAA,MACR;AAEA,MAAA,IAAI,CAAA,GAAI,GAAA,CAAI,MAAA,GAAS,CAAA,EAAG;AACtB,QAAA,OAAA,EAAS,UAAA,GAAa,SAAA,EAAW,CAAA,GAAI,CAAC,CAAA;AAAA,MACxC;AAAA,IACF;AAAA,EACF;AAEA,EAAA,MAAM,SAAA;AACR","file":"fallback.js","sourcesContent":["// ============================================================================\n// FlowX — Fallback Chain\n// ============================================================================\n\nexport interface FallbackOptions {\n /** Predicate to determine if the error warrants a fallback */\n shouldFallback?: (error: Error) => boolean;\n /** Callback fired when the primary function fails and fallback is used */\n onFallback?: (error: Error, fallbackIndex: number) => void;\n}\n\n/**\n * Execute a function with a fallback value or function if it fails.\n *\n * @example\n * ```ts\n * const data = await withFallback(\n * () => fetch('/primary-api'),\n * 'default-value',\n * );\n * ```\n */\nexport async function withFallback<T>(\n fn: () => T | Promise<T>,\n fallback: T | (() => T | Promise<T>),\n options?: FallbackOptions,\n): Promise<T> {\n try {\n return await fn();\n } catch (error) {\n const err = error instanceof Error ? error : new Error(String(error));\n\n if (options?.shouldFallback && !options.shouldFallback(err)) {\n throw err;\n }\n\n options?.onFallback?.(err, 0);\n\n if (typeof fallback === 'function') {\n return await (fallback as () => T | Promise<T>)();\n }\n return fallback;\n }\n}\n\n/**\n * Execute the first successful function from a chain of fallbacks.\n *\n * @example\n * ```ts\n * const data = await fallbackChain([\n * () => fetch('/primary'),\n * () => fetch('/secondary'),\n * () => fetch('/tertiary'),\n * ]);\n * ```\n */\nexport async function fallbackChain<T>(\n fns: Array<() => T | Promise<T>>,\n options?: FallbackOptions,\n): Promise<T> {\n if (fns.length === 0) {\n throw new Error('fallbackChain requires at least one function');\n }\n\n let lastError: Error | undefined;\n\n for (let i = 0; i < fns.length; i++) {\n try {\n return await fns[i]();\n } catch (error) {\n lastError = error instanceof Error ? error : new Error(String(error));\n\n if (options?.shouldFallback && !options.shouldFallback(lastError)) {\n throw lastError;\n }\n\n if (i < fns.length - 1) {\n options?.onFallback?.(lastError, i + 1);\n }\n }\n }\n\n throw lastError!;\n}\n"]}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
// src/fallback.ts
|
|
2
|
+
async function withFallback(fn, fallback, options) {
|
|
3
|
+
try {
|
|
4
|
+
return await fn();
|
|
5
|
+
} catch (error) {
|
|
6
|
+
const err = error instanceof Error ? error : new Error(String(error));
|
|
7
|
+
if (options?.shouldFallback && !options.shouldFallback(err)) {
|
|
8
|
+
throw err;
|
|
9
|
+
}
|
|
10
|
+
options?.onFallback?.(err, 0);
|
|
11
|
+
if (typeof fallback === "function") {
|
|
12
|
+
return await fallback();
|
|
13
|
+
}
|
|
14
|
+
return fallback;
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
async function fallbackChain(fns, options) {
|
|
18
|
+
if (fns.length === 0) {
|
|
19
|
+
throw new Error("fallbackChain requires at least one function");
|
|
20
|
+
}
|
|
21
|
+
let lastError;
|
|
22
|
+
for (let i = 0; i < fns.length; i++) {
|
|
23
|
+
try {
|
|
24
|
+
return await fns[i]();
|
|
25
|
+
} catch (error) {
|
|
26
|
+
lastError = error instanceof Error ? error : new Error(String(error));
|
|
27
|
+
if (options?.shouldFallback && !options.shouldFallback(lastError)) {
|
|
28
|
+
throw lastError;
|
|
29
|
+
}
|
|
30
|
+
if (i < fns.length - 1) {
|
|
31
|
+
options?.onFallback?.(lastError, i + 1);
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
throw lastError;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
export { fallbackChain, withFallback };
|
|
39
|
+
//# sourceMappingURL=fallback.mjs.map
|
|
40
|
+
//# sourceMappingURL=fallback.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/fallback.ts"],"names":[],"mappings":";AAsBA,eAAsB,YAAA,CACpB,EAAA,EACA,QAAA,EACA,OAAA,EACY;AACZ,EAAA,IAAI;AACF,IAAA,OAAO,MAAM,EAAA,EAAG;AAAA,EAClB,SAAS,KAAA,EAAO;AACd,IAAA,MAAM,GAAA,GAAM,iBAAiB,KAAA,GAAQ,KAAA,GAAQ,IAAI,KAAA,CAAM,MAAA,CAAO,KAAK,CAAC,CAAA;AAEpE,IAAA,IAAI,SAAS,cAAA,IAAkB,CAAC,OAAA,CAAQ,cAAA,CAAe,GAAG,CAAA,EAAG;AAC3D,MAAA,MAAM,GAAA;AAAA,IACR;AAEA,IAAA,OAAA,EAAS,UAAA,GAAa,KAAK,CAAC,CAAA;AAE5B,IAAA,IAAI,OAAO,aAAa,UAAA,EAAY;AAClC,MAAA,OAAO,MAAO,QAAA,EAAkC;AAAA,IAClD;AACA,IAAA,OAAO,QAAA;AAAA,EACT;AACF;AAcA,eAAsB,aAAA,CACpB,KACA,OAAA,EACY;AACZ,EAAA,IAAI,GAAA,CAAI,WAAW,CAAA,EAAG;AACpB,IAAA,MAAM,IAAI,MAAM,8CAA8C,CAAA;AAAA,EAChE;AAEA,EAAA,IAAI,SAAA;AAEJ,EAAA,KAAA,IAAS,CAAA,GAAI,CAAA,EAAG,CAAA,GAAI,GAAA,CAAI,QAAQ,CAAA,EAAA,EAAK;AACnC,IAAA,IAAI;AACF,MAAA,OAAO,MAAM,GAAA,CAAI,CAAC,CAAA,EAAE;AAAA,IACtB,SAAS,KAAA,EAAO;AACd,MAAA,SAAA,GAAY,iBAAiB,KAAA,GAAQ,KAAA,GAAQ,IAAI,KAAA,CAAM,MAAA,CAAO,KAAK,CAAC,CAAA;AAEpE,MAAA,IAAI,SAAS,cAAA,IAAkB,CAAC,OAAA,CAAQ,cAAA,CAAe,SAAS,CAAA,EAAG;AACjE,QAAA,MAAM,SAAA;AAAA,MACR;AAEA,MAAA,IAAI,CAAA,GAAI,GAAA,CAAI,MAAA,GAAS,CAAA,EAAG;AACtB,QAAA,OAAA,EAAS,UAAA,GAAa,SAAA,EAAW,CAAA,GAAI,CAAC,CAAA;AAAA,MACxC;AAAA,IACF;AAAA,EACF;AAEA,EAAA,MAAM,SAAA;AACR","file":"fallback.mjs","sourcesContent":["// ============================================================================\n// FlowX — Fallback Chain\n// ============================================================================\n\nexport interface FallbackOptions {\n /** Predicate to determine if the error warrants a fallback */\n shouldFallback?: (error: Error) => boolean;\n /** Callback fired when the primary function fails and fallback is used */\n onFallback?: (error: Error, fallbackIndex: number) => void;\n}\n\n/**\n * Execute a function with a fallback value or function if it fails.\n *\n * @example\n * ```ts\n * const data = await withFallback(\n * () => fetch('/primary-api'),\n * 'default-value',\n * );\n * ```\n */\nexport async function withFallback<T>(\n fn: () => T | Promise<T>,\n fallback: T | (() => T | Promise<T>),\n options?: FallbackOptions,\n): Promise<T> {\n try {\n return await fn();\n } catch (error) {\n const err = error instanceof Error ? error : new Error(String(error));\n\n if (options?.shouldFallback && !options.shouldFallback(err)) {\n throw err;\n }\n\n options?.onFallback?.(err, 0);\n\n if (typeof fallback === 'function') {\n return await (fallback as () => T | Promise<T>)();\n }\n return fallback;\n }\n}\n\n/**\n * Execute the first successful function from a chain of fallbacks.\n *\n * @example\n * ```ts\n * const data = await fallbackChain([\n * () => fetch('/primary'),\n * () => fetch('/secondary'),\n * () => fetch('/tertiary'),\n * ]);\n * ```\n */\nexport async function fallbackChain<T>(\n fns: Array<() => T | Promise<T>>,\n options?: FallbackOptions,\n): Promise<T> {\n if (fns.length === 0) {\n throw new Error('fallbackChain requires at least one function');\n }\n\n let lastError: Error | undefined;\n\n for (let i = 0; i < fns.length; i++) {\n try {\n return await fns[i]();\n } catch (error) {\n lastError = error instanceof Error ? error : new Error(String(error));\n\n if (options?.shouldFallback && !options.shouldFallback(lastError)) {\n throw lastError;\n }\n\n if (i < fns.length - 1) {\n options?.onFallback?.(lastError, i + 1);\n }\n }\n }\n\n throw lastError!;\n}\n"]}
|
package/dist/hedge.d.mts
ADDED
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
interface HedgeOptions {
|
|
2
|
+
/** Delay in ms before launching the hedge request (default: 500) */
|
|
3
|
+
delay?: number;
|
|
4
|
+
/** Maximum number of parallel hedged calls (default: 1) */
|
|
5
|
+
maxHedges?: number;
|
|
6
|
+
}
|
|
7
|
+
/**
|
|
8
|
+
* Execute a function with hedged requests — if the primary doesn't respond
|
|
9
|
+
* quickly enough, fire parallel redundant calls and return whichever resolves first.
|
|
10
|
+
*
|
|
11
|
+
* @example
|
|
12
|
+
* ```ts
|
|
13
|
+
* const data = await hedge(() => fetch('/api'), { delay: 200 });
|
|
14
|
+
* ```
|
|
15
|
+
*/
|
|
16
|
+
declare function hedge<T>(fn: () => Promise<T>, options?: HedgeOptions): Promise<T>;
|
|
17
|
+
|
|
18
|
+
export { type HedgeOptions, hedge };
|
package/dist/hedge.d.ts
ADDED
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
interface HedgeOptions {
|
|
2
|
+
/** Delay in ms before launching the hedge request (default: 500) */
|
|
3
|
+
delay?: number;
|
|
4
|
+
/** Maximum number of parallel hedged calls (default: 1) */
|
|
5
|
+
maxHedges?: number;
|
|
6
|
+
}
|
|
7
|
+
/**
|
|
8
|
+
* Execute a function with hedged requests — if the primary doesn't respond
|
|
9
|
+
* quickly enough, fire parallel redundant calls and return whichever resolves first.
|
|
10
|
+
*
|
|
11
|
+
* @example
|
|
12
|
+
* ```ts
|
|
13
|
+
* const data = await hedge(() => fetch('/api'), { delay: 200 });
|
|
14
|
+
* ```
|
|
15
|
+
*/
|
|
16
|
+
declare function hedge<T>(fn: () => Promise<T>, options?: HedgeOptions): Promise<T>;
|
|
17
|
+
|
|
18
|
+
export { type HedgeOptions, hedge };
|
package/dist/hedge.js
ADDED
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
// src/hedge.ts
|
|
4
|
+
function hedge(fn, options) {
|
|
5
|
+
const { delay = 500, maxHedges = 1 } = options ?? {};
|
|
6
|
+
if (delay < 0) throw new RangeError("delay must be >= 0");
|
|
7
|
+
if (maxHedges < 1) throw new RangeError("maxHedges must be >= 1");
|
|
8
|
+
return new Promise((resolve, reject) => {
|
|
9
|
+
let settled = false;
|
|
10
|
+
let completedCount = 0;
|
|
11
|
+
const totalAttempts = 1 + maxHedges;
|
|
12
|
+
const errors = [];
|
|
13
|
+
const timers = [];
|
|
14
|
+
function onResult(value) {
|
|
15
|
+
if (settled) return;
|
|
16
|
+
settled = true;
|
|
17
|
+
for (const t of timers) clearTimeout(t);
|
|
18
|
+
resolve(value);
|
|
19
|
+
}
|
|
20
|
+
function onError(error) {
|
|
21
|
+
errors.push(error);
|
|
22
|
+
completedCount++;
|
|
23
|
+
if (completedCount >= totalAttempts && !settled) {
|
|
24
|
+
settled = true;
|
|
25
|
+
reject(errors[0]);
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
fn().then(onResult, (err) => onError(err instanceof Error ? err : new Error(String(err))));
|
|
29
|
+
for (let i = 0; i < maxHedges; i++) {
|
|
30
|
+
const timer = setTimeout(
|
|
31
|
+
() => {
|
|
32
|
+
if (settled) return;
|
|
33
|
+
fn().then(
|
|
34
|
+
onResult,
|
|
35
|
+
(err) => onError(err instanceof Error ? err : new Error(String(err)))
|
|
36
|
+
);
|
|
37
|
+
},
|
|
38
|
+
delay * (i + 1)
|
|
39
|
+
);
|
|
40
|
+
timers.push(timer);
|
|
41
|
+
}
|
|
42
|
+
});
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
exports.hedge = hedge;
|
|
46
|
+
//# sourceMappingURL=hedge.js.map
|
|
47
|
+
//# sourceMappingURL=hedge.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/hedge.ts"],"names":[],"mappings":";;;AAoBO,SAAS,KAAA,CAAS,IAAsB,OAAA,EAAoC;AACjF,EAAA,MAAM,EAAE,KAAA,GAAQ,GAAA,EAAK,YAAY,CAAA,EAAE,GAAI,WAAW,EAAC;AAEnD,EAAA,IAAI,KAAA,GAAQ,CAAA,EAAG,MAAM,IAAI,WAAW,oBAAoB,CAAA;AACxD,EAAA,IAAI,SAAA,GAAY,CAAA,EAAG,MAAM,IAAI,WAAW,wBAAwB,CAAA;AAEhE,EAAA,OAAO,IAAI,OAAA,CAAW,CAAC,OAAA,EAAS,MAAA,KAAW;AACzC,IAAA,IAAI,OAAA,GAAU,KAAA;AACd,IAAA,IAAI,cAAA,GAAiB,CAAA;AACrB,IAAA,MAAM,gBAAgB,CAAA,GAAI,SAAA;AAC1B,IAAA,MAAM,SAAkB,EAAC;AACzB,IAAA,MAAM,SAA0C,EAAC;AAEjD,IAAA,SAAS,SAAS,KAAA,EAAgB;AAChC,MAAA,IAAI,OAAA,EAAS;AACb,MAAA,OAAA,GAAU,IAAA;AAEV,MAAA,KAAA,MAAW,CAAA,IAAK,MAAA,EAAQ,YAAA,CAAa,CAAC,CAAA;AACtC,MAAA,OAAA,CAAQ,KAAK,CAAA;AAAA,IACf;AAEA,IAAA,SAAS,QAAQ,KAAA,EAAoB;AACnC,MAAA,MAAA,CAAO,KAAK,KAAK,CAAA;AACjB,MAAA,cAAA,EAAA;AACA,MAAA,IAAI,cAAA,IAAkB,aAAA,IAAiB,CAAC,OAAA,EAAS;AAC/C,QAAA,OAAA,GAAU,IAAA;AACV,QAAA,MAAA,CAAO,MAAA,CAAO,CAAC,CAAC,CAAA;AAAA,MAClB;AAAA,IACF;AAGA,IAAA,EAAA,EAAG,CAAE,IAAA,CAAK,QAAA,EAAU,CAAC,QAAQ,OAAA,CAAQ,GAAA,YAAe,KAAA,GAAQ,GAAA,GAAM,IAAI,KAAA,CAAM,MAAA,CAAO,GAAG,CAAC,CAAC,CAAC,CAAA;AAGzF,IAAA,KAAA,IAAS,CAAA,GAAI,CAAA,EAAG,CAAA,GAAI,SAAA,EAAW,CAAA,EAAA,EAAK;AAClC,MAAA,MAAM,KAAA,GAAQ,UAAA;AAAA,QACZ,MAAM;AAEJ,UAAA,IAAI,OAAA,EAAS;AACb,UAAA,EAAA,EAAG,CAAE,IAAA;AAAA,YAAK,QAAA;AAAA,YAAU,CAAC,GAAA,KACnB,OAAA,CAAQ,GAAA,YAAe,KAAA,GAAQ,GAAA,GAAM,IAAI,KAAA,CAAM,MAAA,CAAO,GAAG,CAAC,CAAC;AAAA,WAC7D;AAAA,QACF,CAAA;AAAA,QACA,SAAS,CAAA,GAAI,CAAA;AAAA,OACf;AACA,MAAA,MAAA,CAAO,KAAK,KAAK,CAAA;AAAA,IACnB;AAAA,EACF,CAAC,CAAA;AACH","file":"hedge.js","sourcesContent":["// ============================================================================\n// FlowX — Hedged Requests\n// ============================================================================\n\nexport interface HedgeOptions {\n /** Delay in ms before launching the hedge request (default: 500) */\n delay?: number;\n /** Maximum number of parallel hedged calls (default: 1) */\n maxHedges?: number;\n}\n\n/**\n * Execute a function with hedged requests — if the primary doesn't respond\n * quickly enough, fire parallel redundant calls and return whichever resolves first.\n *\n * @example\n * ```ts\n * const data = await hedge(() => fetch('/api'), { delay: 200 });\n * ```\n */\nexport function hedge<T>(fn: () => Promise<T>, options?: HedgeOptions): Promise<T> {\n const { delay = 500, maxHedges = 1 } = options ?? {};\n\n if (delay < 0) throw new RangeError('delay must be >= 0');\n if (maxHedges < 1) throw new RangeError('maxHedges must be >= 1');\n\n return new Promise<T>((resolve, reject) => {\n let settled = false;\n let completedCount = 0;\n const totalAttempts = 1 + maxHedges;\n const errors: Error[] = [];\n const timers: ReturnType<typeof setTimeout>[] = [];\n\n function onResult(value: T): void {\n if (settled) return;\n settled = true;\n // Clear pending hedge timers\n for (const t of timers) clearTimeout(t);\n resolve(value);\n }\n\n function onError(error: Error): void {\n errors.push(error);\n completedCount++;\n if (completedCount >= totalAttempts && !settled) {\n settled = true;\n reject(errors[0]);\n }\n }\n\n // Launch primary request immediately\n fn().then(onResult, (err) => onError(err instanceof Error ? err : new Error(String(err))));\n\n // Launch hedged requests after delay\n for (let i = 0; i < maxHedges; i++) {\n const timer = setTimeout(\n () => {\n /* istanbul ignore if -- timer is always cleared by onResult before firing */\n if (settled) return;\n fn().then(onResult, (err) =>\n onError(err instanceof Error ? err : new Error(String(err))),\n );\n },\n delay * (i + 1),\n );\n timers.push(timer);\n }\n });\n}\n"]}
|
package/dist/hedge.mjs
ADDED
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
// src/hedge.ts
|
|
2
|
+
function hedge(fn, options) {
|
|
3
|
+
const { delay = 500, maxHedges = 1 } = options ?? {};
|
|
4
|
+
if (delay < 0) throw new RangeError("delay must be >= 0");
|
|
5
|
+
if (maxHedges < 1) throw new RangeError("maxHedges must be >= 1");
|
|
6
|
+
return new Promise((resolve, reject) => {
|
|
7
|
+
let settled = false;
|
|
8
|
+
let completedCount = 0;
|
|
9
|
+
const totalAttempts = 1 + maxHedges;
|
|
10
|
+
const errors = [];
|
|
11
|
+
const timers = [];
|
|
12
|
+
function onResult(value) {
|
|
13
|
+
if (settled) return;
|
|
14
|
+
settled = true;
|
|
15
|
+
for (const t of timers) clearTimeout(t);
|
|
16
|
+
resolve(value);
|
|
17
|
+
}
|
|
18
|
+
function onError(error) {
|
|
19
|
+
errors.push(error);
|
|
20
|
+
completedCount++;
|
|
21
|
+
if (completedCount >= totalAttempts && !settled) {
|
|
22
|
+
settled = true;
|
|
23
|
+
reject(errors[0]);
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
fn().then(onResult, (err) => onError(err instanceof Error ? err : new Error(String(err))));
|
|
27
|
+
for (let i = 0; i < maxHedges; i++) {
|
|
28
|
+
const timer = setTimeout(
|
|
29
|
+
() => {
|
|
30
|
+
if (settled) return;
|
|
31
|
+
fn().then(
|
|
32
|
+
onResult,
|
|
33
|
+
(err) => onError(err instanceof Error ? err : new Error(String(err)))
|
|
34
|
+
);
|
|
35
|
+
},
|
|
36
|
+
delay * (i + 1)
|
|
37
|
+
);
|
|
38
|
+
timers.push(timer);
|
|
39
|
+
}
|
|
40
|
+
});
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
export { hedge };
|
|
44
|
+
//# sourceMappingURL=hedge.mjs.map
|
|
45
|
+
//# sourceMappingURL=hedge.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/hedge.ts"],"names":[],"mappings":";AAoBO,SAAS,KAAA,CAAS,IAAsB,OAAA,EAAoC;AACjF,EAAA,MAAM,EAAE,KAAA,GAAQ,GAAA,EAAK,YAAY,CAAA,EAAE,GAAI,WAAW,EAAC;AAEnD,EAAA,IAAI,KAAA,GAAQ,CAAA,EAAG,MAAM,IAAI,WAAW,oBAAoB,CAAA;AACxD,EAAA,IAAI,SAAA,GAAY,CAAA,EAAG,MAAM,IAAI,WAAW,wBAAwB,CAAA;AAEhE,EAAA,OAAO,IAAI,OAAA,CAAW,CAAC,OAAA,EAAS,MAAA,KAAW;AACzC,IAAA,IAAI,OAAA,GAAU,KAAA;AACd,IAAA,IAAI,cAAA,GAAiB,CAAA;AACrB,IAAA,MAAM,gBAAgB,CAAA,GAAI,SAAA;AAC1B,IAAA,MAAM,SAAkB,EAAC;AACzB,IAAA,MAAM,SAA0C,EAAC;AAEjD,IAAA,SAAS,SAAS,KAAA,EAAgB;AAChC,MAAA,IAAI,OAAA,EAAS;AACb,MAAA,OAAA,GAAU,IAAA;AAEV,MAAA,KAAA,MAAW,CAAA,IAAK,MAAA,EAAQ,YAAA,CAAa,CAAC,CAAA;AACtC,MAAA,OAAA,CAAQ,KAAK,CAAA;AAAA,IACf;AAEA,IAAA,SAAS,QAAQ,KAAA,EAAoB;AACnC,MAAA,MAAA,CAAO,KAAK,KAAK,CAAA;AACjB,MAAA,cAAA,EAAA;AACA,MAAA,IAAI,cAAA,IAAkB,aAAA,IAAiB,CAAC,OAAA,EAAS;AAC/C,QAAA,OAAA,GAAU,IAAA;AACV,QAAA,MAAA,CAAO,MAAA,CAAO,CAAC,CAAC,CAAA;AAAA,MAClB;AAAA,IACF;AAGA,IAAA,EAAA,EAAG,CAAE,IAAA,CAAK,QAAA,EAAU,CAAC,QAAQ,OAAA,CAAQ,GAAA,YAAe,KAAA,GAAQ,GAAA,GAAM,IAAI,KAAA,CAAM,MAAA,CAAO,GAAG,CAAC,CAAC,CAAC,CAAA;AAGzF,IAAA,KAAA,IAAS,CAAA,GAAI,CAAA,EAAG,CAAA,GAAI,SAAA,EAAW,CAAA,EAAA,EAAK;AAClC,MAAA,MAAM,KAAA,GAAQ,UAAA;AAAA,QACZ,MAAM;AAEJ,UAAA,IAAI,OAAA,EAAS;AACb,UAAA,EAAA,EAAG,CAAE,IAAA;AAAA,YAAK,QAAA;AAAA,YAAU,CAAC,GAAA,KACnB,OAAA,CAAQ,GAAA,YAAe,KAAA,GAAQ,GAAA,GAAM,IAAI,KAAA,CAAM,MAAA,CAAO,GAAG,CAAC,CAAC;AAAA,WAC7D;AAAA,QACF,CAAA;AAAA,QACA,SAAS,CAAA,GAAI,CAAA;AAAA,OACf;AACA,MAAA,MAAA,CAAO,KAAK,KAAK,CAAA;AAAA,IACnB;AAAA,EACF,CAAC,CAAA;AACH","file":"hedge.mjs","sourcesContent":["// ============================================================================\n// FlowX — Hedged Requests\n// ============================================================================\n\nexport interface HedgeOptions {\n /** Delay in ms before launching the hedge request (default: 500) */\n delay?: number;\n /** Maximum number of parallel hedged calls (default: 1) */\n maxHedges?: number;\n}\n\n/**\n * Execute a function with hedged requests — if the primary doesn't respond\n * quickly enough, fire parallel redundant calls and return whichever resolves first.\n *\n * @example\n * ```ts\n * const data = await hedge(() => fetch('/api'), { delay: 200 });\n * ```\n */\nexport function hedge<T>(fn: () => Promise<T>, options?: HedgeOptions): Promise<T> {\n const { delay = 500, maxHedges = 1 } = options ?? {};\n\n if (delay < 0) throw new RangeError('delay must be >= 0');\n if (maxHedges < 1) throw new RangeError('maxHedges must be >= 1');\n\n return new Promise<T>((resolve, reject) => {\n let settled = false;\n let completedCount = 0;\n const totalAttempts = 1 + maxHedges;\n const errors: Error[] = [];\n const timers: ReturnType<typeof setTimeout>[] = [];\n\n function onResult(value: T): void {\n if (settled) return;\n settled = true;\n // Clear pending hedge timers\n for (const t of timers) clearTimeout(t);\n resolve(value);\n }\n\n function onError(error: Error): void {\n errors.push(error);\n completedCount++;\n if (completedCount >= totalAttempts && !settled) {\n settled = true;\n reject(errors[0]);\n }\n }\n\n // Launch primary request immediately\n fn().then(onResult, (err) => onError(err instanceof Error ? err : new Error(String(err))));\n\n // Launch hedged requests after delay\n for (let i = 0; i < maxHedges; i++) {\n const timer = setTimeout(\n () => {\n /* istanbul ignore if -- timer is always cleared by onResult before firing */\n if (settled) return;\n fn().then(onResult, (err) =>\n onError(err instanceof Error ? err : new Error(String(err))),\n );\n },\n delay * (i + 1),\n );\n timers.push(timer);\n }\n });\n}\n"]}
|
package/dist/index.d.mts
ADDED
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
export { A as AbortError, a as AsyncFn, B as BackoffStrategy, b as BulkheadError, C as CircuitBreakerError, F as FlowXError, R as RateLimitError, T as TimeoutError, c as calculateDelay, s as sleep } from './types-BsCO2J40.mjs';
|
|
2
|
+
export { RetryOptions, retry, retryable } from './retry.mjs';
|
|
3
|
+
export { CircuitBreaker, CircuitBreakerOptions, CircuitState, createCircuitBreaker } from './circuit-breaker.mjs';
|
|
4
|
+
export { Bulkhead, BulkheadOptions, createBulkhead } from './bulkhead.mjs';
|
|
5
|
+
export { FallbackOptions, fallbackChain, withFallback } from './fallback.mjs';
|
|
6
|
+
export { HedgeOptions, hedge } from './hedge.mjs';
|
|
7
|
+
export { Semaphore, createSemaphore } from './semaphore.mjs';
|
|
8
|
+
export { Mutex, createMutex } from './mutex.mjs';
|
|
9
|
+
export { AsyncQueue, QueueAddOptions, QueueOptions, createQueue } from './queue.mjs';
|
|
10
|
+
export { RateLimitOptions, RateLimiter, createRateLimiter } from './rate-limit.mjs';
|
|
11
|
+
export { TimeoutOptions, withTimeout } from './timeout.mjs';
|
|
12
|
+
export { DebounceOptions, DebouncedFunction, debounce } from './debounce.mjs';
|
|
13
|
+
export { ThrottleOptions, ThrottledFunction, throttle } from './throttle.mjs';
|
|
14
|
+
export { BatchOptions, BatchResult, batch } from './batch.mjs';
|
|
15
|
+
export { PipelineStep, pipe, pipeline } from './pipeline.mjs';
|
|
16
|
+
export { PollController, PollOptions, poll } from './poll.mjs';
|
|
17
|
+
export { Deferred, createDeferred } from './deferred.mjs';
|
|
18
|
+
export { MemoOptions, MemoizedFunction, memo } from './memo.mjs';
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
export { A as AbortError, a as AsyncFn, B as BackoffStrategy, b as BulkheadError, C as CircuitBreakerError, F as FlowXError, R as RateLimitError, T as TimeoutError, c as calculateDelay, s as sleep } from './types-BsCO2J40.js';
|
|
2
|
+
export { RetryOptions, retry, retryable } from './retry.js';
|
|
3
|
+
export { CircuitBreaker, CircuitBreakerOptions, CircuitState, createCircuitBreaker } from './circuit-breaker.js';
|
|
4
|
+
export { Bulkhead, BulkheadOptions, createBulkhead } from './bulkhead.js';
|
|
5
|
+
export { FallbackOptions, fallbackChain, withFallback } from './fallback.js';
|
|
6
|
+
export { HedgeOptions, hedge } from './hedge.js';
|
|
7
|
+
export { Semaphore, createSemaphore } from './semaphore.js';
|
|
8
|
+
export { Mutex, createMutex } from './mutex.js';
|
|
9
|
+
export { AsyncQueue, QueueAddOptions, QueueOptions, createQueue } from './queue.js';
|
|
10
|
+
export { RateLimitOptions, RateLimiter, createRateLimiter } from './rate-limit.js';
|
|
11
|
+
export { TimeoutOptions, withTimeout } from './timeout.js';
|
|
12
|
+
export { DebounceOptions, DebouncedFunction, debounce } from './debounce.js';
|
|
13
|
+
export { ThrottleOptions, ThrottledFunction, throttle } from './throttle.js';
|
|
14
|
+
export { BatchOptions, BatchResult, batch } from './batch.js';
|
|
15
|
+
export { PipelineStep, pipe, pipeline } from './pipeline.js';
|
|
16
|
+
export { PollController, PollOptions, poll } from './poll.js';
|
|
17
|
+
export { Deferred, createDeferred } from './deferred.js';
|
|
18
|
+
export { MemoOptions, MemoizedFunction, memo } from './memo.js';
|