# `streaming` _(no submodules)_ ## Purpose This module marshals binary `ReadableStream` bodies between the main and worker processes by piggy-backing on `@suaveplan/api-worker- rpc`'s `stream-chunk` / `stream-end` / `stream-ack` frames. It implements the producer (`sendStream`) and consumer (`receiveStream`) halves of a single body transfer keyed on a numeric `streamId` (the same id baked into the body descriptor on the request or response envelope). ## Features - Window-based back-pressure: the producer stalls after `DEFAULT_STREAM_ WINDOW` (16) outbound chunks until the consumer sends a matching `stream-ack`, preventing unbounded buffering across the port. - Reuses the wire frame shape of `api-worker-rpc` so a single port can multiplex RPC and bridge streams interchangeably. - Producer errors are forwarded via `errorToEnvelope`; consumer rehydrates via `envelopeToError`, preserving the `SuaveplanError` code chain. - Defensive enqueue: non-binary chunks fail with `ROUTER_BRIDGE.STREAM_ INTERRUPTED` so misuse is loud rather than silently corrupting the body. ## Usage: Basic ```ts import { sendStream, receiveStream, } from "@suaveplan/api-router-worker-bridge/streaming"; const stream = receiveStream(port, 1); // consume `stream` like any ReadableStream await sendStream(port, 1, sourceStream); ``` ## Usage: Advanced Tune the back-pressure window for a high-throughput download path: ```ts import { sendStream } from "@suaveplan/api-router-worker-bridge/streaming"; await sendStream(port, streamId, hugeAttachment.body!, { window: 64 }); ``` ## API Reference - `sendStream(port, streamId, stream, options?) → Promise`. - `receiveStream(port, streamId, options?) → ReadableStream`. - `DEFAULT_STREAM_WINDOW = 16`. - `StreamOptions { window?: number }`. ## Implementation Notes The producer's ack listener is registered for the entire pump lifetime and torn down in `finally` so a crash in the source stream cannot leak a listener. `receiveStream` issues a `stream-ack` whenever its locally- buffered count reaches the window, not after every chunk — this matches the producer's pause threshold so throughput is steady rather than sawtoothed. `ArrayBuffer` payloads are coerced to `Uint8Array` to absorb runtime variation in how `MessagePort` surfaces transfers.