@dangao/bun-server 2.0.3 → 2.1.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 (135) hide show
  1. package/README.md +4 -0
  2. package/dist/config/config-module.d.ts +3 -0
  3. package/dist/config/config-module.d.ts.map +1 -1
  4. package/dist/controller/controller.d.ts.map +1 -1
  5. package/dist/core/application.d.ts +6 -1
  6. package/dist/core/application.d.ts.map +1 -1
  7. package/dist/core/context.d.ts +10 -0
  8. package/dist/core/context.d.ts.map +1 -1
  9. package/dist/core/server.d.ts +5 -0
  10. package/dist/core/server.d.ts.map +1 -1
  11. package/dist/database/database-context.d.ts +25 -0
  12. package/dist/database/database-context.d.ts.map +1 -0
  13. package/dist/database/database-extension.d.ts +8 -9
  14. package/dist/database/database-extension.d.ts.map +1 -1
  15. package/dist/database/database-module.d.ts +7 -1
  16. package/dist/database/database-module.d.ts.map +1 -1
  17. package/dist/database/db-proxy.d.ts +12 -0
  18. package/dist/database/db-proxy.d.ts.map +1 -0
  19. package/dist/database/index.d.ts +6 -1
  20. package/dist/database/index.d.ts.map +1 -1
  21. package/dist/database/orm/transaction-interceptor.d.ts +0 -16
  22. package/dist/database/orm/transaction-interceptor.d.ts.map +1 -1
  23. package/dist/database/orm/transaction-manager.d.ts +10 -61
  24. package/dist/database/orm/transaction-manager.d.ts.map +1 -1
  25. package/dist/database/service.d.ts +4 -4
  26. package/dist/database/service.d.ts.map +1 -1
  27. package/dist/database/sql-manager.d.ts +14 -0
  28. package/dist/database/sql-manager.d.ts.map +1 -0
  29. package/dist/database/sqlite-adapter.d.ts +32 -0
  30. package/dist/database/sqlite-adapter.d.ts.map +1 -0
  31. package/dist/database/strategy-decorator.d.ts +8 -0
  32. package/dist/database/strategy-decorator.d.ts.map +1 -0
  33. package/dist/database/types.d.ts +122 -1
  34. package/dist/database/types.d.ts.map +1 -1
  35. package/dist/di/module-registry.d.ts.map +1 -1
  36. package/dist/index.d.ts +3 -3
  37. package/dist/index.d.ts.map +1 -1
  38. package/dist/index.js +3544 -2876
  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/dist/validation/decorators.d.ts.map +1 -1
  52. package/docs/database.md +48 -15
  53. package/docs/idle-timeout.md +42 -0
  54. package/docs/lifecycle.md +6 -0
  55. package/docs/microservice-nacos.md +1 -0
  56. package/docs/microservice-service-registry.md +7 -0
  57. package/docs/zh/database.md +48 -15
  58. package/docs/zh/idle-timeout.md +41 -0
  59. package/docs/zh/lifecycle.md +5 -0
  60. package/docs/zh/microservice-nacos.md +1 -0
  61. package/docs/zh/microservice-service-registry.md +6 -0
  62. package/package.json +5 -4
  63. package/src/ai/providers/anthropic-provider.ts +1 -1
  64. package/src/ai/providers/google-provider.ts +1 -1
  65. package/src/ai/providers/ollama-provider.ts +1 -1
  66. package/src/ai/providers/openai-provider.ts +2 -2
  67. package/src/auth/jwt.ts +1 -1
  68. package/src/cache/interceptors.ts +3 -3
  69. package/src/cache/types.ts +10 -10
  70. package/src/client/runtime.ts +1 -1
  71. package/src/config/config-module.ts +46 -14
  72. package/src/config/service.ts +2 -2
  73. package/src/controller/controller.ts +11 -1
  74. package/src/controller/param-binder.ts +1 -1
  75. package/src/conversation/service.ts +1 -1
  76. package/src/core/application.ts +61 -2
  77. package/src/core/cluster.ts +4 -4
  78. package/src/core/context.ts +71 -0
  79. package/src/core/server.ts +10 -0
  80. package/src/dashboard/controller.ts +2 -2
  81. package/src/database/connection-manager.ts +4 -4
  82. package/src/database/database-context.ts +43 -0
  83. package/src/database/database-extension.ts +12 -45
  84. package/src/database/database-module.ts +254 -11
  85. package/src/database/db-proxy.ts +75 -0
  86. package/src/database/index.ts +29 -0
  87. package/src/database/orm/transaction-interceptor.ts +12 -149
  88. package/src/database/orm/transaction-manager.ts +143 -210
  89. package/src/database/service.ts +53 -30
  90. package/src/database/sql-manager.ts +62 -0
  91. package/src/database/sqlite-adapter.ts +121 -0
  92. package/src/database/strategy-decorator.ts +42 -0
  93. package/src/database/types.ts +133 -1
  94. package/src/debug/middleware.ts +2 -2
  95. package/src/di/module-registry.ts +21 -5
  96. package/src/error/handler.ts +3 -3
  97. package/src/events/event-module.ts +4 -4
  98. package/src/files/static-middleware.ts +2 -2
  99. package/src/files/storage.ts +1 -1
  100. package/src/index.ts +27 -1
  101. package/src/interceptor/builtin/log-interceptor.ts +1 -1
  102. package/src/mcp/server.ts +1 -1
  103. package/src/microservice/service-registry/service-registry-module.ts +25 -1
  104. package/src/middleware/builtin/error-handler.ts +2 -2
  105. package/src/middleware/builtin/file-upload.ts +1 -1
  106. package/src/middleware/builtin/rate-limit.ts +1 -1
  107. package/src/middleware/builtin/static-file.ts +2 -2
  108. package/src/prompt/stores/file-store.ts +4 -4
  109. package/src/request/body-parser.ts +3 -3
  110. package/src/router/index.ts +1 -0
  111. package/src/router/registry.ts +10 -1
  112. package/src/router/route.ts +31 -3
  113. package/src/router/router.ts +10 -1
  114. package/src/router/timeout-decorator.ts +35 -0
  115. package/src/security/filter.ts +1 -1
  116. package/src/security/guards/guard-registry.ts +1 -1
  117. package/src/session/middleware.ts +1 -1
  118. package/src/session/types.ts +5 -5
  119. package/src/testing/test-client.ts +1 -1
  120. package/src/validation/decorators.ts +70 -2
  121. package/src/validation/rules/common.ts +2 -2
  122. package/tests/config/config-module-extended.test.ts +24 -0
  123. package/tests/core/application.test.ts +10 -0
  124. package/tests/core/context.test.ts +52 -0
  125. package/tests/database/database-module.test.ts +92 -344
  126. package/tests/database/db-proxy.test.ts +93 -0
  127. package/tests/database/sql-manager.test.ts +43 -0
  128. package/tests/database/sqlite-adapter.test.ts +45 -0
  129. package/tests/database/strategy-decorator.test.ts +29 -0
  130. package/tests/database/transaction.test.ts +84 -222
  131. package/tests/di/lifecycle.test.ts +37 -0
  132. package/tests/error/error-handler.test.ts +24 -0
  133. package/tests/microservice/service-registry.test.ts +15 -0
  134. package/tests/router/timeout-decorator.test.ts +48 -0
  135. package/tests/validation/validation.test.ts +18 -0
