Move docs/ package mirror into document-navigator plugin
Relocate the ~6k-file docs tree from the repo root into plugins/document-navigator/docs/ so the plugin is self-contained and portable. docs/superpowers/ (specs and plans) stays at the repo root. Moved via cp+rm rather than git mv because directory rename() fails with EPERM on this WSL /mnt DrvFs mount; git rename-detection pairs the identical-content files at commit time. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,142 @@
|
||||
# @suaveplan/api-sse-bun - Bun.serve concrete engine for @suaveplan/api-sse: text/event-stream framing, Last-Event-Id replay, per-(tenant,topic) ring buffer with broker delegation, gzip streaming, keep-alive comments, per-tenant connection cap, shared subscription bus with WS engine, and the runSseEngineConformance harness bound to createBunSseEngine.
|
||||
|
||||
`Bun.serve`-backed Server-Sent Events engine for the `@suaveplan/api`
|
||||
plugin system. Implements the abstract `@suaveplan/api-sse`
|
||||
contract and passes `runSseEngineConformance` end-to-end. Lands at
|
||||
api-plugin-foundation umbrella.
|
||||
|
||||
SSE complements `api-ws-bun`: where WebSocket carries bi-directional
|
||||
duplex traffic, SSE is the simpler server→client stream useful for
|
||||
activity feeds, dashboards, notifications, and any payload pattern
|
||||
that does not need client→server acks. SSE also falls back gracefully
|
||||
on networks that block WebSocket (corporate proxies, restrictive
|
||||
firewalls) so a single broadcast can reach clients via either
|
||||
transport.
|
||||
|
||||
<!-- begin:auto-docs -->
|
||||
## Documentation tree
|
||||
|
||||
- [compression](./src/compression/compression.md) — The `compression` module owns the engine's optional gzip path. SSE streams compress well — UTF-8 text framed with repea…
|
||||
- [compression](./src/compression/compression.md) — The `compression` module owns the engine's optional gzip path. SSE streams compress well — UTF-8 text framed with repea…
|
||||
- [engine](./src/engine/bun-sse-engine.md) — The `bun-sse-engine` module exports `createBunSseEngine`, the factory the host calls to mount Server-Sent Events on top…
|
||||
- [bun-sse-engine](./src/engine/bun-sse-engine.md) — The `bun-sse-engine` module exports `createBunSseEngine`, the factory the host calls to mount Server-Sent Events on top…
|
||||
- [error-codes](./src/error-codes/error-codes.md) — The `error-codes` module defines the stable `SSE_BUN_*` error registry used across the Bun SSE engine. Every failure mo…
|
||||
- [error-codes](./src/error-codes/error-codes.md) — The `error-codes` module defines the stable `SSE_BUN_*` error registry used across the Bun SSE engine. Every failure mo…
|
||||
- [event-buffer](./src/event-buffer/event-buffer.md) — The `event-buffer` module owns the per-`(tenant, topic)` replay storage the engine consults on `Last-Event-Id` reconnec…
|
||||
- [event-buffer](./src/event-buffer/event-buffer.md) — The `event-buffer` module owns the per-`(tenant, topic)` replay storage the engine consults on `Last-Event-Id` reconnec…
|
||||
- [handshake](./src/handshake/handshake.md) — The `handshake` module implements the 7-step SSE handshake pipeline: topic validation, `Last-Event-Id` parsing, authent…
|
||||
- [handshake](./src/handshake/handshake.md) — The `handshake` module implements the 7-step SSE handshake pipeline: topic validation, `Last-Event-Id` parsing, authent…
|
||||
- [instruments](./src/instruments/instruments.md) — The `instruments` module wires the engine's OpenTelemetry surface. Every metric mandated by design doc §11.7 — connecti…
|
||||
- [instruments](./src/instruments/instruments.md) — The `instruments` module wires the engine's OpenTelemetry surface. Every metric mandated by design doc §11.7 — connecti…
|
||||
- [keep-alive](./src/keep-alive/keep-alive.md) — The `keep-alive` module emits invisible SSE comment lines on a fixed cadence so intermediary proxies (corporate gateway…
|
||||
- [keep-alive](./src/keep-alive/keep-alive.md) — The `keep-alive` module emits invisible SSE comment lines on a fixed cadence so intermediary proxies (corporate gateway…
|
||||
- [last-event-id](./src/last-event-id/last-event-id.md) — The `last-event-id` module parses and validates the `Last-Event-Id` header browsers send automatically on `EventSource`…
|
||||
- [last-event-id](./src/last-event-id/last-event-id.md) — The `last-event-id` module parses and validates the `Last-Event-Id` header browsers send automatically on `EventSource`…
|
||||
- [limits](./src/limits/tenant-cap.md) — The `tenant-cap` module owns the per-tenant SSE connection counter the engine consults during handshake. A tenant that…
|
||||
- [tenant-cap](./src/limits/tenant-cap.md) — The `tenant-cap` module owns the per-tenant SSE connection counter the engine consults during handshake. A tenant that…
|
||||
- [options](./src/options/options.md) — The `options` module declares the public configuration surface accepted by `createBunSseEngine` and exposes `resolveOpt…
|
||||
- [options](./src/options/options.md) — The `options` module declares the public configuration surface accepted by `createBunSseEngine` and exposes `resolveOpt…
|
||||
- [stream](./src/stream/sse-stream.md) — The `sse-stream` module owns the byte-level framing for the SSE wire protocol. Every event the engine pushes to a clien…
|
||||
- [sse-stream](./src/stream/sse-stream.md) — The `sse-stream` module owns the byte-level framing for the SSE wire protocol. Every event the engine pushes to a clien…
|
||||
- [subscription](./src/subscription/subscription-bus.md) — The `subscription-bus` module owns the shared fan-out surface both the WS and SSE engines plug into. The host construct…
|
||||
- [subscription-bus](./src/subscription/subscription-bus.md) — The `subscription-bus` module owns the shared fan-out surface both the WS and SSE engines plug into. The host construct…
|
||||
- [testing](./src/testing/conformance.md) — The `testing` module exposes `runBunSseEngineConformance` — a thin binding that hands `createBunSseEngine` to the abstr…
|
||||
- [conformance](./src/testing/conformance.md) — The `testing` module exposes `runBunSseEngineConformance` — a thin binding that hands `createBunSseEngine` to the abstr…
|
||||
<!-- end:auto-docs -->
|
||||
|
||||
## Modules
|
||||
|
||||
- **`engine/bun-sse-engine`** — `createBunSseEngine(options)` factory
|
||||
returning the public engine value; wires options + buffer + bus +
|
||||
cap + instruments + handshake into one cohesive instance.
|
||||
- **`handshake/handshake`** — 7-step pipeline (topic validation,
|
||||
Last-Event-Id parse, auth, cap acquire, compression negotiate,
|
||||
prologue + replay, subscribe + keep-alive).
|
||||
- **`stream/sse-stream`** — WHATWG-compliant byte-level framing for
|
||||
`id`/`event`/`data`/`retry`/`:comment` lines.
|
||||
- **`event-buffer/event-buffer`** — in-memory ring buffer + broker
|
||||
delegate behind one `EventBuffer` surface.
|
||||
- **`subscription/subscription-bus`** — shared topic + tenant bus the
|
||||
WS engine reuses.
|
||||
- **`limits/tenant-cap`** — per-tenant connection counter enforced at
|
||||
handshake time.
|
||||
- **`compression/compression`** — `Accept-Encoding` negotiation +
|
||||
`node:zlib` streaming with sync-flush after every chunk.
|
||||
- **`keep-alive/keep-alive`** — periodic `:keepalive` comment
|
||||
scheduler with injectable timer for `FakeClock` tests.
|
||||
- **`last-event-id/last-event-id`** — header parser enforcing decimal
|
||||
format.
|
||||
- **`instruments/instruments`** — OTel meter bundle: connections
|
||||
gauge, events-sent counter, handshake-duration histogram,
|
||||
replay-hit/miss counter, compression-ratio histogram.
|
||||
- **`error-codes/error-codes`** — 10 stable `SSE_BUN_*` codes +
|
||||
`SseBunError` subclass.
|
||||
- **`testing/conformance`** — `runBunSseEngineConformance()` binding
|
||||
to the abstract `runSseEngineConformance` harness.
|
||||
|
||||
## Defaults
|
||||
|
||||
| Knob | Default | Notes |
|
||||
|------|---------|-------|
|
||||
| `eventBufferSize` | 256 | Per-`(tenant, topic)` ring capacity. |
|
||||
| `eventBufferMs` | 300_000 | 5 min — pinned to WS reconnect window. |
|
||||
| `keepAliveCommentMs` | 15_000 | 15 s — inside the 30 s proxy idle window. |
|
||||
| `maxConnectionsPerTenant` | 1_000 | Per-tenant cap. |
|
||||
| `maxEventBytes` | 65_536 | 64 KiB per encoded frame. |
|
||||
| `compressionEnabled` | `true` | Honours `Accept-Encoding: gzip`. |
|
||||
| `retryMs` | 3_000 | Initial `retry:` directive. |
|
||||
|
||||
## Boundary vs `api-ws-bun`
|
||||
|
||||
SSE is **server→client only**. It does **not** carry client→server
|
||||
messages, acks, or close codes — the client opens a long-lived GET,
|
||||
the server streams text/event-stream until the client disconnects or
|
||||
the server tears down. Use SSE when you need a uni-directional
|
||||
broadcast stream that defaults to working through restrictive
|
||||
intermediaries; use WS when you need duplex semantics, binary frames,
|
||||
or per-message acks. The two engines share the same subscription bus
|
||||
and event-buffer surface so the choice is per-route, not per-deploy.
|
||||
|
||||
## Install + use
|
||||
|
||||
```bash
|
||||
bun add @suaveplan/api-sse-bun
|
||||
```
|
||||
|
||||
```ts
|
||||
import { createBunSseEngine } from "@suaveplan/api-sse-bun";
|
||||
|
||||
const engine = createBunSseEngine({
|
||||
authenticate: async (req) => ({
|
||||
tenantId: (req.headers.get("x-tenant") ?? "anon") as never,
|
||||
principal: null,
|
||||
}),
|
||||
});
|
||||
|
||||
Bun.serve({
|
||||
port: 0,
|
||||
async fetch(request) {
|
||||
const url = new URL(request.url);
|
||||
if (url.pathname === "/sse/audit") {
|
||||
return engine.acceptRequest({
|
||||
request: {
|
||||
headers: request.headers,
|
||||
url: request.url,
|
||||
method: request.method,
|
||||
},
|
||||
path: url.pathname,
|
||||
topic: "audit",
|
||||
});
|
||||
}
|
||||
return new Response("not found", { status: 404 });
|
||||
},
|
||||
});
|
||||
```
|
||||
|
||||
## Status
|
||||
|
||||
Stage-7 keystone. Conformance is pinned by the abstract
|
||||
`runSseEngineConformance` harness from `@suaveplan/api-sse`; this
|
||||
package's `runBunSseEngineConformance()` re-runs it bound to
|
||||
`createBunSseEngine`.
|
||||
|
||||
Reference in New Issue
Block a user