@angular-helpers/worker-http 0.2.0 → 0.4.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.
@@ -1,10 +1,15 @@
1
- import { Provider } from '@angular/core';
1
+ import * as i0 from '@angular/core';
2
+ import { Provider, InjectionToken, EnvironmentProviders, OnDestroy } from '@angular/core';
3
+ import { HttpContextToken, HttpBackend, HttpRequest, HttpEvent, HttpContext, HttpResponse } from '@angular/common/http';
4
+ import { WorkerSerializer } from '@angular-helpers/worker-http/serializer';
5
+ import { WorkerInterceptorSpec } from '@angular-helpers/worker-http/interceptors';
6
+ import { Observable } from 'rxjs';
2
7
 
3
8
  /**
4
9
  * Discriminated union for worker HTTP feature kinds.
5
10
  * Mirrors Angular's HttpFeatureKind pattern.
6
11
  */
7
- type WorkerHttpFeatureKind = 'WorkerConfigs' | 'WorkerRoutes' | 'WorkerFallback' | 'WorkerSerialization';
12
+ type WorkerHttpFeatureKind = 'WorkerConfigs' | 'WorkerRoutes' | 'WorkerFallback' | 'WorkerSerialization' | 'WorkerInterceptors';
8
13
  /**
9
14
  * Feature object — mirrors Angular's HttpFeature<K> shape.
10
15
  */
