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,42 @@
1
+ /** A step in the pipeline */
2
+ type PipelineStep<TIn, TOut> = (input: TIn) => TOut | Promise<TOut>;
3
+ /**
4
+ * Compose multiple async functions into a single pipeline.
5
+ *
6
+ * @example
7
+ * ```ts
8
+ * const process = pipeline(
9
+ * (x: number) => x * 2,
10
+ * (x: number) => x + 1,
11
+ * (x: number) => String(x),
12
+ * );
13
+ * const result = await process(5); // "11"
14
+ * ```
15
+ */
16
+ declare function pipeline<A, B>(s1: PipelineStep<A, B>): (input: A) => Promise<B>;
17
+ declare function pipeline<A, B, C>(s1: PipelineStep<A, B>, s2: PipelineStep<B, C>): (input: A) => Promise<C>;
18
+ declare function pipeline<A, B, C, D>(s1: PipelineStep<A, B>, s2: PipelineStep<B, C>, s3: PipelineStep<C, D>): (input: A) => Promise<D>;
19
+ declare function pipeline<A, B, C, D, E>(s1: PipelineStep<A, B>, s2: PipelineStep<B, C>, s3: PipelineStep<C, D>, s4: PipelineStep<D, E>): (input: A) => Promise<E>;
20
+ declare function pipeline<A, B, C, D, E, F>(s1: PipelineStep<A, B>, s2: PipelineStep<B, C>, s3: PipelineStep<C, D>, s4: PipelineStep<D, E>, s5: PipelineStep<E, F>): (input: A) => Promise<F>;
21
+ declare function pipeline(...steps: Array<PipelineStep<any, any>>): (input: any) => Promise<any>;
22
+ /**
23
+ * Execute a value through a series of async transformation steps.
24
+ *
25
+ * @example
26
+ * ```ts
27
+ * const result = await pipe(
28
+ * 5,
29
+ * (x) => x * 2,
30
+ * (x) => x + 1,
31
+ * (x) => String(x),
32
+ * ); // "11"
33
+ * ```
34
+ */
35
+ declare function pipe<A, B>(input: A, s1: PipelineStep<A, B>): Promise<B>;
36
+ declare function pipe<A, B, C>(input: A, s1: PipelineStep<A, B>, s2: PipelineStep<B, C>): Promise<C>;
37
+ declare function pipe<A, B, C, D>(input: A, s1: PipelineStep<A, B>, s2: PipelineStep<B, C>, s3: PipelineStep<C, D>): Promise<D>;
38
+ declare function pipe<A, B, C, D, E>(input: A, s1: PipelineStep<A, B>, s2: PipelineStep<B, C>, s3: PipelineStep<C, D>, s4: PipelineStep<D, E>): Promise<E>;
39
+ declare function pipe<A, B, C, D, E, F>(input: A, s1: PipelineStep<A, B>, s2: PipelineStep<B, C>, s3: PipelineStep<C, D>, s4: PipelineStep<D, E>, s5: PipelineStep<E, F>): Promise<F>;
40
+ declare function pipe(input: any, ...steps: Array<PipelineStep<any, any>>): Promise<any>;
41
+
42
+ export { type PipelineStep, pipe, pipeline };
@@ -0,0 +1,42 @@
1
+ /** A step in the pipeline */
2
+ type PipelineStep<TIn, TOut> = (input: TIn) => TOut | Promise<TOut>;
3
+ /**
4
+ * Compose multiple async functions into a single pipeline.
5
+ *
6
+ * @example
7
+ * ```ts
8
+ * const process = pipeline(
9
+ * (x: number) => x * 2,
10
+ * (x: number) => x + 1,
11
+ * (x: number) => String(x),
12
+ * );
13
+ * const result = await process(5); // "11"
14
+ * ```
15
+ */
16
+ declare function pipeline<A, B>(s1: PipelineStep<A, B>): (input: A) => Promise<B>;
17
+ declare function pipeline<A, B, C>(s1: PipelineStep<A, B>, s2: PipelineStep<B, C>): (input: A) => Promise<C>;
18
+ declare function pipeline<A, B, C, D>(s1: PipelineStep<A, B>, s2: PipelineStep<B, C>, s3: PipelineStep<C, D>): (input: A) => Promise<D>;
19
+ declare function pipeline<A, B, C, D, E>(s1: PipelineStep<A, B>, s2: PipelineStep<B, C>, s3: PipelineStep<C, D>, s4: PipelineStep<D, E>): (input: A) => Promise<E>;
20
+ declare function pipeline<A, B, C, D, E, F>(s1: PipelineStep<A, B>, s2: PipelineStep<B, C>, s3: PipelineStep<C, D>, s4: PipelineStep<D, E>, s5: PipelineStep<E, F>): (input: A) => Promise<F>;
21
+ declare function pipeline(...steps: Array<PipelineStep<any, any>>): (input: any) => Promise<any>;
22
+ /**
23
+ * Execute a value through a series of async transformation steps.
24
+ *
25
+ * @example
26
+ * ```ts
27
+ * const result = await pipe(
28
+ * 5,
29
+ * (x) => x * 2,
30
+ * (x) => x + 1,
31
+ * (x) => String(x),
32
+ * ); // "11"
33
+ * ```
34
+ */
35
+ declare function pipe<A, B>(input: A, s1: PipelineStep<A, B>): Promise<B>;
36
+ declare function pipe<A, B, C>(input: A, s1: PipelineStep<A, B>, s2: PipelineStep<B, C>): Promise<C>;
37
+ declare function pipe<A, B, C, D>(input: A, s1: PipelineStep<A, B>, s2: PipelineStep<B, C>, s3: PipelineStep<C, D>): Promise<D>;
38
+ declare function pipe<A, B, C, D, E>(input: A, s1: PipelineStep<A, B>, s2: PipelineStep<B, C>, s3: PipelineStep<C, D>, s4: PipelineStep<D, E>): Promise<E>;
39
+ declare function pipe<A, B, C, D, E, F>(input: A, s1: PipelineStep<A, B>, s2: PipelineStep<B, C>, s3: PipelineStep<C, D>, s4: PipelineStep<D, E>, s5: PipelineStep<E, F>): Promise<F>;
40
+ declare function pipe(input: any, ...steps: Array<PipelineStep<any, any>>): Promise<any>;
41
+
42
+ export { type PipelineStep, pipe, pipeline };
@@ -0,0 +1,30 @@
1
+ 'use strict';
2
+
3
+ // src/pipeline.ts
4
+ function pipeline(...steps) {
5
+ if (steps.length === 0) {
6
+ throw new Error("pipeline requires at least one step");
7
+ }
8
+ return async (input) => {
9
+ let current = input;
10
+ for (const step of steps) {
11
+ current = await step(current);
12
+ }
13
+ return current;
14
+ };
15
+ }
16
+ async function pipe(input, ...steps) {
17
+ if (steps.length === 0) {
18
+ throw new Error("pipe requires at least one step");
19
+ }
20
+ let current = input;
21
+ for (const step of steps) {
22
+ current = await step(current);
23
+ }
24
+ return current;
25
+ }
26
+
27
+ exports.pipe = pipe;
28
+ exports.pipeline = pipeline;
29
+ //# sourceMappingURL=pipeline.js.map
30
+ //# sourceMappingURL=pipeline.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/pipeline.ts"],"names":[],"mappings":";;;AA4CO,SAAS,YAAY,KAAA,EAAoE;AAC9F,EAAA,IAAI,KAAA,CAAM,WAAW,CAAA,EAAG;AACtB,IAAA,MAAM,IAAI,MAAM,qCAAqC,CAAA;AAAA,EACvD;AAEA,EAAA,OAAO,OAAO,KAAA,KAAe;AAC3B,IAAA,IAAI,OAAA,GAAU,KAAA;AACd,IAAA,KAAA,MAAW,QAAQ,KAAA,EAAO;AACxB,MAAA,OAAA,GAAU,MAAM,KAAK,OAAO,CAAA;AAAA,IAC9B;AACA,IAAA,OAAO,OAAA;AAAA,EACT,CAAA;AACF;AA2CA,eAAsB,IAAA,CAAK,UAAe,KAAA,EAAoD;AAC5F,EAAA,IAAI,KAAA,CAAM,WAAW,CAAA,EAAG;AACtB,IAAA,MAAM,IAAI,MAAM,iCAAiC,CAAA;AAAA,EACnD;AAEA,EAAA,IAAI,OAAA,GAAU,KAAA;AACd,EAAA,KAAA,MAAW,QAAQ,KAAA,EAAO;AACxB,IAAA,OAAA,GAAU,MAAM,KAAK,OAAO,CAAA;AAAA,EAC9B;AACA,EAAA,OAAO,OAAA;AACT","file":"pipeline.js","sourcesContent":["// ============================================================================\n// FlowX — Async Pipeline Composition\n// ============================================================================\n\n/** A step in the pipeline */\nexport type PipelineStep<TIn, TOut> = (input: TIn) => TOut | Promise<TOut>;\n\n/**\n * Compose multiple async functions into a single pipeline.\n *\n * @example\n * ```ts\n * const process = pipeline(\n * (x: number) => x * 2,\n * (x: number) => x + 1,\n * (x: number) => String(x),\n * );\n * const result = await process(5); // \"11\"\n * ```\n */\nexport function pipeline<A, B>(s1: PipelineStep<A, B>): (input: A) => Promise<B>;\nexport function pipeline<A, B, C>(\n s1: PipelineStep<A, B>,\n s2: PipelineStep<B, C>,\n): (input: A) => Promise<C>;\nexport function pipeline<A, B, C, D>(\n s1: PipelineStep<A, B>,\n s2: PipelineStep<B, C>,\n s3: PipelineStep<C, D>,\n): (input: A) => Promise<D>;\nexport function pipeline<A, B, C, D, E>(\n s1: PipelineStep<A, B>,\n s2: PipelineStep<B, C>,\n s3: PipelineStep<C, D>,\n s4: PipelineStep<D, E>,\n): (input: A) => Promise<E>;\nexport function pipeline<A, B, C, D, E, F>(\n s1: PipelineStep<A, B>,\n s2: PipelineStep<B, C>,\n s3: PipelineStep<C, D>,\n s4: PipelineStep<D, E>,\n s5: PipelineStep<E, F>,\n): (input: A) => Promise<F>;\nexport function pipeline(...steps: Array<PipelineStep<any, any>>): (input: any) => Promise<any>;\nexport function pipeline(...steps: Array<PipelineStep<any, any>>): (input: any) => Promise<any> {\n if (steps.length === 0) {\n throw new Error('pipeline requires at least one step');\n }\n\n return async (input: any) => {\n let current = input;\n for (const step of steps) {\n current = await step(current);\n }\n return current;\n };\n}\n\n/**\n * Execute a value through a series of async transformation steps.\n *\n * @example\n * ```ts\n * const result = await pipe(\n * 5,\n * (x) => x * 2,\n * (x) => x + 1,\n * (x) => String(x),\n * ); // \"11\"\n * ```\n */\nexport async function pipe<A, B>(input: A, s1: PipelineStep<A, B>): Promise<B>;\nexport async function pipe<A, B, C>(\n input: A,\n s1: PipelineStep<A, B>,\n s2: PipelineStep<B, C>,\n): Promise<C>;\nexport async function pipe<A, B, C, D>(\n input: A,\n s1: PipelineStep<A, B>,\n s2: PipelineStep<B, C>,\n s3: PipelineStep<C, D>,\n): Promise<D>;\nexport async function pipe<A, B, C, D, E>(\n input: A,\n s1: PipelineStep<A, B>,\n s2: PipelineStep<B, C>,\n s3: PipelineStep<C, D>,\n s4: PipelineStep<D, E>,\n): Promise<E>;\nexport async function pipe<A, B, C, D, E, F>(\n input: A,\n s1: PipelineStep<A, B>,\n s2: PipelineStep<B, C>,\n s3: PipelineStep<C, D>,\n s4: PipelineStep<D, E>,\n s5: PipelineStep<E, F>,\n): Promise<F>;\nexport async function pipe(input: any, ...steps: Array<PipelineStep<any, any>>): Promise<any>;\nexport async function pipe(input: any, ...steps: Array<PipelineStep<any, any>>): Promise<any> {\n if (steps.length === 0) {\n throw new Error('pipe requires at least one step');\n }\n\n let current = input;\n for (const step of steps) {\n current = await step(current);\n }\n return current;\n}\n"]}
@@ -0,0 +1,27 @@
1
+ // src/pipeline.ts
2
+ function pipeline(...steps) {
3
+ if (steps.length === 0) {
4
+ throw new Error("pipeline requires at least one step");
5
+ }
6
+ return async (input) => {
7
+ let current = input;
8
+ for (const step of steps) {
9
+ current = await step(current);
10
+ }
11
+ return current;
12
+ };
13
+ }
14
+ async function pipe(input, ...steps) {
15
+ if (steps.length === 0) {
16
+ throw new Error("pipe requires at least one step");
17
+ }
18
+ let current = input;
19
+ for (const step of steps) {
20
+ current = await step(current);
21
+ }
22
+ return current;
23
+ }
24
+
25
+ export { pipe, pipeline };
26
+ //# sourceMappingURL=pipeline.mjs.map
27
+ //# sourceMappingURL=pipeline.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/pipeline.ts"],"names":[],"mappings":";AA4CO,SAAS,YAAY,KAAA,EAAoE;AAC9F,EAAA,IAAI,KAAA,CAAM,WAAW,CAAA,EAAG;AACtB,IAAA,MAAM,IAAI,MAAM,qCAAqC,CAAA;AAAA,EACvD;AAEA,EAAA,OAAO,OAAO,KAAA,KAAe;AAC3B,IAAA,IAAI,OAAA,GAAU,KAAA;AACd,IAAA,KAAA,MAAW,QAAQ,KAAA,EAAO;AACxB,MAAA,OAAA,GAAU,MAAM,KAAK,OAAO,CAAA;AAAA,IAC9B;AACA,IAAA,OAAO,OAAA;AAAA,EACT,CAAA;AACF;AA2CA,eAAsB,IAAA,CAAK,UAAe,KAAA,EAAoD;AAC5F,EAAA,IAAI,KAAA,CAAM,WAAW,CAAA,EAAG;AACtB,IAAA,MAAM,IAAI,MAAM,iCAAiC,CAAA;AAAA,EACnD;AAEA,EAAA,IAAI,OAAA,GAAU,KAAA;AACd,EAAA,KAAA,MAAW,QAAQ,KAAA,EAAO;AACxB,IAAA,OAAA,GAAU,MAAM,KAAK,OAAO,CAAA;AAAA,EAC9B;AACA,EAAA,OAAO,OAAA;AACT","file":"pipeline.mjs","sourcesContent":["// ============================================================================\n// FlowX — Async Pipeline Composition\n// ============================================================================\n\n/** A step in the pipeline */\nexport type PipelineStep<TIn, TOut> = (input: TIn) => TOut | Promise<TOut>;\n\n/**\n * Compose multiple async functions into a single pipeline.\n *\n * @example\n * ```ts\n * const process = pipeline(\n * (x: number) => x * 2,\n * (x: number) => x + 1,\n * (x: number) => String(x),\n * );\n * const result = await process(5); // \"11\"\n * ```\n */\nexport function pipeline<A, B>(s1: PipelineStep<A, B>): (input: A) => Promise<B>;\nexport function pipeline<A, B, C>(\n s1: PipelineStep<A, B>,\n s2: PipelineStep<B, C>,\n): (input: A) => Promise<C>;\nexport function pipeline<A, B, C, D>(\n s1: PipelineStep<A, B>,\n s2: PipelineStep<B, C>,\n s3: PipelineStep<C, D>,\n): (input: A) => Promise<D>;\nexport function pipeline<A, B, C, D, E>(\n s1: PipelineStep<A, B>,\n s2: PipelineStep<B, C>,\n s3: PipelineStep<C, D>,\n s4: PipelineStep<D, E>,\n): (input: A) => Promise<E>;\nexport function pipeline<A, B, C, D, E, F>(\n s1: PipelineStep<A, B>,\n s2: PipelineStep<B, C>,\n s3: PipelineStep<C, D>,\n s4: PipelineStep<D, E>,\n s5: PipelineStep<E, F>,\n): (input: A) => Promise<F>;\nexport function pipeline(...steps: Array<PipelineStep<any, any>>): (input: any) => Promise<any>;\nexport function pipeline(...steps: Array<PipelineStep<any, any>>): (input: any) => Promise<any> {\n if (steps.length === 0) {\n throw new Error('pipeline requires at least one step');\n }\n\n return async (input: any) => {\n let current = input;\n for (const step of steps) {\n current = await step(current);\n }\n return current;\n };\n}\n\n/**\n * Execute a value through a series of async transformation steps.\n *\n * @example\n * ```ts\n * const result = await pipe(\n * 5,\n * (x) => x * 2,\n * (x) => x + 1,\n * (x) => String(x),\n * ); // \"11\"\n * ```\n */\nexport async function pipe<A, B>(input: A, s1: PipelineStep<A, B>): Promise<B>;\nexport async function pipe<A, B, C>(\n input: A,\n s1: PipelineStep<A, B>,\n s2: PipelineStep<B, C>,\n): Promise<C>;\nexport async function pipe<A, B, C, D>(\n input: A,\n s1: PipelineStep<A, B>,\n s2: PipelineStep<B, C>,\n s3: PipelineStep<C, D>,\n): Promise<D>;\nexport async function pipe<A, B, C, D, E>(\n input: A,\n s1: PipelineStep<A, B>,\n s2: PipelineStep<B, C>,\n s3: PipelineStep<C, D>,\n s4: PipelineStep<D, E>,\n): Promise<E>;\nexport async function pipe<A, B, C, D, E, F>(\n input: A,\n s1: PipelineStep<A, B>,\n s2: PipelineStep<B, C>,\n s3: PipelineStep<C, D>,\n s4: PipelineStep<D, E>,\n s5: PipelineStep<E, F>,\n): Promise<F>;\nexport async function pipe(input: any, ...steps: Array<PipelineStep<any, any>>): Promise<any>;\nexport async function pipe(input: any, ...steps: Array<PipelineStep<any, any>>): Promise<any> {\n if (steps.length === 0) {\n throw new Error('pipe requires at least one step');\n }\n\n let current = input;\n for (const step of steps) {\n current = await step(current);\n }\n return current;\n}\n"]}
@@ -0,0 +1,35 @@
1
+ import { B as BackoffStrategy } from './types-BsCO2J40.mjs';
2
+
3
+ interface PollOptions<T> {
4
+ /** Polling interval in ms (default: 1000) */
5
+ interval?: number;
6
+ /** Condition to stop polling — return true to resolve */
7
+ until?: (result: T) => boolean;
8
+ /** Maximum number of poll attempts (default: Infinity) */
9
+ maxAttempts?: number;
10
+ /** Backoff strategy for interval (default: 'fixed') */
11
+ backoff?: BackoffStrategy;
12
+ /** AbortSignal for cancellation */
13
+ signal?: AbortSignal;
14
+ }
15
+ interface PollController<T> {
16
+ /** Promise that resolves with the final result */
17
+ result: Promise<T>;
18
+ /** Stop polling early */
19
+ stop: () => void;
20
+ }
21
+ /**
22
+ * Poll an async function until a condition is met.
23
+ *
24
+ * @example
25
+ * ```ts
26
+ * const { result } = poll(
27
+ * () => checkJobStatus(jobId),
28
+ * { until: (status) => status === 'done', interval: 2000 },
29
+ * );
30
+ * const finalStatus = await result;
31
+ * ```
32
+ */
33
+ declare function poll<T>(fn: () => T | Promise<T>, options?: PollOptions<T>): PollController<T>;
34
+
35
+ export { type PollController, type PollOptions, poll };
package/dist/poll.d.ts ADDED
@@ -0,0 +1,35 @@
1
+ import { B as BackoffStrategy } from './types-BsCO2J40.js';
2
+
3
+ interface PollOptions<T> {
4
+ /** Polling interval in ms (default: 1000) */
5
+ interval?: number;
6
+ /** Condition to stop polling — return true to resolve */
7
+ until?: (result: T) => boolean;
8
+ /** Maximum number of poll attempts (default: Infinity) */
9
+ maxAttempts?: number;
10
+ /** Backoff strategy for interval (default: 'fixed') */
11
+ backoff?: BackoffStrategy;
12
+ /** AbortSignal for cancellation */
13
+ signal?: AbortSignal;
14
+ }
15
+ interface PollController<T> {
16
+ /** Promise that resolves with the final result */
17
+ result: Promise<T>;
18
+ /** Stop polling early */
19
+ stop: () => void;
20
+ }
21
+ /**
22
+ * Poll an async function until a condition is met.
23
+ *
24
+ * @example
25
+ * ```ts
26
+ * const { result } = poll(
27
+ * () => checkJobStatus(jobId),
28
+ * { until: (status) => status === 'done', interval: 2000 },
29
+ * );
30
+ * const finalStatus = await result;
31
+ * ```
32
+ */
33
+ declare function poll<T>(fn: () => T | Promise<T>, options?: PollOptions<T>): PollController<T>;
34
+
35
+ export { type PollController, type PollOptions, poll };
package/dist/poll.js ADDED
@@ -0,0 +1,111 @@
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 AbortError = class extends FlowXError {
13
+ constructor(message = "Operation aborted") {
14
+ super(message, "ERR_ABORTED");
15
+ this.name = "AbortError";
16
+ }
17
+ };
18
+ function sleep(ms, signal) {
19
+ return new Promise((resolve, reject) => {
20
+ if (signal?.aborted) {
21
+ reject(new AbortError());
22
+ return;
23
+ }
24
+ let onAbort;
25
+ const timer = setTimeout(() => {
26
+ if (signal && onAbort) {
27
+ signal.removeEventListener("abort", onAbort);
28
+ }
29
+ resolve();
30
+ }, ms);
31
+ if (signal) {
32
+ onAbort = () => {
33
+ clearTimeout(timer);
34
+ reject(new AbortError());
35
+ };
36
+ signal.addEventListener("abort", onAbort, { once: true });
37
+ }
38
+ });
39
+ }
40
+ function calculateDelay(attempt, baseDelay, strategy, jitter = false) {
41
+ let delay;
42
+ if (typeof strategy === "function") {
43
+ delay = strategy(attempt, baseDelay);
44
+ } else {
45
+ switch (strategy) {
46
+ case "fixed":
47
+ delay = baseDelay;
48
+ break;
49
+ case "linear":
50
+ delay = baseDelay * attempt;
51
+ break;
52
+ case "exponential":
53
+ delay = baseDelay * Math.pow(2, attempt - 1);
54
+ break;
55
+ }
56
+ }
57
+ if (jitter) {
58
+ const factor = typeof jitter === "number" ? jitter : 1;
59
+ delay = delay * (1 - factor * 0.5 + Math.random() * factor);
60
+ }
61
+ return Math.max(0, Math.floor(delay));
62
+ }
63
+
64
+ // src/poll.ts
65
+ function poll(fn, options) {
66
+ const {
67
+ interval = 1e3,
68
+ until,
69
+ maxAttempts = Infinity,
70
+ backoff = "fixed",
71
+ signal
72
+ } = options ?? {};
73
+ if (interval < 0) throw new RangeError("interval must be >= 0");
74
+ let stopped = false;
75
+ let rejectFn = null;
76
+ const result = (async () => {
77
+ for (let attempt = 1; attempt <= maxAttempts; attempt++) {
78
+ if (stopped || signal?.aborted) {
79
+ throw new AbortError("Polling stopped");
80
+ }
81
+ const value = await fn();
82
+ if (until ? until(value) : true) {
83
+ return value;
84
+ }
85
+ if (attempt < maxAttempts) {
86
+ const waitTime = calculateDelay(attempt, interval, backoff);
87
+ await sleep(waitTime, signal).catch((err) => {
88
+ if (stopped) throw new AbortError("Polling stopped");
89
+ throw err;
90
+ });
91
+ }
92
+ }
93
+ throw new Error("Polling exceeded maximum attempts");
94
+ })();
95
+ const wrappedResult = new Promise((resolve, reject) => {
96
+ rejectFn = reject;
97
+ result.then(resolve, reject);
98
+ });
99
+ function stop() {
100
+ stopped = true;
101
+ rejectFn?.(new AbortError("Polling stopped"));
102
+ }
103
+ return {
104
+ result: wrappedResult,
105
+ stop
106
+ };
107
+ }
108
+
109
+ exports.poll = poll;
110
+ //# sourceMappingURL=poll.js.map
111
+ //# sourceMappingURL=poll.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/types.ts","../src/poll.ts"],"names":[],"mappings":"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","file":"poll.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 — Polling with Backoff\n// ============================================================================\nimport { AbortError, BackoffStrategy, calculateDelay, sleep } from './types';\n\nexport interface PollOptions<T> {\n /** Polling interval in ms (default: 1000) */\n interval?: number;\n /** Condition to stop polling — return true to resolve */\n until?: (result: T) => boolean;\n /** Maximum number of poll attempts (default: Infinity) */\n maxAttempts?: number;\n /** Backoff strategy for interval (default: 'fixed') */\n backoff?: BackoffStrategy;\n /** AbortSignal for cancellation */\n signal?: AbortSignal;\n}\n\nexport interface PollController<T> {\n /** Promise that resolves with the final result */\n result: Promise<T>;\n /** Stop polling early */\n stop: () => void;\n}\n\n/**\n * Poll an async function until a condition is met.\n *\n * @example\n * ```ts\n * const { result } = poll(\n * () => checkJobStatus(jobId),\n * { until: (status) => status === 'done', interval: 2000 },\n * );\n * const finalStatus = await result;\n * ```\n */\nexport function poll<T>(fn: () => T | Promise<T>, options?: PollOptions<T>): PollController<T> {\n const {\n interval = 1000,\n until,\n maxAttempts = Infinity,\n backoff = 'fixed',\n signal,\n } = options ?? {};\n\n if (interval < 0) throw new RangeError('interval must be >= 0');\n\n let stopped = false;\n let rejectFn: ((error: Error) => void) | null = null;\n\n const result = (async (): Promise<T> => {\n for (let attempt = 1; attempt <= maxAttempts; attempt++) {\n if (stopped || signal?.aborted) {\n throw new AbortError('Polling stopped');\n }\n\n const value = await fn();\n\n if (until ? until(value) : true) {\n return value;\n }\n\n if (attempt < maxAttempts) {\n const waitTime = calculateDelay(attempt, interval, backoff);\n await sleep(waitTime, signal).catch((err) => {\n /* istanbul ignore if -- stop() doesn't abort sleep; this is a defensive guard */\n if (stopped) throw new AbortError('Polling stopped');\n throw err;\n });\n }\n }\n\n throw new Error('Polling exceeded maximum attempts');\n })();\n\n // Capture the reject function for external stopping\n const wrappedResult = new Promise<T>((resolve, reject) => {\n rejectFn = reject;\n result.then(resolve, reject);\n });\n\n function stop(): void {\n stopped = true;\n rejectFn?.(new AbortError('Polling stopped'));\n }\n\n return {\n result: wrappedResult,\n stop,\n };\n}\n"]}
package/dist/poll.mjs ADDED
@@ -0,0 +1,109 @@
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 AbortError = class extends FlowXError {
11
+ constructor(message = "Operation aborted") {
12
+ super(message, "ERR_ABORTED");
13
+ this.name = "AbortError";
14
+ }
15
+ };
16
+ function sleep(ms, signal) {
17
+ return new Promise((resolve, reject) => {
18
+ if (signal?.aborted) {
19
+ reject(new AbortError());
20
+ return;
21
+ }
22
+ let onAbort;
23
+ const timer = setTimeout(() => {
24
+ if (signal && onAbort) {
25
+ signal.removeEventListener("abort", onAbort);
26
+ }
27
+ resolve();
28
+ }, ms);
29
+ if (signal) {
30
+ onAbort = () => {
31
+ clearTimeout(timer);
32
+ reject(new AbortError());
33
+ };
34
+ signal.addEventListener("abort", onAbort, { once: true });
35
+ }
36
+ });
37
+ }
38
+ function calculateDelay(attempt, baseDelay, strategy, jitter = false) {
39
+ let delay;
40
+ if (typeof strategy === "function") {
41
+ delay = strategy(attempt, baseDelay);
42
+ } else {
43
+ switch (strategy) {
44
+ case "fixed":
45
+ delay = baseDelay;
46
+ break;
47
+ case "linear":
48
+ delay = baseDelay * attempt;
49
+ break;
50
+ case "exponential":
51
+ delay = baseDelay * Math.pow(2, attempt - 1);
52
+ break;
53
+ }
54
+ }
55
+ if (jitter) {
56
+ const factor = typeof jitter === "number" ? jitter : 1;
57
+ delay = delay * (1 - factor * 0.5 + Math.random() * factor);
58
+ }
59
+ return Math.max(0, Math.floor(delay));
60
+ }
61
+
62
+ // src/poll.ts
63
+ function poll(fn, options) {
64
+ const {
65
+ interval = 1e3,
66
+ until,
67
+ maxAttempts = Infinity,
68
+ backoff = "fixed",
69
+ signal
70
+ } = options ?? {};
71
+ if (interval < 0) throw new RangeError("interval must be >= 0");
72
+ let stopped = false;
73
+ let rejectFn = null;
74
+ const result = (async () => {
75
+ for (let attempt = 1; attempt <= maxAttempts; attempt++) {
76
+ if (stopped || signal?.aborted) {
77
+ throw new AbortError("Polling stopped");
78
+ }
79
+ const value = await fn();
80
+ if (until ? until(value) : true) {
81
+ return value;
82
+ }
83
+ if (attempt < maxAttempts) {
84
+ const waitTime = calculateDelay(attempt, interval, backoff);
85
+ await sleep(waitTime, signal).catch((err) => {
86
+ if (stopped) throw new AbortError("Polling stopped");
87
+ throw err;
88
+ });
89
+ }
90
+ }
91
+ throw new Error("Polling exceeded maximum attempts");
92
+ })();
93
+ const wrappedResult = new Promise((resolve, reject) => {
94
+ rejectFn = reject;
95
+ result.then(resolve, reject);
96
+ });
97
+ function stop() {
98
+ stopped = true;
99
+ rejectFn?.(new AbortError("Polling stopped"));
100
+ }
101
+ return {
102
+ result: wrappedResult,
103
+ stop
104
+ };
105
+ }
106
+
107
+ export { poll };
108
+ //# sourceMappingURL=poll.mjs.map
109
+ //# sourceMappingURL=poll.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/types.ts","../src/poll.ts"],"names":[],"mappings":"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","file":"poll.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 — Polling with Backoff\n// ============================================================================\nimport { AbortError, BackoffStrategy, calculateDelay, sleep } from './types';\n\nexport interface PollOptions<T> {\n /** Polling interval in ms (default: 1000) */\n interval?: number;\n /** Condition to stop polling — return true to resolve */\n until?: (result: T) => boolean;\n /** Maximum number of poll attempts (default: Infinity) */\n maxAttempts?: number;\n /** Backoff strategy for interval (default: 'fixed') */\n backoff?: BackoffStrategy;\n /** AbortSignal for cancellation */\n signal?: AbortSignal;\n}\n\nexport interface PollController<T> {\n /** Promise that resolves with the final result */\n result: Promise<T>;\n /** Stop polling early */\n stop: () => void;\n}\n\n/**\n * Poll an async function until a condition is met.\n *\n * @example\n * ```ts\n * const { result } = poll(\n * () => checkJobStatus(jobId),\n * { until: (status) => status === 'done', interval: 2000 },\n * );\n * const finalStatus = await result;\n * ```\n */\nexport function poll<T>(fn: () => T | Promise<T>, options?: PollOptions<T>): PollController<T> {\n const {\n interval = 1000,\n until,\n maxAttempts = Infinity,\n backoff = 'fixed',\n signal,\n } = options ?? {};\n\n if (interval < 0) throw new RangeError('interval must be >= 0');\n\n let stopped = false;\n let rejectFn: ((error: Error) => void) | null = null;\n\n const result = (async (): Promise<T> => {\n for (let attempt = 1; attempt <= maxAttempts; attempt++) {\n if (stopped || signal?.aborted) {\n throw new AbortError('Polling stopped');\n }\n\n const value = await fn();\n\n if (until ? until(value) : true) {\n return value;\n }\n\n if (attempt < maxAttempts) {\n const waitTime = calculateDelay(attempt, interval, backoff);\n await sleep(waitTime, signal).catch((err) => {\n /* istanbul ignore if -- stop() doesn't abort sleep; this is a defensive guard */\n if (stopped) throw new AbortError('Polling stopped');\n throw err;\n });\n }\n }\n\n throw new Error('Polling exceeded maximum attempts');\n })();\n\n // Capture the reject function for external stopping\n const wrappedResult = new Promise<T>((resolve, reject) => {\n rejectFn = reject;\n result.then(resolve, reject);\n });\n\n function stop(): void {\n stopped = true;\n rejectFn?.(new AbortError('Polling stopped'));\n }\n\n return {\n result: wrappedResult,\n stop,\n };\n}\n"]}
@@ -0,0 +1,47 @@
1
+ interface QueueOptions {
2
+ /** Maximum concurrent tasks (default: 1) */
3
+ concurrency?: number;
4
+ /** Start processing immediately (default: true) */
5
+ autoStart?: boolean;
6
+ /** Per-task timeout in ms (0 = no timeout) */
7
+ timeout?: number;
8
+ }
9
+ interface QueueAddOptions {
10
+ /** Task priority — lower number = higher priority (default: 0) */
11
+ priority?: number;
12
+ }
13
+ interface AsyncQueue {
14
+ /** Add a task to the queue */
15
+ add: <T>(fn: () => Promise<T>, options?: QueueAddOptions) => Promise<T>;
16
+ /** Add multiple tasks and return all results */
17
+ addAll: <T>(fns: Array<() => Promise<T>>, options?: QueueAddOptions) => Promise<T[]>;
18
+ /** Pause processing */
19
+ pause: () => void;
20
+ /** Resume processing */
21
+ resume: () => void;
22
+ /** Clear all pending tasks */
23
+ clear: () => void;
24
+ /** Wait until the queue is empty */
25
+ onEmpty: () => Promise<void>;
26
+ /** Wait until the queue is idle (empty + no active tasks) */
27
+ onIdle: () => Promise<void>;
28
+ /** Number of pending tasks */
29
+ readonly size: number;
30
+ /** Number of active tasks */
31
+ readonly pending: number;
32
+ /** Whether the queue is paused */
33
+ readonly isPaused: boolean;
34
+ }
35
+ /**
36
+ * Create a priority async queue with concurrency control.
37
+ *
38
+ * @example
39
+ * ```ts
40
+ * const queue = createQueue({ concurrency: 3 });
41
+ * const result = await queue.add(() => fetch('/api'), { priority: 1 });
42
+ * await queue.onIdle();
43
+ * ```
44
+ */
45
+ declare function createQueue(options?: QueueOptions): AsyncQueue;
46
+
47
+ export { type AsyncQueue, type QueueAddOptions, type QueueOptions, createQueue };
@@ -0,0 +1,47 @@
1
+ interface QueueOptions {
2
+ /** Maximum concurrent tasks (default: 1) */
3
+ concurrency?: number;
4
+ /** Start processing immediately (default: true) */
5
+ autoStart?: boolean;
6
+ /** Per-task timeout in ms (0 = no timeout) */
7
+ timeout?: number;
8
+ }
9
+ interface QueueAddOptions {
10
+ /** Task priority — lower number = higher priority (default: 0) */
11
+ priority?: number;
12
+ }
13
+ interface AsyncQueue {
14
+ /** Add a task to the queue */
15
+ add: <T>(fn: () => Promise<T>, options?: QueueAddOptions) => Promise<T>;
16
+ /** Add multiple tasks and return all results */
17
+ addAll: <T>(fns: Array<() => Promise<T>>, options?: QueueAddOptions) => Promise<T[]>;
18
+ /** Pause processing */
19
+ pause: () => void;
20
+ /** Resume processing */
21
+ resume: () => void;
22
+ /** Clear all pending tasks */
23
+ clear: () => void;
24
+ /** Wait until the queue is empty */
25
+ onEmpty: () => Promise<void>;
26
+ /** Wait until the queue is idle (empty + no active tasks) */
27
+ onIdle: () => Promise<void>;
28
+ /** Number of pending tasks */
29
+ readonly size: number;
30
+ /** Number of active tasks */
31
+ readonly pending: number;
32
+ /** Whether the queue is paused */
33
+ readonly isPaused: boolean;
34
+ }
35
+ /**
36
+ * Create a priority async queue with concurrency control.
37
+ *
38
+ * @example
39
+ * ```ts
40
+ * const queue = createQueue({ concurrency: 3 });
41
+ * const result = await queue.add(() => fetch('/api'), { priority: 1 });
42
+ * await queue.onIdle();
43
+ * ```
44
+ */
45
+ declare function createQueue(options?: QueueOptions): AsyncQueue;
46
+
47
+ export { type AsyncQueue, type QueueAddOptions, type QueueOptions, createQueue };