Notifications Module
The Notifications Module (@ever-works/agent/notifications) provides a complete notification system for delivering in-app messages to users. It supports notification creation with deduplication, read/dismiss tracking, persistent notifications, and automated cleanup.
Module Structure
packages/agent/src/notifications/
├── index.ts # Barrel exports
├── notifications.module.ts # NestJS module definition
└── notification.service.ts # NotificationService (core logic)
Architecture
NotificationService
The @Injectable() service that manages the full notification lifecycle.
Creating Notifications
async create(dto: CreateNotificationDto): Promise<Notification>
Creates a notification with optional deduplication. When a deduplicationKey is provided, the service checks for an existing active notification with the same key:
- If found and not dismissed: updates the existing notification (refreshes
updatedAt) - If none found: creates a new notification
- Race conditions are handled with a try-catch fallback to fetch-existing
CreateNotificationDto fields:
| Field | Type | Required | Description |
|---|---|---|---|
userId | string | Yes | Target user |
title | string | Yes | Notification title |
message | string | Yes | Notification body |
type | NotificationType | Yes | info, warning, error, success |
category | NotificationCategory | Yes | ai_credits, subscription, generation, system, security |
deduplicationKey | string | No | Prevents duplicate notifications |
persistent | boolean | No | Survives read/dismiss until explicitly cleared |
expiresAt | Date | No | Auto-expiration timestamp |
actionUrl | string | No | Link to relevant page |
metadata | Record<string, unknown> | No | Arbitrary structured data |
Querying Notifications
| Method | Signature | Description |
|---|---|---|
getNotifications | (userId, options?) => Promise<{ items, total }> | Paginated notification list with optional category/type filtering |
getUnreadCount | (userId) => Promise<number> | Count of unread notifications |
getPersistentNotifications | (userId, category?) => Promise<Notification[]> | Active persistent notifications (not dismissed, not expired) |
NotificationQueryOptions:
interface NotificationQueryOptions {
page?: number; // Default: 1
limit?: number; // Default: 20
category?: NotificationCategory;
type?: NotificationType;
isRead?: boolean;
}