Files
skills/docs/communication/messaging/sms/src/service/bus-map.md
2026-05-29 08:20:56 +01:00

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 EventBus contract — one value per topic (versus the legacy SmsEventMap tuple form which mirrors the upstream on/off/emit shape).
  • 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.