@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/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