# `createInMemoryEventsBus` _(no submodules)_ ## Purpose `createInMemoryEventsBus` is the factory entry point of `@suaveplan/api-events-in-memory`. It returns a fresh {@link InMemoryEventsBus} whose `publish` calls are recorded in a per-topic ring of payloads and whose subscriber delivery is delegated to a private `@suaveplan/events` `EventBus`. Tests can both assert "this event was published with this payload" (via `published(topic)`) and assert "this subscriber observed the side-effect" (via the subscriber callback) without any mocks or test doubles — the real production bus runs underneath. ## Features - Recording layer wraps every `publish` / `publishAsync` / `emit` call; the payload is appended to the topic's history BEFORE dispatch so history is still complete even if a subscriber throws. - Strict-throw history-overflow policy via the cap-bounded {@link History}. `published(topic)`'s "every publish since `reset()`" guarantee survives long-running test suites. - Subscriber surface (`on` / `once` / `off`) mirrors `@suaveplan/events`' `EventBus`; the more powerful `EventBus.emitAsync` semantics are exposed through `publishAsync` (sequential await over registered listeners; same delivery order; same error-capture model). - `emit(topic, payload)` alias satisfies the structural `CapabilityEventBusLike` contract from `@suaveplan/api-types/capabilities` so the bus can be handed to API plugins as their `events` capability without an additional adapter. - `dispose()` clears history AND tears down every subscriber so test isolation is straightforward — call once per test, no leaks. - `createInMemoryEventBus` (no "s") is a stable alias matching the prompt's `./adapter` subpath; both spellings will continue to exist. ## Usage: Basic ```ts import { createInMemoryEventsBus } from "@suaveplan/api-events-in-memory/bus"; const bus = createInMemoryEventsBus(); const seen: unknown[] = []; bus.on("billing.invoice.created", (payload) => seen.push(payload)); bus.publish("billing.invoice.created", { invoiceId: "inv_1", amount: 100 }); console.log(bus.published("billing.invoice.created")); // [{ invoiceId: "inv_1", amount: 100 }] console.log(seen); // [{ invoiceId: "inv_1", amount: 100 }] bus.reset(); console.log(bus.published("billing.invoice.created")); // [] ``` ## Usage: Advanced Pin the per-topic cap when the test publishes in a tight loop, then recover by `reset()` between batches: ```ts import { createInMemoryEventsBus } from "@suaveplan/api-events-in-memory/bus"; import { EVENTS_IN_MEMORY_CODES, EventsInMemoryError, } from "@suaveplan/api-events-in-memory/error-codes"; const bus = createInMemoryEventsBus({ maxHistoryPerTopic: 3 }); async function fanOut(count: number) { for (let i = 0; i < count; i += 1) { await bus.publishAsync("metrics.tick", { i }); } } try { await fanOut(5); } catch (error) { if ( error instanceof EventsInMemoryError && error.code === EVENTS_IN_MEMORY_CODES.HISTORY_OVERFLOW ) { bus.reset(); await fanOut(2); } else { throw error; } } console.log(bus.published("metrics.tick").length); // 2 bus.dispose(); ``` ## API Reference - `createInMemoryEventsBus(options?: InMemoryEventsBusOptions): InMemoryEventsBus` — factory. - `createInMemoryEventBus` — alias, same return value. - `InMemoryEventsBus.publish(topic, payload): void` — sync publish; appends history first. - `InMemoryEventsBus.publishAsync(topic, payload): Promise` — async publish. - `InMemoryEventsBus.emit(topic, payload): Promise` — `CapabilityEventBusLike` alias. - `InMemoryEventsBus.on(topic, listener): Unsubscribe` — register a subscriber. - `InMemoryEventsBus.once(topic, listener): Unsubscribe` — one-shot subscriber. - `InMemoryEventsBus.off(topic, listener): void` — remove a subscriber. - `InMemoryEventsBus.published(topic): readonly unknown[]` — snapshot of history. - `InMemoryEventsBus.topics(): readonly string[]` — sorted topic names. - `InMemoryEventsBus.reset(): void` — clear history; keep subscribers. - `InMemoryEventsBus.dispose(): void` — clear history AND subscribers. ## Implementation Notes The underlying `EventBus` is parameterised with the open `EventMap` shape (`Record`) so the in-memory adapter can carry any topic name without forcing the test to declare a typed map up front. Recording happens BEFORE dispatch because the contract that matters for tests is "this publish was attempted" — history that drops on subscriber failure would silently hide test bugs. `emit` and `publishAsync` share the same body; `emit` exists only so the bus satisfies the structural `CapabilityEventBusLike` interface from `@suaveplan/api-types`.