<!-- GENERATED — do not edit. Regenerate with: npm run docs:signatures -->

# @fonderie/courier — signatures

## @fonderie/courier

Subpath exports: `@fonderie/courier/types`, `@fonderie/courier/migrations`, `@fonderie/courier/env.json`

```ts
new CourierModule(config: ICourierConfig, store?: IStoreAdapter | undefined, bus?: EventBus | undefined): CourierModule
  .name: "@fonderie/courier"
  .version: string
  .deps: string[]
  .dispatcher: Dispatcher
  .describeAdmin(): IAdminDescription
  .checkReadiness(): IReadinessProblem[]
  .install(app: IFonderieApp): void

function validateCourierConfig(config: ICourierConfig, registeredChannels: Iterable<string>): void

function handleSendGridDelivery(req: Request, store: IStoreAdapter, publicKey?: string | undefined): Promise<Response>

function handleMailgunDelivery(req: Request, store: IStoreAdapter, signingKey?: string | undefined): Promise<Response>

function handleMailtrapDelivery(req: Request, store: IStoreAdapter): Promise<Response>

new Dispatcher(config: ICourierConfig, resolver: ITemplateResolver, store?: IStoreAdapter | undefined): Dispatcher
  .setLocales(locales: ILocaleSettings): void
  .registerChannel(channel: ICourierChannel): Dispatcher
  .channelNames(): string[]
  .dispatch(message: ICourierMessage): Promise<void>

function messageStats(store: IStoreAdapter, options?: { hours?: number; }): Promise<IMessageStats>

interface IMessageStats {
    sent: number;
    failed: number;
    pending: number;
    sentAt: Date | null;
    failedAt: Date | null;
    lastError: string | null;
}

function accountEraser(store: IStoreAdapter): ICourierAccountEraser

interface ICourierAccountEraser {
    readonly name: 'courier';
    erase(subject: ICourierErasureSubject): Promise<ICourierErasureResult>;
}

interface ICourierErasureResult {
    erased: number;
    kept?: string;
}

interface ICourierErasureSubject {
    userId: string;
    email: string | null;
    phone: string | null;
}

new SmsChannel(config: ISmsChannelConfig): SmsChannel
  .name: "sms"
  .send(message: ICourierMessage, template: IRenderedTemplate): Promise<void>

new PushChannel(config: IPushChannelConfig): PushChannel
  .name: "push"
  .send(message: ICourierMessage, template: IRenderedTemplate): Promise<void>

new EmailChannel(config: IEmailChannelConfig): EmailChannel
  .name: "email"
  .send(message: ICourierMessage, template: IRenderedTemplate): Promise<void | ISendResult>

new DBTemplateResolver(store: IStoreAdapter, defaults?: DefaultTemplates | undefined): DBTemplateResolver
  .setLocales(settings: ILocaleSettings): void
  .resolve(type: string, data: Record<string, unknown>, locale?: string | undefined): Promise<IRenderedTemplate>

new FSTemplateResolver(directory: string, defaults?: DefaultTemplates | undefined): FSTemplateResolver
  .setLocales(settings: ILocaleSettings): void
  .resolve(type: string, data: Record<string, unknown>, locale?: string | undefined): Promise<IRenderedTemplate>

new DefaultTemplates(maps?: DefaultTemplateMap[]): DefaultTemplates
  .get(type: string): IDefaultTemplate | undefined
  .getLocalized(type: string, locale: string): { copy: IDefaultTemplateCopy; locale: string; } | undefined
  .languages(type: string): string[]
  .size: number
  .types(): string[]

function renderFragment(frag: { subject?: string | null; text: string; html?: string | null; }, layoutHtml: string | undefined, data: Record<string, unknown>, locale?: string | undefined): IRenderedTemplate

function getLayoutHtml(store: IStoreAdapter, locale?: string | undefined, settings?: ILocaleSettings): Promise<string | undefined>

function templateVariables(...parts: (string | null | undefined)[]): string[]

function setTemplate(opts: { type: string; text: string; locale?: string | null; subject?: string | null; html?: string | null; active?: boolean; ifVersion?: number; actor?: string; }, store: IStoreAdapter): Promise<...>

function rollbackTemplate(opts: { type: string; locale?: string | null; toVersion: number; actor?: string; }, store: IStoreAdapter): Promise<ITemplateEntry>

function listTemplateRevisions(type: string, locale: string | null, store: IStoreAdapter): Promise<ITemplateRevision[]>

function getTemplateEntry(type: string, locale: string | null, store: IStoreAdapter): Promise<ITemplateEntry | null>

function listTemplateEntries(store: IStoreAdapter): Promise<ITemplateEntry[]>

function deleteTemplate(type: string, locale: string | null, store: IStoreAdapter): Promise<boolean>

function buildTemplateAdminRoutes(store: IStoreAdapter, adminToken: string, opts?: ITemplateAdminOptions): RouteRow[]

interface ITemplateAdminOptions {
    brandName?: string;
    systemTypes?: Iterable<string>;
    locales?: () => ILocaleSettings;
    defaults?: DefaultTemplates;
}

interface ITemplateEntry {
    type: string;
    locale: string | null;
    subject: string | null;
    html: string | null;
    text: string;
    active: boolean;
    version: number;
    updatedBy: string | null;
    updatedAt: string;
}

interface ITemplateRevision {
    type: string;
    locale: string | null;
    subject: string | null;
    html: string | null;
    text: string;
    version: number;
    actor: string | null;
    createdAt: string;
}

interface IMessageLog {
    id: string;
    messageType: string;
    channel: string;
    recipient: string;
    locale: string | null;
    resolvedLocale: string | null;
    status: MessageLogStatus;
    error: string | null;
    attempts: number;
    provider: string | null;
    providerMessageId: string | null;
    openedAt: string | null;
    clickedAt: string | null;
    bouncedAt: string | null;
    bounceReason: string | null;
    createdAt: string;
    sentAt: string | null;
}

type MessageLogStatus = 'pending' | 'sent' | 'failed' | 'delivered' | 'opened' | 'clicked' | 'bounced' | 'spam';

interface ICourierMessage {
    type: string;
    locale?: string;
    fallbackLocale?: string;
    recipient: {
        email: string | null;
        phone: string | null;
        deviceToken: string | null;
    };
    data: Record<string, unknown>;
}

interface ICourierChannel {
    name: string;
    send(message: ICourierMessage, template: IRenderedTemplate): Promise<ISendResult | void>;
}

interface IRenderedTemplate {
    subject?: string;
    html?: string;
    text: string;
    locale?: string;
}

interface ITemplateResolver {
    resolve(type: string, data: Record<string, unknown>, locale?: string): Promise<IRenderedTemplate>;
    setLocales?(settings: ILocaleSettings): void;
}

interface IDefaultTemplate {
    subject?: string;
    text: string;
    html?: string;
    locales?: Readonly<Record<string, IDefaultTemplateCopy>>;
}

type DefaultTemplateMap = Record<string, IDefaultTemplate>;

const Channel: { readonly EMAIL: "email"; readonly SMS: "sms"; readonly PUSH: "push"; }

interface ICourierConfig {
    channels: Record<string, Array<'email' | 'sms' | 'push'>>;
    sms?: ISmsChannelConfig;
    push?: IPushChannelConfig;
    email?: IEmailChannelConfig;
    brandName?: string;
    recipientLocaleLookup?: boolean;
    adminToken?: string;
    templates?: {
        source: 'db' | 'fs';
        directory?: string;
        defaults?: DefaultTemplateMap | DefaultTemplateMap[];
    };
    delivery?: {
        signingKeys?: {
            sendgrid?: string;
            mailgun?: string;
        };
        allowUnverifiedMailtrap?: boolean;
    };
}

interface IEmailChannelConfig {
    provider: 'resend' | 'ses' | 'smtp';
    from: string;
    replyTo?: string;
    senderDns?: {
        dkimSelectors?: string[];
        returnPathDomain?: string;
    };
    apiKey?: string;
    smtp?: {
        host: string;
        port: number;
        secure: boolean;
        user: string;
        pass: string;
    };
}

interface ISmsChannelConfig {
    provider: 'twilio' | 'vonage';
    from: string;
    accountSid?: string;
    authToken?: string;
    apiKey?: string;
    apiSecret?: string;
}

interface IPushChannelConfig {
    provider: 'fcm';
    serviceAccount: Record<string, unknown>;
}

function checkSenderDns(from: string, opts?: { dkimSelectors?: string[]; returnPathDomain?: string; resolveTxt?: ResolveTxt; }): Promise<ISenderDnsReport>

function describeSenderDnsProblems(report: ISenderDnsReport): string[]

function senderDnsCheck(email: { from: string; senderDns?: { dkimSelectors?: string[]; returnPathDomain?: string; }; }, resolveTxt?: ResolveTxt | undefined): IAdminCheck

function senderDomain(from: string): string | null

interface ISenderDnsRecord {
    reason?: string;
    metadata?: Record<string, string | number>;
    kind: 'spf' | 'dmarc' | 'dkim';
    present: boolean;
    foundAt?: string;
    value?: string;
    problem?: string;
    advice?: string;
    skipped?: boolean;
}

interface ISenderDnsReport {
    domain?: string;
    error?: string;
    records: ISenderDnsRecord[];
    ok: boolean;
}

type ResolveTxt = (hostname: string) => Promise<string[][]>;
```