@@ -1,30 +1,207 @@
1
1
  import { Module, MODULE_METADATA_KEY, type ModuleProvider } from '../di/module';
2
- import type { ApplicationExtension } from '../extensions/types';
3
- import {
4
- InterceptorRegistry,
5
- INTERCEPTOR_REGISTRY_TOKEN,
6
- } from '../interceptor';
7
2
  import { type AsyncModuleOptions, registerAsyncProviders } from '../di/async-module';
3
+ import type { Constructor } from '@/core/types';
4
+ import type { Middleware } from '../middleware';
8
5
 
9
6
  import { DatabaseExtension } from './database-extension';
10
7
  import { DatabaseHealthIndicator } from './health-indicator';
11
8
  import { OrmService } from './orm/service';
12
9
  import { TransactionManager } from './orm/transaction-manager';
13
- import { TransactionInterceptor } from './orm/transaction-interceptor';
14
10
  import { TRANSACTION_METADATA_KEY } from './orm/transaction-decorator';
15
11
  import { DatabaseService } from './service';
16
12
  import {
13
+ BUN_SQL_MANAGER_TOKEN,
14
+ DB_TOKEN,
17
15
  DATABASE_OPTIONS_TOKEN,
18
16
  DATABASE_SERVICE_TOKEN,
17
+ SQLITE_MANAGER_TOKEN,
18
+ type BunSQLConfig,
19
19
  type DatabaseModuleOptions,
20
+ type SqliteV2Config,
20
21
  } from './types';
