@nestbolt/notifications
Quick Start
Get up and running with @nestbolt/notifications in three steps -- register the module, create a notification, and send it.
This guide walks through a complete working example: registering the notification module, creating a notification class, setting up a notifiable entity, and sending your first notification.
Step 1: Register the Module
Import NotificationModule in your root AppModule and call forRoot() with your desired configuration. The module is registered globally, so you only need to import it once.
import { Module } from "@nestjs/common";
import { TypeOrmModule } from "@nestjs/typeorm";
import { NotificationModule } from "@nestbolt/notifications";
import { User } from "./users/user.entity";
@Module({
imports: [
TypeOrmModule.forRoot({
type: "postgres",
host: "localhost",
port: 5432,
username: "postgres",
password: "postgres",
database: "myapp",
entities: [User],
synchronize: true,
}),
NotificationModule.forRoot({
channels: {
database: true,
},
}),
],
})
export class AppModule {}This enables the database channel, which stores notifications in the notifications table. The mail channel and custom channels can be added later -- see Configuration.
Step 2: Create a Notifiable Entity
A "notifiable" is any TypeORM entity that can receive notifications. Apply the @Notifiable() decorator and extend NotifiableMixin(BaseEntity):
import { Entity, PrimaryGeneratedColumn, Column, BaseEntity } from "typeorm";
import { Notifiable, NotifiableMixin } from "@nestbolt/notifications";
@Entity("users")
@Notifiable()
export class User extends NotifiableMixin(BaseEntity) {
@PrimaryGeneratedColumn("uuid")
id!: string;
@Column()
name!: string;
@Column()
email!: string;
routeNotificationFor(channel: string): string | undefined {
if (channel === "mail") return this.email;
return undefined;
}
}The mixin adds methods like notify(), getNotifications(), unreadNotifications(), and more directly to your entity. See Notifiable Entities for the full API.
Step 3: Create a Notification Class
Define a notification by extending the Notification base class. Override via() to declare delivery channels, and implement a method for each channel:
import { Notification } from "@nestbolt/notifications";
export class WelcomeNotification extends Notification {
constructor(private user: { name: string }) {
super();
}
via(): string[] {
return ["database"];
}
toDatabase() {
return {
message: `Welcome to the platform, ${this.user.name}!`,
type: "welcome",
};
}
notificationType(): string {
return "WelcomeNotification";
}
}Step 4: Send the Notification
There are two ways to send notifications.
Option A: Via NotificationService
Inject NotificationService into any service or controller:
import { Injectable } from "@nestjs/common";
import { NotificationService } from "@nestbolt/notifications";
import { WelcomeNotification } from "./notifications/welcome.notification";
import { User } from "./users/user.entity";
@Injectable()
export class UserService {
constructor(private readonly notificationService: NotificationService) {}
async register(name: string, email: string): Promise<User> {
const user = new User();
user.name = name;
user.email = email;
await user.save();
await this.notificationService.send(
user,
new WelcomeNotification(user),
);
return user;
}
}Option B: Via the Entity Mixin
If your entity uses NotifiableMixin, you can call notify() directly on the entity instance:
await user.notify(new WelcomeNotification(user));This is functionally identical to calling notificationService.send().
Step 5: Query Notifications
After sending, you can query the user's notifications:
// Get all notifications
const notifications = await user.getNotifications();
// Get only unread notifications
const unread = await user.unreadNotifications();
// Get the unread count
const count = await user.getUnreadNotificationCount();
// Mark a notification as read
await user.markNotificationAsRead(notifications[0].id);
// Mark all as read
await user.markAllNotificationsAsRead();Or use NotificationService directly:
const notifications = await notificationService.getNotifications("User", user.id);
const unread = await notificationService.getUnreadNotifications("User", user.id);
const count = await notificationService.getUnreadCount("User", user.id);Complete Example
Here is a full working example combining all the pieces:
// notifications/order-shipped.notification.ts
import { Notification, MailMessage } from "@nestbolt/notifications";
interface Order {
id: string;
trackingUrl: string;
customerName: string;
}
export class OrderShippedNotification extends Notification {
constructor(private order: Order) {
super();
}
via(): string[] {
return ["database", "mail"];
}
toDatabase() {
return {
message: `Your order #${this.order.id} has been shipped.`,
orderId: this.order.id,
trackingUrl: this.order.trackingUrl,
};
}
toMail() {
return new MailMessage()
.subject("Your order has shipped!")
.greeting(`Hello ${this.order.customerName}`)
.line(`Great news -- your order #${this.order.id} is on its way.`)
.line("You can track your package using the link below.")
.action("Track Your Order", this.order.trackingUrl)
.salutation("Thank you for shopping with us");
}
}// orders/order.service.ts
import { Injectable } from "@nestjs/common";
import { NotificationService } from "@nestbolt/notifications";
import { OrderShippedNotification } from "../notifications/order-shipped.notification";
@Injectable()
export class OrderService {
constructor(private readonly notificationService: NotificationService) {}
async shipOrder(order: Order, customer: User): Promise<void> {
// ... shipping logic ...
await this.notificationService.send(
customer,
new OrderShippedNotification(order),
);
}
}Next Steps
- Configuration -- Explore
forRoot()andforRootAsync()options, including mail transport and custom channels. - Creating Notifications -- Learn about the full
Notificationbase class API. - Mail Channel -- Deep dive into the
MailMessagebuilder for rich emails.