worker-lib 2.0.8 → 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,264 +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
- - src/app/page.tsx
85
+ ## API Reference
160
86
 
161
- ```tsx
162
- "use client";
163
- import { useState } from "react";
164
- import { createWorker } from "worker-lib";
165
- import type { WorkerTest } from "../libs/worker-test";
87
+ ### `initWorker(workerProcess)`
88
+ Initializes the worker side.
89
+ - `workerProcess`: An object containing the functions to be exposed.
166
90
 
167
- // Create an instance to execute the Worker
168
- // execute("function name",... parameter) to start the Worker
169
- const execute = createWorker<WorkerTest>(
170
- () => new Worker(new URL("../libs/worker-test", import.meta.url)),
171
- 5 // Maximum parallel number
172
- );
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`.
173
95
 
174
- const Page = () => {
175
- const [values, setValues] = useState<(number | string)[]>([]);
176
- const [a, setA] = useState(300);
177
- const [b, setB] = useState(100);
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).
178
100
 
179
- return (
180
- <div>
181
- <form>
182
- <input
183
- name="a"
184
- value={a}
185
- onChange={(e) => setA(Number(e.currentTarget.value))}
186
- />
187
- <input
188
- name="b"
189
- value={b}
190
- onChange={(e) => setB(Number(e.currentTarget.value))}
191
- />
192
- <button
193
- type="button"
194
- onClick={async () => {
195
- const index = values.length;
196
- setValues([...values, "running"]);
197
- //Calling a Worker
198
- const result = await execute("add", a, b);
199
- setValues((values) =>
200
- values.map((v, i) => (i === index ? result : v))
201
- );
202
- }}
203
- >
204
- Add
205
- </button>
206
- <button
207
- type="button"
208
- onClick={async () => {
209
- const index = values.length;
210
- setValues([...values, "running"]);
211
- //Calling a Worker
212
- const result = await execute("add2", String(a), String(b));
213
- setValues((values) =>
214
- values.map((v, i) => (i === index ? result : v))
215
- );
216
- }}
217
- >
218
- Add(String)
219
- </button>
220
- <button
221
- type="button"
222
- onClick={async () => {
223
- const index = values.length;
224
- setValues([...values, "running"]);
225
- //Calling a Worker
226
- const result = await execute("sub", a, b);
227
- setValues((values) =>
228
- values.map((v, i) => (i === index ? result : v))
229
- );
230
- }}
231
- >
232
- Sub
233
- </button>
234
- <button
235
- type="button"
236
- onClick={async () => {
237
- const index = values.length;
238
- setValues([...values, "running"]);
239
- //Calling a Worker
240
- const result = await execute("mul", a, b);
241
- setValues((values) =>
242
- values.map((v, i) => (i === index ? result : v))
243
- );
244
- }}
245
- >
246
- Mul
247
- </button>
248
- <button
249
- type="button"
250
- onClick={async () => {
251
- const index = values.length;
252
- setValues([...values, "running"]);
253
- //Calling a Worker
254
- const result = await execute("error", a, b).catch((e) => e);
255
- setValues((values) =>
256
- values.map((v, i) => (i === index ? result : v))
257
- );
258
- }}
259
- >
260
- Error
261
- </button>
262
- </form>
263
- {values.map((v, index) => (
264
- <div key={index}>{v}</div>
265
- ))}
266
- </div>
267
- );
268
- };
269
- export default Page;
270
- ```
101
+ ### `waitAll()`
102
+ Returns a promise that resolves when all currently running tasks are complete.
103
+
104
+ ### `close()`
105
+ Terminates all workers in the pool.
106
+
107
+ ## Examples
108
+
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":"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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/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":"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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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "worker-lib",
3
- "version": "2.0.8",
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
- "@types/node": "24.0.3",
52
- "cpy-cli": "5.0.0",
53
- "typescript": "^5.8.3"
52
+ "@types/node": "25.2.3",
53
+ "cpy-cli": "7.0.0",
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
+ });