Initial Commit

This commit is contained in:
2026-05-27 23:29:53 +01:00
commit fbc70f96e6
10000 changed files with 1102152 additions and 0 deletions

View File

@@ -0,0 +1,77 @@
# `marshal-response`
<!-- begin:auto-docs -->
_(no submodules)_
<!-- end:auto-docs -->
## Purpose
This module is the response-side counterpart to `marshal-request`. It
converts a Fetch `Response` produced by a worker-side handler into a
plain `SerializedResponse` envelope safe to ship across a `MessagePort`,
and rehydrates that envelope back into a real `Response` on the main
process so the host pipeline can apply Steps 9-11 (response validation,
ETag, Server-Timing aggregation).
## Features
- Validates status code is in the 100-599 range (`ROUTER_BRIDGE.RESPONSE_INVALID`).
- Preserves status text and full header list (response headers are not on
any deny-list — the bridge only filters request-side credentials).
- Inlines bodies up to `DEFAULT_RESPONSE_INLINE_LIMIT` (64 KiB) and
streams everything else through the streaming module.
- Hard cap at `DEFAULT_RESPONSE_MAX_BYTES` (16 MiB) for inline bodies;
oversize payloads either stream or fail with
`ROUTER_BRIDGE.BODY_TOO_LARGE`.
- Tagged-union body shape mirrors the request side for symmetry.
## Usage: Basic
```ts
import { marshalResponse, rehydrateResponse } from
"@suaveplan/api-router-worker-bridge/marshal-response";
const wire = await marshalResponse(
new Response(JSON.stringify({ ok: true }), {
status: 200,
headers: { "content-type": "application/json" },
})
);
const reborn = rehydrateResponse(wire);
await reborn.json(); // { ok: true }
```
## Usage: Advanced
Stream a large attachment response via a stream id:
```ts
import {
marshalResponse,
rehydrateResponse,
} from "@suaveplan/api-router-worker-bridge/marshal-response";
const streamId = 99;
const wire = await marshalResponse(largeDownload, {
streamId,
inlineBodyLimit: 0,
});
// caller pipes `largeDownload.body` over the streaming channel; main side:
const reborn = rehydrateResponse(wire, mainStreamFor(streamId));
```
## API Reference
- `marshalResponse(response, options?) → Promise<SerializedResponse>`.
- `rehydrateResponse(serialized, streamBody?) → Response`.
- `serializedResponseSchema` — Zod validator.
- `DEFAULT_RESPONSE_INLINE_LIMIT`, `DEFAULT_RESPONSE_MAX_BYTES`.
## Implementation Notes
`statusText` is preserved because some clients (and HTTP/1.1 caches)
still depend on the reason phrase. The body tagged union is identical in
shape to `SerializedRequestBody`, but the two types are intentionally
distinct so future divergence (e.g. server-sent-event hints) does not
silently propagate. Status validation runs first so a `100/600` test
case fails cleanly even when the body would also fail.