@dangao/bun-server 1.8.3 → 1.10.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 (88) hide show
  1. package/README.md +60 -6
  2. package/dist/core/application.d.ts +12 -0
  3. package/dist/core/application.d.ts.map +1 -1
  4. package/dist/core/server.d.ts +7 -0
  5. package/dist/core/server.d.ts.map +1 -1
  6. package/dist/events/event-module.d.ts +4 -0
  7. package/dist/events/event-module.d.ts.map +1 -1
  8. package/dist/events/types.d.ts +16 -0
  9. package/dist/events/types.d.ts.map +1 -1
  10. package/dist/index.js +4969 -4882
  11. package/docs/custom-decorators.md +1 -7
  12. package/docs/extensions.md +0 -2
  13. package/docs/guide.md +0 -1
  14. package/docs/zh/custom-decorators.md +1 -7
  15. package/docs/zh/extensions.md +0 -2
  16. package/docs/zh/guide.md +0 -1
  17. package/docs/zh/migration.md +0 -5
  18. package/package.json +4 -4
  19. package/src/core/application.ts +38 -0
  20. package/src/core/server.ts +9 -0
  21. package/src/events/event-module.ts +108 -0
  22. package/src/events/types.ts +19 -0
  23. package/tests/auth/auth-decorators.test.ts +0 -1
  24. package/tests/auth/oauth2-service.test.ts +0 -1
  25. package/tests/cache/cache-decorators-extended.test.ts +0 -1
  26. package/tests/cache/cache-decorators.test.ts +0 -1
  27. package/tests/cache/cache-interceptors.test.ts +0 -1
  28. package/tests/cache/cache-module.test.ts +0 -1
  29. package/tests/cache/cache-service-proxy.test.ts +0 -1
  30. package/tests/config/config-center-integration.test.ts +0 -1
  31. package/tests/config/config-module-extended.test.ts +0 -1
  32. package/tests/config/config-module.test.ts +0 -1
  33. package/tests/controller/controller.test.ts +0 -1
  34. package/tests/controller/param-binder.test.ts +0 -1
  35. package/tests/controller/path-combination.test.ts +0 -1
  36. package/tests/core/application.test.ts +34 -0
  37. package/tests/database/database-module.test.ts +0 -1
  38. package/tests/database/orm.test.ts +0 -1
  39. package/tests/database/postgres-mysql-integration.test.ts +0 -1
  40. package/tests/database/transaction.test.ts +0 -1
  41. package/tests/di/container.test.ts +0 -1
  42. package/tests/error/error-handler.test.ts +0 -1
  43. package/tests/events/event-decorators.test.ts +0 -1
  44. package/tests/events/event-listener-scanner.test.ts +0 -1
  45. package/tests/events/event-module.test.ts +0 -1
  46. package/tests/extensions/logger-module.test.ts +0 -1
  47. package/tests/health/health-module.test.ts +0 -1
  48. package/tests/integration/oauth2-e2e.test.ts +0 -1
  49. package/tests/integration/session-e2e.test.ts +0 -1
  50. package/tests/interceptor/base-interceptor.test.ts +0 -1
  51. package/tests/interceptor/builtin/cache-interceptor.test.ts +0 -1
  52. package/tests/interceptor/builtin/log-interceptor.test.ts +0 -1
  53. package/tests/interceptor/builtin/permission-interceptor.test.ts +0 -1
  54. package/tests/interceptor/interceptor-advanced-integration.test.ts +0 -1
  55. package/tests/interceptor/interceptor-chain.test.ts +0 -1
  56. package/tests/interceptor/interceptor-integration.test.ts +0 -1
  57. package/tests/interceptor/interceptor-metadata.test.ts +0 -1
  58. package/tests/interceptor/interceptor-registry.test.ts +0 -1
  59. package/tests/interceptor/perf/interceptor-performance.test.ts +0 -1
  60. package/tests/metrics/metrics-module.test.ts +0 -1
  61. package/tests/microservice/config-center.test.ts +0 -1
  62. package/tests/microservice/service-client-decorators.test.ts +0 -1
  63. package/tests/microservice/service-registry-decorators.test.ts +0 -1
  64. package/tests/microservice/service-registry.test.ts +0 -1
  65. package/tests/middleware/builtin/middleware-builtin-extended.test.ts +0 -1
  66. package/tests/middleware/builtin/rate-limit.test.ts +0 -1
  67. package/tests/middleware/middleware-decorators.test.ts +0 -1
  68. package/tests/middleware/middleware-pipeline.test.ts +0 -1
  69. package/tests/middleware/middleware.test.ts +0 -1
  70. package/tests/perf/optimization.test.ts +0 -1
  71. package/tests/queue/queue-decorators.test.ts +0 -1
  72. package/tests/queue/queue-module.test.ts +0 -1
  73. package/tests/queue/queue-service.test.ts +0 -1
  74. package/tests/router/router-decorators.test.ts +0 -1
  75. package/tests/router/router-extended.test.ts +0 -1
  76. package/tests/security/guards/guards-integration.test.ts +0 -1
  77. package/tests/security/guards/guards.test.ts +0 -1
  78. package/tests/security/guards/reflector.test.ts +0 -1
  79. package/tests/security/security-filter.test.ts +0 -1
  80. package/tests/security/security-module-extended.test.ts +0 -1
  81. package/tests/security/security-module.test.ts +0 -1
  82. package/tests/session/session-decorators.test.ts +0 -1
  83. package/tests/session/session-module.test.ts +0 -1
  84. package/tests/swagger/decorators.test.ts +0 -1
  85. package/tests/swagger/swagger-module.test.ts +0 -1
  86. package/tests/swagger/ui.test.ts +0 -1
  87. package/tests/validation/class-validator.test.ts +0 -1
  88. package/tests/validation/controller-validation.test.ts +0 -1
