@dangao/bun-server 2.0.8 → 2.2.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 (97) hide show
  1. package/README.md +4 -0
  2. package/dist/controller/controller.d.ts.map +1 -1
  3. package/dist/core/application.d.ts +6 -1
  4. package/dist/core/application.d.ts.map +1 -1
  5. package/dist/core/server.d.ts +5 -0
  6. package/dist/core/server.d.ts.map +1 -1
  7. package/dist/database/database-context.d.ts +25 -0
  8. package/dist/database/database-context.d.ts.map +1 -0
  9. package/dist/database/database-extension.d.ts +8 -9
  10. package/dist/database/database-extension.d.ts.map +1 -1
  11. package/dist/database/database-module.d.ts +7 -1
  12. package/dist/database/database-module.d.ts.map +1 -1
  13. package/dist/database/db-proxy.d.ts +12 -0
  14. package/dist/database/db-proxy.d.ts.map +1 -0
  15. package/dist/database/index.d.ts +6 -1
  16. package/dist/database/index.d.ts.map +1 -1
  17. package/dist/database/orm/transaction-interceptor.d.ts +0 -16
  18. package/dist/database/orm/transaction-interceptor.d.ts.map +1 -1
  19. package/dist/database/orm/transaction-manager.d.ts +10 -61
  20. package/dist/database/orm/transaction-manager.d.ts.map +1 -1
  21. package/dist/database/service.d.ts.map +1 -1
  22. package/dist/database/sql-manager.d.ts +14 -0
  23. package/dist/database/sql-manager.d.ts.map +1 -0
  24. package/dist/database/sqlite-adapter.d.ts +32 -0
  25. package/dist/database/sqlite-adapter.d.ts.map +1 -0
  26. package/dist/database/strategy-decorator.d.ts +8 -0
  27. package/dist/database/strategy-decorator.d.ts.map +1 -0
  28. package/dist/database/types.d.ts +122 -1
  29. package/dist/database/types.d.ts.map +1 -1
  30. package/dist/di/container.d.ts +16 -0
  31. package/dist/di/container.d.ts.map +1 -1
  32. package/dist/di/lifecycle.d.ts +48 -0
  33. package/dist/di/lifecycle.d.ts.map +1 -1
  34. package/dist/di/module-registry.d.ts +10 -6
  35. package/dist/di/module-registry.d.ts.map +1 -1
  36. package/dist/index.d.ts +4 -4
  37. package/dist/index.d.ts.map +1 -1
  38. package/dist/index.js +3267 -2620
  39. package/dist/microservice/service-registry/service-registry-module.d.ts +16 -0
  40. package/dist/microservice/service-registry/service-registry-module.d.ts.map +1 -1
  41. package/dist/router/index.d.ts +1 -0
  42. package/dist/router/index.d.ts.map +1 -1
  43. package/dist/router/registry.d.ts +1 -1
  44. package/dist/router/registry.d.ts.map +1 -1
  45. package/dist/router/route.d.ts +2 -1
  46. package/dist/router/route.d.ts.map +1 -1
  47. package/dist/router/router.d.ts +1 -1
  48. package/dist/router/router.d.ts.map +1 -1
  49. package/dist/router/timeout-decorator.d.ts +6 -0
  50. package/dist/router/timeout-decorator.d.ts.map +1 -0
  51. package/docs/database.md +48 -15
  52. package/docs/idle-timeout.md +42 -0
  53. package/docs/lifecycle.md +80 -4
  54. package/docs/microservice-nacos.md +1 -0
  55. package/docs/microservice-service-registry.md +7 -0
  56. package/docs/zh/database.md +48 -15
  57. package/docs/zh/idle-timeout.md +41 -0
  58. package/docs/zh/lifecycle.md +49 -5
  59. package/docs/zh/microservice-nacos.md +1 -0
  60. package/docs/zh/microservice-service-registry.md +6 -0
  61. package/package.json +1 -1
  62. package/src/controller/controller.ts +11 -1
  63. package/src/core/application.ts +98 -26
  64. package/src/core/server.ts +10 -0
  65. package/src/database/database-context.ts +43 -0
  66. package/src/database/database-extension.ts +12 -45
  67. package/src/database/database-module.ts +254 -11
  68. package/src/database/db-proxy.ts +75 -0
  69. package/src/database/index.ts +29 -0
  70. package/src/database/orm/transaction-interceptor.ts +12 -149
  71. package/src/database/orm/transaction-manager.ts +143 -210
  72. package/src/database/service.ts +28 -2
  73. package/src/database/sql-manager.ts +62 -0
  74. package/src/database/sqlite-adapter.ts +121 -0
  75. package/src/database/strategy-decorator.ts +42 -0
  76. package/src/database/types.ts +133 -1
  77. package/src/di/container.ts +55 -1
  78. package/src/di/lifecycle.ts +114 -0
  79. package/src/di/module-registry.ts +78 -14
  80. package/src/index.ts +31 -1
  81. package/src/microservice/service-registry/service-registry-module.ts +25 -1
  82. package/src/router/index.ts +1 -0
  83. package/src/router/registry.ts +10 -1
  84. package/src/router/route.ts +31 -3
  85. package/src/router/router.ts +10 -1
  86. package/src/router/timeout-decorator.ts +35 -0
  87. package/tests/core/application.test.ts +10 -0
  88. package/tests/database/database-module.test.ts +91 -430
  89. package/tests/database/db-proxy.test.ts +93 -0
  90. package/tests/database/sql-manager.test.ts +43 -0
  91. package/tests/database/sqlite-adapter.test.ts +45 -0
  92. package/tests/database/strategy-decorator.test.ts +29 -0
  93. package/tests/database/transaction.test.ts +84 -222
  94. package/tests/di/lifecycle.test.ts +139 -1
  95. package/tests/di/scoped-lifecycle.test.ts +61 -0
  96. package/tests/microservice/service-registry.test.ts +15 -0
  97. package/tests/router/timeout-decorator.test.ts +48 -0
