106 lines
5.5 KiB
Markdown
106 lines
5.5 KiB
Markdown
# @suaveplan/api-events-in-memory - In-memory EventsBus adapter for the @suaveplan/api testing kit. Wraps @suaveplan/events' EventBus with a per-topic recording layer so tests can assert that side-effect publishes happened. Exposes published(topic) and reset() helpers, options-bounded history with EVENTS_IN_MEMORY.HISTORY_OVERFLOW protection, Zod-validated options at the boundary, and a small waitFor harness for async assertions. No mocks — the real production bus delivers events to subscribers; this adapter only records publish history.
|
|
|
|
In-memory events bus adapter for the `@suaveplan/api` testing kit.
|
|
Wraps `@suaveplan/events`' production `EventBus` with a per-topic
|
|
recording layer so tests can assert that side-effect publishes
|
|
happened, without booting cross-process IPC and without mocks. The
|
|
real bus delivers events to subscribers; this adapter only adds a
|
|
queryable publish history.
|
|
|
|
<!-- begin:auto-docs -->
|
|
## Documentation tree
|
|
|
|
- [bus](./src/bus/bus.md) — `createInMemoryEventsBus` is the factory entry point of `@suaveplan/api-events-in-memory`. It returns a fresh {@link In…
|
|
- [bus](./src/bus/bus.md) — `createInMemoryEventsBus` is the factory entry point of `@suaveplan/api-events-in-memory`. It returns a fresh {@link In…
|
|
- [error-codes](./src/error-codes/error-codes.md) — The error-code registry pins the two failure modes that the in-memory events bus exposes to test code. Together they le…
|
|
- [error-codes](./src/error-codes/error-codes.md) — The error-code registry pins the two failure modes that the in-memory events bus exposes to test code. Together they le…
|
|
- [history](./src/history/history.md) — `History` is the per-topic append-only payload store that backs `bus.published(topic)`. Each `publish` invocation appen…
|
|
- [history](./src/history/history.md) — `History` is the per-topic append-only payload store that backs `bus.published(topic)`. Each `publish` invocation appen…
|
|
- [options](./src/options/options.md) — The options module is the single boundary at which user-supplied configuration enters the in-memory events bus. It owns…
|
|
- [options](./src/options/options.md) — The options module is the single boundary at which user-supplied configuration enters the in-memory events bus. It owns…
|
|
- [testing](./src/testing/testing.md) — The testing harness packages an {@link InMemoryEventsBus} with a `waitFor` helper for tests that publish asynchronously…
|
|
- [testing](./src/testing/testing.md) — The testing harness packages an {@link InMemoryEventsBus} with a `waitFor` helper for tests that publish asynchronously…
|
|
<!-- end:auto-docs -->
|
|
|
|
## Why
|
|
|
|
Per the API Plugin Foundation design (§13.2), the testing kit needs an
|
|
events bus whose publishes are observable from the test code:
|
|
|
|
```ts
|
|
import { createInMemoryEventsBus } from "@suaveplan/api-events-in-memory";
|
|
|
|
const bus = createInMemoryEventsBus();
|
|
|
|
// app code under test
|
|
bus.publish("billing.invoice.created", { invoiceId: "inv_1", amount: 100 });
|
|
|
|
// test
|
|
expect(bus.published("billing.invoice.created")).toHaveLength(1);
|
|
```
|
|
|
|
The simplest correct implementation wraps the production bus and adds
|
|
a recording layer around `publish` / `publishAsync`. Subscribers fire
|
|
as usual; ordering and FIFO invariants from the real bus are preserved.
|
|
|
|
## Install
|
|
|
|
```sh
|
|
bun add -d @suaveplan/api-events-in-memory
|
|
```
|
|
|
|
## Surface
|
|
|
|
- `./` — `createInMemoryEventsBus`, `createInMemoryEventBus` (alias),
|
|
`InMemoryEventsBus`, `History`, error codes, options.
|
|
- `./bus` (a.k.a. `./adapter`) — factory + types only.
|
|
- `./testing` — `createInMemoryEventsBusHarness` with a `waitFor`
|
|
helper for async assertions.
|
|
- `./error-codes` — `EVENTS_IN_MEMORY_CODES` + `EventsInMemoryError`.
|
|
- `./options` — Zod schema + `resolveInMemoryEventsBusOptions`.
|
|
- `./history` — standalone history ring (used by the bus internally).
|
|
|
|
## Quick reference
|
|
|
|
```ts
|
|
import { createInMemoryEventsBus } from "@suaveplan/api-events-in-memory";
|
|
import { createInMemoryEventsBusHarness } from "@suaveplan/api-events-in-memory/testing";
|
|
|
|
const bus = createInMemoryEventsBus({ maxHistoryPerTopic: 100 });
|
|
bus.on("user.signup", (payload) => doStuff(payload));
|
|
await bus.publishAsync("user.signup", { userId: "u1" });
|
|
expect(bus.published("user.signup")).toEqual([{ userId: "u1" }]);
|
|
|
|
const harness = createInMemoryEventsBusHarness();
|
|
await harness.waitFor((b) => b.published("welcome.email").length === 1);
|
|
harness.dispose();
|
|
```
|
|
|
|
## Options
|
|
|
|
| Option | Default | Notes |
|
|
| ---------------------- | ------- | ------------------------------------------------------------------ |
|
|
| `maxHistoryPerTopic` | `1000` | Strict-throw cap; `publish` raises `HISTORY_OVERFLOW` past the cap |
|
|
|
|
Invalid options raise `EVENTS_IN_MEMORY.INVALID_OPTIONS` with the
|
|
underlying `z.ZodError` on `cause`.
|
|
|
|
## Error codes
|
|
|
|
| Code | Raised when |
|
|
| ----------------------------------------- | --------------------------------------------------- |
|
|
| `EVENTS_IN_MEMORY.HISTORY_OVERFLOW` | `publish` would exceed `maxHistoryPerTopic` |
|
|
| `EVENTS_IN_MEMORY.INVALID_OPTIONS` | factory options fail Zod validation |
|
|
|
|
## Out of scope
|
|
|
|
- Persistence across process restarts — by design, in-memory.
|
|
- Multi-host fan-out — see future `api-events-redis`.
|
|
- Bounded-queue backpressure — `@suaveplan/events` already provides
|
|
this and the in-memory adapter inherits it through delegation.
|
|
|
|
## License
|
|
|
|
MIT — Suaveplan Team.
|
|
|