worker-lib 2.0.9 → 2.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -7,291 +7,103 @@
7
7
 
8
8
  ## Overview
9
9
 
10
- Library for easy use of web-worker and worker_threads.
10
+ `worker-lib` is a lightweight, type-safe library designed to make **Web Workers** (Browser) and **worker_threads** (Node.js) as easy to use as standard asynchronous functions.
11
11
 
12
- ```ts
13
- import {
14
- createWorker,
15
- initWorker,
16
- waitAll,
17
- waitReady,
18
- close,
19
- } from "worker-lib"; //auto
12
+ ## Features
20
13
 
21
- import {
22
- createWorker,
23
- initWorker,
24
- waitAll,
25
- waitReady,
26
- close,
27
- } from "worker-lib/node"; // Node.js worker_threads
14
+ - **🚀 Cross-Platform**: Supports both Browser and Node.js with a unified API.
15
+ - **🛡️ Type-Safe**: Full TypeScript support with automatic type inference for worker functions.
16
+ - **⚡ Parallelism**: Built-in worker pool management with configurable concurrency limits.
17
+ - **🔄 Callback Support**: Pass functions as arguments to workers for progress updates or event handling.
18
+ - **📦 Zero Config**: Minimal setup required to get started.
28
19
 
29
- import {
30
- createWorker,
31
- initWorker,
32
- waitAll,
33
- waitReady,
34
- close,
35
- } from "worker-lib/web-worker"; // Web Worker
36
- ```
20
+ ## Installation
37
21
 
38
- ## Example
22
+ ```bash
23
+ npm install worker-lib
24
+ # or
25
+ pnpm add worker-lib
26
+ ```
39
27
 
40
- https://github.com/SoraKumo001/worker-lib-samples/
28
+ ## Basic Usage
41
29
 
42
- ### Node.js (worker_threads)
30
+ ### 1. Define Worker (worker.ts)
43
31
 
44
- - src/worker-test.ts
32
+ Register your functions using `initWorker`.
45
33
 
46
34
  ```ts
47
35
  import { initWorker } from "worker-lib";
48
36
 
49
- const add = (a: number, b: number) => {
50
- for (let i = 0; i < 1000000000; i++); //Overload unnecessarily
51
- return a + b;
52
- };
53
- const add2 = (a: string, b: string) => {
54
- for (let i = 0; i < 1000000000; i++); //Overload unnecessarily
55
- return a + b;
56
- };
57
- const sub = (a: number, b: number) => {
58
- for (let i = 0; i < 1000000000; i++); //Overload unnecessarily
59
- return a - b;
60
- };
61
- const mul = (a: number, b: number) => {
62
- for (let i = 0; i < 1000000000; i++); //Overload unnecessarily
63
- return a * b;
64
- };
37
+ const add = (a: number, b: number) => a + b;
65
38
 
66
- const error = (a: number, b: number) => {
67
- for (let i = 0; i < 1000000000; i++); //Overload unnecessarily
68
- throw new Error("throw");
69
- return a + b;
39
+ const heavyTask = async (data: string, onProgress: (percent: number, status: string) => void) => {
40
+ onProgress(10, "Starting...");
41
+ // ... heavy computation ...
42
+ onProgress(100, "Done");
43
+ return `Processed: ${data}`;
70
44
  };
71
45
 
72
- // Initialization process to make it usable in Worker.
73
- const map = initWorker({ add, add2, sub, mul, error });
74
- // Export only the type
75
- export type WorkerTest = typeof map;
46
+ const workerMap = initWorker({ add, heavyTask });
47
+ export type MyWorker = typeof workerMap;
76
48
  ```
77
49
 
78
- - src/index.ts
50
+ ### 2. Use Worker in Main Thread
51
+
52
+ #### Node.js (worker_threads)
79
53
 
80
54
  ```ts
81
55
  import { Worker } from "node:worker_threads";
82
- import { createWorker } from "worker-lib";
83
- import type { WorkerTest } from "./worker-test";
56
+ import { createWorker } from "worker-lib/node";
57
+ import type { MyWorker } from "./worker";
84
58
  import path from "node:path";
85
59
 
86
- const { execute, close } = createWorker<WorkerTest>(
87
- () => new Worker(path.resolve(__dirname, "./worker-test.js")),
88
- 4 // Maximum parallel number
60
+ const { execute, close } = createWorker<MyWorker>(
61
+ () => new Worker(path.resolve(__dirname, "./worker.js")),
62
+ 4 // Max parallel workers
89
63
  );
90
64
 
91
- const main = async () => {
92
- const a = 300;
93
- const b = 100;
94
- const p = [
95
- execute("add", a, b).then((result) => {
96
- console.log("add", result);
97
- }),
98
- execute("add2", a.toString(), b.toString()).then((result) => {
99
- console.log("add2", result);
100
- }),
101
- execute("sub", a, b).then((result) => {
102
- console.log("sub", result);
103
- }),
104
- execute("mul", a, b).then((result) => {
105
- console.log("sub", result);
106
- }),
107
- execute("error", a, b)
108
- .then((result) => {
109
- console.log("error", result);
110
- })
111
- .catch((e) => {
112
- console.error("error", e);
113
- }),
114
- ];
115
- console.log("Start");
116
- await Promise.all(p);
117
- close(); // Close the worker
118
- };
119
-
120
- main();
65
+ const result = await execute("add", 10, 20);
66
+ console.log(result); // 30
121
67
  ```
122
68
 
123
- ### Next.js (Web Worker)
124
-
125
- - src/libs/worker-test.ts
69
+ #### Browser / Next.js (Web Worker)
126
70
 
127
71
  ```ts
128
- import { initWorker } from "worker-lib";
129
-
130
- const add = (a: number, b: number) => {
131
- for (let i = 0; i < 1000000000; i++); //Overload unnecessarily
132
- return a + b;
133
- };
134
- const add2 = (a: string, b: string) => {
135
- for (let i = 0; i < 1000000000; i++); //Overload unnecessarily
136
- return a + b;
137
- };
138
- const sub = (a: number, b: number) => {
139
- for (let i = 0; i < 1000000000; i++); //Overload unnecessarily
140
- return a - b;
141
- };
142
- const mul = (a: number, b: number) => {
143
- for (let i = 0; i < 1000000000; i++); //Overload unnecessarily
144
- return a * b;
145
- };
72
+ import { createWorker } from "worker-lib";
73
+ import type { MyWorker } from "./worker";
146
74
 
147
- const error = (a: number, b: number) => {
148
- for (let i = 0; i < 1000000000; i++); //Overload unnecessarily
149
- throw new Error("throw");
150
- return a + b;
151
- };
75
+ const { execute } = createWorker<MyWorker>(
76
+ () => new Worker(new URL("./worker.ts", import.meta.url)),
77
+ 5
78
+ );
152
79
 
153
- // Initialization process to make it usable in Worker.
154
- const map = initWorker({ add, add2, sub, mul, error });
155
- // Export only the type
156
- export type WorkerTest = typeof map;
80
+ const result = await execute("heavyTask", "input-data", (percent, status) => {
81
+ console.log(`[${status}] ${percent}%`);
82
+ });
157
83
  ```
158
84
 
159
- ### Callback
160
-
161
- `worker-lib` supports passing callback functions to workers.
162
-
163
- - worker.ts
164
- ```ts
165
- import { initWorker } from "worker-lib";
166
-
167
- const progressTask = async (onProgress: (percent: number) => void) => {
168
- onProgress(10);
169
- // ... heavy task ...
170
- onProgress(50);
171
- // ... heavy task ...
172
- onProgress(100);
173
- return "Done";
174
- };
85
+ ## API Reference
175
86
 
176
- initWorker({ progressTask });
177
- ```
87
+ ### `initWorker(workerProcess)`
88
+ Initializes the worker side.
89
+ - `workerProcess`: An object containing the functions to be exposed.
178
90
 
179
- - main.ts
180
- ```ts
181
- const result = await execute("progressTask", (percent) => {
182
- console.log(`Progress: ${percent}%`);
183
- });
184
- ```
91
+ ### `createWorker(builder, limit?)`
92
+ Creates a worker pool.
93
+ - `builder`: A function that returns a new `Worker` instance.
94
+ - `limit`: (Optional) Maximum number of concurrent workers. Default is `4`.
185
95
 
186
- - src/app/page.tsx
96
+ ### `execute(name, ...args)`
97
+ Executes a worker function.
98
+ - `name`: The name of the function to execute.
99
+ - `args`: Arguments to pass to the function (supports callbacks).
187
100
 
