Files
zod-backend/src/common/modules/notification/services/notifications.service.ts
2025-08-23 21:52:59 +03:00

77 lines
3.0 KiB
TypeScript

import { forwardRef, Inject, Injectable, Logger } from '@nestjs/common';
import { RedisPubSubService } from '~/common/redis/services';
import { PageOptionsRequestDto } from '~/core/dtos';
import { OTP_BODY, OTP_TITLE } from '../../otp/constants';
import { OtpType } from '../../otp/enums';
import { ISendOtp } from '../../otp/interfaces';
import { SendEmailRequestDto } from '../dtos/request';
import { Notification } from '../entities';
import { EventType, NotificationChannel, NotificationScope } from '../enums';
import { NotificationsRepository } from '../repositories';
@Injectable()
export class NotificationsService {
private readonly logger = new Logger(NotificationsService.name);
constructor(
private readonly notificationRepository: NotificationsRepository,
@Inject(forwardRef(() => RedisPubSubService))
private readonly redisPubSubService: RedisPubSubService,
) {}
async getNotifications(userId: string, pageOptionsDto: PageOptionsRequestDto) {
this.logger.log(`Getting notifications for user ${userId}`);
const [[notifications, count], unreadCount] = await Promise.all([
this.notificationRepository.getNotifications(userId, pageOptionsDto),
this.notificationRepository.getUnreadNotificationsCount(userId),
]);
this.logger.log(`Returning notifications for user ${userId}`);
return { notifications, count, unreadCount };
}
createNotification(notification: Partial<Notification>) {
this.logger.log(`Creating notification for user ${notification.userId}`);
return this.notificationRepository.createNotification(notification);
}
markAsRead(userId: string) {
this.logger.log(`Marking notifications as read for user ${userId}`);
return this.notificationRepository.markAsRead(userId);
}
async sendEmailAsync(data: SendEmailRequestDto) {
this.logger.log(`emitting ${EventType.NOTIFICATION_CREATED} event`);
const notification = await this.createNotification({
recipient: data.to,
title: data.subject,
message: '',
scope: NotificationScope.USER_INVITED,
channel: NotificationChannel.EMAIL,
});
// return this.redisPubSubService.emit(EventType.NOTIFICATION_CREATED, notification, data.data);
this.redisPubSubService.publishEvent(EventType.NOTIFICATION_CREATED, {
...notification,
data,
});
}
async sendOtpNotification(sendOtpRequest: ISendOtp, otp: string) {
this.logger.log(`Sending OTP to ${sendOtpRequest.recipient}`);
const notification = await this.createNotification({
recipient: sendOtpRequest.recipient,
title: OTP_TITLE,
message: OTP_BODY.replace('{otp}', otp),
scope: NotificationScope.OTP,
channel: sendOtpRequest.otpType === OtpType.EMAIL ? NotificationChannel.EMAIL : NotificationChannel.SMS,
});
this.logger.log(`emitting ${EventType.NOTIFICATION_CREATED} event`);
return this.redisPubSubService.publishEvent(EventType.NOTIFICATION_CREATED, {
...notification,
data: { otp },
});
}
}