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.
Files changed (112) hide show
  1. package/README.md +443 -0
  2. package/dist/batch.d.mts +37 -0
  3. package/dist/batch.d.ts +37 -0
  4. package/dist/batch.js +75 -0
  5. package/dist/batch.js.map +1 -0
  6. package/dist/batch.mjs +73 -0
  7. package/dist/batch.mjs.map +1 -0
  8. package/dist/bulkhead.d.mts +30 -0
  9. package/dist/bulkhead.d.ts +30 -0
  10. package/dist/bulkhead.js +85 -0
  11. package/dist/bulkhead.js.map +1 -0
  12. package/dist/bulkhead.mjs +83 -0
  13. package/dist/bulkhead.mjs.map +1 -0
  14. package/dist/circuit-breaker.d.mts +44 -0
  15. package/dist/circuit-breaker.d.ts +44 -0
  16. package/dist/circuit-breaker.js +132 -0
  17. package/dist/circuit-breaker.js.map +1 -0
  18. package/dist/circuit-breaker.mjs +130 -0
  19. package/dist/circuit-breaker.mjs.map +1 -0
  20. package/dist/debounce.d.mts +30 -0
  21. package/dist/debounce.d.ts +30 -0
  22. package/dist/debounce.js +96 -0
  23. package/dist/debounce.js.map +1 -0
  24. package/dist/debounce.mjs +94 -0
  25. package/dist/debounce.mjs.map +1 -0
  26. package/dist/deferred.d.mts +27 -0
  27. package/dist/deferred.d.ts +27 -0
  28. package/dist/deferred.js +42 -0
  29. package/dist/deferred.js.map +1 -0
  30. package/dist/deferred.mjs +40 -0
  31. package/dist/deferred.mjs.map +1 -0
  32. package/dist/fallback.d.mts +33 -0
  33. package/dist/fallback.d.ts +33 -0
  34. package/dist/fallback.js +43 -0
  35. package/dist/fallback.js.map +1 -0
  36. package/dist/fallback.mjs +40 -0
  37. package/dist/fallback.mjs.map +1 -0
  38. package/dist/hedge.d.mts +18 -0
  39. package/dist/hedge.d.ts +18 -0
  40. package/dist/hedge.js +47 -0
  41. package/dist/hedge.js.map +1 -0
  42. package/dist/hedge.mjs +45 -0
  43. package/dist/hedge.mjs.map +1 -0
  44. package/dist/index.d.mts +18 -0
  45. package/dist/index.d.ts +18 -0
  46. package/dist/index.js +1151 -0
  47. package/dist/index.js.map +1 -0
  48. package/dist/index.mjs +1122 -0
  49. package/dist/index.mjs.map +1 -0
  50. package/dist/memo.d.mts +35 -0
  51. package/dist/memo.d.ts +35 -0
  52. package/dist/memo.js +74 -0
  53. package/dist/memo.js.map +1 -0
  54. package/dist/memo.mjs +72 -0
  55. package/dist/memo.mjs.map +1 -0
  56. package/dist/mutex.d.mts +24 -0
  57. package/dist/mutex.d.ts +24 -0
  58. package/dist/mutex.js +46 -0
  59. package/dist/mutex.js.map +1 -0
  60. package/dist/mutex.mjs +44 -0
  61. package/dist/mutex.mjs.map +1 -0
  62. package/dist/pipeline.d.mts +42 -0
  63. package/dist/pipeline.d.ts +42 -0
  64. package/dist/pipeline.js +30 -0
  65. package/dist/pipeline.js.map +1 -0
  66. package/dist/pipeline.mjs +27 -0
  67. package/dist/pipeline.mjs.map +1 -0
  68. package/dist/poll.d.mts +35 -0
  69. package/dist/poll.d.ts +35 -0
  70. package/dist/poll.js +111 -0
  71. package/dist/poll.js.map +1 -0
  72. package/dist/poll.mjs +109 -0
  73. package/dist/poll.mjs.map +1 -0
  74. package/dist/queue.d.mts +47 -0
  75. package/dist/queue.d.ts +47 -0
  76. package/dist/queue.js +121 -0
  77. package/dist/queue.js.map +1 -0
  78. package/dist/queue.mjs +119 -0
  79. package/dist/queue.mjs.map +1 -0
  80. package/dist/rate-limit.d.mts +28 -0
  81. package/dist/rate-limit.d.ts +28 -0
  82. package/dist/rate-limit.js +94 -0
  83. package/dist/rate-limit.js.map +1 -0
  84. package/dist/rate-limit.mjs +92 -0
  85. package/dist/rate-limit.mjs.map +1 -0
  86. package/dist/retry.d.mts +45 -0
  87. package/dist/retry.d.ts +45 -0
  88. package/dist/retry.js +111 -0
  89. package/dist/retry.js.map +1 -0
  90. package/dist/retry.mjs +108 -0
  91. package/dist/retry.mjs.map +1 -0
  92. package/dist/semaphore.d.mts +27 -0
  93. package/dist/semaphore.d.ts +27 -0
  94. package/dist/semaphore.js +47 -0
  95. package/dist/semaphore.js.map +1 -0
  96. package/dist/semaphore.mjs +45 -0
  97. package/dist/semaphore.mjs.map +1 -0
  98. package/dist/throttle.d.mts +25 -0
  99. package/dist/throttle.d.ts +25 -0
  100. package/dist/throttle.js +97 -0
  101. package/dist/throttle.js.map +1 -0
  102. package/dist/throttle.mjs +95 -0
  103. package/dist/throttle.mjs.map +1 -0
  104. package/dist/timeout.d.mts +19 -0
  105. package/dist/timeout.d.ts +19 -0
  106. package/dist/timeout.js +79 -0
  107. package/dist/timeout.js.map +1 -0
  108. package/dist/timeout.mjs +77 -0
  109. package/dist/timeout.mjs.map +1 -0
  110. package/dist/types-BsCO2J40.d.mts +35 -0
  111. package/dist/types-BsCO2J40.d.ts +35 -0
  112. package/package.json +167 -0
