From f21ee1d1318b8f1f4d85719b09ec9ca6dfc487b1 Mon Sep 17 00:00:00 2001 From: SauravDhakal Date: Sat, 4 Apr 2026 20:53:07 +0545 Subject: [PATCH] feat: Event architecture implemented --- common/emails/index.ts | 5 ++++- roadmap.md | 1 + src/app.module.ts | 2 +- src/auth/auth.module.ts | 4 +--- src/auth/auth.service.ts | 12 ++++-------- src/mail/mail.listener.ts | 12 ++++++++++++ src/mail/mail.module.ts | 3 ++- src/mail/mail.service.ts | 19 +++++++++++++++++++ 8 files changed, 44 insertions(+), 14 deletions(-) create mode 100644 src/mail/mail.listener.ts diff --git a/common/emails/index.ts b/common/emails/index.ts index 80560e5..726d725 100644 --- a/common/emails/index.ts +++ b/common/emails/index.ts @@ -1,7 +1,10 @@ import { welcomeToApp } from "./auth" const EmailTemplates = { - welcomeToApp, + signup_completed: { + subject: "Welcome to app", + body: welcomeToApp + }, } export default EmailTemplates diff --git a/roadmap.md b/roadmap.md index 1e2808e..c1132eb 100644 --- a/roadmap.md +++ b/roadmap.md @@ -15,6 +15,7 @@ ``` 2. Also an API of my own +3. Production and testing env diff # 🏗️ SaaS Architect’s Roadmap: NestJS & DevOps diff --git a/src/app.module.ts b/src/app.module.ts index c766dd6..412ddc7 100644 --- a/src/app.module.ts +++ b/src/app.module.ts @@ -22,6 +22,7 @@ import { MailModule } from './mail/mail.module'; ConfigModule.forRoot({ isGlobal: true, }), + EventEmitterModule.forRoot(), UserModule, AuthModule, RequestContextModule, @@ -31,7 +32,6 @@ import { MailModule } from './mail/mail.module'; AuthorizationModule, CacheModule, MailModule, - EventEmitterModule.forRoot() ], controllers: [AppController], providers: [ diff --git a/src/auth/auth.module.ts b/src/auth/auth.module.ts index 7e2b83f..5147518 100644 --- a/src/auth/auth.module.ts +++ b/src/auth/auth.module.ts @@ -1,12 +1,11 @@ import { Global, Module } from '@nestjs/common'; import { AuthService } from './auth.service'; import { AuthController } from './auth.controller'; -import { APP_GUARD, Reflector } from '@nestjs/core'; +import { APP_GUARD } from '@nestjs/core'; import { AuthGuard } from './guards/auth.guard'; import { UserModule } from 'src/user/user.module'; import { JwtModule } from '@nestjs/jwt'; import { RequestContextModule } from 'core/als/request-context.module'; -import { MailModule } from 'src/mail/mail.module'; @Global() @Module({ @@ -22,7 +21,6 @@ import { MailModule } from 'src/mail/mail.module'; UserModule, JwtModule, RequestContextModule, - MailModule ], }) export class AuthModule { } diff --git a/src/auth/auth.service.ts b/src/auth/auth.service.ts index 317bd3a..20caaa4 100644 --- a/src/auth/auth.service.ts +++ b/src/auth/auth.service.ts @@ -5,8 +5,7 @@ import * as bcrypt from 'bcrypt'; import { UserService } from 'src/user/user.service'; import { TokenInputType } from './types'; import { JwtService } from '@nestjs/jwt'; -import EmailTemplates from 'common/emails'; -import { MailService } from 'src/mail/mail.service'; +import { EventEmitter2 } from '@nestjs/event-emitter'; @Injectable() @Public() @@ -14,7 +13,7 @@ export class AuthService { constructor( private readonly userService: UserService, private readonly jwtService: JwtService, - private readonly mailService: MailService, + private readonly eventEmitter: EventEmitter2 ) { } async register(dto: RegisterUserRequestDTO) { @@ -24,11 +23,8 @@ export class AuthService { password: hashedPassword, }); - this.mailService.sendMail({ - to: dto.email, - subject: "Welcome onboard", - body: EmailTemplates.welcomeToApp - }) + this.eventEmitter.emit('user.sign_up', dto.email) + return true; } diff --git a/src/mail/mail.listener.ts b/src/mail/mail.listener.ts new file mode 100644 index 0000000..bb57f05 --- /dev/null +++ b/src/mail/mail.listener.ts @@ -0,0 +1,12 @@ +import { Injectable } from "@nestjs/common" +import { OnEvent } from "@nestjs/event-emitter" +import { MailService } from "./mail.service" + +@Injectable() +export class MailListener { + constructor(private readonly mailService: MailService) { } + @OnEvent('user.sign_up') + handleUserSignUp(email: string) { + this.mailService.sendWelcomeMail({ to: email }) + } +} diff --git a/src/mail/mail.module.ts b/src/mail/mail.module.ts index 2631d18..b2d2432 100644 --- a/src/mail/mail.module.ts +++ b/src/mail/mail.module.ts @@ -1,8 +1,9 @@ import { Module } from '@nestjs/common'; import { MailService } from './mail.service'; +import { MailListener } from './mail.listener'; @Module({ - providers: [MailService], + providers: [MailService, MailListener], exports: [MailService] }) export class MailModule { } diff --git a/src/mail/mail.service.ts b/src/mail/mail.service.ts index aaca171..5f5f2cd 100644 --- a/src/mail/mail.service.ts +++ b/src/mail/mail.service.ts @@ -1,5 +1,6 @@ import { Injectable } from '@nestjs/common'; import { ConfigService } from "@nestjs/config"; +import EmailTemplates from 'common/emails'; import * as nodemailer from "nodemailer"; @Injectable() @@ -30,6 +31,24 @@ export class MailService { this.mailServiceAvailable = true; } + /* + * SIGN-UP + * */ + sendWelcomeMail({ to }: { to: string }) { + if (!this.mailServiceAvailable) + throw new Error("Mail service not available") + + const email = EmailTemplates.signup_completed; + + this.transporter.sendMail( + { + to, + subject: email.subject, + html: email.body + } + ) + } + sendMail({ to, subject, body }: { to: string, subject: string, body: string }) { if (!this.mailServiceAvailable) throw new Error("Mail service not available")