Aviary
Channels

Channels

A channel is a transport — mail, database, Slack, and the real-time SSE / WebSocket channels. Import a channel's module and it registers itself; the notification's to<Channel>() method shapes the payload.

A channel is a transport: it takes a notification and delivers it over one medium — an email, a persisted row, a websocket push, a Slack message. A notification declares a channel by annotating a payload method with the channel's handle (@Mail(), @Database(), …); the channels are then inferred, and each channel reads that one to<Channel>() method for its payload.

For the conceptual split between channels (where it goes) and dispatchers (when it goes), see Channels vs. dispatchers.

Built-in channels

ChannelPackageHandle / decoratorReadsNotification interface
mail@dudousxd/nestjs-notifications-mailMail / @Mail()toMail()MailNotification
database@dudousxd/nestjs-notifications-databaseDatabase / @Database()toDatabase()DatabaseNotification
broadcast@dudousxd/nestjs-notifications-broadcastBroadcast / @Broadcast()toBroadcast()BroadcastNotification
slack@dudousxd/nestjs-notifications-slackSlack / @Slack()toSlack()SlackNotification
discord@dudousxd/nestjs-notifications-discordDiscord / @Discord()toDiscord()DiscordNotification
telegram@dudousxd/nestjs-notifications-telegramTelegram / @Telegram()toTelegram()TelegramNotification
teams@dudousxd/nestjs-notifications-teamsTeams / @Teams()toTeams()TeamsNotification
sse@dudousxd/nestjs-notifications-sseSse / @Sse()toSse()SseNotification
webhook@dudousxd/nestjs-notifications-webhookWebhook / @Webhook()toWebhook()WebhookNotification
sms@dudousxd/nestjs-notifications-smsSms / @Sms()toSms()SmsNotification
push@dudousxd/nestjs-notifications-pushPush / @Push()toPush()PushNotification

Each channel ships as its own package, so you only pull in what you send. The handle is both the method decorator that declares a payload (@Mail()) and a type-safe token you can return from via() — see Notifications.

Real-time / in-app delivery

sse and broadcast aren't just two more transports — they're how you deliver notifications live, into your app: the unread badge, the feed that updates without a refresh. SSE (native NestJS Server-Sent Events) is the lightweight default; broadcast uses socket.io when you want a WebSocket. Pair either with the persisted database channel — see the Real-time & in-app guide.

Registration is just an import

There is no channels array to maintain. Each *ChannelModule.forRoot() provides a ChannelDriver, and the core finds it through Nest's DiscoveryService at startup. Import the module once in your root module and the channel is live — usable from any notification via its decorator handle.

app.module.ts
import { NotificationsModule } from '@dudousxd/nestjs-notifications-core';
import { MailChannelModule } from '@dudousxd/nestjs-notifications-mail';
import { SlackChannelModule } from '@dudousxd/nestjs-notifications-slack';

@Module({
  imports: [
    NotificationsModule.forRoot(),
    MailChannelModule.forRoot({ from: 'no-reply@example.com' }),
    SlackChannelModule.forRoot({ webhookUrl: process.env.SLACK_WEBHOOK_URL }),
  ],
})
export class AppModule {}

Every channel module is global: true by default, so a single registration in the root module makes it discoverable app-wide. Set global: false to scope it to the importing module.

When a payload method is missing

If via() routes a notification to a channel but the notification doesn't implement that channel's method, the channel throws a MissingChannelMethodError at send time:

Notification "InvoicePaid" is routed to the "mail" channel but does not implement
toMail(). Implement it to define the channel payload.

Implement the channel's notification interface (MailNotification, SlackNotification, …) to turn that runtime error into a compile-time one.

Routing a channel that no module registered throws a different error — ChannelNotRegisteredError — which lists the channels that are registered. That usually means you forgot to import the channel's module.

Build your own

Need a channel that isn't built in? A channel is just a class with a channel name and a send() method. See Writing a custom channel.

On this page