188
- ```tsx
189
- "use client";
190
- import { useState } from "react";
191
- import { createWorker } from "worker-lib";
192
- import type { WorkerTest } from "../libs/worker-test";
101
+ ### `waitAll()`
102
+ Returns a promise that resolves when all currently running tasks are complete.
193
103
 
194
- // Create an instance to execute the Worker
195
- // execute("function name",... parameter) to start the Worker
196
- const execute = createWorker<WorkerTest>(
197
- () => new Worker(new URL("../libs/worker-test", import.meta.url)),
198
- 5 // Maximum parallel number
199
- );
104
+ ### `close()`
105
+ Terminates all workers in the pool.
200
106
 
201
- const Page = () => {
202
- const [values, setValues] = useState<(number | string)[]>([]);
203
- const [a, setA] = useState(300);
204
- const [b, setB] = useState(100);
107
+ ## Examples
205
108
 
206
- return (
207
- <div>
208
- <form>
209
- <input
210
- name="a"
211
- value={a}
212
- onChange={(e) => setA(Number(e.currentTarget.value))}
213
- />
214
- <input
215
- name="b"
216
- value={b}
217
- onChange={(e) => setB(Number(e.currentTarget.value))}
218
- />
219
- <button
220
- type="button"
221
- onClick={async () => {
222
- const index = values.length;
223
- setValues([...values, "running"]);
224
- //Calling a Worker
225
- const result = await execute("add", a, b);
226
- setValues((values) =>
227
- values.map((v, i) => (i === index ? result : v))
228
- );
229
- }}
230
- >
231
- Add
232
- </button>
233
- <button
234
- type="button"
235
- onClick={async () => {
236
- const index = values.length;
237
- setValues([...values, "running"]);
238
- //Calling a Worker
239
- const result = await execute("add2", String(a), String(b));
240
- setValues((values) =>
241
- values.map((v, i) => (i === index ? result : v))
242
- );
243
- }}
244
- >
245
- Add(String)
246
- </button>
247
- <button
248
- type="button"
249
- onClick={async () => {
250
- const index = values.length;
251
- setValues([...values, "running"]);
252
- //Calling a Worker
253
- const result = await execute("sub", a, b);
254
- setValues((values) =>
255
- values.map((v, i) => (i === index ? result : v))
256
- );
257
- }}
258
- >
259
- Sub
260
- </button>
261
- <button
262
- type="button"
263
- onClick={async () => {
264
- const index = values.length;
265
- setValues([...values, "running"]);
266
- //Calling a Worker
267
- const result = await execute("mul", a, b);
268
- setValues((values) =>
269
- values.map((v, i) => (i === index ? result : v))
270
- );
271
- }}
272
- >
273
- Mul
274
- </button>
275
- <button
276
- type="button"
277
- onClick={async () => {
278
- const index = values.length;
279
- setValues([...values, "running"]);
280
- //Calling a Worker
281
- const result = await execute("error", a, b).catch((e) => e);
282
- setValues((values) =>
283
- values.map((v, i) => (i === index ? result : v))
284
- );
285
- }}
286
- >
287
- Error
288
- </button>
289
- </form>
290
- {values.map((v, index) => (
291
- <div key={index}>{v}</div>
292
- ))}
293
- </div>
294
- );
295
- };
296
- export default Page;
297
- ```
109
+ For more detailed examples, check the [samples repository](https://github.com/SoraKumo001/worker-lib-samples/).
package/dist/cjs/index.js CHANGED
@@ -14,7 +14,7 @@ const exec = (worker, name, ...value) => {
14
14
  const { data } = result;
15
15
  switch (data.type) {
16
16
  case "callback":
17
- const r = value[data.payload.index](data.payload.value);
17
+ const r = value[data.payload.index](...data.payload.value);
18
18
  worker.postMessage({
19
19
  type: "callback_result",
20
20
  payload: { id: data.payload.id, result: await r },
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":";;;AAsBA,MAAM,IAAI,GAAG,CAAC,MAAc,EAAmB,EAAE;IAC/C,OAAO,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,EAAE;QAC7B,MAAM,CAAC,gBAAgB,CACrB,SAAS,EACT,GAAG,EAAE;YACH,OAAO,CAAC,MAAM,CAAC,CAAC;QAClB,CAAC,EACD,EAAE,IAAI,EAAE,IAAI,EAAE,CACf,CAAC;IACJ,CAAC,CAAC,CAAC;AACL,CAAC,CAAC;AACF,MAAM,IAAI,GAAG,CACX,MAAc,EACd,IAAa,EACb,GAAG,KAA6B,EACC,EAAE;IACnC,OAAO,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE;QACrC,MAAM,CAAC,GAAG,KAAK,EAAE,MAAwC,EAAE,EAAE;YAC3D,MAAM,EAAE,IAAI,EAAE,GAAG,MAAM,CAAC;YACxB,QAAQ,IAAI,CAAC,IAAI,EAAE,CAAC;gBAClB,KAAK,UAAU;oBACb,MAAM,CAAC,GAAG,KAAK,CAAC,IAAI,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC;oBACxD,MAAM,CAAC,WAAW,CAAC;wBACjB,IAAI,EAAE,iBAAiB;wBACvB,OAAO,EAAE,EAAE,EAAE,EAAE,IAAI,CAAC,OAAO,CAAC,EAAE,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE;qBAClD,CAAC,CAAC;oBACH,MAAM;gBACR,KAAK,QAAQ;oBACX,MAAM,CAAC,mBAAmB,CAAC,SAAS,EAAE,CAAC,CAAC,CAAC;oBACzC,OAAO,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;oBACtB,MAAM;gBACR,KAAK,OAAO;oBACV,MAAM,CAAC,mBAAmB,CAAC,SAAS,EAAE,CAAC,CAAC,CAAC;oBACzC,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;oBACrB,MAAM;YACV,CAAC;QACH,CAAC,CAAC;QACF,MAAM,CAAC,gBAAgB,CAAC,SAAS,EAAE,CAAC,CAAC,CAAC;QACtC,MAAM,CAAC,WAAW,CAAC;YACjB,IAAI,EAAE,UAAU;YAChB,OAAO,EAAE;gBACP,IAAI;gBACJ,KAAK,EAAE,KAAK,CAAC,GAAG,CAAC,CAAC,CAAU,EAAE,EAAE,CAAC,CAAC,CAAC,OAAO,CAAC,KAAK,UAAU,CAAC,IAAI,CAAC,CAAC;gBACjE,QAAQ,EAAE,KAAK,CAAC,GAAG,CAAC,CAAC,CAAU,EAAE,EAAE,CAAC,OAAO,CAAC,KAAK,UAAU,CAAC;aAC7D;SACoB,CAAC,CAAC;IAC3B,CAAC,CAAC,CAAC;AACL,CAAC,CAAC;AAEF;;;;;;;;;;;;;;GAcG;AACI,MAAM,YAAY,GAAG,CAC1B,OAAiD,EACjD,KAAK,GAAG,CAAC,EACT,EAAE;IACF,IAAI,OAAO,GAGL,KAAK,CAAC,KAAK,CAAC;SACf,IAAI,CAAC,SAAS,CAAC;SACf,GAAG,CAAC,GAAG,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;IACnB,MAAM,UAAU,GAAiC,EAAE,CAAC;IACpD,IAAI,WAAW,GAAG,KAAK,CAAC;IAExB,MAAM,WAAW,GAAG,KAAK,IAAI,EAAE;QAC7B,OAAO,IAAI,EAAE,CAAC;YACZ,MAAM,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC,EAAE,cAAc,EAAE,EAAE,EAAE,CAAC,CAAC,cAAc,CAAC,CAAC;YACrE,IAAI,MAAM,EAAE,CAAC;gBACX,MAAM,CAAC,cAAc,GAAG,OAAO,CAAC,aAAa,EAAW,CAAC;gBACzD,IAAI,CAAC,MAAM,CAAC,MAAM,EAAE,CAAC;oBACnB,MAAM,MAAM,GAAG,OAAO,EAAE,CAAC;oBACzB,MAAM,MAAM,GACV,MAAM,YAAY,MAAM;wBACtB,CAAC,CAAC,MAAM;wBACR,CAAC,CAAC,IAAI,MAAM,CAAC,MAAsB,CAAC,CAAC;oBACzC,MAAM,CAAC,MAAM,GAAG,MAAM,IAAI,CAAC,MAAM,CAAC,CAAC;gBACrC,CAAC;gBACD,OAAO,MAAM,CAAC;YAChB,CAAC;YACD,MAAM,OAAO,CAAC,IAAI,CAChB,OAAO,CAAC,GAAG,CAAC,CAAC,EAAE,cAAc,EAAE,EAAE,EAAE,CAAC,cAAc,EAAE,OAAO,CAAC,CAC7D,CAAC;QACJ,CAAC;IACH,CAAC,CAAC;IAEF;;;;;;OAMG;IACH,MAAM,OAAO,GAAG,KAAK,EACnB,IAAO,EACP,GAAG,KAAuB,EACU,EAAE;QACtC,MAAM,MAAM,GAAG,MAAM,WAAW,EAAE,CAAC;QACnC,MAAM,EAAE,cAAc,EAAE,GAAG,MAAM,CAAC;QAClC,IAAI,CAAC,cAAc;YAAE,MAAM,IAAI,KAAK,CAAC,kBAAkB,CAAC,CAAC;QACzD,IAAI,CAAC,MAAM,CAAC,MAAO,EAAE,IAAc,EAAE,GAAG,KAAK,CAAC;aAC3C,IAAI,CAAC,cAAc,CAAC,OAAO,CAAC;aAC5B,KAAK,CAAC,cAAc,CAAC,MAAM,CAAC;aAC5B,OAAO,CAAC,GAAG,EAAE;YACZ,MAAM,CAAC,cAAc,GAAG,SAAS,CAAC;QACpC,CAAC,CAAC,CAAC;QACL,OAAO,cAAc,CAAC,OAA6C,CAAC;IACtE,CAAC,CAAC;IAEF;;;OAGG;IACH,MAAM,YAAY,GAAG,KAAK,IAAI,EAAE;QAC9B,OAAO,OAAO,CAAC,GAAG,CAChB,OAAO,CAAC,GAAG,CAAC,KAAK,EAAE,MAAM,EAAE,EAAE;YAC3B,IAAI,CAAC,MAAM,CAAC,MAAM,EAAE,CAAC;gBACnB,MAAM,MAAM,GAAG,OAAO,EAAE,CAAC;gBACzB,MAAM,MAAM,GACV,MAAM,YAAY,MAAM;oBACtB,CAAC,CAAC,MAAM;oBACR,CAAC,CAAC,IAAI,MAAM,CAAC,MAAsB,CAAC,CAAC;gBACzC,MAAM,CAAC,MAAM,GAAG,MAAM,IAAI,CAAC,MAAM,CAAC,CAAC;YACrC,CAAC;QACH,CAAC,CAAC,CACH,CAAC;IACJ,CAAC,CAAC;IAEF;;;OAGG;IACH,MAAM,OAAO,GAAG,KAAK,IAAI,EAAE;QACzB,OAAO,OAAO,CAAC,IAAI,CAAC,CAAC,EAAE,cAAc,EAAE,EAAE,EAAE,CAAC,cAAc,CAAC,EAAE,CAAC;YAC5D,MAAM,OAAO,CAAC,GAAG,CACf,OAAO,CAAC,OAAO,CAAC,CAAC,EAAE,cAAc,EAAE,EAAE,EAAE,CACrC,cAAc,CAAC,CAAC,CAAC,CAAC,cAAc,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,EAAE,CAC/C,CACF,CAAC;QACJ,CAAC;IACH,CAAC,CAAC;IAEF;;;;OAIG;IACH,MAAM,SAAS,GAAG,KAAK,EAAE,SAAS,GAAG,CAAC,EAAE,EAAE;QACxC,MAAM,CAAC,GAAG,OAAO,CAAC,aAAa,EAAQ,CAAC;QACxC,UAAU,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QACnB,CAAC,KAAK,IAAI,EAAE;YACV,IAAI,CAAC,WAAW,EAAE,CAAC;gBACjB,WAAW,GAAG,IAAI,CAAC;gBACnB,GAAG,CAAC;oBACF,MAAM,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC,EAAE,cAAc,EAAE,EAAE,EAAE,CACrD,cAAc,CAAC,CAAC,CAAC,CAAC,cAAc,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,EAAE,CAC/C,CAAC;oBACF,IAAI,OAAO,CAAC,MAAM,KAAK,OAAO,CAAC,MAAM;wBAAE,MAAM,OAAO,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;oBACnE,UAAU,CAAC,KAAK,EAAE,EAAE,OAAO,EAAE,CAAC;oBAC9B,IAAI,SAAS;wBAAE,MAAM,IAAI,OAAO,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,UAAU,CAAC,CAAC,EAAE,SAAS,CAAC,CAAC,CAAC;;wBAC7D,MAAM,OAAO,CAAC,OAAO,EAAE,CAAC;gBAC/B,CAAC,QAAQ,UAAU,CAAC,MAAM,EAAE;gBAC5B,WAAW,GAAG,KAAK,CAAC;YACtB,CAAC;QACH,CAAC,CAAC,EAAE,CAAC;QACL,OAAO,CAAC,CAAC,OAAO,CAAC;IACnB,CAAC,CAAC;IAEF;;OAEG;IACH,MAAM,KAAK,GAAG,GAAG,EAAE;QACjB,KAAK,MAAM,EAAE,MAAM,EAAE,IAAI,OAAO,EAAE,CAAC;YACjC,MAAM,EAAE,SAAS,EAAE,CAAC;QACtB,CAAC;IACH,CAAC,CAAC;IAEF;;;OAGG;IACH,MAAM,QAAQ,GAAG,CAAC,KAAa,EAAE,EAAE;QACjC,OAAO,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,MAAM,EAAE,SAAS,EAAE,CAAC,CAAC;QAC9C,OAAO,GAAG,KAAK,CAAC,KAAK,CAAC;aACnB,IAAI,CAAC,SAAS,CAAC;aACf,GAAG,CAAC,GAAG,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;IACrB,CAAC,CAAC;IACF,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,SAAS,EAAE,KAAK,EAAE,QAAQ,EAAE,YAAY,EAAE,CAAC;AACxE,CAAC,CAAC;AAxIW,QAAA,YAAY,gBAwIvB;AAEF;;;;;;GAMG;AACI,MAAM,UAAU,GAAG,CAAuB,UAAa,EAAE,EAAE;IAChE,MAAM,MAAM,GAAG,IAAyB,CAAC;IACzC,MAAM,CAAC,gBAAgB,CAAC,SAAS,EAAE,KAAK,EAAE,CAAe,EAAE,EAAE;QAC3D,MAAM,IAAI,GAAG,CAAC,CAAC,IAA0B,CAAC;QAC1C,IAAI,IAAI,CAAC,IAAI,KAAK,UAAU,EAAE,CAAC;YAC7B,MAAM,EACJ,IAAI,EACJ,KAAK,EACL,QAAQ,GACT,GAIG,IAAI,CAAC,OAAO,CAAC;YACjB,MAAM,IAAI,GAAG,UAAU,CAAC,IAAI,CAAC,CAAC;YAC9B,IAAI,IAAI,EAAE,CAAC;gBACT,IAAI,CAAC;oBACH,MAAM,MAAM,GAAG,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,EAAE,CACpC,QAAQ,CAAC,KAAK,CAAC;wBACb,CAAC,CAAC,CAAC,GAAG,MAAiB,EAAE,EAAE,CAAC,YAAY,CAAI,MAAM,EAAE,KAAK,EAAE,MAAM,CAAC;wBAClE,CAAC,CAAC,CAAC,CACN,CAAC;oBACF,MAAM,CAAC,WAAW,CAAC;wBACjB,IAAI,EAAE,QAAQ;wBACd,OAAO,EAAE,MAAM,IAAI,CAAC,GAAG,MAAM,CAAC;qBAC/B,CAAC,CAAC;gBACL,CAAC;gBAAC,OAAO,CAAC,EAAE,CAAC;oBACX,MAAM,CAAC,WAAW,CAAC,EAAE,IAAI,EAAE,OAAO,EAAE,OAAO,EAAE,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;gBAC5D,CAAC;YACH,CAAC;QACH,CAAC;IACH,CAAC,CAAC,CAAC;IACH,MAAM,CAAC,WAAW,CAAC,SAAS,CAAC,CAAC;IAC9B,OAAO,UAAU,CAAC;AACpB,CAAC,CAAC;AAlCW,QAAA,UAAU,cAkCrB;AAEF,MAAM,YAAY,GAAG,CAAI,MAAc,EAAE,KAAa,EAAE,MAAiB,EAAE,EAAE;IAC3E,MAAM,EAAE,GAAG,WAAW,CAAC,EAAE,EAAE,CAAC;IAC5B,OAAO,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,EAAE;QAC7B,MAAM,CAAC,gBAAgB,CACrB,SAAS,EACT,CAAC,CAAe,EAAE,EAAE;YAClB,MAAM,IAAI,GAAG,CAAC,CAAC,IAA0B,CAAC;YAC1C,IAAI,IAAI,CAAC,IAAI,KAAK,iBAAiB,IAAI,IAAI,CAAC,OAAO,CAAC,EAAE,KAAK,EAAE,EAAE,CAAC;gBAC9D,OAAO,CAAC,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC;YAC/B,CAAC;QACH,CAAC,EACD,EAAE,IAAI,EAAE,IAAI,EAAE,CACf,CAAC;QACF,MAAM,CAAC,WAAW,CAAC;YACjB,IAAI,EAAE,UAAU;YAChB,OAAO,EAAE,EAAE,EAAE,EAAE,KAAK,EAAE,KAAK,EAAE,MAAM,EAAE;SACtC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;AACL,CAAC,CAAC;AAEF,MAAM,WAAW,GAAG,EAAE,EAAE,EAAE,CAAC,EAAE,QAAQ,EAAE,EAAE,EAGxC,CAAC","sourcesContent":["import type { Worker as WorkerNode } from \"node:worker_threads\";\ntype WorkerType = { [key: string]: (...args: any) => any };\ntype WorkerRecvEvent<T> =\n | {\n type: \"function\";\n payload: { name: keyof T; callback: boolean[]; value: unknown[] };\n }\n | { type: \"callback_result\"; payload: { id: number; result: unknown } };\ntype WorkerSendEvent<T extends WorkerType> =\n | {\n type: \"callback\";\n payload: { id: number; result: unknown; index: number; value: T };\n }\n | {\n type: \"result\";\n payload: ReturnType<T[keyof T]>;\n }\n | {\n type: \"error\";\n payload: unknown;\n };\n\nconst init = (worker: Worker): Promise<Worker> => {\n return new Promise((resolve) => {\n worker.addEventListener(\n \"message\",\n () => {\n resolve(worker);\n },\n { once: true }\n );\n });\n};\nconst exec = <T extends WorkerType>(\n worker: Worker,\n name: keyof T,\n ...value: Parameters<T[keyof T]>\n): Promise<ReturnType<T[keyof T]>> => {\n return new Promise((resolve, reject) => {\n const p = async (result: MessageEvent<WorkerSendEvent<T>>) => {\n const { data } = result;\n switch (data.type) {\n case \"callback\":\n const r = value[data.payload.index](data.payload.value);\n worker.postMessage({\n type: \"callback_result\",\n payload: { id: data.payload.id, result: await r },\n });\n break;\n case \"result\":\n worker.removeEventListener(\"message\", p);\n resolve(data.payload);\n break;\n case \"error\":\n worker.removeEventListener(\"message\", p);\n reject(data.payload);\n break;\n }\n };\n worker.addEventListener(\"message\", p);\n worker.postMessage({\n type: \"function\",\n payload: {\n name,\n value: value.map((v: unknown) => !(typeof v === \"function\") && v),\n callback: value.map((v: unknown) => typeof v === \"function\"),\n },\n } as WorkerRecvEvent<T>);\n });\n};\n\n/**\n * Creates a worker pool with a specified limit of concurrent workers.\n *\n * @template T - The type of the worker.\n * @param {() => Worker | WorkerNode} builder - A function that returns a new Worker or WorkerNode instance.\n * @param {number} [limit=4] - The maximum number of concurrent workers.\n * @returns {{\n * execute: <K extends keyof T>(name: K, ...value: Parameters<T[K]>) => Promise<Awaited<ReturnType<T[K]>>>,\n * waitAll: () => Promise<void>,\n * waitReady: (retryTime?: number) => Promise<void>,\n * close: () => void,\n * setLimit: (limit: number) => void,\n * launchWorker: () => Promise<void[]>\n * }} An object containing methods to interact with the worker pool.\n */\nexport const createWorker = <T extends WorkerType>(\n builder: () => Worker | WorkerNode | string | URL,\n limit = 4\n) => {\n let workers: {\n worker?: Worker;\n resultResolver?: PromiseWithResolvers<unknown>;\n }[] = Array(limit)\n .fill(undefined)\n .map(() => ({}));\n const emptyWaits: PromiseWithResolvers<void>[] = [];\n let isEmptyWait = false;\n\n const getResolver = async () => {\n while (true) {\n const target = workers.find(({ resultResolver }) => !resultResolver);\n if (target) {\n target.resultResolver = Promise.withResolvers<unknown>();\n if (!target.worker) {\n const result = builder();\n const worker =\n result instanceof Worker\n ? result\n : new Worker(result as string | URL);\n target.worker = await init(worker);\n }\n return target;\n }\n await Promise.race(\n workers.map(({ resultResolver }) => resultResolver?.promise)\n );\n }\n };\n\n /**\n * @method execute - Executes a method on a worker.\n * @template K - The key of the method to execute.\n * @param {K} name - The name of the method to execute.\n * @param {...Parameters<T[K]>} value - The arguments to pass to the method.\n * @returns {Promise<Awaited<ReturnType<T[K]>>>} A promise that resolves with the result of the method.\n */\n const execute = async <K extends keyof T>(\n name: K,\n ...value: Parameters<T[K]>\n ): Promise<Awaited<ReturnType<T[K]>>> => {\n const target = await getResolver();\n const { resultResolver } = target;\n if (!resultResolver) throw new Error(\"Unexpected error\");\n exec(target.worker!, name as string, ...value)\n .then(resultResolver.resolve)\n .catch(resultResolver.reject)\n .finally(() => {\n target.resultResolver = undefined;\n });\n return resultResolver.promise as Promise<Awaited<ReturnType<T[K]>>>;\n };\n\n /**\n * @method launchWorker - Launches all workers in the pool.\n * @returns {Promise<void[]>} A promise that resolves when all workers have been launched.\n */\n const launchWorker = async () => {\n return Promise.all(\n workers.map(async (target) => {\n if (!target.worker) {\n const result = builder();\n const worker =\n result instanceof Worker\n ? result\n : new Worker(result as string | URL);\n target.worker = await init(worker);\n }\n })\n );\n };\n\n /**\n * @method waitAll - Waits for all workers to complete their tasks.\n * @returns {Promise<void>} A promise that resolves when all workers have completed their tasks.\n */\n const waitAll = async () => {\n while (workers.find(({ resultResolver }) => resultResolver)) {\n await Promise.all(\n workers.flatMap(({ resultResolver }) =>\n resultResolver ? [resultResolver.promise] : []\n )\n );\n }\n };\n\n /**\n * @method waitReady - Waits for the worker pool to be ready.\n * @param {number} [retryTime=1] - The time to wait between retries in milliseconds.\n * @returns {Promise<void>} A promise that resolves when the worker pool is ready.\n */\n const waitReady = async (retryTime = 1) => {\n const p = Promise.withResolvers<void>();\n emptyWaits.push(p);\n (async () => {\n if (!isEmptyWait) {\n isEmptyWait = true;\n do {\n const actives = workers.flatMap(({ resultResolver }) =>\n resultResolver ? [resultResolver.promise] : []\n );\n if (workers.length === actives.length) await Promise.race(actives);\n emptyWaits.shift()?.resolve();\n if (retryTime) await new Promise((r) => setTimeout(r, retryTime));\n else await Promise.resolve();\n } while (emptyWaits.length);\n isEmptyWait = false;\n }\n })();\n return p.promise;\n };\n\n /**\n * @method close - Terminates all workers in the pool.\n */\n const close = () => {\n for (const { worker } of workers) {\n worker?.terminate();\n }\n };\n\n /**\n * @method setLimit - Sets a new limit for the number of concurrent workers.\n * @param {number} limit - The new limit for the number of concurrent workers.\n */\n const setLimit = (limit: number) => {\n workers.forEach((w) => w.worker?.terminate());\n workers = Array(limit)\n .fill(undefined)\n .map(() => ({}));\n };\n return { execute, waitAll, waitReady, close, setLimit, launchWorker };\n};\n\n/**\n * Initializes a web worker with the provided worker process.\n *\n * @template T - The type of the worker process.\n * @param {T} WorkerProc - The worker process to initialize.\n * @returns {T} The initialized worker process.\n */\nexport const initWorker = <T extends WorkerType>(WorkerProc: T) => {\n const worker = self as unknown as Worker;\n worker.addEventListener(\"message\", async (e: MessageEvent) => {\n const data = e.data as WorkerRecvEvent<T>;\n if (data.type === \"function\") {\n const {\n name,\n value,\n callback,\n }: {\n name: keyof T;\n value: unknown[];\n callback: boolean[];\n } = data.payload;\n const proc = WorkerProc[name];\n if (proc) {\n try {\n const params = value.map((v, index) =>\n callback[index]\n ? (...params: unknown[]) => callbackProc<T>(worker, index, params)\n : v\n );\n worker.postMessage({\n type: \"result\",\n payload: await proc(...params),\n });\n } catch (e) {\n worker.postMessage({ type: \"error\", payload: String(e) });\n }\n }\n }\n });\n worker.postMessage(undefined);\n return WorkerProc;\n};\n\nconst callbackProc = <T>(worker: Worker, index: number, params: unknown[]) => {\n const id = WorkerValue.id++;\n return new Promise((resolve) => {\n worker.addEventListener(\n \"message\",\n (e: MessageEvent) => {\n const data = e.data as WorkerRecvEvent<T>;\n if (data.type === \"callback_result\" && data.payload.id === id) {\n resolve(data.payload.result);\n }\n },\n { once: true }\n );\n worker.postMessage({\n type: \"callback\",\n payload: { id, index, value: params },\n });\n });\n};\n\nconst WorkerValue = { id: 0, promises: {} } as {\n id: number;\n promises: { [key: number]: Promise<unknown> };\n};\n"]}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"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","sourcesContent":["import type { Worker as WorkerNode } from \"node:worker_threads\";\ntype WorkerType = { [key: string]: (...args: any) => any };\ntype CallbackValue<T extends WorkerType> = Parameters<\n Extract<Parameters<T[keyof T]>[number], (...args: any) => any>\n>;\ntype WorkerRecvEvent<T extends WorkerType> =\n | {\n type: \"function\";\n payload: { name: keyof T; callback: boolean[]; value: unknown[] };\n }\n | { type: \"callback_result\"; payload: { id: number; result: unknown } };\ntype WorkerSendEvent<T extends WorkerType> =\n | {\n type: \"callback\";\n payload: {\n id: number;\n result: unknown;\n index: number;\n value: CallbackValue<T>;\n };\n }\n | {\n type: \"result\";\n payload: ReturnType<T[keyof T]>;\n }\n | {\n type: \"error\";\n payload: unknown;\n };\n\nconst init = (worker: Worker): Promise<Worker> => {\n return new Promise((resolve) => {\n worker.addEventListener(\n \"message\",\n () => {\n resolve(worker);\n },\n { once: true }\n );\n });\n};\nconst exec = <T extends WorkerType>(\n worker: Worker,\n name: keyof T,\n ...value: Parameters<T[keyof T]>\n): Promise<ReturnType<T[keyof T]>> => {\n return new Promise((resolve, reject) => {\n const p = async (result: MessageEvent<WorkerSendEvent<T>>) => {\n const { data } = result;\n switch (data.type) {\n case \"callback\":\n const r = value[data.payload.index](...data.payload.value);\n worker.postMessage({\n type: \"callback_result\",\n payload: { id: data.payload.id, result: await r },\n });\n break;\n case \"result\":\n worker.removeEventListener(\"message\", p);\n resolve(data.payload);\n break;\n case \"error\":\n worker.removeEventListener(\"message\", p);\n reject(data.payload);\n break;\n }\n };\n worker.addEventListener(\"message\", p);\n worker.postMessage({\n type: \"function\",\n payload: {\n name,\n value: value.map((v: unknown) => !(typeof v === \"function\") && v),\n callback: value.map((v: unknown) => typeof v === \"function\"),\n },\n } as WorkerRecvEvent<T>);\n });\n};\n\n/**\n * Creates a worker pool with a specified limit of concurrent workers.\n *\n * @template T - The type of the worker.\n * @param {() => Worker | WorkerNode} builder - A function that returns a new Worker or WorkerNode instance.\n * @param {number} [limit=4] - The maximum number of concurrent workers.\n * @returns {{\n * execute: <K extends keyof T>(name: K, ...value: Parameters<T[K]>) => Promise<Awaited<ReturnType<T[K]>>>,\n * waitAll: () => Promise<void>,\n * waitReady: (retryTime?: number) => Promise<void>,\n * close: () => void,\n * setLimit: (limit: number) => void,\n * launchWorker: () => Promise<void[]>\n * }} An object containing methods to interact with the worker pool.\n */\nexport const createWorker = <T extends WorkerType>(\n builder: () => Worker | WorkerNode | string | URL,\n limit = 4\n) => {\n let workers: {\n worker?: Worker;\n resultResolver?: PromiseWithResolvers<unknown>;\n }[] = Array(limit)\n .fill(undefined)\n .map(() => ({}));\n const emptyWaits: PromiseWithResolvers<void>[] = [];\n let isEmptyWait = false;\n\n const getResolver = async () => {\n while (true) {\n const target = workers.find(({ resultResolver }) => !resultResolver);\n if (target) {\n target.resultResolver = Promise.withResolvers<unknown>();\n if (!target.worker) {\n const result = builder();\n const worker =\n result instanceof Worker\n ? result\n : new Worker(result as string | URL);\n target.worker = await init(worker);\n }\n return target;\n }\n await Promise.race(\n workers.map(({ resultResolver }) => resultResolver?.promise)\n );\n }\n };\n\n /**\n * @method execute - Executes a method on a worker.\n * @template K - The key of the method to execute.\n * @param {K} name - The name of the method to execute.\n * @param {...Parameters<T[K]>} value - The arguments to pass to the method.\n * @returns {Promise<Awaited<ReturnType<T[K]>>>} A promise that resolves with the result of the method.\n */\n const execute = async <K extends keyof T>(\n name: K,\n ...value: Parameters<T[K]>\n ): Promise<Awaited<ReturnType<T[K]>>> => {\n const target = await getResolver();\n const { resultResolver } = target;\n if (!resultResolver) throw new Error(\"Unexpected error\");\n exec(target.worker!, name as string, ...value)\n .then(resultResolver.resolve)\n .catch(resultResolver.reject)\n .finally(() => {\n target.resultResolver = undefined;\n });\n return resultResolver.promise as Promise<Awaited<ReturnType<T[K]>>>;\n };\n\n /**\n * @method launchWorker - Launches all workers in the pool.\n * @returns {Promise<void[]>} A promise that resolves when all workers have been launched.\n */\n const launchWorker = async () => {\n return Promise.all(\n workers.map(async (target) => {\n if (!target.worker) {\n const result = builder();\n const worker =\n result instanceof Worker\n ? result\n : new Worker(result as string | URL);\n target.worker = await init(worker);\n }\n })\n );\n };\n\n /**\n * @method waitAll - Waits for all workers to complete their tasks.\n * @returns {Promise<void>} A promise that resolves when all workers have completed their tasks.\n */\n const waitAll = async () => {\n while (workers.find(({ resultResolver }) => resultResolver)) {\n await Promise.all(\n workers.flatMap(({ resultResolver }) =>\n resultResolver ? [resultResolver.promise] : []\n )\n );\n }\n };\n\n /**\n * @method waitReady - Waits for the worker pool to be ready.\n * @param {number} [retryTime=1] - The time to wait between retries in milliseconds.\n * @returns {Promise<void>} A promise that resolves when the worker pool is ready.\n */\n const waitReady = async (retryTime = 1) => {\n const p = Promise.withResolvers<void>();\n emptyWaits.push(p);\n (async () => {\n if (!isEmptyWait) {\n isEmptyWait = true;\n do {\n const actives = workers.flatMap(({ resultResolver }) =>\n resultResolver ? [resultResolver.promise] : []\n );\n if (workers.length === actives.length) await Promise.race(actives);\n emptyWaits.shift()?.resolve();\n if (retryTime) await new Promise((r) => setTimeout(r, retryTime));\n else await Promise.resolve();\n } while (emptyWaits.length);\n isEmptyWait = false;\n }\n })();\n return p.promise;\n };\n\n /**\n * @method close - Terminates all workers in the pool.\n */\n const close = () => {\n for (const { worker } of workers) {\n worker?.terminate();\n }\n };\n\n /**\n * @method setLimit - Sets a new limit for the number of concurrent workers.\n * @param {number} limit - The new limit for the number of concurrent workers.\n */\n const setLimit = (limit: number) => {\n workers.forEach((w) => w.worker?.terminate());\n workers = Array(limit)\n .fill(undefined)\n .map(() => ({}));\n };\n return { execute, waitAll, waitReady, close, setLimit, launchWorker };\n};\n\n/**\n * Initializes a web worker with the provided worker process.\n *\n * @template T - The type of the worker process.\n * @param {T} WorkerProc - The worker process to initialize.\n * @returns {T} The initialized worker process.\n */\nexport const initWorker = <T extends WorkerType>(WorkerProc: T) => {\n const worker = self as unknown as Worker;\n worker.addEventListener(\"message\", async (e: MessageEvent) => {\n const data = e.data as WorkerRecvEvent<T>;\n if (data.type === \"function\") {\n const {\n name,\n value,\n callback,\n }: {\n name: keyof T;\n value: unknown[];\n callback: boolean[];\n } = data.payload;\n const proc = WorkerProc[name];\n if (proc) {\n try {\n const params = value.map((v, index) =>\n callback[index]\n ? (...params: CallbackValue<T>) =>\n callbackProc<T>(worker, index, params)\n : v\n );\n worker.postMessage({\n type: \"result\",\n payload: await proc(...params),\n });\n } catch (e) {\n worker.postMessage({ type: \"error\", payload: String(e) });\n }\n }\n }\n });\n worker.postMessage(undefined);\n return WorkerProc;\n};\n\nconst callbackProc = <T extends WorkerType>(\n worker: Worker,\n index: number,\n params: CallbackValue<T>\n) => {\n const id = WorkerValue.id++;\n return new Promise((resolve) => {\n worker.addEventListener(\n \"message\",\n (e: MessageEvent) => {\n const data = e.data as WorkerRecvEvent<T>;\n if (data.type === \"callback_result\" && data.payload.id === id) {\n resolve(data.payload.result);\n }\n },\n { once: true }\n );\n worker.postMessage({\n type: \"callback\",\n payload: { id, index, value: params },\n });\n });\n};\n\nconst WorkerValue = { id: 0, promises: {} } as {\n id: number;\n promises: { [key: number]: Promise<unknown> };\n};\n"]}
package/dist/cjs/node.js CHANGED
@@ -14,7 +14,7 @@ const exec = (worker, name, ...value) => {
14
14
  const p = async (data) => {
15
15
  switch (data.type) {
16
16
  case "callback":
17
- const r = value[data.payload.index](data.payload.value);
17
+ const r = value[data.payload.index](...data.payload.value);
18
18
  worker.postMessage({
19
19
  type: "callback_result",
20
20
  payload: { id: data.payload.id, result: await r },
@@ -1 +1 @@
1
- {"version":3,"file":"node.js","sourceRoot":"","sources":["../../src/node.ts"],"names":[],"mappings":"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","sourcesContent":["import { parentPort, Worker } from \"node:worker_threads\";\ntype WorkerType = { [key: string]: (...args: any) => any };\ntype WorkerRecvEvent<T> =\n | {\n type: \"function\";\n payload: { name: keyof T; callback: boolean[]; value: unknown[] };\n }\n | { type: \"callback_result\"; payload: { id: number; result: unknown } };\ntype WorkerSendEvent<T extends WorkerType> =\n | {\n type: \"callback\";\n payload: { id: number; result: unknown; index: number; value: T };\n }\n | {\n type: \"result\";\n payload: ReturnType<T[keyof T]>;\n }\n | {\n type: \"error\";\n payload: unknown;\n };\n\nconst init = (worker: Worker): Promise<Worker> => {\n return new Promise((resolve) => {\n worker.once(\"message\", () => {\n resolve(worker);\n });\n });\n};\nconst exec = <T extends WorkerType>(\n worker: Worker,\n name: keyof T,\n ...value: Parameters<T[keyof T]>\n): Promise<ReturnType<T[keyof T]>> => {\n return new Promise((resolve, reject) => {\n const p = async (data: WorkerSendEvent<T>) => {\n switch (data.type) {\n case \"callback\":\n const r = value[data.payload.index](data.payload.value);\n worker.postMessage({\n type: \"callback_result\",\n payload: { id: data.payload.id, result: await r },\n });\n break;\n case \"result\":\n worker.removeListener(\"message\", p);\n resolve(data.payload);\n break;\n case \"error\":\n worker.removeListener(\"message\", p);\n reject(data.payload);\n break;\n }\n };\n worker.addListener(\"message\", p);\n worker.postMessage({\n type: \"function\",\n payload: {\n name,\n value: value.map((v: unknown) => !(typeof v === \"function\") && v),\n callback: value.map((v: unknown) => typeof v === \"function\"),\n },\n } as WorkerRecvEvent<T>);\n });\n};\n\n/**\n * Creates a worker pool with a specified limit of concurrent workers.\n *\n * @template T - The type of the worker.\n * @param {() => Worker | WorkerNode} builder - A function that returns a new Worker or WorkerNode instance.\n * @param {number} [limit=4] - The maximum number of concurrent workers.\n * @returns {{\n * execute: <K extends keyof T>(name: K, ...value: Parameters<T[K]>) => Promise<Awaited<ReturnType<T[K]>>>,\n * waitAll: () => Promise<void>,\n * waitReady: (retryTime?: number) => Promise<void>,\n * close: () => void,\n * setLimit: (limit: number) => void,\n * launchWorker: () => Promise<void[]>\n * }} An object containing methods to interact with the worker pool.\n */\nexport const createWorker = <T extends WorkerType>(\n builder: () => Worker | string | URL,\n limit = 4\n) => {\n let workers: {\n worker?: Worker;\n resultResolver?: PromiseWithResolvers<unknown>;\n }[] = Array(limit)\n .fill(undefined)\n .map(() => ({}));\n const emptyWaits: PromiseWithResolvers<void>[] = [];\n let isEmptyWait = false;\n\n const getResolver = async () => {\n while (true) {\n const target = workers.find(({ resultResolver }) => !resultResolver);\n if (target) {\n target.resultResolver = Promise.withResolvers<unknown>();\n if (!target.worker) {\n const result = builder();\n const worker = result instanceof Worker ? result : new Worker(result);\n target.worker = await init(worker);\n }\n return target;\n }\n await Promise.race(\n workers.map(({ resultResolver }) => resultResolver?.promise)\n );\n }\n };\n\n /**\n * @method execute - Executes a method on a worker.\n * @template K - The key of the method to execute.\n * @param {K} name - The name of the method to execute.\n * @param {...Parameters<T[K]>} value - The arguments to pass to the method.\n * @returns {Promise<Awaited<ReturnType<T[K]>>>} A promise that resolves with the result of the method.\n */\n const execute = async <K extends keyof T>(\n name: K,\n ...value: Parameters<T[K]>\n ): Promise<Awaited<ReturnType<T[K]>>> => {\n const target = await getResolver();\n const { resultResolver } = target;\n if (!resultResolver) throw new Error(\"Unexpected error\");\n exec(target.worker!, name as string, ...value)\n .then(resultResolver.resolve)\n .catch(resultResolver.reject)\n .finally(() => {\n target.resultResolver = undefined;\n });\n return resultResolver.promise as Promise<Awaited<ReturnType<T[K]>>>;\n };\n\n /**\n * @method launchWorker - Launches all workers in the pool.\n * @returns {Promise<void[]>} A promise that resolves when all workers have been launched.\n */\n const launchWorker = async () => {\n return Promise.all(\n workers.map(async (target) => {\n if (!target.worker) {\n const result = builder();\n const worker = result instanceof Worker ? result : new Worker(result);\n target.worker = await init(worker);\n }\n })\n );\n };\n\n /**\n * @method waitAll - Waits for all workers to complete their tasks.\n * @returns {Promise<void>} A promise that resolves when all workers have completed their tasks.\n */\n const waitAll = async () => {\n while (workers.find(({ resultResolver }) => resultResolver)) {\n await Promise.all(\n workers.flatMap(({ resultResolver }) =>\n resultResolver ? [resultResolver.promise] : []\n )\n );\n }\n };\n\n /**\n * @method waitReady - Waits for the worker pool to be ready.\n * @param {number} [retryTime=1] - The time to wait between retries in milliseconds.\n * @returns {Promise<void>} A promise that resolves when the worker pool is ready.\n */\n const waitReady = async (retryTime = 1) => {\n const p = Promise.withResolvers<void>();\n emptyWaits.push(p);\n (async () => {\n if (!isEmptyWait) {\n isEmptyWait = true;\n do {\n const actives = workers.flatMap(({ resultResolver }) =>\n resultResolver ? [resultResolver.promise] : []\n );\n if (workers.length === actives.length) await Promise.race(actives);\n emptyWaits.shift()?.resolve();\n if (retryTime) await new Promise((r) => setTimeout(r, retryTime));\n else await Promise.resolve();\n } while (emptyWaits.length);\n isEmptyWait = false;\n }\n })();\n return p.promise;\n };\n\n /**\n * @method close - Terminates all workers in the pool.\n */\n const close = () => {\n for (const { worker } of workers) {\n worker?.terminate();\n }\n };\n\n /**\n * @method setLimit - Sets a new limit for the number of concurrent workers.\n * @param {number} limit - The new limit for the number of concurrent workers.\n */\n const setLimit = (limit: number) => {\n workers.forEach((w) => w.worker?.terminate());\n workers = Array(limit)\n .fill(undefined)\n .map(() => ({}));\n };\n return { execute, waitAll, waitReady, close, setLimit, launchWorker };\n};\n\n/**\n * Initializes a web worker with the provided worker process.\n *\n * @template T - The type of the worker process.\n * @param {T} WorkerProc - The worker process to initialize.\n * @returns {T} The initialized worker process.\n */\nexport const initWorker = <T extends WorkerType>(WorkerProc: T) => {\n const worker = parentPort;\n if (!worker) {\n throw new Error(\"This is not a worker thread\");\n }\n worker.addListener(\"message\", async (data: WorkerRecvEvent<T>) => {\n if (data.type === \"function\") {\n const {\n name,\n value,\n callback,\n }: {\n name: keyof T;\n value: unknown[];\n callback: boolean[];\n } = data.payload;\n const proc = WorkerProc[name];\n if (proc) {\n try {\n const params = value.map((v, index) =>\n callback[index]\n ? (...params: unknown[]) =>\n callbackProc<T>(worker as never, index, params)\n : v\n );\n worker.postMessage({\n type: \"result\",\n payload: await proc(...params),\n });\n } catch (e) {\n worker.postMessage({ type: \"error\", payload: String(e) });\n }\n }\n }\n });\n worker.postMessage(undefined);\n return WorkerProc;\n};\n\nconst callbackProc = <T>(worker: Worker, index: number, params: unknown[]) => {\n const id = WorkerValue.id++;\n return new Promise((resolve) => {\n worker.once(\"message\", (data: WorkerRecvEvent<T>) => {\n if (data.type === \"callback_result\" && data.payload.id === id) {\n resolve(data.payload.result);\n }\n });\n worker.postMessage({\n type: \"callback\",\n payload: { id, index, value: params },\n });\n });\n};\n\nconst WorkerValue = { id: 0, promises: {} } as {\n id: number;\n promises: { [key: number]: Promise<unknown> };\n};\n"]}
1
+ {"version":3,"file":"node.js","sourceRoot":"","sources":["../../src/node.ts"],"names":[],"mappings":"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","sourcesContent":["import { parentPort, Worker } from \"node:worker_threads\";\ntype WorkerType = { [key: string]: (...args: any) => any };\ntype CallbackValue<T extends WorkerType> = Parameters<\n Extract<Parameters<T[keyof T]>[number], (...args: any) => any>\n>;\ntype WorkerRecvEvent<T extends WorkerType> =\n | {\n type: \"function\";\n payload: { name: keyof T; callback: boolean[]; value: unknown[] };\n }\n | { type: \"callback_result\"; payload: { id: number; result: unknown } };\ntype WorkerSendEvent<T extends WorkerType> =\n | {\n type: \"callback\";\n payload: {\n id: number;\n result: unknown;\n index: number;\n value: CallbackValue<T>;\n };\n }\n | {\n type: \"result\";\n payload: ReturnType<T[keyof T]>;\n }\n | {\n type: \"error\";\n payload: unknown;\n };\n\nconst init = (worker: Worker): Promise<Worker> => {\n return new Promise((resolve) => {\n worker.once(\"message\", () => {\n resolve(worker);\n });\n });\n};\nconst exec = <T extends WorkerType>(\n worker: Worker,\n name: keyof T,\n ...value: Parameters<T[keyof T]>\n): Promise<ReturnType<T[keyof T]>> => {\n return new Promise((resolve, reject) => {\n const p = async (data: WorkerSendEvent<T>) => {\n switch (data.type) {\n case \"callback\":\n const r = value[data.payload.index](...data.payload.value);\n worker.postMessage({\n type: \"callback_result\",\n payload: { id: data.payload.id, result: await r },\n });\n break;\n case \"result\":\n worker.removeListener(\"message\", p);\n resolve(data.payload);\n break;\n case \"error\":\n worker.removeListener(\"message\", p);\n reject(data.payload);\n break;\n }\n };\n worker.addListener(\"message\", p);\n worker.postMessage({\n type: \"function\",\n payload: {\n name,\n value: value.map((v: unknown) => !(typeof v === \"function\") && v),\n callback: value.map((v: unknown) => typeof v === \"function\"),\n },\n } as WorkerRecvEvent<T>);\n });\n};\n\n/**\n * Creates a worker pool with a specified limit of concurrent workers.\n *\n * @template T - The type of the worker.\n * @param {() => Worker | WorkerNode} builder - A function that returns a new Worker or WorkerNode instance.\n * @param {number} [limit=4] - The maximum number of concurrent workers.\n * @returns {{\n * execute: <K extends keyof T>(name: K, ...value: Parameters<T[K]>) => Promise<Awaited<ReturnType<T[K]>>>,\n * waitAll: () => Promise<void>,\n * waitReady: (retryTime?: number) => Promise<void>,\n * close: () => void,\n * setLimit: (limit: number) => void,\n * launchWorker: () => Promise<void[]>\n * }} An object containing methods to interact with the worker pool.\n */\nexport const createWorker = <T extends WorkerType>(\n builder: () => Worker | string | URL,\n limit = 4\n) => {\n let workers: {\n worker?: Worker;\n resultResolver?: PromiseWithResolvers<unknown>;\n }[] = Array(limit)\n .fill(undefined)\n .map(() => ({}));\n const emptyWaits: PromiseWithResolvers<void>[] = [];\n let isEmptyWait = false;\n\n const getResolver = async () => {\n while (true) {\n const target = workers.find(({ resultResolver }) => !resultResolver);\n if (target) {\n target.resultResolver = Promise.withResolvers<unknown>();\n if (!target.worker) {\n const result = builder();\n const worker = result instanceof Worker ? result : new Worker(result);\n target.worker = await init(worker);\n }\n return target;\n }\n await Promise.race(\n workers.map(({ resultResolver }) => resultResolver?.promise)\n );\n }\n };\n\n /**\n * @method execute - Executes a method on a worker.\n * @template K - The key of the method to execute.\n * @param {K} name - The name of the method to execute.\n * @param {...Parameters<T[K]>} value - The arguments to pass to the method.\n * @returns {Promise<Awaited<ReturnType<T[K]>>>} A promise that resolves with the result of the method.\n */\n const execute = async <K extends keyof T>(\n name: K,\n ...value: Parameters<T[K]>\n ): Promise<Awaited<ReturnType<T[K]>>> => {\n const target = await getResolver();\n const { resultResolver } = target;\n if (!resultResolver) throw new Error(\"Unexpected error\");\n exec(target.worker!, name as string, ...value)\n .then(resultResolver.resolve)\n .catch(resultResolver.reject)\n .finally(() => {\n target.resultResolver = undefined;\n });\n return resultResolver.promise as Promise<Awaited<ReturnType<T[K]>>>;\n };\n\n /**\n * @method launchWorker - Launches all workers in the pool.\n * @returns {Promise<void[]>} A promise that resolves when all workers have been launched.\n */\n const launchWorker = async () => {\n return Promise.all(\n workers.map(async (target) => {\n if (!target.worker) {\n const result = builder();\n const worker = result instanceof Worker ? result : new Worker(result);\n target.worker = await init(worker);\n }\n })\n );\n };\n\n /**\n * @method waitAll - Waits for all workers to complete their tasks.\n * @returns {Promise<void>} A promise that resolves when all workers have completed their tasks.\n */\n const waitAll = async () => {\n while (workers.find(({ resultResolver }) => resultResolver)) {\n await Promise.all(\n workers.flatMap(({ resultResolver }) =>\n resultResolver ? [resultResolver.promise] : []\n )\n );\n }\n };\n\n /**\n * @method waitReady - Waits for the worker pool to be ready.\n * @param {number} [retryTime=1] - The time to wait between retries in milliseconds.\n * @returns {Promise<void>} A promise that resolves when the worker pool is ready.\n */\n const waitReady = async (retryTime = 1) => {\n const p = Promise.withResolvers<void>();\n emptyWaits.push(p);\n (async () => {\n if (!isEmptyWait) {\n isEmptyWait = true;\n do {\n const actives = workers.flatMap(({ resultResolver }) =>\n resultResolver ? [resultResolver.promise] : []\n );\n if (workers.length === actives.length) await Promise.race(actives);\n emptyWaits.shift()?.resolve();\n if (retryTime) await new Promise((r) => setTimeout(r, retryTime));\n else await Promise.resolve();\n } while (emptyWaits.length);\n isEmptyWait = false;\n }\n })();\n return p.promise;\n };\n\n /**\n * @method close - Terminates all workers in the pool.\n */\n const close = () => {\n for (const { worker } of workers) {\n worker?.terminate();\n }\n };\n\n /**\n * @method setLimit - Sets a new limit for the number of concurrent workers.\n * @param {number} limit - The new limit for the number of concurrent workers.\n */\n const setLimit = (limit: number) => {\n workers.forEach((w) => w.worker?.terminate());\n workers = Array(limit)\n .fill(undefined)\n .map(() => ({}));\n };\n return { execute, waitAll, waitReady, close, setLimit, launchWorker };\n};\n\n/**\n * Initializes a web worker with the provided worker process.\n *\n * @template T - The type of the worker process.\n * @param {T} WorkerProc - The worker process to initialize.\n * @returns {T} The initialized worker process.\n */\nexport const initWorker = <T extends WorkerType>(WorkerProc: T) => {\n const worker = parentPort;\n if (!worker) {\n throw new Error(\"This is not a worker thread\");\n }\n worker.addListener(\"message\", async (data: WorkerRecvEvent<T>) => {\n if (data.type === \"function\") {\n const {\n name,\n value,\n callback,\n }: {\n name: keyof T;\n value: unknown[];\n callback: boolean[];\n } = data.payload;\n const proc = WorkerProc[name];\n if (proc) {\n try {\n const params = value.map((v, index) =>\n callback[index]\n ? (...params: CallbackValue<T>) =>\n callbackProc<T>(worker as never, index, params)\n : v\n );\n worker.postMessage({\n type: \"result\",\n payload: await proc(...params),\n });\n } catch (e) {\n worker.postMessage({ type: \"error\", payload: String(e) });\n }\n }\n }\n });\n worker.postMessage(undefined);\n return WorkerProc;\n};\n\nconst callbackProc = <T extends WorkerType>(\n worker: Worker,\n index: number,\n params: CallbackValue<T>\n) => {\n const id = WorkerValue.id++;\n return new Promise((resolve) => {\n worker.once(\"message\", (data: WorkerRecvEvent<T>) => {\n if (data.type === \"callback_result\" && data.payload.id === id) {\n resolve(data.payload.result);\n }\n });\n worker.postMessage({\n type: \"callback\",\n payload: { id, index, value: params },\n });\n });\n};\n\nconst WorkerValue = { id: 0, promises: {} } as {\n id: number;\n promises: { [key: number]: Promise<unknown> };\n};\n"]}
package/dist/esm/index.js CHANGED
@@ -11,7 +11,7 @@ const exec = (worker, name, ...value) => {
11
11
  const { data } = result;
12
12
  switch (data.type) {
13
13
  case "callback":
14
- const r = value[data.payload.index](data.payload.value);
14
+ const r = value[data.payload.index](...data.payload.value);
15
15
  worker.postMessage({
16
16
  type: "callback_result",
17
17
  payload: { id: data.payload.id, result: await r },
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"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","sourcesContent":["import type { Worker as WorkerNode } from \"node:worker_threads\";\ntype WorkerType = { [key: string]: (...args: any) => any };\ntype WorkerRecvEvent<T> =\n | {\n type: \"function\";\n payload: { name: keyof T; callback: boolean[]; value: unknown[] };\n }\n | { type: \"callback_result\"; payload: { id: number; result: unknown } };\ntype WorkerSendEvent<T extends WorkerType> =\n | {\n type: \"callback\";\n payload: { id: number; result: unknown; index: number; value: T };\n }\n | {\n type: \"result\";\n payload: ReturnType<T[keyof T]>;\n }\n | {\n type: \"error\";\n payload: unknown;\n };\n\nconst init = (worker: Worker): Promise<Worker> => {\n return new Promise((resolve) => {\n worker.addEventListener(\n \"message\",\n () => {\n resolve(worker);\n },\n { once: true }\n );\n });\n};\nconst exec = <T extends WorkerType>(\n worker: Worker,\n name: keyof T,\n ...value: Parameters<T[keyof T]>\n): Promise<ReturnType<T[keyof T]>> => {\n return new Promise((resolve, reject) => {\n const p = async (result: MessageEvent<WorkerSendEvent<T>>) => {\n const { data } = result;\n switch (data.type) {\n case \"callback\":\n const r = value[data.payload.index](data.payload.value);\n worker.postMessage({\n type: \"callback_result\",\n payload: { id: data.payload.id, result: await r },\n });\n break;\n case \"result\":\n worker.removeEventListener(\"message\", p);\n resolve(data.payload);\n break;\n case \"error\":\n worker.removeEventListener(\"message\", p);\n reject(data.payload);\n break;\n }\n };\n worker.addEventListener(\"message\", p);\n worker.postMessage({\n type: \"function\",\n payload: {\n name,\n value: value.map((v: unknown) => !(typeof v === \"function\") && v),\n callback: value.map((v: unknown) => typeof v === \"function\"),\n },\n } as WorkerRecvEvent<T>);\n });\n};\n\n/**\n * Creates a worker pool with a specified limit of concurrent workers.\n *\n * @template T - The type of the worker.\n * @param {() => Worker | WorkerNode} builder - A function that returns a new Worker or WorkerNode instance.\n * @param {number} [limit=4] - The maximum number of concurrent workers.\n * @returns {{\n * execute: <K extends keyof T>(name: K, ...value: Parameters<T[K]>) => Promise<Awaited<ReturnType<T[K]>>>,\n * waitAll: () => Promise<void>,\n * waitReady: (retryTime?: number) => Promise<void>,\n * close: () => void,\n * setLimit: (limit: number) => void,\n * launchWorker: () => Promise<void[]>\n * }} An object containing methods to interact with the worker pool.\n */\nexport const createWorker = <T extends WorkerType>(\n builder: () => Worker | WorkerNode | string | URL,\n limit = 4\n) => {\n let workers: {\n worker?: Worker;\n resultResolver?: PromiseWithResolvers<unknown>;\n }[] = Array(limit)\n .fill(undefined)\n .map(() => ({}));\n const emptyWaits: PromiseWithResolvers<void>[] = [];\n let isEmptyWait = false;\n\n const getResolver = async () => {\n while (true) {\n const target = workers.find(({ resultResolver }) => !resultResolver);\n if (target) {\n target.resultResolver = Promise.withResolvers<unknown>();\n if (!target.worker) {\n const result = builder();\n const worker =\n result instanceof Worker\n ? result\n : new Worker(result as string | URL);\n target.worker = await init(worker);\n }\n return target;\n }\n await Promise.race(\n workers.map(({ resultResolver }) => resultResolver?.promise)\n );\n }\n };\n\n /**\n * @method execute - Executes a method on a worker.\n * @template K - The key of the method to execute.\n * @param {K} name - The name of the method to execute.\n * @param {...Parameters<T[K]>} value - The arguments to pass to the method.\n * @returns {Promise<Awaited<ReturnType<T[K]>>>} A promise that resolves with the result of the method.\n */\n const execute = async <K extends keyof T>(\n name: K,\n ...value: Parameters<T[K]>\n ): Promise<Awaited<ReturnType<T[K]>>> => {\n const target = await getResolver();\n const { resultResolver } = target;\n if (!resultResolver) throw new Error(\"Unexpected error\");\n exec(target.worker!, name as string, ...value)\n .then(resultResolver.resolve)\n .catch(resultResolver.reject)\n .finally(() => {\n target.resultResolver = undefined;\n });\n return resultResolver.promise as Promise<Awaited<ReturnType<T[K]>>>;\n };\n\n /**\n * @method launchWorker - Launches all workers in the pool.\n * @returns {Promise<void[]>} A promise that resolves when all workers have been launched.\n */\n const launchWorker = async () => {\n return Promise.all(\n workers.map(async (target) => {\n if (!target.worker) {\n const result = builder();\n const worker =\n result instanceof Worker\n ? result\n : new Worker(result as string | URL);\n target.worker = await init(worker);\n }\n })\n );\n };\n\n /**\n * @method waitAll - Waits for all workers to complete their tasks.\n * @returns {Promise<void>} A promise that resolves when all workers have completed their tasks.\n */\n const waitAll = async () => {\n while (workers.find(({ resultResolver }) => resultResolver)) {\n await Promise.all(\n workers.flatMap(({ resultResolver }) =>\n resultResolver ? [resultResolver.promise] : []\n )\n );\n }\n };\n\n /**\n * @method waitReady - Waits for the worker pool to be ready.\n * @param {number} [retryTime=1] - The time to wait between retries in milliseconds.\n * @returns {Promise<void>} A promise that resolves when the worker pool is ready.\n */\n const waitReady = async (retryTime = 1) => {\n const p = Promise.withResolvers<void>();\n emptyWaits.push(p);\n (async () => {\n if (!isEmptyWait) {\n isEmptyWait = true;\n do {\n const actives = workers.flatMap(({ resultResolver }) =>\n resultResolver ? [resultResolver.promise] : []\n );\n if (workers.length === actives.length) await Promise.race(actives);\n emptyWaits.shift()?.resolve();\n if (retryTime) await new Promise((r) => setTimeout(r, retryTime));\n else await Promise.resolve();\n } while (emptyWaits.length);\n isEmptyWait = false;\n }\n })();\n return p.promise;\n };\n\n /**\n * @method close - Terminates all workers in the pool.\n */\n const close = () => {\n for (const { worker } of workers) {\n worker?.terminate();\n }\n };\n\n /**\n * @method setLimit - Sets a new limit for the number of concurrent workers.\n * @param {number} limit - The new limit for the number of concurrent workers.\n */\n const setLimit = (limit: number) => {\n workers.forEach((w) => w.worker?.terminate());\n workers = Array(limit)\n .fill(undefined)\n .map(() => ({}));\n };\n return { execute, waitAll, waitReady, close, setLimit, launchWorker };\n};\n\n/**\n * Initializes a web worker with the provided worker process.\n *\n * @template T - The type of the worker process.\n * @param {T} WorkerProc - The worker process to initialize.\n * @returns {T} The initialized worker process.\n */\nexport const initWorker = <T extends WorkerType>(WorkerProc: T) => {\n const worker = self as unknown as Worker;\n worker.addEventListener(\"message\", async (e: MessageEvent) => {\n const data = e.data as WorkerRecvEvent<T>;\n if (data.type === \"function\") {\n const {\n name,\n value,\n callback,\n }: {\n name: keyof T;\n value: unknown[];\n callback: boolean[];\n } = data.payload;\n const proc = WorkerProc[name];\n if (proc) {\n try {\n const params = value.map((v, index) =>\n callback[index]\n ? (...params: unknown[]) => callbackProc<T>(worker, index, params)\n : v\n );\n worker.postMessage({\n type: \"result\",\n payload: await proc(...params),\n });\n } catch (e) {\n worker.postMessage({ type: \"error\", payload: String(e) });\n }\n }\n }\n });\n worker.postMessage(undefined);\n return WorkerProc;\n};\n\nconst callbackProc = <T>(worker: Worker, index: number, params: unknown[]) => {\n const id = WorkerValue.id++;\n return new Promise((resolve) => {\n worker.addEventListener(\n \"message\",\n (e: MessageEvent) => {\n const data = e.data as WorkerRecvEvent<T>;\n if (data.type === \"callback_result\" && data.payload.id === id) {\n resolve(data.payload.result);\n }\n },\n { once: true }\n );\n worker.postMessage({\n type: \"callback\",\n payload: { id, index, value: params },\n });\n });\n};\n\nconst WorkerValue = { id: 0, promises: {} } as {\n id: number;\n promises: { [key: number]: Promise<unknown> };\n};\n"]}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"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","sourcesContent":["import type { Worker as WorkerNode } from \"node:worker_threads\";\ntype WorkerType = { [key: string]: (...args: any) => any };\ntype CallbackValue<T extends WorkerType> = Parameters<\n Extract<Parameters<T[keyof T]>[number], (...args: any) => any>\n>;\ntype WorkerRecvEvent<T extends WorkerType> =\n | {\n type: \"function\";\n payload: { name: keyof T; callback: boolean[]; value: unknown[] };\n }\n | { type: \"callback_result\"; payload: { id: number; result: unknown } };\ntype WorkerSendEvent<T extends WorkerType> =\n | {\n type: \"callback\";\n payload: {\n id: number;\n result: unknown;\n index: number;\n value: CallbackValue<T>;\n };\n }\n | {\n type: \"result\";\n payload: ReturnType<T[keyof T]>;\n }\n | {\n type: \"error\";\n payload: unknown;\n };\n\nconst init = (worker: Worker): Promise<Worker> => {\n return new Promise((resolve) => {\n worker.addEventListener(\n \"message\",\n () => {\n resolve(worker);\n },\n { once: true }\n );\n });\n};\nconst exec = <T extends WorkerType>(\n worker: Worker,\n name: keyof T,\n ...value: Parameters<T[keyof T]>\n): Promise<ReturnType<T[keyof T]>> => {\n return new Promise((resolve, reject) => {\n const p = async (result: MessageEvent<WorkerSendEvent<T>>) => {\n const { data } = result;\n switch (data.type) {\n case \"callback\":\n const r = value[data.payload.index](...data.payload.value);\n worker.postMessage({\n type: \"callback_result\",\n payload: { id: data.payload.id, result: await r },\n });\n break;\n case \"result\":\n worker.removeEventListener(\"message\", p);\n resolve(data.payload);\n break;\n case \"error\":\n worker.removeEventListener(\"message\", p);\n reject(data.payload);\n break;\n }\n };\n worker.addEventListener(\"message\", p);\n worker.postMessage({\n type: \"function\",\n payload: {\n name,\n value: value.map((v: unknown) => !(typeof v === \"function\") && v),\n callback: value.map((v: unknown) => typeof v === \"function\"),\n },\n } as WorkerRecvEvent<T>);\n });\n};\n\n/**\n * Creates a worker pool with a specified limit of concurrent workers.\n *\n * @template T - The type of the worker.\n * @param {() => Worker | WorkerNode} builder - A function that returns a new Worker or WorkerNode instance.\n * @param {number} [limit=4] - The maximum number of concurrent workers.\n * @returns {{\n * execute: <K extends keyof T>(name: K, ...value: Parameters<T[K]>) => Promise<Awaited<ReturnType<T[K]>>>,\n * waitAll: () => Promise<void>,\n * waitReady: (retryTime?: number) => Promise<void>,\n * close: () => void,\n * setLimit: (limit: number) => void,\n * launchWorker: () => Promise<void[]>\n * }} An object containing methods to interact with the worker pool.\n */\nexport const createWorker = <T extends WorkerType>(\n builder: () => Worker | WorkerNode | string | URL,\n limit = 4\n) => {\n let workers: {\n worker?: Worker;\n resultResolver?: PromiseWithResolvers<unknown>;\n }[] = Array(limit)\n .fill(undefined)\n .map(() => ({}));\n const emptyWaits: PromiseWithResolvers<void>[] = [];\n let isEmptyWait = false;\n\n const getResolver = async () => {\n while (true) {\n const target = workers.find(({ resultResolver }) => !resultResolver);\n if (target) {\n target.resultResolver = Promise.withResolvers<unknown>();\n if (!target.worker) {\n const result = builder();\n const worker =\n result instanceof Worker\n ? result\n : new Worker(result as string | URL);\n target.worker = await init(worker);\n }\n return target;\n }\n await Promise.race(\n workers.map(({ resultResolver }) => resultResolver?.promise)\n );\n }\n };\n\n /**\n * @method execute - Executes a method on a worker.\n * @template K - The key of the method to execute.\n * @param {K} name - The name of the method to execute.\n * @param {...Parameters<T[K]>} value - The arguments to pass to the method.\n * @returns {Promise<Awaited<ReturnType<T[K]>>>} A promise that resolves with the result of the method.\n */\n const execute = async <K extends keyof T>(\n name: K,\n ...value: Parameters<T[K]>\n ): Promise<Awaited<ReturnType<T[K]>>> => {\n const target = await getResolver();\n const { resultResolver } = target;\n if (!resultResolver) throw new Error(\"Unexpected error\");\n exec(target.worker!, name as string, ...value)\n .then(resultResolver.resolve)\n .catch(resultResolver.reject)\n .finally(() => {\n target.resultResolver = undefined;\n });\n return resultResolver.promise as Promise<Awaited<ReturnType<T[K]>>>;\n };\n\n /**\n * @method launchWorker - Launches all workers in the pool.\n * @returns {Promise<void[]>} A promise that resolves when all workers have been launched.\n */\n const launchWorker = async () => {\n return Promise.all(\n workers.map(async (target) => {\n if (!target.worker) {\n const result = builder();\n const worker =\n result instanceof Worker\n ? result\n : new Worker(result as string | URL);\n target.worker = await init(worker);\n }\n })\n );\n };\n\n /**\n * @method waitAll - Waits for all workers to complete their tasks.\n * @returns {Promise<void>} A promise that resolves when all workers have completed their tasks.\n */\n const waitAll = async () => {\n while (workers.find(({ resultResolver }) => resultResolver)) {\n await Promise.all(\n workers.flatMap(({ resultResolver }) =>\n resultResolver ? [resultResolver.promise] : []\n )\n );\n }\n };\n\n /**\n * @method waitReady - Waits for the worker pool to be ready.\n * @param {number} [retryTime=1] - The time to wait between retries in milliseconds.\n * @returns {Promise<void>} A promise that resolves when the worker pool is ready.\n */\n const waitReady = async (retryTime = 1) => {\n const p = Promise.withResolvers<void>();\n emptyWaits.push(p);\n (async () => {\n if (!isEmptyWait) {\n isEmptyWait = true;\n do {\n const actives = workers.flatMap(({ resultResolver }) =>\n resultResolver ? [resultResolver.promise] : []\n );\n if (workers.length === actives.length) await Promise.race(actives);\n emptyWaits.shift()?.resolve();\n if (retryTime) await new Promise((r) => setTimeout(r, retryTime));\n else await Promise.resolve();\n } while (emptyWaits.length);\n isEmptyWait = false;\n }\n })();\n return p.promise;\n };\n\n /**\n * @method close - Terminates all workers in the pool.\n */\n const close = () => {\n for (const { worker } of workers) {\n worker?.terminate();\n }\n };\n\n /**\n * @method setLimit - Sets a new limit for the number of concurrent workers.\n * @param {number} limit - The new limit for the number of concurrent workers.\n */\n const setLimit = (limit: number) => {\n workers.forEach((w) => w.worker?.terminate());\n workers = Array(limit)\n .fill(undefined)\n .map(() => ({}));\n };\n return { execute, waitAll, waitReady, close, setLimit, launchWorker };\n};\n\n/**\n * Initializes a web worker with the provided worker process.\n *\n * @template T - The type of the worker process.\n * @param {T} WorkerProc - The worker process to initialize.\n * @returns {T} The initialized worker process.\n */\nexport const initWorker = <T extends WorkerType>(WorkerProc: T) => {\n const worker = self as unknown as Worker;\n worker.addEventListener(\"message\", async (e: MessageEvent) => {\n const data = e.data as WorkerRecvEvent<T>;\n if (data.type === \"function\") {\n const {\n name,\n value,\n callback,\n }: {\n name: keyof T;\n value: unknown[];\n callback: boolean[];\n } = data.payload;\n const proc = WorkerProc[name];\n if (proc) {\n try {\n const params = value.map((v, index) =>\n callback[index]\n ? (...params: CallbackValue<T>) =>\n callbackProc<T>(worker, index, params)\n : v\n );\n worker.postMessage({\n type: \"result\",\n payload: await proc(...params),\n });\n } catch (e) {\n worker.postMessage({ type: \"error\", payload: String(e) });\n }\n }\n }\n });\n worker.postMessage(undefined);\n return WorkerProc;\n};\n\nconst callbackProc = <T extends WorkerType>(\n worker: Worker,\n index: number,\n params: CallbackValue<T>\n) => {\n const id = WorkerValue.id++;\n return new Promise((resolve) => {\n worker.addEventListener(\n \"message\",\n (e: MessageEvent) => {\n const data = e.data as WorkerRecvEvent<T>;\n if (data.type === \"callback_result\" && data.payload.id === id) {\n resolve(data.payload.result);\n }\n },\n { once: true }\n );\n worker.postMessage({\n type: \"callback\",\n payload: { id, index, value: params },\n });\n });\n};\n\nconst WorkerValue = { id: 0, promises: {} } as {\n id: number;\n promises: { [key: number]: Promise<unknown> };\n};\n"]}
package/dist/esm/node.js CHANGED
@@ -11,7 +11,7 @@ const exec = (worker, name, ...value) => {
11
11
  const p = async (data) => {
12
12
  switch (data.type) {
13
13
  case "callback":
14
- const r = value[data.payload.index](data.payload.value);
14
+ const r = value[data.payload.index](...data.payload.value);
15
15
  worker.postMessage({
16
16
  type: "callback_result",
17
17
  payload: { id: data.payload.id, result: await r },
@@ -1 +1 @@
1
- {"version":3,"file":"node.js","sourceRoot":"","sources":["../../src/node.ts"],"names":[],"mappings":"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","sourcesContent":["import { parentPort, Worker } from \"node:worker_threads\";\ntype WorkerType = { [key: string]: (...args: any) => any };\ntype WorkerRecvEvent<T> =\n | {\n type: \"function\";\n payload: { name: keyof T; callback: boolean[]; value: unknown[] };\n }\n | { type: \"callback_result\"; payload: { id: number; result: unknown } };\ntype WorkerSendEvent<T extends WorkerType> =\n | {\n type: \"callback\";\n payload: { id: number; result: unknown; index: number; value: T };\n }\n | {\n type: \"result\";\n payload: ReturnType<T[keyof T]>;\n }\n | {\n type: \"error\";\n payload: unknown;\n };\n\nconst init = (worker: Worker): Promise<Worker> => {\n return new Promise((resolve) => {\n worker.once(\"message\", () => {\n resolve(worker);\n });\n });\n};\nconst exec = <T extends WorkerType>(\n worker: Worker,\n name: keyof T,\n ...value: Parameters<T[keyof T]>\n): Promise<ReturnType<T[keyof T]>> => {\n return new Promise((resolve, reject) => {\n const p = async (data: WorkerSendEvent<T>) => {\n switch (data.type) {\n case \"callback\":\n const r = value[data.payload.index](data.payload.value);\n worker.postMessage({\n type: \"callback_result\",\n payload: { id: data.payload.id, result: await r },\n });\n break;\n case \"result\":\n worker.removeListener(\"message\", p);\n resolve(data.payload);\n break;\n case \"error\":\n worker.removeListener(\"message\", p);\n reject(data.payload);\n break;\n }\n };\n worker.addListener(\"message\", p);\n worker.postMessage({\n type: \"function\",\n payload: {\n name,\n value: value.map((v: unknown) => !(typeof v === \"function\") && v),\n callback: value.map((v: unknown) => typeof v === \"function\"),\n },\n } as WorkerRecvEvent<T>);\n });\n};\n\n/**\n * Creates a worker pool with a specified limit of concurrent workers.\n *\n * @template T - The type of the worker.\n * @param {() => Worker | WorkerNode} builder - A function that returns a new Worker or WorkerNode instance.\n * @param {number} [limit=4] - The maximum number of concurrent workers.\n * @returns {{\n * execute: <K extends keyof T>(name: K, ...value: Parameters<T[K]>) => Promise<Awaited<ReturnType<T[K]>>>,\n * waitAll: () => Promise<void>,\n * waitReady: (retryTime?: number) => Promise<void>,\n * close: () => void,\n * setLimit: (limit: number) => void,\n * launchWorker: () => Promise<void[]>\n * }} An object containing methods to interact with the worker pool.\n */\nexport const createWorker = <T extends WorkerType>(\n builder: () => Worker | string | URL,\n limit = 4\n) => {\n let workers: {\n worker?: Worker;\n resultResolver?: PromiseWithResolvers<unknown>;\n }[] = Array(limit)\n .fill(undefined)\n .map(() => ({}));\n const emptyWaits: PromiseWithResolvers<void>[] = [];\n let isEmptyWait = false;\n\n const getResolver = async () => {\n while (true) {\n const target = workers.find(({ resultResolver }) => !resultResolver);\n if (target) {\n target.resultResolver = Promise.withResolvers<unknown>();\n if (!target.worker) {\n const result = builder();\n const worker = result instanceof Worker ? result : new Worker(result);\n target.worker = await init(worker);\n }\n return target;\n }\n await Promise.race(\n workers.map(({ resultResolver }) => resultResolver?.promise)\n );\n }\n };\n\n /**\n * @method execute - Executes a method on a worker.\n * @template K - The key of the method to execute.\n * @param {K} name - The name of the method to execute.\n * @param {...Parameters<T[K]>} value - The arguments to pass to the method.\n * @returns {Promise<Awaited<ReturnType<T[K]>>>} A promise that resolves with the result of the method.\n */\n const execute = async <K extends keyof T>(\n name: K,\n ...value: Parameters<T[K]>\n ): Promise<Awaited<ReturnType<T[K]>>> => {\n const target = await getResolver();\n const { resultResolver } = target;\n if (!resultResolver) throw new Error(\"Unexpected error\");\n exec(target.worker!, name as string, ...value)\n .then(resultResolver.resolve)\n .catch(resultResolver.reject)\n .finally(() => {\n target.resultResolver = undefined;\n });\n return resultResolver.promise as Promise<Awaited<ReturnType<T[K]>>>;\n };\n\n /**\n * @method launchWorker - Launches all workers in the pool.\n * @returns {Promise<void[]>} A promise that resolves when all workers have been launched.\n */\n const launchWorker = async () => {\n return Promise.all(\n workers.map(async (target) => {\n if (!target.worker) {\n const result = builder();\n const worker = result instanceof Worker ? result : new Worker(result);\n target.worker = await init(worker);\n }\n })\n );\n };\n\n /**\n * @method waitAll - Waits for all workers to complete their tasks.\n * @returns {Promise<void>} A promise that resolves when all workers have completed their tasks.\n */\n const waitAll = async () => {\n while (workers.find(({ resultResolver }) => resultResolver)) {\n await Promise.all(\n workers.flatMap(({ resultResolver }) =>\n resultResolver ? [resultResolver.promise] : []\n )\n );\n }\n };\n\n /**\n * @method waitReady - Waits for the worker pool to be ready.\n * @param {number} [retryTime=1] - The time to wait between retries in milliseconds.\n * @returns {Promise<void>} A promise that resolves when the worker pool is ready.\n */\n const waitReady = async (retryTime = 1) => {\n const p = Promise.withResolvers<void>();\n emptyWaits.push(p);\n (async () => {\n if (!isEmptyWait) {\n isEmptyWait = true;\n do {\n const actives = workers.flatMap(({ resultResolver }) =>\n resultResolver ? [resultResolver.promise] : []\n );\n if (workers.length === actives.length) await Promise.race(actives);\n emptyWaits.shift()?.resolve();\n if (retryTime) await new Promise((r) => setTimeout(r, retryTime));\n else await Promise.resolve();\n } while (emptyWaits.length);\n isEmptyWait = false;\n }\n })();\n return p.promise;\n };\n\n /**\n * @method close - Terminates all workers in the pool.\n */\n const close = () => {\n for (const { worker } of workers) {\n worker?.terminate();\n }\n };\n\n /**\n * @method setLimit - Sets a new limit for the number of concurrent workers.\n * @param {number} limit - The new limit for the number of concurrent workers.\n */\n const setLimit = (limit: number) => {\n workers.forEach((w) => w.worker?.terminate());\n workers = Array(limit)\n .fill(undefined)\n .map(() => ({}));\n };\n return { execute, waitAll, waitReady, close, setLimit, launchWorker };\n};\n\n/**\n * Initializes a web worker with the provided worker process.\n *\n * @template T - The type of the worker process.\n * @param {T} WorkerProc - The worker process to initialize.\n * @returns {T} The initialized worker process.\n */\nexport const initWorker = <T extends WorkerType>(WorkerProc: T) => {\n const worker = parentPort;\n if (!worker) {\n throw new Error(\"This is not a worker thread\");\n }\n worker.addListener(\"message\", async (data: WorkerRecvEvent<T>) => {\n if (data.type === \"function\") {\n const {\n name,\n value,\n callback,\n }: {\n name: keyof T;\n value: unknown[];\n callback: boolean[];\n } = data.payload;\n const proc = WorkerProc[name];\n if (proc) {\n try {\n const params = value.map((v, index) =>\n callback[index]\n ? (...params: unknown[]) =>\n callbackProc<T>(worker as never, index, params)\n : v\n );\n worker.postMessage({\n type: \"result\",\n payload: await proc(...params),\n });\n } catch (e) {\n worker.postMessage({ type: \"error\", payload: String(e) });\n }\n }\n }\n });\n worker.postMessage(undefined);\n return WorkerProc;\n};\n\nconst callbackProc = <T>(worker: Worker, index: number, params: unknown[]) => {\n const id = WorkerValue.id++;\n return new Promise((resolve) => {\n worker.once(\"message\", (data: WorkerRecvEvent<T>) => {\n if (data.type === \"callback_result\" && data.payload.id === id) {\n resolve(data.payload.result);\n }\n });\n worker.postMessage({\n type: \"callback\",\n payload: { id, index, value: params },\n });\n });\n};\n\nconst WorkerValue = { id: 0, promises: {} } as {\n id: number;\n promises: { [key: number]: Promise<unknown> };\n};\n"]}
1
+ {"version":3,"file":"node.js","sourceRoot":"","sources":["../../src/node.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,EAAE,MAAM,qBAAqB,CAAC;AA8BzD,MAAM,IAAI,GAAG,CAAC,MAAc,EAAmB,EAAE;IAC/C,OAAO,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,EAAE;QAC7B,MAAM,CAAC,IAAI,CAAC,SAAS,EAAE,GAAG,EAAE;YAC1B,OAAO,CAAC,MAAM,CAAC,CAAC;QAClB,CAAC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;AACL,CAAC,CAAC;AACF,MAAM,IAAI,GAAG,CACX,MAAc,EACd,IAAa,EACb,GAAG,KAA6B,EACC,EAAE;IACnC,OAAO,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE;QACrC,MAAM,CAAC,GAAG,KAAK,EAAE,IAAwB,EAAE,EAAE;YAC3C,QAAQ,IAAI,CAAC,IAAI,EAAE,CAAC;gBAClB,KAAK,UAAU;oBACb,MAAM,CAAC,GAAG,KAAK,CAAC,IAAI,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,GAAG,IAAI,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC;oBAC3D,MAAM,CAAC,WAAW,CAAC;wBACjB,IAAI,EAAE,iBAAiB;wBACvB,OAAO,EAAE,EAAE,EAAE,EAAE,IAAI,CAAC,OAAO,CAAC,EAAE,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE;qBAClD,CAAC,CAAC;oBACH,MAAM;gBACR,KAAK,QAAQ;oBACX,MAAM,CAAC,cAAc,CAAC,SAAS,EAAE,CAAC,CAAC,CAAC;oBACpC,OAAO,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;oBACtB,MAAM;gBACR,KAAK,OAAO;oBACV,MAAM,CAAC,cAAc,CAAC,SAAS,EAAE,CAAC,CAAC,CAAC;oBACpC,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;oBACrB,MAAM;YACV,CAAC;QACH,CAAC,CAAC;QACF,MAAM,CAAC,WAAW,CAAC,SAAS,EAAE,CAAC,CAAC,CAAC;QACjC,MAAM,CAAC,WAAW,CAAC;YACjB,IAAI,EAAE,UAAU;YAChB,OAAO,EAAE;gBACP,IAAI;gBACJ,KAAK,EAAE,KAAK,CAAC,GAAG,CAAC,CAAC,CAAU,EAAE,EAAE,CAAC,CAAC,CAAC,OAAO,CAAC,KAAK,UAAU,CAAC,IAAI,CAAC,CAAC;gBACjE,QAAQ,EAAE,KAAK,CAAC,GAAG,CAAC,CAAC,CAAU,EAAE,EAAE,CAAC,OAAO,CAAC,KAAK,UAAU,CAAC;aAC7D;SACoB,CAAC,CAAC;IAC3B,CAAC,CAAC,CAAC;AACL,CAAC,CAAC;AAEF;;;;;;;;;;;;;;GAcG;AACH,MAAM,CAAC,MAAM,YAAY,GAAG,CAC1B,OAAoC,EACpC,KAAK,GAAG,CAAC,EACT,EAAE;IACF,IAAI,OAAO,GAGL,KAAK,CAAC,KAAK,CAAC;SACf,IAAI,CAAC,SAAS,CAAC;SACf,GAAG,CAAC,GAAG,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;IACnB,MAAM,UAAU,GAAiC,EAAE,CAAC;IACpD,IAAI,WAAW,GAAG,KAAK,CAAC;IAExB,MAAM,WAAW,GAAG,KAAK,IAAI,EAAE;QAC7B,OAAO,IAAI,EAAE,CAAC;YACZ,MAAM,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC,EAAE,cAAc,EAAE,EAAE,EAAE,CAAC,CAAC,cAAc,CAAC,CAAC;YACrE,IAAI,MAAM,EAAE,CAAC;gBACX,MAAM,CAAC,cAAc,GAAG,OAAO,CAAC,aAAa,EAAW,CAAC;gBACzD,IAAI,CAAC,MAAM,CAAC,MAAM,EAAE,CAAC;oBACnB,MAAM,MAAM,GAAG,OAAO,EAAE,CAAC;oBACzB,MAAM,MAAM,GAAG,MAAM,YAAY,MAAM,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,IAAI,MAAM,CAAC,MAAM,CAAC,CAAC;oBACtE,MAAM,CAAC,MAAM,GAAG,MAAM,IAAI,CAAC,MAAM,CAAC,CAAC;gBACrC,CAAC;gBACD,OAAO,MAAM,CAAC;YAChB,CAAC;YACD,MAAM,OAAO,CAAC,IAAI,CAChB,OAAO,CAAC,GAAG,CAAC,CAAC,EAAE,cAAc,EAAE,EAAE,EAAE,CAAC,cAAc,EAAE,OAAO,CAAC,CAC7D,CAAC;QACJ,CAAC;IACH,CAAC,CAAC;IAEF;;;;;;OAMG;IACH,MAAM,OAAO,GAAG,KAAK,EACnB,IAAO,EACP,GAAG,KAAuB,EACU,EAAE;QACtC,MAAM,MAAM,GAAG,MAAM,WAAW,EAAE,CAAC;QACnC,MAAM,EAAE,cAAc,EAAE,GAAG,MAAM,CAAC;QAClC,IAAI,CAAC,cAAc;YAAE,MAAM,IAAI,KAAK,CAAC,kBAAkB,CAAC,CAAC;QACzD,IAAI,CAAC,MAAM,CAAC,MAAO,EAAE,IAAc,EAAE,GAAG,KAAK,CAAC;aAC3C,IAAI,CAAC,cAAc,CAAC,OAAO,CAAC;aAC5B,KAAK,CAAC,cAAc,CAAC,MAAM,CAAC;aAC5B,OAAO,CAAC,GAAG,EAAE;YACZ,MAAM,CAAC,cAAc,GAAG,SAAS,CAAC;QACpC,CAAC,CAAC,CAAC;QACL,OAAO,cAAc,CAAC,OAA6C,CAAC;IACtE,CAAC,CAAC;IAEF;;;OAGG;IACH,MAAM,YAAY,GAAG,KAAK,IAAI,EAAE;QAC9B,OAAO,OAAO,CAAC,GAAG,CAChB,OAAO,CAAC,GAAG,CAAC,KAAK,EAAE,MAAM,EAAE,EAAE;YAC3B,IAAI,CAAC,MAAM,CAAC,MAAM,EAAE,CAAC;gBACnB,MAAM,MAAM,GAAG,OAAO,EAAE,CAAC;gBACzB,MAAM,MAAM,GAAG,MAAM,YAAY,MAAM,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,IAAI,MAAM,CAAC,MAAM,CAAC,CAAC;gBACtE,MAAM,CAAC,MAAM,GAAG,MAAM,IAAI,CAAC,MAAM,CAAC,CAAC;YACrC,CAAC;QACH,CAAC,CAAC,CACH,CAAC;IACJ,CAAC,CAAC;IAEF;;;OAGG;IACH,MAAM,OAAO,GAAG,KAAK,IAAI,EAAE;QACzB,OAAO,OAAO,CAAC,IAAI,CAAC,CAAC,EAAE,cAAc,EAAE,EAAE,EAAE,CAAC,cAAc,CAAC,EAAE,CAAC;YAC5D,MAAM,OAAO,CAAC,GAAG,CACf,OAAO,CAAC,OAAO,CAAC,CAAC,EAAE,cAAc,EAAE,EAAE,EAAE,CACrC,cAAc,CAAC,CAAC,CAAC,CAAC,cAAc,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,EAAE,CAC/C,CACF,CAAC;QACJ,CAAC;IACH,CAAC,CAAC;IAEF;;;;OAIG;IACH,MAAM,SAAS,GAAG,KAAK,EAAE,SAAS,GAAG,CAAC,EAAE,EAAE;QACxC,MAAM,CAAC,GAAG,OAAO,CAAC,aAAa,EAAQ,CAAC;QACxC,UAAU,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QACnB,CAAC,KAAK,IAAI,EAAE;YACV,IAAI,CAAC,WAAW,EAAE,CAAC;gBACjB,WAAW,GAAG,IAAI,CAAC;gBACnB,GAAG,CAAC;oBACF,MAAM,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC,EAAE,cAAc,EAAE,EAAE,EAAE,CACrD,cAAc,CAAC,CAAC,CAAC,CAAC,cAAc,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,EAAE,CAC/C,CAAC;oBACF,IAAI,OAAO,CAAC,MAAM,KAAK,OAAO,CAAC,MAAM;wBAAE,MAAM,OAAO,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;oBACnE,UAAU,CAAC,KAAK,EAAE,EAAE,OAAO,EAAE,CAAC;oBAC9B,IAAI,SAAS;wBAAE,MAAM,IAAI,OAAO,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,UAAU,CAAC,CAAC,EAAE,SAAS,CAAC,CAAC,CAAC;;wBAC7D,MAAM,OAAO,CAAC,OAAO,EAAE,CAAC;gBAC/B,CAAC,QAAQ,UAAU,CAAC,MAAM,EAAE;gBAC5B,WAAW,GAAG,KAAK,CAAC;YACtB,CAAC;QACH,CAAC,CAAC,EAAE,CAAC;QACL,OAAO,CAAC,CAAC,OAAO,CAAC;IACnB,CAAC,CAAC;IAEF;;OAEG;IACH,MAAM,KAAK,GAAG,GAAG,EAAE;QACjB,KAAK,MAAM,EAAE,MAAM,EAAE,IAAI,OAAO,EAAE,CAAC;YACjC,MAAM,EAAE,SAAS,EAAE,CAAC;QACtB,CAAC;IACH,CAAC,CAAC;IAEF;;;OAGG;IACH,MAAM,QAAQ,GAAG,CAAC,KAAa,EAAE,EAAE;QACjC,OAAO,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,MAAM,EAAE,SAAS,EAAE,CAAC,CAAC;QAC9C,OAAO,GAAG,KAAK,CAAC,KAAK,CAAC;aACnB,IAAI,CAAC,SAAS,CAAC;aACf,GAAG,CAAC,GAAG,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;IACrB,CAAC,CAAC;IACF,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,SAAS,EAAE,KAAK,EAAE,QAAQ,EAAE,YAAY,EAAE,CAAC;AACxE,CAAC,CAAC;AAEF;;;;;;GAMG;AACH,MAAM,CAAC,MAAM,UAAU,GAAG,CAAuB,UAAa,EAAE,EAAE;IAChE,MAAM,MAAM,GAAG,UAAU,CAAC;IAC1B,IAAI,CAAC,MAAM,EAAE,CAAC;QACZ,MAAM,IAAI,KAAK,CAAC,6BAA6B,CAAC,CAAC;IACjD,CAAC;IACD,MAAM,CAAC,WAAW,CAAC,SAAS,EAAE,KAAK,EAAE,IAAwB,EAAE,EAAE;QAC/D,IAAI,IAAI,CAAC,IAAI,KAAK,UAAU,EAAE,CAAC;YAC7B,MAAM,EACJ,IAAI,EACJ,KAAK,EACL,QAAQ,GACT,GAIG,IAAI,CAAC,OAAO,CAAC;YACjB,MAAM,IAAI,GAAG,UAAU,CAAC,IAAI,CAAC,CAAC;YAC9B,IAAI,IAAI,EAAE,CAAC;gBACT,IAAI,CAAC;oBACH,MAAM,MAAM,GAAG,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,EAAE,CACpC,QAAQ,CAAC,KAAK,CAAC;wBACb,CAAC,CAAC,CAAC,GAAG,MAAwB,EAAE,EAAE,CAC9B,YAAY,CAAI,MAAe,EAAE,KAAK,EAAE,MAAM,CAAC;wBACnD,CAAC,CAAC,CAAC,CACN,CAAC;oBACF,MAAM,CAAC,WAAW,CAAC;wBACjB,IAAI,EAAE,QAAQ;wBACd,OAAO,EAAE,MAAM,IAAI,CAAC,GAAG,MAAM,CAAC;qBAC/B,CAAC,CAAC;gBACL,CAAC;gBAAC,OAAO,CAAC,EAAE,CAAC;oBACX,MAAM,CAAC,WAAW,CAAC,EAAE,IAAI,EAAE,OAAO,EAAE,OAAO,EAAE,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;gBAC5D,CAAC;YACH,CAAC;QACH,CAAC;IACH,CAAC,CAAC,CAAC;IACH,MAAM,CAAC,WAAW,CAAC,SAAS,CAAC,CAAC;IAC9B,OAAO,UAAU,CAAC;AACpB,CAAC,CAAC;AAEF,MAAM,YAAY,GAAG,CACnB,MAAc,EACd,KAAa,EACb,MAAwB,EACxB,EAAE;IACF,MAAM,EAAE,GAAG,WAAW,CAAC,EAAE,EAAE,CAAC;IAC5B,OAAO,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,EAAE;QAC7B,MAAM,CAAC,IAAI,CAAC,SAAS,EAAE,CAAC,IAAwB,EAAE,EAAE;YAClD,IAAI,IAAI,CAAC,IAAI,KAAK,iBAAiB,IAAI,IAAI,CAAC,OAAO,CAAC,EAAE,KAAK,EAAE,EAAE,CAAC;gBAC9D,OAAO,CAAC,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC;YAC/B,CAAC;QACH,CAAC,CAAC,CAAC;QACH,MAAM,CAAC,WAAW,CAAC;YACjB,IAAI,EAAE,UAAU;YAChB,OAAO,EAAE,EAAE,EAAE,EAAE,KAAK,EAAE,KAAK,EAAE,MAAM,EAAE;SACtC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;AACL,CAAC,CAAC;AAEF,MAAM,WAAW,GAAG,EAAE,EAAE,EAAE,CAAC,EAAE,QAAQ,EAAE,EAAE,EAGxC,CAAC","sourcesContent":["import { parentPort, Worker } from \"node:worker_threads\";\ntype WorkerType = { [key: string]: (...args: any) => any };\ntype CallbackValue<T extends WorkerType> = Parameters<\n Extract<Parameters<T[keyof T]>[number], (...args: any) => any>\n>;\ntype WorkerRecvEvent<T extends WorkerType> =\n | {\n type: \"function\";\n payload: { name: keyof T; callback: boolean[]; value: unknown[] };\n }\n | { type: \"callback_result\"; payload: { id: number; result: unknown } };\ntype WorkerSendEvent<T extends WorkerType> =\n | {\n type: \"callback\";\n payload: {\n id: number;\n result: unknown;\n index: number;\n value: CallbackValue<T>;\n };\n }\n | {\n type: \"result\";\n payload: ReturnType<T[keyof T]>;\n }\n | {\n type: \"error\";\n payload: unknown;\n };\n\nconst init = (worker: Worker): Promise<Worker> => {\n return new Promise((resolve) => {\n worker.once(\"message\", () => {\n resolve(worker);\n });\n });\n};\nconst exec = <T extends WorkerType>(\n worker: Worker,\n name: keyof T,\n ...value: Parameters<T[keyof T]>\n): Promise<ReturnType<T[keyof T]>> => {\n return new Promise((resolve, reject) => {\n const p = async (data: WorkerSendEvent<T>) => {\n switch (data.type) {\n case \"callback\":\n const r = value[data.payload.index](...data.payload.value);\n worker.postMessage({\n type: \"callback_result\",\n payload: { id: data.payload.id, result: await r },\n });\n break;\n case \"result\":\n worker.removeListener(\"message\", p);\n resolve(data.payload);\n break;\n case \"error\":\n worker.removeListener(\"message\", p);\n reject(data.payload);\n break;\n }\n };\n worker.addListener(\"message\", p);\n worker.postMessage({\n type: \"function\",\n payload: {\n name,\n value: value.map((v: unknown) => !(typeof v === \"function\") && v),\n callback: value.map((v: unknown) => typeof v === \"function\"),\n },\n } as WorkerRecvEvent<T>);\n });\n};\n\n/**\n * Creates a worker pool with a specified limit of concurrent workers.\n *\n * @template T - The type of the worker.\n * @param {() => Worker | WorkerNode} builder - A function that returns a new Worker or WorkerNode instance.\n * @param {number} [limit=4] - The maximum number of concurrent workers.\n * @returns {{\n * execute: <K extends keyof T>(name: K, ...value: Parameters<T[K]>) => Promise<Awaited<ReturnType<T[K]>>>,\n * waitAll: () => Promise<void>,\n * waitReady: (retryTime?: number) => Promise<void>,\n * close: () => void,\n * setLimit: (limit: number) => void,\n * launchWorker: () => Promise<void[]>\n * }} An object containing methods to interact with the worker pool.\n */\nexport const createWorker = <T extends WorkerType>(\n builder: () => Worker | string | URL,\n limit = 4\n) => {\n let workers: {\n worker?: Worker;\n resultResolver?: PromiseWithResolvers<unknown>;\n }[] = Array(limit)\n .fill(undefined)\n .map(() => ({}));\n const emptyWaits: PromiseWithResolvers<void>[] = [];\n let isEmptyWait = false;\n\n const getResolver = async () => {\n while (true) {\n const target = workers.find(({ resultResolver }) => !resultResolver);\n if (target) {\n target.resultResolver = Promise.withResolvers<unknown>();\n if (!target.worker) {\n const result = builder();\n const worker = result instanceof Worker ? result : new Worker(result);\n target.worker = await init(worker);\n }\n return target;\n }\n await Promise.race(\n workers.map(({ resultResolver }) => resultResolver?.promise)\n );\n }\n };\n\n /**\n * @method execute - Executes a method on a worker.\n * @template K - The key of the method to execute.\n * @param {K} name - The name of the method to execute.\n * @param {...Parameters<T[K]>} value - The arguments to pass to the method.\n * @returns {Promise<Awaited<ReturnType<T[K]>>>} A promise that resolves with the result of the method.\n */\n const execute = async <K extends keyof T>(\n name: K,\n ...value: Parameters<T[K]>\n ): Promise<Awaited<ReturnType<T[K]>>> => {\n const target = await getResolver();\n const { resultResolver } = target;\n if (!resultResolver) throw new Error(\"Unexpected error\");\n exec(target.worker!, name as string, ...value)\n .then(resultResolver.resolve)\n .catch(resultResolver.reject)\n .finally(() => {\n target.resultResolver = undefined;\n });\n return resultResolver.promise as Promise<Awaited<ReturnType<T[K]>>>;\n };\n\n /**\n * @method launchWorker - Launches all workers in the pool.\n * @returns {Promise<void[]>} A promise that resolves when all workers have been launched.\n */\n const launchWorker = async () => {\n return Promise.all(\n workers.map(async (target) => {\n if (!target.worker) {\n const result = builder();\n const worker = result instanceof Worker ? result : new Worker(result);\n target.worker = await init(worker);\n }\n })\n );\n };\n\n /**\n * @method waitAll - Waits for all workers to complete their tasks.\n * @returns {Promise<void>} A promise that resolves when all workers have completed their tasks.\n */\n const waitAll = async () => {\n while (workers.find(({ resultResolver }) => resultResolver)) {\n await Promise.all(\n workers.flatMap(({ resultResolver }) =>\n resultResolver ? [resultResolver.promise] : []\n )\n );\n }\n };\n\n /**\n * @method waitReady - Waits for the worker pool to be ready.\n * @param {number} [retryTime=1] - The time to wait between retries in milliseconds.\n * @returns {Promise<void>} A promise that resolves when the worker pool is ready.\n */\n const waitReady = async (retryTime = 1) => {\n const p = Promise.withResolvers<void>();\n emptyWaits.push(p);\n (async () => {\n if (!isEmptyWait) {\n isEmptyWait = true;\n do {\n const actives = workers.flatMap(({ resultResolver }) =>\n resultResolver ? [resultResolver.promise] : []\n );\n if (workers.length === actives.length) await Promise.race(actives);\n emptyWaits.shift()?.resolve();\n if (retryTime) await new Promise((r) => setTimeout(r, retryTime));\n else await Promise.resolve();\n } while (emptyWaits.length);\n isEmptyWait = false;\n }\n })();\n return p.promise;\n };\n\n /**\n * @method close - Terminates all workers in the pool.\n */\n const close = () => {\n for (const { worker } of workers) {\n worker?.terminate();\n }\n };\n\n /**\n * @method setLimit - Sets a new limit for the number of concurrent workers.\n * @param {number} limit - The new limit for the number of concurrent workers.\n */\n const setLimit = (limit: number) => {\n workers.forEach((w) => w.worker?.terminate());\n workers = Array(limit)\n .fill(undefined)\n .map(() => ({}));\n };\n return { execute, waitAll, waitReady, close, setLimit, launchWorker };\n};\n\n/**\n * Initializes a web worker with the provided worker process.\n *\n * @template T - The type of the worker process.\n * @param {T} WorkerProc - The worker process to initialize.\n * @returns {T} The initialized worker process.\n */\nexport const initWorker = <T extends WorkerType>(WorkerProc: T) => {\n const worker = parentPort;\n if (!worker) {\n throw new Error(\"This is not a worker thread\");\n }\n worker.addListener(\"message\", async (data: WorkerRecvEvent<T>) => {\n if (data.type === \"function\") {\n const {\n name,\n value,\n callback,\n }: {\n name: keyof T;\n value: unknown[];\n callback: boolean[];\n } = data.payload;\n const proc = WorkerProc[name];\n if (proc) {\n try {\n const params = value.map((v, index) =>\n callback[index]\n ? (...params: CallbackValue<T>) =>\n callbackProc<T>(worker as never, index, params)\n : v\n );\n worker.postMessage({\n type: \"result\",\n payload: await proc(...params),\n });\n } catch (e) {\n worker.postMessage({ type: \"error\", payload: String(e) });\n }\n }\n }\n });\n worker.postMessage(undefined);\n return WorkerProc;\n};\n\nconst callbackProc = <T extends WorkerType>(\n worker: Worker,\n index: number,\n params: CallbackValue<T>\n) => {\n const id = WorkerValue.id++;\n return new Promise((resolve) => {\n worker.once(\"message\", (data: WorkerRecvEvent<T>) => {\n if (data.type === \"callback_result\" && data.payload.id === id) {\n resolve(data.payload.result);\n }\n });\n worker.postMessage({\n type: \"callback\",\n payload: { id, index, value: params },\n });\n });\n};\n\nconst WorkerValue = { id: 0, promises: {} } as {\n id: number;\n promises: { [key: number]: Promise<unknown> };\n};\n"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "worker-lib",
3
- "version": "2.0.9",
3
+ "version": "2.1.0",
4
4
  "main": "./dist/cjs/index.js",
5
5
  "types": "./dist/cjs/index.d.ts",
6
6
  "exports": {
@@ -45,12 +45,15 @@
45
45
  },
46
46
  "license": "MIT",
47
47
  "scripts": {
48
- "build": "tsc && tsc --project ./tsconfig.esm.json && cpy esm dist"
48
+ "build": "tsc && tsc --project ./tsconfig.esm.json && cpy esm dist",
49
+ "test": "vitest run"
49
50
  },
50
51
  "devDependencies": {
51
52
  "@types/node": "25.2.3",
52
53
  "cpy-cli": "7.0.0",
53
- "typescript": "^5.9.3"
54
+ "tsx": "4.21.0",
55
+ "typescript": "^5.9.3",
56
+ "vitest": "4.0.18"
54
57
  },
55
58
  "description": "Library for easy use of web-worker",
56
59
  "repository": {
@@ -0,0 +1,13 @@
1
+ import { initWorker } from "../src/node";
2
+
3
+ const add = (a: number, b: number) => a + b;
4
+
5
+ const asyncTask = async (onProgress: (percent: number, status: string) => void) => {
6
+ onProgress(10, "starting");
7
+ onProgress(50, "halfway");
8
+ onProgress(100, "done");
9
+ return "task-result";
10
+ };
11
+
12
+ const map = initWorker({ add, asyncTask });
13
+ export type TestWorker = typeof map;
@@ -0,0 +1,42 @@
1
+ import { describe, it, expect, afterAll } from "vitest";
2
+ import { createWorker } from "../src/node";
3
+ import type { TestWorker } from "./worker-script";
4
+ import path from "node:path";
5
+
6
+ describe("worker-lib node", () => {
7
+ const { execute, close } = createWorker<TestWorker>(
8
+ () => {
9
+ // Use tsx to run the TypeScript worker file directly
10
+ const workerPath = path.resolve(__dirname, "./worker-script.ts");
11
+ const normalizedPath = workerPath.split(path.sep).join("/");
12
+ return new (require("node:worker_threads").Worker)(
13
+ `require('tsx/cjs'); require('${normalizedPath}');`,
14
+ { eval: true }
15
+ );
16
+ },
17
+ 2
18
+ );
19
+
20
+ afterAll(() => {
21
+ close();
22
+ });
23
+
24
+ it("should execute a simple function", async () => {
25
+ const result = await execute("add", 10, 20);
26
+ expect(result).toBe(30);
27
+ });
28
+
29
+ it("should execute a function with callbacks", async () => {
30
+ const progress: { percent: number; status: string }[] = [];
31
+
32
+ const result = await execute("asyncTask", (percent, status) => {
33
+ progress.push({ percent, status });
34
+ });
35
+
36
+ expect(result).toBe("task-result");
37
+ expect(progress).toHaveLength(3);
38
+ expect(progress[0]).toEqual({ percent: 10, status: "starting" });
39
+ expect(progress[1]).toEqual({ percent: 50, status: "halfway" });
40
+ expect(progress[2]).toEqual({ percent: 100, status: "done" });
41
+ });
42
+ });