# `bridge` _(no submodules)_ ## Purpose This module ties `marshal-request`, `marshal-response`, and `streaming` together into the two halves of a working Fetch-`Request`-to-`Response` bridge over a single `MessagePort`. `createMainBridge` hands back a `dispatch(Request) → Promise` function that worker-isolated plugins consume; `createWorkerBridge` runs inside the worker and routes incoming envelopes to a user-supplied handler. ## Features - Single bridge dispatch RPC method (`http.dispatch`); the main-side listener correlates responses by `id` so multiple in-flight requests multiplex over one port. - Optional request- and response-body streaming when `inlineBodyLimit` is set to `0`, threading through the `streaming` module. - Worker-side error rethrows are forwarded via `errorToEnvelope`, so the main side observes the original `SuaveplanError.code` chain. - `close()` on either side drops pending calls with a deterministic `ROUTER_BRIDGE.STREAM_INTERRUPTED` error rather than hanging. - Strict envelope validation on both ends — a malformed payload fails with `ROUTER_BRIDGE.MARSHAL_FAILED` or `RESPONSE_INVALID`. ## Usage: Basic ```ts import { createMainBridge, createWorkerBridge, } from "@suaveplan/api-router-worker-bridge/bridge"; const { dispatch } = createMainBridge(mainPort); createWorkerBridge(workerPort, async (req) => new Response(`hello ${new URL(req.url).pathname}`) ); const res = await dispatch(new Request("https://api.local/world")); await res.text(); // "hello /world" ``` ## Usage: Advanced Wire a streaming-only bridge for large uploads/downloads: ```ts import { createMainBridge, createWorkerBridge, } from "@suaveplan/api-router-worker-bridge/bridge"; const { dispatch } = createMainBridge(mainPort, { inlineBodyLimit: 0, streamWindow: 32, }); createWorkerBridge( workerPort, async (req) => new Response(req.body, { headers: req.headers }), { inlineBodyLimit: 0, streamWindow: 32 } ); ``` ## API Reference - `createMainBridge(port, options?) → { dispatch(Request): Promise, close(): void }`. - `createWorkerBridge(port, handler, options?) → { close(): void }`. - `BRIDGE_DISPATCH_METHOD = "http.dispatch"`. - `BridgeOptions { inlineBodyLimit?, maxBodyBytes?, headerDenyList?, streamWindow? }`. - `WorkerHandler = (Request) => Promise | Response`. ## Implementation Notes The bridge intentionally re-uses `api-worker-rpc`'s request/response and stream frame shapes (and `PROTOCOL_VERSION`) so its traffic shares the same wire dialect — a downstream channel can multiplex both ordinary RPC and HTTP traffic without parsing ambiguity. When the request body is streamed, the same numeric id is used for both the RPC correlation and the stream id; that is safe because the streaming-frame `kind` is disjoint from the response frame and never collides.