@dangao/bun-server 1.0.0 → 1.0.3

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 (200) hide show
  1. package/package.json +4 -2
  2. package/readme.md +163 -2
  3. package/src/auth/controller.ts +148 -0
  4. package/src/auth/decorators.ts +81 -0
  5. package/src/auth/index.ts +12 -0
  6. package/src/auth/jwt.ts +169 -0
  7. package/src/auth/oauth2.ts +244 -0
  8. package/src/auth/types.ts +248 -0
  9. package/src/cache/cache-module.ts +67 -0
  10. package/src/cache/decorators.ts +202 -0
  11. package/src/cache/index.ts +27 -0
  12. package/src/cache/service.ts +151 -0
  13. package/src/cache/types.ts +420 -0
  14. package/src/config/config-module.ts +76 -0
  15. package/src/config/index.ts +8 -0
  16. package/src/config/service.ts +93 -0
  17. package/src/config/types.ts +27 -0
  18. package/src/controller/controller.ts +251 -0
  19. package/src/controller/decorators.ts +84 -0
  20. package/src/controller/index.ts +7 -0
  21. package/src/controller/metadata.ts +27 -0
  22. package/src/controller/param-binder.ts +157 -0
  23. package/src/core/application.ts +233 -0
  24. package/src/core/context.ts +228 -0
  25. package/src/core/index.ts +4 -0
  26. package/src/core/server.ts +128 -0
  27. package/src/core/types.ts +2 -0
  28. package/src/database/connection-manager.ts +239 -0
  29. package/src/database/connection-pool.ts +322 -0
  30. package/src/database/database-extension.ts +62 -0
  31. package/src/database/database-module.ts +115 -0
  32. package/src/database/health-indicator.ts +51 -0
  33. package/src/database/index.ts +47 -0
  34. package/src/database/orm/decorators.ts +155 -0
  35. package/src/database/orm/drizzle-repository.ts +39 -0
  36. package/src/database/orm/index.ts +23 -0
  37. package/src/database/orm/repository-decorator.ts +39 -0
  38. package/src/database/orm/repository.ts +103 -0
  39. package/src/database/orm/service.ts +49 -0
  40. package/src/database/orm/transaction-decorator.ts +45 -0
  41. package/src/database/orm/transaction-interceptor.ts +243 -0
  42. package/src/database/orm/transaction-manager.ts +276 -0
  43. package/src/database/orm/transaction-types.ts +140 -0
  44. package/src/database/orm/types.ts +99 -0
  45. package/src/database/service.ts +221 -0
  46. package/src/database/types.ts +171 -0
  47. package/src/di/container.ts +398 -0
  48. package/src/di/decorators.ts +228 -0
  49. package/src/di/index.ts +4 -0
  50. package/src/di/module-registry.ts +188 -0
  51. package/src/di/module.ts +65 -0
  52. package/src/di/types.ts +67 -0
  53. package/src/error/error-codes.ts +222 -0
  54. package/src/error/filter.ts +43 -0
  55. package/src/error/handler.ts +66 -0
  56. package/src/error/http-exception.ts +115 -0
  57. package/src/error/i18n.ts +217 -0
  58. package/src/error/index.ts +16 -0
  59. package/src/extensions/index.ts +5 -0
  60. package/src/extensions/logger-extension.ts +31 -0
  61. package/src/extensions/logger-module.ts +69 -0
  62. package/src/extensions/types.ts +14 -0
  63. package/src/files/index.ts +5 -0
  64. package/src/files/static-middleware.ts +53 -0
  65. package/src/files/storage.ts +67 -0
  66. package/src/files/types.ts +33 -0
  67. package/src/files/upload-middleware.ts +45 -0
  68. package/src/health/controller.ts +76 -0
  69. package/src/health/health-module.ts +51 -0
  70. package/src/health/index.ts +12 -0
  71. package/src/health/types.ts +28 -0
  72. package/src/index.ts +270 -0
  73. package/src/metrics/collector.ts +209 -0
  74. package/src/metrics/controller.ts +40 -0
  75. package/src/metrics/index.ts +15 -0
  76. package/src/metrics/metrics-module.ts +58 -0
  77. package/src/metrics/middleware.ts +46 -0
  78. package/src/metrics/prometheus.ts +79 -0
  79. package/src/metrics/types.ts +103 -0
  80. package/src/middleware/builtin/cors.ts +60 -0
  81. package/src/middleware/builtin/error-handler.ts +90 -0
  82. package/src/middleware/builtin/file-upload.ts +42 -0
  83. package/src/middleware/builtin/index.ts +14 -0
  84. package/src/middleware/builtin/logger.ts +91 -0
  85. package/src/middleware/builtin/rate-limit.ts +252 -0
  86. package/src/middleware/builtin/static-file.ts +88 -0
  87. package/src/middleware/decorators.ts +91 -0
  88. package/src/middleware/index.ts +11 -0
  89. package/src/middleware/middleware.ts +13 -0
  90. package/src/middleware/pipeline.ts +93 -0
  91. package/src/queue/decorators.ts +110 -0
  92. package/src/queue/index.ts +26 -0
  93. package/src/queue/queue-module.ts +64 -0
  94. package/src/queue/service.ts +302 -0
  95. package/src/queue/types.ts +341 -0
  96. package/src/request/body-parser.ts +133 -0
  97. package/src/request/file-handler.ts +46 -0
  98. package/src/request/index.ts +5 -0
  99. package/src/request/request.ts +107 -0
  100. package/src/request/response.ts +150 -0
  101. package/src/router/decorators.ts +122 -0
  102. package/src/router/index.ts +6 -0
  103. package/src/router/registry.ts +98 -0
  104. package/src/router/route.ts +140 -0
  105. package/src/router/router.ts +241 -0
  106. package/src/router/types.ts +27 -0
  107. package/src/security/access-decision-manager.ts +34 -0
  108. package/src/security/authentication-manager.ts +47 -0
  109. package/src/security/context.ts +92 -0
  110. package/src/security/filter.ts +162 -0
  111. package/src/security/index.ts +8 -0
  112. package/src/security/providers/index.ts +3 -0
  113. package/src/security/providers/jwt-provider.ts +60 -0
  114. package/src/security/providers/oauth2-provider.ts +70 -0
  115. package/src/security/security-module.ts +145 -0
  116. package/src/security/types.ts +165 -0
  117. package/src/session/decorators.ts +45 -0
  118. package/src/session/index.ts +19 -0
  119. package/src/session/middleware.ts +143 -0
  120. package/src/session/service.ts +218 -0
  121. package/src/session/session-module.ts +69 -0
  122. package/src/session/types.ts +373 -0
  123. package/src/swagger/decorators.ts +133 -0
  124. package/src/swagger/generator.ts +234 -0
  125. package/src/swagger/index.ts +7 -0
  126. package/src/swagger/swagger-extension.ts +41 -0
  127. package/src/swagger/swagger-module.ts +83 -0
  128. package/src/swagger/types.ts +188 -0
  129. package/src/swagger/ui.ts +98 -0
  130. package/src/testing/harness.ts +96 -0
  131. package/src/validation/decorators.ts +95 -0
  132. package/src/validation/errors.ts +28 -0
  133. package/src/validation/index.ts +14 -0
  134. package/src/validation/types.ts +35 -0
  135. package/src/validation/validator.ts +63 -0
  136. package/src/websocket/decorators.ts +51 -0
  137. package/src/websocket/index.ts +12 -0
  138. package/src/websocket/registry.ts +133 -0
  139. package/tests/cache/cache-module.test.ts +212 -0
  140. package/tests/config/config-module.test.ts +151 -0
  141. package/tests/controller/controller.test.ts +189 -0
  142. package/tests/core/application.test.ts +57 -0
  143. package/tests/core/context-body.test.ts +44 -0
  144. package/tests/core/context.test.ts +86 -0
  145. package/tests/core/edge-cases.test.ts +432 -0
  146. package/tests/database/database-module.test.ts +385 -0
  147. package/tests/database/orm.test.ts +164 -0
  148. package/tests/database/postgres-mysql-integration.test.ts +395 -0
  149. package/tests/database/transaction.test.ts +238 -0
  150. package/tests/di/container.test.ts +264 -0
  151. package/tests/di/module.test.ts +128 -0
  152. package/tests/error/error-codes.test.ts +121 -0
  153. package/tests/error/error-handler.test.ts +68 -0
  154. package/tests/error/error-handling.test.ts +254 -0
  155. package/tests/error/http-exception.test.ts +37 -0
  156. package/tests/error/i18n-integration.test.ts +175 -0
  157. package/tests/extensions/logger-extension.test.ts +40 -0
  158. package/tests/files/static-middleware.test.ts +67 -0
  159. package/tests/files/upload-middleware.test.ts +43 -0
  160. package/tests/health/health-module.test.ts +116 -0
  161. package/tests/integration/application-router.test.ts +85 -0
  162. package/tests/integration/body-parsing.test.ts +88 -0
  163. package/tests/integration/cache-e2e.test.ts +114 -0
  164. package/tests/integration/oauth2-e2e.test.ts +615 -0
  165. package/tests/integration/session-e2e.test.ts +207 -0
  166. package/tests/metrics/metrics-module.test.ts +178 -0
  167. package/tests/middleware/builtin.test.ts +206 -0
  168. package/tests/middleware/file-upload.test.ts +41 -0
  169. package/tests/middleware/middleware.test.ts +120 -0
  170. package/tests/middleware/pipeline.test.ts +72 -0
  171. package/tests/middleware/rate-limit.test.ts +314 -0
  172. package/tests/middleware/static-file.test.ts +62 -0
  173. package/tests/perf/harness.test.ts +48 -0
  174. package/tests/perf/optimization.test.ts +183 -0
  175. package/tests/perf/regression.test.ts +120 -0
  176. package/tests/queue/queue-module.test.ts +217 -0
  177. package/tests/request/body-parser.test.ts +96 -0
  178. package/tests/request/response.test.ts +99 -0
  179. package/tests/router/decorators.test.ts +48 -0
  180. package/tests/router/registry.test.ts +51 -0
  181. package/tests/router/route.test.ts +71 -0
  182. package/tests/router/router-normalization.test.ts +106 -0
  183. package/tests/router/router.test.ts +133 -0
  184. package/tests/security/access-decision-manager.test.ts +84 -0
  185. package/tests/security/authentication-manager.test.ts +81 -0
  186. package/tests/security/context.test.ts +302 -0
  187. package/tests/security/filter.test.ts +225 -0
  188. package/tests/security/jwt-provider.test.ts +106 -0
  189. package/tests/security/oauth2-provider.test.ts +269 -0
  190. package/tests/security/security-module.test.ts +143 -0
  191. package/tests/session/session-module.test.ts +307 -0
  192. package/tests/stress/di-stress.test.ts +30 -0
  193. package/tests/swagger/decorators.test.ts +153 -0
  194. package/tests/swagger/generator.test.ts +202 -0
  195. package/tests/swagger/swagger-extension.test.ts +72 -0
  196. package/tests/swagger/swagger-module.test.ts +79 -0
  197. package/tests/utils/test-port.ts +10 -0
  198. package/tests/validation/controller-validation.test.ts +64 -0
  199. package/tests/validation/validation.test.ts +42 -0
  200. package/tests/websocket/gateway.test.ts +68 -0
