@dangao/bun-server 3.1.0 → 3.3.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 (161) hide show
  1. package/dist/ai/types.d.ts +4 -0
  2. package/dist/ai/types.d.ts.map +1 -1
  3. package/dist/auth/types.d.ts +4 -0
  4. package/dist/auth/types.d.ts.map +1 -1
  5. package/dist/cache/interceptors.d.ts +3 -3
  6. package/dist/cache/interceptors.d.ts.map +1 -1
  7. package/dist/cache/service.d.ts +6 -6
  8. package/dist/cache/service.d.ts.map +1 -1
  9. package/dist/cache/types.d.ts +12 -12
  10. package/dist/cache/types.d.ts.map +1 -1
  11. package/dist/config/service.d.ts +6 -4
  12. package/dist/config/service.d.ts.map +1 -1
  13. package/dist/core/application.d.ts +4 -0
  14. package/dist/core/application.d.ts.map +1 -1
  15. package/dist/core/context.d.ts +4 -2
  16. package/dist/core/context.d.ts.map +1 -1
  17. package/dist/database/connection-manager.d.ts +2 -2
  18. package/dist/database/connection-manager.d.ts.map +1 -1
  19. package/dist/database/connection-pool.d.ts +4 -4
  20. package/dist/database/connection-pool.d.ts.map +1 -1
  21. package/dist/database/database-module.d.ts.map +1 -1
  22. package/dist/database/db-proxy.d.ts.map +1 -1
  23. package/dist/database/driver.d.ts +83 -0
  24. package/dist/database/driver.d.ts.map +1 -0
  25. package/dist/database/index.d.ts +2 -1
  26. package/dist/database/index.d.ts.map +1 -1
  27. package/dist/database/service.d.ts +0 -10
  28. package/dist/database/service.d.ts.map +1 -1
  29. package/dist/database/sql-manager.d.ts.map +1 -1
  30. package/dist/database/sqlite-adapter.d.ts +4 -2
  31. package/dist/database/sqlite-adapter.d.ts.map +1 -1
  32. package/dist/database/types.d.ts +26 -0
  33. package/dist/database/types.d.ts.map +1 -1
  34. package/dist/di/container.d.ts +2 -0
  35. package/dist/di/container.d.ts.map +1 -1
  36. package/dist/di/module-registry.d.ts.map +1 -1
  37. package/dist/di/module.d.ts +11 -1
  38. package/dist/di/module.d.ts.map +1 -1
  39. package/dist/di/types.d.ts +1 -1
  40. package/dist/di/types.d.ts.map +1 -1
  41. package/dist/error/handler.d.ts.map +1 -1
  42. package/dist/error/http-exception.d.ts +8 -8
  43. package/dist/error/http-exception.d.ts.map +1 -1
  44. package/dist/error/index.d.ts +1 -0
  45. package/dist/error/index.d.ts.map +1 -1
  46. package/dist/events/service.d.ts +2 -2
  47. package/dist/events/service.d.ts.map +1 -1
  48. package/dist/events/types.d.ts +12 -3
  49. package/dist/events/types.d.ts.map +1 -1
  50. package/dist/index.js +5951 -5820
  51. package/dist/index.node.mjs +310 -139
  52. package/dist/interceptor/base-interceptor.d.ts +3 -3
  53. package/dist/interceptor/base-interceptor.d.ts.map +1 -1
  54. package/dist/interceptor/builtin/log-interceptor.d.ts +1 -1
  55. package/dist/interceptor/builtin/log-interceptor.d.ts.map +1 -1
  56. package/dist/interceptor/builtin/permission-interceptor.d.ts +1 -1
  57. package/dist/interceptor/builtin/permission-interceptor.d.ts.map +1 -1
  58. package/dist/interceptor/interceptor-chain.d.ts +1 -1
  59. package/dist/interceptor/interceptor-chain.d.ts.map +1 -1
  60. package/dist/interceptor/interceptor-registry.d.ts +3 -1
  61. package/dist/interceptor/interceptor-registry.d.ts.map +1 -1
  62. package/dist/interceptor/types.d.ts +6 -1
  63. package/dist/interceptor/types.d.ts.map +1 -1
  64. package/dist/microservice/service-client/types.d.ts +1 -0
  65. package/dist/microservice/service-client/types.d.ts.map +1 -1
  66. package/dist/microservice/tracing/tracer.d.ts +1 -0
  67. package/dist/microservice/tracing/tracer.d.ts.map +1 -1
  68. package/dist/middleware/builtin/file-upload.d.ts +2 -0
  69. package/dist/middleware/builtin/file-upload.d.ts.map +1 -1
  70. package/dist/middleware/builtin/rate-limit.d.ts +9 -1
  71. package/dist/middleware/builtin/rate-limit.d.ts.map +1 -1
  72. package/dist/queue/service.d.ts +2 -2
  73. package/dist/queue/service.d.ts.map +1 -1
  74. package/dist/queue/types.d.ts +25 -1
  75. package/dist/queue/types.d.ts.map +1 -1
  76. package/dist/router/decorators.d.ts +1 -2
  77. package/dist/router/decorators.d.ts.map +1 -1
  78. package/dist/security/guards/types.d.ts +1 -0
  79. package/dist/security/guards/types.d.ts.map +1 -1
  80. package/dist/security/types.d.ts +1 -1
  81. package/dist/security/types.d.ts.map +1 -1
  82. package/dist/session/types.d.ts +8 -0
  83. package/dist/session/types.d.ts.map +1 -1
  84. package/dist/swagger/decorators.d.ts +1 -1
  85. package/dist/swagger/decorators.d.ts.map +1 -1
  86. package/dist/swagger/types.d.ts +1 -1
  87. package/dist/swagger/types.d.ts.map +1 -1
  88. package/dist/testing/harness.d.ts +1 -1
  89. package/dist/testing/harness.d.ts.map +1 -1
  90. package/dist/testing/test-client.d.ts +1 -1
  91. package/dist/testing/test-client.d.ts.map +1 -1
  92. package/dist/testing/testing-module.d.ts +2 -2
  93. package/dist/testing/testing-module.d.ts.map +1 -1
  94. package/dist/validation/errors.d.ts +5 -1
  95. package/dist/validation/errors.d.ts.map +1 -1
  96. package/docs/database.md +44 -0
  97. package/docs/zh/database.md +44 -0
  98. package/package.json +3 -3
  99. package/src/ai/types.ts +5 -0
  100. package/src/auth/types.ts +4 -1
  101. package/src/cache/interceptors.ts +6 -6
  102. package/src/cache/service-proxy.ts +2 -2
  103. package/src/cache/service.ts +17 -8
  104. package/src/cache/types.ts +12 -12
  105. package/src/config/service.ts +8 -6
  106. package/src/core/application.ts +7 -1
  107. package/src/core/context.ts +6 -3
  108. package/src/database/connection-manager.ts +5 -46
  109. package/src/database/connection-pool.ts +26 -49
  110. package/src/database/database-module.ts +6 -0
  111. package/src/database/db-proxy.ts +3 -2
  112. package/src/database/driver.ts +368 -0
  113. package/src/database/index.ts +8 -0
  114. package/src/database/service.ts +3 -74
  115. package/src/database/sql-manager.ts +38 -24
  116. package/src/database/sqlite-adapter.ts +4 -3
  117. package/src/database/types.ts +27 -2
  118. package/src/di/container.ts +13 -0
  119. package/src/di/module-registry.ts +2 -3
  120. package/src/di/module.ts +21 -2
  121. package/src/di/types.ts +1 -2
  122. package/src/error/handler.ts +3 -4
  123. package/src/error/http-exception.ts +11 -11
  124. package/src/error/index.ts +1 -1
  125. package/src/events/service.ts +4 -2
  126. package/src/events/types.ts +14 -3
  127. package/src/interceptor/base-interceptor.ts +5 -6
  128. package/src/interceptor/builtin/log-interceptor.ts +2 -3
  129. package/src/interceptor/builtin/permission-interceptor.ts +2 -3
  130. package/src/interceptor/interceptor-chain.ts +6 -7
  131. package/src/interceptor/interceptor-registry.ts +5 -3
  132. package/src/interceptor/types.ts +9 -4
  133. package/src/microservice/service-client/types.ts +1 -1
  134. package/src/microservice/tracing/tracer.ts +15 -3
  135. package/src/middleware/builtin/file-upload.ts +3 -2
  136. package/src/middleware/builtin/rate-limit.ts +22 -5
  137. package/src/queue/service.ts +1 -1
  138. package/src/queue/types.ts +40 -1
  139. package/src/router/decorators.ts +2 -3
  140. package/src/security/guards/types.ts +2 -1
  141. package/src/security/types.ts +1 -2
  142. package/src/session/service.ts +1 -1
  143. package/src/session/types.ts +10 -0
  144. package/src/swagger/decorators.ts +15 -4
  145. package/src/swagger/generator.ts +2 -3
  146. package/src/swagger/types.ts +1 -2
  147. package/src/testing/harness.ts +1 -2
  148. package/src/testing/test-client.ts +2 -2
  149. package/src/testing/testing-module.ts +5 -5
  150. package/src/validation/errors.ts +6 -2
  151. package/tests/bun-test-shim.d.ts +11 -0
  152. package/tests/controller/context-decorator.test.ts +1 -2
  153. package/tests/database/database-module.test.ts +4 -0
  154. package/tests/database/driver-mysql2.test.ts +95 -0
  155. package/tests/database/driver.test.ts +234 -0
  156. package/tests/database/orm.test.ts +4 -0
  157. package/tests/di/module.test.ts +199 -1
  158. package/tests/events/event-emitter.test.ts +2 -2
  159. package/tests/global.d.ts +30 -0
  160. package/tests/queue/queue-service.test.ts +14 -0
  161. package/tests/testing/testing-module.test.ts +20 -0