@@ -38,5 +43,303 @@ interface WorkerRoute {
38
43
  * Fallback strategy when workers are unavailable (SSR, old browsers).
39
44
  */
40
45
  type WorkerFallbackStrategy = 'main-thread' | 'error';
46
+ /**
47
+ * Serializable HTTP request — POJO version of Angular's HttpRequest.
48
+ * Structured-clone safe: no classes, no functions, no prototype chains.
49
+ */
50
+ interface SerializableRequest {
51
+ method: string;
52
+ url: string;
53
+ headers: Record<string, string[]>;
54
+ params: Record<string, string[]>;
55
+ body: unknown;
56
+ responseType: 'json' | 'text' | 'blob' | 'arraybuffer';
57
+ withCredentials: boolean;
58
+ context: Record<string, unknown>;
59
+ }
60
+ /**
61
+ * Serializable HTTP response — POJO version of Angular's HttpResponse.
62
+ */
63
+ interface SerializableResponse {
64
+ status: number;
65
+ statusText: string;
66
+ headers: Record<string, string[]>;
67
+ body: unknown;
68
+ url: string;
69
+ }
70
+
71
+ /**
72
+ * Per-worker interceptor specs map. Key is the worker id from
73
+ * `WorkerConfig.id`, plus the special `'*'` wildcard that applies to every
74
+ * worker. Specs from `'*'` are prepended to the worker-specific specs at
75
+ * resolve time.
76
+ */
77
+ type WorkerInterceptorSpecsMap = Readonly<Record<string, readonly WorkerInterceptorSpec[]>>;
78
+ /**
79
+ * Per-request HttpContextToken that carries the target worker ID.
80
+ *
81
+ * `null` → use URL-pattern auto-routing (or main-thread fallback if no route matches).
82
+ *
83
+ * @example
84
+ * ```typescript
85
+ * // With WorkerHttpClient (recommended)
86
+ * this.http.get('/api/data', { worker: 'secure' });
87
+ *
88
+ * // With standard HttpClient (power user)
89
+ * this.http.get('/api/data', {
90
+ * context: new HttpContext().set(WORKER_TARGET, 'secure'),
91
+ * });
92
+ * ```
93
+ */
94
+ declare const WORKER_TARGET: HttpContextToken<string>;
95
+ /**
96
+ * Optional serializer for crossing the worker boundary.
97
+ * Provided via `withWorkerSerialization()`. Defaults to `null` (structured clone).
98
+ *
99
+ * When set, `WorkerHttpBackend` serializes the request body before `postMessage`
100
+ * using this serializer. The worker-side `createWorkerPipeline()` receives the
101
+ * serialized form — add a worker interceptor to deserialize it if needed.
102
+ */
103
+ declare const WORKER_HTTP_SERIALIZER_TOKEN: InjectionToken<WorkerSerializer>;
104
+ /**
105
+ * Per-worker interceptor specs provided via `withWorkerInterceptors()`.
106
+ * Defaults to an empty map (no interceptors).
107
+ */
108
+ declare const WORKER_HTTP_INTERCEPTORS_TOKEN: InjectionToken<Readonly<Record<string, readonly WorkerInterceptorSpec[]>>>;
109
+
110
+ /**
111
+ * Sets up the worker HTTP infrastructure and replaces Angular's `HttpBackend`
112
+ * with `WorkerHttpBackend`.
113
+ *
114
+ * Drop-in companion to `provideHttpClient()`. Can be used INSTEAD of it —
115
+ * `HttpClient` and the full interceptor chain are included automatically.
116
+ *
117
+ * @example
118
+ * ```typescript
119
+ * // app.config.ts
120
+ * export const appConfig: ApplicationConfig = {
121
+ * providers: [
122
+ * provideWorkerHttpClient(
123
+ * withWorkerConfigs([
124
+ * { id: 'public', workerUrl: new URL('./workers/public.worker', import.meta.url) },
125
+ * ]),
126
+ * withWorkerRoutes([
127
+ * { pattern: /\/api\//, worker: 'public', priority: 1 },
128
+ * ]),
129
+ * withWorkerFallback('main-thread'),
130
+ * ),
131
+ * ],
132
+ * };
133
+ * ```
134
+ */
135
+ declare function provideWorkerHttpClient(...features: WorkerHttpFeature<WorkerHttpFeatureKind>[]): EnvironmentProviders;
136
+ /**
137
+ * Registers worker definitions (id + workerUrl + optional pool size).
138
+ *
139
+ * At least one config is required for any request to reach a worker.
140
+ *
141
+ * @example
142
+ * ```typescript
143
+ * withWorkerConfigs([
144
+ * { id: 'public', workerUrl: new URL('./workers/public.worker', import.meta.url) },
145
+ * { id: 'secure', workerUrl: new URL('./workers/secure.worker', import.meta.url), maxInstances: 2 },
146
+ * ])
147
+ * ```
148
+ */
149
+ declare function withWorkerConfigs(configs: WorkerConfig[]): WorkerHttpFeature<'WorkerConfigs'>;
150
+ /**
151
+ * Declares URL-pattern → worker routing rules evaluated in priority order.
152
+ *
153
+ * When a request URL matches a pattern, the associated worker handles it.
154
+ * Explicit `WORKER_TARGET` context always takes precedence over routes.
155
+ *
156
+ * @example
157
+ * ```typescript
158
+ * withWorkerRoutes([
159
+ * { pattern: /\/api\/secure\//, worker: 'secure', priority: 10 },
160
+ * { pattern: /\/api\//, worker: 'public', priority: 1 },
161
+ * ])
162
+ * ```
163
+ */
164
+ declare function withWorkerRoutes(routes: WorkerRoute[]): WorkerHttpFeature<'WorkerRoutes'>;
165
+ /**
166
+ * Sets the fallback strategy when workers are unavailable (SSR, old browsers,
167
+ * or when no route matches).
168
+ *
169
+ * - `'main-thread'` (default) — silently delegates to `FetchBackend`
170
+ * - `'error'` — throws, forcing explicit handling in the application
171
+ *
172
+ * @example
173
+ * ```typescript
174
+ * withWorkerFallback('main-thread') // SSR-safe
175
+ * ```
176
+ */
177
+ declare function withWorkerFallback(strategy: WorkerFallbackStrategy): WorkerHttpFeature<'WorkerFallback'>;
178
+ /**
179
+ * Configures a custom serializer for crossing the worker boundary.
180
+ *
181
+ * By default `WorkerHttpBackend` relies on the browser's structured clone algorithm
182
+ * (safe for plain objects, arrays, primitives, `Date`, `ArrayBuffer`).
183
+ * Use `withWorkerSerialization` when your request bodies contain types that
184
+ * structured clone cannot handle (e.g. class instances, circular references, `Map`, `Set`).
185
+ *
186
+ * **Worker-side note:** The serialized form is what the worker receives as `req.body`.
187
+ * If you use `createSerovalSerializer` or similar, add a worker-side interceptor
188
+ * to deserialize the body before calling `fetch()`.
189
+ *
190
+ * @example
191
+ * ```typescript
192
+ * import { createSerovalSerializer } from '@angular-helpers/worker-http/serializer';
193
+ *
194
+ * provideWorkerHttpClient(
195
+ * withWorkerConfigs([...]),
196
+ * withWorkerSerialization(createSerovalSerializer()),
197
+ * )
198
+ * ```
199
+ */
200
+ declare function withWorkerSerialization(serializer: WorkerSerializer): WorkerHttpFeature<'WorkerSerialization'>;
201
+ /**
202
+ * Configures the worker-side interceptor pipeline from Angular DI.
203
+ *
204
+ * Specs are forwarded to each worker via an `init-interceptors` handshake
205
+ * message posted before any HTTP request. Workers must call
206
+ * `createConfigurableWorkerPipeline()` to receive and act on the handshake.
207
+ *
208
+ * Two shapes are accepted:
209
+ * - `WorkerInterceptorSpec[]` — applied to every registered worker
210
+ * - `Record<workerId, WorkerInterceptorSpec[]>` — per-worker, with the
211
+ * special `'*'` key applied to all workers in addition to the
212
+ * worker-specific specs
213
+ *
214
+ * @example
215
+ * ```typescript
216
+ * provideWorkerHttpClient(
217
+ * withWorkerConfigs([{ id: 'api', workerUrl: ... }]),
218
+ * withWorkerInterceptors([
219
+ * workerLogging(),
220
+ * workerRetry({ maxRetries: 3 }),
221
+ * workerCache({ ttl: 30_000 }),
222
+ * ]),
223
+ * );
224
+ * ```
225
+ *
226
+ * @example Per-worker specs
227
+ * ```typescript
228
+ * withWorkerInterceptors({
229
+ * '*': [workerLogging()],
230
+ * 'secure': [workerHmacSigning({ keyMaterial })],
231
+ * });
232
+ * ```
233
+ */
234
+ declare function withWorkerInterceptors(specs: readonly WorkerInterceptorSpec[] | WorkerInterceptorSpecsMap): WorkerHttpFeature<'WorkerInterceptors'>;
235
+
236
+ /**
237
+ * Angular `HttpBackend` replacement that routes HTTP requests to web workers.
238
+ *
239
+ * Registered via `provideWorkerHttpClient()`. Not meant to be used directly.
240
+ *
241
+ * Flow per request:
242
+ * 1. Check SSR: if `Worker` is undefined → fallback strategy
243
+ * 2. Resolve target worker ID from `WORKER_TARGET` context or URL-pattern routing
244
+ * 3. Serialize `HttpRequest` → `SerializableRequest` (structured-clone safe)
245
+ * 4. Dispatch to the worker's `WorkerTransport`
246
+ * 5. Deserialize `SerializableResponse` → `HttpResponse`
247
+ */
248
+ declare class WorkerHttpBackend extends HttpBackend implements OnDestroy {
249
+ private readonly configs;
250
+ private readonly routes;
251
+ private readonly fallback;
252
+ private readonly serializer;
253
+ private readonly interceptorSpecs;
254
+ private readonly fetchBackend;
255
+ private readonly transports;
256
+ handle(req: HttpRequest<unknown>): Observable<HttpEvent<unknown>>;
257
+ ngOnDestroy(): void;
258
+ private getOrCreateTransport;
259
+ private resolveSpecsFor;
260
+ private handleFallback;
261
+ static ɵfac: i0.ɵɵFactoryDeclaration<WorkerHttpBackend, never>;
262
+ static ɵprov: i0.ɵɵInjectableDeclaration<WorkerHttpBackend>;
263
+ }
264
+
265
+ /**
266
+ * Options accepted by `WorkerHttpClient` methods.
267
+ * Identical to `HttpClient` options with an optional `worker` field added.
268
+ */
269
+ interface WorkerRequestOptions {
270
+ /** Target worker ID. Overrides URL-pattern routing for this specific request. */
271
+ worker?: string | null;
272
+ context?: HttpContext;
273
+ headers?: Record<string, string | string[]>;
274
+ params?: Record<string, string | number | boolean | ReadonlyArray<string | number | boolean>>;
275
+ responseType?: 'json';
276
+ withCredentials?: boolean;
277
+ observe?: 'body';
278
+ reportProgress?: boolean;
279
+ transferCache?: {
280
+ includeHeaders?: string[];
281
+ } | boolean;
282
+ }
283
+ /**
284
+ * Convenience wrapper over `HttpClient` that adds an optional `{ worker }` field
285
+ * to every method. Under the hood it sets `WORKER_TARGET` on the `HttpContext` —
286
+ * the caller never has to touch the context manually.
287
+ *
288
+ * Usage is identical to `HttpClient` — just inject `WorkerHttpClient` instead.
289
+ *
290
+ * @example
291
+ * ```typescript
292
+ * @Injectable({ providedIn: 'root' })
293
+ * export class DataService {
294
+ * private readonly http = inject(WorkerHttpClient);
295
+ *
296
+ * getUsers(): Observable<User[]> {
297
+ * return this.http.get<User[]>('/api/users'); // auto-routed by URL pattern
298
+ * }
299
+ *
300
+ * getSensitiveReport(): Observable<Report> {
301
+ * return this.http.get<Report>('/api/secure/reports', { worker: 'secure' });
302
+ * }
303
+ * }
304
+ * ```
305
+ */
306
+ declare class WorkerHttpClient {
307
+ private readonly http;
308
+ get<T>(url: string, options?: WorkerRequestOptions): Observable<T>;
309
+ post<T>(url: string, body: unknown, options?: WorkerRequestOptions): Observable<T>;
310
+ put<T>(url: string, body: unknown, options?: WorkerRequestOptions): Observable<T>;
311
+ patch<T>(url: string, body: unknown, options?: WorkerRequestOptions): Observable<T>;
312
+ delete<T>(url: string, options?: WorkerRequestOptions): Observable<T>;
313
+ head<T>(url: string, options?: WorkerRequestOptions): Observable<T>;
314
+ private withWorker;
315
+ static ɵfac: i0.ɵɵFactoryDeclaration<WorkerHttpClient, never>;
316
+ static ɵprov: i0.ɵɵInjectableDeclaration<WorkerHttpClient>;
317
+ }
318
+
319
+ /**
320
+ * Converts an Angular `HttpRequest` into a structured-clone-safe POJO
321
+ * that can be sent to a web worker via `postMessage`.
322
+ *
323
+ * Notes:
324
+ * - `urlWithParams` is used so query params embedded via `HttpParams` are included.
325
+ * - The `context` field is intentionally left empty: `HttpContext` uses class references
326
+ * as keys which cannot cross the worker boundary.
327
+ */
328
+ declare function toSerializableRequest(req: HttpRequest<unknown>): SerializableRequest;
329
+ /**
330
+ * Converts a worker `SerializableResponse` back into an Angular `HttpResponse`.
331
+ */
332
+ declare function toHttpResponse(res: SerializableResponse, req: HttpRequest<unknown>): HttpResponse<unknown>;
333
+ /**
334
+ * Matches a URL against a sorted list of `WorkerRoute` rules.
335
+ * Rules with higher `priority` are evaluated first.
336
+ * Returns the matched worker ID or `null` if no rule matches.
337
+ */
338
+ declare function matchWorkerRoute(url: string, routes: Array<{
339
+ pattern: RegExp | string;
340
+ worker: string;
341
+ priority?: number;
342
+ }>): string | null;
41
343
 
42
- export type { WorkerConfig, WorkerFallbackStrategy, WorkerHttpFeature, WorkerHttpFeatureKind, WorkerRoute };
344
+ export { WORKER_HTTP_INTERCEPTORS_TOKEN, WORKER_HTTP_SERIALIZER_TOKEN, WORKER_TARGET, WorkerHttpBackend, WorkerHttpClient, matchWorkerRoute, provideWorkerHttpClient, toHttpResponse, toSerializableRequest, withWorkerConfigs, withWorkerFallback, withWorkerInterceptors, withWorkerRoutes, withWorkerSerialization };
345
+ export type { SerializableRequest, SerializableResponse, WorkerConfig, WorkerFallbackStrategy, WorkerHttpFeature, WorkerHttpFeatureKind, WorkerInterceptorSpecsMap, WorkerRequestOptions, WorkerRoute };
@@ -109,17 +109,120 @@ interface ContentIntegrityConfig {
109
109
  * runs them through the interceptor chain, executes `fetch()`,
110
110
  * and sends the response back.
111
111
  *
112
+ * For a runtime-configurable variant whose chain is built from specs sent
113
+ * from the main thread, use `createConfigurableWorkerPipeline()` instead.
114
+ *
112
115
  * @example
113
116
  * ```typescript
114
117
  * // workers/secure.worker.ts
115
- * import { createWorkerPipeline } from '@angular-helpers/worker-http/interceptors';
116
- * import { hmacSigningInterceptor } from './my-interceptors';
118
+ * import { createWorkerPipeline, hmacSigningInterceptor } from '@angular-helpers/worker-http/interceptors';
117
119
  *
118
- * createWorkerPipeline([hmacSigningInterceptor]);
120
+ * createWorkerPipeline([hmacSigningInterceptor({ keyMaterial })]);
119
121
  * ```
120
122
  */
121
123
  declare function createWorkerPipeline(interceptors: WorkerInterceptorFn[]): void;
122
124
 
125
+ /**
126
+ * Serializable subset of LoggingConfig — `logger` is a function and cannot
127
+ * cross the worker boundary, so it is dropped here. The configurable pipeline
128
+ * uses `console.log` inside the worker for built-in logging.
129
+ */
130
+ type SerializableLoggingConfig = Omit<LoggingConfig, 'logger'>;
131
+ /**
132
+ * Serializable subset of HmacInterceptorConfig — `payloadBuilder` is a function
133
+ * and cannot cross the worker boundary. The default payload builder is used.
134
+ *
135
+ * `keyMaterial` is `ArrayBuffer | Uint8Array`, both of which ARE supported by
136
+ * the structured clone algorithm.
137
+ */
138
+ type SerializableHmacConfig = Omit<HmacInterceptorConfig, 'payloadBuilder'>;
139
+ /**
140
+ * Discriminated union of interceptor specifications that can be configured
141
+ * from Angular DI via `withWorkerInterceptors([...])` and forwarded to the
142
+ * worker over `postMessage`.
143
+ *
144
+ * For interceptors with custom function fields (loggers, payload builders),
145
+ * register the interceptor in the worker file via `registerInterceptor()` and
146
+ * reference it here with `kind: 'custom'`.
147
+ */
148
+ type WorkerInterceptorSpec = {
149
+ readonly kind: 'logging';
150
+ readonly config?: SerializableLoggingConfig;
151
+ } | {
152
+ readonly kind: 'retry';
153
+ readonly config?: RetryConfig;
154
+ } | {
155
+ readonly kind: 'cache';
156
+ readonly config?: CacheConfig;
157
+ } | {
158
+ readonly kind: 'hmac-signing';
159
+ readonly config: SerializableHmacConfig;
160
+ } | {
161
+ readonly kind: 'rate-limit';
162
+ readonly config?: RateLimitConfig;
163
+ } | {
164
+ readonly kind: 'content-integrity';
165
+ readonly config?: ContentIntegrityConfig;
166
+ } | {
167
+ readonly kind: 'custom';
168
+ readonly name: string;
169
+ readonly config?: unknown;
170
+ };
171
+ /**
172
+ * Wire format for the init handshake message sent from the main thread to the
173
+ * worker. Posted exactly once per worker, before any HTTP request.
174
+ */
175
+ interface WorkerInterceptorInitMessage {
176
+ readonly type: 'init-interceptors';
177
+ readonly specs: readonly WorkerInterceptorSpec[];
178
+ }
179
+
180
+ type CustomFactory = (config?: unknown) => WorkerInterceptorFn;
181
+ /**
182
+ * Registers a custom interceptor factory that can be referenced from
183
+ * `withWorkerInterceptors([workerCustom('my-name', config)])`.
184
+ *
185
+ * Must be called inside the worker file BEFORE `createConfigurableWorkerPipeline()`.
186
+ *
187
+ * @example
188
+ * ```typescript
189
+ * // app.worker.ts
190
+ * import { createConfigurableWorkerPipeline, registerInterceptor } from '@angular-helpers/worker-http/interceptors';
191
+ *
192
+ * registerInterceptor('auth-token', (config: { token: string }) => async (req, next) => {
193
+ * const headers = { ...req.headers, authorization: [`Bearer ${config.token}`] };
194
+ * return next({ ...req, headers });
195
+ * });
196
+ *
197
+ * createConfigurableWorkerPipeline();
198
+ * ```
199
+ */
200
+ declare function registerInterceptor(name: string, factory: CustomFactory): void;
201
+ /**
202
+ * Resolves a single spec to its concrete `WorkerInterceptorFn`.
203
+ *
204
+ * Exported for test use. Throws on unknown `kind` or unregistered custom name
205
+ * so misconfiguration fails loudly at init time, not on the first request.
206
+ */
207
+ declare function resolveSpec(spec: WorkerInterceptorSpec): WorkerInterceptorFn;
208
+ /**
209
+ * Creates a worker-side pipeline whose interceptor chain is supplied at
210
+ * runtime via the init handshake message sent by `WorkerHttpBackend`.
211
+ *
212
+ * Behavior:
213
+ * - Listens for the first `init-interceptors` message and builds the chain
214
+ * from the received specs.
215
+ * - Until init arrives, incoming `request` messages are buffered (they will
216
+ * be flushed once the chain is ready).
217
+ * - If no init arrives (e.g. worker used standalone without
218
+ * `withWorkerInterceptors`), the pipeline runs with an empty chain so
219
+ * every request goes straight to `fetch()`.
220
+ *
221
+ * Custom interceptor factories must be registered with
222
+ * `registerInterceptor(name, factory)` before this call.
223
+ */
224
+ declare function createConfigurableWorkerPipeline(): void;
225
+
123
226
  /**
124
227
  * Creates a retry interceptor with exponential backoff.
125
228
  *
@@ -240,5 +343,24 @@ declare function contentIntegrityInterceptor(config?: ContentIntegrityConfig): W
240
343
  */
241
344
  declare function composeInterceptors(...fns: WorkerInterceptorFn[]): WorkerInterceptorFn;
242
345
 
243
- export { cacheInterceptor, composeInterceptors, contentIntegrityInterceptor, createWorkerPipeline, hmacSigningInterceptor, loggingInterceptor, rateLimitInterceptor, retryInterceptor };
244
- export type { CacheConfig, ContentIntegrityConfig, HmacInterceptorConfig, LoggingConfig, RateLimitConfig, RetryConfig, SerializableRequest, SerializableResponse, WorkerInterceptorFn };
346
+ /**
347
+ * Spec builders pure factories that return POJO `WorkerInterceptorSpec`
348
+ * objects suitable for `withWorkerInterceptors([...])`.
349
+ *
350
+ * Each builder mirrors the corresponding worker-side interceptor factory but
351
+ * accepts only serializable config (no function fields).
352
+ */
353
+ declare function workerLogging(config?: SerializableLoggingConfig): WorkerInterceptorSpec;
354
+ declare function workerRetry(config?: RetryConfig): WorkerInterceptorSpec;
355
+ declare function workerCache(config?: CacheConfig): WorkerInterceptorSpec;
356
+ declare function workerHmacSigning(config: SerializableHmacConfig): WorkerInterceptorSpec;
357
+ declare function workerRateLimit(config?: RateLimitConfig): WorkerInterceptorSpec;
358
+ declare function workerContentIntegrity(config?: ContentIntegrityConfig): WorkerInterceptorSpec;
359
+ /**
360
+ * Reference a custom interceptor that has been registered on the worker side
361
+ * via `registerInterceptor(name, factory)`.
362
+ */
363
+ declare function workerCustom(name: string, config?: unknown): WorkerInterceptorSpec;
364
+
365
+ export { cacheInterceptor, composeInterceptors, contentIntegrityInterceptor, createConfigurableWorkerPipeline, createWorkerPipeline, hmacSigningInterceptor, loggingInterceptor, rateLimitInterceptor, registerInterceptor, resolveSpec, retryInterceptor, workerCache, workerContentIntegrity, workerCustom, workerHmacSigning, workerLogging, workerRateLimit, workerRetry };
366
+ export type { CacheConfig, ContentIntegrityConfig, HmacInterceptorConfig, LoggingConfig, RateLimitConfig, RetryConfig, SerializableHmacConfig, SerializableLoggingConfig, SerializableRequest, SerializableResponse, WorkerInterceptorFn, WorkerInterceptorInitMessage, WorkerInterceptorSpec };
@@ -38,6 +38,18 @@ interface WorkerTransportConfig {
38
38
  transferDetection?: 'auto' | 'manual' | 'none';
39
39
  /** Timeout in ms for a single request (default: 30000) */
40
40
  requestTimeout?: number;
41
+ /**
42
+ * Optional handshake message posted to every worker as soon as it is
43
+ * created, BEFORE any request. Useful to ship runtime configuration
44
+ * (e.g. interceptor specs) that the worker uses to build its pipeline.
45
+ *
46
+ * The shape is opaque to the transport — the worker is responsible for
47
+ * recognising and acting on it.
48
+ */
49
+ initMessage?: {
50
+ type: string;
51
+ [key: string]: unknown;
52
+ };
41
53
  }
42
54
  /**
43
55
  * Message sent from main thread to worker.