@@ -78,6 +78,59 @@ export type DatabaseConfig =
78
78
  | { type: 'postgres'; config: PostgresConfig }
79
79
  | { type: 'mysql'; config: MysqlConfig };
80
80
 
81
+ /**
82
+ * Bun.SQL 连接池配置
83
+ */
84
+ export interface BunSQLPoolOptions {
85
+ /**
86
+ * 最大物理连接数
87
+ * @default 10
88
+ */
89
+ max?: number;
90
+ /**
91
+ * 空闲连接超时(秒)
92
+ * @default 30
93
+ */
94
+ idleTimeout?: number;
95
+ /**
96
+ * 连接最大生存时间(秒)
97
+ * @default 0
98
+ */
99
+ maxLifetime?: number;
100
+ /**
101
+ * 获取连接超时(毫秒)
102
+ * @default 30000
103
+ */
104
+ connectionTimeout?: number;
105
+ }
106
+
107
+ /**
108
+ * Bun.SQL 配置(Postgres/MySQL)
109
+ */
110
+ export interface BunSQLConfig {
111
+ type: 'postgres' | 'mysql';
112
+ url: string;
113
+ pool?: BunSQLPoolOptions;
114
+ }
115
+
116
+ /**
117
+ * SQLite V2 配置
118
+ */
119
+ export interface SqliteV2Config {
120
+ type: 'sqlite';
121
+ database: string;
122
+ wal?: boolean;
123
+ maxWriteConcurrency?: number;
124
+ }
125
+
126
+ /**
127
+ * 多租户配置
128
+ */
129
+ export interface TenantConfig {
130
+ id: string;
131
+ config: BunSQLConfig | SqliteV2Config;
132
+ }
133
+
81
134
  /**
82
135
  * 连接池配置
83
136
  */
