@navios/di 0.7.1 → 0.9.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 (263) hide show
  1. package/CHANGELOG.md +110 -0
  2. package/README.md +117 -17
  3. package/lib/browser/container/abstract-container.d.mts +112 -0
  4. package/lib/browser/container/abstract-container.d.mts.map +1 -0
  5. package/lib/browser/container/abstract-container.mjs +100 -0
  6. package/lib/browser/container/abstract-container.mjs.map +1 -0
  7. package/lib/browser/container/container.d.mts +100 -0
  8. package/lib/browser/container/container.d.mts.map +1 -0
  9. package/lib/browser/container/container.mjs +424 -0
  10. package/lib/browser/container/container.mjs.map +1 -0
  11. package/lib/browser/container/scoped-container.d.mts +93 -0
  12. package/lib/browser/container/scoped-container.d.mts.map +1 -0
  13. package/lib/browser/container/scoped-container.mjs +119 -0
  14. package/lib/browser/container/scoped-container.mjs.map +1 -0
  15. package/lib/browser/decorators/factory.decorator.d.mts +26 -0
  16. package/lib/browser/decorators/factory.decorator.d.mts.map +1 -0
  17. package/lib/browser/decorators/factory.decorator.mjs +20 -0
  18. package/lib/browser/decorators/factory.decorator.mjs.map +1 -0
  19. package/lib/browser/decorators/injectable.decorator.d.mts +38 -0
  20. package/lib/browser/decorators/injectable.decorator.d.mts.map +1 -0
  21. package/lib/browser/decorators/injectable.decorator.mjs +21 -0
  22. package/lib/browser/decorators/injectable.decorator.mjs.map +1 -0
  23. package/lib/browser/enums/injectable-scope.enum.d.mts +18 -0
  24. package/lib/browser/enums/injectable-scope.enum.d.mts.map +1 -0
  25. package/lib/browser/enums/injectable-scope.enum.mjs +20 -0
  26. package/lib/browser/enums/injectable-scope.enum.mjs.map +1 -0
  27. package/lib/browser/enums/injectable-type.enum.d.mts +8 -0
  28. package/lib/browser/enums/injectable-type.enum.d.mts.map +1 -0
  29. package/lib/browser/enums/injectable-type.enum.mjs +10 -0
  30. package/lib/browser/enums/injectable-type.enum.mjs.map +1 -0
  31. package/lib/browser/errors/di-error.d.mts +43 -0
  32. package/lib/browser/errors/di-error.d.mts.map +1 -0
  33. package/lib/browser/errors/di-error.mjs +98 -0
  34. package/lib/browser/errors/di-error.mjs.map +1 -0
  35. package/lib/browser/event-emitter.d.mts +16 -0
  36. package/lib/browser/event-emitter.d.mts.map +1 -0
  37. package/lib/browser/event-emitter.mjs +320 -0
  38. package/lib/browser/event-emitter.mjs.map +1 -0
  39. package/lib/browser/index.d.mts +37 -1508
  40. package/lib/browser/index.mjs +29 -2650
  41. package/lib/browser/interfaces/container.interface.d.mts +59 -0
  42. package/lib/browser/interfaces/container.interface.d.mts.map +1 -0
  43. package/lib/browser/interfaces/factory.interface.d.mts +14 -0
  44. package/lib/browser/interfaces/factory.interface.d.mts.map +1 -0
  45. package/lib/browser/interfaces/on-service-destroy.interface.d.mts +7 -0
  46. package/lib/browser/interfaces/on-service-destroy.interface.d.mts.map +1 -0
  47. package/lib/browser/interfaces/on-service-init.interface.d.mts +7 -0
  48. package/lib/browser/interfaces/on-service-init.interface.d.mts.map +1 -0
  49. package/lib/browser/internal/context/async-local-storage.browser.mjs +20 -0
  50. package/lib/browser/internal/context/async-local-storage.browser.mjs.map +1 -0
  51. package/lib/browser/internal/context/async-local-storage.d.mts +9 -0
  52. package/lib/browser/internal/context/async-local-storage.d.mts.map +1 -0
  53. package/lib/browser/internal/context/async-local-storage.types.d.mts +11 -0
  54. package/lib/browser/internal/context/async-local-storage.types.d.mts.map +1 -0
  55. package/lib/browser/internal/context/factory-context.d.mts +23 -0
  56. package/lib/browser/internal/context/factory-context.d.mts.map +1 -0
  57. package/lib/browser/internal/context/resolution-context.d.mts +43 -0
  58. package/lib/browser/internal/context/resolution-context.d.mts.map +1 -0
  59. package/lib/browser/internal/context/resolution-context.mjs +56 -0
  60. package/lib/browser/internal/context/resolution-context.mjs.map +1 -0
  61. package/lib/browser/internal/context/service-initialization-context.d.mts +48 -0
  62. package/lib/browser/internal/context/service-initialization-context.d.mts.map +1 -0
  63. package/lib/browser/internal/context/sync-local-storage.mjs +53 -0
  64. package/lib/browser/internal/context/sync-local-storage.mjs.map +1 -0
  65. package/lib/browser/internal/core/instance-resolver.d.mts +119 -0
  66. package/lib/browser/internal/core/instance-resolver.d.mts.map +1 -0
  67. package/lib/browser/internal/core/instance-resolver.mjs +306 -0
  68. package/lib/browser/internal/core/instance-resolver.mjs.map +1 -0
  69. package/lib/browser/internal/core/name-resolver.d.mts +52 -0
  70. package/lib/browser/internal/core/name-resolver.d.mts.map +1 -0
  71. package/lib/browser/internal/core/name-resolver.mjs +118 -0
  72. package/lib/browser/internal/core/name-resolver.mjs.map +1 -0
  73. package/lib/browser/internal/core/scope-tracker.d.mts +65 -0
  74. package/lib/browser/internal/core/scope-tracker.d.mts.map +1 -0
  75. package/lib/browser/internal/core/scope-tracker.mjs +120 -0
  76. package/lib/browser/internal/core/scope-tracker.mjs.map +1 -0
  77. package/lib/browser/internal/core/service-initializer.d.mts +44 -0
  78. package/lib/browser/internal/core/service-initializer.d.mts.map +1 -0
  79. package/lib/browser/internal/core/service-initializer.mjs +109 -0
  80. package/lib/browser/internal/core/service-initializer.mjs.map +1 -0
  81. package/lib/browser/internal/core/service-invalidator.d.mts +81 -0
  82. package/lib/browser/internal/core/service-invalidator.d.mts.map +1 -0
  83. package/lib/browser/internal/core/service-invalidator.mjs +142 -0
  84. package/lib/browser/internal/core/service-invalidator.mjs.map +1 -0
  85. package/lib/browser/internal/core/token-resolver.d.mts +54 -0
  86. package/lib/browser/internal/core/token-resolver.d.mts.map +1 -0
  87. package/lib/browser/internal/core/token-resolver.mjs +77 -0
  88. package/lib/browser/internal/core/token-resolver.mjs.map +1 -0
  89. package/lib/browser/internal/holder/holder-storage.interface.d.mts +99 -0
  90. package/lib/browser/internal/holder/holder-storage.interface.d.mts.map +1 -0
  91. package/lib/browser/internal/holder/instance-holder.d.mts +101 -0
  92. package/lib/browser/internal/holder/instance-holder.d.mts.map +1 -0
  93. package/lib/browser/internal/holder/instance-holder.mjs +19 -0
  94. package/lib/browser/internal/holder/instance-holder.mjs.map +1 -0
  95. package/lib/browser/internal/holder/unified-storage.d.mts +53 -0
  96. package/lib/browser/internal/holder/unified-storage.d.mts.map +1 -0
  97. package/lib/browser/internal/holder/unified-storage.mjs +144 -0
  98. package/lib/browser/internal/holder/unified-storage.mjs.map +1 -0
  99. package/lib/browser/internal/lifecycle/circular-detector.d.mts +39 -0
  100. package/lib/browser/internal/lifecycle/circular-detector.d.mts.map +1 -0
  101. package/lib/browser/internal/lifecycle/circular-detector.mjs +55 -0
  102. package/lib/browser/internal/lifecycle/circular-detector.mjs.map +1 -0
  103. package/lib/browser/internal/lifecycle/lifecycle-event-bus.d.mts +18 -0
  104. package/lib/browser/internal/lifecycle/lifecycle-event-bus.d.mts.map +1 -0
  105. package/lib/browser/internal/lifecycle/lifecycle-event-bus.mjs +43 -0
  106. package/lib/browser/internal/lifecycle/lifecycle-event-bus.mjs.map +1 -0
  107. package/lib/browser/internal/stub-factory-class.d.mts +14 -0
  108. package/lib/browser/internal/stub-factory-class.d.mts.map +1 -0
  109. package/lib/browser/internal/stub-factory-class.mjs +18 -0
  110. package/lib/browser/internal/stub-factory-class.mjs.map +1 -0
  111. package/lib/browser/symbols/injectable-token.d.mts +5 -0
  112. package/lib/browser/symbols/injectable-token.d.mts.map +1 -0
  113. package/lib/browser/symbols/injectable-token.mjs +6 -0
  114. package/lib/browser/symbols/injectable-token.mjs.map +1 -0
  115. package/lib/browser/token/injection-token.d.mts +55 -0
  116. package/lib/browser/token/injection-token.d.mts.map +1 -0
  117. package/lib/browser/token/injection-token.mjs +100 -0
  118. package/lib/browser/token/injection-token.mjs.map +1 -0
  119. package/lib/browser/token/registry.d.mts +37 -0
  120. package/lib/browser/token/registry.d.mts.map +1 -0
  121. package/lib/browser/token/registry.mjs +86 -0
  122. package/lib/browser/token/registry.mjs.map +1 -0
  123. package/lib/browser/utils/default-injectors.d.mts +12 -0
  124. package/lib/browser/utils/default-injectors.d.mts.map +1 -0
  125. package/lib/browser/utils/default-injectors.mjs +13 -0
  126. package/lib/browser/utils/default-injectors.mjs.map +1 -0
  127. package/lib/browser/utils/get-injectable-token.d.mts +9 -0
  128. package/lib/browser/utils/get-injectable-token.d.mts.map +1 -0
  129. package/lib/browser/utils/get-injectable-token.mjs +13 -0
  130. package/lib/browser/utils/get-injectable-token.mjs.map +1 -0
  131. package/lib/browser/utils/get-injectors.d.mts +55 -0
  132. package/lib/browser/utils/get-injectors.d.mts.map +1 -0
  133. package/lib/browser/utils/get-injectors.mjs +121 -0
  134. package/lib/browser/utils/get-injectors.mjs.map +1 -0
  135. package/lib/browser/utils/types.d.mts +23 -0
  136. package/lib/browser/utils/types.d.mts.map +1 -0
  137. package/lib/{container-Pb_Y4Z4x.mjs → container-8-z89TyQ.mjs} +1269 -1305
  138. package/lib/container-8-z89TyQ.mjs.map +1 -0
  139. package/lib/{container-BuAutHGg.d.mts → container-CNiqesCL.d.mts} +600 -569
  140. package/lib/container-CNiqesCL.d.mts.map +1 -0
  141. package/lib/{container-DnzgpfBe.cjs → container-CaY2fDuk.cjs} +1287 -1329
  142. package/lib/container-CaY2fDuk.cjs.map +1 -0
  143. package/lib/{container-oGTgX2iX.d.cts → container-D-0Ho3qL.d.cts} +601 -565
  144. package/lib/container-D-0Ho3qL.d.cts.map +1 -0
  145. package/lib/index.cjs +13 -15
  146. package/lib/index.cjs.map +1 -1
  147. package/lib/index.d.cts +58 -223
  148. package/lib/index.d.cts.map +1 -1
  149. package/lib/index.d.mts +62 -222
  150. package/lib/index.d.mts.map +1 -1
  151. package/lib/index.mjs +5 -6
  152. package/lib/index.mjs.map +1 -1
  153. package/lib/testing/index.cjs +569 -311
  154. package/lib/testing/index.cjs.map +1 -1
  155. package/lib/testing/index.d.cts +370 -41
  156. package/lib/testing/index.d.cts.map +1 -1
  157. package/lib/testing/index.d.mts +370 -41
  158. package/lib/testing/index.d.mts.map +1 -1
  159. package/lib/testing/index.mjs +568 -305
  160. package/lib/testing/index.mjs.map +1 -1
  161. package/package.json +2 -1
  162. package/src/__tests__/circular-detector.spec.mts +193 -0
  163. package/src/__tests__/concurrent.spec.mts +368 -0
  164. package/src/__tests__/container.spec.mts +32 -30
  165. package/src/__tests__/di-error.spec.mts +351 -0
  166. package/src/__tests__/e2e.browser.spec.mts +0 -4
  167. package/src/__tests__/e2e.spec.mts +10 -19
  168. package/src/__tests__/event-emitter.spec.mts +232 -109
  169. package/src/__tests__/get-injectors.spec.mts +250 -39
  170. package/src/__tests__/injection-token.spec.mts +293 -349
  171. package/src/__tests__/library-findings.spec.mts +8 -8
  172. package/src/__tests__/registry.spec.mts +358 -210
  173. package/src/__tests__/resolution-context.spec.mts +255 -0
  174. package/src/__tests__/scope-tracker.spec.mts +598 -0
  175. package/src/__tests__/scope-upgrade.spec.mts +808 -0
  176. package/src/__tests__/scoped-container.spec.mts +595 -0
  177. package/src/__tests__/test-container.spec.mts +293 -0
  178. package/src/__tests__/token-resolver.spec.mts +207 -0
  179. package/src/__tests__/unified-storage.spec.mts +535 -0
  180. package/src/__tests__/unit-test-container.spec.mts +405 -0
  181. package/src/__type-tests__/container.spec-d.mts +180 -0
  182. package/src/__type-tests__/factory.spec-d.mts +15 -3
  183. package/src/__type-tests__/inject.spec-d.mts +115 -20
  184. package/src/__type-tests__/injectable.spec-d.mts +69 -52
  185. package/src/__type-tests__/injection-token.spec-d.mts +176 -0
  186. package/src/__type-tests__/scoped-container.spec-d.mts +212 -0
  187. package/src/container/abstract-container.mts +327 -0
  188. package/src/container/container.mts +142 -170
  189. package/src/container/scoped-container.mts +126 -208
  190. package/src/decorators/factory.decorator.mts +16 -11
  191. package/src/decorators/injectable.decorator.mts +20 -16
  192. package/src/enums/index.mts +2 -2
  193. package/src/enums/injectable-scope.enum.mts +1 -0
  194. package/src/enums/injectable-type.enum.mts +1 -0
  195. package/src/errors/di-error.mts +96 -0
  196. package/src/event-emitter.mts +3 -27
  197. package/src/index.mts +6 -153
  198. package/src/interfaces/container.interface.mts +13 -0
  199. package/src/interfaces/factory.interface.mts +1 -1
  200. package/src/interfaces/index.mts +1 -1
  201. package/src/internal/context/async-local-storage.mts +3 -2
  202. package/src/internal/context/async-local-storage.types.mts +1 -0
  203. package/src/internal/context/factory-context.mts +1 -0
  204. package/src/internal/context/index.mts +3 -1
  205. package/src/internal/context/resolution-context.mts +1 -0
  206. package/src/internal/context/service-initialization-context.mts +43 -0
  207. package/src/internal/core/index.mts +5 -4
  208. package/src/internal/core/instance-resolver.mts +461 -292
  209. package/src/internal/core/name-resolver.mts +196 -0
  210. package/src/internal/core/scope-tracker.mts +242 -0
  211. package/src/internal/core/{instantiator.mts → service-initializer.mts} +51 -29
  212. package/src/internal/core/service-invalidator.mts +290 -0
  213. package/src/internal/core/{token-processor.mts → token-resolver.mts} +17 -88
  214. package/src/internal/holder/holder-storage.interface.mts +11 -5
  215. package/src/internal/holder/index.mts +2 -5
  216. package/src/internal/holder/instance-holder.mts +1 -3
  217. package/src/internal/holder/unified-storage.mts +245 -0
  218. package/src/internal/index.mts +2 -1
  219. package/src/internal/lifecycle/circular-detector.mts +1 -0
  220. package/src/internal/lifecycle/index.mts +1 -1
  221. package/src/internal/lifecycle/lifecycle-event-bus.mts +1 -0
  222. package/src/internal/stub-factory-class.mts +16 -0
  223. package/src/symbols/injectable-token.mts +3 -1
  224. package/src/testing/index.mts +2 -0
  225. package/src/testing/test-container.mts +546 -85
  226. package/src/testing/types.mts +117 -0
  227. package/src/testing/unit-test-container.mts +509 -0
  228. package/src/token/injection-token.mts +41 -4
  229. package/src/token/registry.mts +75 -9
  230. package/src/utils/default-injectors.mts +16 -0
  231. package/src/utils/get-injectable-token.mts +2 -3
  232. package/src/utils/get-injectors.mts +26 -15
  233. package/src/utils/index.mts +3 -1
  234. package/src/utils/types.mts +1 -0
  235. package/tsdown.config.mts +11 -1
  236. package/lib/browser/index.d.mts.map +0 -1
  237. package/lib/browser/index.mjs.map +0 -1
  238. package/lib/container-BuAutHGg.d.mts.map +0 -1
  239. package/lib/container-DnzgpfBe.cjs.map +0 -1
  240. package/lib/container-Pb_Y4Z4x.mjs.map +0 -1
  241. package/lib/container-oGTgX2iX.d.cts.map +0 -1
  242. package/src/__tests__/async-local-storage.browser.spec.mts +0 -166
  243. package/src/__tests__/async-local-storage.spec.mts +0 -333
  244. package/src/__tests__/errors.spec.mts +0 -87
  245. package/src/__tests__/factory.spec.mts +0 -137
  246. package/src/__tests__/injectable.spec.mts +0 -246
  247. package/src/__tests__/request-scope.spec.mts +0 -416
  248. package/src/__tests__/service-instantiator.spec.mts +0 -410
  249. package/src/__tests__/service-locator-event-bus.spec.mts +0 -242
  250. package/src/__tests__/service-locator-manager.spec.mts +0 -300
  251. package/src/__tests__/service-locator.spec.mts +0 -966
  252. package/src/__tests__/unified-api.spec.mts +0 -130
  253. package/src/browser.mts +0 -11
  254. package/src/injectors.mts +0 -18
  255. package/src/internal/context/request-context.mts +0 -214
  256. package/src/internal/core/invalidator.mts +0 -437
  257. package/src/internal/core/service-locator.mts +0 -202
  258. package/src/internal/holder/base-holder-manager.mts +0 -238
  259. package/src/internal/holder/holder-manager.mts +0 -85
  260. package/src/internal/holder/request-storage.mts +0 -134
  261. package/src/internal/holder/singleton-storage.mts +0 -105
  262. package/src/testing/README.md +0 -80
  263. package/src/testing/__tests__/test-container.spec.mts +0 -173
