@offmain/workerkit 0.11.0 → 0.12.3
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 +62 -8
- package/dist/index.cjs +9 -9
- package/dist/index.js +174 -154
- package/dist/types/tools/main-worker-factory/main-worker-factory.d.ts +3 -3
- package/dist/types/tools/main-worker-factory/types.d.ts +20 -6
- package/dist/types/tools/worker-factory/worker-factory.d.ts +7 -3
- package/package.json +5 -2
package/README.md
CHANGED
|
@@ -57,14 +57,68 @@ console.log(data); // [15]
|
|
|
57
57
|
|
|
58
58
|
## WorkerConfig Options
|
|
59
59
|
|
|
60
|
-
| Option | Type
|
|
61
|
-
| ---------------- |
|
|
62
|
-
| `name` | `string`
|
|
63
|
-
| `role` | `string`
|
|
64
|
-
| `func` | `Function`
|
|
65
|
-
| `
|
|
66
|
-
| `
|
|
67
|
-
| `
|
|
60
|
+
| Option | Type | Default | Description |
|
|
61
|
+
| ---------------- | --------------- | ------------------------------- | --------------------------------------------------------------------------------------------------- |
|
|
62
|
+
| `name` | `string` | — | Unique identifier used to call the worker |
|
|
63
|
+
| `role` | `string` | — | Logical grouping label |
|
|
64
|
+
| `func` | `Function` | — | The exported worker function to run (optional if `workerURL` is provided) |
|
|
65
|
+
| `workerURL` | `string \| URL` | — | Worker script URL or `new URL(..., import.meta.url)` for module bundlers |
|
|
66
|
+
| `maxConcurrency` | `number` | `navigator.hardwareConcurrency` | Max parallel worker instances — defaults to the number of logical CPU cores reported by the browser |
|
|
67
|
+
| `retries` | `number` | `0` | How many times to retry a failed shard before marking it as rejected |
|
|
68
|
+
| `partition` | `boolean` | `false` | Split array input across multiple workers automatically |
|
|
69
|
+
|
|
70
|
+
---
|
|
71
|
+
|
|
72
|
+
## Module Bundler Integration (`workerURL`)
|
|
73
|
+
|
|
74
|
+
When worker logic relies on external npm packages (such as Luxon, `date-fns`, `i18next`, or custom data transformation modules), dynamic inline stringification (`.toString()`) cannot access those closed-over imports.
|
|
75
|
+
|
|
76
|
+
Passing `workerURL` enables modern module bundlers (Webpack 5, Vite, Rollup, Parcel) to analyze and bundle the worker file along with all of its dependencies into a dedicated ES module worker chunk.
|
|
77
|
+
|
|
78
|
+
### Dedicated Worker Script
|
|
79
|
+
|
|
80
|
+
```ts
|
|
81
|
+
// transform-data.worker.ts
|
|
82
|
+
import { format } from 'date-fns';
|
|
83
|
+
import { t } from './i18n.ts';
|
|
84
|
+
|
|
85
|
+
self.addEventListener('message', (event) => {
|
|
86
|
+
try {
|
|
87
|
+
const { items, locale } = event.data.data;
|
|
88
|
+
const result = items.map((item: any) => ({
|
|
89
|
+
...item,
|
|
90
|
+
formattedDate: format(new Date(item.timestamp), 'yyyy-MM-dd'),
|
|
91
|
+
label: t('transaction', locale),
|
|
92
|
+
}));
|
|
93
|
+
|
|
94
|
+
self.postMessage({ ok: true, data: result });
|
|
95
|
+
} catch (err) {
|
|
96
|
+
self.postMessage({ ok: false, error: (err as Error).message });
|
|
97
|
+
}
|
|
98
|
+
});
|
|
99
|
+
```
|
|
100
|
+
|
|
101
|
+
### Registering with `workerURL`
|
|
102
|
+
|
|
103
|
+
```ts
|
|
104
|
+
import { MainWorkerFactory } from '@offmain/workerkit';
|
|
105
|
+
|
|
106
|
+
const factory = new MainWorkerFactory({
|
|
107
|
+
workers: [
|
|
108
|
+
{
|
|
109
|
+
name: 'transformData',
|
|
110
|
+
role: 'compute',
|
|
111
|
+
// Webpack 5 / Vite statically analyzes new URL(..., import.meta.url)
|
|
112
|
+
workerURL: new URL('./transform-data.worker.ts', import.meta.url),
|
|
113
|
+
maxConcurrency: 4,
|
|
114
|
+
},
|
|
115
|
+
] as const,
|
|
116
|
+
});
|
|
117
|
+
|
|
118
|
+
const settled = await factory.runWorker('transformData', {
|
|
119
|
+
srcData: { locale: 'es', items: [{ timestamp: Date.now() }] },
|
|
120
|
+
});
|
|
121
|
+
```
|
|
68
122
|
|
|
69
123
|
---
|
|
70
124
|
|
package/dist/index.cjs
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
"use strict";var
|
|
1
|
+
"use strict";var v=Object.defineProperty;var y=(n,e,r)=>e in n?v(n,e,{enumerable:!0,configurable:!0,writable:!0,value:r}):n[e]=r;var k=(n,e,r)=>y(n,typeof e!="symbol"?e+"":e,r);Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const m=n=>`
|
|
2
2
|
const extractTransferables = (value, seen = new Set()) => {
|
|
3
3
|
if (value === null || typeof value !== 'object') return [];
|
|
4
4
|
if (seen.has(value)) return [];
|
|
@@ -15,13 +15,13 @@ const extractTransferables = (value, seen = new Set()) => {
|
|
|
15
15
|
|
|
16
16
|
self.addEventListener('message', async (event) => {
|
|
17
17
|
try {
|
|
18
|
-
const output = await ${
|
|
18
|
+
const output = await ${n}(event.data);
|
|
19
19
|
self.postMessage({ ok: true, data: output }, extractTransferables(output));
|
|
20
20
|
} catch (err) {
|
|
21
21
|
self.postMessage({ ok: false, error: err instanceof Error ? err.message : String(err) });
|
|
22
22
|
}
|
|
23
23
|
})
|
|
24
|
-
`,P=
|
|
24
|
+
`,P=n=>`
|
|
25
25
|
const extractTransferables = (value, seen = new Set()) => {
|
|
26
26
|
if (value === null || typeof value !== 'object') return [];
|
|
27
27
|
if (seen.has(value)) return [];
|
|
@@ -36,7 +36,7 @@ const extractTransferables = (value, seen = new Set()) => {
|
|
|
36
36
|
return Object.values(value).flatMap(v => extractTransferables(v, seen));
|
|
37
37
|
};
|
|
38
38
|
|
|
39
|
-
const workerFn = ${
|
|
39
|
+
const workerFn = ${n};
|
|
40
40
|
let outputPort = null;
|
|
41
41
|
let inputPort = null;
|
|
42
42
|
let pendingData = null;
|
|
@@ -93,7 +93,7 @@ self.addEventListener('message', (event) => {
|
|
|
93
93
|
pendingData = event.data;
|
|
94
94
|
}
|
|
95
95
|
});
|
|
96
|
-
`,
|
|
96
|
+
`,W=n=>`
|
|
97
97
|
const extractTransferables = (value, seen = new Set()) => {
|
|
98
98
|
if (value === null || typeof value !== 'object') return [];
|
|
99
99
|
if (seen.has(value)) return [];
|
|
@@ -108,7 +108,7 @@ const extractTransferables = (value, seen = new Set()) => {
|
|
|
108
108
|
return Object.values(value).flatMap(v => extractTransferables(v, seen));
|
|
109
109
|
};
|
|
110
110
|
|
|
111
|
-
const workerFn = ${
|
|
111
|
+
const workerFn = ${n};
|
|
112
112
|
let cachedDataset = null;
|
|
113
113
|
|
|
114
114
|
self.addEventListener('message', async (event) => {
|
|
@@ -149,8 +149,8 @@ self.addEventListener('message', async (event) => {
|
|
|
149
149
|
self.postMessage({ ok: false, error: err instanceof Error ? err.message : String(err) });
|
|
150
150
|
}
|
|
151
151
|
});
|
|
152
|
-
`;var
|
|
153
|
-
const reducer = ${
|
|
152
|
+
`;var w=(n=>(n.Default="default",n.Pipeline="pipeline",n.Persistent="persistent",n))(w||{});const M=Object.freeze({persistent:W,pipeline:P,default:m});class h{constructor(e,r){k(this,"_worker");if(r!=null&&r.workerInstance)this._worker=r.workerInstance;else if(r!=null&&r.workerURL)this._worker=new Worker(r.workerURL,{type:"module"});else if(e){const o=(r==null?void 0:r.mode)??"default",a=M[o](e.toString()),i=new Blob([a],{type:"application/javascript"});this._worker=new Worker(URL.createObjectURL(i))}else throw new Error("Either workerFunction or options.workerURL must be provided to WorkerFactory.")}get getWorker(){return this._worker}}class b{constructor(e){this.results=e}}function g(n,e=new Set){return n===null||typeof n!="object"?[]:e.has(n)?[]:(e.add(n),n instanceof ArrayBuffer||n instanceof MessagePort||typeof ImageBitmap<"u"&&n instanceof ImageBitmap||typeof OffscreenCanvas<"u"&&n instanceof OffscreenCanvas?[n]:ArrayBuffer.isView(n)?[n.buffer]:Array.isArray(n)?n.flatMap(r=>g(r,e)):Object.values(n).flatMap(r=>g(r,e)))}class E{constructor(e){k(this,"_workers");k(this,"_threads");k(this,"_persistentWorkers",new Map);this._workers=e.workers,this._threads=navigator.hardwareConcurrency}initWorker(e){return new h(e.func,{workerURL:e.workerURL})}partitionArray(e,r){if(!e.length)return[];if(r<=0)throw new Error("numChunks must be positive");const o=Math.min(r,e.length),a=Math.floor(e.length/o),i=e.length%o,l=[];let f=0;for(let t=0;t<o;t++){const s=a+(t<i?1:0);l.push(e.slice(f,f+s)),f+=s}return l}findWorkerByName(e){return this._workers.find(r=>r.name===e)}async runWorker(e,{srcData:r,...o}){const a=this.findWorkerByName(e);if(!a)return Promise.reject(new Error(`Worker "${e}" not found`));const i=a.maxConcurrency??this._threads,l=!!(Array.isArray(r)&&r.length>1&&a.partition),f=l?this.partitionArray(r,i):r,t=this.createWorkerPromises(a,e,{data:f,...o},i,l),s=await Promise.allSettled(t);return new b(s)}createWorkerPromises(e,r,o,a,i){const{data:l,...f}=o;return Array.from({length:a},(t,s)=>{const u=i&&Array.isArray(l)?l[s]:l;return this.runWorkerWithRetry({workerFunc:e.func,workerURL:e.workerURL,workerName:r,index:s,data:{data:u,...f}},e.retries)})}async runWorkerWithRetry(e,r=2){try{return await this.initiateWorker(e)}catch(o){if(r>0)return console.error(`Worker ${e.index} failed, retrying (${r} left):`,o),this.runWorkerWithRetry(e,r-1);throw console.error("Worker failed after all retries:",o),o}}initiateWorker({workerFunc:e,workerURL:r,workerName:o,index:a,data:i}){return new Promise((l,f)=>{const s=this.initWorker({name:o,role:"",func:e,workerURL:r}).getWorker;s.onerror=c=>{s.terminate(),f({index:a,workerConfigs:{workerFunc:e,workerName:o,index:a,data:i},failedResult:c})},s.onmessage=c=>{var d,p;if(((d=c.data)==null?void 0:d.ok)===!1){s.terminate(),f({index:a,workerConfigs:{workerFunc:e,workerName:o,index:a,data:i},failedResult:new ErrorEvent("error",{message:c.data.error})});return}l({index:a,workerConfigs:{workerFunc:e,workerName:o,index:a,data:i},successResult:new MessageEvent("message",{data:(p=c.data)==null?void 0:p.data})}),s.terminate()};const u={index:a,...Array.isArray(i)?{data:i}:i};s.postMessage(u,g(u))})}async collectResults(e,r={}){const o=e.results.filter(t=>t.status==="fulfilled"),a=e.results.filter(t=>t.status==="rejected"),i=o.map(t=>t.value.successResult.data),l=r.reducer?r.reducer.toString():"(shards) => shards.flat()";return{data:await new Promise((t,s)=>{const u=`
|
|
153
|
+
const reducer = ${l};
|
|
154
154
|
self.addEventListener('message', (event) => {
|
|
155
155
|
try {
|
|
156
156
|
const result = reducer(event.data);
|
|
@@ -159,4 +159,4 @@ self.addEventListener('message', async (event) => {
|
|
|
159
159
|
self.postMessage({ ok: false, error: String(err) });
|
|
160
160
|
}
|
|
161
161
|
});
|
|
162
|
-
`,c=new Blob([
|
|
162
|
+
`,c=new Blob([u],{type:"application/javascript"}),d=new Worker(URL.createObjectURL(c));d.onmessage=p=>{d.terminate(),p.data.ok?t(p.data.data):s(new Error(p.data.error))},d.onerror=p=>{d.terminate(),s(p)},d.postMessage(i)}),succeeded:o.length,failed:a.length,errors:a}}async pipeline(e){if(e.length===0)throw new Error("Pipeline requires at least one step");if(e.length===1){const r=e[0],o=this.findWorkerByName(r.worker);if(!o)throw new Error(`Worker "${r.worker}" not found`);const i=this.initWorker(o).getWorker;return new Promise((l,f)=>{i.onmessage=s=>{var u,c;i.terminate(),((u=s.data)==null?void 0:u.ok)===!1?f(new Error(s.data.error)):l((c=s.data)==null?void 0:c.data)},i.onerror=s=>{i.terminate(),f(s)};const t=r.srcData??{};i.postMessage({data:t,index:0},g(t))})}return new Promise((r,o)=>{const a=[],i=[];for(const t of e){const s=this.findWorkerByName(t.worker);if(!s){o(new Error(`Worker "${t.worker}" not found`));return}const u=new h(s.func,{mode:w.Pipeline,workerURL:s.workerURL});a.push(u.getWorker)}for(let t=0;t<a.length-1;t++)i.push(new MessageChannel);for(let t=0;t<a.length;t++){const s=[],u={};t>0&&(u.inputPort=i[t-1].port1,s.push(u.inputPort)),t<a.length-1&&(u.outputPort=i[t].port2,s.push(u.outputPort)),a[t].postMessage({__pipeline_ports__:!0,...u},s)}const l=a[a.length-1];l.onmessage=t=>{var s,u;a.forEach(c=>c.terminate()),((s=t.data)==null?void 0:s.ok)===!1?o(new Error(t.data.error)):r((u=t.data)==null?void 0:u.data)},l.onerror=t=>{a.forEach(s=>s.terminate()),o(t)};const f=e[0].srcData??{};a[0].postMessage({data:f,index:0},g(f))})}async runPersistent(e,r){const o=this.findWorkerByName(e);if(!o)throw new Error(`Worker "${e}" not found`);let a=this._persistentWorkers.get(e);return a||(a=new h(o.func,{mode:w.Persistent,workerURL:o.workerURL}).getWorker,this._persistentWorkers.set(e,a)),new Promise((i,l)=>{a.onmessage=t=>{var s,u;((s=t.data)==null?void 0:s.ok)===!1?l(new Error(t.data.error)):i((u=t.data)==null?void 0:u.data)},a.onerror=t=>{l(t)};const f={type:"run",config:r.config};r.dataset!==void 0&&(f.dataset=r.dataset),a.postMessage(f,g(f))})}release(e){const r=this._persistentWorkers.get(e);r&&(r.postMessage({type:"release"}),r.terminate(),this._persistentWorkers.delete(e))}}exports.MainWorkerFactory=E;exports.WorkerFactory=h;
|
package/dist/index.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
var
|
|
2
|
-
var m = (
|
|
3
|
-
var
|
|
4
|
-
const y = (
|
|
1
|
+
var v = Object.defineProperty;
|
|
2
|
+
var m = (n, e, r) => e in n ? v(n, e, { enumerable: !0, configurable: !0, writable: !0, value: r }) : n[e] = r;
|
|
3
|
+
var k = (n, e, r) => m(n, typeof e != "symbol" ? e + "" : e, r);
|
|
4
|
+
const y = (n) => `
|
|
5
5
|
const extractTransferables = (value, seen = new Set()) => {
|
|
6
6
|
if (value === null || typeof value !== 'object') return [];
|
|
7
7
|
if (seen.has(value)) return [];
|
|
@@ -18,13 +18,13 @@ const extractTransferables = (value, seen = new Set()) => {
|
|
|
18
18
|
|
|
19
19
|
self.addEventListener('message', async (event) => {
|
|
20
20
|
try {
|
|
21
|
-
const output = await ${
|
|
21
|
+
const output = await ${n}(event.data);
|
|
22
22
|
self.postMessage({ ok: true, data: output }, extractTransferables(output));
|
|
23
23
|
} catch (err) {
|
|
24
24
|
self.postMessage({ ok: false, error: err instanceof Error ? err.message : String(err) });
|
|
25
25
|
}
|
|
26
26
|
})
|
|
27
|
-
`, P = (
|
|
27
|
+
`, P = (n) => `
|
|
28
28
|
const extractTransferables = (value, seen = new Set()) => {
|
|
29
29
|
if (value === null || typeof value !== 'object') return [];
|
|
30
30
|
if (seen.has(value)) return [];
|
|
@@ -39,7 +39,7 @@ const extractTransferables = (value, seen = new Set()) => {
|
|
|
39
39
|
return Object.values(value).flatMap(v => extractTransferables(v, seen));
|
|
40
40
|
};
|
|
41
41
|
|
|
42
|
-
const workerFn = ${
|
|
42
|
+
const workerFn = ${n};
|
|
43
43
|
let outputPort = null;
|
|
44
44
|
let inputPort = null;
|
|
45
45
|
let pendingData = null;
|
|
@@ -96,7 +96,7 @@ self.addEventListener('message', (event) => {
|
|
|
96
96
|
pendingData = event.data;
|
|
97
97
|
}
|
|
98
98
|
});
|
|
99
|
-
`,
|
|
99
|
+
`, W = (n) => `
|
|
100
100
|
const extractTransferables = (value, seen = new Set()) => {
|
|
101
101
|
if (value === null || typeof value !== 'object') return [];
|
|
102
102
|
if (seen.has(value)) return [];
|
|
@@ -111,7 +111,7 @@ const extractTransferables = (value, seen = new Set()) => {
|
|
|
111
111
|
return Object.values(value).flatMap(v => extractTransferables(v, seen));
|
|
112
112
|
};
|
|
113
113
|
|
|
114
|
-
const workerFn = ${
|
|
114
|
+
const workerFn = ${n};
|
|
115
115
|
let cachedDataset = null;
|
|
116
116
|
|
|
117
117
|
self.addEventListener('message', async (event) => {
|
|
@@ -153,13 +153,13 @@ self.addEventListener('message', async (event) => {
|
|
|
153
153
|
}
|
|
154
154
|
});
|
|
155
155
|
`;
|
|
156
|
-
var
|
|
157
|
-
const
|
|
158
|
-
persistent:
|
|
156
|
+
var w = /* @__PURE__ */ ((n) => (n.Default = "default", n.Pipeline = "pipeline", n.Persistent = "persistent", n))(w || {});
|
|
157
|
+
const M = Object.freeze({
|
|
158
|
+
persistent: W,
|
|
159
159
|
pipeline: P,
|
|
160
160
|
default: y
|
|
161
161
|
});
|
|
162
|
-
class
|
|
162
|
+
class h {
|
|
163
163
|
/**
|
|
164
164
|
* Creates a new `Worker` from the given function.
|
|
165
165
|
*
|
|
@@ -168,16 +168,25 @@ class k {
|
|
|
168
168
|
*
|
|
169
169
|
* @param workerFunction - The function to run inside the worker thread.
|
|
170
170
|
* Must be self-contained — it cannot reference variables from the outer
|
|
171
|
-
* scope because it is
|
|
171
|
+
* scope because it is serialized via `.toString()`.
|
|
172
172
|
* @param options - Optional configuration. Set `mode` to control the
|
|
173
173
|
* worker execution mode (default, pipeline, or persistent).
|
|
174
174
|
*/
|
|
175
|
-
constructor(e,
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
175
|
+
constructor(e, r) {
|
|
176
|
+
k(this, "_worker");
|
|
177
|
+
if (r != null && r.workerInstance)
|
|
178
|
+
this._worker = r.workerInstance;
|
|
179
|
+
else if (r != null && r.workerURL)
|
|
180
|
+
this._worker = new Worker(r.workerURL, { type: "module" });
|
|
181
|
+
else if (e) {
|
|
182
|
+
const o = (r == null ? void 0 : r.mode) ?? "default", a = M[o](e.toString()), i = new Blob([a], {
|
|
183
|
+
type: "application/javascript"
|
|
184
|
+
});
|
|
185
|
+
this._worker = new Worker(URL.createObjectURL(i));
|
|
186
|
+
} else
|
|
187
|
+
throw new Error(
|
|
188
|
+
"Either workerFunction or options.workerURL must be provided to WorkerFactory."
|
|
189
|
+
);
|
|
181
190
|
}
|
|
182
191
|
/**
|
|
183
192
|
* Returns the underlying native `Worker` instance.
|
|
@@ -194,31 +203,33 @@ class b {
|
|
|
194
203
|
this.results = e;
|
|
195
204
|
}
|
|
196
205
|
}
|
|
197
|
-
function
|
|
198
|
-
return
|
|
199
|
-
(
|
|
206
|
+
function g(n, e = /* @__PURE__ */ new Set()) {
|
|
207
|
+
return n === null || typeof n != "object" ? [] : e.has(n) ? [] : (e.add(n), n instanceof ArrayBuffer || n instanceof MessagePort || typeof ImageBitmap < "u" && n instanceof ImageBitmap || typeof OffscreenCanvas < "u" && n instanceof OffscreenCanvas ? [n] : ArrayBuffer.isView(n) ? [n.buffer] : Array.isArray(n) ? n.flatMap((r) => g(r, e)) : Object.values(n).flatMap(
|
|
208
|
+
(r) => g(r, e)
|
|
200
209
|
));
|
|
201
210
|
}
|
|
202
|
-
class
|
|
211
|
+
class _ {
|
|
203
212
|
/**
|
|
204
213
|
* Creates a new `MainWorkerFactory`.
|
|
205
214
|
*
|
|
206
215
|
* @param options - Configuration object containing the `workers` registry.
|
|
207
216
|
*/
|
|
208
217
|
constructor(e) {
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
218
|
+
k(this, "_workers");
|
|
219
|
+
k(this, "_threads");
|
|
220
|
+
k(this, "_persistentWorkers", /* @__PURE__ */ new Map());
|
|
212
221
|
this._workers = e.workers, this._threads = navigator.hardwareConcurrency;
|
|
213
222
|
}
|
|
214
223
|
/**
|
|
215
|
-
* Instantiates a {@link WorkerFactory} for the given worker
|
|
224
|
+
* Instantiates a {@link WorkerFactory} for the given worker configuration.
|
|
216
225
|
*
|
|
217
|
-
* @param
|
|
226
|
+
* @param config - The worker configuration containing `func` or `workerURL`.
|
|
218
227
|
* @returns A new `WorkerFactory` wrapping the worker.
|
|
219
228
|
*/
|
|
220
229
|
initWorker(e) {
|
|
221
|
-
return new
|
|
230
|
+
return new h(e.func, {
|
|
231
|
+
workerURL: e.workerURL
|
|
232
|
+
});
|
|
222
233
|
}
|
|
223
234
|
/**
|
|
224
235
|
* Splits an array into up to `numChunks` evenly-sized sub-arrays.
|
|
@@ -236,16 +247,16 @@ class B {
|
|
|
236
247
|
* partitionArray([1, 2, 3, 4, 5], 3);
|
|
237
248
|
* // → [[1, 2], [3, 4], [5]]
|
|
238
249
|
*/
|
|
239
|
-
partitionArray(e,
|
|
250
|
+
partitionArray(e, r) {
|
|
240
251
|
if (!e.length) return [];
|
|
241
|
-
if (
|
|
242
|
-
const
|
|
252
|
+
if (r <= 0) throw new Error("numChunks must be positive");
|
|
253
|
+
const o = Math.min(r, e.length), a = Math.floor(e.length / o), i = e.length % o, f = [];
|
|
243
254
|
let l = 0;
|
|
244
|
-
for (let
|
|
245
|
-
const
|
|
246
|
-
|
|
255
|
+
for (let t = 0; t < o; t++) {
|
|
256
|
+
const s = a + (t < i ? 1 : 0);
|
|
257
|
+
f.push(e.slice(l, l + s)), l += s;
|
|
247
258
|
}
|
|
248
|
-
return
|
|
259
|
+
return f;
|
|
249
260
|
}
|
|
250
261
|
/**
|
|
251
262
|
* Looks up a registered worker configuration by name.
|
|
@@ -254,7 +265,7 @@ class B {
|
|
|
254
265
|
* @returns The matching config, or `undefined` if not found.
|
|
255
266
|
*/
|
|
256
267
|
findWorkerByName(e) {
|
|
257
|
-
return this._workers.find((
|
|
268
|
+
return this._workers.find((r) => r.name === e);
|
|
258
269
|
}
|
|
259
270
|
/**
|
|
260
271
|
* Runs a named worker against the provided data, distributing work across
|
|
@@ -283,20 +294,20 @@ class B {
|
|
|
283
294
|
* const settled = await foreman.runWorker('sum', { srcData: [1, 2, 3] });
|
|
284
295
|
*/
|
|
285
296
|
async runWorker(e, {
|
|
286
|
-
srcData:
|
|
287
|
-
...
|
|
297
|
+
srcData: r,
|
|
298
|
+
...o
|
|
288
299
|
}) {
|
|
289
300
|
const a = this.findWorkerByName(e);
|
|
290
301
|
if (!a)
|
|
291
302
|
return Promise.reject(new Error(`Worker "${e}" not found`));
|
|
292
|
-
const
|
|
303
|
+
const i = a.maxConcurrency ?? this._threads, f = !!(Array.isArray(r) && r.length > 1 && a.partition), l = f ? this.partitionArray(r, i) : r, t = this.createWorkerPromises(
|
|
293
304
|
a,
|
|
294
305
|
e,
|
|
295
|
-
{ data: l, ...
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
),
|
|
299
|
-
return new b(
|
|
306
|
+
{ data: l, ...o },
|
|
307
|
+
i,
|
|
308
|
+
f
|
|
309
|
+
), s = await Promise.allSettled(t);
|
|
310
|
+
return new b(s);
|
|
300
311
|
}
|
|
301
312
|
/**
|
|
302
313
|
* Builds the array of per-thread worker promises for a single `runWorker`
|
|
@@ -312,16 +323,17 @@ class B {
|
|
|
312
323
|
* @param isPartitioned - Whether `data` is a pre-split array of shards.
|
|
313
324
|
* @returns An array of promises, one per thread.
|
|
314
325
|
*/
|
|
315
|
-
createWorkerPromises(e,
|
|
316
|
-
const { data:
|
|
317
|
-
return Array.from({ length: a }, (
|
|
318
|
-
const
|
|
326
|
+
createWorkerPromises(e, r, o, a, i) {
|
|
327
|
+
const { data: f, ...l } = o;
|
|
328
|
+
return Array.from({ length: a }, (t, s) => {
|
|
329
|
+
const u = i && Array.isArray(f) ? f[s] : f;
|
|
319
330
|
return this.runWorkerWithRetry(
|
|
320
331
|
{
|
|
321
332
|
workerFunc: e.func,
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
333
|
+
workerURL: e.workerURL,
|
|
334
|
+
workerName: r,
|
|
335
|
+
index: s,
|
|
336
|
+
data: { data: u, ...l }
|
|
325
337
|
},
|
|
326
338
|
e.retries
|
|
327
339
|
);
|
|
@@ -339,16 +351,16 @@ class B {
|
|
|
339
351
|
* @returns The successful {@link WorkerResult} once the worker resolves.
|
|
340
352
|
* @throws The last caught error when all retries are exhausted.
|
|
341
353
|
*/
|
|
342
|
-
async runWorkerWithRetry(e,
|
|
354
|
+
async runWorkerWithRetry(e, r = 2) {
|
|
343
355
|
try {
|
|
344
356
|
return await this.initiateWorker(e);
|
|
345
|
-
} catch (
|
|
346
|
-
if (
|
|
357
|
+
} catch (o) {
|
|
358
|
+
if (r > 0)
|
|
347
359
|
return console.error(
|
|
348
|
-
`Worker ${e.index} failed, retrying (${
|
|
349
|
-
|
|
350
|
-
), this.runWorkerWithRetry(e,
|
|
351
|
-
throw console.error("Worker failed after all retries:",
|
|
360
|
+
`Worker ${e.index} failed, retrying (${r} left):`,
|
|
361
|
+
o
|
|
362
|
+
), this.runWorkerWithRetry(e, r - 1);
|
|
363
|
+
throw console.error("Worker failed after all retries:", o), o;
|
|
352
364
|
}
|
|
353
365
|
}
|
|
354
366
|
/**
|
|
@@ -366,48 +378,54 @@ class B {
|
|
|
366
378
|
* The underlying `Worker` is always terminated after the first message,
|
|
367
379
|
* whether it succeeded or failed.
|
|
368
380
|
*
|
|
369
|
-
* @param instanceConfig - Worker function, name, shard index, and data.
|
|
381
|
+
* @param instanceConfig - Worker function, URL, name, shard index, and data.
|
|
370
382
|
* @returns A promise that resolves with the worker's result.
|
|
371
383
|
*/
|
|
372
384
|
initiateWorker({
|
|
373
385
|
workerFunc: e,
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
386
|
+
workerURL: r,
|
|
387
|
+
workerName: o,
|
|
388
|
+
index: a,
|
|
389
|
+
data: i
|
|
377
390
|
}) {
|
|
378
|
-
return new Promise((f,
|
|
379
|
-
const
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
391
|
+
return new Promise((f, l) => {
|
|
392
|
+
const s = this.initWorker({
|
|
393
|
+
name: o,
|
|
394
|
+
role: "",
|
|
395
|
+
func: e,
|
|
396
|
+
workerURL: r
|
|
397
|
+
}).getWorker;
|
|
398
|
+
s.onerror = (c) => {
|
|
399
|
+
s.terminate(), l({
|
|
400
|
+
index: a,
|
|
401
|
+
workerConfigs: { workerFunc: e, workerName: o, index: a, data: i },
|
|
402
|
+
failedResult: c
|
|
385
403
|
});
|
|
386
|
-
},
|
|
387
|
-
var
|
|
388
|
-
if (((
|
|
389
|
-
|
|
390
|
-
index:
|
|
391
|
-
workerConfigs: { workerFunc: e, workerName:
|
|
404
|
+
}, s.onmessage = (c) => {
|
|
405
|
+
var d, p;
|
|
406
|
+
if (((d = c.data) == null ? void 0 : d.ok) === !1) {
|
|
407
|
+
s.terminate(), l({
|
|
408
|
+
index: a,
|
|
409
|
+
workerConfigs: { workerFunc: e, workerName: o, index: a, data: i },
|
|
392
410
|
failedResult: new ErrorEvent("error", {
|
|
393
|
-
message:
|
|
411
|
+
message: c.data.error
|
|
394
412
|
})
|
|
395
413
|
});
|
|
396
414
|
return;
|
|
397
415
|
}
|
|
398
416
|
f({
|
|
399
|
-
index:
|
|
400
|
-
workerConfigs: { workerFunc: e, workerName:
|
|
417
|
+
index: a,
|
|
418
|
+
workerConfigs: { workerFunc: e, workerName: o, index: a, data: i },
|
|
401
419
|
successResult: new MessageEvent("message", {
|
|
402
|
-
data: (
|
|
420
|
+
data: (p = c.data) == null ? void 0 : p.data
|
|
403
421
|
})
|
|
404
|
-
}),
|
|
422
|
+
}), s.terminate();
|
|
405
423
|
};
|
|
406
|
-
const
|
|
407
|
-
index:
|
|
408
|
-
...Array.isArray(
|
|
424
|
+
const u = {
|
|
425
|
+
index: a,
|
|
426
|
+
...Array.isArray(i) ? { data: i } : i
|
|
409
427
|
};
|
|
410
|
-
|
|
428
|
+
s.postMessage(u, g(u));
|
|
411
429
|
});
|
|
412
430
|
}
|
|
413
431
|
/**
|
|
@@ -442,16 +460,16 @@ class B {
|
|
|
442
460
|
* reducer: (shards) => shards.flat().reduce((a, b) => a + b, 0),
|
|
443
461
|
* });
|
|
444
462
|
*/
|
|
445
|
-
async collectResults(e,
|
|
446
|
-
const
|
|
447
|
-
(
|
|
463
|
+
async collectResults(e, r = {}) {
|
|
464
|
+
const o = e.results.filter(
|
|
465
|
+
(t) => t.status === "fulfilled"
|
|
448
466
|
), a = e.results.filter(
|
|
449
|
-
(
|
|
450
|
-
),
|
|
467
|
+
(t) => t.status === "rejected"
|
|
468
|
+
), i = o.map((t) => t.value.successResult.data), f = r.reducer ? r.reducer.toString() : "(shards) => shards.flat()";
|
|
451
469
|
return {
|
|
452
|
-
data: await new Promise((
|
|
453
|
-
const
|
|
454
|
-
const reducer = ${
|
|
470
|
+
data: await new Promise((t, s) => {
|
|
471
|
+
const u = `
|
|
472
|
+
const reducer = ${f};
|
|
455
473
|
self.addEventListener('message', (event) => {
|
|
456
474
|
try {
|
|
457
475
|
const result = reducer(event.data);
|
|
@@ -460,14 +478,14 @@ class B {
|
|
|
460
478
|
self.postMessage({ ok: false, error: String(err) });
|
|
461
479
|
}
|
|
462
480
|
});
|
|
463
|
-
`, c = new Blob([
|
|
464
|
-
d.onmessage = (
|
|
465
|
-
d.terminate(),
|
|
466
|
-
}, d.onerror = (
|
|
467
|
-
d.terminate(),
|
|
468
|
-
}, d.postMessage(
|
|
481
|
+
`, c = new Blob([u], { type: "application/javascript" }), d = new Worker(URL.createObjectURL(c));
|
|
482
|
+
d.onmessage = (p) => {
|
|
483
|
+
d.terminate(), p.data.ok ? t(p.data.data) : s(new Error(p.data.error));
|
|
484
|
+
}, d.onerror = (p) => {
|
|
485
|
+
d.terminate(), s(p);
|
|
486
|
+
}, d.postMessage(i);
|
|
469
487
|
}),
|
|
470
|
-
succeeded:
|
|
488
|
+
succeeded: o.length,
|
|
471
489
|
failed: a.length,
|
|
472
490
|
errors: a
|
|
473
491
|
};
|
|
@@ -502,56 +520,57 @@ class B {
|
|
|
502
520
|
if (e.length === 0)
|
|
503
521
|
throw new Error("Pipeline requires at least one step");
|
|
504
522
|
if (e.length === 1) {
|
|
505
|
-
const
|
|
506
|
-
if (!
|
|
507
|
-
const
|
|
508
|
-
return new Promise((
|
|
509
|
-
|
|
510
|
-
var
|
|
511
|
-
|
|
512
|
-
},
|
|
513
|
-
|
|
523
|
+
const r = e[0], o = this.findWorkerByName(r.worker);
|
|
524
|
+
if (!o) throw new Error(`Worker "${r.worker}" not found`);
|
|
525
|
+
const i = this.initWorker(o).getWorker;
|
|
526
|
+
return new Promise((f, l) => {
|
|
527
|
+
i.onmessage = (s) => {
|
|
528
|
+
var u, c;
|
|
529
|
+
i.terminate(), ((u = s.data) == null ? void 0 : u.ok) === !1 ? l(new Error(s.data.error)) : f((c = s.data) == null ? void 0 : c.data);
|
|
530
|
+
}, i.onerror = (s) => {
|
|
531
|
+
i.terminate(), l(s);
|
|
514
532
|
};
|
|
515
|
-
const
|
|
516
|
-
|
|
517
|
-
{ data:
|
|
518
|
-
|
|
533
|
+
const t = r.srcData ?? {};
|
|
534
|
+
i.postMessage(
|
|
535
|
+
{ data: t, index: 0 },
|
|
536
|
+
g(t)
|
|
519
537
|
);
|
|
520
538
|
});
|
|
521
539
|
}
|
|
522
|
-
return new Promise((
|
|
523
|
-
const a = [],
|
|
524
|
-
for (const
|
|
525
|
-
const
|
|
526
|
-
if (!
|
|
527
|
-
|
|
540
|
+
return new Promise((r, o) => {
|
|
541
|
+
const a = [], i = [];
|
|
542
|
+
for (const t of e) {
|
|
543
|
+
const s = this.findWorkerByName(t.worker);
|
|
544
|
+
if (!s) {
|
|
545
|
+
o(new Error(`Worker "${t.worker}" not found`));
|
|
528
546
|
return;
|
|
529
547
|
}
|
|
530
|
-
const
|
|
531
|
-
mode:
|
|
548
|
+
const u = new h(s.func, {
|
|
549
|
+
mode: w.Pipeline,
|
|
550
|
+
workerURL: s.workerURL
|
|
532
551
|
});
|
|
533
|
-
a.push(
|
|
552
|
+
a.push(u.getWorker);
|
|
534
553
|
}
|
|
535
|
-
for (let
|
|
536
|
-
|
|
537
|
-
for (let
|
|
538
|
-
const
|
|
539
|
-
|
|
540
|
-
{ __pipeline_ports__: !0, ...
|
|
541
|
-
|
|
554
|
+
for (let t = 0; t < a.length - 1; t++)
|
|
555
|
+
i.push(new MessageChannel());
|
|
556
|
+
for (let t = 0; t < a.length; t++) {
|
|
557
|
+
const s = [], u = {};
|
|
558
|
+
t > 0 && (u.inputPort = i[t - 1].port1, s.push(u.inputPort)), t < a.length - 1 && (u.outputPort = i[t].port2, s.push(u.outputPort)), a[t].postMessage(
|
|
559
|
+
{ __pipeline_ports__: !0, ...u },
|
|
560
|
+
s
|
|
542
561
|
);
|
|
543
562
|
}
|
|
544
|
-
const
|
|
545
|
-
|
|
546
|
-
var
|
|
547
|
-
a.forEach((c) => c.terminate()), ((
|
|
548
|
-
},
|
|
549
|
-
a.forEach((
|
|
563
|
+
const f = a[a.length - 1];
|
|
564
|
+
f.onmessage = (t) => {
|
|
565
|
+
var s, u;
|
|
566
|
+
a.forEach((c) => c.terminate()), ((s = t.data) == null ? void 0 : s.ok) === !1 ? o(new Error(t.data.error)) : r((u = t.data) == null ? void 0 : u.data);
|
|
567
|
+
}, f.onerror = (t) => {
|
|
568
|
+
a.forEach((s) => s.terminate()), o(t);
|
|
550
569
|
};
|
|
551
570
|
const l = e[0].srcData ?? {};
|
|
552
571
|
a[0].postMessage(
|
|
553
572
|
{ data: l, index: 0 },
|
|
554
|
-
|
|
573
|
+
g(l)
|
|
555
574
|
);
|
|
556
575
|
});
|
|
557
576
|
}
|
|
@@ -589,24 +608,25 @@ class B {
|
|
|
589
608
|
* // Release when done
|
|
590
609
|
* factory.release('transform');
|
|
591
610
|
*/
|
|
592
|
-
async runPersistent(e,
|
|
593
|
-
const
|
|
594
|
-
if (!
|
|
611
|
+
async runPersistent(e, r) {
|
|
612
|
+
const o = this.findWorkerByName(e);
|
|
613
|
+
if (!o) throw new Error(`Worker "${e}" not found`);
|
|
595
614
|
let a = this._persistentWorkers.get(e);
|
|
596
|
-
return a || (a = new
|
|
597
|
-
mode:
|
|
598
|
-
|
|
599
|
-
|
|
600
|
-
|
|
601
|
-
|
|
602
|
-
|
|
603
|
-
|
|
615
|
+
return a || (a = new h(o.func, {
|
|
616
|
+
mode: w.Persistent,
|
|
617
|
+
workerURL: o.workerURL
|
|
618
|
+
}).getWorker, this._persistentWorkers.set(e, a)), new Promise((i, f) => {
|
|
619
|
+
a.onmessage = (t) => {
|
|
620
|
+
var s, u;
|
|
621
|
+
((s = t.data) == null ? void 0 : s.ok) === !1 ? f(new Error(t.data.error)) : i((u = t.data) == null ? void 0 : u.data);
|
|
622
|
+
}, a.onerror = (t) => {
|
|
623
|
+
f(t);
|
|
604
624
|
};
|
|
605
625
|
const l = {
|
|
606
626
|
type: "run",
|
|
607
|
-
config:
|
|
627
|
+
config: r.config
|
|
608
628
|
};
|
|
609
|
-
|
|
629
|
+
r.dataset !== void 0 && (l.dataset = r.dataset), a.postMessage(l, g(l));
|
|
610
630
|
});
|
|
611
631
|
}
|
|
612
632
|
/**
|
|
@@ -619,11 +639,11 @@ class B {
|
|
|
619
639
|
* @param workerName - Name of the persistent worker to release.
|
|
620
640
|
*/
|
|
621
641
|
release(e) {
|
|
622
|
-
const
|
|
623
|
-
|
|
642
|
+
const r = this._persistentWorkers.get(e);
|
|
643
|
+
r && (r.postMessage({ type: "release" }), r.terminate(), this._persistentWorkers.delete(e));
|
|
624
644
|
}
|
|
625
645
|
}
|
|
626
646
|
export {
|
|
627
|
-
|
|
628
|
-
|
|
647
|
+
_ as MainWorkerFactory,
|
|
648
|
+
h as WorkerFactory
|
|
629
649
|
};
|
|
@@ -45,9 +45,9 @@ declare class MainWorkerFactory<TConfigs extends readonly WorkerConfig<WorkerFun
|
|
|
45
45
|
workers: TConfigs;
|
|
46
46
|
});
|
|
47
47
|
/**
|
|
48
|
-
* Instantiates a {@link WorkerFactory} for the given worker
|
|
48
|
+
* Instantiates a {@link WorkerFactory} for the given worker configuration.
|
|
49
49
|
*
|
|
50
|
-
* @param
|
|
50
|
+
* @param config - The worker configuration containing `func` or `workerURL`.
|
|
51
51
|
* @returns A new `WorkerFactory` wrapping the worker.
|
|
52
52
|
*/
|
|
53
53
|
private initWorker;
|
|
@@ -147,7 +147,7 @@ declare class MainWorkerFactory<TConfigs extends readonly WorkerConfig<WorkerFun
|
|
|
147
147
|
* The underlying `Worker` is always terminated after the first message,
|
|
148
148
|
* whether it succeeded or failed.
|
|
149
149
|
*
|
|
150
|
-
* @param instanceConfig - Worker function, name, shard index, and data.
|
|
150
|
+
* @param instanceConfig - Worker function, URL, name, shard index, and data.
|
|
151
151
|
* @returns A promise that resolves with the worker's result.
|
|
152
152
|
*/
|
|
153
153
|
private initiateWorker;
|
|
@@ -23,8 +23,13 @@ export interface WorkerConfig<TFunc extends WorkerFunction = WorkerFunction> {
|
|
|
23
23
|
name: WorkerName;
|
|
24
24
|
/** Human-readable role label (e.g. `'compute'`, `'transform'`). */
|
|
25
25
|
role: WorkerRole;
|
|
26
|
-
/** The worker function that will be serialised and run in a thread. */
|
|
27
|
-
func
|
|
26
|
+
/** The worker function that will be serialised and run in a thread. Optional if `workerURL` is provided. */
|
|
27
|
+
func?: TFunc;
|
|
28
|
+
/**
|
|
29
|
+
* The worker script URL (or `URL` object created via `new URL(..., import.meta.url)`).
|
|
30
|
+
* Enables module bundlers like Webpack 5, Vite, Rollup, and Parcel to bundle worker code and its dependencies.
|
|
31
|
+
*/
|
|
32
|
+
workerURL?: string | URL;
|
|
28
33
|
/**
|
|
29
34
|
* Maximum number of parallel threads to spawn for this worker.
|
|
30
35
|
* Defaults to `navigator.hardwareConcurrency` when omitted.
|
|
@@ -41,6 +46,11 @@ export interface WorkerConfig<TFunc extends WorkerFunction = WorkerFunction> {
|
|
|
41
46
|
* array.
|
|
42
47
|
*/
|
|
43
48
|
partition?: boolean;
|
|
49
|
+
/**
|
|
50
|
+
* A list of worker functions that must complete before this worker can start.
|
|
51
|
+
* If any dependency fails, this worker will not run.
|
|
52
|
+
*/
|
|
53
|
+
dependencies?: Array<() => void>;
|
|
44
54
|
}
|
|
45
55
|
/**
|
|
46
56
|
* Derives a `name → function` map from a readonly tuple of
|
|
@@ -52,9 +62,11 @@ export interface WorkerConfig<TFunc extends WorkerFunction = WorkerFunction> {
|
|
|
52
62
|
* @typeParam T - The readonly tuple of `WorkerConfig` values.
|
|
53
63
|
*/
|
|
54
64
|
export type WorkerConfigMap<T extends readonly WorkerConfig<WorkerFunction<any, any>>[]> = {
|
|
55
|
-
[K in T[number]['name']]: Extract<T[number], {
|
|
65
|
+
[K in T[number]['name']]: NonNullable<Extract<T[number], {
|
|
66
|
+
name: K;
|
|
67
|
+
}>['func']> extends WorkerFunction ? NonNullable<Extract<T[number], {
|
|
56
68
|
name: K;
|
|
57
|
-
}>['func'];
|
|
69
|
+
}>['func']> : WorkerFunction;
|
|
58
70
|
};
|
|
59
71
|
/**
|
|
60
72
|
* Extracts the `params` type from a {@link WorkerFunction}.
|
|
@@ -91,8 +103,10 @@ export interface MainWorkerFactoryWorker extends WorkerConfig {
|
|
|
91
103
|
export interface WorkerInstanceConfig<TFunc extends WorkerFunction = WorkerFunction> {
|
|
92
104
|
/** Name of the parent worker config, used in logs and error objects. */
|
|
93
105
|
workerName: WorkerName;
|
|
94
|
-
/** The function serialised and executed inside the thread. */
|
|
95
|
-
workerFunc
|
|
106
|
+
/** The function serialised and executed inside the thread (optional if `workerURL` is set). */
|
|
107
|
+
workerFunc?: TFunc;
|
|
108
|
+
/** Worker script URL (string or URL object). */
|
|
109
|
+
workerURL?: string | URL;
|
|
96
110
|
/** Zero-based shard index assigned to this thread. */
|
|
97
111
|
index: number;
|
|
98
112
|
/** The data payload (full or partitioned shard) sent to the thread. */
|
|
@@ -7,9 +7,13 @@ export declare enum WorkerMode {
|
|
|
7
7
|
export interface WorkerFactoryOptions {
|
|
8
8
|
/** The worker execution mode. Defaults to `WorkerMode.Default`. */
|
|
9
9
|
mode?: WorkerMode;
|
|
10
|
+
/** The worker instance to use instead of creating a worker from a function. */
|
|
11
|
+
workerInstance?: Worker;
|
|
12
|
+
/** The worker URL to use instead of creating a worker from a function. */
|
|
13
|
+
workerURL?: string | URL;
|
|
10
14
|
}
|
|
11
15
|
/**
|
|
12
|
-
* Low-level factory that
|
|
16
|
+
* Low-level factory that serializes a {@link WorkerFunction} into a Blob URL
|
|
13
17
|
* and spawns a native `Worker` from it.
|
|
14
18
|
*
|
|
15
19
|
* `WorkerFactory` is an internal building block used by `MainWorkerFactory`.
|
|
@@ -39,11 +43,11 @@ declare class WorkerFactory {
|
|
|
39
43
|
*
|
|
40
44
|
* @param workerFunction - The function to run inside the worker thread.
|
|
41
45
|
* Must be self-contained — it cannot reference variables from the outer
|
|
42
|
-
* scope because it is
|
|
46
|
+
* scope because it is serialized via `.toString()`.
|
|
43
47
|
* @param options - Optional configuration. Set `mode` to control the
|
|
44
48
|
* worker execution mode (default, pipeline, or persistent).
|
|
45
49
|
*/
|
|
46
|
-
constructor(workerFunction
|
|
50
|
+
constructor(workerFunction?: WorkerFunction, options?: WorkerFactoryOptions);
|
|
47
51
|
/**
|
|
48
52
|
* Returns the underlying native `Worker` instance.
|
|
49
53
|
*
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@offmain/workerkit",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.12.3",
|
|
4
4
|
"description": "A lightweight manager for running functions in Web Workers with partitioning, retries, and concurrency control",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.cjs",
|
|
@@ -76,6 +76,9 @@
|
|
|
76
76
|
"typescript": "^5.7.2",
|
|
77
77
|
"vite": "^6.3.3",
|
|
78
78
|
"vite-plugin-dts": "^4.5.4",
|
|
79
|
-
"vitest": "^1.0.0"
|
|
79
|
+
"vitest": "^1.0.0",
|
|
80
|
+
"luxon": "^3.7.2",
|
|
81
|
+
"i18next": "^25.5.1",
|
|
82
|
+
"@types/luxon": "^3.7.2"
|
|
80
83
|
}
|
|
81
84
|
}
|