import type { StandardSchemaV1 } from "@standard-schema/spec"; import type { ChannelDefinition } from "../broadcasting/index.js"; import type { BroadcastPort, BroadcastPublication } from "../broadcasting/server.js"; import { type JobDef, type JobDispatcher, type JobHook, type JobRetryOptions, type JobTimeoutDuration } from "../jobs/index.js"; import type { SendMailOptions } from "../mail/index.js"; import type { ProviderInstrumentationTarget } from "../providers/index.js"; /** * Any Standard Schema compatible validator. */ export type StandardSchema = StandardSchemaV1; /** * Value or promise of that value. */ export type MaybePromise = T | Promise; /** * Infer the parsed output type from a Standard Schema. */ export type InferSchemaOutput = StandardSchemaV1.InferOutput; /** * Minimal notification definition shape accepted by notification ports. */ export interface NotificationPayloadDef { /** * Stable notification name used by dispatchers, tests, and tooling. */ readonly name: Name; /** * Standard Schema payload validator. */ readonly payload: Payload; /** * Optional human-readable description for docs and tooling. */ readonly description?: string; } /** * Infer the parsed payload type for a notification definition. */ export type InferNotificationPayload = N["payload"] extends StandardSchemaV1 ? Output : never; /** * Result for one notification channel. */ export interface NotificationChannelResult { /** * Channel name, such as `email`, `sms`, `push`, or `inApp`. */ channel: string; /** * Delivery outcome for this channel. */ status: "queued" | "sent" | "skipped" | "failed"; /** * Provider delivery ID when available. */ id?: string; /** * Provider name when available. */ provider?: string; /** * Human-readable skip or failure reason. */ reason?: string; /** * Channel-specific metadata. Dispatchers should keep this safe to log. */ details?: Record; } /** * Original error captured for one failed notification channel. */ export interface NotificationChannelError { channel: string; error: unknown; } /** * Arguments passed to a notification channel handler. */ export interface NotificationChannelHandleArgs { /** * Notification definition being delivered. */ notification: NotificationDef; /** * Parsed notification payload. */ payload: InferSchemaOutput; /** * Handler context. */ ctx: Ctx; /** * Channel name being delivered. */ channel: string; } /** * Handler for one notification channel. */ export type NotificationChannelHandler = (args: NotificationChannelHandleArgs) => MaybePromise; /** * Notification channel handlers keyed by channel name. */ export type NotificationChannels = Record>; /** * Arguments passed to an app-owned notification preference evaluator. */ export interface NotificationPreferenceArgs extends NotificationChannelHandleArgs { /** * Optional metadata supplied by the notification sender. */ metadata?: Record; } /** * App-owned decision for one notification channel. */ export interface NotificationPreferenceDecision { /** * Whether this channel should deliver. */ deliver: boolean; /** * Optional reason recorded when delivery is skipped. */ reason?: string; } /** * Optional app-facing port for notification channel preferences and opt-outs. */ export interface NotificationPreferencesPort { /** * Evaluate the current preference immediately before channel delivery. */ evaluate(args: NotificationPreferenceArgs): MaybePromise; } /** * Notification definition created by `defineNotification(...)`. */ export interface NotificationDef extends NotificationPayloadDef { /** * Discriminator for notification definitions. */ readonly kind: "notification"; /** * Channel handlers that deliver the notification. */ readonly channels: NotificationChannels; } /** * Options for declaring a typed notification. */ export interface DefineNotificationOptions { /** * Standard Schema payload validator. */ payload: Payload; /** * Optional human-readable description for docs and tooling. */ description?: string; /** * Channel handlers that deliver the notification. */ channels: NotificationChannels; } /** * Options passed when sending a notification. */ export interface SendNotificationOptions { /** * Subset of channels to deliver. Defaults to all channels on the definition. */ channels?: readonly string[]; /** * Optional app metadata attached to memory deliveries and instrumentation. */ metadata?: Record; /** * Request correlation ID for instrumentation. */ requestId?: string; /** * Trace identifier for instrumentation. */ traceId?: string; /** * Span identifier for instrumentation. */ spanId?: string; /** * Parent span identifier for instrumentation. */ parentSpanId?: string; /** * W3C traceparent header value for instrumentation. */ traceparent?: string; } /** * Result returned after a notification send attempt. */ export interface SendNotificationResult { /** * Notification name. */ notificationName: string; /** * Parsed notification payload. */ payload: unknown; /** * Channels selected for delivery. */ channels: readonly string[]; /** * Per-channel delivery results. */ results: readonly NotificationChannelResult[]; } /** * App-facing notification port. */ export interface NotificationPort { /** * Send a typed notification. */ send(notification: N, payload: InferNotificationPayload, options?: SendNotificationOptions): Promise; } /** * Options for the inline notification dispatcher. */ export interface InlineNotificationDispatcherOptions { /** * Static notification context or factory evaluated for each send. */ ctx?: Ctx | (() => MaybePromise); /** * Called when a channel handler or preference check fails. A returned result * replaces the default failed result. Observer failures are ignored so the * remaining channels still run. */ onError?: (error: unknown, args: NotificationChannelHandleArgs) => MaybePromise; /** * How completed channel failures are surfaced. Defaults to `"report"`. * `"throw"` still runs every selected channel before rejecting. */ failureMode?: "report" | "throw"; /** * Optional app-owned notification preference evaluator. */ preferences?: NotificationPreferencesPort; /** * Optional devtools/provider instrumentation target. */ instrumentation?: ProviderInstrumentationTarget; } /** * Delivery captured by the memory notification port. */ export interface MemoryNotificationDelivery { /** * Generated delivery ID. */ id: string; /** * Notification name. */ notificationName: string; /** * Parsed payload that would have been sent. */ payload: unknown; /** * Selected channels. */ channels: readonly string[]; /** * Optional app metadata supplied by the caller. */ metadata?: Record; /** * Timestamp assigned by the memory port. */ sentAt: Date; } /** * In-memory notification port for tests and local examples. */ export interface MemoryNotificationPort extends NotificationPort { /** * Captured notification sends. */ readonly deliveries: readonly MemoryNotificationDelivery[]; /** * Clear captured notification sends. */ clear(): void; } /** * Options for `createMemoryNotificationPort(...)`. */ export interface CreateMemoryNotificationPortOptions { /** * Clock used for captured deliveries. */ now?: () => Date; /** * ID factory used for captured deliveries. */ id?: () => string; /** * Observer called after a delivery is captured. */ onSend?: (delivery: MemoryNotificationDelivery) => MaybePromise; } /** * Context shape required by `defineMailNotificationChannel(...)`. */ export interface MailNotificationContext { ports: { mailer: { send(message: SendMailOptions): MaybePromise<{ id?: string; provider?: string; }>; }; }; } /** * Render a mail message for one notification payload. */ export type MailNotificationRenderer = (args: NotificationChannelHandleArgs) => MaybePromise; /** * Context-bound notification helper factory. */ export interface Notifications { /** * Define a notification with the bound context type. */ defineNotification(name: Name, options: DefineNotificationOptions): NotificationDef; } /** * Notification definitions available to durable delivery workers. */ export interface NotificationRegistry { /** * Registered definitions in declaration order. */ readonly definitions: readonly NotificationDef[]; /** * Resolve a notification definition by its stable name. */ get(name: string): NotificationDef | undefined; } /** * Payload carried by the first-party notification delivery job. */ export interface NotificationDeliveryJobPayload { notificationName: string; channel: string; payload: unknown; options: Omit; } type NotificationDeliveryPayloadSchema = StandardSchemaV1; /** * Job definition used by queued notification dispatchers and workers. */ export interface NotificationDeliveryJob extends JobDef { /** * Registry used by both enqueue-time checks and worker delivery. */ readonly registry: NotificationRegistry; } /** * Options for the first-party notification delivery job. */ export interface DefineNotificationDeliveryJobOptions { /** * Stable job name. Defaults to `"notifications.deliver"`. */ name?: Name; /** * Notification definitions available to the worker. */ registry: NotificationRegistry; /** * Optional app-owned preferences evaluated when the job runs. */ preferences?: NotificationPreferencesPort; /** * Retry policy. Defaults to exponential backoff with three attempts. */ retry?: JobRetryOptions; /** * Optional maximum duration for each channel delivery attempt. */ timeout?: JobTimeoutDuration; /** * Optional execution hooks applied to each delivery attempt. */ hooks?: readonly JobHook, Ctx>[]; } /** * Options for a notification dispatcher backed by Beignet jobs. */ export interface QueuedNotificationDispatcherOptions { /** * Job dispatcher used to enqueue one delivery job per channel. */ jobs: JobDispatcher; /** * Registered notification delivery job. */ deliveryJob: NotificationDeliveryJob; /** * Optional devtools/provider instrumentation target. */ instrumentation?: ProviderInstrumentationTarget; } /** * Error thrown when notification payload validation fails. */ export declare class NotificationValidationError extends Error { /** * Raw Standard Schema validation issues. */ readonly issues: readonly StandardSchemaV1.Issue[]; constructor(args: { name: string; issues: readonly StandardSchemaV1.Issue[]; }); } /** * Error thrown when notification delivery fails. */ export declare class NotificationDeliveryError extends Error { /** * Notification name. */ readonly notificationName: string; /** * First channel that failed, retained for concise error handling. */ readonly channel: string; /** * Original error for the first failed channel when available. */ readonly cause: unknown; /** * Complete notification result after every selected channel ran. */ readonly result: SendNotificationResult; /** * Failed channel results. */ readonly failures: readonly NotificationChannelResult[]; /** * Original channel errors in delivery order. */ readonly errors: readonly NotificationChannelError[]; constructor(args: { result: SendNotificationResult; errors?: readonly NotificationChannelError[]; }); } /** * Error thrown when a notification registry cannot safely resolve a delivery. */ export declare class NotificationRegistryError extends Error { constructor(message: string); } /** * Define the notification catalog available to durable delivery workers. * Duplicate names throw because queued delivery resolves definitions by name. */ export declare function defineNotificationRegistry(definitions: readonly NotificationDef[]): NotificationRegistry; /** * Define the generic job that resolves and delivers one notification channel. * Register the returned job with every worker or outbox registry that can * receive queued notifications. */ export declare function defineNotificationDeliveryJob(options: DefineNotificationDeliveryJobOptions): NotificationDeliveryJob; /** * Validate and parse a notification payload with the notification's Standard * Schema. */ export declare function parseNotificationPayload(notification: N, payload: unknown): Promise>; /** * Create an inline notification dispatcher. * * The dispatcher validates payloads and runs selected channel handlers * immediately. Channel failures are isolated and reported after every selected * channel runs. Use this directly in tests and local apps, or use * `createQueuedNotificationDispatcher(...)` for background execution. */ export declare function createInlineNotificationDispatcher(options?: InlineNotificationDispatcherOptions): NotificationPort; /** * Options for the inline notifications provider. */ export interface InlineNotificationsProviderOptions extends Omit, "ctx" | "instrumentation"> { /** * Provider name. Defaults to "inline-notifications". */ name?: string; } /** * Ports contributed by the inline notifications provider. */ export interface InlineNotificationsProviderPorts { /** * Beignet notification port. */ notifications: NotificationPort; } /** * Create a provider that contributes an inline notification dispatcher. * * Use it as the dev-default `notifications` port in `server/providers.ts`. * Channel handlers run with an app service context built lazily through the * server context blueprint on each send, so the provider is safe to register * before all providers have started. Sends are recorded as devtools events * through the `notifications` watcher when an instrumentation port is * installed. */ export declare function createInlineNotificationsProvider(options?: InlineNotificationsProviderOptions): import("../providers/provider.js").ServiceProvider, { notifications: NotificationPort; }, unknown, void>; /** * Create a notification dispatcher that enqueues one delivery job per channel. * Separate jobs keep provider retries from resending channels that already * completed successfully. */ export declare function createQueuedNotificationDispatcher(options: QueuedNotificationDispatcherOptions): NotificationPort; /** * Options for the queued notifications provider. */ export interface QueuedNotificationsProviderOptions { /** * Registered notification delivery job. */ deliveryJob: NotificationDeliveryJob; /** * Provider name. Defaults to `"queued-notifications"`. */ name?: string; } /** * Create a provider that contributes a job-backed notification dispatcher. */ export declare function createQueuedNotificationsProvider(options: QueuedNotificationsProviderOptions): import("../providers/provider.js").ServiceProvider<{ jobs: JobDispatcher; }, StandardSchemaV1, { notifications: NotificationPort; }, unknown, void>; /** * Define a mail-backed notification channel. * * Return `undefined` from the renderer when the channel should be skipped, for * example when a recipient does not have an email address. */ export declare function defineMailNotificationChannel(render: MailNotificationRenderer): NotificationChannelHandler; /** Deliver a typed browser hint through the existing notification delivery pipeline. * `sent` means provider acceptance, including when the recipient is offline. * Return undefined to skip. Persistent inbox writes and their outbox ordering belong to the app. */ export declare function defineBroadcastNotificationChannel(options: { channel: C; render: (args: NotificationChannelHandleArgs) => MaybePromise> | undefined>; }): NotificationChannelHandler; /** * Create an in-memory notification port for tests and examples. * * The memory port validates payloads and records notification intent without * running channel handlers. */ export declare function createMemoryNotificationPort(options?: CreateMemoryNotificationPortOptions): MemoryNotificationPort; /** * Create notification helper methods bound to an application context type. * * Call it once in `lib/notifications.ts`: * * ```ts * export const { defineNotification } = createNotifications(); * ``` * * Notifications represent user-facing communication intent. Channel handlers * decide how that intent becomes mail, SMS, push, in-app delivery, or another * app-owned channel. */ export declare function createNotifications(): Notifications; export {}; //# sourceMappingURL=index.d.ts.map