@@ -1,5 +1,55 @@
1
1
  import { ZodObject, ZodOptional, ZodRecord, ZodType, z } from "zod/v4";
2
2
 
3
+ //#region src/token/injection-token.d.mts
4
+ type ClassType = new (...args: any[]) => any;
5
+ type ClassTypeWithoutArguments = new () => any;
6
+ type ClassTypeWithArgument<Arg> = new (arg: Arg) => any;
7
+ type ClassTypeWithOptionalArgument<Arg> = new (arg?: Arg) => any;
8
+ type ClassTypeWithInstance<T> = new (...args: any[]) => T;
9
+ type ClassTypeWithInstanceAndArgument<T, Arg> = new (arg: Arg) => T;
10
+ type ClassTypeWithInstanceAndOptionalArgument<T, Arg> = new (arg?: Arg) => T;
11
+ type BaseInjectionTokenSchemaType = ZodObject | ZodRecord;
12
+ type OptionalInjectionTokenSchemaType = ZodOptional<ZodObject> | ZodOptional<ZodRecord>;
13
+ type InjectionTokenSchemaType = BaseInjectionTokenSchemaType | OptionalInjectionTokenSchemaType;
14
+ declare class InjectionToken<T, S extends InjectionTokenSchemaType | unknown = unknown, Required extends boolean = (S extends ZodOptional<ZodObject> ? false : S extends ZodOptional<ZodRecord> ? false : S extends ZodObject ? true : S extends ZodRecord ? true : false)> {
15
+ readonly name: string | symbol | ClassType;
16
+ readonly schema: ZodObject | undefined;
17
+ readonly id: string;
18
+ private formattedName;
19
+ constructor(name: string | symbol | ClassType, schema: ZodObject | undefined, customId?: string);
20
+ static create<T extends ClassType>(name: T): InjectionToken<InstanceType<T>, undefined>;
21
+ static create<T extends ClassType, Schema extends InjectionTokenSchemaType>(name: T, schema: Schema): Schema['_def']['type'] extends 'ZodOptional' ? InjectionToken<InstanceType<T>, Schema, false> : InjectionToken<InstanceType<T>, Schema, true>;
22
+ static create<T>(name: string | symbol): InjectionToken<T, undefined>;
23
+ static create<T, Schema extends InjectionTokenSchemaType>(name: string | any, schema: Schema): InjectionToken<T, Schema>;
24
+ static bound<T, S extends InjectionTokenSchemaType>(token: InjectionToken<T, S>, value: z.input<S>): BoundInjectionToken<T, S>;
25
+ static factory<T, S extends InjectionTokenSchemaType>(token: InjectionToken<T, S>, factory: (ctx: FactoryContext) => Promise<z.input<S>>): FactoryInjectionToken<T, S>;
26
+ static refineType<T>(token: BoundInjectionToken<any, any>): BoundInjectionToken<T, any>;
27
+ toString(): string;
28
+ }
29
+ declare class BoundInjectionToken<T, S extends InjectionTokenSchemaType> {
30
+ readonly token: InjectionToken<T, S>;
31
+ readonly value: z.input<S>;
32
+ id: string;
33
+ name: string | symbol | ClassType;
34
+ schema: InjectionTokenSchemaType;
35
+ constructor(token: InjectionToken<T, S>, value: z.input<S>);
36
+ toString(): string;
37
+ }
38
+ declare class FactoryInjectionToken<T, S extends InjectionTokenSchemaType> {
39
+ readonly token: InjectionToken<T, S>;
40
+ readonly factory: (ctx: FactoryContext) => Promise<z.input<S>>;
41
+ value?: z.input<S>;
42
+ resolved: boolean;
43
+ id: string;
44
+ name: string | symbol | ClassType;
45
+ schema: InjectionTokenSchemaType;
46
+ constructor(token: InjectionToken<T, S>, factory: (ctx: FactoryContext) => Promise<z.input<S>>);
47
+ resolve(ctx: FactoryContext): Promise<z.input<S>>;
48
+ toString(): string;
49
+ }
50
+ type AnyInjectableType = ClassType | InjectionToken<any, any> | BoundInjectionToken<any, any> | FactoryInjectionToken<any, any>;
51
+ type InjectionTokenType = InjectionToken<any, any> | BoundInjectionToken<any, any> | FactoryInjectionToken<any, any>;
52
+ //#endregion
3
53
  //#region src/utils/types.d.mts
4
54
  type Join<TElements, TSeparator extends string> = TElements extends Readonly<[infer First, ...infer Rest]> ? Rest extends ReadonlyArray<string> ? First extends string ? `${First}${Rest extends [] ? '' : TSeparator}${Join<Rest, TSeparator>}` : never : never : '';
5
55
  type UnionToIntersection<U> = (U extends any ? (k: U) => void : never) extends ((k: infer I) => void) ? I : never;
@@ -19,14 +69,6 @@ interface InjectState {
19
69
  requests: InjectRequest[];
20
70
  }
21
71
  //#endregion
22
- //#region src/interfaces/factory.interface.d.mts
23
- interface Factorable<T> {
24
- create(ctx?: FactoryContext): Promise<T> | T;
25
- }
26
- interface FactorableWithArgs<T, A extends InjectionTokenSchemaType> {
27
- create(ctx?: FactoryContext, ...args: [z.output<A>]): Promise<T> | T;
28
- }
29
- //#endregion
30
72
  //#region src/interfaces/container.interface.d.mts
