@dangao/bun-server 1.7.1 → 1.8.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.
Files changed (116) hide show
  1. package/README.md +129 -21
  2. package/dist/di/decorators.d.ts +37 -0
  3. package/dist/di/decorators.d.ts.map +1 -1
  4. package/dist/di/index.d.ts +1 -1
  5. package/dist/di/index.d.ts.map +1 -1
  6. package/dist/di/module-registry.d.ts +17 -0
  7. package/dist/di/module-registry.d.ts.map +1 -1
  8. package/dist/events/decorators.d.ts +52 -0
  9. package/dist/events/decorators.d.ts.map +1 -0
  10. package/dist/events/event-module.d.ts +97 -0
  11. package/dist/events/event-module.d.ts.map +1 -0
  12. package/dist/events/index.d.ts +5 -0
  13. package/dist/events/index.d.ts.map +1 -0
  14. package/dist/events/service.d.ts +76 -0
  15. package/dist/events/service.d.ts.map +1 -0
  16. package/dist/events/types.d.ts +184 -0
  17. package/dist/events/types.d.ts.map +1 -0
  18. package/dist/index.d.ts +5 -3
  19. package/dist/index.d.ts.map +1 -1
  20. package/dist/index.js +1511 -11
  21. package/dist/security/filter.d.ts +23 -0
  22. package/dist/security/filter.d.ts.map +1 -1
  23. package/dist/security/guards/builtin/auth-guard.d.ts +44 -0
  24. package/dist/security/guards/builtin/auth-guard.d.ts.map +1 -0
  25. package/dist/security/guards/builtin/index.d.ts +3 -0
  26. package/dist/security/guards/builtin/index.d.ts.map +1 -0
  27. package/dist/security/guards/builtin/roles-guard.d.ts +66 -0
  28. package/dist/security/guards/builtin/roles-guard.d.ts.map +1 -0
  29. package/dist/security/guards/decorators.d.ts +50 -0
  30. package/dist/security/guards/decorators.d.ts.map +1 -0
  31. package/dist/security/guards/execution-context.d.ts +56 -0
  32. package/dist/security/guards/execution-context.d.ts.map +1 -0
  33. package/dist/security/guards/guard-registry.d.ts +67 -0
  34. package/dist/security/guards/guard-registry.d.ts.map +1 -0
  35. package/dist/security/guards/index.d.ts +7 -0
  36. package/dist/security/guards/index.d.ts.map +1 -0
  37. package/dist/security/guards/reflector.d.ts +57 -0
  38. package/dist/security/guards/reflector.d.ts.map +1 -0
  39. package/dist/security/guards/types.d.ts +126 -0
  40. package/dist/security/guards/types.d.ts.map +1 -0
  41. package/dist/security/index.d.ts +1 -0
  42. package/dist/security/index.d.ts.map +1 -1
  43. package/dist/security/security-module.d.ts +20 -0
  44. package/dist/security/security-module.d.ts.map +1 -1
  45. package/dist/validation/class-validator.d.ts +108 -0
  46. package/dist/validation/class-validator.d.ts.map +1 -0
  47. package/dist/validation/custom-validator.d.ts +130 -0
  48. package/dist/validation/custom-validator.d.ts.map +1 -0
  49. package/dist/validation/errors.d.ts +22 -2
  50. package/dist/validation/errors.d.ts.map +1 -1
  51. package/dist/validation/index.d.ts +7 -1
  52. package/dist/validation/index.d.ts.map +1 -1
  53. package/dist/validation/rules/array.d.ts +33 -0
  54. package/dist/validation/rules/array.d.ts.map +1 -0
  55. package/dist/validation/rules/common.d.ts +90 -0
  56. package/dist/validation/rules/common.d.ts.map +1 -0
  57. package/dist/validation/rules/conditional.d.ts +30 -0
  58. package/dist/validation/rules/conditional.d.ts.map +1 -0
  59. package/dist/validation/rules/index.d.ts +5 -0
  60. package/dist/validation/rules/index.d.ts.map +1 -0
  61. package/dist/validation/rules/object.d.ts +30 -0
  62. package/dist/validation/rules/object.d.ts.map +1 -0
  63. package/dist/validation/types.d.ts +52 -1
  64. package/dist/validation/types.d.ts.map +1 -1
  65. package/docs/events.md +494 -0
  66. package/docs/guards.md +376 -0
  67. package/docs/guide.md +309 -1
  68. package/docs/request-lifecycle.md +444 -0
  69. package/docs/validation.md +407 -0
  70. package/docs/zh/events.md +494 -0
  71. package/docs/zh/guards.md +376 -0
  72. package/docs/zh/guide.md +309 -1
  73. package/docs/zh/request-lifecycle.md +444 -0
  74. package/docs/zh/validation.md +407 -0
  75. package/package.json +1 -1
  76. package/src/di/decorators.ts +46 -0
  77. package/src/di/index.ts +10 -1
  78. package/src/di/module-registry.ts +39 -0
  79. package/src/events/decorators.ts +103 -0
  80. package/src/events/event-module.ts +272 -0
  81. package/src/events/index.ts +32 -0
  82. package/src/events/service.ts +352 -0
  83. package/src/events/types.ts +223 -0
  84. package/src/index.ts +133 -1
  85. package/src/security/filter.ts +88 -8
  86. package/src/security/guards/builtin/auth-guard.ts +68 -0
  87. package/src/security/guards/builtin/index.ts +3 -0
  88. package/src/security/guards/builtin/roles-guard.ts +165 -0
  89. package/src/security/guards/decorators.ts +124 -0
  90. package/src/security/guards/execution-context.ts +152 -0
  91. package/src/security/guards/guard-registry.ts +164 -0
  92. package/src/security/guards/index.ts +7 -0
  93. package/src/security/guards/reflector.ts +99 -0
  94. package/src/security/guards/types.ts +144 -0
  95. package/src/security/index.ts +1 -0
  96. package/src/security/security-module.ts +72 -2
  97. package/src/validation/class-validator.ts +322 -0
  98. package/src/validation/custom-validator.ts +289 -0
  99. package/src/validation/errors.ts +50 -2
  100. package/src/validation/index.ts +103 -1
  101. package/src/validation/rules/array.ts +118 -0
  102. package/src/validation/rules/common.ts +286 -0
  103. package/src/validation/rules/conditional.ts +52 -0
  104. package/src/validation/rules/index.ts +51 -0
  105. package/src/validation/rules/object.ts +86 -0
  106. package/src/validation/types.ts +61 -1
  107. package/tests/di/global-module.test.ts +487 -0
  108. package/tests/events/event-decorators.test.ts +173 -0
  109. package/tests/events/event-emitter.test.ts +373 -0
  110. package/tests/events/event-module.test.ts +373 -0
  111. package/tests/security/guards/guards-integration.test.ts +371 -0
  112. package/tests/security/guards/guards.test.ts +775 -0
  113. package/tests/security/security-module.test.ts +2 -2
  114. package/tests/validation/class-validator.test.ts +349 -0
  115. package/tests/validation/custom-validator.test.ts +335 -0
  116. package/tests/validation/rules.test.ts +543 -0