package/docs/database.md CHANGED
@@ -25,6 +25,50 @@ DatabaseModule.forRoot({
25
25
  });
26
26
  ```
27
27
 
28
+ ## Driver selection (decoupled from the runtime platform)
29
+
30
+ > Added in v3.2.0.
31
+
32
+ By default the underlying driver for Postgres/MySQL is chosen by the runtime platform: the Bun runtime uses the built-in `Bun.SQL`, while Node.js uses the pure-JS `mysql2` / `postgres` drivers.
33
+
34
+ The optional `driver` field lets you **explicitly pick a pure-JS driver even under the Bun runtime**, decoupled from the platform engine (fs/crypto/http server, etc.):
35
+
36
+ | driver | Behavior |
37
+ | --- | --- |
38
+ | `'auto'` (default) | Bun → `Bun.SQL`; Node → `mysql2` (MySQL) / `postgres` (PostgreSQL). Backward compatible. |
39
+ | `'mysql2'` | Always use `mysql2`, regardless of runtime (only for `type: 'mysql'`). |
40
+ | `'postgres'` | Always use `postgres`, regardless of runtime (only for `type: 'postgres'`). |
41
+ | `'bun-sql'` | Force `Bun.SQL` (valid on Bun only; throws a clear error on Node). |
42
+
43
+ ```ts
44
+ DatabaseModule.forRoot({
45
+ database: {
46
+ type: 'mysql',
47
+ driver: 'mysql2', // uses mysql2 even on the Bun runtime
48
+ config: {
49
+ host: '127.0.0.1',
50
+ port: 3306,
51
+ database: 'app',
52
+ user: 'root',
53
+ password: process.env.DB_PASSWORD!,
54
+ },
55
+ },
56
+ });
57
+
58
+ // The V2 single-tenant form is supported too:
59
+ DatabaseModule.forRoot({
60
+ type: 'mysql',
61
+ url: process.env.DB_URL!,
62
+ driver: 'mysql2',
63
+ });
64
+ ```
65
+
66
+ ### Why? MySQL under `bun build --compile`
67
+
68
+ A single binary produced by `bun build --compile` freezes the Bun runtime at build time, and the built-in `Bun.SQL` MySQL adapter has several known issues. Setting `driver: 'mysql2'` lets the compiled binary connect using the statically bundled pure-JS `mysql2` driver, without falling back to SQLite and without switching the whole platform via `BUN_SERVER_PLATFORM=node` (which would also move the HTTP server to Node).
69
+
70
+ The `driver` switch is orthogonal to `BUN_SERVER_PLATFORM`: the former only selects the SQL driver, while the latter selects the entire platform engine.
71
+
28
72
  ## Route strategy
29
73
 
30
74
  ```ts
