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; /** * 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 >;