@@ -108,12 +161,59 @@ export interface ConnectionPoolOptions {
108
161
  * DatabaseModule 配置选项
109
162
  */
110
163
  export interface DatabaseModuleOptions {
164
+ /**
165
+ * 全局默认连接策略
166
+ * - pool: 每次查询走共享池(默认)
167
+ * - session: 首次查询惰性 reserve,整个请求复用同一连接
168
+ * @default "pool"
169
+ */
170
+ defaultStrategy?: 'pool' | 'session';
171
+
172
+ /**
173
+ * 多租户配置
174
+ */
175
+ tenants?: TenantConfig[];
176
+ /**
177
+ * 默认租户 ID
178
+ * @default "default"
179
+ */
180
+ defaultTenant?: string;
181
+
182
+ /**
183
+ * 单租户:数据库类型(V2)
184
+ */
185
+ type?: DatabaseType;
186
+ /**
187
+ * 单租户:Postgres/MySQL URL(V2)
188
+ */
189
+ url?: string;
190
+ /**
191
+ * 单租户:SQLite 文件路径(V2)
192
+ */
193
+ databasePath?: string;
194
+ /**
195
+ * 单租户:SQLite WAL 模式
196
+ * @default true
197
+ */
198
+ wal?: boolean;
199
+ /**
200
+ * 单租户:SQLite 最大写并发
201
+ * @default 1
202
+ */
203
+ maxWriteConcurrency?: number;
204
+ /**
205
+ * Bun.SQL 连接池参数(V2)
206
+ */
207
+ bunSqlPool?: BunSQLPoolOptions;
208
+
111
209
  /**
112
210
  * 数据库配置
211
+ * @deprecated 使用 V2 字段(type/url/databasePath)或 tenants
113
212
  */
114
- database: DatabaseConfig;
213
+ database?: DatabaseConfig;
115
214
  /**
116
215
  * 连接池配置
216
+ * @deprecated 旧连接池配置,仅用于兼容旧 DatabaseService
117
217
  */
118
218
  pool?: ConnectionPoolOptions;
119
219
  /**
@@ -135,6 +235,23 @@ export interface DatabaseModuleOptions {
135
235
  */
136
236
  drizzle?: unknown;
137
237
  };
238
+
239
+ /**
240
+ * @deprecated 旧字段兼容(用于构造 URL)
241
+ */
242
+ host?: string;
243
+ /**
244
+ * @deprecated 旧字段兼容(用于构造 URL)
245
+ */
246
+ port?: number;
247
+ /**
248
+ * @deprecated 旧字段兼容(用于构造 URL)
249
+ */
250
+ username?: string;
251
+ /**
252
+ * @deprecated 旧字段兼容(用于构造 URL)
253
+ */
254
+ password?: string;
138
255
  }
139
256
 
140
257
  /**
@@ -169,3 +286,18 @@ export const DATABASE_SERVICE_TOKEN = Symbol('@dangao/bun-server:database:servic
169
286
  * DatabaseModule Options Token
170
287
  */
171
288
  export const DATABASE_OPTIONS_TOKEN = Symbol('@dangao/bun-server:database:options');