@@ -0,0 +1,398 @@
1
+ import "reflect-metadata";
2
+ import {
3
+ type DependencyMetadata,
4
+ Lifecycle,
5
+ type ProviderConfig,
6
+ } from "./types";
7
+ import {
8
+ getDependencyMetadata,
9
+ getLifecycle,
10
+ getTypeReference,
11
+ } from "./decorators";
12
+ import { LoggerManager } from "@dangao/logsmith";
13
+ import type { Constructor } from "@/core/types";
14
+
15
+ /**
16
+ * 依赖注入容器
17
+ * 管理依赖的注册、解析和生命周期
18
+ */
19
+ interface ContainerOptions {
20
+ parent?: Container;
21
+ }
22
+
23
+ export class Container {
24
+ private readonly parent?: Container;
25
+
26
+ public constructor(options: ContainerOptions = {}) {
27
+ this.parent = options.parent;
28
+ }
29
+ /**
30
+ * 注册的提供者
31
+ */
32
+ private readonly providers = new Map<string | symbol, ProviderConfig>();
33
+
34
+ /**
35
+ * 单例实例缓存
36
+ */
37
+ private readonly singletons = new Map<string | symbol, unknown>();
38
+
39
+ /**
40
+ * 类型到 token 的映射(用于接口注入)
41
+ */
42
+ private readonly typeToToken = new Map<
43
+ Constructor<unknown>,
44
+ string | symbol
45
+ >();
46
+
47
+ /**
48
+ * 依赖计划缓存,避免重复解析反射元数据
49
+ */
50
+ private readonly dependencyPlans = new Map<
51
+ Constructor<unknown>,
52
+ DependencyPlan
53
+ >();
54
+
55
+ /**
56
+ * 注册提供者
57
+ * @param token - 提供者标识符(类构造函数或 token)
58
+ * @param config - 提供者配置
59
+ */
60
+ public register<T>(
61
+ token: Constructor<T> | string | symbol,
62
+ config?: ProviderConfig,
63
+ ): void {
64
+ const tokenKey = this.getTokenKey(token);
65
+
66
+ // 如果配置中没有指定生命周期,尝试从装饰器元数据获取
67
+ let lifecycle = config?.lifecycle;
68
+ if (!lifecycle && typeof token === "function") {
69
+ lifecycle = getLifecycle(token);
70
+ }
71
+
72
+ const providerConfig: ProviderConfig = {
73
+ lifecycle: lifecycle || Lifecycle.Singleton,
74
+ ...config,
75
+ };
76
+
77
+ if (
78
+ typeof token === "function" && !providerConfig.factory &&
79
+ !providerConfig.implementation
80
+ ) {
81
+ providerConfig.implementation = token;
82
+ }
83
+
84
+ this.providers.set(tokenKey, providerConfig);
85
+
86
+ // 如果是类构造函数,建立类型到 token 的映射
87
+ if (typeof token === "function") {
88
+ this.typeToToken.set(token, tokenKey);
89
+ }
90
+ }
91
+
92
+ /**
93
+ * 注册单例
94
+ * @param token - 提供者标识符
95
+ * @param instance - 实例对象
96
+ */
97
+ public registerInstance<T>(
98
+ token: Constructor<T> | string | symbol,
99
+ instance: T,
100
+ ): void {
101
+ const tokenKey = this.getTokenKey(token);
102
+ this.singletons.set(tokenKey, instance);
103
+ this.providers.set(tokenKey, {
104
+ lifecycle: Lifecycle.Singleton,
105
+ });
106
+ }
107
+
108
+ /**
109
+ * 解析依赖
110
+ * @param token - 提供者标识符
111
+ * @returns 解析后的实例
112
+ */
113
+ public resolve<T>(token: Constructor<T> | string | symbol): T {
114
+ const tokenKey = this.getTokenKey(token);
115
+ const provider = this.providers.get(tokenKey);
116
+
117
+ if (!provider) {
118
+ if (this.parent) {
119
+ return this.parent.resolve(token as Constructor<T>);
120
+ }
121
+ // 如果没有注册,尝试直接实例化(用于未注册的类)
122
+ // 但只有在是构造函数时才允许
123
+ if (typeof token === "function") {
124
+ // 检查是否有参数,如果有参数则需要注册
125
+ const paramTypes = Reflect.getMetadata(
126
+ "design:paramtypes",
127
+ token,
128
+ ) as unknown[];
129
+ if (paramTypes && paramTypes.length > 0) {
130
+ // 有依赖,必须先注册
131
+ throw new Error(`Provider not found for token: ${String(tokenKey)}`);
132
+ }
133
+ // 无参数,可以直接实例化
134
+ return new token() as T;
135
+ }
136
+ throw new Error(`Provider not found for token: ${String(tokenKey)}`);
137
+ }
138
+
139
+ // 检查单例缓存
140
+ if (provider.lifecycle === Lifecycle.Singleton) {
141
+ const singleton = this.singletons.get(tokenKey);
142
+ if (singleton) {
143
+ return singleton as T;
144
+ }
145
+ }
146
+
147
+ // 使用工厂函数或实例化
148
+ let instance: T;
149
+ if (provider.factory) {
150
+ instance = provider.factory() as T;
151
+ } else if (typeof token === "function") {
152
+ instance = this.instantiate(token as Constructor<T>);
153
+ } else if (
154
+ provider.implementation && typeof provider.implementation === "function"
155
+ ) {
156
+ instance = this.instantiate(provider.implementation as Constructor<T>);
157
+ } else {
158
+ throw new Error(
159
+ `Cannot instantiate token: ${
160
+ String(tokenKey)
161
+ }. Factory function required.`,
162
+ );
163
+ }
164
+
165
+ // 缓存单例
166
+ if (provider.lifecycle === Lifecycle.Singleton) {
167
+ this.singletons.set(tokenKey, instance);
168
+ }
169
+
170
+ return instance;
171
+ }
172
+
173
+ /**
174
+ * 解析依赖(内部方法,支持 string | symbol token)
175
+ * @param token - 提供者标识符
176
+ * @returns 解析后的实例
177
+ */
178
+ private resolveInternal(
179
+ token: Constructor<unknown> | string | symbol,
180
+ ): unknown {
181
+ // 调试:记录 token 的类型和值
182
+ const tokenType = typeof token;
183
+ const tokenString = String(token);
184
+ const logger = LoggerManager.getLogger();
185
+
186
+ // 调试:记录 token 信息
187
+ if (
188
+ tokenString.includes("Level2") || tokenString.includes("Dependency") ||
189
+ tokenString.includes("Service")
190
+ ) {
191
+ logger.debug(
192
+ `[DI Debug] resolveInternal: token=${tokenString}, tokenType=${tokenType}`,
193
+ );
194
+ }
195
+
196
+ // 检查是否是 string 或 symbol
197
+ // 注意:必须先检查 string/symbol,因为函数也是对象
198
+ if (typeof token === "string" || typeof token === "symbol") {
199
+ // 对于 string | symbol token,直接查找提供者
200
+ const provider = this.providers.get(token);
201
+ if (!provider) {
202
+ if (this.parent) {
203
+ return this.parent.resolveInternal(token);
204
+ }
205
+ throw new Error(`Provider not found for token: ${String(token)}`);
206
+ }
207
+
208
+ // 检查单例缓存
209
+ if (provider.lifecycle === Lifecycle.Singleton) {
210
+ const singleton = this.singletons.get(token);
211
+ if (singleton) {
212
+ return singleton;
213
+ }
214
+ }
215
+
216
+ // 使用工厂函数或实现类
217
+ if (provider.factory) {
218
+ const instance = provider.factory();
219
+ if (provider.lifecycle === Lifecycle.Singleton) {
220
+ this.singletons.set(token, instance);
221
+ }
222
+ return instance;
223
+ }
224
+
225
+ if (
226
+ provider.implementation && typeof provider.implementation === "function"
227
+ ) {
228
+ const instance = this.instantiate(provider.implementation);
229
+ if (provider.lifecycle === Lifecycle.Singleton) {
230
+ this.singletons.set(token, instance);
231
+ }
232
+ return instance;
233
+ }
234
+
235
+ throw new Error(
236
+ `Cannot instantiate token: ${
237
+ String(token)
238
+ }. Factory function required.`,
239
+ );
240
+ }
241
+
242
+ // 对于构造函数类型,使用公共 resolve 方法
243
+ // 确保 token 是函数类型
244
+ if (typeof token === "function") {
245
+ return this.resolve(token as new (...args: unknown[]) => unknown);
246
+ }
247
+
248
+ throw new Error(
249
+ `Invalid token type: ${tokenType}. Token: ${String(token)}`,
250
+ );
251
+ }
252
+
253
+ /**
254
+ * 实例化类(自动注入依赖)
255
+ * @param constructor - 构造函数
256
+ * @returns 实例
257
+ */
258
+ private instantiate<T>(constructor: Constructor<T>): T {
259
+ const plan = this.getDependencyPlan(constructor);
260
+
261
+ if (plan.paramLength === 0) {
262
+ return new constructor();
263
+ }
264
+
265
+ const dependencies = new Array(plan.paramLength);
266
+ for (let index = 0; index < plan.paramLength; index++) {
267
+ dependencies[index] = this.resolveFromPlan(constructor, plan, index);
268
+ }
269
+
270
+ return new constructor(...dependencies);
271
+ }
272
+
273
+ /**
274
+ * 获取 token 键
275
+ * @param token - 提供者标识符
276
+ * @returns token 键
277
+ */
278
+ private getTokenKey(
279
+ token: (new (...args: unknown[]) => unknown) | string | symbol,
280
+ ): string | symbol {
281
+ if (typeof token === "function") {
282
+ return token.name || Symbol(token.toString());
283
+ }
284
+ return token;
285
+ }
286
+
287
+ /**
288
+ * 清除所有注册(主要用于测试)
289
+ */
290
+ public clear(): void {
291
+ this.providers.clear();
292
+ this.singletons.clear();
293
+ this.typeToToken.clear();
294
+ this.dependencyPlans.clear();
295
+ }
296
+
297
+ /**
298
+ * 检查是否已注册
299
+ * @param token - 提供者标识符
300
+ * @returns 是否已注册
301
+ */
302
+ public isRegistered(token: Constructor<unknown> | string | symbol): boolean {
303
+ const tokenKey = this.getTokenKey(token);
304
+ return this.providers.has(tokenKey);
305
+ }
306
+
307
+ private getDependencyPlan(constructor: Constructor<unknown>): DependencyPlan {
308
+ let plan = this.dependencyPlans.get(constructor);
309
+ if (plan) {
310
+ return plan;
311
+ }
312
+
313
+ const paramTypes =
314
+ (Reflect.getMetadata(
315
+ "design:paramtypes",
316
+ constructor,
317
+ ) as (Constructor<unknown> | undefined)[]) ?? [];
318
+ const dependencyMetadata = getDependencyMetadata(constructor);
319
+ const metadataMap = new Map<number, DependencyMetadata>();
320
+ let paramLength = paramTypes.length;
321
+
322
+ for (const meta of dependencyMetadata) {
323
+ if (meta && typeof meta.index === "number") {
324
+ metadataMap.set(meta.index, meta);
325
+ if (meta.index + 1 > paramLength) {
326
+ paramLength = meta.index + 1;
327
+ }
328
+ }
329
+ }
330
+
331
+ const resolvedTypes = new Map<number, Constructor<unknown>>();
332
+
333
+ for (let i = 0; i < paramLength; i++) {
334
+ const typeRef = getTypeReference(constructor, i);
335
+ if (typeRef && typeof typeRef === "function") {
336
+ resolvedTypes.set(i, typeRef as Constructor<unknown>);
337
+ }
338
+ }
339
+
340
+ for (const [index, meta] of metadataMap.entries()) {
341
+ const depType = meta?.type;
342
+ if (typeof depType === "function") {
343
+ resolvedTypes.set(index, depType as Constructor<unknown>);
344
+ } else if (typeof depType === "string") {
345
+ const globalType = (globalThis as Record<string, unknown>)[depType];
346
+ if (typeof globalType === "function") {
347
+ resolvedTypes.set(index, globalType as Constructor<unknown>);
348
+ }
349
+ }
350
+ }
351
+
352
+ plan = {
353
+ paramTypes,
354
+ metadataMap,
355
+ resolvedTypes,
356
+ paramLength,
357
+ };
358
+ this.dependencyPlans.set(constructor, plan);
359
+ return plan;
360
+ }
361
+
362
+ private resolveFromPlan(
363
+ constructor: Constructor<unknown>,
364
+ plan: DependencyPlan,
365
+ index: number,
366
+ ): unknown {
367
+ const meta = plan.metadataMap.get(index);
368
+ if (meta?.token) {
369
+ return this.resolveInternal(meta.token);
370
+ }
371
+
372
+ const resolvedType = plan.resolvedTypes.get(index);
373
+ if (resolvedType) {
374
+ return this.resolveInternal(resolvedType);
375
+ }
376
+
377
+ const paramType = plan.paramTypes[index];
378
+ if (paramType) {
379
+ const token = this.typeToToken.get(paramType);
380
+ if (token) {
381
+ return this.resolveInternal(token);
382
+ }
383
+ return this.resolveInternal(paramType);
384
+ }
385
+
386
+ throw new Error(
387
+ `Cannot resolve dependency at index ${index} of ${constructor.name}. ` +
388
+ "Parameter type is undefined. Use @Inject() decorator to specify the dependency type.",
389
+ );
390
+ }
391
+ }
392
+
393
+ interface DependencyPlan {
394
+ paramTypes: (Constructor<unknown> | undefined)[];
395
+ metadataMap: Map<number, DependencyMetadata>;
396
+ resolvedTypes: Map<number, Constructor<unknown>>;
397
+ paramLength: number;
398
+ }
@@ -0,0 +1,228 @@
1
+ import "reflect-metadata";
2
+ import { type DependencyMetadata, Lifecycle } from "./types";
3
+ import { LoggerManager } from "@dangao/logsmith";
4
+ import type { Constructor } from "@/core/types";
5
+
6
+ /**
7
+ * 依赖元数据键
8
+ */
9
+ const DEPENDENCY_METADATA_KEY = Symbol("dependency:metadata");
10
+ const INJECTABLE_METADATA_KEY = Symbol("injectable");
11
+
12
+ /**
13
+ * 类型引用映射(用于保存构造函数类型,避免 Reflect.defineMetadata 序列化问题)
14
+ */
15
+ const typeReferenceMap = new WeakMap<
16
+ Constructor<unknown>,
17
+ Map<string, Constructor<unknown>>
18
+ >();
19
+
20
+ /**
21
+ * Injectable 装饰器
22
+ * 标记类为可注入的
23
+ * @param config - 提供者配置
24
+ */
25
+ export function Injectable(
26
+ config?: { lifecycle?: Lifecycle },
27
+ ): (target: Constructor<unknown>) => void {
28
+ return function (target: new (...args: unknown[]) => unknown) {
29
+ // 保存可注入标记
30
+ Reflect.defineMetadata(INJECTABLE_METADATA_KEY, true, target);
31
+ // 保存生命周期配置
32
+ if (config?.lifecycle) {
33
+ Reflect.defineMetadata("lifecycle", config.lifecycle, target);
34
+ }
35
+ };
36
+ }
37
+
38
+ /**
39
+ * Inject 装饰器
40
+ * 标记需要注入的依赖
41
+ * @param token - 依赖标识符(可选,默认使用参数类型)
42
+ */
43
+ export function Inject(
44
+ token?: Constructor<unknown> | string | symbol,
45
+ ): ParameterDecorator {
46
+ return function (
47
+ target: unknown,
48
+ _propertyKey: string | symbol | undefined,
49
+ parameterIndex: number,
50
+ ) {
51
+ const logger = LoggerManager.getLogger();
52
+
53
+ // 参数装饰器的 target 可能是构造函数本身(用于构造函数参数)
54
+ // 也可能是类的原型(用于方法参数)
55
+ const constructor = typeof target === "function"
56
+ ? (target as Constructor<unknown>)
57
+ : (target as any)?.constructor;
58
+ if (!constructor) {
59
+ return;
60
+ }
61
+
62
+ // 获取参数类型(从构造函数获取)
63
+ const paramTypes = Reflect.getMetadata(
64
+ "design:paramtypes",
65
+ constructor,
66
+ ) as Constructor<unknown>[];
67
+ const paramType = paramTypes?.[parameterIndex];
68
+
69
+ // 获取或创建依赖元数据(保存在构造函数上)
70
+ let metadata: DependencyMetadata[] =
71
+ Reflect.getMetadata(DEPENDENCY_METADATA_KEY, constructor) || [];
72
+
73
+ // 确保数组有足够的长度
74
+ const paramCount = paramTypes?.length || 0;
75
+ while (metadata.length < paramCount) {
76
+ metadata.push(undefined as unknown as DependencyMetadata);
77
+ }
78
+
79
+ // 确定依赖类型
80
+ let dependencyType: Constructor<unknown>;
81
+ let dependencyToken: string | symbol | undefined;
82
+
83
+ if (token) {
84
+ if (typeof token === "string" || typeof token === "symbol") {
85
+ dependencyToken = token;
86
+ // 如果没有参数类型,使用 Object 作为占位符
87
+ dependencyType = paramType || (Object as Constructor<unknown>);
88
+ } else {
89
+ dependencyType = token;
90
+ }
91
+ } else {
92
+ // 如果没有提供 token,使用参数类型
93
+ // 如果 paramType 是 undefined,说明 reflect-metadata 没有正确获取类型
94
+ // 在这种情况下,我们不能使用 Object,因为 Object 不是正确的依赖类型
95
+ if (!paramType) {
96
+ throw new Error(
97
+ `Cannot determine dependency type for parameter ${parameterIndex} of ${constructor.name}. ` +
98
+ "Please provide explicit type using @Inject(Type) or ensure emitDecoratorMetadata is enabled.",
99
+ );
100
+ }
101
+ dependencyType = paramType;
102
+ }
103
+
104
+ // 保存类型引用到 WeakMap(避免 Reflect.defineMetadata 序列化问题)
105
+ // 无论 dependencyType 是什么类型,都保存到 WeakMap 中
106
+ if (!typeReferenceMap.has(constructor)) {
107
+ typeReferenceMap.set(constructor, new Map());
108
+ }
109
+ const typeRefs = typeReferenceMap.get(constructor)!;
110
+ // 保存类型引用(无论是函数类型还是其他类型)
111
+ typeRefs.set(String(parameterIndex), dependencyType);
112
+
113
+ metadata[parameterIndex] = {
114
+ index: parameterIndex,
115
+ type: dependencyType,
116
+ token: dependencyToken,
117
+ };
118
+
119
+ // 调试:记录元数据保存信息
120
+ if (constructor.name === "Service" || constructor.name === "Level2") {
121
+ logger.debug(
122
+ `[DI Debug] @Inject(${
123
+ token
124
+ ? (typeof token === "function" ? token.name : String(token))
125
+ : "auto"
126
+ }) on ${constructor.name}[${parameterIndex}]: saving metadata.length=${metadata.length}`,
127
+ );
128
+ }
129
+
130
+ Reflect.defineMetadata(DEPENDENCY_METADATA_KEY, metadata, constructor);
131
+
132
+ // 调试:验证元数据是否被正确保存
133
+ if (constructor.name === "Service" || constructor.name === "Level2") {
134
+ const savedMetadata = Reflect.getMetadata(
135
+ DEPENDENCY_METADATA_KEY,
136
+ constructor,
137
+ );
138
+ logger.debug(
139
+ `[DI Debug] @Inject on ${constructor.name}: saved metadata.exists=${
140
+ savedMetadata ? "yes" : "no"
141
+ }, length=${savedMetadata?.length || 0}`,
142
+ );
143
+ }
144
+ };
145
+ }
146
+
147
+ /**
148
+ * 获取依赖元数据
149
+ * @param target - 目标类或原型
150
+ * @returns 依赖元数据数组
151
+ */
152
+ export function getDependencyMetadata(target: unknown): DependencyMetadata[] {
153
+ // 参数装饰器的元数据保存在构造函数上
154
+ // 如果 target 是构造函数,直接获取
155
+ // 如果 target 是原型,从构造函数获取
156
+ const constructor = typeof target === "function"
157
+ ? target
158
+ : (target as any)?.constructor;
159
+ if (!constructor) {
160
+ return [];
161
+ }
162
+ const rawMetadata = Reflect.getMetadata(DEPENDENCY_METADATA_KEY, constructor);
163
+ const metadata = rawMetadata || [];
164
+
165
+ // 调试:记录元数据信息
166
+ if (constructor.name === "Service" || constructor.name === "Level2") {
167
+ LoggerManager.getLogger().debug(
168
+ `[DI Debug] getDependencyMetadata(${constructor.name}): rawMetadata=${
169
+ rawMetadata ? "exists" : "undefined"
170
+ }, length=${metadata.length}`,
171
+ );
172
+ }
173
+
174
+ // 从 WeakMap 恢复类型引用(避免 Reflect.defineMetadata 序列化问题)
175
+ const typeRefs = typeReferenceMap.get(constructor);
176
+ if (typeRefs) {
177
+ for (let i = 0; i < metadata.length; i++) {
178
+ const meta = metadata[i];
179
+ if (meta !== undefined && meta !== null) {
180
+ const typeRef = typeRefs.get(String(meta.index));
181
+ if (typeRef && typeof typeRef === "function") {
182
+ // 恢复类型引用
183
+ meta.type = typeRef;
184
+ }
185
+ }
186
+ }
187
+ }
188
+
189
+ // 返回完整的元数据数组(包括 undefined),让调用者决定如何处理
190
+ return metadata;
191
+ }
192
+
193
+ /**
194
+ * 检查类是否可注入
195
+ * @param target - 目标类
196
+ * @returns 是否可注入
197
+ */
198
+ export function isInjectable(target: Constructor<unknown>): boolean {
199
+ return Reflect.getMetadata(INJECTABLE_METADATA_KEY, target) === true;
200
+ }
201
+
202
+ /**
203
+ * 获取类的生命周期配置
204
+ * @param target - 目标类
205
+ * @returns 生命周期
206
+ */
207
+ export function getLifecycle(
208
+ target: Constructor<unknown>,
209
+ ): Lifecycle | undefined {
210
+ return Reflect.getMetadata("lifecycle", target);
211
+ }
212
+
213
+ /**
214
+ * 获取类型引用(从 WeakMap)
215
+ * @param constructor - 构造函数
216
+ * @param parameterIndex - 参数索引
217
+ * @returns 类型引用
218
+ */
219
+ export function getTypeReference(
220
+ constructor: Constructor<unknown>,
221
+ parameterIndex: number,
222
+ ): Constructor<unknown> | undefined {
223
+ const typeRefs = typeReferenceMap.get(constructor);
224
+ if (typeRefs) {
225
+ return typeRefs.get(String(parameterIndex)) as Constructor<unknown>;
226
+ }
227
+ return undefined as unknown as Constructor<unknown>;
228
+ }
@@ -0,0 +1,4 @@
1
+ export { Container } from './container';
2
+ export { Injectable, Inject, getDependencyMetadata, isInjectable, getLifecycle } from './decorators';
3
+ export { Lifecycle, type ProviderConfig, type DependencyMetadata } from './types';
4
+