@gravito/flare 3.3.0 → 4.0.0
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/README.md +135 -3
- package/dist/index.cjs +1035 -97
- package/dist/index.d.cts +1249 -12
- package/dist/index.d.ts +1249 -12
- package/dist/index.js +1039 -97
- package/package.json +6 -4
package/README.md
CHANGED
|
@@ -2,17 +2,20 @@
|
|
|
2
2
|
|
|
3
3
|
> Lightweight, high-performance notifications for Gravito with multi-channel delivery (mail, database, broadcast, Slack, SMS).
|
|
4
4
|
|
|
5
|
-
**Status**: v3.
|
|
5
|
+
**Status**: v3.4.0 - Production ready with advanced features (Retries, Metrics, Batching, Timeout, Rate Limiting, Preference Driver).
|
|
6
6
|
|
|
7
7
|
## Features
|
|
8
8
|
|
|
9
9
|
- **Zero runtime overhead**: Pure type wrappers that delegate to channel drivers
|
|
10
10
|
- **Multi-channel delivery**: Mail, database, broadcast, Slack, SMS (Twilio & AWS SNS)
|
|
11
11
|
- **High Performance**: Parallel channel execution and batch sending capabilities
|
|
12
|
-
- **Reliability**: Built-in retry mechanism with exponential backoff
|
|
12
|
+
- **Reliability**: Built-in retry mechanism with exponential backoff and timeout protection
|
|
13
13
|
- **Observability**: Comprehensive metrics with Prometheus support
|
|
14
14
|
- **Developer Experience**: Strong typing, lifecycle hooks, and template system
|
|
15
|
-
- **Queue support**: Works with `@gravito/stream` for async delivery
|
|
15
|
+
- **Queue support**: Works with `@gravito/stream` for async delivery with Lazy Loading
|
|
16
|
+
- **Rate Limiting**: Channel-level rate limiting with Token Bucket algorithm
|
|
17
|
+
- **Preference Driver**: User notification preferences with automatic channel filtering
|
|
18
|
+
- **Middleware System**: Extensible middleware chain for custom notification processing
|
|
16
19
|
|
|
17
20
|
## Installation
|
|
18
21
|
|
|
@@ -144,6 +147,135 @@ class OrderShipped extends TemplatedNotification {
|
|
|
144
147
|
}
|
|
145
148
|
```
|
|
146
149
|
|
|
150
|
+
### Timeout Protection (v3.4.0)
|
|
151
|
+
All channels support timeout configuration to prevent slow responses from blocking notifications:
|
|
152
|
+
|
|
153
|
+
```typescript
|
|
154
|
+
OrbitFlare.configure({
|
|
155
|
+
channels: {
|
|
156
|
+
slack: {
|
|
157
|
+
webhookUrl: process.env.SLACK_WEBHOOK_URL,
|
|
158
|
+
timeout: 5000, // 5 秒超時
|
|
159
|
+
onTimeout: (channel, notification) => {
|
|
160
|
+
console.error(`Timeout: ${channel}`)
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
})
|
|
165
|
+
```
|
|
166
|
+
|
|
167
|
+
### Rate Limiting (v3.4.0)
|
|
168
|
+
Protect downstream services with channel-level rate limiting:
|
|
169
|
+
|
|
170
|
+
```typescript
|
|
171
|
+
import { RateLimitMiddleware } from '@gravito/flare'
|
|
172
|
+
|
|
173
|
+
const rateLimiter = new RateLimitMiddleware({
|
|
174
|
+
email: {
|
|
175
|
+
maxPerSecond: 10,
|
|
176
|
+
maxPerMinute: 100,
|
|
177
|
+
maxPerHour: 1000
|
|
178
|
+
},
|
|
179
|
+
sms: {
|
|
180
|
+
maxPerSecond: 5
|
|
181
|
+
}
|
|
182
|
+
})
|
|
183
|
+
|
|
184
|
+
notifications.use(rateLimiter)
|
|
185
|
+
|
|
186
|
+
// 檢查狀態
|
|
187
|
+
const status = rateLimiter.getStatus('email')
|
|
188
|
+
console.log(`剩餘: ${status.second}/10`)
|
|
189
|
+
```
|
|
190
|
+
|
|
191
|
+
### Lazy Loading for Queue (v3.4.0)
|
|
192
|
+
Optimize queue serialization with Lazy Loading pattern:
|
|
193
|
+
|
|
194
|
+
```typescript
|
|
195
|
+
import { LazyNotification } from '@gravito/flare'
|
|
196
|
+
|
|
197
|
+
class OrderConfirmation extends LazyNotification<Order> {
|
|
198
|
+
constructor(private orderId: string) {
|
|
199
|
+
super()
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
protected async loadData(notifiable: Notifiable): Promise<Order> {
|
|
203
|
+
return await db.orders.find(this.orderId)
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
via(user: Notifiable): string[] {
|
|
207
|
+
return ['mail', 'database']
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
async toMail(user: Notifiable): Promise<MailMessage> {
|
|
211
|
+
const order = await this.ensureLoaded(user)
|
|
212
|
+
return {
|
|
213
|
+
subject: `訂單確認 #${order.id}`,
|
|
214
|
+
view: 'emails.order-confirmation',
|
|
215
|
+
data: { order },
|
|
216
|
+
to: user.email,
|
|
217
|
+
}
|
|
218
|
+
}
|
|
219
|
+
}
|
|
220
|
+
```
|
|
221
|
+
|
|
222
|
+
### User Preferences (v3.4.0)
|
|
223
|
+
Respect user notification preferences automatically:
|
|
224
|
+
|
|
225
|
+
```typescript
|
|
226
|
+
import { PreferenceMiddleware } from '@gravito/flare'
|
|
227
|
+
|
|
228
|
+
// 方式 1: 在 OrbitFlare 配置中啟用
|
|
229
|
+
OrbitFlare.configure({
|
|
230
|
+
enablePreference: true
|
|
231
|
+
})
|
|
232
|
+
|
|
233
|
+
// 方式 2: 使用自定義偏好提供者
|
|
234
|
+
const preferenceMiddleware = new PreferenceMiddleware({
|
|
235
|
+
async getUserPreferences(notifiable) {
|
|
236
|
+
const prefs = await db.userPreferences.find(notifiable.id)
|
|
237
|
+
return {
|
|
238
|
+
enabledChannels: prefs.enabledChannels,
|
|
239
|
+
disabledChannels: prefs.disabledChannels,
|
|
240
|
+
disabledNotifications: prefs.disabledNotifications
|
|
241
|
+
}
|
|
242
|
+
}
|
|
243
|
+
})
|
|
244
|
+
|
|
245
|
+
notifications.use(preferenceMiddleware)
|
|
246
|
+
|
|
247
|
+
// 方式 3: 在 Notifiable 物件中實作
|
|
248
|
+
class User implements Notifiable {
|
|
249
|
+
async getNotificationPreferences() {
|
|
250
|
+
return {
|
|
251
|
+
enabledChannels: ['email', 'slack'],
|
|
252
|
+
disabledChannels: ['sms']
|
|
253
|
+
}
|
|
254
|
+
}
|
|
255
|
+
}
|
|
256
|
+
```
|
|
257
|
+
|
|
258
|
+
### Middleware Chain (v3.4.0)
|
|
259
|
+
Combine multiple middleware for powerful notification processing:
|
|
260
|
+
|
|
261
|
+
```typescript
|
|
262
|
+
import { RateLimitMiddleware, PreferenceMiddleware } from '@gravito/flare'
|
|
263
|
+
|
|
264
|
+
// 建立中介層
|
|
265
|
+
const rateLimiter = new RateLimitMiddleware({ /* ... */ })
|
|
266
|
+
const preferenceFilter = new PreferenceMiddleware({ /* ... */ })
|
|
267
|
+
|
|
268
|
+
// 註冊中介層(執行順序:由內而外)
|
|
269
|
+
notifications
|
|
270
|
+
.use(rateLimiter) // 先限流
|
|
271
|
+
.use(preferenceFilter) // 後過濾
|
|
272
|
+
|
|
273
|
+
// 或在 OrbitFlare 配置中一次註冊
|
|
274
|
+
OrbitFlare.configure({
|
|
275
|
+
middleware: [rateLimiter, preferenceFilter]
|
|
276
|
+
})
|
|
277
|
+
```
|
|
278
|
+
|
|
147
279
|
## API Reference
|
|
148
280
|
|
|
149
281
|
### NotificationManager
|