@offmain/workerkit 0.13.0 → 0.14.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 +74 -25
- package/dist/index.cjs +15 -7
- package/dist/index.js +208 -161
- package/dist/types/tools/define-worker.d.ts +21 -0
- package/dist/types/tools/define-worker.test.d.ts +1 -0
- package/dist/types/tools/index.d.ts +1 -0
- package/dist/types/tools/main-worker-factory/types.d.ts +2 -0
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -75,27 +75,32 @@ When worker logic relies on external npm packages (such as Luxon, `date-fns`, `i
|
|
|
75
75
|
|
|
76
76
|
Passing `createWorker` 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
77
|
|
|
78
|
-
### Dedicated Worker Script
|
|
78
|
+
### Dedicated Worker Script with `defineWorker`
|
|
79
|
+
|
|
80
|
+
When writing standalone worker files, wrap your export in `defineWorker`. This automatically handles standard runs, worker-to-worker pipelines (`pipeline()`), and persistent dataset caching without manual `postMessage` / `onmessage` boilerplate:
|
|
79
81
|
|
|
80
82
|
```ts
|
|
81
83
|
// transform-data.worker.ts
|
|
84
|
+
import { defineWorker } from '@offmain/workerkit';
|
|
82
85
|
import { format } from 'date-fns';
|
|
83
86
|
import { t } from './i18n.ts';
|
|
84
87
|
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
88
|
+
export default defineWorker(
|
|
89
|
+
async ({
|
|
90
|
+
data,
|
|
91
|
+
options,
|
|
92
|
+
}: {
|
|
93
|
+
data: { items: any[]; locale: string };
|
|
94
|
+
options?: { prefix?: string };
|
|
95
|
+
}) => {
|
|
96
|
+
const { items, locale } = data;
|
|
97
|
+
return items.map((item: any) => ({
|
|
89
98
|
...item,
|
|
90
99
|
formattedDate: format(new Date(item.timestamp), 'yyyy-MM-dd'),
|
|
91
|
-
label: t('transaction', locale),
|
|
100
|
+
label: (options?.prefix ?? '') + t('transaction', locale),
|
|
92
101
|
}));
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
} catch (err) {
|
|
96
|
-
self.postMessage({ ok: false, error: (err as Error).message });
|
|
97
|
-
}
|
|
98
|
-
});
|
|
102
|
+
},
|
|
103
|
+
);
|
|
99
104
|
```
|
|
100
105
|
|
|
101
106
|
### Webpack 5 & Vite Static Analysis (`createWorker`)
|
|
@@ -176,7 +181,7 @@ Only the final result crosses back to the main thread. If your pipeline generate
|
|
|
176
181
|
|
|
177
182
|
### Usage
|
|
178
183
|
|
|
179
|
-
|
|
184
|
+
````ts
|
|
180
185
|
import { MainWorkerFactory } from '@offmain/workerkit';
|
|
181
186
|
import { fetchData, transform, aggregate } from './workers.ts';
|
|
182
187
|
|
|
@@ -188,20 +193,33 @@ const factory = new MainWorkerFactory({
|
|
|
188
193
|
] as const,
|
|
189
194
|
});
|
|
190
195
|
|
|
196
|
+
### Step-Specific Options and Configs in Pipeline
|
|
197
|
+
|
|
198
|
+
You can pass step-specific parameters (such as `options`, `configs`, etc.) directly to each pipeline step:
|
|
199
|
+
|
|
200
|
+
```ts
|
|
191
201
|
const result = await factory.pipeline<AggregateResult>([
|
|
192
|
-
{
|
|
193
|
-
|
|
194
|
-
|
|
202
|
+
{
|
|
203
|
+
worker: 'fetchData',
|
|
204
|
+
srcData: { url: '/api/records' },
|
|
205
|
+
options: { timeout: 5000 },
|
|
206
|
+
},
|
|
207
|
+
{
|
|
208
|
+
worker: 'transform',
|
|
209
|
+
configs: { multiplier: 2 },
|
|
210
|
+
},
|
|
211
|
+
{
|
|
212
|
+
worker: 'aggregate',
|
|
213
|
+
options: { threshold: 10 },
|
|
214
|
+
},
|
|
195
215
|
]);
|
|
216
|
+
````
|
|
196
217
|
|
|
197
|
-
|
|
198
|
-
```
|
|
199
|
-
|
|
200
|
-
### How each step receives data
|
|
218
|
+
### How each step receives data and parameters
|
|
201
219
|
|
|
202
|
-
- The first step receives `srcData` as `{ data: srcData,
|
|
203
|
-
- Each subsequent step receives the previous step's output as `{ data: previousOutput, index: 0 }`.
|
|
204
|
-
- Worker functions
|
|
220
|
+
- The first step receives `srcData` merged with its step parameters as `{ data: srcData, options: { timeout: 5000 }, index: 0 }`.
|
|
221
|
+
- Each subsequent step receives the previous step's output merged with its step parameters as `{ data: previousOutput, configs: { multiplier: 2 }, index: 0 }`.
|
|
222
|
+
- Worker functions (both inline functions and native scripts using `defineWorker`) receive all step parameters in their first argument.
|
|
205
223
|
|
|
206
224
|
### When to use pipeline vs runWorker
|
|
207
225
|
|
|
@@ -310,11 +328,42 @@ The framework handles the caching transparently — your function always receive
|
|
|
310
328
|
|
|
311
329
|
The cached dataset lives in worker memory until `release()` is called. For large datasets, always call `release()` when you're done to free the memory:
|
|
312
330
|
|
|
331
|
+
After releasing, the next `runPersistent` call will create a fresh worker instance (requiring a new dataset).
|
|
332
|
+
|
|
333
|
+
---
|
|
334
|
+
|
|
335
|
+
## Lifecycle Management (`terminate`, `destroy`, `reset`, `restart`)
|
|
336
|
+
|
|
337
|
+
`MainWorkerFactory` provides built-in lifecycle management to terminate running workers and clean up browser resources:
|
|
338
|
+
|
|
339
|
+
### `terminate()` / `destroy()`
|
|
340
|
+
|
|
341
|
+
Immediately stops all active workers (one-shot tasks, pipelines, reducers) and releases all cached persistent workers:
|
|
342
|
+
|
|
313
343
|
```ts
|
|
314
|
-
|
|
344
|
+
// Stop all active threads and release persistent workers
|
|
345
|
+
factory.terminate();
|
|
346
|
+
// or
|
|
347
|
+
factory.destroy(); // Alias for terminate()
|
|
348
|
+
|
|
349
|
+
console.log(factory.isTerminated); // true
|
|
315
350
|
```
|
|
316
351
|
|
|
317
|
-
After
|
|
352
|
+
After calling `terminate()`, any attempt to run workers on the factory instance will immediately reject.
|
|
353
|
+
|
|
354
|
+
### `reset()` / `restart()`
|
|
355
|
+
|
|
356
|
+
Terminates all active/persistent worker instances and restores the factory to an active state (`isTerminated = false`), allowing new worker instances to be initiated cleanly:
|
|
357
|
+
|
|
358
|
+
```ts
|
|
359
|
+
// Stop existing workers and reset factory state
|
|
360
|
+
factory.reset(); // or factory.restart()
|
|
361
|
+
|
|
362
|
+
console.log(factory.isTerminated); // false
|
|
363
|
+
|
|
364
|
+
// Factory is ready to initiate fresh worker instances again
|
|
365
|
+
const settled = await factory.runWorker('sum', { srcData: [1, 2, 3] });
|
|
366
|
+
```
|
|
318
367
|
|
|
319
368
|
---
|
|
320
369
|
|
package/dist/index.cjs
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
"use strict";var
|
|
1
|
+
"use strict";var S=Object.defineProperty;var x=(n,e,r)=>e in n?S(n,e,{enumerable:!0,configurable:!0,writable:!0,value:r}):n[e]=r;var y=(n,e,r)=>x(n,typeof e!="symbol"?e+"":e,r);Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const O=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 [];
|
|
@@ -21,7 +21,7 @@ self.addEventListener('message', async (event) => {
|
|
|
21
21
|
self.postMessage({ ok: false, error: err instanceof Error ? err.message : String(err) });
|
|
22
22
|
}
|
|
23
23
|
})
|
|
24
|
-
`,
|
|
24
|
+
`,F=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 [];
|
|
@@ -40,10 +40,15 @@ const workerFn = ${n};
|
|
|
40
40
|
let outputPort = null;
|
|
41
41
|
let inputPort = null;
|
|
42
42
|
let pendingData = null;
|
|
43
|
+
let stepParams = {};
|
|
43
44
|
|
|
44
45
|
async function processData(data) {
|
|
45
46
|
try {
|
|
46
|
-
const
|
|
47
|
+
const payload =
|
|
48
|
+
typeof data === 'object' && data !== null && 'data' in data
|
|
49
|
+
? { ...stepParams, ...data }
|
|
50
|
+
: { data, ...stepParams, index: 0 };
|
|
51
|
+
const output = await workerFn(payload);
|
|
47
52
|
const result = { ok: true, data: output };
|
|
48
53
|
const transfers = extractTransferables(output);
|
|
49
54
|
if (outputPort) {
|
|
@@ -63,6 +68,9 @@ async function processData(data) {
|
|
|
63
68
|
|
|
64
69
|
self.addEventListener('message', (event) => {
|
|
65
70
|
if (event.data && event.data.__pipeline_ports__) {
|
|
71
|
+
if (event.data.stepParams) {
|
|
72
|
+
stepParams = event.data.stepParams;
|
|
73
|
+
}
|
|
66
74
|
if (event.data.outputPort) {
|
|
67
75
|
outputPort = event.data.outputPort;
|
|
68
76
|
}
|
|
@@ -74,7 +82,7 @@ self.addEventListener('message', (event) => {
|
|
|
74
82
|
if (outputPort) outputPort.postMessage(e.data);
|
|
75
83
|
else self.postMessage(e.data);
|
|
76
84
|
} else {
|
|
77
|
-
processData({ data: e.data.data, index: 0 });
|
|
85
|
+
processData({ data: e.data.data, ...stepParams, index: 0 });
|
|
78
86
|
}
|
|
79
87
|
};
|
|
80
88
|
}
|
|
@@ -93,7 +101,7 @@ self.addEventListener('message', (event) => {
|
|
|
93
101
|
pendingData = event.data;
|
|
94
102
|
}
|
|
95
103
|
});
|
|
96
|
-
`,
|
|
104
|
+
`,R=n=>`
|
|
97
105
|
const extractTransferables = (value, seen = new Set()) => {
|
|
98
106
|
if (value === null || typeof value !== 'object') return [];
|
|
99
107
|
if (seen.has(value)) return [];
|
|
@@ -149,7 +157,7 @@ self.addEventListener('message', async (event) => {
|
|
|
149
157
|
self.postMessage({ ok: false, error: err instanceof Error ? err.message : String(err) });
|
|
150
158
|
}
|
|
151
159
|
});
|
|
152
|
-
`;var
|
|
160
|
+
`;var P=(n=>(n.Default="default",n.Pipeline="pipeline",n.Persistent="persistent",n))(P||{});const C=Object.freeze({persistent:R,pipeline:F,default:O});class v{constructor(e,r){y(this,"_worker");if(r!=null&&r.createWorker)this._worker=r.createWorker();else if(e){const s=(r==null?void 0:r.mode)??"default",t=C[s](e.toString()),l=new Blob([t],{type:"application/javascript"});this._worker=new Worker(URL.createObjectURL(l))}else throw new Error("Either workerFunction or options.createWorker must be provided to WorkerFactory.")}get getWorker(){return this._worker}}class j{constructor(e){this.results=e}}function m(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=>m(r,e)):Object.values(n).flatMap(r=>m(r,e)))}class L{constructor(e){y(this,"_workers");y(this,"_threads");y(this,"_persistentWorkers",new Map);y(this,"_activeWorkers",new Set);y(this,"_isTerminated",!1);this._workers=e.workers,this._threads=navigator.hardwareConcurrency}get isTerminated(){return this._isTerminated}trackWorker(e){if(this._isTerminated)throw e.terminate(),new Error("MainWorkerFactory has been terminated");return this._activeWorkers.add(e),e}terminateWorker(e){this._activeWorkers.delete(e);try{e.terminate()}catch{}}initWorker(e){const r=new v(e.func,{createWorker:e.createWorker});return this.trackWorker(r.getWorker),r}partitionArray(e,r){if(!e.length)return[];if(r<=0)throw new Error("numChunks must be positive");const s=Math.min(r,e.length),t=Math.floor(e.length/s),l=e.length%s,c=[];let f=0;for(let a=0;a<s;a++){const o=t+(a<l?1:0);c.push(e.slice(f,f+o)),f+=o}return c}findWorkerByName(e){return this._workers.find(r=>r.name===e)}async runWorker(e,{srcData:r,...s}){if(this._isTerminated)return Promise.reject(new Error("MainWorkerFactory has been terminated"));const t=this.findWorkerByName(e);if(!t)return Promise.reject(new Error(`Worker "${e}" not found`));const l=t.maxConcurrency??this._threads,c=!!(Array.isArray(r)&&r.length>1&&t.partition),f=c?this.partitionArray(r,l):r,a=this.createWorkerPromises(t,e,{data:f,...s},l,c),o=await Promise.allSettled(a);return new j(o)}createWorkerPromises(e,r,s,t,l){const{data:c,...f}=s;return Array.from({length:t},(a,o)=>{const d=l&&Array.isArray(c)?c[o]:c;return this.runWorkerWithRetry({workerFunc:e.func,createWorker:e.createWorker,workerName:r,index:o,data:{data:d,...f}},e.retries)})}async runWorkerWithRetry(e,r=2){try{return await this.initiateWorker(e)}catch(s){if(r>0)return console.error(`Worker ${e.index} failed, retrying (${r} left):`,s),this.runWorkerWithRetry(e,r-1);throw console.error("Worker failed after all retries:",s),s}}initiateWorker({workerFunc:e,createWorker:r,workerName:s,index:t,data:l}){return new Promise((c,f)=>{const o=this.initWorker({name:s,role:"",func:e,createWorker:r}).getWorker;o.onerror=p=>{this.terminateWorker(o),f({index:t,workerConfigs:{workerFunc:e,createWorker:r,workerName:s,index:t,data:l},failedResult:p})},o.onmessage=p=>{var i,u;if(((i=p.data)==null?void 0:i.ok)===!1){this.terminateWorker(o),f({index:t,workerConfigs:{workerFunc:e,createWorker:r,workerName:s,index:t,data:l},failedResult:new ErrorEvent("error",{message:p.data.error})});return}c({index:t,workerConfigs:{workerFunc:e,createWorker:r,workerName:s,index:t,data:l},successResult:new MessageEvent("message",{data:(u=p.data)==null?void 0:u.data})}),this.terminateWorker(o)};const d={index:t,...Array.isArray(l)?{data:l}:l};o.postMessage(d,m(d))})}async collectResults(e,r={}){if(this._isTerminated)throw new Error("MainWorkerFactory has been terminated");const s=e.results.filter(a=>a.status==="fulfilled"),t=e.results.filter(a=>a.status==="rejected"),l=s.map(a=>a.value.successResult.data),c=r.reducer?r.reducer.toString():"(shards) => shards.flat()";return{data:await new Promise((a,o)=>{const d=`
|
|
153
161
|
const reducer = ${c};
|
|
154
162
|
self.addEventListener('message', (event) => {
|
|
155
163
|
try {
|
|
@@ -159,4 +167,4 @@ self.addEventListener('message', async (event) => {
|
|
|
159
167
|
self.postMessage({ ok: false, error: String(err) });
|
|
160
168
|
}
|
|
161
169
|
});
|
|
162
|
-
`,
|
|
170
|
+
`,p=new Blob([d],{type:"application/javascript"}),i=this.trackWorker(new Worker(URL.createObjectURL(p)));i.onmessage=u=>{this.terminateWorker(i),u.data.ok?a(u.data.data):o(new Error(u.data.error))},i.onerror=u=>{this.terminateWorker(i),o(u)},i.postMessage(l)}),succeeded:s.length,failed:t.length,errors:t}}async pipeline(e){if(this._isTerminated)throw new Error("MainWorkerFactory has been terminated");if(e.length===0)throw new Error("Pipeline requires at least one step");if(e.length===1){const r=e[0],{worker:s,srcData:t,...l}=r,c=this.findWorkerByName(r.worker);if(!c)throw new Error(`Worker "${r.worker}" not found`);const a=this.initWorker(c).getWorker;return new Promise((o,d)=>{a.onmessage=u=>{var k,g;this.terminateWorker(a),((k=u.data)==null?void 0:k.ok)===!1?d(new Error(u.data.error)):o((g=u.data)==null?void 0:g.data)},a.onerror=u=>{this.terminateWorker(a),d(u)};const i={data:t??{},...l,index:0};a.postMessage(i,m(i))})}return new Promise((r,s)=>{const t=[],l=[];for(const i of e){const u=this.findWorkerByName(i.worker);if(!u){s(new Error(`Worker "${i.worker}" not found`));return}const k=new v(u.func,{mode:P.Pipeline,createWorker:u.createWorker}),g=this.trackWorker(k.getWorker);t.push(g)}for(let i=0;i<t.length-1;i++)l.push(new MessageChannel);for(let i=0;i<t.length;i++){const{worker:u,srcData:k,...g}=e[i],W=[],w={};if(i>0&&(w.inputPort=l[i-1].port1,W.push(w.inputPort)),i<t.length-1&&(w.outputPort=l[i].port2,W.push(w.outputPort)),t[i].postMessage({__pipeline_ports__:!0,stepParams:g,...w},W),i<t.length-1){const _=t[i],A=t[i+1],{worker:I,srcData:U,...D}=e[i+1];_.onmessage=h=>{var E,T;if(h.data&&h.data.__pipeline_ports__)return;if(((E=h.data)==null?void 0:E.ok)===!1){t.forEach(B=>this.terminateWorker(B)),s(new Error(h.data.error));return}const b={data:((T=h.data)==null?void 0:T.ok)!==void 0?h.data.data:h.data,...D,index:0};A.postMessage(b,m(b))},_.onerror=h=>{t.forEach(M=>this.terminateWorker(M)),s(h)}}}const c=t[t.length-1];c.onmessage=i=>{var u,k;t.forEach(g=>this.terminateWorker(g)),((u=i.data)==null?void 0:u.ok)===!1?s(new Error(i.data.error)):r((k=i.data)==null?void 0:k.data)},c.onerror=i=>{t.forEach(u=>this.terminateWorker(u)),s(i)};const{worker:f,srcData:a,...o}=e[0],p={data:a??{},...o,index:0};t[0].postMessage(p,m(p))})}async runPersistent(e,r){if(this._isTerminated)throw new Error("MainWorkerFactory has been terminated");const s=this.findWorkerByName(e);if(!s)throw new Error(`Worker "${e}" not found`);let t=this._persistentWorkers.get(e);if(!t){const l=new v(s.func,{mode:P.Persistent,createWorker:s.createWorker});t=this.trackWorker(l.getWorker),this._persistentWorkers.set(e,t)}return new Promise((l,c)=>{t.onmessage=a=>{var o,d;((o=a.data)==null?void 0:o.ok)===!1?c(new Error(a.data.error)):l((d=a.data)==null?void 0:d.data)},t.onerror=a=>{c(a)};const f={type:"run",config:r.config};r.dataset!==void 0&&(f.dataset=r.dataset),t.postMessage(f,m(f))})}release(e){const r=this._persistentWorkers.get(e);if(r){try{r.postMessage({type:"release"})}catch{}this.terminateWorker(r),this._persistentWorkers.delete(e)}}terminate(){this._isTerminated=!0;for(const e of this._persistentWorkers.values()){try{e.postMessage({type:"release"})}catch{}this.terminateWorker(e)}this._persistentWorkers.clear();for(const e of Array.from(this._activeWorkers))this.terminateWorker(e);this._activeWorkers.clear()}destroy(){this.terminate()}reset(){this.terminate(),this._isTerminated=!1}restart(){this.reset()}}function $(n){if(typeof self>"u")return;let e=null,r=null,s=null,t={};const l=(f,a)=>{self.postMessage(f,a)};async function c(f){try{const a=typeof f=="object"&&f!==null&&"data"in f?{...t,...f}:{data:f,...t,index:0},o=await n(a),d={ok:!0,data:o},p=m(o);e?e.postMessage(d,p):l(d,p)}catch(a){const o={ok:!1,error:a instanceof Error?a.message:String(a)};e?e.postMessage(o):l(o)}}self.addEventListener("message",f=>{const a=f.data;if(a&&a.__pipeline_ports__){a.stepParams&&(t=a.stepParams),a.outputPort&&(e=a.outputPort),a.inputPort&&(r=a.inputPort,r.onmessage=o=>{var d;o.data&&o.data.ok===!1?e?e.postMessage(o.data):l(o.data):c({data:(d=o.data)==null?void 0:d.data,...t,index:0})}),s!==null&&(c(s),s=null);return}r?s=a:c(a)})}exports.MainWorkerFactory=L;exports.WorkerFactory=v;exports.defineWorker=$;
|
package/dist/index.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
var
|
|
2
|
-
var
|
|
3
|
-
var
|
|
4
|
-
const
|
|
1
|
+
var S = Object.defineProperty;
|
|
2
|
+
var x = (n, e, r) => e in n ? S(n, e, { enumerable: !0, configurable: !0, writable: !0, value: r }) : n[e] = r;
|
|
3
|
+
var y = (n, e, r) => x(n, typeof e != "symbol" ? e + "" : e, r);
|
|
4
|
+
const O = (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 [];
|
|
@@ -24,7 +24,7 @@ self.addEventListener('message', async (event) => {
|
|
|
24
24
|
self.postMessage({ ok: false, error: err instanceof Error ? err.message : String(err) });
|
|
25
25
|
}
|
|
26
26
|
})
|
|
27
|
-
`,
|
|
27
|
+
`, R = (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 [];
|
|
@@ -43,10 +43,15 @@ const workerFn = ${n};
|
|
|
43
43
|
let outputPort = null;
|
|
44
44
|
let inputPort = null;
|
|
45
45
|
let pendingData = null;
|
|
46
|
+
let stepParams = {};
|
|
46
47
|
|
|
47
48
|
async function processData(data) {
|
|
48
49
|
try {
|
|
49
|
-
const
|
|
50
|
+
const payload =
|
|
51
|
+
typeof data === 'object' && data !== null && 'data' in data
|
|
52
|
+
? { ...stepParams, ...data }
|
|
53
|
+
: { data, ...stepParams, index: 0 };
|
|
54
|
+
const output = await workerFn(payload);
|
|
50
55
|
const result = { ok: true, data: output };
|
|
51
56
|
const transfers = extractTransferables(output);
|
|
52
57
|
if (outputPort) {
|
|
@@ -66,6 +71,9 @@ async function processData(data) {
|
|
|
66
71
|
|
|
67
72
|
self.addEventListener('message', (event) => {
|
|
68
73
|
if (event.data && event.data.__pipeline_ports__) {
|
|
74
|
+
if (event.data.stepParams) {
|
|
75
|
+
stepParams = event.data.stepParams;
|
|
76
|
+
}
|
|
69
77
|
if (event.data.outputPort) {
|
|
70
78
|
outputPort = event.data.outputPort;
|
|
71
79
|
}
|
|
@@ -77,7 +85,7 @@ self.addEventListener('message', (event) => {
|
|
|
77
85
|
if (outputPort) outputPort.postMessage(e.data);
|
|
78
86
|
else self.postMessage(e.data);
|
|
79
87
|
} else {
|
|
80
|
-
processData({ data: e.data.data, index: 0 });
|
|
88
|
+
processData({ data: e.data.data, ...stepParams, index: 0 });
|
|
81
89
|
}
|
|
82
90
|
};
|
|
83
91
|
}
|
|
@@ -96,7 +104,7 @@ self.addEventListener('message', (event) => {
|
|
|
96
104
|
pendingData = event.data;
|
|
97
105
|
}
|
|
98
106
|
});
|
|
99
|
-
`,
|
|
107
|
+
`, F = (n) => `
|
|
100
108
|
const extractTransferables = (value, seen = new Set()) => {
|
|
101
109
|
if (value === null || typeof value !== 'object') return [];
|
|
102
110
|
if (seen.has(value)) return [];
|
|
@@ -153,13 +161,13 @@ self.addEventListener('message', async (event) => {
|
|
|
153
161
|
}
|
|
154
162
|
});
|
|
155
163
|
`;
|
|
156
|
-
var
|
|
157
|
-
const
|
|
158
|
-
persistent:
|
|
159
|
-
pipeline:
|
|
160
|
-
default:
|
|
164
|
+
var P = /* @__PURE__ */ ((n) => (n.Default = "default", n.Pipeline = "pipeline", n.Persistent = "persistent", n))(P || {});
|
|
165
|
+
const C = Object.freeze({
|
|
166
|
+
persistent: F,
|
|
167
|
+
pipeline: R,
|
|
168
|
+
default: O
|
|
161
169
|
});
|
|
162
|
-
class
|
|
170
|
+
class W {
|
|
163
171
|
/**
|
|
164
172
|
* Creates a new `Worker` from the given function or factory option.
|
|
165
173
|
*
|
|
@@ -169,14 +177,14 @@ class g {
|
|
|
169
177
|
* @param options - Optional configuration containing `createWorker` or `mode`.
|
|
170
178
|
*/
|
|
171
179
|
constructor(e, r) {
|
|
172
|
-
|
|
180
|
+
y(this, "_worker");
|
|
173
181
|
if (r != null && r.createWorker)
|
|
174
182
|
this._worker = r.createWorker();
|
|
175
183
|
else if (e) {
|
|
176
|
-
const
|
|
184
|
+
const s = (r == null ? void 0 : r.mode) ?? "default", t = C[s](e.toString()), l = new Blob([t], {
|
|
177
185
|
type: "application/javascript"
|
|
178
186
|
});
|
|
179
|
-
this._worker = new Worker(URL.createObjectURL(
|
|
187
|
+
this._worker = new Worker(URL.createObjectURL(l));
|
|
180
188
|
} else
|
|
181
189
|
throw new Error(
|
|
182
190
|
"Either workerFunction or options.createWorker must be provided to WorkerFactory."
|
|
@@ -192,28 +200,28 @@ class g {
|
|
|
192
200
|
return this._worker;
|
|
193
201
|
}
|
|
194
202
|
}
|
|
195
|
-
class
|
|
203
|
+
class L {
|
|
196
204
|
constructor(e) {
|
|
197
205
|
this.results = e;
|
|
198
206
|
}
|
|
199
207
|
}
|
|
200
|
-
function
|
|
201
|
-
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) =>
|
|
202
|
-
(r) =>
|
|
208
|
+
function m(n, e = /* @__PURE__ */ new Set()) {
|
|
209
|
+
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) => m(r, e)) : Object.values(n).flatMap(
|
|
210
|
+
(r) => m(r, e)
|
|
203
211
|
));
|
|
204
212
|
}
|
|
205
|
-
class
|
|
213
|
+
class U {
|
|
206
214
|
/**
|
|
207
215
|
* Creates a new `MainWorkerFactory`.
|
|
208
216
|
*
|
|
209
217
|
* @param options - Configuration object containing the `workers` registry.
|
|
210
218
|
*/
|
|
211
219
|
constructor(e) {
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
220
|
+
y(this, "_workers");
|
|
221
|
+
y(this, "_threads");
|
|
222
|
+
y(this, "_persistentWorkers", /* @__PURE__ */ new Map());
|
|
223
|
+
y(this, "_activeWorkers", /* @__PURE__ */ new Set());
|
|
224
|
+
y(this, "_isTerminated", !1);
|
|
217
225
|
this._workers = e.workers, this._threads = navigator.hardwareConcurrency;
|
|
218
226
|
}
|
|
219
227
|
/**
|
|
@@ -247,7 +255,7 @@ class E {
|
|
|
247
255
|
* @returns A new `WorkerFactory` wrapping the worker.
|
|
248
256
|
*/
|
|
249
257
|
initWorker(e) {
|
|
250
|
-
const r = new
|
|
258
|
+
const r = new W(e.func, {
|
|
251
259
|
createWorker: e.createWorker
|
|
252
260
|
});
|
|
253
261
|
return this.trackWorker(r.getWorker), r;
|
|
@@ -271,11 +279,11 @@ class E {
|
|
|
271
279
|
partitionArray(e, r) {
|
|
272
280
|
if (!e.length) return [];
|
|
273
281
|
if (r <= 0) throw new Error("numChunks must be positive");
|
|
274
|
-
const
|
|
275
|
-
let
|
|
276
|
-
for (let
|
|
277
|
-
const
|
|
278
|
-
c.push(e.slice(
|
|
282
|
+
const s = Math.min(r, e.length), t = Math.floor(e.length / s), l = e.length % s, c = [];
|
|
283
|
+
let f = 0;
|
|
284
|
+
for (let a = 0; a < s; a++) {
|
|
285
|
+
const o = t + (a < l ? 1 : 0);
|
|
286
|
+
c.push(e.slice(f, f + o)), f += o;
|
|
279
287
|
}
|
|
280
288
|
return c;
|
|
281
289
|
}
|
|
@@ -316,21 +324,21 @@ class E {
|
|
|
316
324
|
*/
|
|
317
325
|
async runWorker(e, {
|
|
318
326
|
srcData: r,
|
|
319
|
-
...
|
|
327
|
+
...s
|
|
320
328
|
}) {
|
|
321
329
|
if (this._isTerminated)
|
|
322
330
|
return Promise.reject(new Error("MainWorkerFactory has been terminated"));
|
|
323
|
-
const
|
|
324
|
-
if (!
|
|
331
|
+
const t = this.findWorkerByName(e);
|
|
332
|
+
if (!t)
|
|
325
333
|
return Promise.reject(new Error(`Worker "${e}" not found`));
|
|
326
|
-
const
|
|
327
|
-
|
|
334
|
+
const l = t.maxConcurrency ?? this._threads, c = !!(Array.isArray(r) && r.length > 1 && t.partition), f = c ? this.partitionArray(r, l) : r, a = this.createWorkerPromises(
|
|
335
|
+
t,
|
|
328
336
|
e,
|
|
329
|
-
{ data:
|
|
330
|
-
|
|
337
|
+
{ data: f, ...s },
|
|
338
|
+
l,
|
|
331
339
|
c
|
|
332
|
-
),
|
|
333
|
-
return new
|
|
340
|
+
), o = await Promise.allSettled(a);
|
|
341
|
+
return new L(o);
|
|
334
342
|
}
|
|
335
343
|
/**
|
|
336
344
|
* Builds the array of per-thread worker promises for a single `runWorker`
|
|
@@ -346,17 +354,17 @@ class E {
|
|
|
346
354
|
* @param isPartitioned - Whether `data` is a pre-split array of shards.
|
|
347
355
|
* @returns An array of promises, one per thread.
|
|
348
356
|
*/
|
|
349
|
-
createWorkerPromises(e, r,
|
|
350
|
-
const { data: c, ...
|
|
351
|
-
return Array.from({ length:
|
|
352
|
-
const
|
|
357
|
+
createWorkerPromises(e, r, s, t, l) {
|
|
358
|
+
const { data: c, ...f } = s;
|
|
359
|
+
return Array.from({ length: t }, (a, o) => {
|
|
360
|
+
const d = l && Array.isArray(c) ? c[o] : c;
|
|
353
361
|
return this.runWorkerWithRetry(
|
|
354
362
|
{
|
|
355
363
|
workerFunc: e.func,
|
|
356
364
|
createWorker: e.createWorker,
|
|
357
365
|
workerName: r,
|
|
358
|
-
index:
|
|
359
|
-
data: { data:
|
|
366
|
+
index: o,
|
|
367
|
+
data: { data: d, ...f }
|
|
360
368
|
},
|
|
361
369
|
e.retries
|
|
362
370
|
);
|
|
@@ -377,13 +385,13 @@ class E {
|
|
|
377
385
|
async runWorkerWithRetry(e, r = 2) {
|
|
378
386
|
try {
|
|
379
387
|
return await this.initiateWorker(e);
|
|
380
|
-
} catch (
|
|
388
|
+
} catch (s) {
|
|
381
389
|
if (r > 0)
|
|
382
390
|
return console.error(
|
|
383
391
|
`Worker ${e.index} failed, retrying (${r} left):`,
|
|
384
|
-
|
|
392
|
+
s
|
|
385
393
|
), this.runWorkerWithRetry(e, r - 1);
|
|
386
|
-
throw console.error("Worker failed after all retries:",
|
|
394
|
+
throw console.error("Worker failed after all retries:", s), s;
|
|
387
395
|
}
|
|
388
396
|
}
|
|
389
397
|
/**
|
|
@@ -406,66 +414,66 @@ class E {
|
|
|
406
414
|
initiateWorker({
|
|
407
415
|
workerFunc: e,
|
|
408
416
|
createWorker: r,
|
|
409
|
-
workerName:
|
|
410
|
-
index:
|
|
411
|
-
data:
|
|
417
|
+
workerName: s,
|
|
418
|
+
index: t,
|
|
419
|
+
data: l
|
|
412
420
|
}) {
|
|
413
|
-
return new Promise((c,
|
|
414
|
-
const
|
|
415
|
-
name:
|
|
421
|
+
return new Promise((c, f) => {
|
|
422
|
+
const o = this.initWorker({
|
|
423
|
+
name: s,
|
|
416
424
|
role: "",
|
|
417
425
|
func: e,
|
|
418
426
|
createWorker: r
|
|
419
427
|
}).getWorker;
|
|
420
|
-
|
|
421
|
-
this.terminateWorker(
|
|
422
|
-
index:
|
|
428
|
+
o.onerror = (p) => {
|
|
429
|
+
this.terminateWorker(o), f({
|
|
430
|
+
index: t,
|
|
423
431
|
workerConfigs: {
|
|
424
432
|
workerFunc: e,
|
|
425
433
|
createWorker: r,
|
|
426
|
-
workerName:
|
|
427
|
-
index:
|
|
428
|
-
data:
|
|
434
|
+
workerName: s,
|
|
435
|
+
index: t,
|
|
436
|
+
data: l
|
|
429
437
|
},
|
|
430
|
-
failedResult:
|
|
438
|
+
failedResult: p
|
|
431
439
|
});
|
|
432
|
-
},
|
|
433
|
-
var
|
|
434
|
-
if (((
|
|
435
|
-
this.terminateWorker(
|
|
436
|
-
index:
|
|
440
|
+
}, o.onmessage = (p) => {
|
|
441
|
+
var i, u;
|
|
442
|
+
if (((i = p.data) == null ? void 0 : i.ok) === !1) {
|
|
443
|
+
this.terminateWorker(o), f({
|
|
444
|
+
index: t,
|
|
437
445
|
workerConfigs: {
|
|
438
446
|
workerFunc: e,
|
|
439
447
|
createWorker: r,
|
|
440
|
-
workerName:
|
|
441
|
-
index:
|
|
442
|
-
data:
|
|
448
|
+
workerName: s,
|
|
449
|
+
index: t,
|
|
450
|
+
data: l
|
|
443
451
|
},
|
|
444
452
|
failedResult: new ErrorEvent("error", {
|
|
445
|
-
message:
|
|
453
|
+
message: p.data.error
|
|
446
454
|
})
|
|
447
455
|
});
|
|
448
456
|
return;
|
|
449
457
|
}
|
|
450
458
|
c({
|
|
451
|
-
index:
|
|
459
|
+
index: t,
|
|
452
460
|
workerConfigs: {
|
|
453
461
|
workerFunc: e,
|
|
454
462
|
createWorker: r,
|
|
455
|
-
workerName:
|
|
456
|
-
index:
|
|
457
|
-
data:
|
|
463
|
+
workerName: s,
|
|
464
|
+
index: t,
|
|
465
|
+
data: l
|
|
458
466
|
},
|
|
459
467
|
successResult: new MessageEvent("message", {
|
|
460
|
-
data: (
|
|
468
|
+
data: (u = p.data) == null ? void 0 : u.data
|
|
461
469
|
})
|
|
462
|
-
}), this.terminateWorker(
|
|
470
|
+
}), this.terminateWorker(o);
|
|
463
471
|
};
|
|
464
|
-
const
|
|
465
|
-
index:
|
|
466
|
-
...Array.isArray(
|
|
472
|
+
const d = {
|
|
473
|
+
index: t,
|
|
474
|
+
...Array.isArray(l) ? { data: l } : l
|
|
467
475
|
};
|
|
468
|
-
|
|
476
|
+
o.postMessage(d, m(d));
|
|
469
477
|
});
|
|
470
478
|
}
|
|
471
479
|
/**
|
|
@@ -503,14 +511,14 @@ class E {
|
|
|
503
511
|
async collectResults(e, r = {}) {
|
|
504
512
|
if (this._isTerminated)
|
|
505
513
|
throw new Error("MainWorkerFactory has been terminated");
|
|
506
|
-
const
|
|
507
|
-
(
|
|
508
|
-
),
|
|
509
|
-
(
|
|
510
|
-
),
|
|
514
|
+
const s = e.results.filter(
|
|
515
|
+
(a) => a.status === "fulfilled"
|
|
516
|
+
), t = e.results.filter(
|
|
517
|
+
(a) => a.status === "rejected"
|
|
518
|
+
), l = s.map((a) => a.value.successResult.data), c = r.reducer ? r.reducer.toString() : "(shards) => shards.flat()";
|
|
511
519
|
return {
|
|
512
|
-
data: await new Promise((
|
|
513
|
-
const
|
|
520
|
+
data: await new Promise((a, o) => {
|
|
521
|
+
const d = `
|
|
514
522
|
const reducer = ${c};
|
|
515
523
|
self.addEventListener('message', (event) => {
|
|
516
524
|
try {
|
|
@@ -520,16 +528,16 @@ class E {
|
|
|
520
528
|
self.postMessage({ ok: false, error: String(err) });
|
|
521
529
|
}
|
|
522
530
|
});
|
|
523
|
-
`,
|
|
524
|
-
|
|
525
|
-
this.terminateWorker(
|
|
526
|
-
},
|
|
527
|
-
this.terminateWorker(
|
|
528
|
-
},
|
|
531
|
+
`, p = new Blob([d], { type: "application/javascript" }), i = this.trackWorker(new Worker(URL.createObjectURL(p)));
|
|
532
|
+
i.onmessage = (u) => {
|
|
533
|
+
this.terminateWorker(i), u.data.ok ? a(u.data.data) : o(new Error(u.data.error));
|
|
534
|
+
}, i.onerror = (u) => {
|
|
535
|
+
this.terminateWorker(i), o(u);
|
|
536
|
+
}, i.postMessage(l);
|
|
529
537
|
}),
|
|
530
|
-
succeeded:
|
|
531
|
-
failed:
|
|
532
|
-
errors:
|
|
538
|
+
succeeded: s.length,
|
|
539
|
+
failed: t.length,
|
|
540
|
+
errors: t
|
|
533
541
|
};
|
|
534
542
|
}
|
|
535
543
|
/**
|
|
@@ -564,58 +572,66 @@ class E {
|
|
|
564
572
|
if (e.length === 0)
|
|
565
573
|
throw new Error("Pipeline requires at least one step");
|
|
566
574
|
if (e.length === 1) {
|
|
567
|
-
const r = e[0],
|
|
568
|
-
if (!
|
|
569
|
-
const
|
|
570
|
-
return new Promise((
|
|
571
|
-
|
|
572
|
-
var
|
|
573
|
-
this.terminateWorker(
|
|
574
|
-
},
|
|
575
|
-
this.terminateWorker(
|
|
575
|
+
const r = e[0], { worker: s, srcData: t, ...l } = r, c = this.findWorkerByName(r.worker);
|
|
576
|
+
if (!c) throw new Error(`Worker "${r.worker}" not found`);
|
|
577
|
+
const a = this.initWorker(c).getWorker;
|
|
578
|
+
return new Promise((o, d) => {
|
|
579
|
+
a.onmessage = (u) => {
|
|
580
|
+
var k, g;
|
|
581
|
+
this.terminateWorker(a), ((k = u.data) == null ? void 0 : k.ok) === !1 ? d(new Error(u.data.error)) : o((g = u.data) == null ? void 0 : g.data);
|
|
582
|
+
}, a.onerror = (u) => {
|
|
583
|
+
this.terminateWorker(a), d(u);
|
|
576
584
|
};
|
|
577
|
-
const
|
|
578
|
-
|
|
579
|
-
{ data: t, index: 0 },
|
|
580
|
-
k(t)
|
|
581
|
-
);
|
|
585
|
+
const i = { data: t ?? {}, ...l, index: 0 };
|
|
586
|
+
a.postMessage(i, m(i));
|
|
582
587
|
});
|
|
583
588
|
}
|
|
584
|
-
return new Promise((r,
|
|
585
|
-
const
|
|
586
|
-
for (const
|
|
587
|
-
const
|
|
588
|
-
if (!
|
|
589
|
-
|
|
589
|
+
return new Promise((r, s) => {
|
|
590
|
+
const t = [], l = [];
|
|
591
|
+
for (const i of e) {
|
|
592
|
+
const u = this.findWorkerByName(i.worker);
|
|
593
|
+
if (!u) {
|
|
594
|
+
s(new Error(`Worker "${i.worker}" not found`));
|
|
590
595
|
return;
|
|
591
596
|
}
|
|
592
|
-
const
|
|
593
|
-
mode:
|
|
594
|
-
createWorker:
|
|
595
|
-
}),
|
|
596
|
-
|
|
597
|
+
const k = new W(u.func, {
|
|
598
|
+
mode: P.Pipeline,
|
|
599
|
+
createWorker: u.createWorker
|
|
600
|
+
}), g = this.trackWorker(k.getWorker);
|
|
601
|
+
t.push(g);
|
|
597
602
|
}
|
|
598
|
-
for (let
|
|
599
|
-
|
|
600
|
-
for (let
|
|
601
|
-
const
|
|
602
|
-
|
|
603
|
-
{ __pipeline_ports__: !0, ...
|
|
604
|
-
|
|
605
|
-
)
|
|
603
|
+
for (let i = 0; i < t.length - 1; i++)
|
|
604
|
+
l.push(new MessageChannel());
|
|
605
|
+
for (let i = 0; i < t.length; i++) {
|
|
606
|
+
const { worker: u, srcData: k, ...g } = e[i], v = [], w = {};
|
|
607
|
+
if (i > 0 && (w.inputPort = l[i - 1].port1, v.push(w.inputPort)), i < t.length - 1 && (w.outputPort = l[i].port2, v.push(w.outputPort)), t[i].postMessage(
|
|
608
|
+
{ __pipeline_ports__: !0, stepParams: g, ...w },
|
|
609
|
+
v
|
|
610
|
+
), i < t.length - 1) {
|
|
611
|
+
const _ = t[i], A = t[i + 1], { worker: j, srcData: $, ...D } = e[i + 1];
|
|
612
|
+
_.onmessage = (h) => {
|
|
613
|
+
var E, T;
|
|
614
|
+
if (h.data && h.data.__pipeline_ports__) return;
|
|
615
|
+
if (((E = h.data) == null ? void 0 : E.ok) === !1) {
|
|
616
|
+
t.forEach((B) => this.terminateWorker(B)), s(new Error(h.data.error));
|
|
617
|
+
return;
|
|
618
|
+
}
|
|
619
|
+
const b = { data: ((T = h.data) == null ? void 0 : T.ok) !== void 0 ? h.data.data : h.data, ...D, index: 0 };
|
|
620
|
+
A.postMessage(b, m(b));
|
|
621
|
+
}, _.onerror = (h) => {
|
|
622
|
+
t.forEach((M) => this.terminateWorker(M)), s(h);
|
|
623
|
+
};
|
|
624
|
+
}
|
|
606
625
|
}
|
|
607
|
-
const c =
|
|
608
|
-
c.onmessage = (
|
|
609
|
-
var
|
|
610
|
-
|
|
611
|
-
}, c.onerror = (
|
|
612
|
-
|
|
626
|
+
const c = t[t.length - 1];
|
|
627
|
+
c.onmessage = (i) => {
|
|
628
|
+
var u, k;
|
|
629
|
+
t.forEach((g) => this.terminateWorker(g)), ((u = i.data) == null ? void 0 : u.ok) === !1 ? s(new Error(i.data.error)) : r((k = i.data) == null ? void 0 : k.data);
|
|
630
|
+
}, c.onerror = (i) => {
|
|
631
|
+
t.forEach((u) => this.terminateWorker(u)), s(i);
|
|
613
632
|
};
|
|
614
|
-
const
|
|
615
|
-
|
|
616
|
-
{ data: u, index: 0 },
|
|
617
|
-
k(u)
|
|
618
|
-
);
|
|
633
|
+
const { worker: f, srcData: a, ...o } = e[0], p = { data: a ?? {}, ...o, index: 0 };
|
|
634
|
+
t[0].postMessage(p, m(p));
|
|
619
635
|
});
|
|
620
636
|
}
|
|
621
637
|
/**
|
|
@@ -655,28 +671,28 @@ class E {
|
|
|
655
671
|
async runPersistent(e, r) {
|
|
656
672
|
if (this._isTerminated)
|
|
657
673
|
throw new Error("MainWorkerFactory has been terminated");
|
|
658
|
-
const
|
|
659
|
-
if (!
|
|
660
|
-
let
|
|
661
|
-
if (!
|
|
662
|
-
const
|
|
663
|
-
mode:
|
|
664
|
-
createWorker:
|
|
674
|
+
const s = this.findWorkerByName(e);
|
|
675
|
+
if (!s) throw new Error(`Worker "${e}" not found`);
|
|
676
|
+
let t = this._persistentWorkers.get(e);
|
|
677
|
+
if (!t) {
|
|
678
|
+
const l = new W(s.func, {
|
|
679
|
+
mode: P.Persistent,
|
|
680
|
+
createWorker: s.createWorker
|
|
665
681
|
});
|
|
666
|
-
|
|
682
|
+
t = this.trackWorker(l.getWorker), this._persistentWorkers.set(e, t);
|
|
667
683
|
}
|
|
668
|
-
return new Promise((
|
|
669
|
-
|
|
670
|
-
var
|
|
671
|
-
((
|
|
672
|
-
},
|
|
673
|
-
c(
|
|
684
|
+
return new Promise((l, c) => {
|
|
685
|
+
t.onmessage = (a) => {
|
|
686
|
+
var o, d;
|
|
687
|
+
((o = a.data) == null ? void 0 : o.ok) === !1 ? c(new Error(a.data.error)) : l((d = a.data) == null ? void 0 : d.data);
|
|
688
|
+
}, t.onerror = (a) => {
|
|
689
|
+
c(a);
|
|
674
690
|
};
|
|
675
|
-
const
|
|
691
|
+
const f = {
|
|
676
692
|
type: "run",
|
|
677
693
|
config: r.config
|
|
678
694
|
};
|
|
679
|
-
r.dataset !== void 0 && (
|
|
695
|
+
r.dataset !== void 0 && (f.dataset = r.dataset), t.postMessage(f, m(f));
|
|
680
696
|
});
|
|
681
697
|
}
|
|
682
698
|
/**
|
|
@@ -738,7 +754,38 @@ class E {
|
|
|
738
754
|
this.reset();
|
|
739
755
|
}
|
|
740
756
|
}
|
|
757
|
+
function V(n) {
|
|
758
|
+
if (typeof self > "u") return;
|
|
759
|
+
let e = null, r = null, s = null, t = {};
|
|
760
|
+
const l = (f, a) => {
|
|
761
|
+
self.postMessage(f, a);
|
|
762
|
+
};
|
|
763
|
+
async function c(f) {
|
|
764
|
+
try {
|
|
765
|
+
const a = typeof f == "object" && f !== null && "data" in f ? { ...t, ...f } : { data: f, ...t, index: 0 }, o = await n(a), d = { ok: !0, data: o }, p = m(o);
|
|
766
|
+
e ? e.postMessage(d, p) : l(d, p);
|
|
767
|
+
} catch (a) {
|
|
768
|
+
const o = {
|
|
769
|
+
ok: !1,
|
|
770
|
+
error: a instanceof Error ? a.message : String(a)
|
|
771
|
+
};
|
|
772
|
+
e ? e.postMessage(o) : l(o);
|
|
773
|
+
}
|
|
774
|
+
}
|
|
775
|
+
self.addEventListener("message", (f) => {
|
|
776
|
+
const a = f.data;
|
|
777
|
+
if (a && a.__pipeline_ports__) {
|
|
778
|
+
a.stepParams && (t = a.stepParams), a.outputPort && (e = a.outputPort), a.inputPort && (r = a.inputPort, r.onmessage = (o) => {
|
|
779
|
+
var d;
|
|
780
|
+
o.data && o.data.ok === !1 ? e ? e.postMessage(o.data) : l(o.data) : c({ data: (d = o.data) == null ? void 0 : d.data, ...t, index: 0 });
|
|
781
|
+
}), s !== null && (c(s), s = null);
|
|
782
|
+
return;
|
|
783
|
+
}
|
|
784
|
+
r ? s = a : c(a);
|
|
785
|
+
});
|
|
786
|
+
}
|
|
741
787
|
export {
|
|
742
|
-
|
|
743
|
-
|
|
788
|
+
U as MainWorkerFactory,
|
|
789
|
+
W as WorkerFactory,
|
|
790
|
+
V as defineWorker
|
|
744
791
|
};
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { WorkerFunction } from './main-worker-factory/types';
|
|
2
|
+
/**
|
|
3
|
+
* Defines and exports a function to run inside a native Web Worker script,
|
|
4
|
+
* providing full compatibility with `MainWorkerFactory` features including
|
|
5
|
+
* standard runs, worker-to-worker pipelines (`foreman.pipeline()`), and
|
|
6
|
+
* dataset caching (`foreman.runPersistent()`).
|
|
7
|
+
*
|
|
8
|
+
* @typeParam TParams - The type of the payload sent to the worker.
|
|
9
|
+
* @typeParam TResult - The return type of the worker function.
|
|
10
|
+
*
|
|
11
|
+
* @param workerFn - The worker execution function.
|
|
12
|
+
*
|
|
13
|
+
* @example
|
|
14
|
+
* // my-native-worker.ts
|
|
15
|
+
* import { defineWorker } from '@offmain/workerkit';
|
|
16
|
+
*
|
|
17
|
+
* export default defineWorker(async ({ data }: { data: number[] }) => {
|
|
18
|
+
* return data.map((x) => x * 2);
|
|
19
|
+
* });
|
|
20
|
+
*/
|
|
21
|
+
export declare function defineWorker<TParams = unknown, TResult = unknown>(workerFn: WorkerFunction<TParams, TResult | Promise<TResult>>): void;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -168,4 +168,6 @@ export interface PipelineStep {
|
|
|
168
168
|
worker: string;
|
|
169
169
|
/** Input data for the first step (subsequent steps receive previous output) */
|
|
170
170
|
srcData?: unknown;
|
|
171
|
+
/** Any additional step parameters, configs, or options forwarded to the worker payload. */
|
|
172
|
+
[key: string]: unknown;
|
|
171
173
|
}
|
package/package.json
CHANGED