Files
2026-06-09 21:06:27 +01:00

9.9 KiB

@suaveplan/api-plugin-notifications - Notifications plugin for @suaveplan/api. Ships SurrealDB-backed NotificationRepository + DeviceTokenRepository, /notifications and /push Hono OpenAPI route groups, an APN service with injectable transport (no hardcoded network library), an event-bus integration via ctx.eventBus, 18 NOTIFICATIONS_PLUGIN_* error codes, and 6 OTel counters. Server-tier — runs in Bun and Node.

SurrealDB-backed notifications + push plugin for @suaveplan/api. Ships a NotificationRepository + DeviceTokenRepository pair, an ApnService with a pluggable transport contract (no hardcoded @parse/node-apn dependency), eleven /notifications/* Hono OpenAPI routes, five /push/* routes, an opt-in multi-channel NotificationDispatcher (apn + email) wired on top of @suaveplan/notification-channel, @suaveplan/emailer, and @suaveplan/delivery-tracking, twenty-two NOTIFICATIONS_PLUGIN_* error codes, and eight OTel counters.

Server-tier — runs in Bun and Node.

Documentation tree

  • apn-channel — Adapts the in-package ApnService to the @suaveplan/notification-channel DeliveryChannel interface so `Notificatio…
    • apn-channel — Adapts the in-package ApnService to the @suaveplan/notification-channel DeliveryChannel interface so `Notificatio…
  • email-channel — Adapts @suaveplan/emailer's EmailService to the @suaveplan/notification-channel DeliveryChannel interface so `N…
    • email-channel — Adapts @suaveplan/emailer's EmailService to the @suaveplan/notification-channel DeliveryChannel interface so `N…
  • idempotency-adapter — Defines the narrow contract that lets NotificationDispatcher delegate per-call deduplication to a caller-supplied imp…
    • idempotency-adapter — Defines the narrow contract that lets NotificationDispatcher delegate per-call deduplication to a caller-supplied imp…
  • notification-dispatcher — Top-level orchestrator that lets callers send one notification through whichever delivery channel they pick (APN, email…
    • notification-dispatcher — Top-level orchestrator that lets callers send one notification through whichever delivery channel they pick (APN, email…
  • error-codes — Stable error-code registry for @suaveplan/api-plugin-notifications. The module exports a frozen `NOTIFICATIONS_PLUGIN…
    • error-codes — Stable error-code registry for @suaveplan/api-plugin-notifications. The module exports a frozen `NOTIFICATIONS_PLUGIN…
  • otel — OpenTelemetry instrument bundle for @suaveplan/api-plugin-notifications. The module exposes a lazy, memoised factory…
    • instruments — OpenTelemetry instrument bundle for @suaveplan/api-plugin-notifications. The module exposes a lazy, memoised factory…
  • plugin — Plugin descriptor factory for @suaveplan/api-plugin-notifications. Composes everything in the package — Zod-validated…
    • plugin — Plugin descriptor factory for @suaveplan/api-plugin-notifications. Composes everything in the package — Zod-validated…
  • device-token-repository — SurrealDB-backed repository for the device_token table. Owns every SurrealQL statement the plugin issues against devi…
    • device-token-repository — SurrealDB-backed repository for the device_token table. Owns every SurrealQL statement the plugin issues against devi…
  • notification-repository — SurrealDB-backed repository for the notification table. Owns every SurrealQL statement the plugin issues against noti…
    • notification-repository — SurrealDB-backed repository for the notification table. Owns every SurrealQL statement the plugin issues against noti…
  • notifications-routes — Hono OpenAPI route module exposing the /notifications/* surface. Eleven endpoints cover list / unread-count / create…
    • notifications-routes — Hono OpenAPI route module exposing the /notifications/* surface. Eleven endpoints cover list / unread-count / create…
  • push-routes — Hono OpenAPI route module exposing the /push/* surface for device- token registration and APN delivery. Five endpoint…
    • push-routes — Hono OpenAPI route module exposing the /push/* surface for device- token registration and APN delivery. Five endpoint…
  • dispatch-schemas — Defines the Zod boundary for the NotificationDispatcher surface. The dispatcher fans a single call out to whichever d…
  • notification-schemas — Zod boundary schemas for the notification entity and every wire surface the plugin exposes — list / get / create / upda…
  • options — Zod schema for plugin options accepted by createNotificationsPlugin() plus the nested APN configuration shape (`ApnCo…
  • push-schemas — Zod boundary schemas for the /push/* route group and the device-token entity stored in SurrealDB. Schemas describe bo…
  • services — Module-augmentation file that declares three new service slots on @suaveplan/api-plugin/service-registry's `ServiceRe…
    • apn-service — Apple Push Notification delivery service. Validates an ApnConfig at construction-time, builds a pluggable `ApnTranspo…
      • apn-service — Apple Push Notification delivery service. Validates an ApnConfig at construction-time, builds a pluggable `ApnTranspo…
    • registry-augmentation — Module-augmentation file that declares three new service slots on @suaveplan/api-plugin/service-registry's `ServiceRe…
  • apn-transport — Pluggable transport contract for Apple Push Notification delivery. The plugin never depends on a concrete APN client li…
    • apn-transport — Pluggable transport contract for Apple Push Notification delivery. The plugin never depends on a concrete APN client li…
  • types — Public type aliases for cross-module wiring: the typed event-bus payload map (NotificationsPluginEvents), the discrim…
    • types — Public type aliases for cross-module wiring: the typed event-bus payload map (NotificationsPluginEvents), the discrim…

Modules

Usage

import { createNotificationsPlugin } from "@suaveplan/api-plugin-notifications";

await api.loadPlugin(
    createNotificationsPlugin({
        basePath: "/v1/notifications",
        pushBasePath: "/v1/push",
        enablePush: true,
        apn: {
            token: { key: "/keys/AuthKey.p8", keyId: "K", teamId: "T" },
            defaultTopic: "com.example.app",
            production: true,
        },
    })
);

Pluggable APN transport

Production hosts inject a node-apn-backed ApnTransport; tests use the deterministic MemoryApnTransport:

import { ApnService, type ApnTransport } from "@suaveplan/api-plugin-notifications";

const transport: ApnTransport = makeNodeApnTransport(provider);
const service = new ApnService({ config, transport });

See src/transport/apn-transport/apn-transport.md for the full contract.