multiple notification strategies

This commit is contained in:
Tria
2026-06-03 16:17:36 +03:00
parent 36a8002163
commit da10d067f8
7 changed files with 81 additions and 8 deletions

View File

@@ -15,6 +15,7 @@
"dependencies": { "dependencies": {
"@edr/api-common": "workspace:*", "@edr/api-common": "workspace:*",
"@edr/types": "workspace:*", "@edr/types": "workspace:*",
"@nestjs/axios": "^4.0.1",
"@nestjs/common": "^11.0.0", "@nestjs/common": "^11.0.0",
"@nestjs/config": "^4.0.0", "@nestjs/config": "^4.0.0",
"@nestjs/core": "^11.0.0", "@nestjs/core": "^11.0.0",
@@ -27,7 +28,7 @@
"@tria-plc/iamapi-common": "^0.1.6", "@tria-plc/iamapi-common": "^0.1.6",
"amqp-connection-manager": "^5.0.0", "amqp-connection-manager": "^5.0.0",
"amqplib": "^2.0.1", "amqplib": "^2.0.1",
"axios": "^1.7.7", "axios": "^1.16.1",
"class-transformer": "^0.5.1", "class-transformer": "^0.5.1",
"class-validator": "^0.14.1", "class-validator": "^0.14.1",
"dotenv": "^17.4.2", "dotenv": "^17.4.2",
@@ -76,4 +77,4 @@
"coverageDirectory": "../coverage", "coverageDirectory": "../coverage",
"testEnvironment": "node" "testEnvironment": "node"
} }
} }

View File

@@ -1,9 +1,14 @@
import { Module } from "@nestjs/common"; import { Module } from "@nestjs/common";
import { NotificationsService } from "./notifications.service"; import { NotificationsService } from "./notifications.service";
import { EmailNotificationStrategy } from "./strategies/notification.email.strategy";
import { SmsNotificationStrategy } from "./strategies/notification.sms.strategy";
import { HttpModule } from "@nestjs/axios";
@Module({ @Module({
providers: [NotificationsService], imports: [HttpModule],
controllers: [],
providers: [EmailNotificationStrategy, SmsNotificationStrategy, NotificationsService],
exports: [NotificationsService], exports: [NotificationsService],
}) })
export class NotificationsModule {} export class NotificationsModule { }

View File

@@ -1,14 +1,35 @@
import { Injectable, Logger } from "@nestjs/common"; import { Injectable, Logger, NotFoundException } from "@nestjs/common";
import { EmailNotificationStrategy } from "./strategies/notification.email.strategy";
import { NotificationStrategy } from "./strategies/notification.strategy";
import { SmsNotificationStrategy } from "./strategies/notification.sms.strategy";
type StrategyMethod = "sms" | "email"
@Injectable() @Injectable()
export class NotificationsService { export class NotificationsService {
private readonly logger = new Logger(NotificationsService.name); private readonly logger = new Logger(NotificationsService.name);
private readonly strategies: Map<StrategyMethod, NotificationStrategy>
constructor(private readonly email: EmailNotificationStrategy, private readonly sms: SmsNotificationStrategy) {
this.strategies = new Map([
["sms", this.sms as NotificationStrategy],
["email", this.email as NotificationStrategy]
])
}
/** /**
* Dispatch a notification to an operator or customer. * Dispatch a notification to an operator or customer.
* TODO: wire to email/SMS provider (SendGrid, SMS API, etc.) via a mailer service. * TODO: wire to email/SMS provider (SendGrid, SMS API, etc.) via a mailer service.
*/ */
async send(recipient: string, subject: string, body: string): Promise<void> {
this.logger.log(`[notify] ${recipient} :: ${subject} :: ${body}`); async directSend(method: StrategyMethod, recipient: string, message: string) {
const strategy = this.strategies.get(method);
if (!strategy) {
throw new NotFoundException();
}
const sent = await strategy.send(recipient, message)
this.logger.log(`is sent - ${sent}`)
} }
} }

View File

@@ -0,0 +1,12 @@
import { Injectable, Logger } from "@nestjs/common";
import { NotificationStrategy } from "./notification.strategy";
@Injectable()
export class EmailNotificationStrategy implements NotificationStrategy {
private readonly logger = new Logger(EmailNotificationStrategy.name);
constructor() { }
async send(recipient: string, message: string): Promise<boolean> {
this.logger.log(`${recipient}, ${message}`)
return false;
}
}

View File

@@ -0,0 +1,25 @@
import { Injectable} from "@nestjs/common";
import { NotificationStrategy } from "./notification.strategy";
import { HttpService } from '@nestjs/axios';
import { ConfigService } from "@nestjs/config";
import { firstValueFrom } from 'rxjs';
@Injectable()
export class SmsNotificationStrategy implements NotificationStrategy {
constructor(private readonly httpService: HttpService, private readonly configService: ConfigService) { }
async send(recipient: string, message: string) {
const url = this.configService.get("OZIKING_SMS_URL")
const body = {
to: recipient,
text: message
}
const response = await firstValueFrom(
this.httpService.post(
url,
body,
),
);
return response.status === 201;
}
}

View File

@@ -0,0 +1,6 @@
import { Injectable } from "@nestjs/common";
@Injectable()
export abstract class NotificationStrategy {
abstract send(recipient: string, message: string): Promise<boolean>
}

5
pnpm-lock.yaml generated
View File

@@ -44,6 +44,9 @@ importers:
'@edr/types': '@edr/types':
specifier: workspace:* specifier: workspace:*
version: link:../../packages/types version: link:../../packages/types
'@nestjs/axios':
specifier: ^4.0.1
version: 4.0.1(@nestjs/common@11.1.23(class-transformer@0.5.1)(class-validator@0.14.4)(reflect-metadata@0.2.2)(rxjs@7.8.2))(axios@1.16.1)(rxjs@7.8.2)
'@nestjs/common': '@nestjs/common':
specifier: ^11.0.0 specifier: ^11.0.0
version: 11.1.23(class-transformer@0.5.1)(class-validator@0.14.4)(reflect-metadata@0.2.2)(rxjs@7.8.2) version: 11.1.23(class-transformer@0.5.1)(class-validator@0.14.4)(reflect-metadata@0.2.2)(rxjs@7.8.2)
@@ -81,7 +84,7 @@ importers:
specifier: ^2.0.1 specifier: ^2.0.1
version: 2.0.1 version: 2.0.1
axios: axios:
specifier: ^1.7.7 specifier: ^1.16.1
version: 1.16.1 version: 1.16.1
class-transformer: class-transformer:
specifier: ^0.5.1 specifier: ^0.5.1