/** * @module * FallbackTransport — routes through an ordered list of transports, * advancing to the next when the current one fails. Use for provider * failover across email, SMS, WhatsApp, or push. Composes with * RetryTransport — wrap each entry in RetryTransport to retry within a * provider before failing over to the next. * * @example * ```ts * import { FallbackTransport } from "sently/transports/fallback"; * import { RetryTransport } from "sently/transports/retry"; * import { ResendTransport } from "sently/transports/resend"; * import { SESTransport } from "sently/transports/ses"; * * const transport = new FallbackTransport( * [ * new RetryTransport(new ResendTransport({ apiKey })), * new RetryTransport(new SESTransport({ accessKeyId, secretAccessKey })), * ], * { cooldownMs: 300_000 }, * ); * ``` */ import type { DecoratedTransport, FallbackAugmentedResult } from "../core/decorated-transport.js"; import { getProviderLabel } from "../core/provider-label.js"; import type { MailOptions, SendResult, VerifyResult } from "../core/types.js"; /** One failed provider attempt collected during failover. */ export interface FallbackAttempt { /** Provider label (e.g. `"resend"`, `"ses"`). */ provider: string; /** Error thrown by that transport. */ error: unknown; } /** Per-provider result from {@link FallbackTransport.verifyAll}. */ export interface FallbackProviderVerifyResult { /** Provider label. */ provider: string; /** Whether this provider verified successfully. */ ok: boolean; /** Human-readable status from the provider verify call. */ message?: string; } /** Result of verifying every transport in a fallback chain. */ export interface FallbackVerifyAllResult { /** True when at least one provider in the chain verified successfully. */ ok: boolean; /** Per-provider verify results in chain order. */ providers: FallbackProviderVerifyResult[]; } /** Options for {@link FallbackTransport} failover behavior. */ export interface FallbackOptions { /** * Decide whether a given error should trigger failover to the next * transport. Default: fail over on everything EXCEPT permanent client * errors (HTTP 400/401/403, SMTP permanent 5xx auth failures), since * those will fail identically on every provider. */ shouldFallback?: (error: unknown) => boolean; /** Optional callback fired before advancing to the next transport. */ onFallback?: (failedIndex: number, error: unknown) => void; /** * After a failed send, skip this provider until the cooldown expires (ms). * Prevents hammering a failing provider during an outage. */ cooldownMs?: number; /** Injectable clock for cooldown and testing. Default: `Date.now`. */ now?: () => number; /** * Shared cooldown state across fallback instances (e.g. {@link WeightedFallbackTransport}). * @internal */ cooldownState?: Map; } /** * Thrown when every transport in the chain fails. * {@link FallbackAttempt} entries record which provider failed and why. */ export declare class FallbackError extends Error { /** All failed attempts in order — which provider failed and why. */ readonly attempts: FallbackAttempt[]; /** Creates an error summarizing every failed transport attempt. */ constructor(attempts: FallbackAttempt[]); } /** @deprecated Use {@link getProviderLabel} from `sently/core` patterns. */ export declare const inferProviderLabel: typeof getProviderLabel; type MailerOnFallback = (failedProvider: string, nextProvider: string, error: unknown) => void | Promise; /** * Decorator transport that fails over through an ordered list of transports. * Defaults preserve email {@link Transport} compatibility. */ export declare class FallbackTransport implements DecoratedTransport> { private readonly transports; readonly provider = "fallback"; private readonly shouldFallback; private readonly onFallback?; private readonly cooldownMs; private readonly now; private readonly unhealthyUntil; private mailerOnFallback; /** * Creates a failover transport over an ordered list of backends. * @throws {Error} When the transports array is empty. */ constructor(transports: DecoratedTransport[], options?: FallbackOptions); /** * Register a per-send onFallback callback from sender lifecycle hooks. * @internal Cleared after each send. */ setMailerOnFallback(callback: MailerOnFallback | undefined): void; private isCoolingDown; private markUnhealthy; /** Sends through transports in order until one succeeds. */ send(message: TOptions): Promise>; private findNextTryIndex; /** * Returns the result of the first transport whose verify() returns `ok: true`. * Use {@link verifyAll} for full-chain visibility. */ verify(): Promise; /** Verifies every transport in the chain and returns per-provider results. */ verifyAll(): Promise; /** Calls close() on every transport; one failure does not block the others. */ close(): Promise; } export {};