2.4 KiB
service/bus-map
Purpose
bus-map declares SmsBusMap — the single-payload topic
contract used by SmsService.bus (an EventBus<SmsBusMap>).
The map is split out from the service implementation so the
legacy emitter and the service can both import the contract
without a circular dependency, and so downstream consumers can
type their own EventBus-shaped bridges against the same
contract.
SmsBusMap covers the eight live topics emitted by
SmsService: sms.sent, sms.delivered, sms.failed,
sms.opted_out, sms.opted_in, sms.scheduled, sms.retry,
sms.rate_limited.
Features
- Single-payload
EventBuscontract — one value per topic (versus the legacySmsEventMaptuple form which mirrors the upstreamon/off/emitshape). - Open
Record<string, unknown>base so consumers can extend the map with custom topics in their own packages. - One-to-one mapping with the public type contracts in
src/types/sms.types.ts.
Usage: Basic
import { EventBus } from "@suaveplan/events";
import type { SmsBusMap } from "@suaveplan/sms/service";
const bus = new EventBus<SmsBusMap>();
bus.on("sms.sent", (report) => console.log("sent", report.messageId));
Usage: Advanced
import { EventBus } from "@suaveplan/events";
import type { SmsBusMap } from "@suaveplan/sms/service";
// Extend the map with a host-specific topic to share one bus.
interface HostBusMap extends SmsBusMap {
"host.audit": { actor: string; action: string };
}
const bus = new EventBus<HostBusMap>();
bus.on("sms.failed", (report) => audit({ messageId: report.messageId }));
bus.on("host.audit", (event) => console.log(event.actor, event.action));
API Reference
interface SmsBusMap extends Record<string, unknown>with keys:sms.sent,sms.delivered,sms.failed,sms.opted_out,sms.opted_in,sms.scheduled,sms.retry,sms.rate_limited, each mapped to the matching public type (SmsDeliveryReport,OptOutEntry,{phoneNumber: string},SmsScheduledEvent,SmsRetryEvent,SmsRateLimitedEvent).
Implementation Notes
The map is a type-only export — no runtime symbol — so it
adds zero bundle size. The decision to use single-payload
topics on the bus (rather than the legacy tuple form) follows
@suaveplan/events convention; the tuple form is
preserved exclusively for the upstream on/off/emit surface
and is mediated by LegacyEmitter.mirror. Consumers building
new code should target the bus directly.