import type { StandardSchemaV1 } from "@standard-schema/spec";
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<unknown, unknown>;
/**
 * Value or promise of that value.
 */
export type MaybePromise<T> = T | Promise<T>;
/**
 * Infer the parsed output type from a Standard Schema.
 */
export type InferSchemaOutput<T extends StandardSchemaV1> = StandardSchemaV1.InferOutput<T>;
/**
 * Minimal notification definition shape accepted by notification ports.
 */
export interface NotificationPayloadDef<Name extends string = string, Payload extends StandardSchema = StandardSchema> {
    /**
     * 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 extends NotificationPayloadDef> = N["payload"] extends StandardSchemaV1<unknown, infer Output> ? 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<string, unknown>;
}
/**
 * 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<Payload extends StandardSchema, Ctx> {
    /**
     * Notification definition being delivered.
     */
    notification: NotificationDef<string, Payload, Ctx>;
    /**
     * Parsed notification payload.
     */
    payload: InferSchemaOutput<Payload>;
    /**
     * Handler context.
     */
    ctx: Ctx;
    /**
     * Channel name being delivered.
     */
    channel: string;
}
/**
 * Handler for one notification channel.
 */
export type NotificationChannelHandler<Payload extends StandardSchema, Ctx> = (args: NotificationChannelHandleArgs<Payload, Ctx>) => MaybePromise<NotificationChannelResult | undefined>;
/**
 * Notification channel handlers keyed by channel name.
 */
export type NotificationChannels<Payload extends StandardSchema, Ctx> = Record<string, NotificationChannelHandler<Payload, Ctx>>;
/**
 * Arguments passed to an app-owned notification preference evaluator.
 */
export interface NotificationPreferenceArgs<Payload extends StandardSchema = StandardSchema, Ctx = unknown> extends NotificationChannelHandleArgs<Payload, Ctx> {
    /**
     * Optional metadata supplied by the notification sender.
     */
    metadata?: Record<string, unknown>;
}
/**
 * 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<Ctx = unknown> {
    /**
     * Evaluate the current preference immediately before channel delivery.
     */
    evaluate(args: NotificationPreferenceArgs<StandardSchema, Ctx>): MaybePromise<NotificationPreferenceDecision>;
}
/**
 * Notification definition created by `defineNotification(...)`.
 */
export interface NotificationDef<Name extends string = string, Payload extends StandardSchema = StandardSchema, Ctx = unknown> extends NotificationPayloadDef<Name, Payload> {
    /**
     * Discriminator for notification definitions.
     */
    readonly kind: "notification";
    /**
     * Channel handlers that deliver the notification.
     */
    readonly channels: NotificationChannels<Payload, Ctx>;
}
/**
 * Options for declaring a typed notification.
 */
export interface DefineNotificationOptions<Payload extends StandardSchema, Ctx> {
    /**
     * Standard Schema payload validator.
     */
    payload: Payload;
    /**
     * Optional human-readable description for docs and tooling.
     */
    description?: string;
    /**
     * Channel handlers that deliver the notification.
     */
    channels: NotificationChannels<Payload, Ctx>;
}
/**
 * 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<string, unknown>;
    /**
     * 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<N extends NotificationDef>(notification: N, payload: InferNotificationPayload<N>, options?: SendNotificationOptions): Promise<SendNotificationResult>;
}
/**
 * Options for the inline notification dispatcher.
 */