31
73
  /**
32
74
  * Interface for dependency injection containers.
@@ -52,6 +94,15 @@ interface IContainer {
52
94
  * Checks if a service is registered in the container.
53
95
  */
54
96
  isRegistered(token: any): boolean;
97
+ /**
98
+ * Adds an instance to the container.
99
+ * Accepts class types, InjectionTokens, and BoundInjectionTokens.
100
+ * Rejects InjectionTokens with required schemas (use BoundInjectionToken instead).
101
+ *
102
+ * @param token The class type, InjectionToken, or BoundInjectionToken to register the instance for
103
+ * @param instance The instance to store
104
+ */
105
+ addInstance<T>(token: ClassType | InjectionToken<T, any> | BoundInjectionToken<T, any>, instance: T): void;
55
106
  /**
56
107
  * Disposes the container and cleans up all resources.
57
108
  */
@@ -69,6 +120,69 @@ interface IContainer {
69
120
  tryGetSync<T>(token: any, args?: any): T | null;
70
121
  }
71
122
  //#endregion
123
+ //#region src/enums/injectable-scope.enum.d.mts
124
+ declare enum InjectableScope {
125
+ /**
126
+ * Singleton scope: The instance is created once and shared across the application.
127
+ */
128
+ Singleton = "Singleton",
129
+ /**
130
+ * Instance scope: A new instance is created for each injection.
131
+ */
132
+ Transient = "Transient",
133
+ /**
134
+ * Request scope: The instance is created once per request and shared within that request context.
135
+ */
136
+ Request = "Request",
137
+ }
138
+ //#endregion
139
+ //#region src/enums/injectable-type.enum.d.mts
140
+ declare enum InjectableType {
141
+ Class = "Class",
142
+ Factory = "Factory",
143
+ }
144
+ //#endregion
145
+ //#region src/internal/context/service-initialization-context.d.mts
146
+ /**
147
+ * Context provided to injectors during service initialization.
148
+ *
149
+ * Extends FactoryContext with additional tracking information about
150
+ * the service being initialized, its dependencies, and scope.
151
+ * Used for scope upgrade tracking and dependency management.
152
+ */
153
+ interface ServiceInitializationContext {
154
+ inject: Injectors['asyncInject'];
155
+ /**
156
+ * The container instance for dependency resolution.
157
+ * This may be either a Container or ScopedContainer.
158
+ */
159
+ container: IContainer;
160
+ addDestroyListener: (listener: () => void) => void;
161
+ getDestroyListeners: () => (() => void)[];
162
+ /**
163
+ * The name of the service being initialized.
164
+ */
165
+ serviceName: string;
166
+ /**
167
+ * Set of dependency names that this service depends on.
168
+ * Automatically populated as dependencies are resolved.
169
+ */
170
+ dependencies: Set<string>;
171
+ /**
172
+ * The scope of the service being initialized.
173
+ */
174
+ scope: InjectableScope;
175
+ /**
176
+ * Track a dependency that was resolved.
177
+ * Used for scope upgrade tracking - if a Singleton service
178
+ * resolves a Request dependency, the scope can be upgraded.
179
+ *
180
+ * @param name The name of the dependency
181
+ * @param scope The scope of the dependency
182
+ */
183
+ trackDependency(name: string, scope: InjectableScope): void;
184
+ }
185
+ //#endregion
72
186
  //#region src/utils/get-injectors.d.mts