@@ -27,11 +27,9 @@ Bun Server Framework provides a powerful interceptor mechanism that allows you t
27
27
 
28
28
  ### Basic Decorator Pattern
29
29
 
30
- A custom decorator is a function that returns a `MethodDecorator`. It uses `reflect-metadata` to store metadata on the method.
30
+ A custom decorator is a function that returns a `MethodDecorator`. It uses the Reflect metadata API to store metadata on the method.
31
31
 
32
32
  ```typescript
33
- import 'reflect-metadata';
34
-
35
33
  // 1. Define a metadata key (use Symbol for uniqueness)
36
34
  export const MY_METADATA_KEY = Symbol('@my-app:my-decorator');
37
35
 
@@ -260,8 +258,6 @@ class MyInterceptor extends BaseInterceptor {
260
258
  ### Storing Metadata
261
259
 
262
260
  ```typescript
263
- import 'reflect-metadata';
264
-
265
261
  const METADATA_KEY = Symbol('my-metadata');
266
262
 
267
263
  // Store metadata
@@ -337,7 +333,6 @@ class MyInterceptor extends BaseInterceptor {
337
333
  ### Example 1: Simple Logging Interceptor
338
334
 
339
335
  ```typescript
340
- import 'reflect-metadata';
341
336
  import { BaseInterceptor } from '@dangao/bun-server';
342
337
  import type { Container } from '@dangao/bun-server';
343
338
  import type { Context } from '@dangao/bun-server';
@@ -375,7 +370,6 @@ export class LogInterceptor extends BaseInterceptor {
375
370
  ### Example 2: Rate Limiting Interceptor
376
371
 
377
372
  ```typescript
378
- import 'reflect-metadata';
379
373
  import { BaseInterceptor, HttpException } from '@dangao/bun-server';
380
374
  import type { Container } from '@dangao/bun-server';
381
375
  import type { Context } from '@dangao/bun-server';
@@ -499,8 +499,6 @@ You can create custom decorators to extend controller and route functionality.
499
499
  ### Creating Decorators
500
500
 
501
501
  ```typescript
502
- import 'reflect-metadata';
503
-
504
502
  // Cache decorator
505
503
  export function Cache(ttl: number) {
506
504
  return function (target: any, propertyKey: string, descriptor: PropertyDescriptor) {
package/docs/guide.md CHANGED
@@ -15,7 +15,6 @@ For detailed lifecycle documentation, see [Request Lifecycle](./request-lifecycl
15
15
  ## 1. Initialize Application
16
16
 
17
17
  ```ts
18
- import "reflect-metadata";
19
18
  import { Application } from "@dangao/bun-server";
20
19
 
21
20
  const app = new Application({ port: 3000 });
@@ -29,12 +29,10 @@ AOP(面向切面编程)。这使您能够添加横切关注点,如缓存
29
29
 
30
30
  ### 基本装饰器模式
31
31
 
32
- 自定义装饰器是一个返回 `MethodDecorator` 的函数。它使用 `reflect-metadata`
32
+ 自定义装饰器是一个返回 `MethodDecorator` 的函数。它使用 Reflect 元数据 API
33
33
  在方法上存储元数据。
34
34
 
35
35
  ```typescript
36
- import "reflect-metadata";
37
-
38
36
  // 1. 定义元数据键(使用 Symbol 确保唯一性)
39
37
  export const MY_METADATA_KEY = Symbol("@my-app:my-decorator");
40
38
 
@@ -280,8 +278,6 @@ class MyInterceptor extends BaseInterceptor {
280
278
  ### 存储元数据
281
279
 
282
280
  ```typescript
283
- import "reflect-metadata";
284
-
285
281
  const METADATA_KEY = Symbol("my-metadata");
286
282
 
287
283
  // 存储元数据
@@ -364,7 +360,6 @@ class MyInterceptor extends BaseInterceptor {
364
360
  ### 示例 1:简单日志拦截器
365
361
 
366
362
  ```typescript
367
- import 'reflect-metadata';
368
363
  import { BaseInterceptor } from '@dangao/bun-server';
369
364
  import type { Container } from '@dangao/bun-server';
370
365
  import type { Context } from '@dangao/bun-server';
@@ -402,7 +397,6 @@ export class LogInterceptor extends BaseInterceptor {
402
397
  ### 示例 2:限流拦截器
403
398
 
404
399
  ```typescript
405
- import 'reflect-metadata';
406
400
  import { BaseInterceptor, HttpException } from '@dangao/bun-server';
407
401
  import type { Container } from '@dangao/bun-server';
408
402
  import type { Context } from '@dangao/bun-server';
@@ -511,8 +511,6 @@ app.listen();
511
511
  ### 创建装饰器
512
512
 
513
513
  ```typescript
514
- import "reflect-metadata";
515
-
516
514
  // 缓存装饰器
517
515
  export function Cache(ttl: number) {
518
516
  return function (
package/docs/zh/guide.md CHANGED
@@ -15,7 +15,6 @@ HTTP 请求 → 中间件 → 安全 → 路由 → 拦截器(前置) → 验证
15
15
  ## 1. 初始化应用
16
16
 
17
17
  ```ts
18
- import "reflect-metadata";
19
18
  import { Application } from "@dangao/bun-server";
20
19
 
21
20
  const app = new Application({ port: 3000 });
@@ -12,11 +12,6 @@
12
12
  "emitDecoratorMetadata": true
13
13
  }
14
14
  ```
15
- - 在应用入口(如 `main.ts`)导入一次 `reflect-metadata`:
16
- ```ts
17
- import 'reflect-metadata';
18
- ```
19
-
20
15
  ## 2. 路由与控制器
21
16
 
22
17
  - 将旧的函数式注册迁移到装饰器:
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@dangao/bun-server",
3
- "version": "1.8.3",
3
+ "version": "1.10.0",
4
4
  "type": "module",
5
5
  "main": "./dist/index.js",
6
6
  "types": "./dist/index.d.ts",
@@ -25,7 +25,7 @@
25
25
  ],
26
26
  "files": [
27
27
  "dist",
28
- "readme.md",
28
+ "README.md",
29
29
  "LICENSE",
30
30
  "src",
31
31
  "tests",
@@ -38,7 +38,7 @@
38
38
  "url": "https://github.com/dangaogit/bun-server/issues"
39
39
  },
40
40
  "engines": {
41
- "bun": ">=1.3.3"
41
+ "bun": ">=1.3.10"
42
42
  },
43
43
  "scripts": {
44
44
  "dev": "bun --watch src/index.ts",
@@ -58,6 +58,6 @@
58
58
  "dependencies": {
59
59
  "reflect-metadata": "^0.2.2",
60
60
  "@dangao/logsmith": "0.1.1",
61
- "@dangao/nacos-client": "0.1.0"
61
+ "@dangao/nacos-client": "0.1.1"
62
62
  }
63
63
  }
@@ -18,6 +18,7 @@ import { ConfigService } from '../config/service';
18
18
  import { ConfigModule } from '../config/config-module';
19
19
  import { CacheModule, CACHE_POST_PROCESSOR_TOKEN } from '../cache';
20
20
  import { LoggerManager } from '@dangao/logsmith';
21
+ import { EventModule } from '../events/event-module';
21
22
 
22
23
  /**
23
24
  * 应用配置选项
@@ -44,6 +45,14 @@ export interface ApplicationOptions {
44
45
  * 默认 true
45
46
  */
46
47
  enableSignalHandlers?: boolean;
48
+
49
+ /**
50
+ * 是否启用 SO_REUSEPORT
51
+ * 允许多进程绑定同一端口,用于多进程负载均衡
52
+ * 仅 Linux 有效,macOS/Windows 会忽略
53
+ * @default false
54
+ */
55
+ reusePort?: boolean;
47
56
  }
48
57
 
49
58
  /**
@@ -102,12 +111,16 @@ export class Application {
102
111
  // 初始化配置中心集成(在所有模块注册完成后)
103
112
  await this.initializeConfigCenter();
104
113
 
114
+ // 自动初始化事件监听器(如果 EventModule 已注册且启用了 autoScan)
115
+ this.initializeEventListeners();
116
+
105
117
  const finalPort = port ?? this.options.port ?? 3000;
106
118
  const finalHostname = hostname ?? this.options.hostname;
107
119
 
108
120
  const serverOptions: ServerOptions = {
109
121
  port: finalPort,
110
122
  hostname: finalHostname,
123
+ reusePort: this.options.reusePort,
111
124
  fetch: this.handleRequest.bind(this),
112
125
  websocketRegistry: this.websocketRegistry,
113
126
  gracefulShutdownTimeout: this.options.gracefulShutdownTimeout,
@@ -178,6 +191,31 @@ export class Application {
178
191
  }
179
192
  }
180
193
 
194
+ /**
195
+ * 初始化事件监听器
196
+ * 在所有模块注册完成后调用,自动扫描并注册使用 @OnEvent 装饰器的类
197
+ */
198
+ private initializeEventListeners(): void {
199
+ const container = this.getContainer();
200
+
201
+ // 检查 EventModule 是否已注册
202
+ const registry = ModuleRegistry.getInstance();
203
+ const eventModuleRef = registry.getModuleRef(EventModule);
204
+
205
+ if (!eventModuleRef) {
206
+ // EventModule 未注册,跳过
207
+ return;
208
+ }
209
+
210
+ // 调用自动初始化
211
+ const initialized = EventModule.autoInitialize(container);
212
+
213
+ if (initialized) {
214
+ const logger = LoggerManager.getLogger();
215
+ logger.debug('[Application] Event listeners initialized automatically');
216
+ }
217
+ }
218
+
181
219
  /**
182
220
  * 停止应用(立即停止,不等待请求完成)
183
221
  */
@@ -33,6 +33,14 @@ export interface ServerOptions {
33
33
  * 默认 30 秒
34
34
  */
35
35
  gracefulShutdownTimeout?: number;
36
+
37
+ /**
38
+ * 是否启用 SO_REUSEPORT
39
+ * 允许多进程绑定同一端口,用于多进程负载均衡
40
+ * 仅 Linux 有效,macOS/Windows 会忽略
41
+ * @default false
42
+ */
43
+ reusePort?: boolean;
36
44
  }
37
45
 
38
46
  /**
@@ -70,6 +78,7 @@ export class BunServer {
70
78
  this.server = Bun.serve({
71
79
  port: this.options.port ?? 3000,
72
80
  hostname: this.options.hostname,
81
+ reusePort: this.options.reusePort,
73
82
  fetch: (
74
83
  request: Request,
75
84
  server: Server<WebSocketConnectionData>,
@@ -102,6 +102,11 @@ export class EventModule {
102
102
  */
103
103
  private static listenerClasses: Function[] = [];
104
104
 
105
+ /**
106
+ * 模块选项
107
+ */
108
+ private static options: EventModuleOptions & { autoScan?: boolean } = {};
109
+
105
110
  /**
106
111
  * 创建事件模块
107
112
  * @param options - 模块配置
@@ -121,6 +126,12 @@ export class EventModule {
121
126
  * ```
122
127
  */
123
128
  public static forRoot(options: EventModuleOptions = {}): typeof EventModule {
129
+ // 保存选项(默认启用自动扫描)
130
+ EventModule.options = {
131
+ ...options,
132
+ autoScan: options.autoScan ?? true,
133
+ };
134
+
124
135
  const providers: ModuleProvider[] = [];
125
136
 
126
137
  // 创建事件发射器服务
@@ -269,4 +280,101 @@ export class EventModule {
269
280
 
270
281
  return undefined;
271
282
  }
283
+
284
+ /**
285
+ * 自动初始化事件监听器
286
+ * 由框架在应用启动时自动调用,扫描所有模块中使用 @OnEvent 装饰器的类并注册
287
+ *
288
+ * @param rootContainer - 根容器
289
+ * @returns 是否成功初始化
290
+ *
291
+ * @internal 此方法由框架内部调用,用户通常不需要手动调用
292
+ */
293
+ public static autoInitialize(rootContainer: Container): boolean {
294
+ // 检查是否启用自动扫描
295
+ if (EventModule.options.autoScan === false) {
296
+ return false;
297
+ }
298
+
299
+ // 获取 EventEmitter
300
+ const registry = ModuleRegistry.getInstance();
301
+ const eventModuleRef = registry.getModuleRef(EventModule);
302
+
303
+ if (!eventModuleRef) {
304
+ return false;
305
+ }
306
+
307
+ let eventEmitter: EventEmitter | undefined;
308
+ try {
309
+ eventEmitter = eventModuleRef.container.resolve<EventEmitter>(EVENT_EMITTER_TOKEN);
310
+ } catch {
311
+ return false;
312
+ }
313
+
314
+ if (!eventEmitter) {
315
+ return false;
316
+ }
317
+
318
+ // 收集所有监听器类
319
+ const listenerClasses = new Set<Function>();
320
+
321
+ // 1. 添加通过 registerListeners 注册的类
322
+ for (const listenerClass of EventModule.listenerClasses) {
323
+ listenerClasses.add(listenerClass);
324
+ }
325
+
326
+ // 2. 添加通过选项配置的强制包含类
327
+ if (EventModule.options.includeListeners) {
328
+ for (const listenerClass of EventModule.options.includeListeners) {
329
+ listenerClasses.add(listenerClass);
330
+ }
331
+ }
332
+
333
+ // 3. 自动扫描所有模块的 providers,并从对应的模块容器中解析实例
334
+ const shouldAutoScan = EventModule.options.autoScan ?? true;
335
+ if (shouldAutoScan === true) {
336
+ const allModuleRefs = Array.from(registry['moduleRefs'].values());
337
+
338
+ for (const moduleRef of allModuleRefs) {
339
+ for (const provider of moduleRef.metadata.providers) {
340
+ // 提取提供者类
341
+ let providerClass: Function | undefined;
342
+
343
+ if (typeof provider === 'function') {
344
+ providerClass = provider;
345
+ } else if ('useClass' in provider && provider.useClass) {
346
+ providerClass = provider.useClass;
347
+ }
348
+
349
+ // 检查是否是事件监听器类
350
+ if (providerClass && isEventListenerClass(providerClass)) {
351
+ // 检查是否被排除
352
+ const isExcluded = EventModule.options.excludeListeners?.includes(providerClass);
353
+ if (!isExcluded) {
354
+ // 使用模块容器创建 scanner 并注册监听器
355
+ // 这样可以确保解析的实例和控制器中注入的是同一个
356
+ const scanner = new EventListenerScanner(eventEmitter, moduleRef.container);
357
+ scanner.registerListenerClass(providerClass);
358
+ }
359
+ }
360
+ }
361
+ }
362
+ }
363
+
364
+ // 4. 注册通过选项配置的强制包含类(使用根容器)
365
+ if (EventModule.options.includeListeners) {
366
+ const scanner = new EventListenerScanner(eventEmitter, rootContainer);
367
+ for (const listenerClass of EventModule.options.includeListeners) {
368
+ scanner.registerListenerClass(listenerClass);
369
+ }
370
+ }
371
+
372
+ // 5. 注册通过 registerListeners 注册的类(使用根容器)
373
+ if (EventModule.listenerClasses.length > 0) {
374
+ const scanner = new EventListenerScanner(eventEmitter, rootContainer);
375
+ scanner.scanAndRegister(EventModule.listenerClasses);
376
+ }
377
+
378
+ return true;
379
+ }
272
380
  }
@@ -173,6 +173,25 @@ export interface EventModuleOptions {
173
173
  * @param payload - 事件负载
174
174
  */
175
175
  onError?: (error: Error, event: string | symbol, payload: unknown) => void;
176
+
177
+ /**
178
+ * 是否自动扫描和注册事件监听器
179
+ * 当设置为 true 时,框架会在应用启动时自动扫描所有模块中使用 @OnEvent 装饰器的类
180
+ * @default true
181
+ */
182
+ autoScan?: boolean;
183
+
184
+ /**
185
+ * 需要排除的监听器类(不自动注册)
186
+ * 用于在自动扫描时排除某些类
187
+ */
188
+ excludeListeners?: Function[];
189
+
190
+ /**
191
+ * 额外的监听器类(强制注册)
192
+ * 即使 autoScan 为 false,这些类也会被注册
193
+ */
194
+ includeListeners?: Function[];
176
195
  }
177
196
 
178
197
  /**
@@ -1,5 +1,4 @@
1
1
  import { describe, expect, test, beforeEach } from 'bun:test';
2
- import 'reflect-metadata';
3
2
 
4
3
  import {
5
4
  Auth,
@@ -1,5 +1,4 @@
1
1
  import { describe, expect, test, beforeEach } from 'bun:test';
2
- import 'reflect-metadata';
3
2
 
4
3
  import { OAuth2Service } from '../../src/auth/oauth2';
5
4
  import { JWTUtil } from '../../src/auth/jwt';
@@ -1,5 +1,4 @@
1
1
  import { describe, expect, test, beforeEach } from 'bun:test';
2
- import 'reflect-metadata';
3
2
 
4
3
  import {
5
4
  Cacheable,
@@ -1,4 +1,3 @@
1
- import 'reflect-metadata';
2
1
  import { describe, expect, test, beforeEach, afterEach } from 'bun:test';
3
2
  import { Application } from '../../src/core/application';
4
3
  import { Controller } from '../../src/controller/controller';
@@ -1,5 +1,4 @@
1
1
  import { describe, expect, test, beforeEach } from 'bun:test';
2
- import 'reflect-metadata';
3
2
 
4
3
  import {
5
4
  CacheableInterceptor,
@@ -1,5 +1,4 @@
1
1
  import { describe, expect, test, beforeEach } from 'bun:test';
2
- import 'reflect-metadata';
3
2
 
4
3
  import { MODULE_METADATA_KEY } from '../../src/di/module';
5
4
  import { Container } from '../../src/di/container';
@@ -1,5 +1,4 @@
1
1
  import { describe, expect, test, beforeEach } from 'bun:test';
2
- import 'reflect-metadata';
3
2
 
4
3
  import {
5
4
  CacheServiceProxy,
@@ -1,5 +1,4 @@
1
1
  import { describe, expect, test, beforeEach, afterEach } from 'bun:test';
2
- import 'reflect-metadata';
3
2
 
4
3
  import { MODULE_METADATA_KEY } from '../../src/di/module';
5
4
  import {
@@ -1,5 +1,4 @@
1
1
  import { describe, expect, test, beforeEach, afterEach } from 'bun:test';
2
- import 'reflect-metadata';
3
2
 
4
3
  import { ConfigModule } from '../../src/config/config-module';
5
4
  import { ConfigService } from '../../src/config/service';
@@ -1,5 +1,4 @@
1
1
  import { describe, expect, test, beforeEach } from 'bun:test';
2
- import 'reflect-metadata';
3
2
 
4
3
  import { MODULE_METADATA_KEY } from '../../src/di/module';
5
4
  import { Container } from '../../src/di/container';
@@ -1,4 +1,3 @@
1
- import 'reflect-metadata';
2
1
  import { describe, expect, test, beforeEach, afterEach } from 'bun:test';
3
2
  import { Application } from '../../src/core/application';
4
3
  import { Controller, ControllerRegistry } from '../../src/controller/controller';
@@ -1,5 +1,4 @@
1
1
  import { describe, expect, test, beforeEach } from 'bun:test';
2
- import 'reflect-metadata';
3
2
 
4
3
  import { ParamBinder } from '../../src/controller/param-binder';
5
4
  import {
@@ -1,4 +1,3 @@
1
- import 'reflect-metadata';
2
1
  import { describe, expect, test, beforeEach, afterEach } from 'bun:test';
3
2
  import { Application } from '../../src/core/application';
4
3
  import { Controller, ControllerRegistry } from '../../src/controller/controller';
@@ -53,5 +53,39 @@ describe('Application', () => {
53
53
  const data = await response.json();
54
54
  expect(data.error).toBe('Not Found');
55
55
  });
56
+
57
+ test('should accept reusePort option', async () => {
58
+ const port = getTestPort();
59
+ app = new Application({ port, reusePort: true });
60
+ await app.listen();
61
+
62
+ const server = app.getServer();
63
+ expect(server).toBeDefined();
64
+ expect(server?.isRunning()).toBe(true);
65
+
66
+ const response = await fetch(`http://localhost:${port}/api/ping`);
67
+ expect(response.status).toBe(404);
68
+ });
69
+
70
+ test('should allow two servers on same port with reusePort (Linux only)', async () => {
71
+ if (process.platform !== 'linux') {
72
+ console.log('Skipping reusePort dual-bind test: only works on Linux');
73
+ return;
74
+ }
75
+
76
+ const port = getTestPort();
77
+ app = new Application({ port, reusePort: true });
78
+ await app.listen();
79
+
80
+ const app2 = new Application({ port, reusePort: true });
81
+ await app2.listen();
82
+
83
+ try {
84
+ const response = await fetch(`http://localhost:${port}/api/test`);
85
+ expect(response.status).toBe(404);
86
+ } finally {
87
+ await app2.stop();
88
+ }
89
+ });
56
90
  });
57
91
 
@@ -3,7 +3,6 @@ import { DatabaseModule, DatabaseService, DATABASE_SERVICE_TOKEN } from '../../s
3
3
  import { Container } from '../../src/di/container';
4
4
  import { ModuleRegistry } from '../../src/di/module-registry';
5
5
  import { MODULE_METADATA_KEY } from '../../src/di/module';
6
- import 'reflect-metadata';
7
6
 
8
7
  describe('DatabaseModule', () => {
9
8
  let container: Container;
@@ -11,7 +11,6 @@ import {
11
11
  } from '../../src/database/orm';
12
12
  import { DatabaseService, DATABASE_SERVICE_TOKEN } from '../../src/database';
13
13
  import { Container } from '../../src/di/container';
14
- import 'reflect-metadata';
15
14
 
16
15
  // 测试实体
17
16
  @Entity('test_users')
@@ -7,7 +7,6 @@ import {
7
7
  import { Container } from '../../src/di/container';
8
8
  import { ModuleRegistry } from '../../src/di/module-registry';
9
9
  import { MODULE_METADATA_KEY } from '../../src/di/module';
10
- import 'reflect-metadata';
11
10
 
12
11
  /**
13
12
  * PostgreSQL/MySQL 集成测试
@@ -9,7 +9,6 @@ import {
9
9
  } from '../../src/database/orm';
10
10
  import { DatabaseService, DATABASE_SERVICE_TOKEN } from '../../src/database';
11
11
  import { Container } from '../../src/di/container';
12
- import 'reflect-metadata';
13
12
 
14
13
  describe('TransactionManager', () => {
15
14
  let container: Container;
@@ -1,4 +1,3 @@
1
- import 'reflect-metadata';
2
1
  import { describe, expect, test, beforeEach } from 'bun:test';
3
2
  import { Container } from '../../src/di/container';
4
3
  import { Lifecycle } from '../../src/di/types';
@@ -1,5 +1,4 @@
1
1
  import { describe, expect, test, beforeEach } from 'bun:test';
2
- import 'reflect-metadata';
3
2
 
4
3
  import { handleError } from '../../src/error/handler';
5
4
  import { HttpException, BadRequestException, UnauthorizedException, ForbiddenException, NotFoundException } from '../../src/error';
@@ -1,5 +1,4 @@
1
1
  import { describe, expect, test, beforeEach } from 'bun:test';
2
- import 'reflect-metadata';
3
2
  import {
4
3
  OnEvent,
5
4
  getOnEventMetadata,
@@ -1,5 +1,4 @@
1
1
  import { describe, expect, test, beforeEach } from 'bun:test';
2
- import 'reflect-metadata';
3
2
 
4
3
  import { EventListenerScanner, EVENT_LISTENER_SCANNER_TOKEN } from '../../src/events/event-module';
5
4
  import { EventEmitterService } from '../../src/events/service';
@@ -1,5 +1,4 @@
1
1
  import { describe, expect, test, beforeEach, afterEach } from 'bun:test';
2
- import 'reflect-metadata';
3
2
 
4
3
  import { EventModule } from '../../src/events/event-module';
5
4
  import { EventEmitterService } from '../../src/events/service';
@@ -1,5 +1,4 @@
1
1
  import { describe, expect, test, beforeEach } from 'bun:test';
2
- import 'reflect-metadata';
3
2
 
4
3
  import { Container } from '../../src/di/container';
5
4
  import { MODULE_METADATA_KEY } from '../../src/di/module';
@@ -1,5 +1,4 @@
1
1
  import { describe, expect, test } from 'bun:test';
2
- import 'reflect-metadata';
3
2
 
4
3
  import { MODULE_METADATA_KEY } from '../../src/di/module';
5
4
  import {
@@ -1,4 +1,3 @@
1
- import 'reflect-metadata';
2
1
  import { describe, expect, test, afterEach, beforeEach } from 'bun:test';
3
2
  import { Application } from '../../src/core/application';
4
3
  import { SecurityModule } from '../../src/security/security-module';
@@ -1,5 +1,4 @@
1
1
  import { describe, expect, test, beforeEach, afterEach } from 'bun:test';
2
- import 'reflect-metadata';
3
2
  import {
4
3
  Application,
5
4
  SessionModule,
@@ -1,5 +1,4 @@
1
1
  import { describe, expect, test, beforeEach } from 'bun:test';
2
- import 'reflect-metadata';
3
2
 
4
3
  import { BaseInterceptor } from '../../src/interceptor/base-interceptor';
5
4
  import { Container } from '../../src/di/container';
@@ -1,5 +1,4 @@
1
1
  import { describe, expect, test, beforeEach, afterEach } from 'bun:test';
2
- import 'reflect-metadata';
3
2
 
4
3
  import {
5
4
  Cache,
@@ -1,5 +1,4 @@
1
1
  import { describe, expect, test, beforeEach, mock } from 'bun:test';
2
- import 'reflect-metadata';
3
2
 
4
3
  import { Container } from '../../../src/di/container';
5
4
  import { Context } from '../../../src/core/context';