21
22
  import { ORM_SERVICE_TOKEN } from './orm/types';
22
23
  import { TRANSACTION_SERVICE_TOKEN } from './orm/transaction-types';
24
+ import { BunSQLManager } from './sql-manager';
25
+ import { SqliteManager } from './sqlite-adapter';
26
+ import { db, initDbProxy } from './db-proxy';
27
+ import { getDbStrategy } from './strategy-decorator';
28
+ import { runWithSession, type DatabaseSession } from './database-context';
23
29
 
24
30
  @Module({
25
31
  providers: [],
26
32
  })
27
33
  export class DatabaseModule {
34
+ private static isBunSqlType(
35
+ type: DatabaseModuleOptions['type'] | undefined,
36
+ ): type is 'postgres' | 'mysql' {
37
+ return type === 'postgres' || type === 'mysql';
38
+ }
39
+
40
+ public static normalizeConfig(
41
+ options: DatabaseModuleOptions,
42
+ ): Array<{ tenantId: string; config: BunSQLConfig | SqliteV2Config }> {
43
+ if (options.tenants && options.tenants.length > 0) {
44
+ return options.tenants.map((tenant) => ({
45
+ tenantId: tenant.id,
46
+ config: tenant.config,
47
+ }));
48
+ }
49
+
50
+ if (options.database?.type === 'sqlite') {
51
+ if (options.pool) {
52
+ console.warn('[DatabaseModule] pool options are ignored for SQLite');
53
+ }
54
+ return [
55
+ {
56
+ tenantId: options.defaultTenant ?? 'default',
57
+ config: {
58
+ type: 'sqlite',
59
+ database: options.database.config.path,
60
+ wal: options.wal ?? true,
61
+ maxWriteConcurrency: options.maxWriteConcurrency ?? 1,
62
+ },
63
+ },
64
+ ];
65
+ }
66
+
67
+ if (options.database?.type === 'postgres' || options.database?.type === 'mysql') {
68
+ const db = options.database;
69
+ const protocol = db.type === 'mysql' ? 'mysql' : 'postgres';
70
+ const url =
71
+ `${protocol}://${db.config.user}:${db.config.password}@${db.config.host}:${db.config.port}/${db.config.database}`;
72
+ return [
73
+ {
74
+ tenantId: options.defaultTenant ?? 'default',
75
+ config: {
76
+ type: db.type,
77
+ url,
78
+ pool: options.bunSqlPool,
79
+ },
80
+ },
81
+ ];
82
+ }
83
+
84
+ if (options.type === 'sqlite') {
85
+ return [
86
+ {
87
+ tenantId: options.defaultTenant ?? 'default',
88
+ config: {
89
+ type: 'sqlite',
90
+ database: options.databasePath ?? ':memory:',
91
+ wal: options.wal ?? true,
92
+ maxWriteConcurrency: options.maxWriteConcurrency ?? 1,
93
+ },
94
+ },
95
+ ];
96
+ }
97
+
98
+ if (options.url && DatabaseModule.isBunSqlType(options.type)) {
99
+ return [
100
+ {
101
+ tenantId: options.defaultTenant ?? 'default',
102
+ config: {
103
+ type: options.type,
104
+ url: options.url,
105
+ pool: options.bunSqlPool,
106
+ },
107
+ },
108
+ ];
109
+ }
110
+
111
+ if (options.host && DatabaseModule.isBunSqlType(options.type)) {
112
+ const protocol = options.type === 'mysql' ? 'mysql' : 'postgres';
113
+ const url =
114
+ `${protocol}://${options.username}:${options.password}@${options.host}:${options.port ?? 5432}/${options.databasePath ?? ''}`;
115
+ return [
116
+ {
117
+ tenantId: options.defaultTenant ?? 'default',
118
+ config: {
119
+ type: options.type,
120
+ url,
121
+ pool: options.bunSqlPool,
122
+ },
123
+ },
124
+ ];
125
+ }
126
+
127
+ throw new Error(
128
+ '[DatabaseModule] invalid configuration: specify tenants or single tenant connection options',
129
+ );
130
+ }
131
+
132
+ private static createDatabaseMiddleware(
133
+ options: DatabaseModuleOptions,
134
+ normalized: Array<{ tenantId: string; config: BunSQLConfig | SqliteV2Config }>,
135
+ sqlManager: BunSQLManager,
136
+ sqliteManager: SqliteManager,
137
+ ): Middleware {
138
+ const defaultStrategy = options.defaultStrategy ?? 'pool';
139
+ const defaultTenant = options.defaultTenant ?? normalized[0]?.tenantId ?? 'default';
140
+
141
+ return async (context, next) => {
142
+ const routeHandler = (context as any).routeHandler as
143
+ | { controller: Constructor<unknown>; method: string }
144
+ | undefined;
145
+
146
+ let strategy: 'pool' | 'session' = defaultStrategy;
147
+ if (routeHandler) {
148
+ const routeStrategy = getDbStrategy(
149
+ routeHandler.controller,
150
+ routeHandler.method,
151
+ );
152
+ const hasTx = Boolean(
153
+ Reflect.getMetadata(
154
+ TRANSACTION_METADATA_KEY,
155
+ routeHandler.controller.prototype,
156
+ routeHandler.method,
157
+ ),
158
+ );
159
+ strategy = routeStrategy ?? (hasTx ? 'session' : defaultStrategy);
160
+ }
161
+
162
+ if (strategy !== 'session') {
163
+ return await next();
164
+ }
165
+
166
+ const selected = normalized.find((item) => item.tenantId === defaultTenant) ?? normalized[0];
167
+ if (!selected) {
168
+ return await next();
169
+ }
170
+
171
+ if (selected.config.type === 'sqlite') {
172
+ const sqlite = sqliteManager.getAdapter(selected.tenantId);
173
+ return await runWithSession(
174
+ {
175
+ tenantId: selected.tenantId,
176
+ sqlite,
177
+ },
178
+ async () => await next(),
179
+ );
180
+ }
181
+
182
+ const sql = sqlManager.getOrCreate(selected.tenantId, selected.config);
183
+ let reserved: any;
184
+ const session: DatabaseSession = {
185
+ tenantId: selected.tenantId,
186
+ lazyReserve: async () => {
187
+ if (!reserved) {
188
+ reserved = await sql.reserve();
189
+ session.reserved = reserved;
190
+ }
191
+ return reserved;
192
+ },
193
+ };
194
+
195
+ try {
196
+ return await runWithSession(session, async () => await next());
197
+ } finally {
198
+ if (reserved) {
199
+ await reserved.release().catch(() => undefined);
200
+ }
201
+ }
202
+ };
203
+ }
204
+
28
205
  /**
29
206
  * 创建数据库模块
30
207
  * @param options - 模块配置
@@ -33,8 +210,47 @@ export class DatabaseModule {
33
210
  options: DatabaseModuleOptions,
34
211
  ): typeof DatabaseModule {
35
212
  const providers: ModuleProvider[] = [];
213
+ const normalized = DatabaseModule.normalizeConfig(options);
214
+ const sqlManager = new BunSQLManager();
215
+ const sqliteManager = new SqliteManager();
216
+
217
+ for (const item of normalized) {
218
+ if (item.config.type === 'sqlite') {
219
+ sqliteManager.getOrCreate(item.tenantId, item.config);
220
+ } else {
221
+ sqlManager.getOrCreate(item.tenantId, item.config);
222
+ }
223
+ }
224
+ sqlManager.setDefaultTenant(options.defaultTenant ?? normalized[0]?.tenantId ?? 'default');
225
+ sqliteManager.setDefaultTenant(options.defaultTenant ?? normalized[0]?.tenantId ?? 'default');
226
+
227
+ const legacyOptions: DatabaseModuleOptions = options.database
228
+ ? options
229
+ : {
230
+ ...options,
231
+ database:
232
+ normalized[0]?.config.type === 'sqlite'
233
+ ? {
234
+ type: 'sqlite',
235
+ config: {
236
+ path: (normalized[0].config as SqliteV2Config).database,
237
+ },
238
+ }
239
+ : {
240
+ type: (normalized[0]?.config.type ?? 'postgres') as 'postgres' | 'mysql',
241
+ config: {
242
+ host: options.host ?? 'localhost',
243
+ port: options.port ?? (normalized[0]?.config.type === 'mysql' ? 3306 : 5432),
244
+ database: options.databasePath ?? 'default',
245
+ user: options.username ?? 'root',
246
+ password: options.password ?? '',
247
+ },
248
+ },
249
+ };
36
250
 
37
- const service = new DatabaseService(options);
251
+ const service = new DatabaseService(legacyOptions);
252
+ const transactionManager = new TransactionManager(sqlManager);
253
+ initDbProxy(sqlManager, transactionManager);
38
254
 
39
255
  providers.push(
40
256
  {
@@ -45,7 +261,22 @@ export class DatabaseModule {
45
261
  provide: DATABASE_OPTIONS_TOKEN,
46
262
  useValue: options,
47
263
  },
48
- DatabaseService,
264
+ {
265
+ provide: DatabaseService,
266
+ useValue: service,
267
+ },
268
+ {
269
+ provide: BUN_SQL_MANAGER_TOKEN,
270
+ useValue: sqlManager,
271
+ },
272
+ {
273
+ provide: SQLITE_MANAGER_TOKEN,
274
+ useValue: sqliteManager,
275
+ },
276
+ {
277
+ provide: DB_TOKEN,
278
+ useValue: db,
279
+ },
49
280
  );
50
281
 
51
282
  // 如果启用了 ORM,注册 ORM 服务
@@ -65,13 +296,15 @@ export class DatabaseModule {
65
296
  }
66
297
 
67
298
  // 注册事务管理器(总是注册,即使 ORM 未启用)
68
- const transactionManager = new TransactionManager(service);
69
299
  providers.push(
70
300
  {
71
301
  provide: TRANSACTION_SERVICE_TOKEN,
72
302
  useValue: transactionManager,
73
303
  },
74
- TransactionManager,
304
+ {
305
+ provide: TransactionManager,
306
+ useValue: transactionManager,
307
+ },
75
308
  );
76
309
 
77
310
  // 数据库健康检查指示器可以通过 DatabaseModule.createHealthIndicator() 方法获取
@@ -82,7 +315,13 @@ export class DatabaseModule {
82
315
  Reflect.getMetadata(MODULE_METADATA_KEY, DatabaseModule) || {};
83
316
 
84
317
  // 创建数据库扩展,用于在应用启动时初始化连接
85
- const databaseExtension = new DatabaseExtension();
318
+ const databaseExtension = new DatabaseExtension(sqlManager, sqliteManager);
319
+ const middleware = DatabaseModule.createDatabaseMiddleware(
320
+ options,
321
+ normalized,
322
+ sqlManager,
323
+ sqliteManager,
324
+ );
86
325
 
87
326
  const metadata = {
88
327
  ...existingMetadata,
@@ -102,6 +341,10 @@ export class DatabaseModule {
102
341
  ...(existingMetadata.extensions || []),
103
342
  databaseExtension,
104
343
  ],
344
+ middlewares: [
345
+ ...(existingMetadata.middlewares || []),
346
+ middleware,
347
+ ],
105
348
  };
106
349
  Reflect.defineMetadata(MODULE_METADATA_KEY, metadata, DatabaseModule);
107
350
 
@@ -0,0 +1,75 @@
1
+ import type { BunSQLManager } from './sql-manager';
2
+ import { getCurrentSession } from './database-context';
3
+ import type { TransactionManager } from './orm/transaction-manager';
4
+
5
+ type DbResult = Promise<unknown>;
6
+
7
+ export interface DbProxy {
8
+ (strings: TemplateStringsArray, ...values: unknown[]): DbResult;
9
+ transaction<T>(fn: () => Promise<T>): Promise<T>;
10
+ tenant(tenantId: string): DbProxy;
11
+ }
12
+
13
+ let sqlManagerRef: BunSQLManager | undefined;
14
+ let txManagerRef: TransactionManager | undefined;
15
+
16
+ export function initDbProxy(
17
+ sqlManager: BunSQLManager,
18
+ txManager: TransactionManager,
19
+ ): void {
20
+ sqlManagerRef = sqlManager;
21
+ txManagerRef = txManager;
22
+ }
23
+
24
+ function ensureReady(): { sqlManager: BunSQLManager; txManager: TransactionManager } {
25
+ if (!sqlManagerRef || !txManagerRef) {
26
+ throw new Error(
27
+ '[db] proxy is not initialized. Ensure DatabaseModule.forRoot() is called before using db.',
28
+ );
29
+ }
30
+ return { sqlManager: sqlManagerRef, txManager: txManagerRef };
31
+ }
32
+
33
+ const baseDb = async (
34
+ tenantId: string | undefined,
35
+ strings: TemplateStringsArray,
36
+ ...values: unknown[]
37
+ ): DbResult => {
38
+ const session = getCurrentSession();
39
+ if (session?.reserved) {
40
+ return await session.reserved(strings, ...values);
41
+ }
42
+
43
+ if (session?.lazyReserve) {
44
+ const reserved = await session.lazyReserve();
45
+ return await reserved(strings, ...values);
46
+ }
47
+
48
+ const { sqlManager } = ensureReady();
49
+ if (tenantId) {
50
+ const tenantSql = sqlManager.get(tenantId);
51
+ if (tenantSql) {
52
+ return await tenantSql(strings, ...values);
53
+ }
54
+ }
55
+ return await sqlManager.getDefault()(strings, ...values);
56
+ };
57
+
58
+ function createDb(tenantId?: string): DbProxy {
59
+ const fn = (async (
60
+ strings: TemplateStringsArray,
61
+ ...values: unknown[]
62
+ ) => baseDb(tenantId, strings, ...values)) as DbProxy;
63
+
64
+ fn.transaction = async <T>(txFn: () => Promise<T>): Promise<T> => {
65
+ const { txManager } = ensureReady();
66
+ return await txManager.runInTransaction(txFn);
67
+ };
68
+
69
+ fn.tenant = (id: string): DbProxy => createDb(id);
70
+
71
+ return fn;
72
+ }
73
+
74
+ export const db: DbProxy = createDb();
75
+
@@ -4,9 +4,36 @@ export { DatabaseConnectionManager } from './connection-manager';
4
4
  export { ConnectionPool } from './connection-pool';
5
5
  export { DatabaseHealthIndicator } from './health-indicator';
6
6
  export { DatabaseExtension } from './database-extension';
7
+ export { BunSQLManager } from './sql-manager';
8
+ export { SqliteAdapter, SqliteManager, Semaphore } from './sqlite-adapter';
7
9
  export {
10
+ db,
11
+ initDbProxy,
12
+ type DbProxy,
13
+ } from './db-proxy';
14
+ export {
15
+ DbStrategy,
16
+ Session as DbSession,
17
+ DB_STRATEGY_KEY,
18
+ getDbStrategy,
19
+ type DbStrategyType,
20
+ } from './strategy-decorator';
21
+ export {
22
+ databaseSessionStore,
23
+ getCurrentSession,
24
+ runWithSession,
25
+ type DatabaseSession,
26
+ type TransactionState,
27
+ type ReservedSqlSession,
28
+ } from './database-context';
29
+ export {
30
+ BUN_SQL_MANAGER_TOKEN,
31
+ DB_TOKEN,
8
32
  DATABASE_OPTIONS_TOKEN,
9
33
  DATABASE_SERVICE_TOKEN,
34
+ SQLITE_MANAGER_TOKEN,
35
+ type BunSQLConfig,
36
+ type BunSQLPoolOptions,
10
37
  type ConnectionInfo,
11
38
  type ConnectionPoolOptions,
12
39
  type DatabaseConfig,
@@ -14,7 +41,9 @@ export {
14
41
  type DatabaseType,
15
42
  type MysqlConfig,
16
43
  type PostgresConfig,
44
+ type SqliteV2Config,
17
45
  type SqliteConfig,
46
+ type TenantConfig,
18
47
  } from './types';
19
48
  // ORM 导出
20
49
  export {
@@ -3,8 +3,8 @@ import type { Context } from '../../core/context';
3
3
  import type { Interceptor } from '../../interceptor';
4
4
  import { TRANSACTION_SERVICE_TOKEN } from './transaction-types';
5
5
  import { TransactionManager } from './transaction-manager';
6
- import { getTransactionMetadata, TRANSACTION_METADATA_KEY } from './transaction-decorator';
7
- import { Propagation, TransactionStatus } from './transaction-types';
6
+ import { getTransactionMetadata } from './transaction-decorator';
7
+ import { Propagation } from './transaction-types';
8
8
 
9
9
  /**
10
10
  * 事务拦截器
@@ -51,44 +51,26 @@ export class TransactionInterceptor implements Interceptor {
51
51
  case Propagation.REQUIRED:
52
52
  if (currentTransaction) {
53
53
  // 加入现有事务
54
- return await TransactionInterceptor.executeInExistingTransaction(
55
- originalMethod,
56
- target,
57
- args,
58
- currentTransaction.id,
59
- transactionManager,
60
- );
54
+ return await Promise.resolve(originalMethod.apply(target, args));
61
55
  } else {
62
56
  // 创建新事务
63
- return await TransactionInterceptor.executeInNewTransaction(
64
- originalMethod,
65
- target,
66
- args,
57
+ return await transactionManager.runInTransaction(
58
+ async () => await Promise.resolve(originalMethod.apply(target, args)),
67
59
  transactionMetadata,
68
- transactionManager,
69
60
  );
70
61
  }
71
62
 
72
63
  case Propagation.REQUIRES_NEW:
73
64
  // 总是创建新事务
74
- return await TransactionInterceptor.executeInNewTransaction(
75
- originalMethod,
76
- target,
77
- args,
65
+ return await transactionManager.runInNewTransaction(
66
+ async () => await Promise.resolve(originalMethod.apply(target, args)),
78
67
  transactionMetadata,
79
- transactionManager,
80
68
  );
81
69
 
82
70
  case Propagation.SUPPORTS:
83
71
  if (currentTransaction) {
84
72
  // 加入现有事务
85
- return await TransactionInterceptor.executeInExistingTransaction(
86
- originalMethod,
87
- target,
88
- args,
89
- currentTransaction.id,
90
- transactionManager,
91
- );
73
+ return await Promise.resolve(originalMethod.apply(target, args));
92
74
  } else {
93
75
  // 非事务执行
94
76
  return await Promise.resolve(originalMethod.apply(target, args));
@@ -109,22 +91,15 @@ export class TransactionInterceptor implements Interceptor {
109
91
  case Propagation.NESTED:
110
92
  if (currentTransaction) {
111
93
  // 创建嵌套事务(保存点)
112
- return await TransactionInterceptor.executeInNestedTransaction(
113
- originalMethod,
114
- target,
115
- args,
116
- currentTransaction.id,
94
+ return await transactionManager.runInNestedTransaction(
95
+ async () => await Promise.resolve(originalMethod.apply(target, args)),
117
96
  transactionMetadata,
118
- transactionManager,
119
97
  );
120
98
  } else {
121
99
  // 创建新事务
122
- return await TransactionInterceptor.executeInNewTransaction(
123
- originalMethod,
124
- target,
125
- args,
100
+ return await transactionManager.runInTransaction(
101
+ async () => await Promise.resolve(originalMethod.apply(target, args)),
126
102
  transactionMetadata,
127
- transactionManager,
128
103
  );
129
104
  }
130
105
 
@@ -148,116 +123,4 @@ export class TransactionInterceptor implements Interceptor {
148
123
  return await interceptor.execute(target, propertyKey, originalMethod, args, container);
149
124
  }
150
125
 
151
- /**
152
- * 在新事务中执行方法
153
- */
154
- private static async executeInNewTransaction<T>(
155
- method: (...args: unknown[]) => T | Promise<T>,
156
- target: unknown,
157
- args: unknown[],
158
- options: {
159
- timeout?: number;
160
- rollbackFor?: Array<new () => Error>;
161
- noRollbackFor?: Array<new () => Error>;
162
- },
163
- transactionManager: TransactionManager,
164
- ): Promise<T> {
165
- const context = await transactionManager.beginTransaction({
166
- timeout: options.timeout,
167
- });
168
-
169
- try {
170
- const result = await Promise.resolve(method.apply(target, args));
171
- await transactionManager.commitTransaction(context.id);
172
- return result;
173
- } catch (error) {
174
- // 检查是否需要回滚
175
- if (this.shouldRollback(error, options.rollbackFor, options.noRollbackFor)) {
176
- await transactionManager.rollbackTransaction(context.id);
177
- } else {
178
- await transactionManager.commitTransaction(context.id);
179
- }
180
- throw error;
181
- }
182
- }
183
-
184
- /**
185
- * 在现有事务中执行方法
186
- */
187
- private static async executeInExistingTransaction<T>(
188
- method: (...args: unknown[]) => T | Promise<T>,
189
- target: unknown,
190
- args: unknown[],
191
- transactionId: string,
192
- transactionManager: TransactionManager,
193
- ): Promise<T> {
194
- // 直接执行,不提交或回滚(由外层事务管理)
195
- return await Promise.resolve(method.apply(target, args));
196
- }
197
-
198
- /**
199
- * 在嵌套事务中执行方法
200
- */
201
- private static async executeInNestedTransaction<T>(
202
- method: (...args: unknown[]) => T | Promise<T>,
203
- target: unknown,
204
- args: unknown[],
205
- parentTransactionId: string,
206
- options: {
207
- timeout?: number;
208
- rollbackFor?: Array<new () => Error>;
209
- noRollbackFor?: Array<new () => Error>;
210
- },
211
- transactionManager: TransactionManager,
212
- ): Promise<T> {
213
- const savepointName = await transactionManager.createSavepoint(parentTransactionId);
214
-
215
- try {
216
- const result = await Promise.resolve(method.apply(target, args));
217
- // 嵌套事务成功,不执行任何操作(保存点保留)
218
- return result;
219
- } catch (error) {
220
- // 检查是否需要回滚到保存点
221
- if (this.shouldRollback(error, options.rollbackFor, options.noRollbackFor)) {
222
- await transactionManager.rollbackToSavepoint(parentTransactionId, savepointName);
223
- }
224
- throw error;
225
- }
226
- }
227
-
228
- /**
229
- * 判断是否应该回滚
230
- */
231
- private static shouldRollback(
232
- error: unknown,
233
- rollbackFor?: Array<new () => Error>,
234
- noRollbackFor?: Array<new () => Error>,
235
- ): boolean {
236
- if (!error) {
237
- return false;
238
- }
239
-
240
- // 如果指定了 noRollbackFor,且错误匹配,则不回滚
241
- if (noRollbackFor && noRollbackFor.length > 0) {
242
- for (const ErrorClass of noRollbackFor) {
243
- if (error instanceof ErrorClass) {
244
- return false;
245
- }
246
- }
247
- }
248
-
249
- // 如果指定了 rollbackFor,且错误匹配,则回滚
250
- if (rollbackFor && rollbackFor.length > 0) {
251
- for (const ErrorClass of rollbackFor) {
252
- if (error instanceof ErrorClass) {
253
- return true;
254
- }
255
- }
256
- // 如果指定了 rollbackFor 但错误不匹配,则不回滚
257
- return false;
258
- }
259
-
260
- // 默认情况下,所有错误都回滚
261
- return true;
262
- }
263
126
  }