export interface InlineNotificationDispatcherOptions<Ctx> {
    /**
     * Static notification context or factory evaluated for each send.
     */
    ctx?: Ctx | (() => MaybePromise<Ctx>);
    /**
     * 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<StandardSchema, Ctx>) => MaybePromise<NotificationChannelResult | undefined>;
    /**
     * 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<Ctx>;
    /**
     * 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<string, unknown>;
    /**
     * 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<void>;
}
/**
 * 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<Payload extends StandardSchema, Ctx extends MailNotificationContext> = (args: NotificationChannelHandleArgs<Payload, Ctx>) => MaybePromise<SendMailOptions | undefined>;
/**
 * Context-bound notification helper factory.
 */
export interface Notifications<Ctx> {
    /**
     * Define a notification with the bound context type.
     */
    defineNotification<Name extends string, Payload extends StandardSchema>(name: Name, options: DefineNotificationOptions<Payload, Ctx>): NotificationDef<Name, Payload, Ctx>;
}
/**
 * Notification definitions available to durable delivery workers.
 */
export interface NotificationRegistry<Ctx = unknown> {
    /**
     * Registered definitions in declaration order.
     */
    readonly definitions: readonly NotificationDef<string, StandardSchema, Ctx>[];
    /**
     * Resolve a notification definition by its stable name.
     */
    get(name: string): NotificationDef<string, StandardSchema, Ctx> | undefined;
}
/**
 * Payload carried by the first-party notification delivery job.
 */
export interface NotificationDeliveryJobPayload {
    notificationName: string;
    channel: string;
    payload: unknown;
    options: Omit<SendNotificationOptions, "channels">;
}
type NotificationDeliveryPayloadSchema = StandardSchemaV1<unknown, NotificationDeliveryJobPayload>;
/**
 * Job definition used by queued notification dispatchers and workers.
 */
export interface NotificationDeliveryJob<Name extends string = string, Ctx = unknown> extends JobDef<Name, NotificationDeliveryPayloadSchema, Ctx> {
    /**
     * Registry used by both enqueue-time checks and worker delivery.
     */
    readonly registry: NotificationRegistry<Ctx>;
}
/**
 * Options for the first-party notification delivery job.
 */
export interface DefineNotificationDeliveryJobOptions<Name extends string, Ctx> {
    /**
     * Stable job name. Defaults to `"notifications.deliver"`.
     */
    name?: Name;
    /**
     * Notification definitions available to the worker.
     */
    registry: NotificationRegistry<Ctx>;
    /**
     * Optional app-owned preferences evaluated when the job runs.
     */
    preferences?: NotificationPreferencesPort<Ctx>;
    /**
     * 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<JobDef<Name, NotificationDeliveryPayloadSchema, Ctx>, Ctx>[];
}
/**
 * Options for a notification dispatcher backed by Beignet jobs.
 */
export interface QueuedNotificationDispatcherOptions<Name extends string, Ctx> {
    /**
     * Job dispatcher used to enqueue one delivery job per channel.
     */
    jobs: JobDispatcher;
    /**
     * Registered notification delivery job.
     */
    deliveryJob: NotificationDeliveryJob<Name, Ctx>;
    /**
     * 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<Ctx>(definitions: readonly NotificationDef<string, StandardSchema, Ctx>[]): NotificationRegistry<Ctx>;
/**
 * 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<Ctx, Name extends string = "notifications.deliver">(options: DefineNotificationDeliveryJobOptions<Name, Ctx>): NotificationDeliveryJob<Name, Ctx>;
/**
 * Validate and parse a notification payload with the notification's Standard
 * Schema.
 */
export declare function parseNotificationPayload<N extends NotificationPayloadDef>(notification: N, payload: unknown): Promise<InferNotificationPayload<N>>;
/**
 * 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<Ctx>(options?: InlineNotificationDispatcherOptions<Ctx>): NotificationPort;
/**
 * Options for the inline notifications provider.
 */
export interface InlineNotificationsProviderOptions extends Omit<InlineNotificationDispatcherOptions<unknown>, "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<unknown, StandardSchemaV1<void, void>, {
    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<Name extends string, Ctx>(options: QueuedNotificationDispatcherOptions<Name, Ctx>): NotificationPort;
/**
 * Options for the queued notifications provider.
 */
export interface QueuedNotificationsProviderOptions<Name extends string, Ctx> {
    /**
     * Registered notification delivery job.
     */
    deliveryJob: NotificationDeliveryJob<Name, Ctx>;
    /**
     * Provider name. Defaults to `"queued-notifications"`.
     */
    name?: string;
}
/**
 * Create a provider that contributes a job-backed notification dispatcher.
 */
export declare function createQueuedNotificationsProvider<Name extends string, Ctx>(options: QueuedNotificationsProviderOptions<Name, Ctx>): import("../providers/provider.js").ServiceProvider<{
    jobs: JobDispatcher;
}, StandardSchemaV1<void, void>, {
    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<Payload extends StandardSchema, Ctx extends MailNotificationContext>(render: MailNotificationRenderer<Payload, Ctx>): NotificationChannelHandler<Payload, Ctx>;
/**
 * 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<AppContext>();
 * ```
 *
 * 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<Ctx>(): Notifications<Ctx>;
export {};
//# sourceMappingURL=index.d.ts.map