@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
@@ -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
  }