@praxisjs/concurrent 0.2.2 → 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/CHANGELOG.md CHANGED
@@ -1,5 +1,61 @@
1
1
  # @praxisjs/concurrent
2
2
 
3
+ ## 1.0.0
4
+
5
+ ### Major Changes
6
+
7
+ - 3372878: Migrate all packages from functional APIs to a decorator-first design.
8
+
9
+ **`@praxisjs/core`**
10
+
11
+ - Added `Composable` abstract base class for building class-based composables
12
+ - Removed `resource`, `createResource`, `Resource`, `ResourceStatus`, `ResourceOptions` from public exports — use `@Resource` from `@praxisjs/decorators` instead
13
+
14
+ **`@praxisjs/motion`**
15
+
16
+ - Replaced `useMotion`, `tween`, `spring`, `createTransition`, `Animate`, `easings`, `resolveEasing` with `@Tween` and `@Spring` decorators
17
+
18
+ **`@praxisjs/di`**
19
+
20
+ - Replaced `useService` and `createScope` with a `@Scope` decorator
21
+ - Renamed exported type `Scope` to `ScopeType` to free the name for the new decorator
22
+
23
+ **`@praxisjs/fsm`**
24
+
25
+ - Removed `createMachine` — use the `@StateMachine` and `@Transition` decorators directly
26
+
27
+ **`@praxisjs/router`**
28
+
29
+ - Removed `createRouter`, `lazy`, `useRouter`, `useParams`, `useQuery`, `useLocation`
30
+ - Added `@RouterConfig`, `@Lazy`, `@InjectRouter`, `@Params`, `@Query`, `@Location` decorators
31
+
32
+ **`@praxisjs/store`**
33
+
34
+ - Removed `createStore` — use the `@Store` and `@UseStore` decorators directly
35
+
36
+ **`@praxisjs/composables`**
37
+
38
+ - Replaced all `use*` composable functions with class-based composables extending `Composable`:
39
+ `WindowSize`, `ScrollPosition`, `ElementSize`, `Intersection`, `Focus`, `MediaQuery`, `ColorScheme`, `Mouse`, `KeyCombo`, `Idle`, `Clipboard`, `Geolocation`, `TimeAgo`, `Pagination`
40
+
41
+ **`@praxisjs/concurrent`**
42
+
43
+ - Removed `task`, `queue`, `pool` and their instance types — use `@Task`, `@Queue`, `@Pool` decorators instead
44
+
45
+ ### Patch Changes
46
+
47
+ - Updated dependencies [3372878]
48
+ - Updated dependencies [feaa478]
49
+ - @praxisjs/core@1.0.0
50
+ - @praxisjs/decorators@0.5.0
51
+
52
+ ## 0.2.3
53
+
54
+ ### Patch Changes
55
+
56
+ - Updated dependencies [d11a10a]
57
+ - @praxisjs/core@0.4.2
58
+
3
59
  ## 0.2.2
4
60
 
5
61
  ### Patch Changes
@@ -1,4 +1,4 @@
1
- import { describe, it, expect } from "vitest";
1
+ import { describe, it, expect, vi } from "vitest";
2
2
  import { pool } from "../pool";