289
+
290
+ /**
291
+ * BunSQLManager Token
292
+ */
293
+ export const BUN_SQL_MANAGER_TOKEN = Symbol('@dangao/bun-server:database:bun-sql-manager');
294
+
295
+ /**
296
+ * SQLite manager Token
297
+ */
298
+ export const SQLITE_MANAGER_TOKEN = Symbol('@dangao/bun-server:database:sqlite-manager');
299
+
300
+ /**
301
+ * db proxy Token
302
+ */
303
+ export const DB_TOKEN = Symbol('@dangao/bun-server:database:db');
@@ -14,6 +14,13 @@ import {
14
14
  import { LoggerManager } from "@dangao/logsmith";
15
15
  import type { Constructor } from "@/core/types";
16
16
  import { contextStore } from "../core/context-service";
17
+ import {
18
+ callComponentBeforeCreate,
19
+ callOnAfterCreate,
20
+ callOnBeforeDestroy,
21
+ callOnModuleDestroy,
22
+ callOnAfterDestroy,
23
+ } from "./lifecycle";
17
24
 
18
25
  /**
19
26
  * 依赖注入容器
@@ -365,6 +372,7 @@ export class Container {
365
372
  * @returns 实例
366
373
  */
367
374
  private instantiate<T>(constructor: Constructor<T>): T {
375
+ callComponentBeforeCreate(constructor);
368
376
  const plan = this.getDependencyPlan(constructor);
369
377
 
370
378
  let instance: T;
@@ -379,7 +387,9 @@ export class Container {
379
387
  }
380
388
 
381
389
  // 应用后处理器
382
- return this.applyPostProcessors(instance, constructor);
390
+ const processed = this.applyPostProcessors(instance, constructor);
391
+ callOnAfterCreate(processed);
392
+ return processed;
383
393
  }
384
394
 
385
395
  /**
@@ -409,6 +419,50 @@ export class Container {
409
419
  // scopedInstances 使用 WeakMap,当 Context 对象被 GC 时会自动清理
410
420
  }
411
421
 
422
+ /**
423
+ * 获取指定请求上下文下的 scoped 实例
424
+ * @param context - 请求上下文对象
425
+ * @returns 去重后的 scoped 实例列表
426
+ */
427
+ public getScopedInstances(context: object): unknown[] {
428
+ const scopedMap = this.scopedInstances.get(context);
429
+ if (!scopedMap || scopedMap.size === 0) {
430
+ return [];
431
+ }
432
+ const seen = new Set<unknown>();
433
+ const instances: unknown[] = [];
434
+ for (const instance of scopedMap.values()) {
435
+ if (!seen.has(instance)) {
436
+ seen.add(instance);
437
+ instances.push(instance);
438
+ }
439
+ }
440
+ return instances;
441
+ }
442
+
443
+ /**
444
+ * 清理指定请求上下文的 scoped 实例缓存
445
+ * @param context - 请求上下文对象
446
+ */
447
+ public clearScopedInstances(context: object): void {
448
+ this.scopedInstances.delete(context);
449
+ }
450
+
451
+ /**
452
+ * 触发指定请求上下文下 scoped 实例的销毁钩子并清理缓存
453
+ * @param context - 请求上下文对象
454
+ */
455
+ public async disposeScopedInstances(context: object): Promise<void> {
456
+ const instances = this.getScopedInstances(context);
457
+ if (instances.length === 0) {
458
+ return;
459
+ }
460
+ await callOnBeforeDestroy(instances);
461
+ await callOnModuleDestroy(instances);
462
+ await callOnAfterDestroy(instances);
463
+ this.clearScopedInstances(context);
464
+ }
465
+
412
466
  /**
413
467
  * 检查是否已注册
414
468
  * @param token - 提供者标识符
@@ -30,6 +30,38 @@ export interface OnApplicationShutdown {
30
30
  onApplicationShutdown(signal?: string): Promise<void> | void;
31
31
  }
32
32
 
33
+ /**
34
+ * 组件创建前钩子(静态类方法)
35
+ * 在实例化前调用,适用于 Controller / Injectable 类
36
+ */
37
+ export type ComponentClassBeforeCreate = {
38
+ onBeforeCreate(): void;
39
+ };
40
+
41
+ /**
42
+ * 组件创建后钩子(实例)
43
+ * 在实例化并完成后处理后调用
44
+ */
45
+ export interface OnAfterCreate {
46
+ onAfterCreate(): void;
47
+ }
48
+
49
+ /**
50
+ * 组件销毁前钩子(实例)
51
+ * 在 onModuleDestroy 之前调用(反向顺序)
52
+ */
53
+ export interface OnBeforeDestroy {
54
+ onBeforeDestroy(): Promise<void> | void;
55
+ }
56
+
57
+ /**
58
+ * 组件销毁后钩子(实例)
59
+ * 在 onModuleDestroy 之后调用(反向顺序)
60
+ */
61
+ export interface OnAfterDestroy {
62
+ onAfterDestroy(): Promise<void> | void;
63
+ }
64
+
33
65
  export function hasOnModuleInit(instance: unknown): instance is OnModuleInit {
34
66
  return (
35
67
  instance !== null &&
@@ -70,6 +102,64 @@ export function hasOnApplicationShutdown(instance: unknown): instance is OnAppli
70
102
  );
71
103
  }
72
104
 
105
+ export function hasComponentBeforeCreate(target: unknown): target is ComponentClassBeforeCreate {
106
+ return (
107
+ target !== null &&
108
+ target !== undefined &&
109
+ typeof target === 'function' &&
110
+ 'onBeforeCreate' in target &&
111
+ typeof (target as ComponentClassBeforeCreate).onBeforeCreate === 'function'
112
+ );
113
+ }
114
+
115
+ export function hasOnAfterCreate(instance: unknown): instance is OnAfterCreate {
116
+ return (
117
+ instance !== null &&
118
+ instance !== undefined &&
119
+ typeof instance === 'object' &&
120
+ 'onAfterCreate' in instance &&
121
+ typeof (instance as OnAfterCreate).onAfterCreate === 'function'
122
+ );
123
+ }
124
+
125
+ export function hasOnBeforeDestroy(instance: unknown): instance is OnBeforeDestroy {
126
+ return (
127
+ instance !== null &&
128
+ instance !== undefined &&
129
+ typeof instance === 'object' &&
130
+ 'onBeforeDestroy' in instance &&
131
+ typeof (instance as OnBeforeDestroy).onBeforeDestroy === 'function'
132
+ );
133
+ }
134
+
135
+ export function hasOnAfterDestroy(instance: unknown): instance is OnAfterDestroy {
136
+ return (
137
+ instance !== null &&
138
+ instance !== undefined &&
139
+ typeof instance === 'object' &&
140
+ 'onAfterDestroy' in instance &&
141
+ typeof (instance as OnAfterDestroy).onAfterDestroy === 'function'
142
+ );
143
+ }
144
+
145
+ /**
146
+ * 调用组件类静态 onBeforeCreate
147
+ */
148
+ export function callComponentBeforeCreate(target: unknown): void {
149
+ if (hasComponentBeforeCreate(target)) {
150
+ target.onBeforeCreate();
151
+ }
152
+ }
153
+
154
+ /**
155
+ * 调用组件实例 onAfterCreate
156
+ */
157
+ export function callOnAfterCreate(instance: unknown): void {
158
+ if (hasOnAfterCreate(instance)) {
159
+ instance.onAfterCreate();
160
+ }
161
+ }
162
+
73
163
  /**
74
164
  * 按顺序调用 onModuleInit
75
165
  */
@@ -115,3 +205,27 @@ export async function callOnApplicationShutdown(instances: unknown[], signal?: s
115
205
  }
116
206
  }
