# @zerotal/notifications — public API surface

<!-- AUTO-GENERATED by scripts/api-surface.ts. Do not edit by hand.
     Run `bun run api:surface` to regenerate after an intentional API change. -->

> Not a guide — this is a flat, alphabetical snapshot used to detect unintended
> API changes. For how to use these, read the [documentation](https://zerotal.dev/docs).

## .  `(./src/index.ts)`

class BroadcastChannel = {
  new (): BroadcastChannel
  channelFor: (notifiable: Notifiable) => string
  send: (notifiable: Notifiable, notification: Notification) => Promise<void>
}

class BroadcastMessage = {
  new (data: Record<string, unknown>): BroadcastMessage
  onQueue: (queue: string) => BroadcastMessage
  queue: string | undefined
  readonly data: Record<string, unknown>
}

class DatabaseChannel = {
  new (table: string, _sql: SQLInstance): DatabaseChannel
  _count: () => Promise<number>
  all: (notifiable: Notifiable, query?: InboxQuery) => Promise<NotificationRecord[]>
  clear: (notifiable: Notifiable) => Promise<void>
  delete: (id: string) => Promise<void>
  markAllAsRead: (notifiable: Notifiable) => Promise<void>
  markAsRead: (id: string) => Promise<void>
  markAsUnread: (id: string) => Promise<void>
  prune: (days: number, includeUnread?: boolean) => Promise<number>
  recent: (limit?: number) => Promise<NotificationRecord[]>
  send: (notifiable: Notifiable, notification: Notification) => Promise<void>
  unread: (notifiable: Notifiable, query?: InboxQuery) => Promise<NotificationRecord[]>
  unreadCount: (notifiable: Notifiable) => Promise<number>
}

class LogDriver = {
  new (_channel?: 'console' | string): LogDriver
  send: (message: MailPayload) => Promise<void>
}

class MailChannel = {
  new (config: MailConfigShape): MailChannel
  send: (notifiable: Notifiable, notification: Notification) => Promise<void>
}

class MailMessage = {
  new (): MailMessage
  action: (text: string, url: string) => MailMessage
  attach: (attachment: MailAttachment) => MailMessage
  attachFile: (path: string, options?: {    filename?: string;    contentType?: string;}) => Promise<MailMessage>
  bcc: (address: AddressInput | AddressInput[]) => MailMessage
  cc: (address: AddressInput | AddressInput[]) => MailMessage
  embed: (cid: string, attachment: Omit<MailAttachment, 'cid' | 'inline'>) => MailMessage
  from: (address: AddressInput) => MailMessage
  greeting: {    (text: string): MailMessage;    (text: string, style: TextStyle): MailMessage;    (build: (t: RichLine) => void): MailMessage;}
  header: (name: string, value: string) => MailMessage
  html: (content: string) => MailMessage
  line: {    (text: string): MailMessage;    (text: string, style: TextStyle): MailMessage;    (build: (t: RichLine) => void): MailMessage;}
  replyTo: (address: AddressInput) => MailMessage
  salutation: {    (text: string): MailMessage;    (text: string, style: TextStyle): MailMessage;    (build: (t: RichLine) => void): MailMessage;}
  subject: (text: string) => MailMessage
  text: (content: string) => MailMessage
  to: (address: AddressInput | AddressInput[]) => MailMessage
  toPayload: (defaultFrom: MailAddress, fallbackTo: MailAddress[]) => MailPayload
}

class MessageFailed = {
  new (className: string, to: string[], subject: string, durationMs: number, error: string): MessageFailed
  readonly className: string
  readonly durationMs: number
  readonly error: string
  readonly subject: string
  readonly to: string[]
}

class MessageQueued = {
  new (className: string, to: string[], subject: string, queue: string): MessageQueued
  readonly className: string
  readonly queue: string
  readonly subject: string
  readonly to: string[]
}

class MessageSent = {
  new (className: string, to: string[], subject: string, html: string, durationMs: number, queued: boolean): MessageSent
  readonly className: string
  readonly durationMs: number
  readonly html: string
  readonly queued: boolean
  readonly subject: string
  readonly to: string[]
}

class Notification = {
  new (): Notification
  broadcastType: () => string
  channels: (notifiable?: Notifiable) => string[]
  payload: () => Record<string, unknown>
  toBroadcast: (_notifiable: Notifiable) => BroadcastMessage | Record<string, unknown> | Promise<BroadcastMessage | Record<string, unknown>>
  toDatabase: (_notifiable: Notifiable) => Record<string, unknown> | Promise<Record<string, unknown>>
  toMail: (_notifiable: Notifiable) => MailMessage | Promise<MailMessage>
  toSlack: (_notifiable: Notifiable) => SlackMessage | Promise<SlackMessage>
  toSms: (_notifiable: Notifiable) => SmsMessage | Promise<SmsMessage>
}

class NotificationChannelNotConfiguredError = {
  new (channel: string, hint?: string): NotificationChannelNotConfiguredError
  readonly code: string
  readonly context?: Record<string, unknown> | undefined
  readonly status: number
}

class NotificationChannelUnavailableError = {
  new (message: string): NotificationChannelUnavailableError
  readonly code: string
  readonly context?: Record<string, unknown> | undefined
  readonly status: number
}

class NotificationConfigError = {
  new (message: string, context?: Record<string, unknown>): NotificationConfigError
  readonly code: string
  readonly context?: Record<string, unknown> | undefined
  readonly status: number
}

class NotificationContractError = {
  new (notification: string, method: string, channel: string): NotificationContractError
  readonly code: string
  readonly context?: Record<string, unknown> | undefined
  readonly status: number
}

class NotificationDeliveryError = {
  new (message: string, context?: Record<string, unknown>): NotificationDeliveryError
  readonly code: string
  readonly context?: Record<string, unknown> | undefined
  readonly status: number
}

class NotificationDispatchError = {
  new (notification: string, failures: Array<{ channel: string; error: Error; }>, delivered: string[]): NotificationDispatchError
  readonly code: string
  readonly context?: Record<string, unknown> | undefined
  readonly delivered: string[]
  readonly failures: {    channel: string;    error: Error;}[]
  readonly notification: string
  readonly status: number
}

class NotificationError = {
  new (message: string, code?: string, status?: number, context?: Record<string, unknown>): NotificationError
  readonly code: string
  readonly context?: Record<string, unknown> | undefined
  readonly status: number
}

class NotificationFake = {
  new (app: Application, original: Binding): NotificationFake
  static install: () => NotificationFake
  assertNotSentTo: <T extends Notification>(notifiable: Notifiable, NotificationClass: new (...args: never[]) => T) => void
  assertNothingSent: () => void
  assertQueued: <T extends Notification>(notifiable: Notifiable, NotificationClass: new (...args: never[]) => T) => void
  assertSentCount: (count: number) => void
  assertSentOn: <T extends Notification>(notifiable: Notifiable, NotificationClass: new (...args: never[]) => T, channel: string) => void
  assertSentTimes: <T extends Notification>(NotificationClass: new (...args: never[]) => T, count: number) => void
  assertSentTo: <T extends Notification>(notifiable: Notifiable, NotificationClass: new (...args: never[]) => T, callback?: (notification: T) => boolean) => void
  channels: () => string[]
  database: {    all(): Promise<NotificationRecord[]>;    unread(): Promise<NotificationRecord[]>;    unreadCount(): Promise<number>;    markAllAsRead(): Promise<void>;    markAsRead(): Promise<void>;    markAsUnread(): Promise<void>;    delete(): Promise<void>;    clear(): Promise<void>;}
  extend: () => NotificationFake
  queue: (notifiable: Notifiable, notification: Notification) => Promise<void>
  queueMany: (notifiables: Iterable<Notifiable>, notification: Notification) => Promise<void>
  restore: () => void
  route: (routes: OnDemandRoutes) => {    notify(notification: Notification): Promise<void>;    notifyLater(notification: Notification): Promise<void>;}
  send: (notifiable: Notifiable, notification: Notification) => Promise<void>
  sendMany: (notifiables: Iterable<Notifiable>, notification: Notification) => Promise<void>
  sent: () => CapturedNotification[]
  sentTo: (notifiable: Notifiable) => CapturedNotification[]
}

class NotificationManager = {
  new (config: NotificationConfigShape): NotificationManager
  channels: () => string[]
  database: DatabaseChannel
  extend: (channel: string, factory: ChannelResolver) => NotificationManager
  queue: (notifiable: Notifiable, notification: Notification) => Promise<void>
  queueMany: (notifiables: Iterable<Notifiable>, notification: Notification) => Promise<void>
  route: (routes: OnDemandRoutes) => {    notify(notification: Notification): Promise<void>;    notifyLater(notification: Notification): Promise<void>;}
  send: (notifiable: Notifiable, notification: Notification) => Promise<void>
  sendMany: (notifiables: Iterable<Notifiable>, notification: Notification) => Promise<void>
}

class NotificationProvider = {
  new (app: Application): NotificationProvider
  static dependsOn?: (new (app: Application) => ServiceProvider)[]
  static environments: AppEnvironment[]
  static priority?: number
  static provides: readonly ['notifications']
  devProcesses: () => DevProcessDefinition[]
  doctorChecks: () => DoctorCheck[]
  onBooted: () => Promise<void>
  onBooting: () => Promise<void>
  onRegister: () => void
  onRequestProcessed: (_ctx: HttpContext) => Promise<void>
  onRequestReceived: (_ctx: HttpContext) => Promise<void>
  onResponseSent: (_ctx: HttpContext) => Promise<void>
  onStarted: () => Promise<void>
  onStarting: () => Promise<void>
  onStopped: () => Promise<void>
  onStopping: () => Promise<void>
  replContext: () => Record<string, unknown>
}

class NotificationSent = {
  new (className: string, channel: string, notifiable: string, ok: boolean, durationMs: number, error?: string | undefined): NotificationSent
  readonly channel: string
  readonly className: string
  readonly durationMs: number
  readonly error?: string | undefined
  readonly notifiable: string
  readonly ok: boolean
}

class OnDemandNotifiable = {
  new (_routes: OnDemandRoutes): OnDemandNotifiable
  readonly email?: string
  readonly id: string
  readonly phone?: string
  receivesBroadcastNotificationsOn: () => string
  routeNotificationFor: (channel: string) => string | undefined
}

class ResendDriver = {
  new (_apiKey: string): ResendDriver
  send: (message: MailPayload) => Promise<void>
}

class RichLine = {
  new (): RichLine
  bold: (content: string) => RichLine
  color: (content: string, color: string) => RichLine
  italic: (content: string) => RichLine
  readonly segments: TextSegment[]
  size: (content: string, px: number) => RichLine
  styled: (content: string, style: TextStyle) => RichLine
  text: (content: string) => RichLine
}

class SlackChannel = {
  new (config?: { webhook?: string; }): SlackChannel
  send: (notifiable: Notifiable, notification: Notification) => Promise<void>
}

class SmsChannel = {
  new (config: SmsConfigShape): SmsChannel
  send: (notifiable: Notifiable, notification: Notification) => Promise<void>
}

class SmtpConnectionError = {
  new (message: string): SmtpConnectionError
  readonly code: string
  readonly context?: Record<string, unknown> | undefined
  readonly status: number
}

class SmtpDriver = {
  new (_host: string, _port: number, _username: string, _password: string, _secure?: boolean, _options?: { allowInsecureAuth?: boolean; rejectUnauthorized?: boolean; timeoutMs?: number; clientName?: string; }): SmtpDriver
  send: (message: MailPayload) => Promise<void>
}

class SmtpResponseError = {
  new (replyCode: number, replyText: string, expected: number[]): SmtpResponseError
  readonly code: string
  readonly context?: Record<string, unknown> | undefined
  readonly replyCode: number
  readonly replyText: string
  readonly status: number
}

class UnknownNotificationChannelError = {
  new (channel: string, known?: string[]): UnknownNotificationChannelError
  readonly code: string
  readonly context?: Record<string, unknown> | undefined
  readonly status: number
}

class UnknownNotificationTypeError = {
  new (type: string, known: string[]): UnknownNotificationTypeError
  readonly code: string
  readonly context?: Record<string, unknown> | undefined
  readonly status: number
}

class UnknownSmsDriverError = {
  new (driver: string): UnknownSmsDriverError
  readonly code: string
  readonly context?: Record<string, unknown> | undefined
  readonly status: number
}

const BROADCAST_NOTIFICATION_EVENT = 'notification'

const NotificationRegistry = {    _map: Map<string, NotificationClass>;    register(NotificationClass: NotificationClass): void;    resolve(className: string): NotificationClass | undefined;    all(): ReadonlyMap<string, NotificationClass>;}

const Notify = NotificationManager

const RESERVED_MAIL_HEADERS = readonly string[]

function channelStats = () => ChannelStat[]

function NotificationConfig = (options?: DeepPartial<NotificationConfigShape>) => NotificationConfigShape

function recentDeliveries = () => RecentDelivery[]

function resolveHeaders = (headers: Record<string, string>) => Record<string, string>

interface ChannelStat = {
  avgMs: number
  channel: string
  failed: number
  sent: number
}

interface InboxQuery = {
  limit?: number
  offset?: number
}

interface MailAddress = {
  address: string
  name?: string
}

interface MailAttachment = {
  cid?: string
  content: string | Uint8Array<ArrayBufferLike>
  contentType?: string
  filename: string
  inline?: boolean
}

interface MailConfigShape = {
  driver: 'log' | 'smtp' | 'resend'
  from: {    address: string;    name: string;}
  log: {    channel: 'console' | string;}
  resend: {    apiKey: string;}
  smtp: {    host: string;    port: number;    secure: boolean;    username: string;    password: string;    allowInsecureAuth?: boolean;    rejectUnauthorized?: boolean;    timeoutMs?: number;    clientName?: string;}
}

interface MailDriver = {
  send: (message: MailPayload) => Promise<void>
}

interface MailPayload = {
  attachments?: MailAttachment[]
  bcc?: MailAddress[]
  cc?: MailAddress[]
  from: MailAddress
  headers?: Record<string, string>
  html?: string
  replyTo?: MailAddress
  subject: string
  text?: string
  to: MailAddress[]
}

interface Notifiable = {
  email?: string
  id: string | number
  name?: string
  phone?: string
  receivesBroadcastNotificationsOn?: () => string
  routeNotificationFor?: (channel: string) => string | undefined
}

interface NotificationChannel = {
  send: (notifiable: Notifiable, notification: NotificationLike) => Promise<void>
}

interface NotificationConfigShape = {
  database: {    table: string;}
  mail: MailConfigShape
  slack?: {    webhook?: string;} | undefined
  sms?: SmsConfigShape | undefined
}

interface NotificationRecord = {
  created_at: string
  data: string
  id: string
  notifiable_id: string
  notifiable_type: string
  read_at: string | null
  type: string
}

interface OnDemandRoutes = {
  [key: string]: string | undefined
  broadcast?: string
  mail?: string
  slack?: string
  sms?: string
}

interface RecentDelivery = {
  at: number
  channel: string
  className: string
  durationMs: number
  error: string | undefined
  notifiable: string
  ok: boolean
}

interface SlackMessage = {
  blocks?: unknown[]
  text: string
  webhookUrl?: string
}

interface SmsConfigShape = {
  driver: 'twilio' | 'vonage'
  twilio?: TwilioConfigShape | undefined
  vonage?: VonageConfigShape | undefined
}

interface SmsMessage = {
  body: string
  from?: string
  to?: string
}

interface TextStyle = {
  bold?: boolean
  color?: string
  italic?: boolean
  size?: number
}

interface TwilioConfigShape = {
  accountSid: string
  authToken: string
  from: string
}

interface VonageConfigShape = {
  apiKey: string
  apiSecret: string
  from: string
}

type AddressInput = string | MailAddress

type NotificationClass = (new (...args: never[]) => Notification) & {    fromPayload?(data: Record<string, unknown>): Notification | Promise<Notification>;}
