76 lines
3.7 KiB
Markdown
76 lines
3.7 KiB
Markdown
# `@suaveplan/events` v1.1.0 — Port Missing Capabilities from Suaveplan
|
|
|
|
**Status:** Active
|
|
**Target:** `@suaveplan/events` 0.0.0 → additive capabilities, no breaking changes
|
|
**Source:** `/home/ubuntu/web/suaveplan/openspec/changes/events-v1.1.0/`
|
|
|
|
---
|
|
|
|
## Why
|
|
|
|
The genesis `EventBus` was a cut-down redesign of suaveplan's `EventEmitter`. While it introduced improvements (interceptor API, `BoundedQueue`, idempotent listeners, deterministic injection), it was missing several capabilities that suaveplan had already proven necessary:
|
|
|
|
- No event buffering for late subscribers — plugins attaching after lifecycle transitions miss historical events.
|
|
- No wildcard pattern matching — observers must enumerate every event name.
|
|
- No async iteration — consumers manually manage `on`/`off` instead of `for await`.
|
|
- No `prependListener` — impossible to insert a listener at the head.
|
|
- No listener introspection — `listeners()` / `listenerCount()` absent.
|
|
- No `once()` → `off()` round-trip — `off(type, originalListener)` fails for `once` registrations.
|
|
- No concurrency control on `emitAsync` — one slow listener blocks the chain.
|
|
- No `maxListeners` warning — memory leaks go undetected.
|
|
- No global `errorSink` — caller must inspect `EmitResult.errors` or errors are lost.
|
|
- No `Symbol.dispose` — no RAII cleanup via `using`.
|
|
|
|
These gaps force consumers to reinvent the missing primitives downstream.
|
|
|
|
---
|
|
|
|
## What changes
|
|
|
|
### Core `EventBus` additions
|
|
|
|
1. **`bufferSize` option** — replays the last N events to subscribers that attach after emission.
|
|
2. **`wildcard` option** — subscribe to `plugin:*` and match all `plugin:ready`, `plugin:error`, etc.
|
|
3. **`iter(type, signal?)`** — async iterable over events, compatible with `for await`.
|
|
4. **`prepend(type, listener)`** — insert listener at the head of the dispatch queue.
|
|
5. **`listeners(type)` / `listenerCount(type)`** — introspection without exposing internals.
|
|
6. **`offAll(type?)`** — remove all listeners for a type, or everything.
|
|
7. **`once()` WeakMap tracking** — `off(type, originalListener)` works for `once` registrations.
|
|
8. **`concurrency` option on `emitAsync`** — `sequential` (default), `parallel`, `allSettled`.
|
|
9. **`maxListeners` + `errorSink`** — warnings and centralised error routing.
|
|
10. **`Symbol.dispose`** on `EventBus` and `Unsubscribe` handles.
|
|
11. **`EVENTS.LISTENER.MAX_EXCEEDED`** error code.
|
|
|
|
### Non-goals
|
|
|
|
- No breaking changes to existing `EventBus` API.
|
|
- No `BoundedQueue` integration into `EventBus` dispatch — remains a standalone utility.
|
|
- No changes to companion packages (`events-otel`, `events-schema`, `events-metrics`, `events-transport`) unless required by API additions.
|
|
|
|
---
|
|
|
|
## Impact
|
|
|
|
### Affected dependents
|
|
|
|
Run `bunx turbo ls --filter=...@suaveplan/events` to enumerate. All additive surface, so no downstream code changes required. Verified by running downstream test suites.
|
|
|
|
- `@suaveplan/crypto-vault` — no action needed (uses `EventBus` directly, doesn't touch changed surface)
|
|
- `@suaveplan/network` — no action needed (uses `EventBus` + `BoundedQueue`, unchanged)
|
|
- `@suaveplan/storage` — no action needed
|
|
- `@suaveplan/packer` — no action needed
|
|
- `@suaveplan/fsm` — no action needed
|
|
- `@suaveplan/retry` — no action needed
|
|
- `@suaveplan/migration` — no action needed (type-only import)
|
|
- `@suaveplan/config` — no action needed
|
|
- `@suaveplan/events-schema` — no action needed (type-only import)
|
|
- `@suaveplan/events-metrics` — no action needed (type-only import)
|
|
- `@suaveplan/events-otel` — no action needed (type-only import)
|
|
- `@suaveplan/events-transport` — no action needed (type-only import)
|
|
|
|
---
|
|
|
|
## Migration
|
|
|
|
No migration needed — purely additive.
|