@fest-lib/uniform 0.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/LICENSE +674 -0
- package/README.md +384 -0
- package/dist/cbor-x-DhdMOAu4.js +1196 -0
- package/dist/uniform.js +8526 -0
- package/package.json +78 -0
package/README.md
ADDED
|
@@ -0,0 +1,384 @@
|
|
|
1
|
+
# Fest/Uniform - Advanced Web Worker Communication Library
|
|
2
|
+
|
|
3
|
+
**Fest/Uniform** is an experimental web worker communication library that provides seamless, inline-like function calls across worker boundaries using advanced reflection and proxy techniques.
|
|
4
|
+
|
|
5
|
+
## Features
|
|
6
|
+
|
|
7
|
+
- **Seamless API**: Call worker functions as if they were local
|
|
8
|
+
- **Automatic Serialization**: Handles complex data types and transferables
|
|
9
|
+
- **Optimized Protocol**: Batching, timeouts, and error recovery
|
|
10
|
+
- **Type Safety**: Full TypeScript support with reflection
|
|
11
|
+
- **Performance**: Efficient message passing with minimal overhead
|
|
12
|
+
|
|
13
|
+
## Quick Start
|
|
14
|
+
|
|
15
|
+
### Basic Usage
|
|
16
|
+
|
|
17
|
+
```typescript
|
|
18
|
+
import { createWorkerChannel } from 'fest/uniform';
|
|
19
|
+
|
|
20
|
+
// Create a worker channel
|
|
21
|
+
const worker = await createWorkerChannel({
|
|
22
|
+
name: 'my-worker',
|
|
23
|
+
script: './my-worker.uniform.worker.ts'
|
|
24
|
+
});
|
|
25
|
+
|
|
26
|
+
// Call worker functions seamlessly
|
|
27
|
+
const result = await worker.request('processData', { data: 'hello' });
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
### Queued Channels (Recommended)
|
|
31
|
+
|
|
32
|
+
```typescript
|
|
33
|
+
import { createQueuedWorkerChannel } from 'fest/uniform';
|
|
34
|
+
|
|
35
|
+
// Create queued channel - operations queue until worker is ready
|
|
36
|
+
const worker = new QueuedWorkerChannel({
|
|
37
|
+
name: 'my-worker',
|
|
38
|
+
script: './my-worker.uniform.worker.ts'
|
|
39
|
+
}, (channel) => {
|
|
40
|
+
console.log('Worker channel ready!');
|
|
41
|
+
});
|
|
42
|
+
|
|
43
|
+
// Operations will queue until the channel connects
|
|
44
|
+
const result = await worker.request('processData', { data: 'hello' });
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
### Optimized Protocol
|
|
48
|
+
|
|
49
|
+
```typescript
|
|
50
|
+
import { createOptimizedWorkerChannel } from 'fest/uniform';
|
|
51
|
+
|
|
52
|
+
// Create optimized channel with advanced features
|
|
53
|
+
const worker = await createOptimizedWorkerChannel({
|
|
54
|
+
name: 'my-worker',
|
|
55
|
+
script: './my-worker.uniform.worker.ts'
|
|
56
|
+
}, {
|
|
57
|
+
timeout: 10000,
|
|
58
|
+
retries: 3,
|
|
59
|
+
batching: true,
|
|
60
|
+
compression: false
|
|
61
|
+
});
|
|
62
|
+
|
|
63
|
+
// Request with automatic batching and retry
|
|
64
|
+
const result = await worker.request('processData', { data: 'hello' });
|
|
65
|
+
|
|
66
|
+
// Fire-and-forget notifications
|
|
67
|
+
worker.notify('logMessage', 'Processing complete');
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
### Queued Optimized Channels
|
|
71
|
+
|
|
72
|
+
```typescript
|
|
73
|
+
import { createQueuedOptimizedWorkerChannel } from 'fest/uniform';
|
|
74
|
+
|
|
75
|
+
// Best of both worlds: queuing + optimization
|
|
76
|
+
const worker = createQueuedOptimizedWorkerChannel({
|
|
77
|
+
name: 'my-worker',
|
|
78
|
+
script: './my-worker.uniform.worker.ts'
|
|
79
|
+
}, {
|
|
80
|
+
timeout: 10000,
|
|
81
|
+
retries: 3,
|
|
82
|
+
batching: true
|
|
83
|
+
}, (channel) => {
|
|
84
|
+
console.log('Optimized worker channel ready!');
|
|
85
|
+
});
|
|
86
|
+
|
|
87
|
+
// Operations queue until ready, then use optimized protocol
|
|
88
|
+
const result = await worker.request('processData', { data: 'hello' });
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
### Context-Specific Usage
|
|
92
|
+
|
|
93
|
+
#### Service Worker Context
|
|
94
|
+
```typescript
|
|
95
|
+
import { detectExecutionContext, createServiceWorkerChannel } from 'fest/uniform';
|
|
96
|
+
|
|
97
|
+
if (detectExecutionContext() === 'service-worker') {
|
|
98
|
+
// In service worker, use BroadcastChannel communication
|
|
99
|
+
const channel = await createServiceWorkerChannel({
|
|
100
|
+
name: 'sw-cache-worker',
|
|
101
|
+
script: './cache-worker.js'
|
|
102
|
+
});
|
|
103
|
+
|
|
104
|
+
// Communicate through BroadcastChannel
|
|
105
|
+
const result = await channel.request('cacheData', { data: 'important' });
|
|
106
|
+
}
|
|
107
|
+
```
|
|
108
|
+
|
|
109
|
+
#### Chrome Extension Context
|
|
110
|
+
```typescript
|
|
111
|
+
import { createChromeExtensionChannel } from 'fest/uniform';
|
|
112
|
+
|
|
113
|
+
const worker = await createChromeExtensionChannel({
|
|
114
|
+
name: 'extension-worker',
|
|
115
|
+
script: 'workers/processor.js' // Will be resolved with chrome.runtime.getURL()
|
|
116
|
+
});
|
|
117
|
+
|
|
118
|
+
// Automatic extension URL resolution
|
|
119
|
+
const result = await worker.request('processExtensionData', data);
|
|
120
|
+
```
|
|
121
|
+
|
|
122
|
+
## Worker Implementation
|
|
123
|
+
|
|
124
|
+
### Basic Worker
|
|
125
|
+
|
|
126
|
+
```typescript
|
|
127
|
+
// my-worker.uniform.worker.ts
|
|
128
|
+
import { registerWorkerAPI } from 'fest/uniform';
|
|
129
|
+
|
|
130
|
+
const workerAPI = {
|
|
131
|
+
async processData(payload: { data: string }) {
|
|
132
|
+
// Process the data
|
|
133
|
+
return payload.data.toUpperCase();
|
|
134
|
+
},
|
|
135
|
+
|
|
136
|
+
async logMessage(message: string) {
|
|
137
|
+
console.log('[Worker]', message);
|
|
138
|
+
}
|
|
139
|
+
};
|
|
140
|
+
|
|
141
|
+
registerWorkerAPI(workerAPI);
|
|
142
|
+
```
|
|
143
|
+
|
|
144
|
+
### Advanced Worker with Optimized Protocol
|
|
145
|
+
|
|
146
|
+
```typescript
|
|
147
|
+
// my-worker.uniform.worker.ts
|
|
148
|
+
import { registerWorkerAPI } from 'fest/uniform';
|
|
149
|
+
import { MessageEnvelope } from 'fest/uniform/src/optimized-protocol';
|
|
150
|
+
|
|
151
|
+
const workerAPI = {
|
|
152
|
+
async processData(payload: { data: string }) {
|
|
153
|
+
return payload.data.toUpperCase();
|
|
154
|
+
}
|
|
155
|
+
};
|
|
156
|
+
|
|
157
|
+
// Handle optimized protocol messages
|
|
158
|
+
const processMessage = async (envelope: MessageEnvelope) => {
|
|
159
|
+
if (envelope.type === 'batch') {
|
|
160
|
+
const results = [];
|
|
161
|
+
for (const msg of envelope.payload) {
|
|
162
|
+
results.push(await processSingleMessage(msg));
|
|
163
|
+
}
|
|
164
|
+
return results;
|
|
165
|
+
}
|
|
166
|
+
return await processSingleMessage(envelope);
|
|
167
|
+
};
|
|
168
|
+
|
|
169
|
+
const processSingleMessage = async (envelope: MessageEnvelope) => {
|
|
170
|
+
const handler = workerAPI[envelope.type as keyof typeof workerAPI];
|
|
171
|
+
if (!handler) {
|
|
172
|
+
throw new Error(`Unknown message type: ${envelope.type}`);
|
|
173
|
+
}
|
|
174
|
+
return await handler(envelope.payload);
|
|
175
|
+
};
|
|
176
|
+
|
|
177
|
+
// Register API and message processor
|
|
178
|
+
registerWorkerAPI(workerAPI);
|
|
179
|
+
(globalThis as any).processMessage = processMessage;
|
|
180
|
+
```
|
|
181
|
+
|
|
182
|
+
## API Reference
|
|
183
|
+
|
|
184
|
+
### Core Functions
|
|
185
|
+
|
|
186
|
+
#### `createWorkerChannel(config: WorkerConfig): Promise<WorkerChannel>`
|
|
187
|
+
|
|
188
|
+
Creates a basic worker channel.
|
|
189
|
+
|
|
190
|
+
**Parameters:**
|
|
191
|
+
- `config.name`: Unique channel name
|
|
192
|
+
- `config.script`: Path to worker script
|
|
193
|
+
- `config.options`: Worker options
|
|
194
|
+
|
|
195
|
+
#### `createOptimizedWorkerChannel(config: WorkerConfig, options?: ProtocolOptions): Promise<OptimizedWorkerChannel>`
|
|
196
|
+
|
|
197
|
+
Creates an optimized worker channel with advanced features.
|
|
198
|
+
|
|
199
|
+
**Protocol Options:**
|
|
200
|
+
- `timeout`: Request timeout in milliseconds (default: 30000)
|
|
201
|
+
- `retries`: Number of retry attempts (default: 3)
|
|
202
|
+
- `batching`: Enable message batching (default: true)
|
|
203
|
+
- `compression`: Enable payload compression (default: false)
|
|
204
|
+
|
|
205
|
+
### WorkerChannel Methods
|
|
206
|
+
|
|
207
|
+
#### `request(method: string, args: any[]): Promise<any>`
|
|
208
|
+
|
|
209
|
+
Call a worker method and wait for response.
|
|
210
|
+
|
|
211
|
+
#### `close(): void`
|
|
212
|
+
|
|
213
|
+
Close the worker channel.
|
|
214
|
+
|
|
215
|
+
### OptimizedWorkerChannel Methods
|
|
216
|
+
|
|
217
|
+
#### `request(type: string, payload: any, options?: Partial<ProtocolOptions>): Promise<any>`
|
|
218
|
+
|
|
219
|
+
Send request with optimization features.
|
|
220
|
+
|
|
221
|
+
#### `notify(type: string, payload: any): void`
|
|
222
|
+
|
|
223
|
+
Send fire-and-forget message.
|
|
224
|
+
|
|
225
|
+
#### `stream(type: string, data: any[]): AsyncGenerator<any>`
|
|
226
|
+
|
|
227
|
+
Stream data with backpressure handling.
|
|
228
|
+
|
|
229
|
+
## Advanced Features
|
|
230
|
+
|
|
231
|
+
### Message Batching
|
|
232
|
+
|
|
233
|
+
Automatically batches multiple messages to reduce overhead:
|
|
234
|
+
|
|
235
|
+
```typescript
|
|
236
|
+
const worker = await createOptimizedWorkerChannel(config, { batching: true });
|
|
237
|
+
|
|
238
|
+
// These calls will be batched automatically
|
|
239
|
+
await Promise.all([
|
|
240
|
+
worker.request('method1', data1),
|
|
241
|
+
worker.request('method2', data2),
|
|
242
|
+
worker.request('method3', data3)
|
|
243
|
+
]);
|
|
244
|
+
```
|
|
245
|
+
|
|
246
|
+
### Error Handling and Retries
|
|
247
|
+
|
|
248
|
+
```typescript
|
|
249
|
+
const worker = await createOptimizedWorkerChannel(config, {
|
|
250
|
+
retries: 3,
|
|
251
|
+
timeout: 5000
|
|
252
|
+
});
|
|
253
|
+
|
|
254
|
+
try {
|
|
255
|
+
const result = await worker.request('unreliableMethod', data);
|
|
256
|
+
} catch (error) {
|
|
257
|
+
console.error('All retries failed:', error);
|
|
258
|
+
}
|
|
259
|
+
```
|
|
260
|
+
|
|
261
|
+
### Streaming Data
|
|
262
|
+
|
|
263
|
+
```typescript
|
|
264
|
+
const worker = await createOptimizedWorkerChannel(config);
|
|
265
|
+
|
|
266
|
+
// Stream large datasets
|
|
267
|
+
for await (const result of worker.stream('processChunk', largeDataArray)) {
|
|
268
|
+
console.log('Processed chunk:', result);
|
|
269
|
+
}
|
|
270
|
+
```
|
|
271
|
+
|
|
272
|
+
## Integration Examples
|
|
273
|
+
|
|
274
|
+
### OPFS Worker (Real Example)
|
|
275
|
+
|
|
276
|
+
```typescript
|
|
277
|
+
// From fest/lure OPFS implementation
|
|
278
|
+
import { createOptimizedWorkerChannel } from 'fest/uniform';
|
|
279
|
+
|
|
280
|
+
const workerChannel = await createOptimizedWorkerChannel({
|
|
281
|
+
name: "opfs-worker",
|
|
282
|
+
script: "./OPFS.uniform.worker.ts"
|
|
283
|
+
}, {
|
|
284
|
+
timeout: 10000,
|
|
285
|
+
batching: true
|
|
286
|
+
});
|
|
287
|
+
|
|
288
|
+
// Use like a regular function call
|
|
289
|
+
const result = await workerChannel.request('readFile', {
|
|
290
|
+
rootId: 'user',
|
|
291
|
+
path: '/data.json'
|
|
292
|
+
});
|
|
293
|
+
```
|
|
294
|
+
|
|
295
|
+
## Performance Benefits
|
|
296
|
+
|
|
297
|
+
- **Reduced Latency**: Message batching minimizes round trips
|
|
298
|
+
- **Better Throughput**: Optimized serialization and transfer handling
|
|
299
|
+
- **Automatic Retry**: Built-in error recovery
|
|
300
|
+
- **Memory Efficient**: Proper transferable object handling
|
|
301
|
+
- **Type Safe**: Full TypeScript support across worker boundaries
|
|
302
|
+
|
|
303
|
+
## Migration from postMessage
|
|
304
|
+
|
|
305
|
+
### Before (Traditional)
|
|
306
|
+
|
|
307
|
+
```typescript
|
|
308
|
+
const worker = new Worker('./worker.js');
|
|
309
|
+
|
|
310
|
+
worker.postMessage({ type: 'process', data });
|
|
311
|
+
|
|
312
|
+
worker.onmessage = (e) => {
|
|
313
|
+
const { result, error } = e.data;
|
|
314
|
+
if (error) handleError(error);
|
|
315
|
+
else handleResult(result);
|
|
316
|
+
};
|
|
317
|
+
```
|
|
318
|
+
|
|
319
|
+
### After (Uniform)
|
|
320
|
+
|
|
321
|
+
```typescript
|
|
322
|
+
const worker = await createWorkerChannel({
|
|
323
|
+
name: 'my-worker',
|
|
324
|
+
script: './worker.uniform.worker.ts'
|
|
325
|
+
});
|
|
326
|
+
|
|
327
|
+
try {
|
|
328
|
+
const result = await worker.request('process', data);
|
|
329
|
+
handleResult(result);
|
|
330
|
+
} catch (error) {
|
|
331
|
+
handleError(error);
|
|
332
|
+
}
|
|
333
|
+
```
|
|
334
|
+
|
|
335
|
+
## Execution Context Support
|
|
336
|
+
|
|
337
|
+
Fest/Uniform automatically adapts to different JavaScript execution contexts:
|
|
338
|
+
|
|
339
|
+
### Main Thread Context
|
|
340
|
+
- Full dedicated worker support
|
|
341
|
+
- MessageChannel communication
|
|
342
|
+
- All optimization features available
|
|
343
|
+
|
|
344
|
+
### Service Worker Context
|
|
345
|
+
- BroadcastChannel-based communication
|
|
346
|
+
- No dedicated worker creation (not supported)
|
|
347
|
+
- Queued operations with fallback handling
|
|
348
|
+
|
|
349
|
+
### Chrome Extension Context
|
|
350
|
+
- Dedicated worker support with extension URL resolution
|
|
351
|
+
- Automatic detection of extension environment
|
|
352
|
+
- Fallback communication patterns
|
|
353
|
+
|
|
354
|
+
### Context Detection
|
|
355
|
+
```typescript
|
|
356
|
+
import { detectExecutionContext, supportsDedicatedWorkers } from 'fest/uniform';
|
|
357
|
+
|
|
358
|
+
const context = detectExecutionContext(); // 'main' | 'service-worker' | 'chrome-extension' | 'unknown'
|
|
359
|
+
const hasWorkers = supportsDedicatedWorkers(); // boolean
|
|
360
|
+
```
|
|
361
|
+
|
|
362
|
+
## Browser Support
|
|
363
|
+
|
|
364
|
+
Requires modern browsers with:
|
|
365
|
+
- ES2020 modules
|
|
366
|
+
- MessageChannel API (main thread)
|
|
367
|
+
- BroadcastChannel API (service workers)
|
|
368
|
+
- Proxy API
|
|
369
|
+
- WeakRef (optional)
|
|
370
|
+
|
|
371
|
+
Compatible with all Chromium-based browsers and modern Firefox/Safari.
|
|
372
|
+
|
|
373
|
+
## Examples
|
|
374
|
+
|
|
375
|
+
- [Service Worker Integration](./examples/service-worker-integration.ts) - Using uniform channels in service worker context
|
|
376
|
+
- [Chrome Extension Integration](./examples/chrome-extension-integration.ts) - Chrome extension worker communication
|
|
377
|
+
|
|
378
|
+
## Contributing
|
|
379
|
+
|
|
380
|
+
This library is experimental and evolving. Contributions welcome!
|
|
381
|
+
|
|
382
|
+
## License
|
|
383
|
+
|
|
384
|
+
MIT License
|