73
187
  interface Injectors {
74
188
  asyncInject<T extends ClassTypeWithoutArguments>(token: T): InstanceType<T> extends Factorable<infer R> ? Promise<R> : Promise<InstanceType<T>>;
@@ -112,15 +226,10 @@ interface Injectors {
112
226
  optional<T>(token: BoundInjectionToken<T, any>): T | null;
113
227
  optional<T>(token: FactoryInjectionToken<T, any>): T | null;
114
228
  wrapSyncInit(cb: () => any): (injectState?: InjectState) => [any, Promise<any>[], InjectState];
115
- provideFactoryContext(context: FactoryContext | null): FactoryContext | null;
229
+ provideFactoryContext(context: ServiceInitializationContext | null): ServiceInitializationContext | null;
116
230
  }
117
231
  declare function getInjectors(): Injectors;
118
232
  //#endregion
119
- //#region src/utils/get-injectable-token.d.mts
120
- declare function getInjectableToken<R>(target: ClassType): R extends {
121
- create(...args: any[]): infer V;
122
- } ? InjectionToken<V> : InjectionToken<R>;
123
- //#endregion
124
233
  //#region src/internal/context/factory-context.d.mts
125
234
  /**
126
235
  * Context provided to factory functions during service instantiation.
@@ -138,76 +247,12 @@ interface FactoryContext {
138
247
  addDestroyListener: (listener: () => void) => void;
139
248
  }
140
249
  //#endregion
141
- //#region src/token/injection-token.d.mts
142
- type ClassType = new (...args: any[]) => any;
143
- type ClassTypeWithoutArguments = new () => any;
144
- type ClassTypeWithArgument<Arg> = new (arg: Arg) => any;
145
- type ClassTypeWithOptionalArgument<Arg> = new (arg?: Arg) => any;
146
- type ClassTypeWithInstance<T> = new (...args: any[]) => T;
147
- type ClassTypeWithInstanceAndArgument<T, Arg> = new (arg: Arg) => T;
148
- type ClassTypeWithInstanceAndOptionalArgument<T, Arg> = new (arg?: Arg) => T;
149
- type BaseInjectionTokenSchemaType = ZodObject | ZodRecord;
150
- type OptionalInjectionTokenSchemaType = ZodOptional<ZodObject> | ZodOptional<ZodRecord>;
151
- type InjectionTokenSchemaType = BaseInjectionTokenSchemaType | OptionalInjectionTokenSchemaType;
152
- declare class InjectionToken<T, S extends InjectionTokenSchemaType | unknown = unknown, Required extends boolean = (S extends ZodOptional<ZodObject> ? false : S extends ZodOptional<ZodRecord> ? false : S extends ZodObject ? true : S extends ZodRecord ? true : false)> {
153
- readonly name: string | symbol | ClassType;
154
- readonly schema: ZodObject | undefined;
155
- id: `${string}-${string}-${string}-${string}-${string}`;
156
- private formattedName;
157
- constructor(name: string | symbol | ClassType, schema: ZodObject | undefined);
158
- static create<T extends ClassType>(name: T): InjectionToken<InstanceType<T>, undefined>;
159
- static create<T extends ClassType, Schema extends InjectionTokenSchemaType>(name: T, schema: Schema): Schema['_def']['type'] extends 'ZodOptional' ? InjectionToken<InstanceType<T>, Schema, false> : InjectionToken<InstanceType<T>, Schema, true>;
160
- static create<T>(name: string | symbol): InjectionToken<T, undefined>;
161
- static create<T, Schema extends InjectionTokenSchemaType>(name: string | any, schema: Schema): InjectionToken<T, Schema>;
162
- static bound<T, S extends InjectionTokenSchemaType>(token: InjectionToken<T, S>, value: z.input<S>): BoundInjectionToken<T, S>;
163
- static factory<T, S extends InjectionTokenSchemaType>(token: InjectionToken<T, S>, factory: (ctx: FactoryContext) => Promise<z.input<S>>): FactoryInjectionToken<T, S>;
164
- static refineType<T>(token: BoundInjectionToken<any, any>): BoundInjectionToken<T, any>;
165
- toString(): string;
166
- }
167
- declare class BoundInjectionToken<T, S extends InjectionTokenSchemaType> {
168
- readonly token: InjectionToken<T, S>;
169
- readonly value: z.input<S>;
170
- id: string;
171
- name: string | symbol | ClassType;
172
- schema: InjectionTokenSchemaType;
173
- constructor(token: InjectionToken<T, S>, value: z.input<S>);
174
- toString(): string;
175
- }
176
- declare class FactoryInjectionToken<T, S extends InjectionTokenSchemaType> {
177
- readonly token: InjectionToken<T, S>;
178
- readonly factory: (ctx: FactoryContext) => Promise<z.input<S>>;
179
- value?: z.input<S>;
180
- resolved: boolean;
181
- id: string;
182
- name: string | symbol | ClassType;
183
- schema: InjectionTokenSchemaType;
184
- constructor(token: InjectionToken<T, S>, factory: (ctx: FactoryContext) => Promise<z.input<S>>);
185
- resolve(ctx: FactoryContext): Promise<z.input<S>>;
186
- toString(): string;
187
- }
188
- type AnyInjectableType = ClassType | InjectionToken<any, any> | BoundInjectionToken<any, any> | FactoryInjectionToken<any, any>;
189
- type InjectionTokenType = InjectionToken<any, any> | BoundInjectionToken<any, any> | FactoryInjectionToken<any, any>;
190
- //#endregion
191
- //#region src/enums/injectable-scope.enum.d.mts
192
- declare enum InjectableScope {
193
- /**
194
- * Singleton scope: The instance is created once and shared across the application.
195
- */
196
- Singleton = "Singleton",
197
- /**
198
- * Instance scope: A new instance is created for each injection.
199
- */
200
- Transient = "Transient",
201
- /**
202
- * Request scope: The instance is created once per request and shared within that request context.
203
- */
204
- Request = "Request",
250
+ //#region src/interfaces/factory.interface.d.mts
251
+ interface Factorable<T> {
252
+ create(ctx?: FactoryContext): Promise<T> | T;
205
253
  }
206
- //#endregion
207
- //#region src/enums/injectable-type.enum.d.mts
208
- declare enum InjectableType {
209
- Class = "Class",
210
- Factory = "Factory",
254
+ interface FactorableWithArgs<T, A extends InjectionTokenSchemaType> {
255
+ create(ctx?: FactoryContext, ...args: [z.output<A>]): Promise<T> | T;
211
256
  }
212
257
  //#endregion
213
258
  //#region src/token/registry.d.mts
@@ -216,14 +261,17 @@ type FactoryRecord<Instance = any, Schema = any> = {
216
261
  originalToken: InjectionToken<Instance, Schema>;
217
262
  target: ClassType;
218
263
  type: InjectableType;
264
+ priority: number;
219
265
  };
220
266
  declare class Registry {
221
267
  private readonly parent?;
222
268
  private readonly factories;
269
+ private readonly highestPriority;
223
270
  constructor(parent?: Registry | undefined);
224
271
  has(token: InjectionToken<any, any>): boolean;
225
272
  get<Instance, Schema>(token: InjectionToken<Instance, Schema>): FactoryRecord<Instance, Schema>;
226
- set<Instance, Schema>(token: InjectionToken<Instance, Schema>, scope: InjectableScope, target: ClassType, type: InjectableType): void;
273
+ getAll<Instance, Schema>(token: InjectionToken<Instance, Schema>): FactoryRecord<Instance, Schema>[];
274
+ set<Instance, Schema>(token: InjectionToken<Instance, Schema>, scope: InjectableScope, target: ClassType, type: InjectableType, priority?: number): void;
227
275
  delete(token: InjectionToken<any, any>): void;
228
276
  /**
229
277
  * Updates the scope of an already registered factory.
@@ -238,6 +286,52 @@ declare class Registry {
238
286
  }
239
287
  declare const globalRegistry: Registry;
240
288
  //#endregion
289
+ //#region src/internal/core/name-resolver.d.mts
290
+ /**
291
+ * Handles instance name generation with support for requestId and scope.
292
+ *
293
+ * Generates unique instance identifiers based on token, arguments, and scope.
294
+ * Request-scoped services MUST include requestId in their name for proper isolation.
295
+ */
296
+ declare class NameResolver {
297
+ private readonly logger;
298
+ private readonly instanceNameCache;
299
+ constructor(logger?: Console | null);
300
+ /**
301
+ * Generates a unique instance name based on token, arguments, requestId, and scope.
302
+ *
303
+ * Name formats:
304
+ * - Singleton/Transient without args: `${tokenId}`
305
+ * - Singleton/Transient with args: `${tokenId}:${argsHash}`
306
+ * - Request without args: `${tokenId}:requestId=${requestId}`
307
+ * - Request with args: `${tokenId}:requestId=${requestId}:${argsHash}`
308
+ *
309
+ * @param token The injection token
310
+ * @param args Optional arguments
311
+ * @param requestId Optional request ID (required for request-scoped services)
312
+ * @param scope Optional scope (used to determine if requestId should be included)
313
+ * @returns The generated instance name
314
+ */
315
+ generateInstanceName(token: InjectionTokenType, args?: any, requestId?: string, scope?: InjectableScope): string;
316
+ /**
317
+ * Upgrades an existing instance name to include requestId.
318
+ * Preserves any args hash that might already be in the name.
319
+ *
320
+ * Examples:
321
+ * - `TokenName` → `TokenName:requestId=req-123`
322
+ * - `TokenName:abc123` → `TokenName:requestId=req-123:abc123`
323
+ *
324
+ * @param existingName The existing instance name (without requestId)
325
+ * @param requestId The request ID to add
326
+ * @returns The upgraded instance name with requestId
327
+ */
328
+ upgradeInstanceNameToRequest(existingName: string, requestId: string): string;
329
+ /**
330
+ * Formats a single argument value for instance name generation.
331
+ */
332
+ formatArgValue(value: any): string;
333
+ }
334
+ //#endregion
241
335
  //#region src/errors/di-error.d.mts
242
336
  declare enum DIErrorCode {
243
337
  FactoryNotFound = "FactoryNotFound",
@@ -245,6 +339,14 @@ declare enum DIErrorCode {
245
339
  InstanceNotFound = "InstanceNotFound",
246
340
  InstanceDestroying = "InstanceDestroying",
247
341
  CircularDependency = "CircularDependency",
342
+ TokenValidationError = "TokenValidationError",
343
+ TokenSchemaRequiredError = "TokenSchemaRequiredError",
344
+ ClassNotInjectable = "ClassNotInjectable",
345
+ ScopeMismatchError = "ScopeMismatchError",
346
+ PriorityConflictError = "PriorityConflictError",
347
+ StorageError = "StorageError",
348
+ InitializationError = "InitializationError",
349
+ DependencyResolutionError = "DependencyResolutionError",
248
350
  UnknownError = "UnknownError",
249
351
  }
250
352
  declare class DIError extends Error {
@@ -258,6 +360,14 @@ declare class DIError extends Error {
258
360
  static instanceDestroying(name: string): DIError;
259
361
  static unknown(message: string | Error, context?: Record<string, unknown>): DIError;
260
362
  static circularDependency(cycle: string[]): DIError;
363
+ static tokenValidationError(message: string, schema: InjectionTokenSchemaType | undefined, value: unknown): DIError;
364
+ static tokenSchemaRequiredError(token: string | symbol | unknown): DIError;
365
+ static classNotInjectable(className: string): DIError;
366
+ static scopeMismatchError(token: string | symbol | unknown, expectedScope: string, actualScope: string): DIError;
367
+ static priorityConflictError(token: string | symbol | unknown, records: FactoryRecord[]): DIError;
368
+ static storageError(message: string, operation: string, instanceName?: string): DIError;
369
+ static initializationError(serviceName: string, error: Error | string): DIError;
370
+ static dependencyResolutionError(serviceName: string, dependencyName: string, error: Error | string): DIError;
261
371
  }
262
372
  //#endregion
263
373
  //#region src/internal/holder/instance-holder.d.mts
@@ -274,8 +384,6 @@ declare enum InstanceStatus {
274
384
  /** Instance creation failed with an error */
275
385
  Error = "error",
276
386
  }
277
- /** Callback function for instance effects */
278
- type InstanceEffect = () => void;
279
387
  /** Callback function for instance destruction listeners */
280
388
  type InstanceDestroyListener = () => void | Promise<void>;
281
389
  /**
@@ -370,8 +478,7 @@ type HolderGetResult<T = unknown> = [undefined, InstanceHolder<T>] | [DIError, I
370
478
  * Interface for abstracting holder storage operations.
371
479
  *
372
480
  * Enables unified instance resolution logic regardless of where
373
- * holders are stored (singleton manager, request context, etc.).
374
- * This is the key abstraction for the Storage Strategy pattern.
481
+ * holders are stored. This is the key abstraction for the unified storage pattern.
375
482
  */
376
483
  interface IHolderStorage {
377
484
  /**
@@ -440,223 +547,296 @@ interface IHolderStorage {
440
547
  * @returns Array of instance names that have this instance as a dependency
441
548
  */
442
549
  findDependents(instanceName: string): string[];
550
+ /**
551
+ * Updates dependency references when instance names change.
552
+ * Used during scope upgrades when instance names are regenerated with requestId.
553
+ *
554
+ * @param oldName The old instance name
555
+ * @param newName The new instance name
556
+ */
557
+ updateDependencyReference(oldName: string, newName: string): void;
443
558
  }
444
559
  //#endregion
445
- //#region src/internal/holder/base-holder-manager.d.mts
560
+ //#region src/internal/lifecycle/lifecycle-event-bus.d.mts
446
561
  /**
447
- * Result type for waitForHolderReady.
448
- * Returns either [undefined, holder] on success or [error] on failure.
562
+ * Event bus for service lifecycle events (create, destroy, etc.).
563
+ *
564
+ * Enables loose coupling between services by allowing them to subscribe
565
+ * to lifecycle events of their dependencies without direct references.
566
+ * Used primarily for invalidation cascading.
449
567
  */
450
- type HolderReadyResult<T> = [undefined, InstanceHolder<T>] | [DIError];
568
+ declare class LifecycleEventBus {
569
+ private readonly logger;
570
+ private listeners;
571
+ constructor(logger?: Console | null);
572
+ on<Event extends string | `pre:${string}` | `post:${string}`>(ns: string, event: Event, listener: (event: Event) => void): () => void;
573
+ emit(key: string, event: string): Promise<PromiseSettledResult<any>[] | undefined>;
574
+ }
575
+ //#endregion
576
+ //#region src/internal/core/service-invalidator.d.mts
577
+ interface ClearAllOptions {
578
+ /** Whether to wait for all services to settle before starting (default: true) */
579
+ waitForSettlement?: boolean;
580
+ }
581
+ interface InvalidationOptions {
582
+ /** Whether to emit events after invalidation (default: true) */
583
+ emitEvents?: boolean;
584
+ /** Custom event emitter function */
585
+ onInvalidated?: (instanceName: string) => Promise<void>;
586
+ /** Whether to cascade invalidation to dependents (default: false - events handle it) */
587
+ cascade?: boolean;
588
+ }
451
589
  /**
452
- * Abstract base class providing common functionality for managing InstanceHolder objects.
590
+ * Manages graceful service cleanup with event-based invalidation.
453
591
  *
454
- * Provides shared patterns for holder storage, creation, and lifecycle management
455
- * used by both singleton (HolderManager) and request-scoped (RequestContext) managers.
592
+ * Uses event subscriptions instead of manual dependent finding.
593
+ * When a service is created, it subscribes to destroy events of its dependencies.
594
+ * When a dependency is destroyed, the event automatically invalidates dependents.
456
595
  */
457
- declare abstract class BaseHolderManager {
458
- protected readonly logger: Console | null;
459
- protected readonly _holders: Map<string, InstanceHolder>;
460
- constructor(logger?: Console | null);
461
- /**
462
- * Protected getter for accessing the holders map from subclasses.
463
- */
464
- protected get holders(): Map<string, InstanceHolder>;
465
- /**
466
- * Abstract method to get a holder by name. Each implementation defines its own return type
467
- * based on their specific error handling and validation needs.
468
- */
469
- abstract get(name: string): any;
596
+ declare class ServiceInvalidator {
597
+ private readonly eventBus;
598
+ private readonly logger;
599
+ constructor(eventBus: LifecycleEventBus | null, logger?: Console | null);
470
600
  /**
471
- * Abstract method to set a holder by name. Each implementation may have different validation logic.
601
+ * Invalidates a service using a specific storage.
602
+ * Event-based invalidation means dependents are automatically invalidated
603
+ * via destroy event subscriptions - no need to manually find dependents.
604
+ *
605
+ * @param service The instance name to invalidate
606
+ * @param storage The storage to use for this invalidation
607
+ * @param options Additional options for invalidation behavior
472
608
  */
473
- abstract set(name: string, holder: InstanceHolder): void;
609
+ invalidateWithStorage(service: string, storage: IHolderStorage, options?: InvalidationOptions): Promise<void>;
474
610
  /**
475
- * Abstract method to check if a holder exists. Each implementation may have different validation logic.
611
+ * Sets up destroy event subscriptions for a service's dependencies.
612
+ * Called when a service is successfully instantiated.
613
+ *
614
+ * @param serviceName The name of the service
615
+ * @param dependencies The set of dependency names
616
+ * @param storage The storage to use for invalidation
617
+ * @param holder The holder for the service (to add unsubscribe to destroy listeners)
476
618
  */
477
- abstract has(name: string): any;
619
+ setupDependencySubscriptions(serviceName: string, dependencies: Set<string>, storage: IHolderStorage, holder: InstanceHolder): void;
478
620
  /**
479
- * Deletes a holder by name.
480
- * @param name The name of the holder to delete
481
- * @returns true if the holder was deleted, false if it didn't exist
621
+ * Gracefully clears all services in a specific storage.
622
+ * This allows clearing request-scoped services using a RequestStorage.
482
623
  */
483
- delete(name: string): boolean;
624
+ clearAllWithStorage(storage: IHolderStorage, options?: ClearAllOptions): Promise<void>;
484
625
  /**
485
- * Filters holders based on a predicate function.
486
- * @param predicate Function to test each holder
487
- * @returns A new Map containing only the holders that match the predicate
626
+ * Waits for all services in a specific storage to settle.
488
627
  */
489
- filter(predicate: (value: InstanceHolder<any>, key: string) => boolean): Map<string, InstanceHolder>;
628
+ readyWithStorage(storage: IHolderStorage): Promise<void>;
490
629
  /**
491
- * Clears all holders from this manager.
630
+ * Invalidates a single holder using a specific storage.
492
631
  */
493
- clear(): void;
632
+ private invalidateHolderWithStorage;
494
633
  /**
495
- * Gets the number of holders currently managed.
634
+ * Common invalidation logic for holders based on their status.
496
635
  */
497
- size(): number;
636
+ private invalidateHolderByStatus;
498
637
  /**
499
- * Creates a new holder with Creating status and a deferred creation promise.
500
- * This is useful for creating placeholder holders that can be fulfilled later.
501
- * @param name The name of the instance
502
- * @param type The injectable type
503
- * @param scope The injectable scope
504
- * @param deps Optional set of dependencies
505
- * @returns A tuple containing the deferred promise and the holder
638
+ * Destroys a holder using a specific storage.
506
639
  */
507
- createCreatingHolder<Instance>(name: string, type: InjectableType, scope: InjectableScope, deps?: Set<string>): [ReturnType<typeof Promise.withResolvers<[undefined, Instance]>>, InstanceHolder<Instance>];
640
+ private destroyHolderWithStorage;
508
641
  /**
509
- * Creates a new holder with Created status and an actual instance.
510
- * This is useful for creating holders that already have their instance ready.
511
- * @param name The name of the instance
512
- * @param instance The actual instance to store
513
- * @param type The injectable type
514
- * @param scope The injectable scope
515
- * @param deps Optional set of dependencies
516
- * @returns The created holder
642
+ * Waits for a holder to settle (either created, destroyed, or error state).
517
643
  */
518
- protected createCreatedHolder<Instance>(name: string, instance: Instance, type: InjectableType, scope: InjectableScope, deps?: Set<string>): InstanceHolder<Instance>;
644
+ private waitForHolderToSettle;
519
645
  /**
520
- * Gets all holder names currently managed.
646
+ * Emits events to listeners for instance lifecycle events.
521
647
  */
522
- getAllNames(): string[];
648
+ private emitInstanceEvent;
649
+ }
650
+ //#endregion
651
+ //#region src/internal/core/token-resolver.d.mts
652
+ /**
653
+ * Handles token validation and resolution.
654
+ *
655
+ * Focuses on token validation, normalization, and argument validation.
656
+ * Name generation is handled by NameResolver.
657
+ */
658
+ declare class TokenResolver {
659
+ private readonly logger;
660
+ constructor(logger?: Console | null);
523
661
  /**
524
- * Gets all holders currently managed.
662
+ * Normalizes a token to an InjectionToken.
663
+ * Handles class constructors by getting their injectable token.
664
+ *
665
+ * @param token A class constructor, InjectionToken, BoundInjectionToken, or FactoryInjectionToken
666
+ * @returns The normalized InjectionTokenType
525
667
  */
526
- getAllHolders(): InstanceHolder[];
668
+ normalizeToken(token: AnyInjectableType): InjectionTokenType;
527
669
  /**
528
- * Checks if this manager has any holders.
670
+ * Gets the underlying "real" token from wrapped tokens.
671
+ * For BoundInjectionToken and FactoryInjectionToken, returns the wrapped token.
672
+ * For other tokens, returns the token itself.
673
+ *
674
+ * @param token The token to unwrap
675
+ * @returns The underlying InjectionToken
529
676
  */
530
- isEmpty(): boolean;
677
+ getRealToken<T = unknown>(token: InjectionTokenType): InjectionToken<T>;
531
678
  /**
532
- * Waits for a holder to be ready and returns the appropriate result.
533
- * This is a shared utility used by both singleton and request-scoped resolution.
679
+ * Convenience method that normalizes a token and then gets the real token.
680
+ * Useful for checking registry entries where you need the actual registered token.
534
681
  *
535
- * @param holder The holder to wait for
536
- * @param waiterHolder Optional holder that is doing the waiting (for circular dependency detection)
537
- * @param getHolder Optional function to retrieve holders by name (required if waiterHolder is provided)
538
- * @returns A promise that resolves with [undefined, holder] on success or [DIError] on failure
682
+ * @param token Any injectable type
683
+ * @returns The underlying InjectionToken
539
684
  */
540
- static waitForHolderReady<T>(holder: InstanceHolder<T>, waiterHolder?: InstanceHolder, getHolder?: (name: string) => InstanceHolder | undefined): Promise<HolderReadyResult<T>>;
685
+ getRegistryToken<T = unknown>(token: AnyInjectableType): InjectionToken<T>;
686
+ /**
687
+ * Validates and resolves token arguments, handling factory token resolution and validation.
688
+ *
689
+ * @param token The token to validate
690
+ * @param args Optional arguments
691
+ * @returns [error, { actualToken, validatedArgs }]
692
+ */
693
+ validateAndResolveTokenArgs(token: AnyInjectableType, args?: any): [DIError | undefined, {
694
+ actualToken: InjectionTokenType;
695
+ validatedArgs?: any;
696
+ }];
541
697
  }
542
698
  //#endregion
543
- //#region src/internal/context/request-context.d.mts
699
+ //#region src/internal/holder/unified-storage.d.mts
544
700
  /**
545
- * Interface for request context that manages pre-prepared instances for a specific request.
701
+ * Unified storage implementation that works the same way regardless of scope.
702
+ * Replaces RequestContext, HolderManager, SingletonStorage, RequestStorage.
546
703
  *
547
- * Provides isolated storage for request-scoped services, enabling efficient
548
- * instantiation and cleanup within the lifecycle of a single request.
704
+ * Scope is just metadata - storage operations are identical for all scopes.
705
+ * Different storage instances are just isolated storage spaces.
549
706
  */
550
- interface RequestContext {
707
+ declare class UnifiedStorage implements IHolderStorage {
708
+ readonly scope: InjectableScope;
709
+ private readonly holders;
551
710
  /**
552
- * Unique identifier for this request context.
711
+ * Reverse dependency index: maps a dependency name to the set of holder names that depend on it.
712
+ * This allows O(1) lookup of dependents instead of O(n) iteration.
553
713
  */
554
- readonly requestId: string;
714
+ private readonly dependents;
715
+ constructor(scope?: InjectableScope);
716
+ get<T = unknown>(instanceName: string): HolderGetResult<T>;
717
+ set(instanceName: string, holder: InstanceHolder): void;
718
+ delete(instanceName: string): boolean;
719
+ createHolder<T>(instanceName: string, type: InjectableType, deps: Set<string>): [ReturnType<typeof Promise.withResolvers<[undefined, T]>>, InstanceHolder<T>];
720
+ storeInstance(instanceName: string, instance: unknown): void;
721
+ handles(scope: InjectableScope): boolean;
722
+ getAllNames(): string[];
723
+ forEach(callback: (name: string, holder: InstanceHolder) => void): void;
724
+ findByInstance(instance: unknown): InstanceHolder | null;
725
+ findDependents(instanceName: string): string[];
555
726
  /**
556
- * Instance holders for request-scoped services.
727
+ * Updates dependency references when instance names change.
728
+ * Used during scope upgrades when instance names are regenerated with requestId.
729
+ *
730
+ * @param oldName The old instance name
731
+ * @param newName The new instance name
557
732
  */
558
- readonly holders: Map<string, InstanceHolder>;
733
+ updateDependencyReference(oldName: string, newName: string): void;
559
734
  /**
560
- * Priority for resolution in FactoryContext.inject method.
561
- * Higher values take precedence.
735
+ * Registers a holder's dependencies in the reverse index.
562
736
  */
563
- readonly priority: number;
737
+ private registerDependencies;
564
738
  /**
565
- * Request-specific metadata that can be used during instantiation.
739
+ * Removes a holder from the reverse dependency index.
566
740
  */
567
- readonly metadata: Map<string, any>;
741
+ private removeFromDependentsIndex;
742
+ }
743
+ //#endregion
744
+ //#region src/container/abstract-container.d.mts
745
+ /**
746
+ * Abstract base class for dependency injection containers.
747
+ *
748
+ * Provides shared implementation for common container operations.
749
+ * Both Container and ScopedContainer extend this class.
750
+ */
751
+ declare abstract class AbstractContainer implements IContainer {
568
752
  /**
569
- * Timestamp when this context was created.
753
+ * The default scope used when adding instances without explicit registration.
570
754
  */
571
- readonly createdAt: number;
755
+ protected abstract readonly defaultScope: InjectableScope;
572
756
  /**
573
- * Adds a pre-prepared instance to this context.
757
+ * The request ID for scoped containers, undefined for root container.
574
758
  */
575
- addInstance(instanceName: string, instance: any, holder: InstanceHolder): void;
759
+ protected abstract readonly requestId: string | undefined;
576
760
  /**
577
- * Adds a pre-prepared instance to this context.
761
+ * Gets the storage for this container.
578
762
  */
579
- addInstance(token: InjectionToken<any, undefined>, instance: any): void;
763
+ abstract getStorage(): UnifiedStorage;
580
764
  /**
581
- * Gets an instance holder from this context.
765
+ * Gets the registry for this container.
582
766
  */
583
- get(instanceName: string): InstanceHolder | undefined;
767
+ protected abstract getRegistry(): Registry;
584
768
  /**
585
- * Sets an instance holder by name.
769
+ * Gets the token resolver.
586
770
  */
587
- set(instanceName: string, holder: InstanceHolder): void;
771
+ protected abstract getTokenResolver(): TokenResolver;
588
772
  /**
589
- * Checks if this context has a pre-prepared instance.
773
+ * Gets the name resolver.
590
774
  */
591
- has(instanceName: string): boolean;
775
+ protected abstract getNameResolver(): NameResolver;
592
776
  /**
593
- * Clears all instances and holders from this context.
777
+ * Gets the service invalidator.
594
778
  */
595
- clear(): void;
779
+ protected abstract getServiceInvalidator(): ServiceInvalidator;
596
780
  /**
597
- * Gets metadata value by key.
781
+ * Gets an instance from the container.
598
782
  */
599
- getMetadata(key: string): any | undefined;
783
+ abstract get<T extends ClassType>(token: T): InstanceType<T> extends Factorable<infer R> ? Promise<R> : Promise<InstanceType<T>>;
784
+ abstract get<T extends ClassTypeWithArgument<R>, R>(token: T, args: R): Promise<InstanceType<T>>;
785
+ abstract get<T, S extends InjectionTokenSchemaType>(token: InjectionToken<T, S>, args: z.input<S>): Promise<T>;
786
+ abstract get<T, S extends InjectionTokenSchemaType, R extends boolean>(token: InjectionToken<T, S, R>): R extends false ? Promise<T> : S extends ZodType<infer Type> ? `Error: Your token requires args: ${Join<UnionToArray<keyof Type>, ', '>}` : 'Error: Your token requires args';
787
+ abstract get<T>(token: InjectionToken<T, undefined>): Promise<T>;
788
+ abstract get<T>(token: BoundInjectionToken<T, any>): Promise<T>;
789
+ abstract get<T>(token: FactoryInjectionToken<T, any>): Promise<T>;
600
790
  /**
601
- * Sets metadata value by key.
791
+ * Invalidates a service and its dependencies.
602
792
  */
603
- setMetadata(key: string, value: any): void;
793
+ abstract invalidate(service: unknown): Promise<void>;
604
794
  /**
605
- * Filters holders based on a predicate function.
795
+ * Disposes the container and cleans up all resources.
606
796
  */
607
- filter(predicate: (value: InstanceHolder<any>, key: string) => boolean): Map<string, InstanceHolder>;
797
+ abstract dispose(): Promise<void>;
608
798
  /**
609
- * Deletes a holder by name.
799
+ * Calculates the instance name for a given token and optional arguments.
800
+ *
801
+ * @internal
802
+ * @param token The class type, InjectionToken, BoundInjectionToken, or FactoryInjectionToken
803
+ * @param args Optional arguments (ignored for BoundInjectionToken which uses its bound value)
804
+ * @returns The calculated instance name string, or null if the token is a FactoryInjectionToken that is not yet resolved
610
805
  */
611
- delete(name: string): boolean;
806
+ calculateInstanceName(token: ClassType | InjectionToken<any, any> | BoundInjectionToken<any, any> | FactoryInjectionToken<any, any>, args?: unknown): string | null;
612
807
  /**
613
- * Gets the number of holders currently managed.
808
+ * Checks if a service is registered in the container.
614
809
  */
615
- size(): number;
810
+ isRegistered(token: any): boolean;
616
811
  /**
617
- * Checks if this manager has any holders.
812
+ * Waits for all pending operations to complete.
618
813
  */
619
- isEmpty(): boolean;
620
- }
621
- /** @deprecated Use RequestContext instead */
622
- type RequestContextHolder = RequestContext;
623
- /**
624
- * Default implementation of RequestContext.
625
- *
626
- * Extends BaseHolderManager to provide holder management functionality
627
- * with request-specific metadata and lifecycle support.
628
- */
629
- declare class DefaultRequestContext extends BaseHolderManager implements RequestContext {
630
- readonly requestId: string;
631
- readonly priority: number;
632
- readonly metadata: Map<string, any>;
633
- readonly createdAt: number;
634
- constructor(requestId: string, priority?: number, initialMetadata?: Record<string, any>);
814
+ ready(): Promise<void>;
635
815
  /**
636
- * Public getter for holders to maintain interface compatibility.
816
+ * @internal
817
+ * Attempts to get an instance synchronously if it already exists.
637
818
  */
638
- get holders(): Map<string, InstanceHolder>;
819
+ tryGetSync<T>(token: any, args?: any): T | null;
639
820
  /**
640
- * Gets a holder by name. For RequestContext, this is a simple lookup.
821
+ * @internal
822
+ * Internal method for getting instances synchronously with configurable storage.
641
823
  */
642
- get(name: string): InstanceHolder | undefined;
824
+ protected tryGetSyncFromStorage<T>(token: any, args: any, storage: UnifiedStorage, requestId?: string): T | null;
643
825
  /**
644
- * Sets a holder by name.
826
+ * Adds an instance to the container.
827
+ * Accepts class types, InjectionTokens, and BoundInjectionTokens.
828
+ * Rejects InjectionTokens with required schemas (use BoundInjectionToken instead).
829
+ *
830
+ * @param token The class type, InjectionToken, or BoundInjectionToken to register the instance for
831
+ * @param instance The instance to store
645
832
  */
646
- set(name: string, holder: InstanceHolder): void;
833
+ addInstance<T>(token: ClassType | InjectionToken<T, any> | BoundInjectionToken<T, any>, instance: T): void;
647
834
  /**
648
- * Checks if a holder exists by name.
835
+ * @internal
836
+ * Internal method for adding instances with configurable scope and storage.
649
837
  */
650
- has(name: string): boolean;
651
- addInstance(instanceName: string | InjectionToken<any, undefined>, instance: any, holder?: InstanceHolder): void;
652
- clear(): void;
653
- getMetadata(key: string): any | undefined;
654
- setMetadata(key: string, value: any): void;
838
+ protected addInstanceToStorage<T>(token: ClassType | InjectionToken<T, any> | BoundInjectionToken<T, any>, instance: T, storage: UnifiedStorage, scope: InjectableScope, requestId?: string): void;
655
839
  }
656
- /**
657
- * Creates a new request context with the given parameters.
658
- */
659
- declare function createRequestContext(requestId: string, priority?: number, initialMetadata?: Record<string, any>): RequestContext;
660
840
  //#endregion
661
841
  //#region src/container/scoped-container.d.mts
662
842
  /**
@@ -667,23 +847,20 @@ declare function createRequestContext(requestId: string, priority?: number, init
667
847
  * This design eliminates race conditions that can occur with async operations
668
848
  * when multiple requests are processed concurrently.
669
849
  */
670
- declare class ScopedContainer implements IContainer {
850
+ declare class ScopedContainer extends AbstractContainer {
671
851
  private readonly parent;
672
852
  private readonly registry;
673
853
  readonly requestId: string;
674
- private readonly requestContextHolder;
675
- private readonly holderStorage;
854
+ protected readonly defaultScope = InjectableScope.Request;
855
+ private readonly storage;
676
856
  private disposed;
677
- constructor(parent: Container, registry: Registry, requestId: string, metadata?: Record<string, any>, priority?: number);
678
- /**
679
- * Gets the request context holder for this scoped container.
680
- */
681
- getRequestContextHolder(): RequestContext;
682
- /**
683
- * Gets the holder storage for this scoped container.
684
- * Used by InstanceResolver for request-scoped resolution.
685
- */
686
- getHolderStorage(): IHolderStorage;
857
+ private readonly metadata;
858
+ constructor(parent: Container, registry: Registry, requestId: string, metadata?: Record<string, any>);
859
+ getStorage(): UnifiedStorage;
860
+ protected getRegistry(): Registry;
861
+ protected getTokenResolver(): TokenResolver;
862
+ protected getNameResolver(): NameResolver;
863
+ protected getServiceInvalidator(): ServiceInvalidator;
687
864
  /**
688
865
  * Gets the request ID for this scoped container.
689
866
  */
@@ -700,13 +877,9 @@ declare class ScopedContainer implements IContainer {
700
877
  * Sets metadata on the request context.
701
878
  */
702
879
  setMetadata(key: string, value: any): void;
703
- /**
704
- * Adds a pre-prepared instance to the request context.
705
- */
706
- addInstance(token: InjectionToken<any, undefined>, instance: any): void;
707
880
  /**
708
881
  * Gets an instance from the container.
709
- * Request-scoped services are resolved from this container's context.
882
+ * Request-scoped services are resolved from this container's storage.
710
883
  * All other services are delegated to the parent container.
711
884
  */
712
885
  get<T extends ClassType>(token: T): InstanceType<T> extends Factorable<infer R> ? Promise<R> : Promise<InstanceType<T>>;
@@ -718,352 +891,251 @@ declare class ScopedContainer implements IContainer {
718
891
  get<T>(token: FactoryInjectionToken<T, any>): Promise<T>;
719
892
  /**
720
893
  * Invalidates a service and its dependencies.
721
- * For request-scoped services, invalidation is handled within this context.
722
894
  */
723
895
  invalidate(service: unknown): Promise<void>;
724
896
  /**
725
- * Checks if a service is registered.
726
- */
727
- isRegistered(token: any): boolean;
728
- /**
729
- * Disposes this scoped container and cleans up all request-scoped instances.
730
- * This is an alias for endRequest() for IContainer compatibility.
897
+ * Disposes the container and cleans up all resources.
898
+ * Alias for endRequest().
731
899
  */
732
900
  dispose(): Promise<void>;
733
- /**
734
- * Ends the request and cleans up all request-scoped instances.
735
- * Uses the invalidation system to properly cascade to dependent singletons.
736
- */
737
- endRequest(): Promise<void>;
738
- /**
739
- * Waits for all pending operations to complete.
740
- */
741
- ready(): Promise<void>;
742
901
  /**
743
902
  * @internal
744
- * Attempts to get an instance synchronously if it already exists and is ready.
745
- * For request-scoped services, checks this container's context first.
746
- * For other services, delegates to the parent container.
747
- *
748
- * Returns null if the instance doesn't exist or is not yet ready (still creating).
903
+ * Attempts to get an instance synchronously if it already exists.
904
+ * Checks request storage first, then delegates to parent.
749
905
  */
750
906
  tryGetSync<T>(token: any, args?: any): T | null;
751
907
  /**
752
- * Checks if a token is for a request-scoped service.
908
+ * Adds an instance to the container.
909
+ * Overrides base class to check disposed state.
753
910
  */
754
- private isRequestScoped;
911
+ addInstance<T>(token: ClassType | InjectionToken<T, any> | BoundInjectionToken<T, any>, instance: T): void;
755
912
  /**
756
- * Resolves a request-scoped service from this container's context.
757
- * Uses locking to prevent duplicate initialization during concurrent resolution.
758
- */
759
- private resolveRequestScoped;
760
- /**
761
- * Stores an instance in the request context.
762
- * Called by Container during request-scoped service resolution.
763
- */
764
- storeRequestInstance(instanceName: string, instance: any, holder: InstanceHolder): void;
765
- /**
766
- * Gets an existing instance from the request context.
767
- * Called by Container during resolution to check for existing instances.
768
- */
769
- getRequestInstance(instanceName: string): InstanceHolder | undefined;
770
- /**
771
- * Generates a prefixed event name for request-scoped services.
772
- * Format: {requestId}:{instanceName}
773
- */
774
- getPrefixedEventName(instanceName: string): string;
775
- }
776
- //#endregion
777
- //#region src/internal/lifecycle/lifecycle-event-bus.d.mts
778
- /**
779
- * Event bus for service lifecycle events (create, destroy, etc.).
780
- *
781
- * Enables loose coupling between services by allowing them to subscribe
782
- * to lifecycle events of their dependencies without direct references.
783
- * Used primarily for invalidation cascading.
784
- */
785
- declare class LifecycleEventBus {
786
- private readonly logger;
787
- private listeners;
788
- constructor(logger?: Console | null);
789
- on<Event extends string | `pre:${string}` | `post:${string}`>(ns: string, event: Event, listener: (event: Event) => void): () => void;
790
- emit(key: string, event: string): Promise<PromiseSettledResult<any>[] | undefined>;
791
- }
792
- //#endregion
793
- //#region src/internal/holder/holder-manager.d.mts
794
- /**
795
- * Manages the storage and retrieval of singleton instance holders.
796
- *
797
- * Provides CRUD operations and filtering for the holder map.
798
- * Handles holder state validation (destroying, error states) on retrieval.
799
- */
800
- declare class HolderManager extends BaseHolderManager {
801
- constructor(logger?: Console | null);
802
- get(name: string): [DIError, InstanceHolder] | [DIError] | [undefined, InstanceHolder];
803
- set(name: string, holder: InstanceHolder): void;
804
- has(name: string): [DIError] | [undefined, boolean];
805
- /**
806
- * Creates a new holder with Created status and stores it.
807
- * This is useful for creating holders that already have their instance ready.
808
- * @param name The name of the instance
809
- * @param instance The actual instance to store
810
- * @param type The injectable type
811
- * @param scope The injectable scope
812
- * @param deps Optional set of dependencies
813
- * @returns The created holder
913
+ * Ends the request and cleans up all request-scoped services.
814
914
  */
815
- storeCreatedHolder<Instance>(name: string, instance: Instance, type: InjectableType, scope: InjectableScope, deps?: Set<string>): InstanceHolder<Instance>;
915
+ endRequest(): Promise<void>;
816
916
  }
817
917
  //#endregion
818
- //#region src/internal/core/invalidator.d.mts
819
- interface ClearAllOptions {
820
- /** Maximum number of invalidation rounds to prevent infinite loops (default: 10) */
821
- maxRounds?: number;
822
- /** Whether to wait for all services to settle before starting (default: true) */
823
- waitForSettlement?: boolean;
824
- }
825
- interface InvalidationOptions {
826
- /** Whether to emit events after invalidation (default: true for singletons) */
827
- emitEvents?: boolean;
828
- /** Custom event emitter function */
829
- onInvalidated?: (instanceName: string) => Promise<void>;
830
- /** Whether to cascade invalidation to dependents (default: true) */
831
- cascade?: boolean;
832
- /** Internal: tracks services being invalidated in the current call chain to prevent circular loops */
833
- _invalidating?: Set<string>;
834
- }
918
+ //#region src/internal/core/scope-tracker.d.mts
835
919
  /**
836
- * Manages graceful service cleanup with dependency-aware invalidation.
920
+ * Component for tracking and handling scope upgrades.
837
921
  *
838
- * Ensures services are destroyed in the correct order based on their dependencies.
839
- * Works with any IHolderStorage implementation, enabling unified invalidation
840
- * for both singleton and request-scoped services.
922
+ * Detects when a Singleton service needs to be upgraded to Request scope
923
+ * and coordinates the scope upgrade process atomically.
841
924
  */
842
- declare class Invalidator {
843
- private readonly eventBus;
925
+ declare class ScopeTracker {
926
+ private readonly registry;
927
+ private readonly nameResolver;
844
928
  private readonly logger;
845
- private readonly storage;
846
- constructor(manager: HolderManager, eventBus: LifecycleEventBus | null, logger?: Console | null);
847
- /**
848
- * Invalidates a service and all its dependencies.
849
- * Works with the configured storage (singleton by default).
850
- */
851
- invalidate(service: string, round?: number): Promise<any>;
929
+ constructor(registry: Registry, nameResolver: NameResolver, logger?: Console | null);
852
930
  /**
853
- * Invalidates a service using a specific storage.
854
- * This allows request-scoped invalidation using a RequestStorage.
931
+ * Checks if a dependency requires scope upgrade and performs it if needed.
932
+ * Called during service resolution when a dependency is resolved.
855
933
  *
856
- * @param service The instance name to invalidate
857
- * @param storage The storage to use for this invalidation
858
- * @param round Current invalidation round (for recursion limiting)
859
- * @param options Additional options for invalidation behavior
860
- */
861
- invalidateWithStorage(service: string, storage: IHolderStorage, round?: number, options?: InvalidationOptions): Promise<void>;
862
- /**
863
- * Gracefully clears all services using invalidation logic.
864
- * This method respects service dependencies and ensures proper cleanup order.
865
- * Services that depend on others will be invalidated first, then their dependencies.
866
- */
867
- clearAll(options?: ClearAllOptions): Promise<void>;
868
- /**
869
- * Gracefully clears all services in a specific storage.
870
- * This allows clearing request-scoped services using a RequestStorage.
871
- */
872
- clearAllWithStorage(storage: IHolderStorage, options?: ClearAllOptions): Promise<void>;
873
- /**
874
- * Waits for all services to settle (either created, destroyed, or error state).
875
- */
876
- ready(): Promise<void>;
877
- /**
878
- * Waits for all services in a specific storage to settle.
879
- */
880
- readyWithStorage(storage: IHolderStorage): Promise<void>;
881
- /**
882
- * Invalidates a single holder using a specific storage.
883
- */
884
- private invalidateHolderWithStorage;
885
- /**
886
- * Common invalidation logic for holders based on their status.
887
- */
888
- private invalidateHolderByStatus;
889
- /**
890
- * Destroys a holder using a specific storage.
934
+ * @param currentServiceName - Name of the service being created
935
+ * @param currentServiceScope - Current scope of the service being created
936
+ * @param dependencyName - Name of the dependency being resolved
937
+ * @param dependencyScope - Scope of the dependency
938
+ * @param dependencyToken - Token of the dependency
939
+ * @param singletonStorage - Singleton storage instance
940
+ * @param requestStorage - Request storage instance (if in request context)
941
+ * @param requestId - Request ID (if in request context)
942
+ * @returns [needsUpgrade: boolean, newName?: string] - whether upgrade occurred and new name
943
+ */
944
+ checkAndUpgradeScope(currentServiceName: string, currentServiceScope: InjectableScope, dependencyName: string, dependencyScope: InjectableScope, dependencyToken: InjectionToken<any, any>, singletonStorage: IHolderStorage, requestStorage?: IHolderStorage, requestId?: string): [boolean, string?];
945
+ /**
946
+ * Performs the actual scope upgrade from Singleton to Request.
947
+ * This is the core migration logic.
948
+ *
949
+ * @param serviceName - Current service name (without requestId)
950
+ * @param token - Service injection token
951
+ * @param singletonStorage - Source storage
952
+ * @param requestStorage - Target storage
953
+ * @param requestId - Request ID to include in new name
954
+ * @returns [success: boolean, newName?: string, error?: DIError]
891
955
  */
892
- private destroyHolderWithStorage;
956
+ upgradeScopeToRequest(serviceName: string, token: InjectionToken<any, any>, singletonStorage: IHolderStorage, requestStorage: IHolderStorage, requestId: string): Promise<[boolean, string?, DIError?]>;
893
957
  /**
894
- * Waits for a holder to settle (either created, destroyed, or error state).
958
+ * Synchronous part of scope upgrade - handles immediate updates.
959
+ * Async operations (like waiting for holder creation) should be done separately.
895
960
  */
896
- private waitForHolderToSettle;
961
+ private upgradeScopeToRequestSync;
897
962
  /**
898
- * Clears services with dependency awareness for a specific storage.
963
+ * Updates all parent dependencies to reference the new service name.
964
+ *
965
+ * @param oldName - Original service name
966
+ * @param newName - New service name with requestId
967
+ * @param singletonStorage - Singleton storage to check
968
+ * @param requestStorage - Request storage to check
899
969
  */
900
- private clearServicesWithDependencyAwarenessForStorage;
970
+ updateParentDependencies(oldName: string, newName: string, singletonStorage: IHolderStorage, requestStorage?: IHolderStorage): void;
971
+ }
972
+ //#endregion
973
+ //#region src/internal/core/service-initializer.d.mts
974
+ /**
975
+ * Creates service instances from registry records.
976
+ *
977
+ * Handles both class-based (@Injectable) and factory-based (@Factory) services,
978
+ * managing the instantiation lifecycle including lifecycle hook invocation.
979
+ */
980
+ declare class ServiceInitializer {
981
+ private readonly injectors;
982
+ constructor(injectors: Injectors);
901
983
  /**
902
- * Finds services that are ready to be cleared in the current round.
903
- * A service is ready if all its dependencies have already been cleared.
984
+ * Instantiates a service based on its registry record.
985
+ * @param ctx The factory context for dependency injection
986
+ * @param record The factory record from the registry
987
+ * @param args Optional arguments for the service
988
+ * @returns Promise resolving to [undefined, instance] or [error]
904
989
  */
905
- private findServicesReadyForClearingInStorage;
990
+ instantiateService<T>(ctx: ServiceInitializationContext, record: FactoryRecord<T, any>, args?: any): Promise<[undefined, T] | [DIError]>;
906
991
  /**
907
- * Force clears services that couldn't be cleared through normal dependency resolution.
908
- * This handles edge cases like circular dependencies.
992
+ * Instantiates a class-based service (Injectable decorator).
993
+ * @param ctx The factory context for dependency injection
994
+ * @param record The factory record from the registry
995
+ * @param args Optional arguments for the service constructor
996
+ * @returns Promise resolving to [undefined, instance] or [error]
909
997
  */
910
- private forceClearServicesInStorage;
998
+ private instantiateClass;
911
999
  /**
912
- * Emits events to listeners for instance lifecycle events.
1000
+ * Instantiates a factory-based service (Factory decorator).
1001
+ * @param ctx The factory context for dependency injection
1002
+ * @param record The factory record from the registry
1003
+ * @param args Optional arguments for the factory
1004
+ * @returns Promise resolving to [undefined, instance] or [error]
913
1005
  */
914
- private emitInstanceEvent;
1006
+ private instantiateFactory;
915
1007
  }
916
1008
  //#endregion
917
- //#region src/internal/core/token-processor.d.mts
1009
+ //#region src/internal/core/instance-resolver.d.mts
918
1010
  /**
919
- * Handles token validation, normalization, and instance name generation.
1011
+ * Resolves instances from tokens, handling caching, creation, and scope rules.
920
1012
  *
921
- * Provides utilities for resolving tokens to their underlying InjectionToken,
922
- * validating arguments against schemas, and generating unique instance identifiers.
1013
+ * Uses unified storage for both singleton and request-scoped services.
1014
+ * Coordinates with ServiceInitializer for actual service creation.
1015
+ * Integrates ScopeTracker for automatic scope upgrades.
923
1016
  */
924
- declare class TokenProcessor {
1017
+ declare class InstanceResolver {
1018
+ private readonly registry;
1019
+ private readonly storage;
1020
+ private readonly serviceInitializer;
1021
+ private readonly tokenResolver;
1022
+ private readonly nameResolver;
1023
+ private readonly scopeTracker;
1024
+ private readonly serviceInvalidator;
1025
+ private readonly eventBus;
925
1026
  private readonly logger;
926
- constructor(logger?: Console | null);
1027
+ constructor(registry: Registry, storage: IHolderStorage, serviceInitializer: ServiceInitializer, tokenResolver: TokenResolver, nameResolver: NameResolver, scopeTracker: ScopeTracker, serviceInvalidator: ServiceInvalidator, eventBus: LifecycleEventBus, logger?: Console | null);
927
1028
  /**
928
- * Normalizes a token to an InjectionToken.
929
- * Handles class constructors by getting their injectable token.
1029
+ * Resolves an instance for the given token and arguments.
1030
+ * This method is used for singleton and transient services.
930
1031
  *
931
- * @param token A class constructor, InjectionToken, BoundInjectionToken, or FactoryInjectionToken
932
- * @returns The normalized InjectionTokenType
1032
+ * @param token The injection token
1033
+ * @param args Optional arguments
1034
+ * @param contextContainer The container to use for creating context
1035
+ * @param requestStorage Optional request storage (for scope upgrades)
1036
+ * @param requestId Optional request ID (for scope upgrades)
933
1037
  */
934
- normalizeToken(token: AnyInjectableType): InjectionTokenType;
1038
+ resolveInstance(token: AnyInjectableType, args: any, contextContainer: IContainer, requestStorage?: IHolderStorage, requestId?: string): Promise<[undefined, any] | [DIError]>;
935
1039
  /**
936
- * Gets the underlying "real" token from wrapped tokens.
937
- * For BoundInjectionToken and FactoryInjectionToken, returns the wrapped token.
938
- * For other tokens, returns the token itself.
1040
+ * Resolves a request-scoped instance for a ScopedContainer.
1041
+ * The service will be stored in the ScopedContainer's request storage.
939
1042
  *
940
- * @param token The token to unwrap
941
- * @returns The underlying InjectionToken
1043
+ * @param token The injection token
1044
+ * @param args Optional arguments
1045
+ * @param scopedContainer The ScopedContainer that owns the request context
942
1046
  */
943
- getRealToken<T = unknown>(token: InjectionTokenType): InjectionToken<T>;
1047
+ resolveRequestScopedInstance(token: AnyInjectableType, args: any, scopedContainer: ScopedContainer): Promise<[undefined, any] | [DIError]>;
944
1048
  /**
945
- * Convenience method that normalizes a token and then gets the real token.
946
- * Useful for checking registry entries where you need the actual registered token.
1049
+ * Unified resolution method that works with any IHolderStorage.
1050
+ * This eliminates duplication between singleton and request-scoped resolution.
947
1051
  *
948
- * @param token Any injectable type
949
- * @returns The underlying InjectionToken
1052
+ * IMPORTANT: The check-and-store logic is carefully designed to avoid race conditions.
1053
+ * The storage check and holder creation must happen synchronously (no awaits between).
1054
+ *
1055
+ * @param token The injection token
1056
+ * @param args Optional arguments
1057
+ * @param contextContainer The container for context
1058
+ * @param storage The storage strategy to use
1059
+ * @param scopedContainer Optional scoped container for request-scoped services
1060
+ * @param requestStorage Optional request storage (for scope upgrades)
1061
+ * @param requestId Optional request ID (for scope upgrades)
950
1062
  */
951
- getRegistryToken<T = unknown>(token: AnyInjectableType): InjectionToken<T>;
1063
+ private resolveWithStorage;
952
1064
  /**
953
- * Validates and resolves token arguments, handling factory token resolution and validation.
1065
+ * Internal method to resolve token args and create instance name.
1066
+ * Handles factory token resolution and validation.
954
1067
  */
955
- validateAndResolveTokenArgs(token: AnyInjectableType, args?: any): [DIError | undefined, {
956
- actualToken: InjectionTokenType;
957
- validatedArgs?: any;
958
- }];
1068
+ private resolveTokenAndPrepareInstanceName;
959
1069
  /**
960
- * Generates a unique instance name based on token and arguments.
1070
+ * Handles storage error states (destroying, error, etc.).
1071
+ * Returns a result if handled, null if should proceed with creation.
961
1072
  */
962
- generateInstanceName(token: InjectionTokenType, args: any): string;
1073
+ private handleStorageError;
963
1074
  /**
964
- * Formats a single argument value for instance name generation.
1075
+ * Creates a new instance and stores it using the provided storage strategy.
1076
+ * This unified method replaces instantiateServiceFromRegistry and createRequestScopedInstance.
1077
+ *
1078
+ * For transient services, the instance is created but not stored (no caching).
965
1079
  */
966
- formatArgValue(value: any): string;
1080
+ private createAndStoreInstance;
967
1081
  /**
968
- * Creates a factory context for dependency injection during service instantiation.
969
- * @param container The container instance (Container or ScopedContainer) for dependency resolution
970
- * @param onDependencyResolved Callback when a dependency is resolved, receives the instance name
1082
+ * Creates a transient instance without storage or locking.
1083
+ * Each call creates a new instance.
971
1084
  */
972
- createFactoryContext(container: IContainer, onDependencyResolved?: (instanceName: string) => void): FactoryContext & {
973
- getDestroyListeners: () => (() => void)[];
974
- deps: Set<string>;
975
- };
976
- }
977
- //#endregion
978
- //#region src/internal/core/service-locator.d.mts
979
- /**
980
- * Core DI engine that coordinates service instantiation, resolution, and lifecycle.
981
- *
982
- * Acts as the central orchestrator for dependency injection operations,
983
- * delegating to specialized components (InstanceResolver, Instantiator, Invalidator)
984
- * for specific tasks.
985
- */
986
- declare class ServiceLocator {
987
- private readonly registry;
988
- private readonly logger;
989
- private readonly injectors;
990
- private readonly eventBus;
991
- private readonly manager;
992
- private readonly instantiator;
993
- private readonly tokenProcessor;
994
- private readonly invalidator;
995
- private readonly instanceResolver;
996
- constructor(registry?: Registry, logger?: Console | null, injectors?: Injectors);
997
- getEventBus(): LifecycleEventBus;
998
- getManager(): HolderManager;
999
- getInvalidator(): Invalidator;
1000
- getTokenProcessor(): TokenProcessor;
1001
- getInstanceIdentifier(token: AnyInjectableType, args?: any): string;
1085
+ private createTransientInstance;
1002
1086
  /**
1003
- * Gets or creates an instance for the given token.
1004
- * @param token The injection token
1005
- * @param args Optional arguments
1006
- * @param contextContainer The container to use for creating FactoryContext
1087
+ * Handles successful service instantiation.
1007
1088
  */
1008
- getInstance(token: AnyInjectableType, args: any, contextContainer: IContainer): Promise<any[]>;
1089
+ private handleInstantiationSuccess;
1009
1090
  /**
1010
- * Gets or throws an instance for the given token.
1011
- * @param token The injection token
1012
- * @param args Optional arguments
1013
- * @param contextContainer The container to use for creating FactoryContext
1091
+ * Handles service instantiation errors.
1014
1092
  */
1015
- getOrThrowInstance<Instance>(token: AnyInjectableType, args: any, contextContainer: IContainer): Promise<Instance>;
1093
+ private handleInstantiationError;
1016
1094
  /**
1017
- * Resolves a request-scoped service for a ScopedContainer.
1018
- * The service will be stored in the ScopedContainer's request context.
1019
- *
1020
- * @param token The injection token
1021
- * @param args Optional arguments
1022
- * @param scopedContainer The ScopedContainer that owns the request context
1095
+ * Handles instantiation result (success or error).
1023
1096
  */
1024
- resolveRequestScoped(token: AnyInjectableType, args: any, scopedContainer: ScopedContainer): Promise<any>;
1025
- getSyncInstance<Instance, Schema extends InjectionTokenSchemaType | undefined>(token: AnyInjectableType, args: Schema extends ZodObject ? z.input<Schema> : Schema extends ZodOptional<ZodObject> ? z.input<Schema> | undefined : undefined, contextContainer: IContainer): Instance | null;
1026
- invalidate(service: string, round?: number): Promise<any>;
1097
+ private handleInstantiationResult;
1027
1098
  /**
1028
- * Gracefully clears all services in the ServiceLocator using invalidation logic.
1029
- * This method respects service dependencies and ensures proper cleanup order.
1030
- * Services that depend on others will be invalidated first, then their dependencies.
1099
+ * Waits for an instance holder to be ready and returns the appropriate result.
1031
1100
  *
1032
- * @param options Optional configuration for the clearing process
1033
- * @returns Promise that resolves when all services have been cleared
1034
- */
1035
- clearAll(options?: ClearAllOptions): Promise<void>;
1036
- /**
1037
- * Waits for all services to settle (either created, destroyed, or error state).
1101
+ * @param holder The holder to wait for
1102
+ * @param waiterHolder Optional holder that is doing the waiting (for circular dependency detection)
1103
+ * @param getHolder Optional function to retrieve holders by name (required if waiterHolder is provided)
1038
1104
  */
1039
- ready(): Promise<void>;
1105
+ private waitForInstanceReady;
1040
1106
  /**
1041
- * Helper method for InstanceResolver to generate instance names.
1042
- * This is needed for the factory context creation.
1107
+ * Creates a ServiceInitializationContext for service instantiation.
1043
1108
  */
1044
- generateInstanceName(token: any, args: any): string;
1109
+ private createServiceInitializationContext;
1045
1110
  }
1046
1111
  //#endregion
1047
1112
  //#region src/container/container.d.mts
1048
1113
  /**
1049
1114
  * Main dependency injection container.
1050
1115
  *
1051
- * Provides a simplified public API for dependency injection, wrapping
1052
- * a ServiceLocator instance. Handles singleton and transient services directly,
1116
+ * Provides a simplified public API for dependency injection.
1117
+ * Handles singleton and transient services directly,
1053
1118
  * while request-scoped services require using beginRequest() to create a ScopedContainer.
1054
1119
  */
1055
- declare class Container implements IContainer {
1120
+ declare class Container extends AbstractContainer {
1056
1121
  protected readonly registry: Registry;
1057
1122
  protected readonly logger: Console | null;
1058
1123
  protected readonly injectors: Injectors;
1059
- private readonly serviceLocator;
1124
+ protected readonly defaultScope = InjectableScope.Singleton;
1125
+ protected readonly requestId: undefined;
1126
+ private readonly storage;
1127
+ private readonly serviceInitializer;
1128
+ private readonly serviceInvalidator;
1129
+ private readonly tokenResolver;
1130
+ private readonly nameResolver;
1131
+ private readonly scopeTracker;
1132
+ private readonly eventBus;
1133
+ private readonly instanceResolver;
1060
1134
  private readonly activeRequestIds;
1061
1135
  constructor(registry?: Registry, logger?: Console | null, injectors?: Injectors);
1062
1136
  private registerSelf;
1063
1137
  /**
1064
1138
  * Gets an instance from the container.
1065
- * This method has the same type signature as the inject method from get-injectors.mts
1066
- *
1067
1139
  * NOTE: Request-scoped services cannot be resolved directly from Container.
1068
1140
  * Use beginRequest() to create a ScopedContainer for request-scoped services.
1069
1141
  */
@@ -1075,87 +1147,46 @@ declare class Container implements IContainer {
1075
1147
  get<T>(token: BoundInjectionToken<T, any>): Promise<T>;
1076
1148
  get<T>(token: FactoryInjectionToken<T, any>): Promise<T>;
1077
1149
  /**
1078
- * Gets an instance with a specific container context.
1079
- * Used by ScopedContainer to delegate singleton/transient resolution
1080
- * while maintaining the correct container context for nested inject() calls.
1081
- *
1082
- * @internal
1083
- */
1084
- getWithContext(token: ClassType | InjectionToken<any> | BoundInjectionToken<any, any> | FactoryInjectionToken<any, any>, args: unknown, contextContainer: IContainer): Promise<any>;
1085
- /**
1086
- * Resolves a request-scoped service for a ScopedContainer.
1087
- * The service will be stored in the ScopedContainer's request context.
1088
- *
1089
- * @internal
1090
- */
1091
- resolveForRequest(token: ClassType | InjectionToken<any> | BoundInjectionToken<any, any> | FactoryInjectionToken<any, any>, args: unknown, scopedContainer: ScopedContainer): Promise<any>;
1092
- /**
1093
- * Gets the underlying ServiceLocator instance for advanced usage
1094
- */
1095
- getServiceLocator(): ServiceLocator;
1096
- /**
1097
- * Gets the registry
1098
- */
1099
- getRegistry(): Registry;
1100
- /**
1101
- * Invalidates a service and its dependencies
1150
+ * Invalidates a service and its dependencies.
1102
1151
  */
1103
1152
  invalidate(service: unknown): Promise<void>;
1104
1153
  /**
1105
- * Gets a service holder by instance (reverse lookup)
1106
- */
1107
- private getHolderByInstance;
1108
- /**
1109
- * Checks if a service is registered in the container
1110
- */
1111
- isRegistered(token: any): boolean;
1112
- /**
1113
- * Disposes the container and cleans up all resources
1154
+ * Disposes the container and cleans up all resources.
1114
1155
  */
1115
1156
  dispose(): Promise<void>;
1116
- /**
1117
- * Waits for all pending operations to complete
1118
- */
1119
- ready(): Promise<void>;
1120
1157
  /**
1121
1158
  * @internal
1122
1159
  * Attempts to get an instance synchronously if it already exists.
1123
- * Returns null if the instance doesn't exist or is not ready.
1160
+ * Overrides base class to support requestId parameter for ScopedContainer compatibility.
1124
1161
  */
1125
- tryGetSync<T>(token: any, args?: any): T | null;
1162
+ tryGetSync<T>(token: any, args?: any, requestId?: string): T | null;
1126
1163
  /**
1127
1164
  * Begins a new request context and returns a ScopedContainer.
1128
- *
1129
- * The ScopedContainer provides isolated request-scoped service resolution
1130
- * while delegating singleton and transient services to this Container.
1131
- *
1132
- * @param requestId Unique identifier for this request
1133
- * @param metadata Optional metadata for the request
1134
- * @param priority Priority for resolution (higher = more priority)
1135
- * @returns A ScopedContainer for this request
1136
1165
  */
1137
- beginRequest(requestId: string, metadata?: Record<string, any>, priority?: number): ScopedContainer;
1166
+ beginRequest(requestId: string, metadata?: Record<string, any>): ScopedContainer;
1138
1167
  /**
1139
- * Removes a request ID from the active set.
1140
- * Called by ScopedContainer when the request ends.
1141
- *
1142
- * @internal
1143
- */
1144
- removeActiveRequest(requestId: string): void;
1145
- /**
1146
- * Gets the set of active request IDs.
1168
+ * Gets all active request IDs.
1147
1169
  */
1148
1170
  getActiveRequestIds(): ReadonlySet<string>;
1149
1171
  /**
1150
- * Checks if a request ID is currently active.
1172
+ * Checks if a request is active.
1151
1173
  */
1152
1174
  hasActiveRequest(requestId: string): boolean;
1153
1175
  /**
1154
- * Clears all instances and bindings from the container.
1155
- * This is useful for testing or resetting the container state.
1176
+ * Removes a request ID from active requests.
1177
+ * Called by ScopedContainer when request ends.
1156
1178
  */
1157
- clear(): Promise<void>;
1179
+ removeRequestId(requestId: string): void;
1180
+ getStorage(): UnifiedStorage;
1181
+ getServiceInitializer(): ServiceInitializer;
1182
+ getServiceInvalidator(): ServiceInvalidator;
1183
+ getTokenResolver(): TokenResolver;
1184
+ getNameResolver(): NameResolver;
1185
+ getScopeTracker(): ScopeTracker;
1186
+ getEventBus(): LifecycleEventBus;
1187
+ getRegistry(): Registry;
1188
+ getInstanceResolver(): InstanceResolver;
1158
1189
  }
1159
1190
  //#endregion
1160
- export { InjectRequest as $, InjectableScope as A, ClassTypeWithoutArguments as B, InstanceStatus as C, Registry as D, FactoryRecord as E, ClassTypeWithArgument as F, OptionalInjectionTokenSchemaType as G, InjectionToken as H, ClassTypeWithInstance as I, Injectors as J, FactoryContext as K, ClassTypeWithInstanceAndArgument as L, BaseInjectionTokenSchemaType as M, BoundInjectionToken as N, globalRegistry as O, ClassType as P, FactorableWithArgs as Q, ClassTypeWithInstanceAndOptionalArgument as R, InstanceHolderError as S, DIErrorCode as T, InjectionTokenSchemaType as U, FactoryInjectionToken as V, InjectionTokenType as W, IContainer as X, getInjectors as Y, Factorable as Z, InstanceEffect as _, HolderManager as a, UnionToIntersection as at, InstanceHolderCreating as b, DefaultRequestContext as c, createRequestContext as d, InjectState as et, BaseHolderManager as f, InstanceDestroyListener as g, IHolderStorage as h, Invalidator as i, UnionToArray as it, AnyInjectableType as j, InjectableType as k, RequestContext as l, HolderGetResult as m, ServiceLocator as n, Join as nt, LifecycleEventBus as o, UnionToOvlds as ot, HolderReadyResult as p, getInjectableToken as q, TokenProcessor as r, PopUnion as rt, ScopedContainer as s, Container as t, IsUnion as tt, RequestContextHolder as u, InstanceHolder as v, DIError as w, InstanceHolderDestroying as x, InstanceHolderCreated as y, ClassTypeWithOptionalArgument as z };
1161
- //# sourceMappingURL=container-BuAutHGg.d.mts.map
1191
+ export { ClassTypeWithoutArguments as $, Injectors as A, PopUnion as B, NameResolver as C, Factorable as D, globalRegistry as E, IContainer as F, BaseInjectionTokenSchemaType as G, UnionToIntersection as H, InjectRequest as I, ClassTypeWithArgument as J, BoundInjectionToken as K, InjectState as L, ServiceInitializationContext as M, InjectableType as N, FactorableWithArgs as O, InjectableScope as P, ClassTypeWithOptionalArgument as Q, IsUnion as R, DIErrorCode as S, Registry as T, UnionToOvlds as U, UnionToArray as V, AnyInjectableType as W, ClassTypeWithInstanceAndArgument as X, ClassTypeWithInstance as Y, ClassTypeWithInstanceAndOptionalArgument as Z, InstanceHolderCreating as _, ScopedContainer as a, InstanceStatus as b, ClearAllOptions as c, LifecycleEventBus as d, FactoryInjectionToken as et, HolderGetResult as f, InstanceHolderCreated as g, InstanceHolder as h, ScopeTracker as i, OptionalInjectionTokenSchemaType as it, getInjectors as j, FactoryContext as k, InvalidationOptions as l, InstanceDestroyListener as m, InstanceResolver as n, InjectionTokenSchemaType as nt, UnifiedStorage as o, IHolderStorage as p, ClassType as q, ServiceInitializer as r, InjectionTokenType as rt, TokenResolver as s, Container as t, InjectionToken as tt, ServiceInvalidator as u, InstanceHolderDestroying as v, FactoryRecord as w, DIError as x, InstanceHolderError as y, Join as z };
1192
+ //# sourceMappingURL=container-CNiqesCL.d.mts.map