Files
skills/plugins/document-navigator/docs/communication/messaging/notification-channel/README.md
2026-06-09 21:06:27 +01:00

10 KiB

@suaveplan/notification-channel - Multi-channel notification router with templates, sliding-window rate limiting, retry + dead-letter, scheduler, preferences, hooks, OpenTelemetry instrumentation, and Zod-validated boundaries. Universal: runs unchanged in Bun, Node, and the browser.

Multi-channel notification router with templates, sliding-window rate limiting, retry + dead-letter, scheduler, preferences, hooks, OpenTelemetry instrumentation, and Zod-validated boundaries. Universal: runs unchanged in Bun, Node, and the browser.

Documentation tree

  • delivery-channel — delivery-channel.ts defines the structural contract every concrete delivery channel implements. The contract is inten…
  • email-channel — email-channel.ts ships the EmailChannel DeliveryChannel implementation. The class is provider-neutral: the integr…
  • in-app-channel — in-app-channel.ts ships the InAppChannel implementation that stores notifications for an in-app inbox / unread badg…
  • push-channel — push-channel.ts ships the PushChannel implementation that delivers notifications via the Web Push Protocol (RFC 803…
  • sms-channel — sms-channel.ts ships the SmsChannel DeliveryChannel implementation. Like the email channel, it is provider-neutra…
  • webhook-channel — webhook-channel.ts ships the WebhookChannel implementation that POSTs notifications to an arbitrary HTTPS endpoint.…
  • digest — digest-channel.ts ships the DigestChannel implementation that batches notifications into periodic summaries deliver…
    • digest-channel — digest-channel.ts ships the DigestChannel implementation that batches notifications into periodic summaries deliver…
  • error-codes — error-codes.ts is the single source of truth for every error the @suaveplan/notification-channel package can throw.…
    • error-codes — error-codes.ts is the single source of truth for every error the @suaveplan/notification-channel package can throw.…
  • error-mapping — error-mapping.ts is the canonical place every reason code in NOTIFICATION_CHANNEL_CODES is paired with its typed su…
    • error-mapping — error-mapping.ts is the canonical place every reason code in NOTIFICATION_CHANNEL_CODES is paired with its typed su…
  • fakes — fake-fetch.ts ships the FakeFetch test double — a FetchLike that consumes scripted responses from a FIFO queue an…
    • fake-fetch — fake-fetch.ts ships the FakeFetch test double — a FetchLike that consumes scripted responses from a FIFO queue an…
  • hooks — hooks.ts exposes a small typed hook bus that runs before NotificationRouter commits a notification to a channel. Th…
    • hooks — hooks.ts exposes a small typed hook bus that runs before NotificationRouter commits a notification to a channel. Th…
  • otel — otel/metrics.ts registers the package's four OpenTelemetry instruments on a meter named `@suaveplan/notification-chan…
    • metrics — otel/metrics.ts registers the package's four OpenTelemetry instruments on a meter named `@suaveplan/notification-chan…
  • preferences — preference-manager.ts ships the PreferenceManager class that answers, at every send-time, "should this notification…
    • preference-manager — preference-manager.ts ships the PreferenceManager class that answers, at every send-time, "should this notification…
  • rate-limiter — channel-rate-limiter.ts ships the ChannelRateLimiter class — a per-channel + per-user sliding-window rate limiter.…
    • channel-rate-limiter — channel-rate-limiter.ts ships the ChannelRateLimiter class — a per-channel + per-user sliding-window rate limiter.…
  • retry — delivery-retry.ts ships the DeliveryRetry wrapper that retries a DeliveryChannel.send call with exponential backo…
    • delivery-retry — delivery-retry.ts ships the DeliveryRetry wrapper that retries a DeliveryChannel.send call with exponential backo…
  • router — notification-router.ts ships the NotificationRouter class — the primary entrypoint a consumer talks to. It resolves…
    • notification-router — notification-router.ts ships the NotificationRouter class — the primary entrypoint a consumer talks to. It resolves…
  • scheduler — notification-scheduler.ts ships the NotificationScheduler class for scheduling notifications for future delivery. T…
    • notification-scheduler — notification-scheduler.ts ships the NotificationScheduler class for scheduling notifications for future delivery. T…
  • schemas — schemas.ts exposes a Zod schema for every public option bundle in the package so callers can validate untrusted input…
    • schemas — schemas.ts exposes a Zod schema for every public option bundle in the package so callers can validate untrusted input…
  • templates — template-engine.ts ships the TemplateEngine registry that turns named templates into channel-specific rendered outp…
    • template-engine — template-engine.ts ships the TemplateEngine registry that turns named templates into channel-specific rendered outp…

Install

bun add @suaveplan/notification-channel

Quick start

import {
    EmailChannel,
    NotificationRouter,
} from "@suaveplan/notification-channel";

const email = new EmailChannel({
    from: "noreply@example.com",
    sendFn: async (msg) => ({ messageId: await provider.send(msg) }),
});

const router = new NotificationRouter({
    channels: [{ channel: "email", enabled: true, rateLimit: 100 }],
    defaultChannel: "email",
    deliveryChannels: [email],
});

router.on("notification.failed", (n) => audit.record(n));

await router.send({
    recipient: "user@example.com",
    body: "Welcome to Suaveplan",
    subject: "Welcome",
});

Surface

  • Five sending channels — EmailChannel, SmsChannel, PushChannel, InAppChannel, WebhookChannel.
  • One aggregating channel — DigestChannel (wraps any sending channel).
  • Router — NotificationRouter with templates, routing rules, lifecycle events, OTel meters.
  • Composables — ChannelRateLimiter, DeliveryRetry, NotificationScheduler, PreferenceManager, TemplateEngine.
  • Hooks — notification:routing pre-routing pipeline (onNotificationRouting).
  • Errors — stable NOTIFICATION_CHANNEL_CODES registry with eleven reasons.
  • Test double — FakeFetch for deterministic FetchLike injection.
  • OpenTelemetry — four instruments under the @suaveplan/notification-channel meter.

Modules

Architecture

Every dependency is injectable: Clock and FetchLike come from @suaveplan/types, the storage adapter behind PreferenceManager is caller-supplied, and every channel takes a sendFn callback so the package never bundles a specific provider SDK. The router uses EventBus<NotificationEventMap> so lifecycle events flow through the same typed-pub/sub primitive as the rest of the project.

The 11-code defineCodes("NOTIFICATION_CHANNEL", […]) registry preserves literal-typed unions through the public surface, so an exhaustive switch (err.code) reports unhandled codes at type-check time. OpenTelemetry meters fire on every router send and every dead-letter event so dashboards reflect real production behaviour out of the box.

License

MIT