@nathapp/nestjs-notification 2.1.4 → 3.0.0-rc.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CLAUDE.md +21 -0
- package/UPGRADE-PLAN-PHASE7-8.md +307 -0
- package/UPGRADE-PLAN-PHASE9.md +361 -0
- package/UPGRADE-PLAN.md +425 -0
- package/dist/email/email.interface.d.ts +1 -1
- package/dist/email/email.provider.d.ts +2 -2
- package/dist/email/email.provider.js +7 -5
- package/dist/email/email.provider.js.map +1 -1
- package/dist/email/index.d.ts +1 -3
- package/dist/email/index.js +1 -6
- package/dist/email/index.js.map +1 -1
- package/dist/index.d.ts +4 -3
- package/dist/index.js +22 -3
- package/dist/index.js.map +1 -1
- package/dist/interface/index.d.ts +3 -3
- package/dist/interface/message.interface.d.ts +11 -4
- package/dist/interface/payload.interface.d.ts +71 -0
- package/dist/{push-notification/push-notification-module.interface.js → interface/payload.interface.js} +1 -2
- package/dist/interface/payload.interface.js.map +1 -0
- package/dist/interface/result.interface.d.ts +2 -1
- package/dist/notification/errors.d.ts +3 -0
- package/dist/notification/errors.js +11 -0
- package/dist/notification/errors.js.map +1 -0
- package/dist/notification/index.d.ts +6 -2
- package/dist/notification/index.js +7 -1
- package/dist/notification/index.js.map +1 -1
- package/dist/notification/notification-provider.factory.d.ts +5 -0
- package/dist/notification/notification-provider.factory.js +33 -0
- package/dist/notification/notification-provider.factory.js.map +1 -0
- package/dist/notification/notification.interceptor.d.ts +18 -0
- package/dist/notification/notification.interceptor.js +5 -0
- package/dist/notification/notification.interceptor.js.map +1 -0
- package/dist/notification/notification.module.d.ts +29 -19
- package/dist/notification/notification.module.js +338 -65
- package/dist/notification/notification.module.js.map +1 -1
- package/dist/notification/notification.service.d.ts +18 -2
- package/dist/notification/notification.service.js +277 -16
- package/dist/notification/notification.service.js.map +1 -1
- package/dist/notification/provider-config.d.ts +17 -0
- package/dist/{interface/payload.inteface.js → notification/provider-config.js} +1 -1
- package/dist/notification/provider-config.js.map +1 -0
- package/dist/push-notification/fcm-push-notification.provider.d.ts +3 -0
- package/dist/push-notification/fcm-push-notification.provider.js +17 -2
- package/dist/push-notification/fcm-push-notification.provider.js.map +1 -1
- package/dist/push-notification/firebase.interface.d.ts +1 -0
- package/dist/push-notification/index.d.ts +1 -4
- package/dist/push-notification/index.js +1 -5
- package/dist/push-notification/index.js.map +1 -1
- package/dist/push-notification/push-notification-provider.manager.d.ts +8 -3
- package/dist/push-notification/push-notification-provider.manager.js +12 -3
- package/dist/push-notification/push-notification-provider.manager.js.map +1 -1
- package/dist/push-notification/push-notification.provider.d.ts +1 -0
- package/dist/push-notification/push-notification.provider.js.map +1 -1
- package/dist/push-notification/push-notification.service.js +3 -2
- package/dist/push-notification/push-notification.service.js.map +1 -1
- package/dist/push-notification/user-token.store.js +7 -7
- package/dist/push-notification/user-token.store.js.map +1 -1
- package/dist/sms/constant.d.ts +1 -0
- package/dist/sms/constant.js +5 -0
- package/dist/sms/constant.js.map +1 -0
- package/dist/sms/index.d.ts +3 -2
- package/dist/sms/index.js +6 -2
- package/dist/sms/index.js.map +1 -1
- package/dist/sms/sms.provider.d.ts +9 -0
- package/dist/sms/sms.provider.js +7 -0
- package/dist/sms/sms.provider.js.map +1 -0
- package/dist/sms/sms.service.d.ts +8 -7
- package/dist/sms/sms.service.js +30 -2
- package/dist/sms/sms.service.js.map +1 -1
- package/dist/template/constant.d.ts +1 -0
- package/dist/template/constant.js +2 -1
- package/dist/template/constant.js.map +1 -1
- package/dist/template/engines/string-format.engine.d.ts +6 -0
- package/dist/template/engines/string-format.engine.js +17 -0
- package/dist/template/engines/string-format.engine.js.map +1 -0
- package/dist/template/fake-template.loader.js +14 -18
- package/dist/template/fake-template.loader.js.map +1 -1
- package/dist/template/index.d.ts +4 -2
- package/dist/template/index.js +4 -1
- package/dist/template/index.js.map +1 -1
- package/dist/template/template-engine.d.ts +5 -0
- package/dist/template/template-engine.js +3 -0
- package/dist/template/template-engine.js.map +1 -0
- package/dist/template/template.loader.d.ts +4 -1
- package/dist/template/template.loader.js +22 -14
- package/dist/template/template.loader.js.map +1 -1
- package/dist/whatsapp/constant.d.ts +2 -0
- package/dist/whatsapp/constant.js +6 -0
- package/dist/whatsapp/constant.js.map +1 -0
- package/dist/whatsapp/index.d.ts +3 -0
- package/dist/whatsapp/index.js +11 -0
- package/dist/whatsapp/index.js.map +1 -0
- package/dist/whatsapp/whatsapp.provider.d.ts +9 -0
- package/dist/whatsapp/whatsapp.provider.js +7 -0
- package/dist/whatsapp/whatsapp.provider.js.map +1 -0
- package/dist/whatsapp/whatsapp.service.d.ts +9 -0
- package/dist/whatsapp/whatsapp.service.js +35 -0
- package/dist/whatsapp/whatsapp.service.js.map +1 -0
- package/docs/20260214-fix-plan-notification.md +149 -0
- package/docs/20260214-fix-plan-post-refactor.md +118 -0
- package/docs/20260214-nestjs-notification-review.md +390 -0
- package/docs/20260214-review-post-refactor.md +285 -0
- package/docs/20260215-review-notification-post-fix.md +933 -0
- package/package.json +2 -1
- package/dist/email/email-provider.factory.d.ts +0 -5
- package/dist/email/email-provider.factory.js +0 -18
- package/dist/email/email-provider.factory.js.map +0 -1
- package/dist/email/email.module.d.ts +0 -27
- package/dist/email/email.module.js +0 -110
- package/dist/email/email.module.js.map +0 -1
- package/dist/interface/payload.inteface.d.ts +0 -22
- package/dist/interface/payload.inteface.js.map +0 -1
- package/dist/push-notification/push-notification-module.interface.d.ts +0 -33
- package/dist/push-notification/push-notification-module.interface.js.map +0 -1
- package/dist/push-notification/push-notification-provider-module.factory.d.ts +0 -5
- package/dist/push-notification/push-notification-provider-module.factory.js +0 -13
- package/dist/push-notification/push-notification-provider-module.factory.js.map +0 -1
- package/dist/push-notification/push-notification-provider.factory.d.ts +0 -5
- package/dist/push-notification/push-notification-provider.factory.js +0 -16
- package/dist/push-notification/push-notification-provider.factory.js.map +0 -1
- package/dist/push-notification/push-notification.module.d.ts +0 -15
- package/dist/push-notification/push-notification.module.js +0 -189
- package/dist/push-notification/push-notification.module.js.map +0 -1
|
@@ -0,0 +1,285 @@
|
|
|
1
|
+
# Post-Refactor Code Review: @nathapp/nestjs-notification
|
|
2
|
+
|
|
3
|
+
**Date:** 2026-02-14
|
|
4
|
+
**Branch:** `feat/notification-enterprise-upgrade`
|
|
5
|
+
**Purpose:** Ensure the refactored package is clean and consistent before redesigning external provider packages.
|
|
6
|
+
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
## 1. Provider/Service Consistency
|
|
10
|
+
|
|
11
|
+
### Current Provider Contracts
|
|
12
|
+
|
|
13
|
+
| Channel | Abstract Class | Methods | Extra Requirements |
|
|
14
|
+
|---------|---------------|---------|-------------------|
|
|
15
|
+
| Email | `EmailProvider` | `send(EmailMessage)`, `get isSupportAttachments` | ⚠️ Extra getter |
|
|
16
|
+
| Push | `PushNotificationProvider` | `send(PushMessage)`, `sendMulticast(...)` | ⚠️ `readonly type: PushNotificationPlatform` + extra method |
|
|
17
|
+
| SMS | `SmsProvider` | `send(SmsMessage)` | ✅ Clean |
|
|
18
|
+
| WhatsApp | `WhatsAppProvider` | `send(WhatsAppMessage)` | ✅ Clean |
|
|
19
|
+
|
|
20
|
+
### 🟡 M1: EmailProvider Has Extra `isSupportAttachments` Getter
|
|
21
|
+
|
|
22
|
+
```typescript
|
|
23
|
+
// EmailProvider
|
|
24
|
+
abstract send(message: EmailMessage): Promise<SendResult>;
|
|
25
|
+
abstract get isSupportAttachments(): boolean; // ← extra requirement
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
SMS, WhatsApp, and Push don't have capability-query methods. An external dev writing `BrevoEmailProvider` must implement this extra getter, which is inconsistent.
|
|
29
|
+
|
|
30
|
+
**Recommendation:** Either remove `isSupportAttachments` (most modern email providers support attachments) or add it to the interface doc as an explicit email-only requirement.
|
|
31
|
+
|
|
32
|
+
### 🟡 M2: PushNotificationProvider Has Extra `type` Property and `sendMulticast`
|
|
33
|
+
|
|
34
|
+
```typescript
|
|
35
|
+
// PushNotificationProvider
|
|
36
|
+
abstract readonly type: PushNotificationPlatform; // ← extra
|
|
37
|
+
abstract send(message: PushMessage): Promise<SendResult>;
|
|
38
|
+
abstract sendMulticast(tokens: string[], message: PushMessageOnly): Promise<BatchSendResult>; // ← extra method
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
This is justified (push has android/ios/huawei platforms and multicast), but it makes push the most complex channel to implement. Should be documented clearly.
|
|
42
|
+
|
|
43
|
+
### 🟢 L1: Interface Naming Inconsistency
|
|
44
|
+
|
|
45
|
+
- Email: `IEmailProvider`
|
|
46
|
+
- SMS: `ISmsProvider`
|
|
47
|
+
- WhatsApp: `IWhatsAppProvider`
|
|
48
|
+
- Push: `IPushNotificationProvider`
|
|
49
|
+
|
|
50
|
+
All fine, but `EmailProvider` also has `SmtpEmailProvider` in the same file — a concrete built-in impl mixed with the abstract. SMS/WhatsApp keep them separate (no built-in impl in core).
|
|
51
|
+
|
|
52
|
+
---
|
|
53
|
+
|
|
54
|
+
## 2. Public API Surface
|
|
55
|
+
|
|
56
|
+
### What External Devs Need to Import
|
|
57
|
+
|
|
58
|
+
| Channel | Import | Extend | Implement |
|
|
59
|
+
|---------|--------|--------|-----------|
|
|
60
|
+
| Email | `EmailProvider`, `EmailMessage`, `SendResult` | `EmailProvider` | `send()`, `isSupportAttachments` |
|
|
61
|
+
| Push | `PushNotificationProvider`, `PushMessage`, `SendResult`, `BatchSendResult`, `PushNotificationPlatform` | `PushNotificationProvider` | `send()`, `sendMulticast()`, `type` |
|
|
62
|
+
| SMS | `SmsProvider`, `SmsMessage`, `SendResult` | `SmsProvider` | `send()` |
|
|
63
|
+
| WhatsApp | `WhatsAppProvider`, `WhatsAppMessage`, `SendResult` | `WhatsAppProvider` | `send()` |
|
|
64
|
+
|
|
65
|
+
### 🟡 M3: Unnecessary Exports Leaking Internals
|
|
66
|
+
|
|
67
|
+
The barrel `lib/index.ts` exports internal implementation details that external devs shouldn't depend on:
|
|
68
|
+
|
|
69
|
+
- `EMAIL_OPTIONS`, `EMAIL_SERVICE` — internal DI tokens from old `EmailModule`
|
|
70
|
+
- `EmailOption`, `SmtpOption`, `SmtpHostOption`, `SmtpUriOption`, `CustomEmailOption` — old config types
|
|
71
|
+
- `EmailProviderFactory` — superseded by `NotificationProviderFactory`
|
|
72
|
+
- `FCMPushNotificationOption`, `PushNotificationOption` — FCM-specific config
|
|
73
|
+
- `PushNotificationProviderFactory` (via `push-notification/index.ts`) — old factory
|
|
74
|
+
- `DefaultProviderManager`, `InMemoryUserTokenStore` — internal implementations
|
|
75
|
+
- `WHATSAPP_SERVICE` — unused constant
|
|
76
|
+
|
|
77
|
+
**Risk:** If we change any of these internals, external packages importing them will break.
|
|
78
|
+
|
|
79
|
+
**Recommendation:** Create a clean public API surface. Only export what external devs actually need:
|
|
80
|
+
- Abstract providers (`EmailProvider`, `SmsProvider`, `WhatsAppProvider`, `PushNotificationProvider`)
|
|
81
|
+
- Message types (`EmailMessage`, `SmsMessage`, `WhatsAppMessage`, `PushMessage`)
|
|
82
|
+
- Result types (`SendResult`, `BatchSendResult`)
|
|
83
|
+
- `NotificationModule` and its option interfaces
|
|
84
|
+
- `ProviderConfig` for registration
|
|
85
|
+
|
|
86
|
+
---
|
|
87
|
+
|
|
88
|
+
## 3. Breaking Changes for Existing Consumers
|
|
89
|
+
|
|
90
|
+
| Change | Impact | Migration |
|
|
91
|
+
|--------|--------|-----------|
|
|
92
|
+
| `SmsService` no longer abstract | Packages extending `SmsService` break | Extend `SmsProvider` instead |
|
|
93
|
+
| `WhatsAppService` no longer abstract | Packages extending `WhatsAppService` break | Extend `WhatsAppProvider` instead |
|
|
94
|
+
| New injection tokens `SMS_PROVIDER`, `WHATSAPP_PROVIDER` | Code using `@Inject(SmsService)` still works | No change needed |
|
|
95
|
+
| `strict: true` by default | Unconfigured channels now **throw** instead of returning `{ success: false }` | Set `strict: false` to keep old behavior |
|
|
96
|
+
|
|
97
|
+
---
|
|
98
|
+
|
|
99
|
+
## 4. Registration Flow Trace
|
|
100
|
+
|
|
101
|
+
```
|
|
102
|
+
NotificationModule.forRoot({
|
|
103
|
+
providers: [
|
|
104
|
+
{ channel: 'email', provider: BrevoEmailProvider, options: { apiKey: '...' } }
|
|
105
|
+
]
|
|
106
|
+
})
|
|
107
|
+
↓
|
|
108
|
+
createChannelProviders(configs)
|
|
109
|
+
↓
|
|
110
|
+
groupProvidersByChannel(configs) → { email: [...], push: [...], sms: [...], whatsapp: [...] }
|
|
111
|
+
↓
|
|
112
|
+
NotificationProviderFactory.create(config)
|
|
113
|
+
→ new config.provider(config.options) // creates instance
|
|
114
|
+
→ instanceof check against EmailProvider // validates
|
|
115
|
+
↓
|
|
116
|
+
Register as { provide: EMAIL_PROVIDER, useValue: instance }
|
|
117
|
+
Register as { provide: EmailService, useFactory: (p) => new EmailService(p), inject: [EMAIL_PROVIDER] }
|
|
118
|
+
↓
|
|
119
|
+
NotificationService injects @Optional() EmailService
|
|
120
|
+
```
|
|
121
|
+
|
|
122
|
+
### 🟢 L2: `forRootAsync` — Providers Created in Factory, Not at Module Init
|
|
123
|
+
|
|
124
|
+
In `forRootAsync`, channel providers are created inside `useFactory` callbacks that depend on `NOTIFICATION_OPTIONS`. This is correct — options are resolved first, then providers created. No race condition.
|
|
125
|
+
|
|
126
|
+
### 🟢 L3: Null Providers with `@Optional()`
|
|
127
|
+
|
|
128
|
+
When a channel is not configured, its service is `null`. `NotificationService` handles this with null checks before each `send*` call. Clean.
|
|
129
|
+
|
|
130
|
+
---
|
|
131
|
+
|
|
132
|
+
## 5. Type Safety: `ProviderConfig.options: any`
|
|
133
|
+
|
|
134
|
+
### 🟡 M4: No Type Constraint on Provider Options
|
|
135
|
+
|
|
136
|
+
```typescript
|
|
137
|
+
export interface ProviderConfig<C extends NotificationChannel = NotificationChannel> {
|
|
138
|
+
channel: C;
|
|
139
|
+
provider: Type<ChannelProviderMap[C]>;
|
|
140
|
+
options?: any; // ← no type safety
|
|
141
|
+
}
|
|
142
|
+
```
|
|
143
|
+
|
|
144
|
+
A developer can pass `{ channel: 'email', provider: BrevoEmailProvider, options: 12345 }` and TypeScript won't complain. The error only surfaces at runtime in the provider constructor.
|
|
145
|
+
|
|
146
|
+
**Options to fix:**
|
|
147
|
+
1. Generic options type: `ProviderConfig<C, O = any>` — but this makes registration verbose
|
|
148
|
+
2. Provider-level static typing: each provider exports a helper `BrevoEmailProvider.config(opts): ProviderConfig` — cleanest for consumers
|
|
149
|
+
3. Leave as `any` but document clearly — pragmatic choice
|
|
150
|
+
|
|
151
|
+
**Recommendation:** Option 3 for now (document), option 2 for external provider packages (each exports a typed helper).
|
|
152
|
+
|
|
153
|
+
---
|
|
154
|
+
|
|
155
|
+
## 6. Remaining Dead Code
|
|
156
|
+
|
|
157
|
+
### 🟡 M5: Legacy Modules Still Present
|
|
158
|
+
|
|
159
|
+
| File | Status | Action |
|
|
160
|
+
|------|--------|--------|
|
|
161
|
+
| `email/email.module.ts` | Superseded by `NotificationModule` | Deprecate or remove |
|
|
162
|
+
| `email/email-provider.factory.ts` | Superseded by `NotificationProviderFactory` | Deprecate or remove |
|
|
163
|
+
| `push-notification/push-notification.module.ts` | Superseded | Deprecate or remove |
|
|
164
|
+
| `push-notification/push-notification-provider.factory.ts` | Superseded | Deprecate or remove |
|
|
165
|
+
| `push-notification/push-notification-provider-module.factory.ts` | Superseded | Remove |
|
|
166
|
+
| `push-notification/push-notification-module.interface.ts` | Superseded | Remove |
|
|
167
|
+
|
|
168
|
+
These add ~500 lines of dead code and confuse developers about which pattern to use.
|
|
169
|
+
|
|
170
|
+
**Recommendation:** Add `@deprecated` JSDoc to `EmailModule` and `PushNotificationModule`. Remove the internal factories that are no longer used by any code path.
|
|
171
|
+
|
|
172
|
+
---
|
|
173
|
+
|
|
174
|
+
## 7. External Provider Developer Guide
|
|
175
|
+
|
|
176
|
+
### Minimum Requirements per Channel
|
|
177
|
+
|
|
178
|
+
#### Email Provider
|
|
179
|
+
```typescript
|
|
180
|
+
import { EmailProvider, EmailMessage, SendResult } from '@nathapp/nestjs-notification';
|
|
181
|
+
|
|
182
|
+
export interface MyEmailOptions {
|
|
183
|
+
apiKey: string;
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
export class MyEmailProvider extends EmailProvider {
|
|
187
|
+
constructor(private readonly options: MyEmailOptions) {
|
|
188
|
+
super();
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
get isSupportAttachments(): boolean {
|
|
192
|
+
return true;
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
async send(message: EmailMessage): Promise<SendResult> {
|
|
196
|
+
// message.recipient, message.subject, message.message, message.attachments
|
|
197
|
+
return { success: true, requestId: '...' };
|
|
198
|
+
}
|
|
199
|
+
}
|
|
200
|
+
```
|
|
201
|
+
|
|
202
|
+
#### SMS Provider
|
|
203
|
+
```typescript
|
|
204
|
+
import { SmsProvider, SmsMessage, SendResult } from '@nathapp/nestjs-notification';
|
|
205
|
+
|
|
206
|
+
export class MySmsProvider extends SmsProvider {
|
|
207
|
+
constructor(private readonly options: any) { super(); }
|
|
208
|
+
|
|
209
|
+
async send(message: SmsMessage): Promise<SendResult> {
|
|
210
|
+
// message.recipient, message.message, message.countryIso2, message.dialCode
|
|
211
|
+
return { success: true };
|
|
212
|
+
}
|
|
213
|
+
}
|
|
214
|
+
```
|
|
215
|
+
|
|
216
|
+
#### WhatsApp Provider
|
|
217
|
+
```typescript
|
|
218
|
+
import { WhatsAppProvider, WhatsAppMessage, SendResult } from '@nathapp/nestjs-notification';
|
|
219
|
+
|
|
220
|
+
export class MyWhatsAppProvider extends WhatsAppProvider {
|
|
221
|
+
constructor(private readonly options: any) { super(); }
|
|
222
|
+
|
|
223
|
+
async send(message: WhatsAppMessage): Promise<SendResult> {
|
|
224
|
+
// message.recipient, message.message, message.templateName, message.bodyParams
|
|
225
|
+
return { success: true };
|
|
226
|
+
}
|
|
227
|
+
}
|
|
228
|
+
```
|
|
229
|
+
|
|
230
|
+
#### Push Provider
|
|
231
|
+
```typescript
|
|
232
|
+
import { PushNotificationProvider, PushMessage, PushMessageOnly, SendResult, BatchSendResult, PushNotificationPlatform } from '@nathapp/nestjs-notification';
|
|
233
|
+
|
|
234
|
+
export class MyPushProvider extends PushNotificationProvider {
|
|
235
|
+
readonly type: PushNotificationPlatform = 'firebase'; // or custom string
|
|
236
|
+
|
|
237
|
+
constructor(private readonly options: any) { super(); }
|
|
238
|
+
|
|
239
|
+
async send(message: PushMessage): Promise<SendResult> {
|
|
240
|
+
return { success: true };
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
async sendMulticast(tokens: string[], message: PushMessageOnly): Promise<BatchSendResult> {
|
|
244
|
+
return { successCount: tokens.length, failureCount: 0, responses: [] };
|
|
245
|
+
}
|
|
246
|
+
}
|
|
247
|
+
```
|
|
248
|
+
|
|
249
|
+
### Consumer Registration
|
|
250
|
+
```typescript
|
|
251
|
+
import { NotificationModule } from '@nathapp/nestjs-notification';
|
|
252
|
+
import { BrevoEmailProvider } from '@nathapp/nestjs-notification-brevo';
|
|
253
|
+
|
|
254
|
+
@Module({
|
|
255
|
+
imports: [
|
|
256
|
+
NotificationModule.forRoot({
|
|
257
|
+
providers: [
|
|
258
|
+
{ channel: 'email', provider: BrevoEmailProvider, options: { apiKey: '...' } },
|
|
259
|
+
],
|
|
260
|
+
templateLoader: MyTemplateLoader,
|
|
261
|
+
}),
|
|
262
|
+
],
|
|
263
|
+
})
|
|
264
|
+
export class AppModule {}
|
|
265
|
+
```
|
|
266
|
+
|
|
267
|
+
---
|
|
268
|
+
|
|
269
|
+
## Summary
|
|
270
|
+
|
|
271
|
+
| Severity | Count | Key Items |
|
|
272
|
+
|----------|-------|-----------|
|
|
273
|
+
| 🔴 Critical | 0 | None — previous fixes resolved all criticals |
|
|
274
|
+
| 🟡 Medium | 5 | Provider inconsistencies (M1-M2), leaky exports (M3), untyped options (M4), dead code (M5) |
|
|
275
|
+
| 🟢 Low | 3 | Naming inconsistency (L1), async flow (L2-L3) |
|
|
276
|
+
|
|
277
|
+
### Before Merging to Master
|
|
278
|
+
1. Decide: remove `isSupportAttachments` from `EmailProvider` or keep as email-only requirement
|
|
279
|
+
2. Decide: deprecate or remove legacy modules (`EmailModule`, `PushNotificationModule`)
|
|
280
|
+
3. Clean up barrel exports to only expose public API
|
|
281
|
+
|
|
282
|
+
### Before Redesigning External Providers
|
|
283
|
+
- The provider contract is clear and documented above
|
|
284
|
+
- Each external package: export provider class + options interface, peer dep on `@nathapp/nestjs-notification`
|
|
285
|
+
- Consider typed config helpers per provider package
|