Files
2026-05-27 23:29:53 +01:00

8.3 KiB

@suaveplan/api-ws-bun - Bun.serve-backed WebSocket engine for @suaveplan/api-ws. Implements the abstract WsEngine contract using Bun's native WebSocket primitives: handshake pipeline freezing the principal, per-tenant ConnectionRegistry, SubscriptionBus integration, backpressure eviction (default 256 msg queue), heartbeat (30s ping / 2 missed-pong drop), per-tenant caps (1000), HMAC-signed reconnect tokens (5-min TTL) with auto/memory/broker event-buffer strategies, and the OTel surface from design §11.7. Passes runWsEngineConformance.

Bun.serve-backed WebSocket engine for the @suaveplan/api-ws Stage-1 abstract contract. The engine composes the per-connection handshake pipeline, registry, subscription bus, backpressure guard, heartbeat controller, principal-expiry watcher, reconnect-token issuer, reconnect-event buffer, and OTel surface into one createBunWsEngine(opts) factory call. Passes runWsEngineConformance and ships a real Bun.serve integration smoke under tests/integration/.

Documentation tree

  • backpressure — Enforces the per-connection send-queue cap described in design §11.4. Each connection owns one BackpressureGuard inst…
    • backpressure — Enforces the per-connection send-queue cap described in design §11.4. Each connection owns one BackpressureGuard inst…
  • engine — createBunWsEngine is the package's headline factory. It composes every other module in the package — registry, bus, i…
    • bun-ws-engine — createBunWsEngine is the package's headline factory. It composes every other module in the package — registry, bus, i…
  • error-codes — Provides the stable error-code registry and the typed WsBunError subclass for @suaveplan/api-ws-bun. Every producti…
    • error-codes — Provides the stable error-code registry and the typed WsBunError subclass for @suaveplan/api-ws-bun. Every producti…
  • handshake — Freezes the per-request pipeline result onto a per-connection HandshakeOutcome. The host runs the standard pipeline s…
    • handshake — Freezes the per-request pipeline result onto a per-connection HandshakeOutcome. The host runs the standard pipeline s…
    • subprotocol — Implements RFC 6455 §4.1 subprotocol negotiation as a tiny pure function. The server is supplied the client's requested…
  • heartbeat — Implements the per-connection ping/pong state machine described in design §11.4. The engine instantiates one `Heartbeat…
    • heartbeat — Implements the per-connection ping/pong state machine described in design §11.4. The engine instantiates one `Heartbeat…
  • instruments — Builds the OTel instrument registry the engine emits to. The names, units, and attribute keys all match design doc §11.…
    • instruments — Builds the OTel instrument registry the engine emits to. The names, units, and attribute keys all match design doc §11.…
  • limits — Provides the per-tenant connection-count enforcement function that the handshake pipeline calls before admitting a new…
    • tenant-cap — Provides the per-tenant connection-count enforcement function that the handshake pipeline calls before admitting a new…
  • options — Defines the Zod-validated options surface accepted by createBunWsEngine. Every field has a documented default sourced…
    • options — Defines the Zod-validated options surface accepted by createBunWsEngine. Every field has a documented default sourced…
  • principal — Tracks the underlying token expiry for a frozen principal so the engine can drop the connection at the right moment. Th…
    • principal-expiry — Tracks the underlying token expiry for a frozen principal so the engine can drop the connection at the right moment. Th…
  • event-buffer — Provides the per-(tenant, topic) reconnect-event buffer used to replay events to a reconnecting client whose `lastEve…
  • reconnect-token — Wraps the api-ws contract's signReconnectToken / verifyReconnectToken HMAC token helpers so the engine has a statef…
  • registry — Wraps the api-ws contract's InMemoryConnectionRegistry to give the Bun engine a typed registry surface that the confo…
    • connection-registry — Wraps the api-ws contract's InMemoryConnectionRegistry to give the Bun engine a typed registry surface that the confo…
  • subscription — Builds the per-engine subscription bus instance and binds it to the engine's connection registry. The bus implementatio…
    • subscription-bus — Builds the per-engine subscription bus instance and binds it to the engine's connection registry. The bus implementatio…
  • testing — Binds the abstract runWsEngineConformance harness from @suaveplan/api-ws/testing to a default createBunWsEngine-b…
    • conformance-binding — Binds the abstract runWsEngineConformance harness from @suaveplan/api-ws/testing to a default createBunWsEngine-b…

Defaults

Option Default Source
maxQueuedMessages 256 §11.4
heartbeatMs 30_000 (min 5_000) §11.4
missedPongLimit 2 §11.4
maxConnectionsPerTenant 1_000 §11.4
reconnectTokenTtlMs 300_000 §11.5
reconnectEventBufferStrategy "auto" §11.5 + §14
reconnectEventBufferLimit 256 engine
subprotocols [] engine
pluginId "api-ws-bun" engine

Modules

  • engine — createBunWsEngine, ManagedConnection, BunWsSocketSink.
  • options — BunWsEngineOptions, bunWsEngineOptionsSchema, resolveBunWsEngineOptions.
  • handshake — runHandshake, resolveSubprotocol.
  • registry — BunConnectionRegistry.
  • subscription — createBunSubscriptionBus.
  • backpressure — BackpressureGuard.
  • heartbeat — HeartbeatController.
  • limits — enforceTenantCap.
  • principal — PrincipalExpiryWatcher.
  • reconnect — ReconnectTokenIssuer, MemoryReconnectEventBuffer, BrokerReconnectEventBuffer, resolveReconnectEventBuffer.
  • instruments — createBunWsInstruments (every §11.7 instrument).
  • error-codes — WS_BUN_CODES, WsBunError, ten raise* helpers.
  • testing (subpath @suaveplan/api-ws-bun/testing) — runBunWsConformance, bunEngineFactory, adaptEngineToFactory.

Example

import { createBunWsEngine } from "@suaveplan/api-ws-bun";
import { createInMemoryWsBroker } from "@suaveplan/api-ws-broker-in-memory";

const broker = createInMemoryWsBroker();
const engine = createBunWsEngine({
    reconnectTokenSecret: new Uint8Array(32).fill(7),
    broker,
});

Bun.serve({
    port: 8787,
    fetch(req, srv) {
        if (new URL(req.url).pathname === "/ws") {
            return srv.upgrade(req, { data: { id: crypto.randomUUID() } })
                ? undefined
                : new Response("upgrade failed", { status: 400 });
        }
        return new Response("ok");
    },
    websocket: {
        open(ws) {
            engine.attach({
                id: ws.data.id,
                principal,
                tenantId,
                capabilities: new Set(),
                tokenExpiresAt: Date.now() + 3_600_000,
                sink: {
                    send: (s) => ws.send(s),
                    close: (c, r) => ws.close(c, r),
                    ping: () => ws.ping?.(),
                },
            });
        },
        message() {},
        close() {},
    },
});

Tests

bunx turbo lint typecheck test:coverage --filter=@suaveplan/api-ws-bun