@@ -0,0 +1,494 @@
1
+ # 事件系统
2
+
3
+ 事件模块提供了强大的事件驱动架构,用于构建松耦合、高可维护性的应用。它支持同步和异步事件处理、事件优先级和通配符事件模式。
4
+
5
+ ## 目录
6
+
7
+ - [安装](#安装)
8
+ - [快速开始](#快速开始)
9
+ - [核心概念](#核心概念)
10
+ - [事件模块配置](#事件模块配置)
11
+ - [发布事件](#发布事件)
12
+ - [监听事件](#监听事件)
13
+ - [事件优先级](#事件优先级)
14
+ - [异步事件处理](#异步事件处理)
15
+ - [通配符事件](#通配符事件)
16
+ - [错误处理](#错误处理)
17
+ - [最佳实践](#最佳实践)
18
+ - [API 参考](#api-参考)
19
+
20
+ ## 安装
21
+
22
+ 事件模块已包含在 `@dangao/bun-server` 中,无需额外安装。
23
+
24
+ ## 快速开始
25
+
26
+ ```typescript
27
+ import {
28
+ Application,
29
+ Module,
30
+ Injectable,
31
+ Inject,
32
+ EventModule,
33
+ OnEvent,
34
+ EVENT_EMITTER_TOKEN,
35
+ } from '@dangao/bun-server';
36
+ import type { EventEmitter } from '@dangao/bun-server';
37
+
38
+ // 定义事件
39
+ const USER_CREATED = Symbol('user.created');
40
+
41
+ interface UserCreatedEvent {
42
+ userId: string;
43
+ email: string;
44
+ }
45
+
46
+ // 发布事件的服务
47
+ @Injectable()
48
+ class UserService {
49
+ constructor(
50
+ @Inject(EVENT_EMITTER_TOKEN) private eventEmitter: EventEmitter,
51
+ ) {}
52
+
53
+ async createUser(email: string) {
54
+ const userId = 'user-123';
55
+
56
+ // 发布事件
57
+ this.eventEmitter.emit<UserCreatedEvent>(USER_CREATED, {
58
+ userId,
59
+ email,
60
+ });
61
+
62
+ return { userId, email };
63
+ }
64
+ }
65
+
66
+ // 监听事件的服务
67
+ @Injectable()
68
+ class NotificationService {
69
+ @OnEvent(USER_CREATED)
70
+ handleUserCreated(payload: UserCreatedEvent) {
71
+ console.log(`欢迎邮件已发送至 ${payload.email}`);
72
+ }
73
+ }
74
+
75
+ // 配置模块
76
+ EventModule.forRoot({
77
+ maxListeners: 20,
78
+ });
79
+
80
+ EventModule.registerListeners([NotificationService]);
81
+
82
+ @Module({
83
+ imports: [EventModule],
84
+ providers: [UserService, NotificationService],
85
+ })
86
+ class AppModule {}
87
+
88
+ const app = new Application({ port: 3000 });
89
+ app.registerModule(AppModule);
90
+
91
+ // 模块注册后初始化事件监听器
92
+ EventModule.initializeListeners(app.getContainer());
93
+
94
+ app.listen(3000);
95
+ ```
96
+
97
+ ## 核心概念
98
+
99
+ ### 事件名称
100
+
101
+ 事件可以通过以下方式标识:
102
+
103
+ - **Symbol**:推荐使用,提供类型安全并避免命名冲突
104
+ - **字符串**:适用于动态事件或通配符匹配
105
+
106
+ ```typescript
107
+ // Symbol 事件(推荐)
108
+ const USER_CREATED = Symbol('user.created');
109
+
110
+ // 字符串事件
111
+ const orderEvent = 'order.created';
112
+ ```
113
+
114
+ ### 事件负载
115
+
116
+ 事件可以携带任何数据作为负载。建议定义接口以确保类型安全:
117
+
118
+ ```typescript
119
+ interface UserCreatedEvent {
120
+ userId: string;
121
+ email: string;
122
+ createdAt: Date;
123
+ }
124
+
125
+ // 使用类型化负载发布
126
+ eventEmitter.emit<UserCreatedEvent>(USER_CREATED, {
127
+ userId: '123',
128
+ email: 'user@example.com',
129
+ createdAt: new Date(),
130
+ });
131
+ ```
132
+
133
+ ## 事件模块配置
134
+
135
+ ```typescript
136
+ EventModule.forRoot({
137
+ // 启用通配符事件匹配
138
+ wildcard: true, // 默认: false
139
+
140
+ // 通配符匹配的分隔符
141
+ delimiter: '.', // 默认: '.'
142
+
143
+ // 全局事件前缀
144
+ globalPrefix: 'app', // 可选
145
+
146
+ // 每个事件的最大监听器数量(内存泄漏警告)
147
+ maxListeners: 10, // 默认: 10
148
+
149
+ // 自定义错误处理器
150
+ onError: (error, event, payload) => {
151
+ console.error(`事件 ${String(event)} 发生错误:`, error);
152
+ },
153
+ });
154
+ ```
155
+
156
+ ## 发布事件
157
+
158
+ ### 同步发布
159
+
160
+ 使用 `emit()` 同步发布事件。异步监听器会被触发但不会等待:
161
+
162
+ ```typescript
163
+ @Injectable()
164
+ class OrderService {
165
+ constructor(
166
+ @Inject(EVENT_EMITTER_TOKEN) private eventEmitter: EventEmitter,
167
+ ) {}
168
+
169
+ createOrder(userId: string, amount: number) {
170
+ const order = { id: 'order-1', userId, amount };
171
+
172
+ // 发布事件(不等待异步监听器)
173
+ this.eventEmitter.emit('order.created', {
174
+ orderId: order.id,
175
+ userId,
176
+ amount,
177
+ });
178
+
179
+ return order;
180
+ }
181
+ }
182
+ ```
183
+
184
+ ### 异步发布
185
+
186
+ 使用 `emitAsync()` 等待所有监听器(包括异步监听器)完成:
187
+
188
+ ```typescript
189
+ async createOrder(userId: string, amount: number) {
190
+ const order = { id: 'order-1', userId, amount };
191
+
192
+ // 等待所有监听器完成
193
+ await this.eventEmitter.emitAsync('order.created', {
194
+ orderId: order.id,
195
+ userId,
196
+ amount,
197
+ });
198
+
199
+ return order;
200
+ }
201
+ ```
202
+
203
+ ## 监听事件
204
+
205
+ ### 使用 `@OnEvent()` 装饰器
206
+
207
+ 推荐的事件监听方式:
208
+
209
+ ```typescript
210
+ @Injectable()
211
+ class NotificationService {
212
+ @OnEvent('user.created')
213
+ handleUserCreated(payload: { email: string }) {
214
+ console.log(`发送欢迎邮件至 ${payload.email}`);
215
+ }
216
+
217
+ @OnEvent(USER_DELETED)
218
+ async handleUserDeleted(payload: { userId: string }) {
219
+ await this.cleanupUserData(payload.userId);
220
+ }
221
+ }
222
+ ```
223
+
224
+ ### 手动订阅
225
+
226
+ 你也可以使用 EventEmitter 手动订阅:
227
+
228
+ ```typescript
229
+ @Injectable()
230
+ class DynamicListener {
231
+ constructor(
232
+ @Inject(EVENT_EMITTER_TOKEN) private eventEmitter: EventEmitter,
233
+ ) {
234
+ // 订阅
235
+ const unsubscribe = this.eventEmitter.on('custom.event', (payload) => {
236
+ console.log('收到:', payload);
237
+ });
238
+
239
+ // 之后: 取消订阅
240
+ // unsubscribe();
241
+ }
242
+ }
243
+ ```
244
+
245
+ ### 一次性监听器
246
+
247
+ ```typescript
248
+ // 使用装饰器(监听器在第一次调用后被移除)
249
+ // 注意: @OnEvent 不直接支持 once,请使用手动订阅
250
+
251
+ // 手动一次性订阅
252
+ this.eventEmitter.once('setup.complete', (payload) => {
253
+ console.log('设置完成!');
254
+ });
255
+ ```
256
+
257
+ ## 事件优先级
258
+
259
+ 优先级高的监听器先执行:
260
+
261
+ ```typescript
262
+ @Injectable()
263
+ class HighPriorityService {
264
+ @OnEvent('order.created', { priority: 100 })
265
+ validateOrder(payload: OrderCreatedEvent) {
266
+ // 最先执行
267
+ console.log('验证订单...');
268
+ }
269
+ }
270
+
271
+ @Injectable()
272
+ class LowPriorityService {
273
+ @OnEvent('order.created', { priority: 1 })
274
+ logOrder(payload: OrderCreatedEvent) {
275
+ // 最后执行
276
+ console.log('记录订单...');
277
+ }
278
+ }
279
+ ```
280
+
281
+ 默认优先级为 `0`。相同优先级的监听器按注册顺序执行。
282
+
283
+ ## 异步事件处理
284
+
285
+ 将监听器标记为异步以确保正确的错误处理:
286
+
287
+ ```typescript
288
+ @Injectable()
289
+ class EmailService {
290
+ @OnEvent('user.created', { async: true })
291
+ async sendWelcomeEmail(payload: { email: string }) {
292
+ await this.mailer.send({
293
+ to: payload.email,
294
+ subject: '欢迎!',
295
+ body: '...',
296
+ });
297
+ }
298
+ }
299
+ ```
300
+
301
+ 使用 `emit()` 时:
302
+ - 异步监听器被触发但不会等待
303
+ - 错误会被捕获并传递给错误处理器
304
+
305
+ 使用 `emitAsync()` 时:
306
+ - 所有监听器(同步和异步)都会被等待
307
+ - 所有错误都会被捕获和处理
308
+
309
+ ## 通配符事件
310
+
311
+ 在模块配置中启用通配符匹配:
312
+
313
+ ```typescript
314
+ EventModule.forRoot({
315
+ wildcard: true,
316
+ });
317
+ ```
318
+
319
+ ### 单通配符 (`*`)
320
+
321
+ 精确匹配一个段:
322
+
323
+ ```typescript
324
+ @OnEvent('user.*')
325
+ handleAnyUserEvent(payload: unknown) {
326
+ // 匹配: user.created, user.updated, user.deleted
327
+ // 不匹配: user.profile.updated
328
+ }
329
+ ```
330
+
331
+ ### 双通配符 (`**`)
332
+
333
+ 匹配任意数量的段:
334
+
335
+ ```typescript
336
+ @OnEvent('order.**')
337
+ handleAllOrderEvents(payload: unknown) {
338
+ // 匹配: order.created, order.item.added, order.payment.completed
339
+ }
340
+ ```
341
+
342
+ ## 错误处理
343
+
344
+ ### 全局错误处理器
345
+
346
+ ```typescript
347
+ EventModule.forRoot({
348
+ onError: (error, event, payload) => {
349
+ // 记录到监控服务
350
+ console.error(`事件 ${String(event)} 处理器错误:`, error);
351
+
352
+ // 可选择重新抛出或处理
353
+ },
354
+ });
355
+ ```
356
+
357
+ ### 监听器中的 Try-Catch
358
+
359
+ ```typescript
360
+ @OnEvent('risky.event', { async: true })
361
+ async handleRiskyEvent(payload: unknown) {
362
+ try {
363
+ await this.riskyOperation(payload);
364
+ } catch (error) {
365
+ // 处理或记录错误
366
+ console.error('处理事件失败:', error);
367
+ // 可选择重新抛出以触发全局错误处理器
368
+ throw error;
369
+ }
370
+ }
371
+ ```
372
+
373
+ ## 最佳实践
374
+
375
+ ### 1. 使用 Symbol 作为事件名称
376
+
377
+ ```typescript
378
+ // 好: 类型安全,无命名冲突
379
+ export const USER_CREATED = Symbol('user.created');
380
+
381
+ // 避免: 可能与其他事件冲突
382
+ const eventName = 'user.created';
383
+ ```
384
+
385
+ ### 2. 定义事件负载接口
386
+
387
+ ```typescript
388
+ // 好: 清晰的契约
389
+ export interface UserCreatedEvent {
390
+ userId: string;
391
+ email: string;
392
+ createdAt: Date;
393
+ }
394
+
395
+ // 避免: 不清晰的负载结构
396
+ eventEmitter.emit(USER_CREATED, { userId, email, date: new Date() });
397
+ ```
398
+
399
+ ### 3. 保持监听器职责单一
400
+
401
+ ```typescript
402
+ // 好: 单一职责
403
+ @OnEvent(USER_CREATED)
404
+ sendWelcomeEmail(payload: UserCreatedEvent) { ... }
405
+
406
+ @OnEvent(USER_CREATED)
407
+ trackUserSignup(payload: UserCreatedEvent) { ... }
408
+
409
+ // 避免: 职责过多
410
+ @OnEvent(USER_CREATED)
411
+ handleUserCreated(payload: UserCreatedEvent) {
412
+ this.sendEmail();
413
+ this.trackAnalytics();
414
+ this.notifyAdmin();
415
+ this.createDefaultSettings();
416
+ }
417
+ ```
418
+
419
+ ### 4. 优雅地处理错误
420
+
421
+ ```typescript
422
+ // 好: 错误不会破坏其他监听器
423
+ @OnEvent('payment.failed', { async: true })
424
+ async handlePaymentFailure(payload: PaymentFailedEvent) {
425
+ try {
426
+ await this.notifyUser(payload.userId);
427
+ } catch (error) {
428
+ this.logger.error('通知用户失败', error);
429
+ // 除非必要,不要重新抛出
430
+ }
431
+ }
432
+ ```
433
+
434
+ ### 5. 明智地使用优先级
435
+
436
+ ```typescript
437
+ // 好: 处理前先验证
438
+ @OnEvent('order.submitted', { priority: 100 })
439
+ validateOrder(payload: OrderEvent) { ... }
440
+
441
+ @OnEvent('order.submitted', { priority: 50 })
442
+ processOrder(payload: OrderEvent) { ... }
443
+
444
+ @OnEvent('order.submitted', { priority: 1 })
445
+ logOrder(payload: OrderEvent) { ... }
446
+ ```
447
+
448
+ ## API 参考
449
+
450
+ ### EventModule
451
+
452
+ | 方法 | 描述 |
453
+ |------|------|
454
+ | `forRoot(options?)` | 配置事件模块 |
455
+ | `registerListeners(classes)` | 注册监听器类 |
456
+ | `initializeListeners(container, additional?)` | 初始化并扫描监听器 |
457
+ | `getEventEmitter(container)` | 获取 EventEmitter 实例 |
458
+
459
+ ### EventEmitter
460
+
461
+ | 方法 | 描述 |
462
+ |------|------|
463
+ | `emit(event, payload)` | 同步发布事件 |
464
+ | `emitAsync(event, payload)` | 发布事件并等待所有监听器 |
465
+ | `on(event, listener, options?)` | 订阅事件 |
466
+ | `once(event, listener, options?)` | 一次性订阅事件 |
467
+ | `off(event, listener)` | 取消订阅事件 |
468
+ | `removeAllListeners(event?)` | 移除所有监听器 |
469
+ | `listenerCount(event)` | 获取事件的监听器数量 |
470
+ | `eventNames()` | 获取所有已注册的事件名称 |
471
+
472
+ ### @OnEvent 装饰器
473
+
474
+ ```typescript
475
+ @OnEvent(event: string | symbol, options?: {
476
+ async?: boolean; // 默认: false
477
+ priority?: number; // 默认: 0
478
+ })
479
+ ```
480
+
481
+ ### EventModuleOptions
482
+
483
+ | 选项 | 类型 | 默认值 | 描述 |
484
+ |------|------|--------|------|
485
+ | `wildcard` | `boolean` | `false` | 启用通配符匹配 |
486
+ | `delimiter` | `string` | `'.'` | 通配符分隔符 |
487
+ | `globalPrefix` | `string` | - | 所有事件的前缀 |
488
+ | `maxListeners` | `number` | `10` | 每个事件的最大监听器数量 |
489
+ | `onError` | `function` | - | 全局错误处理器 |
490
+
491
+ ## 相关文档
492
+
493
+ - [开发指南](./guide.md) - 框架指南
494
+ - [请求生命周期](./request-lifecycle.md) - 理解请求流程