89 lines
3.2 KiB
TypeScript
89 lines
3.2 KiB
TypeScript
import z from "zod";
|
|
|
|
/** Channel literals from `@suaveplan/notification-channel`, mirrored here so Zod can validate. */
|
|
const DispatcherChannelEnum = z.enum([
|
|
"email",
|
|
"sms",
|
|
"push",
|
|
"in_app",
|
|
"webhook",
|
|
"apn",
|
|
]);
|
|
|
|
/**
|
|
* APN configuration accepted at plugin-construction time. Mirrors the
|
|
* upstream `APNConfig` surface but is owned by the plugin's Zod
|
|
* boundary so the values arrive at the transport already validated.
|
|
*/
|
|
export const ApnConfigSchema = z.object({
|
|
cert: z.string().optional(),
|
|
key: z.string().optional(),
|
|
pfx: z.string().optional(),
|
|
passphrase: z.string().optional(),
|
|
token: z
|
|
.object({
|
|
key: z.string().min(1),
|
|
keyId: z.string().min(1),
|
|
teamId: z.string().min(1),
|
|
})
|
|
.optional(),
|
|
production: z.boolean().default(false),
|
|
defaultTopic: z.string().optional(),
|
|
address: z.string().optional(),
|
|
port: z.number().int().positive().optional(),
|
|
connectionRetryLimit: z.number().int().min(0).optional(),
|
|
requestTimeout: z.number().int().positive().optional(),
|
|
rejectUnauthorized: z.boolean().optional(),
|
|
});
|
|
export type ApnConfig = z.infer<typeof ApnConfigSchema>;
|
|
|
|
/**
|
|
* Plugin options accepted by `createNotificationsPlugin`.
|
|
*
|
|
* Every field has a default so a no-arg call
|
|
* (`createNotificationsPlugin()`) produces a fully-resolved
|
|
* `NotificationsPluginConfig`.
|
|
*/
|
|
export const NotificationsPluginOptionsSchema = z.object({
|
|
/** Mount prefix for the `/notifications` route group. */
|
|
basePath: z.string().min(1).default("/notifications"),
|
|
/** Mount prefix for the `/push` route group. */
|
|
pushBasePath: z.string().min(1).default("/push"),
|
|
/** Enable APN push delivery (registers the APN service). */
|
|
enablePush: z.boolean().default(false),
|
|
/** APN-specific config; required only when `enablePush === true`. */
|
|
apn: ApnConfigSchema.optional(),
|
|
/** Auto-clean read notifications older than N days (0 disables). */
|
|
autoCleanOldDays: z.number().int().min(0).default(30),
|
|
/** Maximum recipients accepted by `POST /push/send-bulk`. */
|
|
maxBulkRecipients: z.number().int().min(1).max(10000).default(1000),
|
|
/**
|
|
* Opt in to constructing a `NotificationDispatcher` that fans
|
|
* notifications across `notification-channel`-style delivery
|
|
* channels. Off by default — existing routes still call
|
|
* `apnService` directly.
|
|
*/
|
|
enableDispatcher: z.boolean().default(false),
|
|
/**
|
|
* Default delivery channel used by the dispatcher when an input
|
|
* does not specify one. Only consulted when `enableDispatcher` is
|
|
* on.
|
|
*/
|
|
defaultChannel: DispatcherChannelEnum.default("apn"),
|
|
/**
|
|
* Tenant id stamped on every `DeliveryEvent` emitted by the
|
|
* dispatcher. Required to make the events queryable per-tenant.
|
|
*/
|
|
deliveryTenantId: z.string().min(1).default("default"),
|
|
});
|
|
|
|
/** Resolved config used by the plugin runtime. */
|
|
export type NotificationsPluginConfig = z.infer<
|
|
typeof NotificationsPluginOptionsSchema
|
|
>;
|
|
|
|
/** Caller-facing config — every field optional. */
|
|
export type NotificationsPluginConfigInput = z.input<
|
|
typeof NotificationsPluginOptionsSchema
|
|
>;
|