# @suaveplan/api-ws-broker-in-memory - In-memory single-host WebSocket broker for @suaveplan/api-ws. Implements WsBroker via direct in-process fan-out — publish iterates a topic->handlers map and invokes each subscriber's handler. Supports fire-and-forget and await-all delivery modes, idempotent dispose, Zod-validated options, and the WS_BROKER_IN_MEMORY.* error registry (INVALID_OPTIONS, BROKER_DISPOSED). Production-grade for single-host deployments; tests-grade for any plugin manifesting WebSocket endpoints. For multi-host fan-out use @suaveplan/api-ws-broker-redis (Stage 7). Single-host in-process implementation of the `@suaveplan/api-ws` `WsBroker` contract. Suitable for production single-host deployments AND as the default broker wired into `createTestHost` ($2 kit). For multi-host fan-out use `@suaveplan/api-ws-broker-redis` (Stage 7). The broker maintains a per-topic `Set` registry and dispatches every `publish(topic, envelope)` to every handler currently subscribed to that topic. There is no network, no message bus, and no persistence — "in-memory" describes the storage substrate, not the maturity level. ## Documentation tree - [broker](./src/broker/broker.md) — This module implements the `WsBroker` contract from `@suaveplan/api-ws` by maintaining an in-process `Map ## What ships | Subpath | Module | Doc | |---|---|---| | `./broker` | `createInMemoryWsBroker(options?)` factory | [`src/broker/broker.md`](src/broker/broker.md) | | `./error-codes` | `WS_BROKER_IN_MEMORY_CODES` + `WsBrokerInMemoryError` | [`src/error-codes/error-codes.md`](src/error-codes/error-codes.md) | | `./testing` | `createInMemoryBrokerHarness(options?)` for tests | [`src/testing/testing.md`](src/testing/testing.md) | ## Surface - `createInMemoryWsBroker(options?)` — factory returning an `InMemoryWsBroker` (the `WsBroker` contract plus `subscriberCount(topic)` and `isDisposed()` introspection helpers). - `InMemoryWsBrokerOptions { deliveryMode? }` — Zod-validated strict option shape. `deliveryMode` is `"fire-and-forget"` (default) or `"await-all"`. - `WS_BROKER_IN_MEMORY_CODES` — closed set of two stable codes: `INVALID_OPTIONS` and `BROKER_DISPOSED`. - `createInMemoryBrokerHarness(options?)` — opinionated test harness wrapping the broker with a captured-envelope observer + idempotent teardown. ## Quickstart ```ts import { createInMemoryWsBroker } from "@suaveplan/api-ws-broker-in-memory"; import type { TenantId } from "@suaveplan/api-types/tenant"; const broker = createInMemoryWsBroker<{ id: number }>(); const sub = broker.subscribe("orders", (envelope) => { console.log("delivered", envelope.payload.id); }); await broker.publish("orders", { topic: "orders", tenant: "t1" as unknown as TenantId, payload: { id: 1 }, }); await sub.unsubscribe(); broker.dispose(); ``` ## Single-host vs multi-host This package is **single-host only**. Two host replicas instantiated with separate `createInMemoryWsBroker()` calls each see only their own publishes; there is no shared substrate. For multi-host topologies use `@suaveplan/api-ws-broker-redis` (Stage 7), which implements the same `WsBroker` contract over Redis Pub/Sub. ## Quality bars - 100% line / branch / function / statement coverage (Istanbul). - 100% docs coverage — every implementation `.ts` has a sibling `.md` with the required headings. - Zero direct imports of `vitest` / `bun:test` — all test files import from `@suaveplan/testing/runner`. - Stable, namespaced error codes (`WS_BROKER_IN_MEMORY.*`).