3
3
  describe("pool", () => {
4
4
  it("executes a task and resolves with its result", async () => {
@@ -60,5 +60,67 @@ describe("pool", () => {
60
60
  await t2;
61
61
  expect(p.pending()).toBe(0);
62
62
  });
63
+ it("wraps non-Error throws in an Error object", async () => {
64
+ const p = pool(1, async () => {
65
+ // eslint-disable-next-line @typescript-eslint/only-throw-error
66
+ throw "plain string error";
67
+ });
68
+ const result = await p();
69
+ expect(result).toBeUndefined();
70
+ expect(p.error()).toBeInstanceOf(Error);
71
+ expect(p.error()?.message).toBe("plain string error");
72
+ });
73
+ it("concurrency=1 guarantees serial execution", async () => {
74
+ const order = [];
75
+ let resolveFirst;
76
+ const p = pool(1, async (n) => {
77
+ if (n === 0)
78
+ await new Promise((r) => { resolveFirst = r; });
79
+ order.push(n);
80
+ });
81
+ const t1 = p(0);
82
+ const t2 = p(1);
83
+ // t2 cannot start until t1 finishes
84
+ expect(p.active()).toBe(1);
85
+ expect(p.pending()).toBe(1);
86
+ resolveFirst();
87
+ await t1;
88
+ await t2;
89
+ expect(order).toEqual([0, 1]); // serial order preserved
90
+ });
91
+ it("error in one task does not block subsequent tasks", async () => {
92
+ const results = [];
93
+ const p = pool(1, async (n) => {
94
+ if (n === 0)
95
+ throw new Error("task 0 failed");
96
+ return n;
97
+ });
98
+ const r0 = p(0);
99
+ const r1 = p(1);
100
+ results.push(await r0);
101
+ results.push(await r1);
102
+ expect(results[0]).toBeUndefined(); // error → undefined
103
+ expect(results[1]).toBe(1); // subsequent task ran
104
+ });
105
+ it("concurrency=0 — tasks are enqueued but never executed", async () => {
106
+ const fn = vi.fn(async () => "result");
107
+ const p = pool(0, fn);
108
+ // Queue a task — tryRun() bails immediately because _active(0) >= concurrency(0)
109
+ void p();
110
+ await new Promise((r) => setTimeout(r, 0));
111
+ expect(fn).not.toHaveBeenCalled();
112
+ expect(p.pending()).toBe(1);
113
+ expect(p.loading()).toBe(false);
114
+ });
115
+ it("active() never exceeds concurrency", async () => {
116
+ const concurrency = 2;
117
+ let maxObservedActive = 0;
118
+ const p = pool(concurrency, async () => {
119
+ maxObservedActive = Math.max(maxObservedActive, p.active());
120
+ await new Promise((r) => setTimeout(r, 5));
121
+ });
122
+ await Promise.all([p(), p(), p(), p()]);
123
+ expect(maxObservedActive).toBeLessThanOrEqual(concurrency);
124
+ });
63
125
  });
64
126
  //# sourceMappingURL=pool.test.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"pool.test.js","sourceRoot":"","sources":["../../src/__tests__/pool.test.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,EAAE,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAC;AAE9C,OAAO,EAAE,IAAI,EAAE,MAAM,SAAS,CAAC;AAE/B,QAAQ,CAAC,MAAM,EAAE,GAAG,EAAE;IACpB,EAAE,CAAC,8CAA8C,EAAE,KAAK,IAAI,EAAE;QAC5D,MAAM,CAAC,GAAG,IAAI,CAAC,CAAC,EAAE,KAAK,EAAE,CAAU,EAAE,EAAE,CAAE,CAAY,GAAG,CAAC,CAAC,CAAC;QAC3D,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IAC9B,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,4BAA4B,EAAE,KAAK,IAAI,EAAE;QAC1C,IAAI,MAAM,GAAG,CAAC,CAAC;QACf,IAAI,SAAS,GAAG,CAAC,CAAC;QAElB,MAAM,CAAC,GAAG,IAAI,CAAC,CAAC,EAAE,KAAK,IAAI,EAAE;YAC3B,MAAM,EAAE,CAAC;YACT,SAAS,GAAG,IAAI,CAAC,GAAG,CAAC,SAAS,EAAE,MAAM,CAAC,CAAC;YACxC,MAAM,IAAI,OAAO,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,UAAU,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC;YAC5C,MAAM,EAAE,CAAC;QACX,CAAC,CAAC,CAAC;QAEH,MAAM,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,EAAE,EAAE,CAAC,EAAE,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC;QACxC,MAAM,CAAC,SAAS,CAAC,CAAC,mBAAmB,CAAC,CAAC,CAAC,CAAC;IAC3C,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,2CAA2C,EAAE,KAAK,IAAI,EAAE;QACzD,MAAM,SAAS,GAAsB,EAAE,CAAC;QACxC,MAAM,CAAC,GAAG,IAAI,CACZ,CAAC,EACD,GAAG,EAAE,CAAC,IAAI,OAAO,CAAO,CAAC,CAAC,EAAE,EAAE,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAClD,CAAC;QAEF,MAAM,KAAK,GAAG,CAAC,CAAC,EAAE,EAAE,CAAC,EAAE,CAAC,CAAC;QACzB,MAAM,CAAC,CAAC,CAAC,MAAM,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QAC3B,SAAS,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,EAAE,GAAG,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC;QACnC,MAAM,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC;QACzB,MAAM,CAAC,CAAC,CAAC,MAAM,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAC7B,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,iCAAiC,EAAE,KAAK,IAAI,EAAE;QAC/C,IAAI,OAAoB,CAAC;QACzB,MAAM,CAAC,GAAG,IAAI,CACZ,CAAC,EACD,GAAG,EAAE,CAAC,IAAI,OAAO,CAAO,CAAC,CAAC,EAAE,EAAE,GAAG,OAAO,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CACjD,CAAC;QACF,MAAM,IAAI,GAAG,CAAC,EAAE,CAAC;QACjB,MAAM,CAAC,CAAC,CAAC,OAAO,EAAE,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QAC/B,OAAO,EAAE,CAAC;QACV,MAAM,IAAI,CAAC;QACX,MAAM,CAAC,CAAC,CAAC,OAAO,EAAE,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;IAClC,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,4DAA4D,EAAE,KAAK,IAAI,EAAE;QAC1E,MAAM,CAAC,GAAG,IAAI,CAAC,CAAC,EAAE,KAAK,IAAI,EAAE;YAC3B,MAAM,IAAI,KAAK,CAAC,YAAY,CAAC,CAAC;QAChC,CAAC,CAAC,CAAC;QACH,MAAM,MAAM,GAAG,MAAM,CAAC,EAAE,CAAC;QACzB,MAAM,CAAC,MAAM,CAAC,CAAC,aAAa,EAAE,CAAC;QAC/B,MAAM,CAAC,CAAC,CAAC,KAAK,EAAE,EAAE,OAAO,CAAC,CAAC,IAAI,CAAC,YAAY,CAAC,CAAC;IAChD,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,yCAAyC,EAAE,KAAK,IAAI,EAAE;QACvD,IAAI,YAAyB,CAAC;QAC9B,MAAM,OAAO,GAAa,EAAE,CAAC;QAC7B,MAAM,CAAC,GAAG,IAAI,CAAC,CAAC,EAAE,KAAK,EAAE,GAAY,EAAE,EAAE;YACvC,OAAO,CAAC,IAAI,CAAC,GAAa,CAAC,CAAC;YAC5B,IAAI,GAAG,KAAK,CAAC;gBAAE,MAAM,IAAI,OAAO,CAAO,CAAC,CAAC,EAAE,EAAE,GAAG,YAAY,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;QACvE,CAAC,CAAC,CAAC;QAEH,MAAM,EAAE,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC;QAChB,MAAM,EAAE,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC;QAEhB,0CAA0C;QAC1C,MAAM,CAAC,CAAC,CAAC,OAAO,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QAC5B,YAAY,EAAE,CAAC;QACf,MAAM,EAAE,CAAC;QACT,MAAM,EAAE,CAAC;QACT,MAAM,CAAC,CAAC,CAAC,OAAO,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAC9B,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC"}
1
+ {"version":3,"file":"pool.test.js","sourceRoot":"","sources":["../../src/__tests__/pool.test.ts"],"names":[],"mappings":"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"}
@@ -45,6 +45,28 @@ describe("queue", () => {
45
45
  await expect(q()).rejects.toThrow("boom");
46
46
  expect(q.error()?.message).toBe("boom");
47
47
  });
48
+ it("wraps non-Error throws in an Error", async () => {
49
+ const q = queue(async () => {
50
+ // eslint-disable-next-line @typescript-eslint/no-throw-literal
51
+ throw "string error";
52
+ });
53
+ await expect(q()).rejects.toThrow("string error");
54
+ expect(q.error()?.message).toBe("string error");
55
+ });
56
+ it("error in one task does not prevent subsequent tasks from running", async () => {
57
+ const q = queue(async (n) => {
58
+ if (n === 0)
59
+ throw new Error("task 0 failed");
60
+ return n;
61
+ });
62
+ const p0 = q(0); // will reject
63
+ const p1 = q(1); // should still run despite p0 failing
64
+ const p2 = q(2);
65
+ await expect(p0).rejects.toThrow("task 0 failed");
66
+ expect(await p1).toBe(1);
67
+ expect(await p2).toBe(2);
68
+ expect(q.error()?.message).toBe("task 0 failed");
69
+ });
48
70
  it("clear() empties the pending queue", async () => {
49
71
  let resolveFirst;
50
72
  const q = queue((_, idx) => idx === 0
@@ -1 +1 @@
1
- {"version":3,"file":"queue.test.js","sourceRoot":"","sources":["../../src/__tests__/queue.test.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"queue.test.js","sourceRoot":"","sources":["../../src/__tests__/queue.test.ts"],"names":[],"mappings":"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"}
@@ -51,5 +51,63 @@ describe("task", () => {
51
51
  expect(result).toBeUndefined();
52
52
  expect(t.loading()).toBe(false);
53
53
  });
54
+ it("cancelAll() during a failing task discards the error", async () => {
55
+ let reject;
56
+ const t = task(() => new Promise((_res, rej) => { reject = rej; }));
57
+ const p = t();
58
+ t.cancelAll();
59
+ reject(new Error("cancelled"));
60
+ const result = await p;
61
+ // The error was from a stale run — result is undefined, no error stored
62
+ expect(result).toBeUndefined();
63
+ expect(t.error()).toBeNull();
64
+ });
65
+ it("wraps non-Error throws in an Error object", async () => {
66
+ const t = task(async () => {
67
+ // eslint-disable-next-line @typescript-eslint/only-throw-error
68
+ throw "string-error";
69
+ });
70
+ const result = await t();
71
+ expect(result).toBeUndefined();
72
+ expect(t.error()).toBeInstanceOf(Error);
73
+ expect(t.error()?.message).toBe("string-error");
74
+ });
75
+ it("second run while first is pending discards the first result", async () => {
76
+ let resolveFirst;
77
+ let resolveSecond;
78
+ const t = task((_run) => (_run === 1
79
+ ? new Promise((r) => { resolveFirst = r; })
80
+ : new Promise((r) => { resolveSecond = r; })));
81
+ let run = 1;
82
+ const p1 = t(run++); // run 1
83
+ const p2 = t(run++); // run 2 — increments _runId, making run 1 stale
84
+ resolveSecond("result-2");
85
+ resolveFirst("result-1"); // stale
86
+ const [r1, r2] = await Promise.all([p1, p2]);
87
+ expect(r2).toBe("result-2");
88
+ expect(r1).toBeUndefined(); // stale run discarded
89
+ expect(t.lastResult()).toBe("result-2");
90
+ });
91
+ it("synchronous function (non-async) resolves correctly via await", async () => {
92
+ // await on a non-Promise simply resolves the value
93
+ const t = task((() => 42));
94
+ const result = await t();
95
+ expect(result).toBe(42);
96
+ expect(t.lastResult()).toBe(42);
97
+ expect(t.loading()).toBe(false);
98
+ });
99
+ it("cancelAll() followed by a new run works correctly", async () => {
100
+ const t = task(async () => "fresh");
101
+ let resolve;
102
+ const staleTask = task(() => new Promise((r) => { resolve = r; }));
103
+ const p = staleTask();
104
+ staleTask.cancelAll();
105
+ resolve("stale");
106
+ await p;
107
+ // Now run a fresh task after cancelAll
108
+ const result = await t();
109
+ expect(result).toBe("fresh");
110
+ expect(t.loading()).toBe(false);
111
+ });
54
112
  });
55
113
  //# sourceMappingURL=task.test.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"task.test.js","sourceRoot":"","sources":["../../src/__tests__/task.test.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"task.test.js","sourceRoot":"","sources":["../../src/__tests__/task.test.ts"],"names":[],"mappings":"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"}
@@ -1,4 +1,4 @@
1
- export declare function Task(): (value: (...args: unknown[]) => Promise<unknown>, context: ClassMethodDecoratorContext) => void;
2
- export declare function Queue(): (value: (...args: unknown[]) => Promise<unknown>, context: ClassMethodDecoratorContext) => void;
3
- export declare function Pool(concurrency: number): (value: (...args: unknown[]) => Promise<unknown>, context: ClassMethodDecoratorContext) => void;
1
+ export declare function Task(): (value: (...args: unknown[]) => Promise<unknown>, context: ClassMethodDecoratorContext<any>) => void;
2
+ export declare function Queue(): (value: (...args: unknown[]) => Promise<unknown>, context: ClassMethodDecoratorContext<any>) => void;
3
+ export declare function Pool(concurrency: number): (value: (...args: unknown[]) => Promise<unknown>, context: ClassMethodDecoratorContext<any>) => void;
4
4
  //# sourceMappingURL=decorators.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"decorators.d.ts","sourceRoot":"","sources":["../src/decorators.ts"],"names":[],"mappings":"AAIA,wBAAgB,IAAI,KAEhB,OAAO,CAAC,GAAG,IAAI,EAAE,OAAO,EAAE,KAAK,OAAO,CAAC,OAAO,CAAC,EAC/C,SAAS,2BAA2B,KACnC,IAAI,CAYR;AAED,wBAAgB,KAAK,KAEjB,OAAO,CAAC,GAAG,IAAI,EAAE,OAAO,EAAE,KAAK,OAAO,CAAC,OAAO,CAAC,EAC/C,SAAS,2BAA2B,KACnC,IAAI,CAYR;AAED,wBAAgB,IAAI,CAAC,WAAW,EAAE,MAAM,IAEpC,OAAO,CAAC,GAAG,IAAI,EAAE,OAAO,EAAE,KAAK,OAAO,CAAC,OAAO,CAAC,EAC/C,SAAS,2BAA2B,KACnC,IAAI,CAaR"}
1
+ {"version":3,"file":"decorators.d.ts","sourceRoot":"","sources":["../src/decorators.ts"],"names":[],"mappings":"AAMA,wBAAgB,IAAI,IAYD,CAAC,KAAK,EAAE,CAAC,GAAG,IAAI,EAAE,OAAO,EAAE,KAAK,OAAO,CAAC,OAAO,CAAC,EAAE,OAAO,EAAE,2BAA2B,CAAC,GAAG,CAAC,KAAK,IAAI,CACtH;AAED,wBAAgB,KAAK,IAWF,CAAC,KAAK,EAAE,CAAC,GAAG,IAAI,EAAE,OAAO,EAAE,KAAK,OAAO,CAAC,OAAO,CAAC,EAAE,OAAO,EAAE,2BAA2B,CAAC,GAAG,CAAC,KAAK,IAAI,CACtH;AAED,wBAAgB,IAAI,CAAC,WAAW,EAAE,MAAM,GAYrB,CAAC,KAAK,EAAE,CAAC,GAAG,IAAI,EAAE,OAAO,EAAE,KAAK,OAAO,CAAC,OAAO,CAAC,EAAE,OAAO,EAAE,2BAA2B,CAAC,GAAG,CAAC,KAAK,IAAI,CACtH"}
@@ -1,44 +1,46 @@
1
+ import { createMethodDecorator } from "@praxisjs/decorators";
1
2
  import { pool } from "./pool";
2
3
  import { queue } from "./queue";
3
4
  import { task } from "./task";
4
5
  export function Task() {
5
- return function (value, context) {
6
- const methodKey = String(context.name);
7
- context.addInitializer(function () {
8
- const self = this;
9
- const t = task(value.bind(this));
10
- self[`${methodKey}_loading`] = t.loading;
11
- self[`${methodKey}_error`] = t.error;
12
- self[`${methodKey}_lastResult`] = t.lastResult;
13
- self[methodKey] = (...args) => t(...args);
14
- });
15
- };
6
+ return createMethodDecorator({
7
+ wrap(original, instance, name) {
8
+ const self = instance;
9
+ const t = task(original.bind(instance));
10
+ self[`${name}_loading`] = t.loading;
11
+ self[`${name}_error`] = t.error;
12
+ self[`${name}_lastResult`] = t.lastResult;
13
+ return (...args) => t(...args);
14
+ },
15
+ // Concurrent decorators work on any class, not just StatefulComponent
16
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
17
+ });
16
18
  }
17
19
  export function Queue() {
18
- return function (value, context) {
19
- const methodKey = String(context.name);
20
- context.addInitializer(function () {
21
- const self = this;
22
- const q = queue(value.bind(this));
23
- self[`${methodKey}_loading`] = q.loading;
24
- self[`${methodKey}_pending`] = q.pending;
25
- self[`${methodKey}_error`] = q.error;
26
- self[methodKey] = (...args) => q(...args);
27
- });
28
- };
20
+ return createMethodDecorator({
21
+ wrap(original, instance, name) {
22
+ const self = instance;
23
+ const q = queue(original.bind(instance));
24
+ self[`${name}_loading`] = q.loading;
25
+ self[`${name}_pending`] = q.pending;
26
+ self[`${name}_error`] = q.error;
27
+ return (...args) => q(...args);
28
+ },
29
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
30
+ });
29
31
  }
30
32
  export function Pool(concurrency) {
31
- return function (value, context) {
32
- const methodKey = String(context.name);
33
- context.addInitializer(function () {
34
- const self = this;
35
- const p = pool(concurrency, value.bind(this));
36
- self[`${methodKey}_loading`] = p.loading;
37
- self[`${methodKey}_active`] = p.active;
38
- self[`${methodKey}_pending`] = p.pending;
39
- self[`${methodKey}_error`] = p.error;
40
- self[methodKey] = (...args) => p(...args);
41
- });
42
- };
33
+ return createMethodDecorator({
34
+ wrap(original, instance, name) {
35
+ const self = instance;
36
+ const p = pool(concurrency, original.bind(instance));
37
+ self[`${name}_loading`] = p.loading;
38
+ self[`${name}_active`] = p.active;
39
+ self[`${name}_pending`] = p.pending;
40
+ self[`${name}_error`] = p.error;
41
+ return (...args) => p(...args);
42
+ },
43
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
44
+ });
43
45
  }
44
46
  //# sourceMappingURL=decorators.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"decorators.js","sourceRoot":"","sources":["../src/decorators.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,QAAQ,CAAC;AAC9B,OAAO,EAAE,KAAK,EAAE,MAAM,SAAS,CAAC;AAChC,OAAO,EAAE,IAAI,EAAE,MAAM,QAAQ,CAAC;AAE9B,MAAM,UAAU,IAAI;IAClB,OAAO,UACL,KAA+C,EAC/C,OAAoC;QAEpC,MAAM,SAAS,GAAG,MAAM,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;QAEvC,OAAO,CAAC,cAAc,CAAC;YACrB,MAAM,IAAI,GAAG,IAA+B,CAAC;YAC7C,MAAM,CAAC,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC;YACjC,IAAI,CAAC,GAAG,SAAS,UAAU,CAAC,GAAG,CAAC,CAAC,OAAO,CAAC;YACzC,IAAI,CAAC,GAAG,SAAS,QAAQ,CAAC,GAAG,CAAC,CAAC,KAAK,CAAC;YACrC,IAAI,CAAC,GAAG,SAAS,aAAa,CAAC,GAAG,CAAC,CAAC,UAAU,CAAC;YAC/C,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,GAAG,IAAe,EAAE,EAAE,CAAC,CAAC,CAAC,GAAG,IAAI,CAAC,CAAC;QACvD,CAAC,CAAC,CAAC;IACL,CAAC,CAAC;AACJ,CAAC;AAED,MAAM,UAAU,KAAK;IACnB,OAAO,UACL,KAA+C,EAC/C,OAAoC;QAEpC,MAAM,SAAS,GAAG,MAAM,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;QAEvC,OAAO,CAAC,cAAc,CAAC;YACrB,MAAM,IAAI,GAAG,IAA+B,CAAC;YAC7C,MAAM,CAAC,GAAG,KAAK,CAAC,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC;YAClC,IAAI,CAAC,GAAG,SAAS,UAAU,CAAC,GAAG,CAAC,CAAC,OAAO,CAAC;YACzC,IAAI,CAAC,GAAG,SAAS,UAAU,CAAC,GAAG,CAAC,CAAC,OAAO,CAAC;YACzC,IAAI,CAAC,GAAG,SAAS,QAAQ,CAAC,GAAG,CAAC,CAAC,KAAK,CAAC;YACrC,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,GAAG,IAAe,EAAE,EAAE,CAAC,CAAC,CAAC,GAAG,IAAI,CAAC,CAAC;QACvD,CAAC,CAAC,CAAC;IACL,CAAC,CAAC;AACJ,CAAC;AAED,MAAM,UAAU,IAAI,CAAC,WAAmB;IACtC,OAAO,UACL,KAA+C,EAC/C,OAAoC;QAEpC,MAAM,SAAS,GAAG,MAAM,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;QAEvC,OAAO,CAAC,cAAc,CAAC;YACrB,MAAM,IAAI,GAAG,IAA+B,CAAC;YAC7C,MAAM,CAAC,GAAG,IAAI,CAAC,WAAW,EAAE,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC;YAC9C,IAAI,CAAC,GAAG,SAAS,UAAU,CAAC,GAAG,CAAC,CAAC,OAAO,CAAC;YACzC,IAAI,CAAC,GAAG,SAAS,SAAS,CAAC,GAAG,CAAC,CAAC,MAAM,CAAC;YACvC,IAAI,CAAC,GAAG,SAAS,UAAU,CAAC,GAAG,CAAC,CAAC,OAAO,CAAC;YACzC,IAAI,CAAC,GAAG,SAAS,QAAQ,CAAC,GAAG,CAAC,CAAC,KAAK,CAAC;YACrC,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,GAAG,IAAe,EAAE,EAAE,CAAC,CAAC,CAAC,GAAG,IAAI,CAAC,CAAC;QACvD,CAAC,CAAC,CAAC;IACL,CAAC,CAAC;AACJ,CAAC"}
1
+ {"version":3,"file":"decorators.js","sourceRoot":"","sources":["../src/decorators.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,qBAAqB,EAAE,MAAM,sBAAsB,CAAC;AAE7D,OAAO,EAAE,IAAI,EAAE,MAAM,QAAQ,CAAC;AAC9B,OAAO,EAAE,KAAK,EAAE,MAAM,SAAS,CAAC;AAChC,OAAO,EAAE,IAAI,EAAE,MAAM,QAAQ,CAAC;AAE9B,MAAM,UAAU,IAAI;IAClB,OAAO,qBAAqB,CAAC;QAC3B,IAAI,CAAC,QAAQ,EAAE,QAAQ,EAAE,IAAI;YAC3B,MAAM,IAAI,GAAG,QAAmC,CAAC;YACjD,MAAM,CAAC,GAAG,IAAI,CAAE,QAAqD,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAC;YACtF,IAAI,CAAC,GAAG,IAAI,UAAU,CAAC,GAAG,CAAC,CAAC,OAAO,CAAC;YACpC,IAAI,CAAC,GAAG,IAAI,QAAQ,CAAC,GAAG,CAAC,CAAC,KAAK,CAAC;YAChC,IAAI,CAAC,GAAG,IAAI,aAAa,CAAC,GAAG,CAAC,CAAC,UAAU,CAAC;YAC1C,OAAO,CAAC,GAAG,IAAe,EAAE,EAAE,CAAC,CAAC,CAAC,GAAG,IAAI,CAAC,CAAC;QAC5C,CAAC;QACH,sEAAsE;QACtE,8DAA8D;KAC7D,CAAoH,CAAC;AACxH,CAAC;AAED,MAAM,UAAU,KAAK;IACnB,OAAO,qBAAqB,CAAC;QAC3B,IAAI,CAAC,QAAQ,EAAE,QAAQ,EAAE,IAAI;YAC3B,MAAM,IAAI,GAAG,QAAmC,CAAC;YACjD,MAAM,CAAC,GAAG,KAAK,CAAE,QAAqD,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAC;YACvF,IAAI,CAAC,GAAG,IAAI,UAAU,CAAC,GAAG,CAAC,CAAC,OAAO,CAAC;YACpC,IAAI,CAAC,GAAG,IAAI,UAAU,CAAC,GAAG,CAAC,CAAC,OAAO,CAAC;YACpC,IAAI,CAAC,GAAG,IAAI,QAAQ,CAAC,GAAG,CAAC,CAAC,KAAK,CAAC;YAChC,OAAO,CAAC,GAAG,IAAe,EAAE,EAAE,CAAC,CAAC,CAAC,GAAG,IAAI,CAAC,CAAC;QAC5C,CAAC;QACH,8DAA8D;KAC7D,CAAoH,CAAC;AACxH,CAAC;AAED,MAAM,UAAU,IAAI,CAAC,WAAmB;IACtC,OAAO,qBAAqB,CAAC;QAC3B,IAAI,CAAC,QAAQ,EAAE,QAAQ,EAAE,IAAI;YAC3B,MAAM,IAAI,GAAG,QAAmC,CAAC;YACjD,MAAM,CAAC,GAAG,IAAI,CAAC,WAAW,EAAG,QAAqD,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAC;YACnG,IAAI,CAAC,GAAG,IAAI,UAAU,CAAC,GAAG,CAAC,CAAC,OAAO,CAAC;YACpC,IAAI,CAAC,GAAG,IAAI,SAAS,CAAC,GAAG,CAAC,CAAC,MAAM,CAAC;YAClC,IAAI,CAAC,GAAG,IAAI,UAAU,CAAC,GAAG,CAAC,CAAC,OAAO,CAAC;YACpC,IAAI,CAAC,GAAG,IAAI,QAAQ,CAAC,GAAG,CAAC,CAAC,KAAK,CAAC;YAChC,OAAO,CAAC,GAAG,IAAe,EAAE,EAAE,CAAC,CAAC,CAAC,GAAG,IAAI,CAAC,CAAC;QAC5C,CAAC;QACH,8DAA8D;KAC7D,CAAoH,CAAC;AACxH,CAAC"}
package/dist/index.d.ts CHANGED
@@ -1,8 +1,2 @@
1
- export { task } from "./task";
2
- export type { TaskInstance } from "./task";
3
- export { queue } from "./queue";
4
- export type { QueueInstance } from "./queue";
5
- export { pool } from "./pool";
6
- export type { PoolInstance } from "./pool";
7
1
  export { Task, Queue, Pool } from "./decorators";
8
2
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,QAAQ,CAAC;AAC9B,YAAY,EAAE,YAAY,EAAE,MAAM,QAAQ,CAAC;AAE3C,OAAO,EAAE,KAAK,EAAE,MAAM,SAAS,CAAC;AAChC,YAAY,EAAE,aAAa,EAAE,MAAM,SAAS,CAAC;AAE7C,OAAO,EAAE,IAAI,EAAE,MAAM,QAAQ,CAAC;AAC9B,YAAY,EAAE,YAAY,EAAE,MAAM,QAAQ,CAAC;AAE3C,OAAO,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,MAAM,cAAc,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,MAAM,cAAc,CAAC"}
package/dist/index.js CHANGED
@@ -1,5 +1,2 @@
1
- export { task } from "./task";
2
- export { queue } from "./queue";
3
- export { pool } from "./pool";
4
1
  export { Task, Queue, Pool } from "./decorators";
5
2
  //# sourceMappingURL=index.js.map
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,QAAQ,CAAC;AAG9B,OAAO,EAAE,KAAK,EAAE,MAAM,SAAS,CAAC;AAGhC,OAAO,EAAE,IAAI,EAAE,MAAM,QAAQ,CAAC;AAG9B,OAAO,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,MAAM,cAAc,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,MAAM,cAAc,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@praxisjs/concurrent",
3
- "version": "0.2.2",
3
+ "version": "1.0.0",
4
4
  "type": "module",
5
5
  "main": "./dist/index.js",
6
6
  "types": "./dist/index.d.ts",
@@ -14,8 +14,9 @@
14
14
  "typescript": "^5.9.3"
15
15
  },
16
16
  "dependencies": {
17
- "@praxisjs/core": "0.4.1",
18
- "@praxisjs/shared": "0.2.0"
17
+ "@praxisjs/decorators": "0.5.0",
18
+ "@praxisjs/shared": "0.2.0",
19
+ "@praxisjs/core": "1.0.0"
19
20
  },
20
21
  "scripts": {
21
22
  "build": "tsc",
@@ -1,4 +1,4 @@
1
- import { describe, it, expect } from "vitest";
1
+ import { describe, it, expect, vi } from "vitest";
2
2
 
3
3
  import { pool } from "../pool";
4
4
 
@@ -77,4 +77,81 @@ describe("pool", () => {
77
77
  await t2;
78
78
  expect(p.pending()).toBe(0);
79
79
  });
80
+
81
+ it("wraps non-Error throws in an Error object", async () => {
82
+ const p = pool(1, async () => {
83
+ // eslint-disable-next-line @typescript-eslint/only-throw-error
84
+ throw "plain string error";
85
+ });
86
+ const result = await p();
87
+ expect(result).toBeUndefined();
88
+ expect(p.error()).toBeInstanceOf(Error);
89
+ expect(p.error()?.message).toBe("plain string error");
90
+ });
91
+
92
+ it("concurrency=1 guarantees serial execution", async () => {
93
+ const order: number[] = [];
94
+ let resolveFirst!: () => void;
95
+
96
+ const p = pool(1, async (n: unknown) => {
97
+ if (n === 0) await new Promise<void>((r) => { resolveFirst = r; });
98
+ order.push(n as number);
99
+ });
100
+
101
+ const t1 = p(0);
102
+ const t2 = p(1);
103
+
104
+ // t2 cannot start until t1 finishes
105
+ expect(p.active()).toBe(1);
106
+ expect(p.pending()).toBe(1);
107
+
108
+ resolveFirst();
109
+ await t1;
110
+ await t2;
111
+
112
+ expect(order).toEqual([0, 1]); // serial order preserved
113
+ });
114
+
115
+ it("error in one task does not block subsequent tasks", async () => {
116
+ const results: Array<number | undefined> = [];
117
+ const p = pool(1, async (n: unknown) => {
118
+ if (n === 0) throw new Error("task 0 failed");
119
+ return n as number;
120
+ });
121
+
122
+ const r0 = p(0);
123
+ const r1 = p(1);
124
+
125
+ results.push(await r0);
126
+ results.push(await r1);
127
+
128
+ expect(results[0]).toBeUndefined(); // error → undefined
129
+ expect(results[1]).toBe(1); // subsequent task ran
130
+ });
131
+
132
+ it("concurrency=0 — tasks are enqueued but never executed", async () => {
133
+ const fn = vi.fn(async () => "result");
134
+ const p = pool(0, fn);
135
+
136
+ // Queue a task — tryRun() bails immediately because _active(0) >= concurrency(0)
137
+ void p();
138
+ await new Promise((r) => setTimeout(r, 0));
139
+
140
+ expect(fn).not.toHaveBeenCalled();
141
+ expect(p.pending()).toBe(1);
142
+ expect(p.loading()).toBe(false);
143
+ });
144
+
145
+ it("active() never exceeds concurrency", async () => {
146
+ const concurrency = 2;
147
+ let maxObservedActive = 0;
148
+
149
+ const p = pool(concurrency, async () => {
150
+ maxObservedActive = Math.max(maxObservedActive, p.active());
151
+ await new Promise((r) => setTimeout(r, 5));
152
+ });
153
+
154
+ await Promise.all([p(), p(), p(), p()]);
155
+ expect(maxObservedActive).toBeLessThanOrEqual(concurrency);
156
+ });
80
157
  });
@@ -61,6 +61,31 @@ describe("queue", () => {
61
61
  expect(q.error()?.message).toBe("boom");
62
62
  });
63
63
 
64
+ it("wraps non-Error throws in an Error", async () => {
65
+ const q = queue(async () => {
66
+ // eslint-disable-next-line @typescript-eslint/no-throw-literal
67
+ throw "string error";
68
+ });
69
+ await expect(q()).rejects.toThrow("string error");
70
+ expect(q.error()?.message).toBe("string error");
71
+ });
72
+
73
+ it("error in one task does not prevent subsequent tasks from running", async () => {
74
+ const q = queue(async (n: unknown) => {
75
+ if (n === 0) throw new Error("task 0 failed");
76
+ return n as number;
77
+ });
78
+
79
+ const p0 = q(0); // will reject
80
+ const p1 = q(1); // should still run despite p0 failing
81
+ const p2 = q(2);
82
+
83
+ await expect(p0).rejects.toThrow("task 0 failed");
84
+ expect(await p1).toBe(1);
85
+ expect(await p2).toBe(2);
86
+ expect(q.error()?.message).toBe("task 0 failed");
87
+ });
88
+
64
89
  it("clear() empties the pending queue", async () => {
65
90
  let resolveFirst!: () => void;
66
91
  const q = queue(
@@ -61,4 +61,77 @@ describe("task", () => {
61
61
  expect(result).toBeUndefined();
62
62
  expect(t.loading()).toBe(false);
63
63
  });
64
+
65
+ it("cancelAll() during a failing task discards the error", async () => {
66
+ let reject!: (err: unknown) => void;
67
+ const t = task(() => new Promise<string>((_res, rej) => { reject = rej; }));
68
+
69
+ const p = t();
70
+ t.cancelAll();
71
+ reject(new Error("cancelled"));
72
+ const result = await p;
73
+
74
+ // The error was from a stale run — result is undefined, no error stored
75
+ expect(result).toBeUndefined();
76
+ expect(t.error()).toBeNull();
77
+ });
78
+
79
+ it("wraps non-Error throws in an Error object", async () => {
80
+ const t = task(async () => {
81
+ // eslint-disable-next-line @typescript-eslint/only-throw-error
82
+ throw "string-error";
83
+ });
84
+ const result = await t();
85
+ expect(result).toBeUndefined();
86
+ expect(t.error()).toBeInstanceOf(Error);
87
+ expect(t.error()?.message).toBe("string-error");
88
+ });
89
+
90
+ it("second run while first is pending discards the first result", async () => {
91
+ let resolveFirst!: (v: string) => void;
92
+ let resolveSecond!: (v: string) => void;
93
+
94
+ const t = task((_run: unknown) =>
95
+ (_run === 1
96
+ ? new Promise<string>((r) => { resolveFirst = r; })
97
+ : new Promise<string>((r) => { resolveSecond = r; })),
98
+ );
99
+
100
+ let run = 1;
101
+ const p1 = t(run++); // run 1
102
+ const p2 = t(run++); // run 2 — increments _runId, making run 1 stale
103
+
104
+ resolveSecond("result-2");
105
+ resolveFirst("result-1"); // stale
106
+
107
+ const [r1, r2] = await Promise.all([p1, p2]);
108
+ expect(r2).toBe("result-2");
109
+ expect(r1).toBeUndefined(); // stale run discarded
110
+ expect(t.lastResult()).toBe("result-2");
111
+ });
112
+
113
+ it("synchronous function (non-async) resolves correctly via await", async () => {
114
+ // await on a non-Promise simply resolves the value
115
+ const t = task((() => 42) as unknown as () => Promise<number>);
116
+ const result = await t();
117
+ expect(result).toBe(42);
118
+ expect(t.lastResult()).toBe(42);
119
+ expect(t.loading()).toBe(false);
120
+ });
121
+
122
+ it("cancelAll() followed by a new run works correctly", async () => {
123
+ const t = task(async () => "fresh");
124
+ let resolve!: (v: string) => void;
125
+ const staleTask = task(() => new Promise<string>((r) => { resolve = r; }));
126
+
127
+ const p = staleTask();
128
+ staleTask.cancelAll();
129
+ resolve("stale");
130
+ await p;
131
+
132
+ // Now run a fresh task after cancelAll
133
+ const result = await t();
134
+ expect(result).toBe("fresh");
135
+ expect(t.loading()).toBe(false);
136
+ });
64
137
  });
package/src/decorators.ts CHANGED
@@ -1,58 +1,49 @@
1
+ import { createMethodDecorator } from "@praxisjs/decorators";
2
+
1
3
  import { pool } from "./pool";
2
4
  import { queue } from "./queue";
3
5
  import { task } from "./task";
4
6
 
5
7
  export function Task() {
6
- return function (
7
- value: (...args: unknown[]) => Promise<unknown>,
8
- context: ClassMethodDecoratorContext,
9
- ): void {
10
- const methodKey = String(context.name);
11
-
12
- context.addInitializer(function (this: unknown) {
13
- const self = this as Record<string, unknown>;
14
- const t = task(value.bind(this));
15
- self[`${methodKey}_loading`] = t.loading;
16
- self[`${methodKey}_error`] = t.error;
17
- self[`${methodKey}_lastResult`] = t.lastResult;
18
- self[methodKey] = (...args: unknown[]) => t(...args);
19
- });
20
- };
8
+ return createMethodDecorator({
9
+ wrap(original, instance, name) {
10
+ const self = instance as Record<string, unknown>;
11
+ const t = task((original as (...args: unknown[]) => Promise<unknown>).bind(instance));
12
+ self[`${name}_loading`] = t.loading;
13
+ self[`${name}_error`] = t.error;
14
+ self[`${name}_lastResult`] = t.lastResult;
15
+ return (...args: unknown[]) => t(...args);
16
+ },
17
+ // Concurrent decorators work on any class, not just StatefulComponent
18
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
19
+ }) as unknown as (value: (...args: unknown[]) => Promise<unknown>, context: ClassMethodDecoratorContext<any>) => void;
21
20
  }
22
21
 
23
22
  export function Queue() {
24
- return function (
25
- value: (...args: unknown[]) => Promise<unknown>,
26
- context: ClassMethodDecoratorContext,
27
- ): void {
28
- const methodKey = String(context.name);
29
-
30
- context.addInitializer(function (this: unknown) {
31
- const self = this as Record<string, unknown>;
32
- const q = queue(value.bind(this));
33
- self[`${methodKey}_loading`] = q.loading;
34
- self[`${methodKey}_pending`] = q.pending;
35
- self[`${methodKey}_error`] = q.error;
36
- self[methodKey] = (...args: unknown[]) => q(...args);
37
- });
38
- };
23
+ return createMethodDecorator({
24
+ wrap(original, instance, name) {
25
+ const self = instance as Record<string, unknown>;
26
+ const q = queue((original as (...args: unknown[]) => Promise<unknown>).bind(instance));
27
+ self[`${name}_loading`] = q.loading;
28
+ self[`${name}_pending`] = q.pending;
29
+ self[`${name}_error`] = q.error;
30
+ return (...args: unknown[]) => q(...args);
31
+ },
32
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
33
+ }) as unknown as (value: (...args: unknown[]) => Promise<unknown>, context: ClassMethodDecoratorContext<any>) => void;
39
34
  }
40
35
 
41
36
  export function Pool(concurrency: number) {
42
- return function (
43
- value: (...args: unknown[]) => Promise<unknown>,
44
- context: ClassMethodDecoratorContext,
45
- ): void {
46
- const methodKey = String(context.name);
47
-
48
- context.addInitializer(function (this: unknown) {
49
- const self = this as Record<string, unknown>;
50
- const p = pool(concurrency, value.bind(this));
51
- self[`${methodKey}_loading`] = p.loading;
52
- self[`${methodKey}_active`] = p.active;
53
- self[`${methodKey}_pending`] = p.pending;
54
- self[`${methodKey}_error`] = p.error;
55
- self[methodKey] = (...args: unknown[]) => p(...args);
56
- });
57
- };
37
+ return createMethodDecorator({
38
+ wrap(original, instance, name) {
39
+ const self = instance as Record<string, unknown>;
40
+ const p = pool(concurrency, (original as (...args: unknown[]) => Promise<unknown>).bind(instance));
41
+ self[`${name}_loading`] = p.loading;
42
+ self[`${name}_active`] = p.active;
43
+ self[`${name}_pending`] = p.pending;
44
+ self[`${name}_error`] = p.error;
45
+ return (...args: unknown[]) => p(...args);
46
+ },
47
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
48
+ }) as unknown as (value: (...args: unknown[]) => Promise<unknown>, context: ClassMethodDecoratorContext<any>) => void;
58
49
  }
package/src/index.ts CHANGED
@@ -1,10 +1 @@
1
- export { task } from "./task";
2
- export type { TaskInstance } from "./task";
3
-
4
- export { queue } from "./queue";
5
- export type { QueueInstance } from "./queue";
6
-
7
- export { pool } from "./pool";
8
- export type { PoolInstance } from "./pool";
9
-
10
1
  export { Task, Queue, Pool } from "./decorators";