@@ -0,0 +1,95 @@
1
+ // src/throttle.ts
2
+ function throttle(fn, wait, options) {
3
+ const { leading = true, trailing = true } = options ?? {};
4
+ if (wait < 0) throw new RangeError("wait must be >= 0");
5
+ let lastCallTime = null;
6
+ let timer = null;
7
+ let lastArgs = null;
8
+ let isPending = false;
9
+ const trailingResolvers = [];
10
+ async function invokeTrailing() {
11
+ const args = lastArgs;
12
+ const resolvers = trailingResolvers.splice(0);
13
+ lastArgs = null;
14
+ isPending = false;
15
+ timer = null;
16
+ if (!args) {
17
+ for (const r of resolvers) r.resolve(void 0);
18
+ return;
19
+ }
20
+ try {
21
+ const result = await fn(...args);
22
+ for (const r of resolvers) r.resolve(result);
23
+ } catch (error) {
24
+ const err = error instanceof Error ? error : new Error(String(error));
25
+ for (const r of resolvers) r.reject(err);
26
+ }
27
+ }
28
+ function throttled(...args) {
29
+ const now = Date.now();
30
+ lastArgs = args;
31
+ const timeSinceLastCall = lastCallTime === null ? wait : now - lastCallTime;
32
+ const shouldCallLeading = leading && timeSinceLastCall >= wait;
33
+ if (shouldCallLeading) {
34
+ lastCallTime = now;
35
+ lastArgs = null;
36
+ if (timer) {
37
+ clearTimeout(timer);
38
+ timer = null;
39
+ }
40
+ const prevResolvers = trailingResolvers.splice(0);
41
+ const resultPromise = (async () => {
42
+ try {
43
+ const result = await fn(...args);
44
+ for (const r of prevResolvers) r.resolve(result);
45
+ return result;
46
+ } catch (error) {
47
+ const err = error instanceof Error ? error : new Error(String(error));
48
+ for (const r of prevResolvers) r.reject(err);
49
+ throw err;
50
+ }
51
+ })();
52
+ if (trailing) {
53
+ timer = setTimeout(() => {
54
+ lastCallTime = Date.now();
55
+ invokeTrailing();
56
+ }, wait);
57
+ }
58
+ return resultPromise;
59
+ }
60
+ isPending = true;
61
+ return new Promise((resolve, reject) => {
62
+ trailingResolvers.push({ resolve, reject });
63
+ if (!timer && trailing) {
64
+ const remaining = wait - timeSinceLastCall;
65
+ timer = setTimeout(() => {
66
+ lastCallTime = Date.now();
67
+ invokeTrailing();
68
+ }, remaining);
69
+ }
70
+ });
71
+ }
72
+ throttled.cancel = () => {
73
+ if (timer) {
74
+ clearTimeout(timer);
75
+ timer = null;
76
+ }
77
+ lastArgs = null;
78
+ lastCallTime = null;
79
+ isPending = false;
80
+ const resolvers = trailingResolvers.splice(0);
81
+ for (const r of resolvers) {
82
+ r.reject(new Error("Throttled call cancelled"));
83
+ }
84
+ };
85
+ Object.defineProperty(throttled, "pending", {
86
+ get() {
87
+ return isPending;
88
+ }
89
+ });
90
+ return throttled;
91
+ }
92
+
93
+ export { throttle };
94
+ //# sourceMappingURL=throttle.mjs.map
95
+ //# sourceMappingURL=throttle.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/throttle.ts"],"names":[],"mappings":"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","file":"throttle.mjs","sourcesContent":["// ============================================================================\n// FlowX — Async-Aware Throttle\n// ============================================================================\n\nexport interface ThrottleOptions {\n /** Invoke on the leading edge (default: true) */\n leading?: boolean;\n /** Invoke on the trailing edge (default: true) */\n trailing?: boolean;\n}\n\nexport interface ThrottledFunction<TArgs extends any[], TReturn> {\n (...args: TArgs): Promise<TReturn>;\n /** Cancel any pending trailing invocation */\n cancel: () => void;\n /** Whether there is a pending trailing invocation */\n readonly pending: boolean;\n}\n\n/**\n * Create a throttled version of an async function.\n *\n * @example\n * ```ts\n * const throttledSave = throttle(saveData, 1000);\n * await throttledSave(data);\n * ```\n */\nexport function throttle<TArgs extends any[], TReturn>(\n fn: (...args: TArgs) => TReturn | Promise<TReturn>,\n wait: number,\n options?: ThrottleOptions,\n): ThrottledFunction<TArgs, TReturn> {\n const { leading = true, trailing = true } = options ?? {};\n\n if (wait < 0) throw new RangeError('wait must be >= 0');\n\n let lastCallTime: number | null = null;\n let timer: ReturnType<typeof setTimeout> | null = null;\n let lastArgs: TArgs | null = null;\n let isPending = false;\n const trailingResolvers: Array<{\n resolve: (value: TReturn) => void;\n reject: (error: Error) => void;\n }> = [];\n\n async function invokeTrailing(): Promise<void> {\n const args = lastArgs;\n const resolvers = trailingResolvers.splice(0);\n lastArgs = null;\n isPending = false;\n timer = null;\n\n if (!args) {\n /* istanbul ignore next -- resolvers is always empty here; lastArgs cleared before trailing fires */\n for (const r of resolvers) r.resolve(undefined as TReturn);\n return;\n }\n\n try {\n const result = await fn(...args);\n for (const r of resolvers) r.resolve(result);\n } catch (error) {\n const err = error instanceof Error ? error : new Error(String(error));\n for (const r of resolvers) r.reject(err);\n }\n }\n\n function throttled(...args: TArgs): Promise<TReturn> {\n const now = Date.now();\n lastArgs = args;\n\n const timeSinceLastCall = lastCallTime === null ? wait : now - lastCallTime;\n const shouldCallLeading = leading && timeSinceLastCall >= wait;\n\n if (shouldCallLeading) {\n lastCallTime = now;\n lastArgs = null;\n\n if (timer) {\n clearTimeout(timer);\n timer = null;\n }\n\n // Resolve any pending trailing resolvers with this call's result\n const prevResolvers = trailingResolvers.splice(0);\n\n const resultPromise = (async () => {\n try {\n const result = await fn(...args);\n for (const r of prevResolvers) r.resolve(result);\n return result;\n } catch (error) {\n const err = error instanceof Error ? error : new Error(String(error));\n /* istanbul ignore next -- prevResolvers is always empty on leading calls in normal flow */\n for (const r of prevResolvers) r.reject(err);\n throw err;\n }\n })();\n\n if (trailing) {\n timer = setTimeout(() => {\n lastCallTime = Date.now();\n invokeTrailing();\n }, wait);\n }\n\n return resultPromise;\n }\n\n // Schedule trailing call\n isPending = true;\n\n return new Promise<TReturn>((resolve, reject) => {\n trailingResolvers.push({ resolve, reject });\n\n if (!timer && trailing) {\n const remaining = wait - timeSinceLastCall;\n timer = setTimeout(() => {\n lastCallTime = Date.now();\n invokeTrailing();\n }, remaining);\n }\n });\n }\n\n throttled.cancel = (): void => {\n if (timer) {\n clearTimeout(timer);\n timer = null;\n }\n lastArgs = null;\n lastCallTime = null;\n isPending = false;\n const resolvers = trailingResolvers.splice(0);\n for (const r of resolvers) {\n r.reject(new Error('Throttled call cancelled'));\n }\n };\n\n Object.defineProperty(throttled, 'pending', {\n get() {\n return isPending;\n },\n });\n\n return throttled as ThrottledFunction<TArgs, TReturn>;\n}\n"]}
@@ -0,0 +1,19 @@
1
+ interface TimeoutOptions<T = unknown> {
2
+ /** Fallback value or factory when timeout occurs */
3
+ fallback?: T | (() => T | Promise<T>);
4
+ /** AbortSignal for external cancellation */
5
+ signal?: AbortSignal;
6
+ /** Custom error message */
7
+ message?: string;
8
+ }
9
+ /**
10
+ * Wrap an async operation with a timeout.
11
+ *
12
+ * @example
13
+ * ```ts
14
+ * const result = await withTimeout(() => fetch('/slow-api'), 5000);
15
+ * ```
16
+ */
17
+ declare function withTimeout<T>(fn: () => T | Promise<T>, ms: number, options?: TimeoutOptions<T>): Promise<T>;
18
+
19
+ export { type TimeoutOptions, withTimeout };
@@ -0,0 +1,19 @@
1
+ interface TimeoutOptions<T = unknown> {
2
+ /** Fallback value or factory when timeout occurs */
3
+ fallback?: T | (() => T | Promise<T>);
4
+ /** AbortSignal for external cancellation */
5
+ signal?: AbortSignal;
6
+ /** Custom error message */
7
+ message?: string;
8
+ }
9
+ /**
10
+ * Wrap an async operation with a timeout.
11
+ *
12
+ * @example
13
+ * ```ts
14
+ * const result = await withTimeout(() => fetch('/slow-api'), 5000);
15
+ * ```
16
+ */
17
+ declare function withTimeout<T>(fn: () => T | Promise<T>, ms: number, options?: TimeoutOptions<T>): Promise<T>;
18
+
19
+ export { type TimeoutOptions, withTimeout };
@@ -0,0 +1,79 @@
1
+ 'use strict';
2
+
3
+ // src/types.ts
4
+ var FlowXError = class extends Error {
5
+ constructor(message, code) {
6
+ super(message);
7
+ this.name = "FlowXError";
8
+ this.code = code;
9
+ Object.setPrototypeOf(this, new.target.prototype);
10
+ }
11
+ };
12
+ var TimeoutError = class extends FlowXError {
13
+ constructor(message = "Operation timed out") {
14
+ super(message, "ERR_TIMEOUT");
15
+ this.name = "TimeoutError";
16
+ }
17
+ };
18
+ var AbortError = class extends FlowXError {
19
+ constructor(message = "Operation aborted") {
20
+ super(message, "ERR_ABORTED");
21
+ this.name = "AbortError";
22
+ }
23
+ };
24
+
25
+ // src/timeout.ts
26
+ async function withTimeout(fn, ms, options) {
27
+ if (ms <= 0) {
28
+ throw new RangeError("Timeout must be > 0");
29
+ }
30
+ if (options?.signal?.aborted) {
31
+ throw new AbortError();
32
+ }
33
+ const fnResult = fn();
34
+ return Promise.race([
35
+ Promise.resolve(fnResult),
36
+ new Promise((_, reject) => {
37
+ const timer = setTimeout(() => {
38
+ if (options?.fallback !== void 0) {
39
+ const fb = options.fallback;
40
+ if (typeof fb === "function") {
41
+ try {
42
+ const result = fb();
43
+ Promise.resolve(result).then(
44
+ (v) => reject({ __resolved: true, value: v }),
45
+ reject
46
+ );
47
+ } catch (err) {
48
+ reject(err);
49
+ }
50
+ } else {
51
+ reject({ __resolved: true, value: fb });
52
+ }
53
+ } else {
54
+ reject(new TimeoutError(options?.message));
55
+ }
56
+ }, ms);
57
+ if (options?.signal) {
58
+ const onAbort = () => {
59
+ clearTimeout(timer);
60
+ reject(new AbortError());
61
+ };
62
+ options.signal.addEventListener("abort", onAbort, { once: true });
63
+ }
64
+ Promise.resolve(fnResult).then(
65
+ () => clearTimeout(timer),
66
+ () => clearTimeout(timer)
67
+ );
68
+ })
69
+ ]).catch((err) => {
70
+ if (err && typeof err === "object" && "__resolved" in err) {
71
+ return err.value;
72
+ }
73
+ throw err;
74
+ });
75
+ }
76
+
77
+ exports.withTimeout = withTimeout;
78
+ //# sourceMappingURL=timeout.js.map
79
+ //# sourceMappingURL=timeout.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/types.ts","../src/timeout.ts"],"names":[],"mappings":"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","file":"timeout.js","sourcesContent":["// ============================================================================\n// FlowX — Types & Error Hierarchy\n// ============================================================================\n\n/** Generic async function signature */\nexport type AsyncFn<TArgs extends any[] = any[], TReturn = any> = (\n ...args: TArgs\n) => Promise<TReturn>;\n\n/** Backoff strategy for retry/poll operations */\nexport type BackoffStrategy =\n | 'fixed'\n | 'linear'\n | 'exponential'\n | ((attempt: number, delay: number) => number);\n\n// ── Error Classes ───────────────────────────────────────────────────────────\n\n/** Base error class for all FlowX errors */\nexport class FlowXError extends Error {\n public readonly code: string;\n constructor(message: string, code: string) {\n super(message);\n this.name = 'FlowXError';\n this.code = code;\n Object.setPrototypeOf(this, new.target.prototype);\n }\n}\n\n/** Thrown when a promise exceeds its timeout */\nexport class TimeoutError extends FlowXError {\n constructor(message = 'Operation timed out') {\n super(message, 'ERR_TIMEOUT');\n this.name = 'TimeoutError';\n }\n}\n\n/** Thrown when a circuit breaker is open */\nexport class CircuitBreakerError extends FlowXError {\n constructor(message = 'Circuit breaker is open') {\n super(message, 'ERR_CIRCUIT_OPEN');\n this.name = 'CircuitBreakerError';\n }\n}\n\n/** Thrown when a bulkhead rejects due to capacity */\nexport class BulkheadError extends FlowXError {\n constructor(message = 'Bulkhead capacity exceeded') {\n super(message, 'ERR_BULKHEAD_FULL');\n this.name = 'BulkheadError';\n }\n}\n\n/** Thrown when an operation is aborted */\nexport class AbortError extends FlowXError {\n constructor(message = 'Operation aborted') {\n super(message, 'ERR_ABORTED');\n this.name = 'AbortError';\n }\n}\n\n/** Thrown when rate limit is exceeded */\nexport class RateLimitError extends FlowXError {\n constructor(message = 'Rate limit exceeded') {\n super(message, 'ERR_RATE_LIMIT');\n this.name = 'RateLimitError';\n }\n}\n\n// ── Utility Helpers ─────────────────────────────────────────────────────────\n\n/** Sleep for the specified duration, respecting AbortSignal */\nexport function sleep(ms: number, signal?: AbortSignal): Promise<void> {\n return new Promise<void>((resolve, reject) => {\n if (signal?.aborted) {\n reject(new AbortError());\n return;\n }\n\n let onAbort: (() => void) | undefined;\n\n const timer = setTimeout(() => {\n if (signal && onAbort) {\n signal.removeEventListener('abort', onAbort);\n }\n resolve();\n }, ms);\n\n if (signal) {\n onAbort = () => {\n clearTimeout(timer);\n reject(new AbortError());\n };\n signal.addEventListener('abort', onAbort, { once: true });\n }\n });\n}\n\n/** Calculate delay based on backoff strategy */\nexport function calculateDelay(\n attempt: number,\n baseDelay: number,\n strategy: BackoffStrategy,\n jitter: boolean | number = false,\n): number {\n let delay: number;\n\n if (typeof strategy === 'function') {\n delay = strategy(attempt, baseDelay);\n } else {\n switch (strategy) {\n case 'fixed':\n delay = baseDelay;\n break;\n case 'linear':\n delay = baseDelay * attempt;\n break;\n case 'exponential':\n delay = baseDelay * Math.pow(2, attempt - 1);\n break;\n }\n }\n\n if (jitter) {\n const factor = typeof jitter === 'number' ? jitter : 1;\n delay = delay * (1 - factor * 0.5 + Math.random() * factor);\n }\n\n return Math.max(0, Math.floor(delay));\n}\n","// ============================================================================\n// FlowX — Promise Timeout with Cleanup\n// ============================================================================\nimport { AbortError, TimeoutError } from './types';\n\nexport interface TimeoutOptions<T = unknown> {\n /** Fallback value or factory when timeout occurs */\n fallback?: T | (() => T | Promise<T>);\n /** AbortSignal for external cancellation */\n signal?: AbortSignal;\n /** Custom error message */\n message?: string;\n}\n\n/**\n * Wrap an async operation with a timeout.\n *\n * @example\n * ```ts\n * const result = await withTimeout(() => fetch('/slow-api'), 5000);\n * ```\n */\nexport async function withTimeout<T>(\n fn: () => T | Promise<T>,\n ms: number,\n options?: TimeoutOptions<T>,\n): Promise<T> {\n if (ms <= 0) {\n throw new RangeError('Timeout must be > 0');\n }\n\n if (options?.signal?.aborted) {\n throw new AbortError();\n }\n\n const fnResult = fn(); // call synchronously so sync throws propagate\n\n return Promise.race([\n Promise.resolve(fnResult),\n new Promise<T>((_, reject) => {\n const timer = setTimeout(() => {\n if (options?.fallback !== undefined) {\n const fb = options.fallback;\n if (typeof fb === 'function') {\n try {\n const result = (fb as () => T | Promise<T>)();\n Promise.resolve(result).then(\n (v) => reject({ __resolved: true, value: v } as any),\n reject,\n );\n } catch (err) {\n reject(err);\n }\n } else {\n reject({ __resolved: true, value: fb } as any);\n }\n } else {\n reject(new TimeoutError(options?.message));\n }\n }, ms);\n\n // If signal aborts, reject the race\n if (options?.signal) {\n const onAbort = () => {\n clearTimeout(timer);\n reject(new AbortError());\n };\n options.signal.addEventListener('abort', onAbort, { once: true });\n }\n\n // Clean up timer when fn resolves\n Promise.resolve(fnResult).then(\n () => clearTimeout(timer),\n () => clearTimeout(timer),\n );\n }),\n ]).catch((err) => {\n // Handle the fallback resolution hack\n if (err && typeof err === 'object' && '__resolved' in err) {\n return err.value as T;\n }\n throw err;\n });\n}\n"]}
@@ -0,0 +1,77 @@
1
+ // src/types.ts
2
+ var FlowXError = class extends Error {
3
+ constructor(message, code) {
4
+ super(message);
5
+ this.name = "FlowXError";
6
+ this.code = code;
7
+ Object.setPrototypeOf(this, new.target.prototype);
8
+ }
9
+ };
10
+ var TimeoutError = class extends FlowXError {
11
+ constructor(message = "Operation timed out") {
12
+ super(message, "ERR_TIMEOUT");
13
+ this.name = "TimeoutError";
14
+ }
15
+ };
16
+ var AbortError = class extends FlowXError {
17
+ constructor(message = "Operation aborted") {
18
+ super(message, "ERR_ABORTED");
19
+ this.name = "AbortError";
20
+ }
21
+ };
22
+
23
+ // src/timeout.ts
24
+ async function withTimeout(fn, ms, options) {
25
+ if (ms <= 0) {
26
+ throw new RangeError("Timeout must be > 0");
27
+ }
28
+ if (options?.signal?.aborted) {
29
+ throw new AbortError();
30
+ }
31
+ const fnResult = fn();
32
+ return Promise.race([
33
+ Promise.resolve(fnResult),
34
+ new Promise((_, reject) => {
35
+ const timer = setTimeout(() => {
36
+ if (options?.fallback !== void 0) {
37
+ const fb = options.fallback;
38
+ if (typeof fb === "function") {
39
+ try {
40
+ const result = fb();
41
+ Promise.resolve(result).then(
42
+ (v) => reject({ __resolved: true, value: v }),
43
+ reject
44
+ );
45
+ } catch (err) {
46
+ reject(err);
47
+ }
48
+ } else {
49
+ reject({ __resolved: true, value: fb });
50
+ }
51
+ } else {
52
+ reject(new TimeoutError(options?.message));
53
+ }
54
+ }, ms);
55
+ if (options?.signal) {
56
+ const onAbort = () => {
57
+ clearTimeout(timer);
58
+ reject(new AbortError());
59
+ };
60
+ options.signal.addEventListener("abort", onAbort, { once: true });
61
+ }
62
+ Promise.resolve(fnResult).then(
63
+ () => clearTimeout(timer),
64
+ () => clearTimeout(timer)
65
+ );
66
+ })
67
+ ]).catch((err) => {
68
+ if (err && typeof err === "object" && "__resolved" in err) {
69
+ return err.value;
70
+ }
71
+ throw err;
72
+ });
73
+ }
74
+
75
+ export { withTimeout };
76
+ //# sourceMappingURL=timeout.mjs.map
77
+ //# sourceMappingURL=timeout.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/types.ts","../src/timeout.ts"],"names":[],"mappings":"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","file":"timeout.mjs","sourcesContent":["// ============================================================================\n// FlowX — Types & Error Hierarchy\n// ============================================================================\n\n/** Generic async function signature */\nexport type AsyncFn<TArgs extends any[] = any[], TReturn = any> = (\n ...args: TArgs\n) => Promise<TReturn>;\n\n/** Backoff strategy for retry/poll operations */\nexport type BackoffStrategy =\n | 'fixed'\n | 'linear'\n | 'exponential'\n | ((attempt: number, delay: number) => number);\n\n// ── Error Classes ───────────────────────────────────────────────────────────\n\n/** Base error class for all FlowX errors */\nexport class FlowXError extends Error {\n public readonly code: string;\n constructor(message: string, code: string) {\n super(message);\n this.name = 'FlowXError';\n this.code = code;\n Object.setPrototypeOf(this, new.target.prototype);\n }\n}\n\n/** Thrown when a promise exceeds its timeout */\nexport class TimeoutError extends FlowXError {\n constructor(message = 'Operation timed out') {\n super(message, 'ERR_TIMEOUT');\n this.name = 'TimeoutError';\n }\n}\n\n/** Thrown when a circuit breaker is open */\nexport class CircuitBreakerError extends FlowXError {\n constructor(message = 'Circuit breaker is open') {\n super(message, 'ERR_CIRCUIT_OPEN');\n this.name = 'CircuitBreakerError';\n }\n}\n\n/** Thrown when a bulkhead rejects due to capacity */\nexport class BulkheadError extends FlowXError {\n constructor(message = 'Bulkhead capacity exceeded') {\n super(message, 'ERR_BULKHEAD_FULL');\n this.name = 'BulkheadError';\n }\n}\n\n/** Thrown when an operation is aborted */\nexport class AbortError extends FlowXError {\n constructor(message = 'Operation aborted') {\n super(message, 'ERR_ABORTED');\n this.name = 'AbortError';\n }\n}\n\n/** Thrown when rate limit is exceeded */\nexport class RateLimitError extends FlowXError {\n constructor(message = 'Rate limit exceeded') {\n super(message, 'ERR_RATE_LIMIT');\n this.name = 'RateLimitError';\n }\n}\n\n// ── Utility Helpers ─────────────────────────────────────────────────────────\n\n/** Sleep for the specified duration, respecting AbortSignal */\nexport function sleep(ms: number, signal?: AbortSignal): Promise<void> {\n return new Promise<void>((resolve, reject) => {\n if (signal?.aborted) {\n reject(new AbortError());\n return;\n }\n\n let onAbort: (() => void) | undefined;\n\n const timer = setTimeout(() => {\n if (signal && onAbort) {\n signal.removeEventListener('abort', onAbort);\n }\n resolve();\n }, ms);\n\n if (signal) {\n onAbort = () => {\n clearTimeout(timer);\n reject(new AbortError());\n };\n signal.addEventListener('abort', onAbort, { once: true });\n }\n });\n}\n\n/** Calculate delay based on backoff strategy */\nexport function calculateDelay(\n attempt: number,\n baseDelay: number,\n strategy: BackoffStrategy,\n jitter: boolean | number = false,\n): number {\n let delay: number;\n\n if (typeof strategy === 'function') {\n delay = strategy(attempt, baseDelay);\n } else {\n switch (strategy) {\n case 'fixed':\n delay = baseDelay;\n break;\n case 'linear':\n delay = baseDelay * attempt;\n break;\n case 'exponential':\n delay = baseDelay * Math.pow(2, attempt - 1);\n break;\n }\n }\n\n if (jitter) {\n const factor = typeof jitter === 'number' ? jitter : 1;\n delay = delay * (1 - factor * 0.5 + Math.random() * factor);\n }\n\n return Math.max(0, Math.floor(delay));\n}\n","// ============================================================================\n// FlowX — Promise Timeout with Cleanup\n// ============================================================================\nimport { AbortError, TimeoutError } from './types';\n\nexport interface TimeoutOptions<T = unknown> {\n /** Fallback value or factory when timeout occurs */\n fallback?: T | (() => T | Promise<T>);\n /** AbortSignal for external cancellation */\n signal?: AbortSignal;\n /** Custom error message */\n message?: string;\n}\n\n/**\n * Wrap an async operation with a timeout.\n *\n * @example\n * ```ts\n * const result = await withTimeout(() => fetch('/slow-api'), 5000);\n * ```\n */\nexport async function withTimeout<T>(\n fn: () => T | Promise<T>,\n ms: number,\n options?: TimeoutOptions<T>,\n): Promise<T> {\n if (ms <= 0) {\n throw new RangeError('Timeout must be > 0');\n }\n\n if (options?.signal?.aborted) {\n throw new AbortError();\n }\n\n const fnResult = fn(); // call synchronously so sync throws propagate\n\n return Promise.race([\n Promise.resolve(fnResult),\n new Promise<T>((_, reject) => {\n const timer = setTimeout(() => {\n if (options?.fallback !== undefined) {\n const fb = options.fallback;\n if (typeof fb === 'function') {\n try {\n const result = (fb as () => T | Promise<T>)();\n Promise.resolve(result).then(\n (v) => reject({ __resolved: true, value: v } as any),\n reject,\n );\n } catch (err) {\n reject(err);\n }\n } else {\n reject({ __resolved: true, value: fb } as any);\n }\n } else {\n reject(new TimeoutError(options?.message));\n }\n }, ms);\n\n // If signal aborts, reject the race\n if (options?.signal) {\n const onAbort = () => {\n clearTimeout(timer);\n reject(new AbortError());\n };\n options.signal.addEventListener('abort', onAbort, { once: true });\n }\n\n // Clean up timer when fn resolves\n Promise.resolve(fnResult).then(\n () => clearTimeout(timer),\n () => clearTimeout(timer),\n );\n }),\n ]).catch((err) => {\n // Handle the fallback resolution hack\n if (err && typeof err === 'object' && '__resolved' in err) {\n return err.value as T;\n }\n throw err;\n });\n}\n"]}
@@ -0,0 +1,35 @@
1
+ /** Generic async function signature */
2
+ type AsyncFn<TArgs extends any[] = any[], TReturn = any> = (...args: TArgs) => Promise<TReturn>;
3
+ /** Backoff strategy for retry/poll operations */
4
+ type BackoffStrategy = 'fixed' | 'linear' | 'exponential' | ((attempt: number, delay: number) => number);
5
+ /** Base error class for all FlowX errors */
6
+ declare class FlowXError extends Error {
7
+ readonly code: string;
8
+ constructor(message: string, code: string);
9
+ }
10
+ /** Thrown when a promise exceeds its timeout */
11
+ declare class TimeoutError extends FlowXError {
12
+ constructor(message?: string);
13
+ }
14
+ /** Thrown when a circuit breaker is open */
15
+ declare class CircuitBreakerError extends FlowXError {
16
+ constructor(message?: string);
17
+ }
18
+ /** Thrown when a bulkhead rejects due to capacity */
19
+ declare class BulkheadError extends FlowXError {
20
+ constructor(message?: string);
21
+ }
22
+ /** Thrown when an operation is aborted */
23
+ declare class AbortError extends FlowXError {
24
+ constructor(message?: string);
25
+ }
26
+ /** Thrown when rate limit is exceeded */
27
+ declare class RateLimitError extends FlowXError {
28
+ constructor(message?: string);
29
+ }
30
+ /** Sleep for the specified duration, respecting AbortSignal */
31
+ declare function sleep(ms: number, signal?: AbortSignal): Promise<void>;
32
+ /** Calculate delay based on backoff strategy */
33
+ declare function calculateDelay(attempt: number, baseDelay: number, strategy: BackoffStrategy, jitter?: boolean | number): number;
34
+
35
+ export { AbortError as A, type BackoffStrategy as B, CircuitBreakerError as C, FlowXError as F, RateLimitError as R, TimeoutError as T, type AsyncFn as a, BulkheadError as b, calculateDelay as c, sleep as s };
@@ -0,0 +1,35 @@
1
+ /** Generic async function signature */
2
+ type AsyncFn<TArgs extends any[] = any[], TReturn = any> = (...args: TArgs) => Promise<TReturn>;
3
+ /** Backoff strategy for retry/poll operations */
4
+ type BackoffStrategy = 'fixed' | 'linear' | 'exponential' | ((attempt: number, delay: number) => number);
5
+ /** Base error class for all FlowX errors */
6
+ declare class FlowXError extends Error {
7
+ readonly code: string;
8
+ constructor(message: string, code: string);
9
+ }
10
+ /** Thrown when a promise exceeds its timeout */
11
+ declare class TimeoutError extends FlowXError {
12
+ constructor(message?: string);
13
+ }
14
+ /** Thrown when a circuit breaker is open */
15
+ declare class CircuitBreakerError extends FlowXError {
16
+ constructor(message?: string);
17
+ }
18
+ /** Thrown when a bulkhead rejects due to capacity */
19
+ declare class BulkheadError extends FlowXError {
20
+ constructor(message?: string);
21
+ }
22
+ /** Thrown when an operation is aborted */
23
+ declare class AbortError extends FlowXError {
24
+ constructor(message?: string);
25
+ }
26
+ /** Thrown when rate limit is exceeded */
27
+ declare class RateLimitError extends FlowXError {
28
+ constructor(message?: string);
29
+ }
30
+ /** Sleep for the specified duration, respecting AbortSignal */
31
+ declare function sleep(ms: number, signal?: AbortSignal): Promise<void>;
32
+ /** Calculate delay based on backoff strategy */
33
+ declare function calculateDelay(attempt: number, baseDelay: number, strategy: BackoffStrategy, jitter?: boolean | number): number;
34
+
35
+ export { AbortError as A, type BackoffStrategy as B, CircuitBreakerError as C, FlowXError as F, RateLimitError as R, TimeoutError as T, type AsyncFn as a, BulkheadError as b, calculateDelay as c, sleep as s };
package/package.json ADDED
@@ -0,0 +1,167 @@
1
+ {
2
+ "name": "flowx-control",
3
+ "version": "1.0.0",
4
+ "description": "Production-grade, zero-dependency TypeScript resilience & async flow control library. 100% test coverage. Retry with backoff, Circuit Breaker, Bulkhead, Rate Limiter, Priority Queue, Semaphore, Mutex, Debounce, Throttle, Timeout, Hedge, Poll, Batch, Pipeline — all tree-shakable & composable.",
5
+ "main": "dist/index.js",
6
+ "module": "dist/index.mjs",
7
+ "types": "dist/index.d.ts",
8
+ "exports": {
9
+ ".": {
10
+ "import": "./dist/index.mjs",
11
+ "require": "./dist/index.js",
12
+ "types": "./dist/index.d.ts"
13
+ },
14
+ "./retry": {
15
+ "import": "./dist/retry.mjs",
16
+ "require": "./dist/retry.js",
17
+ "types": "./dist/retry.d.ts"
18
+ },
19
+ "./circuit-breaker": {
20
+ "import": "./dist/circuit-breaker.mjs",
21
+ "require": "./dist/circuit-breaker.js",
22
+ "types": "./dist/circuit-breaker.d.ts"
23
+ },
24
+ "./bulkhead": {
25
+ "import": "./dist/bulkhead.mjs",
26
+ "require": "./dist/bulkhead.js",
27
+ "types": "./dist/bulkhead.d.ts"
28
+ },
29
+ "./fallback": {
30
+ "import": "./dist/fallback.mjs",
31
+ "require": "./dist/fallback.js",
32
+ "types": "./dist/fallback.d.ts"
33
+ },
34
+ "./hedge": {
35
+ "import": "./dist/hedge.mjs",
36
+ "require": "./dist/hedge.js",
37
+ "types": "./dist/hedge.d.ts"
38
+ },
39
+ "./timeout": {
40
+ "import": "./dist/timeout.mjs",
41
+ "require": "./dist/timeout.js",
42
+ "types": "./dist/timeout.d.ts"
43
+ },
44
+ "./semaphore": {
45
+ "import": "./dist/semaphore.mjs",
46
+ "require": "./dist/semaphore.js",
47
+ "types": "./dist/semaphore.d.ts"
48
+ },
49
+ "./mutex": {
50
+ "import": "./dist/mutex.mjs",
51
+ "require": "./dist/mutex.js",
52
+ "types": "./dist/mutex.d.ts"
53
+ },
54
+ "./queue": {
55
+ "import": "./dist/queue.mjs",
56
+ "require": "./dist/queue.js",
57
+ "types": "./dist/queue.d.ts"
58
+ },
59
+ "./rate-limit": {
60
+ "import": "./dist/rate-limit.mjs",
61
+ "require": "./dist/rate-limit.js",
62
+ "types": "./dist/rate-limit.d.ts"
63
+ },
64
+ "./debounce": {
65
+ "import": "./dist/debounce.mjs",
66
+ "require": "./dist/debounce.js",
67
+ "types": "./dist/debounce.d.ts"
68
+ },
69
+ "./throttle": {
70
+ "import": "./dist/throttle.mjs",
71
+ "require": "./dist/throttle.js",
72
+ "types": "./dist/throttle.d.ts"
73
+ },
74
+ "./batch": {
75
+ "import": "./dist/batch.mjs",
76
+ "require": "./dist/batch.js",
77
+ "types": "./dist/batch.d.ts"
78
+ },
79
+ "./pipeline": {
80
+ "import": "./dist/pipeline.mjs",
81
+ "require": "./dist/pipeline.js",
82
+ "types": "./dist/pipeline.d.ts"
83
+ },
84
+ "./poll": {
85
+ "import": "./dist/poll.mjs",
86
+ "require": "./dist/poll.js",
87
+ "types": "./dist/poll.d.ts"
88
+ },
89
+ "./deferred": {
90
+ "import": "./dist/deferred.mjs",
91
+ "require": "./dist/deferred.js",
92
+ "types": "./dist/deferred.d.ts"
93
+ },
94
+ "./memo": {
95
+ "import": "./dist/memo.mjs",
96
+ "require": "./dist/memo.js",
97
+ "types": "./dist/memo.d.ts"
98
+ }
99
+ },
100
+ "files": [
101
+ "dist",
102
+ "README.md",
103
+ "LICENSE",
104
+ "CHANGELOG.md"
105
+ ],
106
+ "scripts": {
107
+ "build": "tsup",
108
+ "test": "jest --coverage",
109
+ "test:ci": "jest --coverage",
110
+ "lint": "eslint src/ --ext .ts",
111
+ "format": "prettier --write \"src/**/*.ts\" \"__tests__/**/*.ts\"",
112
+ "typecheck": "tsc --noEmit"
113
+ },
114
+ "keywords": [
115
+ "async",
116
+ "retry",
117
+ "circuit-breaker",
118
+ "bulkhead",
119
+ "rate-limit",
120
+ "queue",
121
+ "semaphore",
122
+ "mutex",
123
+ "throttle",
124
+ "debounce",
125
+ "resilience",
126
+ "fault-tolerance",
127
+ "backoff",
128
+ "timeout",
129
+ "pipeline",
130
+ "concurrency",
131
+ "flow-control",
132
+ "typescript",
133
+ "zero-dependency",
134
+ "hedge",
135
+ "fallback",
136
+ "batch",
137
+ "polling",
138
+ "memoize",
139
+ "deferred",
140
+ "promise"
141
+ ],
142
+ "author": "Avinash Velu <avinashvelu03@gmail.com>",
143
+ "license": "MIT",
144
+ "repository": {
145
+ "type": "git",
146
+ "url": "git+https://github.com/Avinashvelu03/FlowX.git"
147
+ },
148
+ "bugs": {
149
+ "url": "https://github.com/Avinashvelu03/FlowX/issues"
150
+ },
151
+ "homepage": "https://github.com/Avinashvelu03/FlowX#readme",
152
+ "devDependencies": {
153
+ "@types/jest": "^29.5.14",
154
+ "@typescript-eslint/eslint-plugin": "^7.0.0",
155
+ "@typescript-eslint/parser": "^7.0.0",
156
+ "eslint": "^8.57.0",
157
+ "jest": "^29.7.0",
158
+ "prettier": "^3.3.0",
159
+ "ts-jest": "^29.2.0",
160
+ "tsup": "^8.3.0",
161
+ "typescript": "^5.6.0"
162
+ },
163
+ "engines": {
164
+ "node": ">=16.0.0"
165
+ },
166
+ "sideEffects": false
167
+ }