@@ -25,6 +25,50 @@ DatabaseModule.forRoot({
25
25
  });
26
26
  ```
27
27
 
28
+ ## 驱动选择(driver,与运行时平台解耦)
29
+
30
+ > v3.2.0 新增。
31
+
32
+ 默认情况下,Postgres/MySQL 连接的底层驱动由运行时平台决定:Bun 运行时使用内建 `Bun.SQL`,Node.js 运行时使用 `mysql2` / `postgres` 纯 JS 驱动。
33
+
34
+ 通过可选的 `driver` 字段,可以**在 Bun 运行时下也显式选用纯 JS 驱动**,与平台引擎(fs/crypto/http server 等)解耦:
35
+
36
+ | driver | 行为 |
37
+ | --- | --- |
38
+ | `'auto'`(默认) | Bun → `Bun.SQL`;Node → `mysql2`(MySQL)/ `postgres`(PostgreSQL)。向后兼容。 |
39
+ | `'mysql2'` | 无论运行时如何,都使用 `mysql2`(仅 `type: 'mysql'`)。 |
40
+ | `'postgres'` | 无论运行时如何,都使用 `postgres`(仅 `type: 'postgres'`)。 |
41
+ | `'bun-sql'` | 强制使用 `Bun.SQL`(仅 Bun 合法,Node 会抛出清晰错误)。 |
42
+
43
+ ```ts
44
+ DatabaseModule.forRoot({
45
+ database: {
46
+ type: 'mysql',
47
+ driver: 'mysql2', // 即使在 Bun 运行时也走 mysql2
48
+ config: {
49
+ host: '127.0.0.1',
50
+ port: 3306,
51
+ database: 'app',
52
+ user: 'root',
53
+ password: process.env.DB_PASSWORD!,
54
+ },
55
+ },
56
+ });
57
+
58
+ // V2 单租户写法同样支持:
59
+ DatabaseModule.forRoot({
60
+ type: 'mysql',
61
+ url: process.env.DB_URL!,
62
+ driver: 'mysql2',
63
+ });
64
+ ```
65
+
66
+ ### 为什么需要它?`bun build --compile` 下的 MySQL
67
+
68
+ `bun build --compile` 产出的单二进制会把当时的 Bun 运行时焊死,其中内建 `Bun.SQL` 的 MySQL 适配带有若干已知问题。显式设置 `driver: 'mysql2'` 即可让编译产物使用静态打包的纯 JS `mysql2` 驱动连库,无需为此回退到 SQLite,也无需用 `BUN_SERVER_PLATFORM=node` 整体切平台(那会把 HTTP server 也切到 Node)。
69
+
70
+ `driver` 开关与 `BUN_SERVER_PLATFORM` 正交:前者只决定 SQL 驱动,后者决定整个平台引擎。
71
+
28
72
  ## 路由策略示例
29
73
 
30
74
  ```ts
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@dangao/bun-server",
3
- "version": "3.1.0",
3
+ "version": "3.3.0",
4
4
  "type": "module",
