90 lines
3.0 KiB
Markdown
90 lines
3.0 KiB
Markdown
# `plugin/plugin`
|
|
|
|
<!-- begin:auto-docs -->
|
|
_(no submodules)_
|
|
<!-- end:auto-docs -->
|
|
|
|
## Purpose
|
|
|
|
Plugin descriptor factory for `@suaveplan/api-plugin-notifications`.
|
|
Composes everything in the package — Zod-validated options,
|
|
SurrealDB-backed `NotificationRepository` and
|
|
`DeviceTokenRepository`, the optional `ApnService`, the two route
|
|
modules, and the OTel instrument bundle — into a single
|
|
`PluginDescriptor<NotificationsPluginConfig>` that hosts mount via
|
|
`@suaveplan/api-plugin`'s standard lifecycle.
|
|
|
|
## Features
|
|
|
|
- Boundary Zod validation — invalid options throw
|
|
`NotificationsPluginError(INVALID_CONFIG)` with the `ZodError`
|
|
attached as `cause`.
|
|
- Two-phase lifecycle: `onInit` registers repositories and the APN
|
|
service in the host's `ServiceRegistry`; `onReady` mounts both
|
|
route trees and refuses double-mount with
|
|
`ROUTE_PREFIX_COLLISION`.
|
|
- Event-bus integration — emits `notifications:initialized` and
|
|
`notifications:ready` on the shared `ctx.eventBus` so siblings
|
|
observe lifecycle transitions. Route-level events flow through a
|
|
single `forwarder` callback that the route modules call via
|
|
`emitEvent`.
|
|
- Optional APN — `enablePush: false` (default) skips APN
|
|
construction; `enablePush: true` without `config.apn` throws
|
|
`APN_CONFIG_MISSING` at boot.
|
|
- Graceful close — `onClose` shuts down the APN transport (if any)
|
|
and clears the repository references so the GC can collect them.
|
|
|
|
## Usage: Basic
|
|
|
|
```ts
|
|
import { createNotificationsPlugin } from "@suaveplan/api-plugin-notifications";
|
|
|
|
await api.loadPlugin(createNotificationsPlugin());
|
|
```
|
|
|
|
## Usage: Advanced
|
|
|
|
Enable push delivery with a token-auth APN config and a custom mount
|
|
prefix:
|
|
|
|
```ts
|
|
await api.loadPlugin(
|
|
createNotificationsPlugin({
|
|
basePath: "/v1/notifications",
|
|
pushBasePath: "/v1/push",
|
|
enablePush: true,
|
|
apn: {
|
|
token: {
|
|
key: "/keys/AuthKey_ABC.p8",
|
|
keyId: "ABC",
|
|
teamId: "TEAM",
|
|
},
|
|
defaultTopic: "com.example.app",
|
|
production: true,
|
|
},
|
|
maxBulkRecipients: 500,
|
|
autoCleanOldDays: 14,
|
|
})
|
|
);
|
|
```
|
|
|
|
## API Reference
|
|
|
|
- `createNotificationsPlugin(options?: NotificationsPluginConfigInput)` →
|
|
`PluginDescriptor<NotificationsPluginConfig>`
|
|
- Lifecycle hooks: `onInit(ctx)`, `onReady(ctx)`, `onClose()`.
|
|
- Service slots registered: `notificationRepository`,
|
|
`deviceTokenRepository`, `apnService` (only when `enablePush`).
|
|
- Event-bus emissions: `notifications:initialized`,
|
|
`notifications:ready`, plus every event in `NotificationsPluginEvents`.
|
|
|
|
## Implementation Notes
|
|
|
|
The plugin name is `"notifications"`. Dependencies are
|
|
`["database"]` — `onInit` will refuse to boot without an
|
|
`@suaveplan/api-plugin-database`-registered `db` slot. The plugin
|
|
calls `ctx.eventBus.emit(event.type, event.payload)` from a single
|
|
`forwarder` callback rather than dragging the `eventBus` reference
|
|
into every route handler. This matches the api-plugin-events pattern
|
|
and means route handlers stay testable in isolation.
|