117
207
  }
208
+
209
+ /**
210
+ * 按反向顺序调用 onBeforeDestroy
211
+ */
212
+ export async function callOnBeforeDestroy(instances: unknown[]): Promise<void> {
213
+ for (let i = instances.length - 1; i >= 0; i--) {
214
+ const instance = instances[i];
215
+ if (hasOnBeforeDestroy(instance)) {
216
+ await instance.onBeforeDestroy();
217
+ }
218
+ }
219
+ }
220
+
221
+ /**
222
+ * 按反向顺序调用 onAfterDestroy
223
+ */
224
+ export async function callOnAfterDestroy(instances: unknown[]): Promise<void> {
225
+ for (let i = instances.length - 1; i >= 0; i--) {
226
+ const instance = instances[i];
227
+ if (hasOnAfterDestroy(instance)) {
228
+ await instance.onAfterDestroy();
229
+ }
230
+ }
231
+ }
@@ -11,6 +11,8 @@ import {
11
11
  callOnModuleDestroy,
12
12
  callOnApplicationBootstrap,
13
13
  callOnApplicationShutdown,
14
+ callOnBeforeDestroy,
15
+ callOnAfterDestroy,
14
16
  } from './lifecycle';
15
17
 
16
18
  interface ModuleRef {
@@ -225,63 +227,125 @@ export class ModuleRegistry {
225
227
  }
226
228
 
227
229
  /**
228
- * 解析所有模块中的 provider 实例,用于生命周期钩子调用
230
+ * 解析所有模块中的组件实例(providers + controllers),用于生命周期钩子调用
229
231
  */
230
- public resolveAllProviderInstances(): unknown[] {
232
+ public resolveAllComponentInstances(): unknown[] {
231
233
  const instances: unknown[] = [];
234
+ const seen = new Set<unknown>();
232
235
  for (const [, ref] of this.moduleRefs) {
233
236
  for (const provider of ref.metadata.providers) {
234
237
  try {
235
238
  if (typeof provider === 'function') {
236
- instances.push(ref.container.resolve(provider));
239
+ const instance = ref.container.resolve(provider);
240
+ if (!seen.has(instance)) {
241
+ seen.add(instance);
242
+ instances.push(instance);
243
+ }
237
244
  } else if ('useClass' in provider) {
238
245
  const token = provider.provide ?? provider.useClass;
239
- instances.push(ref.container.resolve(token as Constructor<unknown>));
246
+ const instance = ref.container.resolve(token as Constructor<unknown>);
247
+ if (!seen.has(instance)) {
248
+ seen.add(instance);
249
+ instances.push(instance);
250
+ }
240
251
  } else if ('useValue' in provider) {
241
- instances.push(provider.useValue);
252
+ if (!seen.has(provider.useValue)) {
253
+ seen.add(provider.useValue);
254
+ instances.push(provider.useValue);
255
+ }
242
256
  } else if ('useFactory' in provider) {
243
- instances.push(ref.container.resolve(provider.provide as Constructor<unknown>));
257
+ const instance = ref.container.resolve(provider.provide as Constructor<unknown>);
258
+ if (!seen.has(instance)) {
259
+ seen.add(instance);
260
+ instances.push(instance);
261
+ }
244
262
  }
245
263
  } catch (_error) {
246
264
  // skip providers that can't be resolved (e.g. pending async providers)
247
265
  }
248
266
  }
267
+ for (const controller of ref.metadata.controllers) {
268
+ try {
269
+ const instance = ref.container.resolve(controller);
270
+ if (!seen.has(instance)) {
271
+ seen.add(instance);
272
+ instances.push(instance);
273
+ }
274
+ } catch (_error) {
275
+ // skip controllers that can't be resolved
276
+ }
277
+ }
249
278
  }
250
279
  return instances;
251
280
  }
252
281
 
253
282
  /**
254
- * 调用所有 provider onModuleInit 钩子
283
+ * 调用所有组件(providers + controllers)的 onModuleInit 钩子
255
284
  */
256
285
  public async callModuleInitHooks(): Promise<void> {
257
- const instances = this.resolveAllProviderInstances();
286
+ const instances = this.resolveAllComponentInstances();
258
287
  await callOnModuleInit(instances);
259
288
  }
260
289
 
261
290
  /**
262
- * 调用所有 provider onApplicationBootstrap 钩子
291
+ * 调用所有组件(providers + controllers)的 onApplicationBootstrap 钩子
263
292
  */
264
293
  public async callBootstrapHooks(): Promise<void> {
265
- const instances = this.resolveAllProviderInstances();
294
+ const instances = this.resolveAllComponentInstances();
266
295
  await callOnApplicationBootstrap(instances);
267
296
  }
268
297
 
269
298
  /**
270
- * 调用所有 provider onModuleDestroy 钩子
299
+ * 调用所有组件(providers + controllers)的 onModuleDestroy 钩子
271
300
  */
272
301
  public async callModuleDestroyHooks(): Promise<void> {
273
- const instances = this.resolveAllProviderInstances();
302
+ const instances = this.resolveAllComponentInstances();
303
+ await callOnBeforeDestroy(instances);
274
304
  await callOnModuleDestroy(instances);
305
+ await callOnAfterDestroy(instances);
275
306
  }
276
307
 
277
308
  /**
278
- * 调用所有 provider onApplicationShutdown 钩子
309
+ * 调用所有组件(providers + controllers)的 onApplicationShutdown 钩子
279
310
  */
280
311
  public async callShutdownHooks(signal?: string): Promise<void> {
281
- const instances = this.resolveAllProviderInstances();
312
+ const instances = this.resolveAllComponentInstances();
282
313
  await callOnApplicationShutdown(instances, signal);
283
314
  }
284
315
 
316
+ /**
317
+ * 调用当前请求上下文下 scoped 组件的销毁钩子并清理缓存
318
+ */
319
+ public async disposeScopedInstances(context: object): Promise<void> {
320
+ const containers: Container[] = [];
321
+ if (this.rootContainer) {
322
+ containers.push(this.rootContainer);
323
+ }
324
+ containers.push(...this.getAllModuleContainers());
325
+
326
+ const instances: unknown[] = [];
327
+ const seen = new Set<unknown>();
328
+ for (const container of containers) {
329
+ const scopedInstances = container.getScopedInstances(context);
330
+ for (const instance of scopedInstances) {
331
+ if (!seen.has(instance)) {
332
+ seen.add(instance);
333
+ instances.push(instance);
334
+ }
335
+ }
336
+ }
337
+
338
+ if (instances.length > 0) {
339
+ await callOnBeforeDestroy(instances);
340
+ await callOnModuleDestroy(instances);
341
+ await callOnAfterDestroy(instances);
342
+ }
343
+
344
+ for (const container of containers) {
345
+ container.clearScopedInstances(context);
346
+ }
347
+ }
348
+
285
349
  private registerExport(parentContainer: Container, moduleRef: ModuleRef, token: ProviderToken): void {
286
350
  if (!moduleRef.container.isRegistered(token)) {
287
351
  throw new Error(
package/src/index.ts CHANGED
@@ -4,7 +4,7 @@ export { BunServer, type ServerOptions } from './core/server';
4
4
  export { ClusterManager, type ClusterOptions, type ClusterMode } from './core/cluster';
5
5
  export { Context } from './core/context';
6
6
  export { ContextService, CONTEXT_SERVICE_TOKEN, contextStore } from './core/context-service';
7
- export { Route, Router, RouteRegistry } from './router';
7
+ export { Route, Router, RouteRegistry, IdleTimeout } from './router';
8
8
  export { GET, POST, PUT, DELETE, PATCH } from './router/decorators';
9
9
  export type { HttpMethod, RouteHandler, RouteMatch } from './router/types';
10
10
  export { BodyParser, RequestWrapper, ResponseBuilder } from './request';
@@ -42,6 +42,10 @@ export type {
42
42
  OnModuleDestroy,
43
43
  OnApplicationBootstrap,
44
44
  OnApplicationShutdown,
45
+ ComponentClassBeforeCreate,
46
+ OnAfterCreate,
47
+ OnBeforeDestroy,
48
+ OnAfterDestroy,
45
49
  } from './di/lifecycle';
46
50
  export {
47
51
  InterceptorRegistry,
@@ -307,16 +311,41 @@ export {
307
311
  ConnectionPool,
308
312
  DatabaseHealthIndicator,
309
313
  DatabaseExtension,
314
+ BunSQLManager,
315
+ SqliteAdapter,
316
+ SqliteManager,
317
+ Semaphore,
318
+ db,
319
+ initDbProxy,
320
+ DbStrategy,
321
+ DbSession,
322
+ DB_STRATEGY_KEY,
323
+ getDbStrategy,
324
+ databaseSessionStore,
325
+ getCurrentSession,
326
+ runWithSession,
310
327
  DATABASE_SERVICE_TOKEN,
311
328
  DATABASE_OPTIONS_TOKEN,
329
+ BUN_SQL_MANAGER_TOKEN,
330
+ SQLITE_MANAGER_TOKEN,
331
+ DB_TOKEN,
312
332
  type DatabaseModuleOptions,
313
333
  type DatabaseConfig,
314
334
  type DatabaseType,
315
335
  type ConnectionInfo,
316
336
  type ConnectionPoolOptions,
337
+ type BunSQLConfig,
338
+ type BunSQLPoolOptions,
317
339
  type SqliteConfig,
340
+ type SqliteV2Config,
318
341
  type PostgresConfig,
319
342
  type MysqlConfig,
343
+ type TenantConfig,
344
+ type DbStrategyType,
345
+ type DbProxy,
346
+ type DatabaseSession,
347
+ type TransactionState as DatabaseTransactionState,
348
+ type ReservedSqlSession,
320
349
  // ORM exports
321
350
  Entity,
322
351
  Column,
@@ -472,6 +501,7 @@ export {
472
501
  } from './microservice';
473
502
  export {
474
503
  ServiceRegistryModule,
504
+ ServiceRegistryDecorator,
475
505
  NacosServiceRegistry,
476
506
  SERVICE_REGISTRY_TOKEN,
477
507
  type ServiceRegistryModuleOptions,
@@ -2,7 +2,11 @@ import { Module, MODULE_METADATA_KEY, type ModuleProvider } from '../../di/modul
2
2
  import { NacosClient } from '@dangao/nacos-client';
3
3
  import type { NacosClientOptions } from '@dangao/nacos-client';
4
4
  import { NacosServiceRegistry } from './nacos-service-registry';
5
- import { SERVICE_REGISTRY_TOKEN, type ServiceRegistry } from './types';
5
+ import {
6
+ SERVICE_REGISTRY_TOKEN,
7
+ type ServiceRegistry,
8
+ type ServiceInstance,
9
+ } from './types';
6
10
 
7
11
  /**
8
12
  * 服务注册中心 Provider 类型
@@ -45,6 +49,21 @@ export interface ServiceRegistryModuleOptions {
45
49
  */
46
50
  nacos?: NacosServiceRegistryOptions;
47
51
 
52
+ /**
53
+ * 是否自动在 Application.listen 时注册带 @ServiceRegistry 的服务
54
+ * @default true
55
+ */
56
+ autoRegister?: boolean;
57
+
58
+ /**
59
+ * 通过模块配置自动注册服务(无需 @ServiceRegistry 装饰器)
60
+ * 当 autoRegister=true 时在 Application.listen 阶段自动注册
61
+ */
62
+ autoRegisterService?: Omit<ServiceInstance, 'ip' | 'port'> & {
63
+ ip?: string;
64
+ port?: number;
65
+ };
66
+
48
67
  // 未来可以添加其他 provider 的配置
49
68
  // consul?: ConsulServiceRegistryOptions;
50
69
  // eureka?: EurekaServiceRegistryOptions;
@@ -57,11 +76,16 @@ export interface ServiceRegistryModuleOptions {
57
76
  providers: [],
58
77
  })
59
78
  export class ServiceRegistryModule {
79
+ public static autoRegister = true;
80
+ public static autoRegisterService: ServiceRegistryModuleOptions['autoRegisterService'];
81
+
60
82
  /**
61
83
  * 创建服务注册中心模块
62
84
  * @param options - 模块配置
63
85
  */
64
86
  public static forRoot(options: ServiceRegistryModuleOptions): typeof ServiceRegistryModule {
87
+ ServiceRegistryModule.autoRegister = options.autoRegister ?? true;
88
+ ServiceRegistryModule.autoRegisterService = options.autoRegisterService;
65
89
  const providers: ModuleProvider[] = [];
66
90
 
67
91
  let serviceRegistry: ServiceRegistry;
@@ -2,5 +2,6 @@ export { Route } from './route';
2
2
  export { Router } from './router';
3
3
  export { RouteRegistry } from './registry';
4
4
  export { GET, POST, PUT, DELETE, PATCH } from './decorators';
5
+ export { IdleTimeout, IDLE_TIMEOUT_KEY, getIdleTimeout } from './timeout-decorator';
5
6
  export type { HttpMethod, RouteHandler, RouteMatch } from './types';
6
7
 
@@ -42,8 +42,17 @@ export class RouteRegistry {
42
42
  middlewares: Middleware[] = [],
43
43
  controllerClass?: Constructor<unknown>,
44
44
  methodName?: string,
45
+ timeout?: number,
45
46
  ): void {
46
- this.router.register(method, path, handler, middlewares, controllerClass, methodName);
47
+ this.router.register(
48
+ method,
49
+ path,
50
+ handler,
51
+ middlewares,
52
+ controllerClass,
53
+ methodName,
54
+ timeout,
55
+ );
47
56
  }
48
57
 
49
58
  /**