mirror of
https://github.com/HamzaSha1/zod-backend.git
synced 2025-08-26 06:09:41 +00:00
feat: handle notification async using event emitter
This commit is contained in:
3
src/common/modules/notification/enums/event-type.enum.ts
Normal file
3
src/common/modules/notification/enums/event-type.enum.ts
Normal file
@ -0,0 +1,3 @@
|
||||
export enum EventType {
|
||||
NOTIFICATION_CREATED = 'NOTIFICATION_CREATED',
|
||||
}
|
@ -1,3 +1,4 @@
|
||||
export * from './event-type.enum';
|
||||
export * from './notification-channel.enum';
|
||||
export * from './notification-scope.enum';
|
||||
export * from './notification-status.enum';
|
||||
|
@ -2,4 +2,5 @@ export enum NotificationScope {
|
||||
USER_REGISTERED = 'USER_REGISTERED',
|
||||
TASK_COMPLETED = 'TASK_COMPLETED',
|
||||
GIFT_RECEIVED = 'GIFT_RECEIVED',
|
||||
OTP = 'OTP',
|
||||
}
|
||||
|
@ -0,0 +1,3 @@
|
||||
export class NotificationEvent {
|
||||
constructor(public readonly notification: Notification) {}
|
||||
}
|
@ -13,11 +13,11 @@ import { TwilioService } from './services/twilio.service';
|
||||
@Module({
|
||||
imports: [
|
||||
TypeOrmModule.forFeature([Notification]),
|
||||
AuthModule,
|
||||
TwilioModule.forRootAsync({
|
||||
useFactory: buildTwilioOptions,
|
||||
inject: [ConfigService],
|
||||
}),
|
||||
AuthModule,
|
||||
],
|
||||
providers: [NotificationsService, FirebaseService, NotificationsRepository, TwilioService],
|
||||
exports: [NotificationsService],
|
||||
|
@ -1,7 +1,12 @@
|
||||
import { Injectable } from '@nestjs/common';
|
||||
import { forwardRef, Inject, Injectable } from '@nestjs/common';
|
||||
import { EventEmitter2, OnEvent } from '@nestjs/event-emitter';
|
||||
import { DeviceService } from '~/auth/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 { Notification } from '../entities';
|
||||
import { EventType, NotificationChannel, NotificationScope } from '../enums';
|
||||
import { NotificationsRepository } from '../repositories';
|
||||
import { FirebaseService } from './firebase.service';
|
||||
import { TwilioService } from './twilio.service';
|
||||
@ -9,10 +14,11 @@ import { TwilioService } from './twilio.service';
|
||||
@Injectable()
|
||||
export class NotificationsService {
|
||||
constructor(
|
||||
private readonly deviceService: DeviceService,
|
||||
private readonly firebaseService: FirebaseService,
|
||||
private readonly notificationRepository: NotificationsRepository,
|
||||
private readonly twilioService: TwilioService,
|
||||
private readonly eventEmitter: EventEmitter2,
|
||||
@Inject(forwardRef(() => DeviceService)) private readonly deviceService: DeviceService,
|
||||
) {}
|
||||
|
||||
async sendPushNotification(userId: string, title: string, body: string) {
|
||||
@ -47,4 +53,26 @@ export class NotificationsService {
|
||||
markAsRead(userId: string) {
|
||||
return this.notificationRepository.markAsRead(userId);
|
||||
}
|
||||
|
||||
async sendOtpNotification(sendOtpRequest: ISendOtp, otp: string) {
|
||||
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,
|
||||
});
|
||||
|
||||
return this.eventEmitter.emit(EventType.NOTIFICATION_CREATED, notification);
|
||||
}
|
||||
|
||||
@OnEvent(EventType.NOTIFICATION_CREATED)
|
||||
handleNotificationCreatedEvent(notification: Notification) {
|
||||
switch (notification.channel) {
|
||||
case NotificationChannel.SMS:
|
||||
return this.sendSMS(notification.recipient!, notification.message);
|
||||
case NotificationChannel.PUSH:
|
||||
return this.sendPushNotification(notification.userId, notification.title, notification.message);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1 +1,2 @@
|
||||
export * from './otp-contant.constants';
|
||||
export * from './otp-default.constant';
|
||||
|
@ -0,0 +1,2 @@
|
||||
export const OTP_TITLE = 'ZOD - OTP';
|
||||
export const OTP_BODY = 'Your verification code for ZOD is {otp}';
|
@ -1,13 +1,14 @@
|
||||
import { Global, Module } from '@nestjs/common';
|
||||
import { TypeOrmModule } from '@nestjs/typeorm';
|
||||
import { NotificationModule } from '../notification/notification.module';
|
||||
import { Otp } from './entities';
|
||||
import { OtpRepository } from './repositories';
|
||||
import { OtpService } from './services/otp.service';
|
||||
|
||||
@Global()
|
||||
@Module({
|
||||
imports: [TypeOrmModule.forFeature([Otp])],
|
||||
providers: [OtpService, OtpRepository],
|
||||
exports: [OtpService],
|
||||
imports: [TypeOrmModule.forFeature([Otp]), NotificationModule],
|
||||
})
|
||||
export class OtpModule {}
|
||||
|
@ -1,5 +1,6 @@
|
||||
import { Injectable } from '@nestjs/common';
|
||||
import { ConfigService } from '@nestjs/config';
|
||||
import { NotificationsService } from '../../notification/services/notifications.service';
|
||||
import { DEFAULT_OTP_DIGIT, DEFAULT_OTP_LENGTH } from '../constants';
|
||||
import { OtpType } from '../enums';
|
||||
import { ISendOtp, IVerifyOtp } from '../interfaces';
|
||||
@ -8,7 +9,11 @@ import { generateRandomOtp } from '../utils';
|
||||
|
||||
@Injectable()
|
||||
export class OtpService {
|
||||
constructor(private readonly configService: ConfigService, private readonly otpRepository: OtpRepository) {}
|
||||
constructor(
|
||||
private readonly configService: ConfigService,
|
||||
private readonly otpRepository: OtpRepository,
|
||||
private readonly notificationService: NotificationsService,
|
||||
) {}
|
||||
private useMock = this.configService.get<boolean>('USE_MOCK', false);
|
||||
async generateAndSendOtp(sendotpRequest: ISendOtp): Promise<string> {
|
||||
const otp = this.useMock ? DEFAULT_OTP_DIGIT.repeat(DEFAULT_OTP_LENGTH) : generateRandomOtp(DEFAULT_OTP_LENGTH);
|
||||
@ -28,8 +33,7 @@ export class OtpService {
|
||||
return !!otp;
|
||||
}
|
||||
|
||||
private sendOtp(sendotpRequest: ISendOtp, otp: string) {
|
||||
// TODO: send OTP to the user
|
||||
return;
|
||||
private sendOtp(sendOtpRequest: ISendOtp, otp: string) {
|
||||
return this.notificationService.sendOtpNotification(sendOtpRequest, otp);
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user