5
5
  "main": "./dist/index.js",
6
6
  "types": "./dist/index.d.ts",
@@ -48,7 +48,7 @@
48
48
  "test:bun": "bun test tests/platform/bun",
49
49
  "test:node": "vitest run tests/platform/node",
50
50
  "test:platform": "bun run test:bun && bun run test:node",
51
- "type-check": "tsc --noEmit",
51
+ "typecheck": "tsc -p tsconfig.build.json --noEmit && tsc -p tsconfig.test.json --noEmit",
52
52
  "clean": "rm -rf dist",
53
53
  "bundle": "bun build src/index.ts --target=bun --format=esm --outfile=dist/index.js --external reflect-metadata --external @dangao/logsmith --external @dangao/nacos-client --external @vscode/sqlite3",
54
54
  "bundle:node": "bun build src/index.ts --target=node --packages=external --outfile=dist/index.node.mjs",
@@ -88,4 +88,4 @@
88
88
  "postgres": "^3.4.9",
89
89
  "reflect-metadata": "^0.2.2"
90
90
  }
91
- }
91
+ }
package/src/ai/types.ts CHANGED
@@ -144,6 +144,11 @@ export const AI_SERVICE_TOKEN = Symbol('@dangao/bun-server:ai:service');
144
144
  export const AI_MODULE_OPTIONS_TOKEN = Symbol('@dangao/bun-server:ai:options');
145
145
  export const AI_TOOL_REGISTRY_TOKEN = Symbol('@dangao/bun-server:ai:tool-registry');
146
146
 
147
+ /**
148
+ * Metadata key for AiModule options.
149
+ */
150
+ export const MODULE_METADATA_KEY = '@dangao/bun-server:ai:module';
151
+
147
152
  /**
148
153
  * Metadata key for @AiTool decorator
149
154
  */
package/src/auth/types.ts CHANGED
@@ -93,6 +93,10 @@ export interface OAuth2Client {
93
93
  * 允许的授权类型
94
94
  */
95
95
  grantTypes: ('authorization_code' | 'refresh_token')[];
96
+ /**
97
+ * 允许的 OAuth2 scope 列表
98
+ */
99
+ scopes?: string[];
96
100
  }
97
101
 
98
102
  /**
@@ -245,4 +249,3 @@ export interface AuthContext {
245
249
  */
246
250
  isAuthenticated: boolean;
247
251
  }
248
-
@@ -91,8 +91,8 @@ export class CacheableInterceptor extends BaseInterceptor {
91
91
  public async execute<T>(
92
92
  target: unknown,
93
93
  propertyKey: string | symbol,
94
- originalMethod: (...args: unknown[]) => T | Promise<T>,
95
- args: unknown[],
94
+ originalMethod: (...args: any[]) => T | Promise<T>,
95
+ args: any[],
96
96
  container: Container,
97
97
  context?: Context,
98
98
  ): Promise<T> {
@@ -164,8 +164,8 @@ export class CacheEvictInterceptor extends BaseInterceptor {
164
164
  public async execute<T>(
165
165
  target: unknown,
166
166
  propertyKey: string | symbol,
167
- originalMethod: (...args: unknown[]) => T | Promise<T>,
168
- args: unknown[],
167
+ originalMethod: (...args: any[]) => T | Promise<T>,
168
+ args: any[],
169
169
  container: Container,
170
170
  context?: Context,
171
171
  ): Promise<T> {
@@ -238,8 +238,8 @@ export class CachePutInterceptor extends BaseInterceptor {
238
238
  public async execute<T>(
239
239
  target: unknown,
240
240
  propertyKey: string | symbol,
241
- originalMethod: (...args: unknown[]) => T | Promise<T>,
242
- args: unknown[],
241
+ originalMethod: (...args: any[]) => T | Promise<T>,
242
+ args: any[],
243
243
  container: Container,
244
244
  context?: Context,
245
245
  ): Promise<T> {
@@ -87,9 +87,9 @@ export class CacheServiceProxy {
87
87
 
88
88
  // 返回包装后的方法
89
89
  // 使用原型方法以确保拦截器能获取到正确的元数据
90
- const originalMethod = prototypeMethod as (...args: unknown[]) => unknown;
90
+ const originalMethod = prototypeMethod as (...args: any[]) => unknown;
91
91
 
92
- return async function (this: T, ...args: unknown[]): Promise<unknown> {
92
+ return async function (this: T, ...args: any[]): Promise<unknown> {
93
93
  // 按优先级执行拦截器:CacheEvict (beforeInvocation) -> Cacheable/CachePut -> CacheEvict (afterInvocation)
94
94
 
95
95
  // 如果有 @CacheEvict 且配置了 beforeInvocation
@@ -13,11 +13,14 @@ export class CacheService {
13
13
  private keyPrefix: string;
14
14
 
15
15
  public constructor(
16
- @Inject(CACHE_OPTIONS_TOKEN) options: CacheModuleOptions,
16
+ @Inject(CACHE_OPTIONS_TOKEN) options: CacheModuleOptions | CacheStore,
17
17
  ) {
18
- this.store = options.store!;
19
- this.defaultTtl = options.defaultTtl ?? 3600000; // 1 小时
20
- this.keyPrefix = options.keyPrefix ?? '';
18
+ const resolvedOptions: CacheModuleOptions = isCacheStore(options)
19
+ ? { store: options }
20
+ : options;
21
+ this.store = resolvedOptions.store!;
22
+ this.defaultTtl = resolvedOptions.defaultTtl ?? 3600000; // 1 小时
23
+ this.keyPrefix = resolvedOptions.keyPrefix ?? '';
21
24
  }
22
25
 
23
26
  /**
@@ -25,7 +28,7 @@ export class CacheService {
25
28
  * @param key - 缓存键
26
29
  * @returns 缓存值,如果不存在则返回 undefined
27
30
  */
28
- public async get<T = unknown>(key: string): Promise<T | undefined> {
31
+ public async get<T = any>(key: string): Promise<T | undefined> {
29
32
  return this.store.get<T>(this.getKey(key));
30
33
  }
31
34
 
@@ -36,7 +39,7 @@ export class CacheService {
36
39
  * @param ttl - 过期时间(毫秒),0 表示永不过期,undefined 使用默认 TTL
37
40
  * @returns 是否设置成功
38
41
  */
39
- public async set<T = unknown>(
42
+ public async set<T = any>(
40
43
  key: string,
41
44
  value: T,
42
45
  ttl?: number,
@@ -76,7 +79,7 @@ export class CacheService {
76
79
  * @param keys - 缓存键数组
77
80
  * @returns 缓存值映射
78
81
  */
79
- public async getMany<T = unknown>(
82
+ public async getMany<T = any>(
80
83
  keys: string[],
81
84
  ): Promise<Map<string, T>> {
82
85
  const prefixedKeys = keys.map((k) => this.getKey(k));
@@ -97,7 +100,7 @@ export class CacheService {
97
100
  * @param ttl - 过期时间(毫秒),0 表示永不过期,undefined 使用默认 TTL
98
101
  * @returns 是否设置成功
99
102
  */
100
- public async setMany<T = unknown>(
103
+ public async setMany<T = any>(
101
104
  entries: Array<{ key: string; value: T }>,
102
105
  ttl?: number,
103
106
  ): Promise<boolean> {
@@ -149,3 +152,9 @@ export class CacheService {
149
152
  return this.keyPrefix ? `${this.keyPrefix}${key}` : key;
150
153
  }
151
154
  }
155
+
156
+ function isCacheStore(value: CacheModuleOptions | CacheStore): value is CacheStore {
157
+ return typeof (value as CacheStore).get === 'function' &&
158
+ typeof (value as CacheStore).set === 'function' &&
159
+ typeof (value as CacheStore).delete === 'function';
160
+ }
@@ -7,7 +7,7 @@ export interface CacheStore {
7
7
  * @param key - 缓存键
8
8
  * @returns 缓存值,如果不存在则返回 undefined
9
9
  */
10
- get<T = unknown>(key: string): Promise<T | undefined>;
10
+ get<T = any>(key: string): Promise<T | undefined>;
11
11
 
12
12
  /**
13
13
  * 设置缓存值
@@ -16,7 +16,7 @@ export interface CacheStore {
16
16
  * @param ttl - 过期时间(毫秒),0 表示永不过期
17
17
  * @returns 是否设置成功
18
18
  */
19
- set<T = unknown>(key: string, value: T, ttl?: number): Promise<boolean>;
19
+ set<T = any>(key: string, value: T, ttl?: number): Promise<boolean>;
20
20
 
21
21
  /**
22
22
  * 删除缓存
@@ -43,7 +43,7 @@ export interface CacheStore {
43
43
  * @param keys - 缓存键数组
44
44
  * @returns 缓存值映射
45
45
  */
46
- getMany<T = unknown>(keys: string[]): Promise<Map<string, T>>;
46
+ getMany<T = any>(keys: string[]): Promise<Map<string, T>>;
47
47
 
48
48
  /**
49
49
  * 设置多个缓存值
@@ -51,7 +51,7 @@ export interface CacheStore {
51
51
  * @param ttl - 过期时间(毫秒),0 表示永不过期
52
52
  * @returns 是否设置成功
53
53
  */
54
- setMany<T = unknown>(
54
+ setMany<T = any>(
55
55
  entries: Array<{ key: string; value: T }>,
56
56
  ttl?: number,
57
57
  ): Promise<boolean>;
@@ -84,7 +84,7 @@ export class MemoryCacheStore implements CacheStore {
84
84
  }
85
85
  }
86
86
 
87
- public async get<T = unknown>(key: string): Promise<T | undefined> {
87
+ public async get<T = any>(key: string): Promise<T | undefined> {
88
88
  const entry = this.store.get(key);
89
89
  if (!entry) {
90
90
  return undefined;
@@ -99,7 +99,7 @@ export class MemoryCacheStore implements CacheStore {
99
99
  return entry.value as T;
100
100
  }
101
101
 
102
- public async set<T = unknown>(
102
+ public async set<T = any>(
103
103
  key: string,
104
104
  value: T,
105
105
  ttl?: number,
@@ -133,7 +133,7 @@ export class MemoryCacheStore implements CacheStore {
133
133
  return true;
134
134
  }
135
135
 
136
- public async getMany<T = unknown>(
136
+ public async getMany<T = any>(
137
137
  keys: string[],
138
138
  ): Promise<Map<string, T>> {
139
139
  const result = new Map<string, T>();
@@ -154,7 +154,7 @@ export class MemoryCacheStore implements CacheStore {
154
154
  return result;
155
155
  }
156
156
 
157
- public async setMany<T = unknown>(
157
+ public async setMany<T = any>(
158
158
  entries: Array<{ key: string; value: T }>,
159
159
  ttl?: number,
160
160
  ): Promise<boolean> {
@@ -239,7 +239,7 @@ export class RedisCacheStore implements CacheStore {
239
239
  return `${this.keyPrefix}${key}`;
240
240
  }
241
241
 
242
- public async get<T = unknown>(key: string): Promise<T | undefined> {
242
+ public async get<T = any>(key: string): Promise<T | undefined> {
243
243
  const value = await this.client.get(this.getKey(key));
244
244
  if (value === null) {
245
245
  return undefined;
@@ -251,7 +251,7 @@ export class RedisCacheStore implements CacheStore {
251
251
  }
252
252
  }
253
253
 
254
- public async set<T = unknown>(
254
+ public async set<T = any>(
255
255
  key: string,
256
256
  value: T,
257
257
  ttl?: number,
@@ -296,7 +296,7 @@ export class RedisCacheStore implements CacheStore {
296
296
  }
297
297
  }
298
298
 
299
- public async getMany<T = unknown>(
299
+ public async getMany<T = any>(
300
300
  keys: string[],
301
301
  ): Promise<Map<string, T>> {
302
302
  const result = new Map<string, T>();
@@ -325,7 +325,7 @@ export class RedisCacheStore implements CacheStore {
325
325
  return result;
326
326
  }
327
327
 
328
- public async setMany<T = unknown>(
328
+ public async setMany<T = any>(
329
329
  entries: Array<{ key: string; value: T }>,
330
330
  ttl?: number,
331
331
  ): Promise<boolean> {
@@ -67,12 +67,12 @@ export class ConfigService<TConfig extends Record<string, unknown> = Record<stri
67
67
  * 更新配置(用于配置中心动态刷新)
68
68
  * @param newConfig - 新配置对象
69
69
  */
70
- public updateConfig(newConfig: TConfig): void {
71
- this.config = newConfig;
70
+ public updateConfig(newConfig: TConfig | Record<string, unknown>): void {
71
+ this.config = newConfig as TConfig;
72
72
  // 通知所有监听器
73
73
  for (const listener of this.configUpdateListeners) {
74
74
  try {
75
- listener(newConfig);
75
+ listener(this.config);
76
76
  } catch (error) {
77
77
  console.error('[ConfigService] Error in config update listener:', error);
78
78
  }
@@ -83,7 +83,7 @@ export class ConfigService<TConfig extends Record<string, unknown> = Record<stri
83
83
  * 合并配置(用于配置中心增量更新)
84
84
  * @param partialConfig - 部分配置对象
85
85
  */
86
- public mergeConfig(partialConfig: Partial<TConfig>): void {
86
+ public mergeConfig(partialConfig: Partial<TConfig> | Record<string, unknown>): void {
87
87
  this.config = {
88
88
  ...this.config,
89
89
  ...partialConfig,
@@ -125,6 +125,8 @@ export class ConfigService<TConfig extends Record<string, unknown> = Record<stri
125
125
  * @param key - 配置键(如 "db.host")
126
126
  * @param defaultValue - 默认值(可选)
127
127
  */
128
+ public get(key: string): any;
129
+ public get<T>(key: string, defaultValue?: T): T | undefined;
128
130
  public get<T = unknown>(key: string, defaultValue?: T): T | undefined {
129
131
  const namespacedKey = this.applyNamespace(key);
130
132
  const value = this.getValueByPath(this.config, namespacedKey);
@@ -138,6 +140,8 @@ export class ConfigService<TConfig extends Record<string, unknown> = Record<stri
138
140
  * 获取必需的配置值,如果不存在则抛出错误
139
141
  * @param key - 配置键
140
142
  */
143
+ public getRequired(key: string): any;
144
+ public getRequired<T>(key: string): T;
141
145
  public getRequired<T = unknown>(key: string): T {
142
146
  const value = this.get<T>(key);
143
147
  if (value === undefined) {
@@ -191,5 +195,3 @@ export class ConfigService<TConfig extends Record<string, unknown> = Record<stri
191
195
  return current;
192
196
  }
193
197
  }
194
-
195
-
@@ -490,6 +490,13 @@ export class Application {
490
490
  return this.server;
491
491
  }
492
492
 
493
+ /**
494
+ * 获取底层平台服务器实例
495
+ */
496
+ public getNativeServer(): unknown {
497
+ return this.server?.getNativeServer();
498
+ }
499
+
493
500
  /**
494
501
  * 自动注册服务到注册中心
495
502
  * 扫描所有使用 @ServiceRegistry 装饰器的控制器,自动注册服务
@@ -639,4 +646,3 @@ export class Application {
639
646
  this.signalHandlersInstalled = false;
640
647
  }
641
648
  }
642
-
@@ -1,5 +1,6 @@
1
1
  import { BodyParser } from '../request/body-parser';
2
2
  import type { UploadedFileInfo } from '../files';
3
+ import type { Container } from '../di/container';
3
4
  import type { BodyInit } from 'bun'
4
5
  import { type URLSearchParams, URL } from 'url';
5
6
 
@@ -32,7 +33,7 @@ export class Context {
32
33
  /**
33
34
  * 请求路径
34
35
  */
35
- public readonly path: string;
36
+ public path: string;
36
37
 
37
38
  /**
38
39
  * 查询参数
@@ -80,8 +81,11 @@ export class Context {
80
81
  */
81
82
  public readonly signal: AbortSignal;
82
83
 
83
- public constructor(request: Request) {
84
+ public readonly container?: Container;
85
+
86
+ public constructor(request: Request, container?: Container) {
84
87
  this.request = request;
88
+ this.container = container;
85
89
  this.url = new URL(request.url);
86
90
  this.method = request.method;
87
91
  this.path = this.url.pathname;
@@ -304,4 +308,3 @@ export class Context {
304
308
  return sanitized;
305
309
  }
306
310
  }
307
-
@@ -7,6 +7,7 @@ import type {
7
7
  } from './types';
8
8
 
9
9
  import { ConnectionPool } from './connection-pool';
10
+ import { healthCheckViaDriver } from './driver';
10
11
 
11
12
  /**
12
13
  * 数据库连接管理器
@@ -189,58 +190,16 @@ export class DatabaseConnectionManager {
189
190
  }
190
191
 
191
192
  /**
192
- * PostgreSQL 健康检查(使用 Bun.SQL)
193
+ * PostgreSQL 健康检查(按连接 driver tag 分流)
193
194
  */
194
195
  private async healthCheckPostgres(connection: unknown): Promise<boolean> {
195
- try {
196
- // Bun.SQL 对象可以作为函数调用(模板字符串)
197
- if (connection && typeof connection === 'function') {
198
- const result = await (connection as (template: TemplateStringsArray, ...values: unknown[]) => Promise<unknown[]>)`SELECT 1`;
199
- return Array.isArray(result) && result.length > 0;
200
- }
201
- // 或者使用 query 方法(如果存在)
202
- if (
203
- connection &&
204
- typeof connection === 'object' &&
205
- 'query' in connection &&
206
- typeof connection.query === 'function'
207
- ) {
208
- await (connection as { query: (sql: string) => Promise<unknown> }).query(
209
- 'SELECT 1',
210
- );
211
- return true;
212
- }
213
- return false;
214
- } catch (_error) {
215
- return false;
216
- }
196
+ return await healthCheckViaDriver(connection);
217
197
  }
218
198
 
219
199
  /**
220
- * MySQL 健康检查(使用 Bun.SQL)
200
+ * MySQL 健康检查(按连接 driver tag 分流)
221
201
  */
222
202
  private async healthCheckMysql(connection: unknown): Promise<boolean> {
223
- try {
224
- // Bun.SQL 对象可以作为函数调用(模板字符串)
225
- if (connection && typeof connection === 'function') {
226
- const result = await (connection as (template: TemplateStringsArray, ...values: unknown[]) => Promise<unknown[]>)`SELECT 1`;
227
- return Array.isArray(result) && result.length > 0;
228
- }
229
- // 或者使用 query 方法(如果存在)
230
- if (
231
- connection &&
232
- typeof connection === 'object' &&
233
- 'query' in connection &&
234
- typeof connection.query === 'function'
235
- ) {
236
- await (connection as { query: (sql: string) => Promise<unknown> }).query(
237
- 'SELECT 1',
238
- );
239
- return true;
240
- }
241
- return false;
242
- } catch (_error) {
243
- return false;
244
- }
203
+ return await healthCheckViaDriver(connection);
245
204
  }
246
205
  }
@@ -4,6 +4,12 @@ import type {
4
4
  DatabaseType,
5
5
  } from './types';
6
6
  import { getRuntime } from '../platform/runtime';
7
+ import {
8
+ closeViaDriver,
9
+ createMysqlConnection,
10
+ createPostgresConnection,
11
+ resolveDriver,
12
+ } from './driver';
7
13
 
8
14
  /**
9
15
  * 连接池中的连接项
@@ -215,7 +221,7 @@ export class ConnectionPool {
215
221
  }
216
222
 
217
223
  /**
218
- * 创建 PostgreSQL 连接(自动感知运行时)
224
+ * 创建 PostgreSQL 连接(按所选 driver 分流,与运行时平台解耦)
219
225
  */
220
226
  private async createPostgresConnection(
221
227
  config: {
@@ -227,18 +233,16 @@ export class ConnectionPool {
227
233
  ssl?: boolean;
228
234
  },
229
235
  ): Promise<unknown> {
230
- const url = `postgres://${config.user}:${config.password}@${config.host}:${config.port}/${config.database}`;
231
- if (getRuntime().engine === 'bun') {
232
- const { SQL } = await import('bun');
233
- return new SQL(url, { max: 1, tls: config.ssl ?? false });
234
- }
235
- // Node.js:使用 postgres
236
- const postgres = require('postgres') as typeof import('postgres');
237
- return postgres(url, { max: 1, ssl: config.ssl ? 'require' : false });
236
+ const driver = resolveDriver(
237
+ 'postgres',
238
+ this.config.type === 'postgres' ? this.config.driver : undefined,
239
+ getRuntime().engine,
240
+ );
241
+ return await createPostgresConnection(config, driver);
238
242
  }
239
243
 
240
244
  /**
241
- * 创建 MySQL 连接(自动感知运行时)
245
+ * 创建 MySQL 连接(按所选 driver 分流,与运行时平台解耦)
242
246
  */
243
247
  private async createMysqlConnection(
244
248
  config: {
@@ -249,21 +253,12 @@ export class ConnectionPool {
249
253
  password: string;
250
254
  },
251
255
  ): Promise<unknown> {
252
- if (getRuntime().engine === 'bun') {
253
- const url = `mysql://${config.user}:${config.password}@${config.host}:${config.port}/${config.database}`;
254
- const { SQL } = await import('bun');
255
- return new SQL(url, { max: 1 });
256
- }
257
- // Node.js:使用 mysql2
258
- const mysql2 = require('mysql2/promise') as typeof import('mysql2/promise');
259
- const conn = await mysql2.createConnection({
260
- host: config.host,
261
- port: config.port,
262
- database: config.database,
263
- user: config.user,
264
- password: config.password,
265
- });
266
- return conn;
256
+ const driver = resolveDriver(
257
+ 'mysql',
258
+ this.config.type === 'mysql' ? this.config.driver : undefined,
259
+ getRuntime().engine,
260
+ );
261
+ return await createMysqlConnection(config, driver);
267
262
  }
268
263
 
269
264
  /**
@@ -295,35 +290,17 @@ export class ConnectionPool {
295
290
  }
296
291
 
297
292
  /**
298
- * 关闭 PostgreSQL 连接(Bun.SQL 会自动管理连接)
293
+ * 关闭 PostgreSQL 连接(按连接 driver tag 分流:bun-sql → close(),postgres → end())
299
294
  */
300
- private async closePostgresConnection(_connection: unknown): Promise<void> {
301
- // Bun.SQL 会自动管理连接池,这里不需要手动关闭
302
- // 如果需要强制关闭,可以调用 connection.close()
303
- if (
304
- _connection &&
305
- typeof _connection === 'object' &&
306
- 'close' in _connection &&
307
- typeof (_connection as { close: () => void }).close === 'function'
308
- ) {
309
- (_connection as { close: () => void }).close();
310
- }
295
+ private async closePostgresConnection(connection: unknown): Promise<void> {
296
+ await closeViaDriver(connection);
311
297
  }
312
298
 
313
299
  /**
314
- * 关闭 MySQL 连接(Bun.SQL 会自动管理连接)
300
+ * 关闭 MySQL 连接(按连接 driver tag 分流:bun-sql → close(),mysql2 → end())
315
301
  */
316
- private async closeMysqlConnection(_connection: unknown): Promise<void> {
317
- // Bun.SQL 会自动管理连接池,这里不需要手动关闭
318
- // 如果需要强制关闭,可以调用 connection.close()
319
- if (
320
- _connection &&
321
- typeof _connection === 'object' &&
322
- 'close' in _connection &&
323
- typeof (_connection as { close: () => void }).close === 'function'
324
- ) {
325
- (_connection as { close: () => void }).close();
326
- }
302
+ private async closeMysqlConnection(connection: unknown): Promise<void> {
303
+ await closeViaDriver(connection);
327
304
  }
328
305
 
329
306
  /**