@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
@@ -0,0 +1 @@
1
+ {"version":3,"file":"service-invalidator.mjs","names":["InstanceStatus","ServiceInvalidator","eventBus","logger","invalidateWithStorage","service","storage","options","emitEvents","onInvalidated","log","result","get","holder","invalidateHolderWithStorage","setupDependencySubscriptions","serviceName","dependencies","dependencyName","unsubscribe","on","catch","error","destroyListeners","push","clearAllWithStorage","waitForSettlement","readyWithStorage","allServiceNames","getAllNames","length","join","clearPromises","map","Promise","all","holders","forEach","_","waitForHolderToSettle","key","invalidateHolderByStatus","context","onDestroy","destroyHolderWithStorage","status","Destroying","destroyPromise","Creating","creationPromise","listener","then","deps","clear","delete","emitInstanceEvent","Created","Error","name","event","resolve","emit"],"sources":["../../../../src/internal/core/service-invalidator.mts"],"sourcesContent":["import type { IHolderStorage } from '../holder/holder-storage.interface.mjs'\nimport type { InstanceHolder } from '../holder/instance-holder.mjs'\nimport type { LifecycleEventBus } from '../lifecycle/lifecycle-event-bus.mjs'\n\nimport { InstanceStatus } from '../holder/instance-holder.mjs'\n\nexport interface ClearAllOptions {\n /** Whether to wait for all services to settle before starting (default: true) */\n waitForSettlement?: boolean\n}\n\nexport interface InvalidationOptions {\n /** Whether to emit events after invalidation (default: true) */\n emitEvents?: boolean\n /** Custom event emitter function */\n onInvalidated?: (instanceName: string) => Promise<void>\n /** Whether to cascade invalidation to dependents (default: false - events handle it) */\n cascade?: boolean\n}\n\n/**\n * Manages graceful service cleanup with event-based invalidation.\n *\n * Uses event subscriptions instead of manual dependent finding.\n * When a service is created, it subscribes to destroy events of its dependencies.\n * When a dependency is destroyed, the event automatically invalidates dependents.\n */\nexport class ServiceInvalidator {\n constructor(\n private readonly eventBus: LifecycleEventBus | null,\n private readonly logger: Console | null = null,\n ) {}\n\n /**\n * Invalidates a service using a specific storage.\n * Event-based invalidation means dependents are automatically invalidated\n * via destroy event subscriptions - no need to manually find dependents.\n *\n * @param service The instance name to invalidate\n * @param storage The storage to use for this invalidation\n * @param options Additional options for invalidation behavior\n */\n async invalidateWithStorage(\n service: string,\n storage: IHolderStorage,\n options: InvalidationOptions = {},\n ): Promise<void> {\n const { emitEvents = true, onInvalidated } = options\n\n this.logger?.log(\n `[ServiceInvalidator] Starting invalidation process for ${service}`,\n )\n\n const result = storage.get(service)\n if (result === null) {\n return\n }\n\n const [, holder] = result\n if (holder) {\n await this.invalidateHolderWithStorage(\n service,\n holder,\n storage,\n emitEvents,\n onInvalidated,\n )\n }\n }\n\n /**\n * Sets up destroy event subscriptions for a service's dependencies.\n * Called when a service is successfully instantiated.\n *\n * @param serviceName The name of the service\n * @param dependencies The set of dependency names\n * @param storage The storage to use for invalidation\n * @param holder The holder for the service (to add unsubscribe to destroy listeners)\n */\n setupDependencySubscriptions(\n serviceName: string,\n dependencies: Set<string>,\n storage: IHolderStorage,\n holder: InstanceHolder,\n ): void {\n if (!this.eventBus) {\n return\n }\n\n for (const dependencyName of dependencies) {\n // Subscribe to the dependency's destroy event\n const unsubscribe = this.eventBus.on(dependencyName, 'destroy', () => {\n this.logger?.log(\n `[ServiceInvalidator] Dependency ${dependencyName} destroyed, invalidating ${serviceName}`,\n )\n // Automatically invalidate this service when dependency is destroyed\n this.invalidateWithStorage(serviceName, storage).catch((error) => {\n this.logger?.error(\n `[ServiceInvalidator] Error invalidating ${serviceName} after dependency ${dependencyName} destroyed:`,\n error,\n )\n })\n })\n\n // Store unsubscribe function in the service's destroy listeners\n // so it's cleaned up when the service is destroyed\n holder.destroyListeners.push(unsubscribe)\n }\n }\n\n /**\n * Gracefully clears all services in a specific storage.\n * This allows clearing request-scoped services using a RequestStorage.\n */\n async clearAllWithStorage(\n storage: IHolderStorage,\n options: ClearAllOptions = {},\n ): Promise<void> {\n const { waitForSettlement = true } = options\n\n this.logger?.log(\n '[ServiceInvalidator] Starting graceful clearing of all services',\n )\n\n // Wait for all services to settle if requested\n if (waitForSettlement) {\n this.logger?.log(\n '[ServiceInvalidator] Waiting for all services to settle...',\n )\n await this.readyWithStorage(storage)\n }\n\n // Get all service names that need to be cleared\n const allServiceNames = storage.getAllNames()\n\n if (allServiceNames.length === 0) {\n this.logger?.log('[ServiceInvalidator] No services to clear')\n } else {\n this.logger?.log(\n `[ServiceInvalidator] Found ${allServiceNames.length} services to clear: ${allServiceNames.join(', ')}`,\n )\n\n // Clear services - events will handle dependent invalidation\n const clearPromises = allServiceNames.map((serviceName) =>\n this.invalidateWithStorage(serviceName, storage),\n )\n\n await Promise.all(clearPromises)\n }\n\n this.logger?.log('[ServiceInvalidator] Graceful clearing completed')\n }\n\n /**\n * Waits for all services in a specific storage to settle.\n */\n async readyWithStorage(storage: IHolderStorage): Promise<void> {\n const holders: InstanceHolder<any>[] = []\n storage.forEach((_: string, holder: InstanceHolder) => holders.push(holder))\n await Promise.all(\n holders.map((holder) => this.waitForHolderToSettle(holder)),\n )\n }\n\n // ============================================================================\n // INTERNAL INVALIDATION HELPERS\n // ============================================================================\n\n /**\n * Invalidates a single holder using a specific storage.\n */\n private async invalidateHolderWithStorage(\n key: string,\n holder: InstanceHolder<any>,\n storage: IHolderStorage,\n emitEvents: boolean,\n onInvalidated?: (instanceName: string) => Promise<void>,\n ): Promise<void> {\n await this.invalidateHolderByStatus(holder, {\n context: key,\n onDestroy: () =>\n this.destroyHolderWithStorage(\n key,\n holder,\n storage,\n emitEvents,\n onInvalidated,\n ),\n })\n }\n\n /**\n * Common invalidation logic for holders based on their status.\n */\n private async invalidateHolderByStatus(\n holder: InstanceHolder<any>,\n options: {\n context: string\n onDestroy: () => Promise<void>\n },\n ): Promise<void> {\n switch (holder.status) {\n case InstanceStatus.Destroying:\n await holder.destroyPromise\n break\n\n case InstanceStatus.Creating:\n // Wait for creation to complete before destroying\n await holder.creationPromise\n await options.onDestroy()\n break\n\n default:\n await options.onDestroy()\n break\n }\n }\n\n /**\n * Destroys a holder using a specific storage.\n */\n private async destroyHolderWithStorage(\n key: string,\n holder: InstanceHolder<any>,\n storage: IHolderStorage,\n emitEvents: boolean,\n onInvalidated?: (instanceName: string) => Promise<void>,\n ): Promise<void> {\n holder.status = InstanceStatus.Destroying\n this.logger?.log(\n `[ServiceInvalidator] Invalidating ${key} and notifying listeners`,\n )\n\n holder.destroyPromise = Promise.all(\n holder.destroyListeners.map((listener) => listener()),\n ).then(async () => {\n holder.destroyListeners = []\n holder.deps.clear()\n storage.delete(key)\n\n // Emit events if enabled and event bus exists\n if (emitEvents && this.eventBus) {\n await this.emitInstanceEvent(key, 'destroy')\n }\n\n // Call custom callback if provided\n if (onInvalidated) {\n await onInvalidated(key)\n }\n })\n\n await holder.destroyPromise\n }\n\n /**\n * Waits for a holder to settle (either created, destroyed, or error state).\n */\n private async waitForHolderToSettle(\n holder: InstanceHolder<any>,\n ): Promise<void> {\n switch (holder.status) {\n case InstanceStatus.Creating:\n await holder.creationPromise\n break\n case InstanceStatus.Destroying:\n await holder.destroyPromise\n break\n // Already settled states\n case InstanceStatus.Created:\n case InstanceStatus.Error:\n break\n }\n }\n\n /**\n * Emits events to listeners for instance lifecycle events.\n */\n private emitInstanceEvent(\n name: string,\n event: 'create' | 'destroy' = 'create',\n ) {\n if (!this.eventBus) {\n return Promise.resolve()\n }\n this.logger?.log(\n `[ServiceInvalidator]#emitInstanceEvent() Notifying listeners for ${name} with event ${event}`,\n )\n return this.eventBus.emit(name, event)\n }\n}\n"],"mappings":"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"}
@@ -0,0 +1,54 @@
1
+ import { AnyInjectableType, InjectionToken, InjectionTokenType } from "../../token/injection-token.mjs";
2
+ import { DIError } from "../../errors/di-error.mjs";
3
+
4
+ //#region src/internal/core/token-resolver.d.mts
5
+
6
+ /**
7
+ * Handles token validation and resolution.
8
+ *
9
+ * Focuses on token validation, normalization, and argument validation.
10
+ * Name generation is handled by NameResolver.
11
+ */
12
+ declare class TokenResolver {
13
+ private readonly logger;
14
+ constructor(logger?: Console | null);
15
+ /**
16
+ * Normalizes a token to an InjectionToken.
17
+ * Handles class constructors by getting their injectable token.
18
+ *
19
+ * @param token A class constructor, InjectionToken, BoundInjectionToken, or FactoryInjectionToken
20
+ * @returns The normalized InjectionTokenType
21
+ */
22
+ normalizeToken(token: AnyInjectableType): InjectionTokenType;
23
+ /**
24
+ * Gets the underlying "real" token from wrapped tokens.
25
+ * For BoundInjectionToken and FactoryInjectionToken, returns the wrapped token.
26
+ * For other tokens, returns the token itself.
27
+ *
28
+ * @param token The token to unwrap
29
+ * @returns The underlying InjectionToken
30
+ */
31
+ getRealToken<T = unknown>(token: InjectionTokenType): InjectionToken<T>;
32
+ /**
33
+ * Convenience method that normalizes a token and then gets the real token.
34
+ * Useful for checking registry entries where you need the actual registered token.
35
+ *
36
+ * @param token Any injectable type
37
+ * @returns The underlying InjectionToken
38
+ */
39
+ getRegistryToken<T = unknown>(token: AnyInjectableType): InjectionToken<T>;
40
+ /**
41
+ * Validates and resolves token arguments, handling factory token resolution and validation.
42
+ *
43
+ * @param token The token to validate
44
+ * @param args Optional arguments
45
+ * @returns [error, { actualToken, validatedArgs }]
46
+ */
47
+ validateAndResolveTokenArgs(token: AnyInjectableType, args?: any): [DIError | undefined, {
48
+ actualToken: InjectionTokenType;
49
+ validatedArgs?: any;
50
+ }];
51
+ }
52
+ //#endregion
53
+ export { TokenResolver };
54
+ //# sourceMappingURL=token-resolver.d.mts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"token-resolver.d.mts","names":[],"sources":["../../../../src/internal/core/token-resolver.mts"],"sourcesContent":[],"mappings":";;;;;;AAmBA;;;;;AA6BuE,cA7B1D,aAAA,CA6B0D;EAAf,iBAAA,MAAA;EAiBjB,WAAA,CAAA,MAAA,CAAA,EA7CA,OA6CA,GAAA,IAAA;EAAmC;;;;;;;wBAhClD,oBAAoB;;;;;;;;;mCAeT,qBAAqB,eAAe;;;;;;;;uCAiBhC,oBAAoB,eAAe;;;;;;;;qCAgB/D,iCAGP;iBACe"}
@@ -0,0 +1,77 @@
1
+ import { BoundInjectionToken, FactoryInjectionToken } from "../../token/injection-token.mjs";
2
+ import { DIError } from "../../errors/di-error.mjs";
3
+ import { getInjectableToken } from "../../utils/get-injectable-token.mjs";
4
+
5
+ //#region src/internal/core/token-resolver.mts
6
+ /**
7
+ * Handles token validation and resolution.
8
+ *
9
+ * Focuses on token validation, normalization, and argument validation.
10
+ * Name generation is handled by NameResolver.
11
+ */ var TokenResolver = class {
12
+ logger;
13
+ constructor(logger = null) {
14
+ this.logger = logger;
15
+ }
16
+ /**
17
+ * Normalizes a token to an InjectionToken.
18
+ * Handles class constructors by getting their injectable token.
19
+ *
20
+ * @param token A class constructor, InjectionToken, BoundInjectionToken, or FactoryInjectionToken
21
+ * @returns The normalized InjectionTokenType
22
+ */ normalizeToken(token) {
23
+ if (typeof token === "function") return getInjectableToken(token);
24
+ return token;
25
+ }
26
+ /**
27
+ * Gets the underlying "real" token from wrapped tokens.
28
+ * For BoundInjectionToken and FactoryInjectionToken, returns the wrapped token.
29
+ * For other tokens, returns the token itself.
30
+ *
31
+ * @param token The token to unwrap
32
+ * @returns The underlying InjectionToken
33
+ */ getRealToken(token) {
34
+ if (token instanceof BoundInjectionToken || token instanceof FactoryInjectionToken) return token.token;
35
+ return token;
36
+ }
37
+ /**
38
+ * Convenience method that normalizes a token and then gets the real token.
39
+ * Useful for checking registry entries where you need the actual registered token.
40
+ *
41
+ * @param token Any injectable type
42
+ * @returns The underlying InjectionToken
43
+ */ getRegistryToken(token) {
44
+ return this.getRealToken(this.normalizeToken(token));
45
+ }
46
+ /**
47
+ * Validates and resolves token arguments, handling factory token resolution and validation.
48
+ *
49
+ * @param token The token to validate
50
+ * @param args Optional arguments
51
+ * @returns [error, { actualToken, validatedArgs }]
52
+ */ validateAndResolveTokenArgs(token, args) {
53
+ let actualToken = token;
54
+ if (typeof token === "function") actualToken = getInjectableToken(token);
55
+ let realArgs = args;
56
+ if (actualToken instanceof BoundInjectionToken) realArgs = actualToken.value;
57
+ else if (actualToken instanceof FactoryInjectionToken) if (actualToken.resolved) realArgs = actualToken.value;
58
+ else return [DIError.factoryTokenNotResolved(token.name), { actualToken }];
59
+ if (!actualToken.schema) return [void 0, {
60
+ actualToken,
61
+ validatedArgs: realArgs
62
+ }];
63
+ const validatedArgs = actualToken.schema?.safeParse(realArgs);
64
+ if (validatedArgs && !validatedArgs.success) {
65
+ this.logger?.error(`[TokenResolver]#validateAndResolveTokenArgs(): Error validating args for ${actualToken.name.toString()}`, validatedArgs.error);
66
+ return [DIError.tokenValidationError(`Validation failed for ${actualToken.name.toString()}`, actualToken.schema, realArgs), { actualToken }];
67
+ }
68
+ return [void 0, {
69
+ actualToken,
70
+ validatedArgs: validatedArgs?.data
71
+ }];
72
+ }
73
+ };
74
+
75
+ //#endregion
76
+ export { TokenResolver };
77
+ //# sourceMappingURL=token-resolver.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"token-resolver.mjs","names":["DIError","BoundInjectionToken","FactoryInjectionToken","getInjectableToken","TokenResolver","logger","normalizeToken","token","getRealToken","getRegistryToken","validateAndResolveTokenArgs","args","actualToken","realArgs","value","resolved","factoryTokenNotResolved","name","schema","undefined","validatedArgs","safeParse","success","error","toString","tokenValidationError","data"],"sources":["../../../../src/internal/core/token-resolver.mts"],"sourcesContent":["import type {\n AnyInjectableType,\n InjectionTokenType,\n} from '../../token/injection-token.mjs'\n\nimport { DIError } from '../../errors/index.mjs'\nimport {\n BoundInjectionToken,\n FactoryInjectionToken,\n InjectionToken,\n} from '../../token/injection-token.mjs'\nimport { getInjectableToken } from '../../utils/index.mjs'\n\n/**\n * Handles token validation and resolution.\n *\n * Focuses on token validation, normalization, and argument validation.\n * Name generation is handled by NameResolver.\n */\nexport class TokenResolver {\n constructor(private readonly logger: Console | null = null) {}\n\n // ============================================================================\n // TOKEN NORMALIZATION\n // ============================================================================\n\n /**\n * Normalizes a token to an InjectionToken.\n * Handles class constructors by getting their injectable token.\n *\n * @param token A class constructor, InjectionToken, BoundInjectionToken, or FactoryInjectionToken\n * @returns The normalized InjectionTokenType\n */\n normalizeToken(token: AnyInjectableType): InjectionTokenType {\n if (typeof token === 'function') {\n return getInjectableToken(token)\n }\n return token as InjectionTokenType\n }\n\n /**\n * Gets the underlying \"real\" token from wrapped tokens.\n * For BoundInjectionToken and FactoryInjectionToken, returns the wrapped token.\n * For other tokens, returns the token itself.\n *\n * @param token The token to unwrap\n * @returns The underlying InjectionToken\n */\n getRealToken<T = unknown>(token: InjectionTokenType): InjectionToken<T> {\n if (\n token instanceof BoundInjectionToken ||\n token instanceof FactoryInjectionToken\n ) {\n return token.token as InjectionToken<T>\n }\n return token as InjectionToken<T>\n }\n\n /**\n * Convenience method that normalizes a token and then gets the real token.\n * Useful for checking registry entries where you need the actual registered token.\n *\n * @param token Any injectable type\n * @returns The underlying InjectionToken\n */\n getRegistryToken<T = unknown>(token: AnyInjectableType): InjectionToken<T> {\n return this.getRealToken(this.normalizeToken(token))\n }\n\n // ============================================================================\n // TOKEN VALIDATION\n // ============================================================================\n\n /**\n * Validates and resolves token arguments, handling factory token resolution and validation.\n *\n * @param token The token to validate\n * @param args Optional arguments\n * @returns [error, { actualToken, validatedArgs }]\n */\n validateAndResolveTokenArgs(\n token: AnyInjectableType,\n args?: any,\n ): [\n DIError | undefined,\n { actualToken: InjectionTokenType; validatedArgs?: any },\n ] {\n let actualToken = token as InjectionToken<any, any>\n if (typeof token === 'function') {\n actualToken = getInjectableToken(token)\n }\n let realArgs = args\n if (actualToken instanceof BoundInjectionToken) {\n realArgs = actualToken.value\n } else if (actualToken instanceof FactoryInjectionToken) {\n if (actualToken.resolved) {\n realArgs = actualToken.value\n } else {\n return [DIError.factoryTokenNotResolved(token.name), { actualToken }]\n }\n }\n if (!actualToken.schema) {\n return [undefined, { actualToken, validatedArgs: realArgs }]\n }\n const validatedArgs = actualToken.schema?.safeParse(realArgs)\n if (validatedArgs && !validatedArgs.success) {\n this.logger?.error(\n `[TokenResolver]#validateAndResolveTokenArgs(): Error validating args for ${actualToken.name.toString()}`,\n validatedArgs.error,\n )\n return [\n DIError.tokenValidationError(\n `Validation failed for ${actualToken.name.toString()}`,\n actualToken.schema,\n realArgs,\n ),\n { actualToken },\n ]\n }\n return [undefined, { actualToken, validatedArgs: validatedArgs?.data }]\n }\n}\n"],"mappings":";;;;;;;;;;GAmBA,IAAaI,gBAAb,MAAaA;;CACX,YAAY,SAA0C,MAAM;OAA/BC,SAAAA;;;;;;;;IAa7BC,eAAeC,OAA8C;AAC3D,MAAI,OAAOA,UAAU,WACnB,QAAOJ,mBAAmBI,MAAAA;AAE5B,SAAOA;;;;;;;;;IAWTC,aAA0BD,OAA8C;AACtE,MACEA,iBAAiBN,uBACjBM,iBAAiBL,sBAEjB,QAAOK,MAAMA;AAEf,SAAOA;;;;;;;;IAUTE,iBAA8BF,OAA6C;AACzE,SAAO,KAAKC,aAAa,KAAKF,eAAeC,MAAAA,CAAAA;;;;;;;;IAc/CG,4BACEH,OACAI,MAIA;EACA,IAAIC,cAAcL;AAClB,MAAI,OAAOA,UAAU,WACnBK,eAAcT,mBAAmBI,MAAAA;EAEnC,IAAIM,WAAWF;AACf,MAAIC,uBAAuBX,oBACzBY,YAAWD,YAAYE;WACdF,uBAAuBV,sBAChC,KAAIU,YAAYG,SACdF,YAAWD,YAAYE;MAEvB,QAAO,CAACd,QAAQgB,wBAAwBT,MAAMU,KAAI,EAAG,EAAEL,aAAY,CAAE;AAGzE,MAAI,CAACA,YAAYM,OACf,QAAO,CAACC,QAAW;GAAEP;GAAaQ,eAAeP;GAAS,CAAE;EAE9D,MAAMO,gBAAgBR,YAAYM,QAAQG,UAAUR,SAAAA;AACpD,MAAIO,iBAAiB,CAACA,cAAcE,SAAS;AAC3C,QAAKjB,QAAQkB,MACX,4EAA4EX,YAAYK,KAAKO,UAAQ,IACrGJ,cAAcG,MAAK;AAErB,UAAO,CACLvB,QAAQyB,qBACN,yBAAyBb,YAAYK,KAAKO,UAAQ,IAClDZ,YAAYM,QACZL,SAAAA,EAEF,EAAED,aAAY,CACf;;AAEH,SAAO,CAACO,QAAW;GAAEP;GAAaQ,eAAeA,eAAeM;GAAK,CAAE"}
@@ -0,0 +1,99 @@
1
+ import { InjectableScope } from "../../enums/injectable-scope.enum.mjs";
2
+ import { InjectableType } from "../../enums/injectable-type.enum.mjs";
3
+ import { DIError } from "../../errors/di-error.mjs";
4
+ import { InstanceHolder } from "./instance-holder.mjs";
5
+
6
+ //#region src/internal/holder/holder-storage.interface.d.mts
7
+
8
+ /**
9
+ * Result type for holder retrieval operations.
10
+ * - [undefined, holder] - Holder found successfully
11
+ * - [DIError, holder?] - Error occurred (holder may be available for waiting)
12
+ * - null - No holder exists
13
+ */
14
+ type HolderGetResult<T = unknown> = [undefined, InstanceHolder<T>] | [DIError, InstanceHolder<T>?] | null;
15
+ /**
16
+ * Interface for abstracting holder storage operations.
17
+ *
18
+ * Enables unified instance resolution logic regardless of where
19
+ * holders are stored. This is the key abstraction for the unified storage pattern.
20
+ */
21
+ interface IHolderStorage {
22
+ /**
23
+ * The scope this storage handles.
24
+ */
25
+ readonly scope: InjectableScope;
26
+ /**
27
+ * Retrieves an existing holder by instance name.
28
+ *
29
+ * @param instanceName The unique identifier for the instance
30
+ * @returns
31
+ * - [undefined, holder] if found and ready/creating
32
+ * - [DIError, holder?] if found but in error/destroying state
33
+ * - null if not found
34
+ */
35
+ get<T = unknown>(instanceName: string): HolderGetResult<T>;
36
+ /**
37
+ * Stores a holder by instance name.
38
+ *
39
+ * @param instanceName The unique identifier for the instance
40
+ * @param holder The holder to store
41
+ */
42
+ set(instanceName: string, holder: InstanceHolder): void;
43
+ /**
44
+ * Deletes a holder by instance name.
45
+ *
46
+ * @param instanceName The unique identifier for the instance
47
+ * @returns true if the holder was deleted, false if it didn't exist
48
+ */
49
+ delete(instanceName: string): boolean;
50
+ /**
51
+ * Creates a new holder in "Creating" state with a deferred promise.
52
+ * The holder is NOT automatically stored - call set() to store it.
53
+ *
54
+ * @param instanceName The unique identifier for the instance
55
+ * @param type The injectable type
56
+ * @param deps The set of dependency names
57
+ * @returns A tuple containing the deferred promise resolver and the holder
58
+ */
59
+ createHolder<T>(instanceName: string, type: InjectableType, deps: Set<string>): [ReturnType<typeof Promise.withResolvers<[undefined, T]>>, InstanceHolder<T>];
60
+ /**
61
+ * Checks if this storage should be used for the given scope.
62
+ */
63
+ handles(scope: InjectableScope): boolean;
64
+ /**
65
+ * Gets all instance names in this storage.
66
+ */
67
+ getAllNames(): string[];
68
+ /**
69
+ * Iterates over all holders with a callback.
70
+ *
71
+ * @param callback Function called for each holder with (name, holder)
72
+ */
73
+ forEach(callback: (name: string, holder: InstanceHolder) => void): void;
74
+ /**
75
+ * Finds a holder by its instance value (reverse lookup).
76
+ *
77
+ * @param instance The instance to search for
78
+ * @returns The holder if found, null otherwise
79
+ */
80
+ findByInstance(instance: unknown): InstanceHolder | null;
81
+ /**
82
+ * Finds all instance names that depend on the given instance name.
83
+ *
84
+ * @param instanceName The instance name to find dependents for
85
+ * @returns Array of instance names that have this instance as a dependency
86
+ */
87
+ findDependents(instanceName: string): string[];
88
+ /**
89
+ * Updates dependency references when instance names change.
90
+ * Used during scope upgrades when instance names are regenerated with requestId.
91
+ *
92
+ * @param oldName The old instance name
93
+ * @param newName The new instance name
94
+ */
95
+ updateDependencyReference(oldName: string, newName: string): void;
96
+ }
97
+ //#endregion
98
+ export { HolderGetResult, IHolderStorage };
99
+ //# sourceMappingURL=holder-storage.interface.d.mts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"holder-storage.interface.d.mts","names":[],"sources":["../../../../src/internal/holder/holder-storage.interface.mts"],"sourcesContent":[],"mappings":";;;;;;;;;;AAUA;;;AAEK,KAFO,eAEP,CAAA,IAAA,OAAA,CAAA,GAAA,CAAA,SAAA,EADW,cACX,CAD0B,CAC1B,CAAA,CAAA,GAAA,CAAA,OAAA,EAAS,cAAT,CAAwB,CAAxB,CAAA,CAAA,CAAA,GAAA,IAAA;;;;AASL;;;AAmB0C,UAnBzB,cAAA,CAmByB;EAQN;;;EAwBoB,SAAA,KAAA,EA/CtC,eA+CsC;EAAlC;;;;;;;;;0CAhCoB,gBAAgB;;;;;;;oCAQtB;;;;;;;;;;;;;;;;;8CAqB1B,sBACA,eAEN,kBAAkB,OAAA,CAAQ,0BAA0B,MACpD,eAAe;;;;iBAMF;;;;;;;;;;2CAgB0B;;;;;;;qCAQN"}
@@ -0,0 +1,101 @@
1
+ import { InjectableScope } from "../../enums/injectable-scope.enum.mjs";
2
+ import { InjectableType } from "../../enums/injectable-type.enum.mjs";
3
+
4
+ //#region src/internal/holder/instance-holder.d.mts
5
+ /**
6
+ * Represents the lifecycle status of an instance holder.
7
+ */
8
+ declare enum InstanceStatus {
9
+ /** Instance has been successfully created and is ready for use */
10
+ Created = "created",
11
+ /** Instance is currently being created (async initialization in progress) */
12
+ Creating = "creating",
13
+ /** Instance is being destroyed (cleanup in progress) */
14
+ Destroying = "destroying",
15
+ /** Instance creation failed with an error */
16
+ Error = "error",
17
+ }
18
+ /** Callback function for instance destruction listeners */
19
+ type InstanceDestroyListener = () => void | Promise<void>;
20
+ /**
21
+ * Instance holder in the Creating state.
22
+ * The instance is null while creation is in progress.
23
+ */
24
+ interface InstanceHolderCreating<Instance> {
25
+ status: InstanceStatus.Creating;
26
+ name: string;
27
+ instance: null;
28
+ creationPromise: Promise<[undefined, Instance]> | null;
29
+ destroyPromise: null;
30
+ type: InjectableType;
31
+ scope: InjectableScope;
32
+ deps: Set<string>;
33
+ destroyListeners: InstanceDestroyListener[];
34
+ createdAt: number;
35
+ /** Tracks which services this holder is currently waiting for (for circular dependency detection) */
36
+ waitingFor: Set<string>;
37
+ }
38
+ /**
39
+ * Instance holder in the Created state.
40
+ * The instance is available and ready for use.
41
+ */
42
+ interface InstanceHolderCreated<Instance> {
43
+ status: InstanceStatus.Created;
44
+ name: string;
45
+ instance: Instance;
46
+ creationPromise: null;
47
+ destroyPromise: null;
48
+ type: InjectableType;
49
+ scope: InjectableScope;
50
+ deps: Set<string>;
51
+ destroyListeners: InstanceDestroyListener[];
52
+ createdAt: number;
53
+ /** Tracks which services this holder is currently waiting for (for circular dependency detection) */
54
+ waitingFor: Set<string>;
55
+ }
56
+ /**
57
+ * Instance holder in the Destroying state.
58
+ * The instance may still be available but is being cleaned up.
59
+ */
60
+ interface InstanceHolderDestroying<Instance> {
61
+ status: InstanceStatus.Destroying;
62
+ name: string;
63
+ instance: Instance | null;
64
+ creationPromise: null;
65
+ destroyPromise: Promise<void>;
66
+ type: InjectableType;
67
+ scope: InjectableScope;
68
+ deps: Set<string>;
69
+ destroyListeners: InstanceDestroyListener[];
70
+ createdAt: number;
71
+ /** Tracks which services this holder is currently waiting for (for circular dependency detection) */
72
+ waitingFor: Set<string>;
73
+ }
74
+ /**
75
+ * Instance holder in the Error state.
76
+ * The instance field contains the error that occurred during creation.
77
+ */
78
+ interface InstanceHolderError {
79
+ status: InstanceStatus.Error;
80
+ name: string;
81
+ instance: Error;
82
+ creationPromise: null;
83
+ destroyPromise: null;
84
+ type: InjectableType;
85
+ scope: InjectableScope;
86
+ deps: Set<string>;
87
+ destroyListeners: InstanceDestroyListener[];
88
+ createdAt: number;
89
+ /** Tracks which services this holder is currently waiting for (for circular dependency detection) */
90
+ waitingFor: Set<string>;
91
+ }
92
+ /**
93
+ * Holds the state of a service instance throughout its lifecycle.
94
+ *
95
+ * Tracks creation/destruction promises, dependency relationships,
96
+ * destroy listeners, and current status (Creating, Created, Destroying, Error).
97
+ */
98
+ type InstanceHolder<Instance = unknown> = InstanceHolderCreating<Instance> | InstanceHolderCreated<Instance> | InstanceHolderDestroying<Instance> | InstanceHolderError;
99
+ //#endregion
100
+ export { InstanceDestroyListener, InstanceHolder, InstanceHolderCreated, InstanceHolderCreating, InstanceHolderDestroying, InstanceHolderError, InstanceStatus };
101
+ //# sourceMappingURL=instance-holder.d.mts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"instance-holder.d.mts","names":[],"sources":["../../../../src/internal/holder/instance-holder.mts"],"sourcesContent":[],"mappings":";;;;;;;AAKY,aAAA,cAAA;EAYA;EAMK,OAAA,GAAA,SAAA;EACP;EAG6B,QAAA,GAAA,UAAA;EAApB;EAEX,UAAA,GAAA,YAAA;EACC;EACD,KAAA,GAAA,OAAA;;;AAIS,KAlBL,uBAAA,GAkBK,GAAA,GAAA,IAAA,GAlBkC,OAkBlC,CAAA,IAAA,CAAA;AAOjB;;;;AAOS,UA1BQ,sBA0BR,CAAA,QAAA,CAAA,CAAA;EACD,MAAA,EA1BE,cAAA,CAAe,QA0BjB;EACY,IAAA,EAAA,MAAA;EAGN,QAAA,EAAA,IAAA;EAAG,eAAA,EA3BE,OA2BF,CAAA,CAAA,SAAA,EA3BsB,QA2BtB,CAAA,CAAA,GAAA,IAAA;EAOA,cAAA,EAAA,IAAA;EACP,IAAA,EAjCF,cAiCiB;EAEb,KAAA,EAlCH,eAkCG;EAEM,IAAA,EAnCV,GAmCU,CAAA,MAAA,CAAA;EACV,gBAAA,EAnCY,uBAmCZ,EAAA;EACC,SAAA,EAAA,MAAA;EACD;EACY,UAAA,EAnCN,GAmCM,CAAA,MAAA,CAAA;;;AAUpB;;;AAMQ,UA5CS,qBA4CT,CAAA,QAAA,CAAA,CAAA;EACC,MAAA,EA5CC,cAAA,CAAe,OA4ChB;EACD,IAAA,EAAA,MAAA;EACY,QAAA,EA5CR,QA4CQ;EAGN,eAAA,EAAA,IAAA;EAAG,cAAA,EAAA,IAAA;EASL,IAAA,EArDJ,cAqDkB;EACC,KAAA,EArDlB,eAqDkB;EAAvB,IAAA,EApDI,GAoDJ,CAAA,MAAA,CAAA;EACsB,gBAAA,EApDN,uBAoDM,EAAA;EAAtB,SAAA,EAAA,MAAA;EACyB;EAAzB,UAAA,EAlDU,GAkDV,CAAA,MAAA,CAAA;;;;;;UA3Ca;UACP,cAAA,CAAe;;YAEb;;kBAEM;QACV;SACC;QACD;oBACY;;;cAGN;;;;;;UAOG,mBAAA;UACP,cAAA,CAAe;;YAEb;;;QAGJ;SACC;QACD;oBACY;;;cAGN;;;;;;;;KASF,qCACR,uBAAuB,YACvB,sBAAsB,YACtB,yBAAyB,YACzB"}
@@ -0,0 +1,19 @@
1
+ //#region src/internal/holder/instance-holder.mts
2
+ /**
3
+ * Represents the lifecycle status of an instance holder.
4
+ */
5
+ let InstanceStatus = /* @__PURE__ */ function(InstanceStatus$1) {
6
+ /** Instance has been successfully created and is ready for use */
7
+ InstanceStatus$1["Created"] = "created";
8
+ /** Instance is currently being created (async initialization in progress) */
9
+ InstanceStatus$1["Creating"] = "creating";
10
+ /** Instance is being destroyed (cleanup in progress) */
11
+ InstanceStatus$1["Destroying"] = "destroying";
12
+ /** Instance creation failed with an error */
13
+ InstanceStatus$1["Error"] = "error";
14
+ return InstanceStatus$1;
15
+ }({});
16
+
17
+ //#endregion
18
+ export { InstanceStatus };
19
+ //# sourceMappingURL=instance-holder.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"instance-holder.mjs","names":[],"sources":["../../../../src/internal/holder/instance-holder.mts"],"sourcesContent":["import type { InjectableScope, InjectableType } from '../../enums/index.mjs'\n\n/**\n * Represents the lifecycle status of an instance holder.\n */\nexport enum InstanceStatus {\n /** Instance has been successfully created and is ready for use */\n Created = 'created',\n /** Instance is currently being created (async initialization in progress) */\n Creating = 'creating',\n /** Instance is being destroyed (cleanup in progress) */\n Destroying = 'destroying',\n /** Instance creation failed with an error */\n Error = 'error',\n}\n\n/** Callback function for instance destruction listeners */\nexport type InstanceDestroyListener = () => void | Promise<void>\n\n/**\n * Instance holder in the Creating state.\n * The instance is null while creation is in progress.\n */\nexport interface InstanceHolderCreating<Instance> {\n status: InstanceStatus.Creating\n name: string\n instance: null\n creationPromise: Promise<[undefined, Instance]> | null\n destroyPromise: null\n type: InjectableType\n scope: InjectableScope\n deps: Set<string>\n destroyListeners: InstanceDestroyListener[]\n createdAt: number\n /** Tracks which services this holder is currently waiting for (for circular dependency detection) */\n waitingFor: Set<string>\n}\n\n/**\n * Instance holder in the Created state.\n * The instance is available and ready for use.\n */\nexport interface InstanceHolderCreated<Instance> {\n status: InstanceStatus.Created\n name: string\n instance: Instance\n creationPromise: null\n destroyPromise: null\n type: InjectableType\n scope: InjectableScope\n deps: Set<string>\n destroyListeners: InstanceDestroyListener[]\n createdAt: number\n /** Tracks which services this holder is currently waiting for (for circular dependency detection) */\n waitingFor: Set<string>\n}\n\n/**\n * Instance holder in the Destroying state.\n * The instance may still be available but is being cleaned up.\n */\nexport interface InstanceHolderDestroying<Instance> {\n status: InstanceStatus.Destroying\n name: string\n instance: Instance | null\n creationPromise: null\n destroyPromise: Promise<void>\n type: InjectableType\n scope: InjectableScope\n deps: Set<string>\n destroyListeners: InstanceDestroyListener[]\n createdAt: number\n /** Tracks which services this holder is currently waiting for (for circular dependency detection) */\n waitingFor: Set<string>\n}\n\n/**\n * Instance holder in the Error state.\n * The instance field contains the error that occurred during creation.\n */\nexport interface InstanceHolderError {\n status: InstanceStatus.Error\n name: string\n instance: Error\n creationPromise: null\n destroyPromise: null\n type: InjectableType\n scope: InjectableScope\n deps: Set<string>\n destroyListeners: InstanceDestroyListener[]\n createdAt: number\n /** Tracks which services this holder is currently waiting for (for circular dependency detection) */\n waitingFor: Set<string>\n}\n\n/**\n * Holds the state of a service instance throughout its lifecycle.\n *\n * Tracks creation/destruction promises, dependency relationships,\n * destroy listeners, and current status (Creating, Created, Destroying, Error).\n */\nexport type InstanceHolder<Instance = unknown> =\n | InstanceHolderCreating<Instance>\n | InstanceHolderCreated<Instance>\n | InstanceHolderDestroying<Instance>\n | InstanceHolderError\n\n"],"mappings":";;;;AAKA,IAAY,4DAAL;;AAEL;;AAEA;;AAEA;;AAEA"}
@@ -0,0 +1,53 @@
1
+ import { InjectableScope } from "../../enums/injectable-scope.enum.mjs";
2
+ import { InjectableType } from "../../enums/injectable-type.enum.mjs";
3
+ import { InstanceHolder } from "./instance-holder.mjs";
4
+ import { HolderGetResult, IHolderStorage } from "./holder-storage.interface.mjs";
5
+
6
+ //#region src/internal/holder/unified-storage.d.mts
7
+
8
+ /**
9
+ * Unified storage implementation that works the same way regardless of scope.
10
+ * Replaces RequestContext, HolderManager, SingletonStorage, RequestStorage.
11
+ *
12
+ * Scope is just metadata - storage operations are identical for all scopes.
13
+ * Different storage instances are just isolated storage spaces.
14
+ */
15
+ declare class UnifiedStorage implements IHolderStorage {
16
+ readonly scope: InjectableScope;
17
+ private readonly holders;
18
+ /**
19
+ * Reverse dependency index: maps a dependency name to the set of holder names that depend on it.
20
+ * This allows O(1) lookup of dependents instead of O(n) iteration.
21
+ */
22
+ private readonly dependents;
23
+ constructor(scope?: InjectableScope);
24
+ get<T = unknown>(instanceName: string): HolderGetResult<T>;
25
+ set(instanceName: string, holder: InstanceHolder): void;
26
+ delete(instanceName: string): boolean;
27
+ createHolder<T>(instanceName: string, type: InjectableType, deps: Set<string>): [ReturnType<typeof Promise.withResolvers<[undefined, T]>>, InstanceHolder<T>];
28
+ storeInstance(instanceName: string, instance: unknown): void;
29
+ handles(scope: InjectableScope): boolean;
30
+ getAllNames(): string[];
31
+ forEach(callback: (name: string, holder: InstanceHolder) => void): void;
32
+ findByInstance(instance: unknown): InstanceHolder | null;
33
+ findDependents(instanceName: string): string[];
34
+ /**
35
+ * Updates dependency references when instance names change.
36
+ * Used during scope upgrades when instance names are regenerated with requestId.
37
+ *
38
+ * @param oldName The old instance name
39
+ * @param newName The new instance name
40
+ */
41
+ updateDependencyReference(oldName: string, newName: string): void;
42
+ /**
43
+ * Registers a holder's dependencies in the reverse index.
44
+ */
45
+ private registerDependencies;
46
+ /**
47
+ * Removes a holder from the reverse dependency index.
48
+ */
49
+ private removeFromDependentsIndex;
50
+ }
51
+ //#endregion
52
+ export { UnifiedStorage };
53
+ //# sourceMappingURL=unified-storage.d.mts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"unified-storage.d.mts","names":[],"sources":["../../../../src/internal/holder/unified-storage.mts"],"sourcesContent":[],"mappings":";;;;;;;;;;AAkBA;;;;AAc0C,cAd7B,cAAA,YAA0B,cAcG,CAAA;EA8BN,SAAA,KAAA,EA3ClB,eA2CkB;EAmB1B,iBAAA,OAAA;EACA;;;;EAGS,iBAAA,UAAA;EAAf,WAAA,CAAA,KAAA,CAAA,EAzDiB,eAyDjB;EAkDa,GAAA,CAAA,IAAA,OAAA,CAAA,CAAA,YAAA,EAAA,MAAA,CAAA,EAvGyB,eAuGzB,CAvGyC,CAuGzC,CAAA;EAY0B,GAAA,CAAA,YAAA,EAAA,MAAA,EAAA,MAAA,EArFP,cAqFO,CAAA,EAAA,IAAA;EAMN,MAAA,CAAA,YAAA,EAAA,MAAA,CAAA,EAAA,OAAA;EAvIE,YAAA,CAAA,CAAA,CAAA,CAAA,YAAA,EAAA,MAAA,EAAA,IAAA,EA+D7B,cA/D6B,EAAA,IAAA,EAgE7B,GAhE6B,CAAA,MAAA,CAAA,CAAA,EAAA,CAkEnC,UAlEiD,CAAA,OAkE/B,OAAA,CAAQ,aAlEuB,CAAA,CAAA,SAAA,EAkEG,CAlEH,CAAA,CAAA,CAAA,EAmEjD,eAAe;;iBAkDF;;2CAY0B;qCAMN"}
@@ -0,0 +1,144 @@
1
+ import { InjectableScope } from "../../enums/injectable-scope.enum.mjs";
2
+ import { InjectableType } from "../../enums/injectable-type.enum.mjs";
3
+ import { DIError } from "../../errors/di-error.mjs";
4
+ import { InstanceStatus } from "./instance-holder.mjs";
5
+
6
+ //#region src/internal/holder/unified-storage.mts
7
+ /**
8
+ * Unified storage implementation that works the same way regardless of scope.
9
+ * Replaces RequestContext, HolderManager, SingletonStorage, RequestStorage.
10
+ *
11
+ * Scope is just metadata - storage operations are identical for all scopes.
12
+ * Different storage instances are just isolated storage spaces.
13
+ */ var UnifiedStorage = class {
14
+ scope;
15
+ holders = /* @__PURE__ */ new Map();
16
+ /**
17
+ * Reverse dependency index: maps a dependency name to the set of holder names that depend on it.
18
+ * This allows O(1) lookup of dependents instead of O(n) iteration.
19
+ */ dependents = /* @__PURE__ */ new Map();
20
+ constructor(scope = InjectableScope.Singleton) {
21
+ this.scope = scope;
22
+ }
23
+ get(instanceName) {
24
+ const holder = this.holders.get(instanceName);
25
+ if (!holder) return null;
26
+ switch (holder.status) {
27
+ case InstanceStatus.Destroying: return [DIError.instanceDestroying(instanceName), holder];
28
+ case InstanceStatus.Error: return [holder.instance, holder];
29
+ case InstanceStatus.Creating:
30
+ case InstanceStatus.Created: return [void 0, holder];
31
+ default: return null;
32
+ }
33
+ }
34
+ set(instanceName, holder) {
35
+ this.holders.set(instanceName, holder);
36
+ if (holder.deps.size > 0) this.registerDependencies(instanceName, holder.deps);
37
+ }
38
+ delete(instanceName) {
39
+ const holder = this.holders.get(instanceName);
40
+ if (holder) this.removeFromDependentsIndex(instanceName, holder.deps);
41
+ return this.holders.delete(instanceName);
42
+ }
43
+ createHolder(instanceName, type, deps) {
44
+ const deferred = Promise.withResolvers();
45
+ return [deferred, {
46
+ status: InstanceStatus.Creating,
47
+ name: instanceName,
48
+ instance: null,
49
+ creationPromise: deferred.promise,
50
+ destroyPromise: null,
51
+ type,
52
+ scope: this.scope,
53
+ deps,
54
+ destroyListeners: [],
55
+ createdAt: Date.now(),
56
+ waitingFor: /* @__PURE__ */ new Set()
57
+ }];
58
+ }
59
+ storeInstance(instanceName, instance) {
60
+ if (this.holders.get(instanceName)) throw DIError.storageError("Instance already stored", "storeInstance", instanceName);
61
+ this.set(instanceName, {
62
+ status: InstanceStatus.Created,
63
+ name: instanceName,
64
+ instance,
65
+ creationPromise: null,
66
+ destroyPromise: null,
67
+ type: InjectableType.Class,
68
+ scope: this.scope,
69
+ deps: /* @__PURE__ */ new Set(),
70
+ destroyListeners: typeof instance === "object" && instance !== null && "onServiceDestroy" in instance ? [instance.onServiceDestroy] : [],
71
+ createdAt: Date.now(),
72
+ waitingFor: /* @__PURE__ */ new Set()
73
+ });
74
+ }
75
+ handles(scope) {
76
+ return scope === this.scope;
77
+ }
78
+ getAllNames() {
79
+ return Array.from(this.holders.keys());
80
+ }
81
+ forEach(callback) {
82
+ for (const [name, holder] of this.holders) callback(name, holder);
83
+ }
84
+ findByInstance(instance) {
85
+ for (const holder of this.holders.values()) if (holder.instance === instance) return holder;
86
+ return null;
87
+ }
88
+ findDependents(instanceName) {
89
+ const dependents = this.dependents.get(instanceName);
90
+ return dependents ? Array.from(dependents) : [];
91
+ }
92
+ /**
93
+ * Updates dependency references when instance names change.
94
+ * Used during scope upgrades when instance names are regenerated with requestId.
95
+ *
96
+ * @param oldName The old instance name
97
+ * @param newName The new instance name
98
+ */ updateDependencyReference(oldName, newName) {
99
+ for (const holder of this.holders.values()) if (holder.deps.has(oldName)) {
100
+ holder.deps.delete(oldName);
101
+ holder.deps.add(newName);
102
+ }
103
+ const oldDependents = this.dependents.get(oldName);
104
+ if (oldDependents) {
105
+ const newDependents = this.dependents.get(newName) || /* @__PURE__ */ new Set();
106
+ for (const dependent of oldDependents) newDependents.add(dependent);
107
+ this.dependents.set(newName, newDependents);
108
+ this.dependents.delete(oldName);
109
+ }
110
+ for (const [depName, dependents] of this.dependents.entries()) if (depName === oldName) {
111
+ const newDependents = this.dependents.get(newName) || /* @__PURE__ */ new Set();
112
+ for (const dependent of dependents) newDependents.add(dependent);
113
+ this.dependents.set(newName, newDependents);
114
+ this.dependents.delete(oldName);
115
+ }
116
+ }
117
+ /**
118
+ * Registers a holder's dependencies in the reverse index.
119
+ */ registerDependencies(holderName, deps) {
120
+ for (const dep of deps) {
121
+ let dependents = this.dependents.get(dep);
122
+ if (!dependents) {
123
+ dependents = /* @__PURE__ */ new Set();
124
+ this.dependents.set(dep, dependents);
125
+ }
126
+ dependents.add(holderName);
127
+ }
128
+ }
129
+ /**
130
+ * Removes a holder from the reverse dependency index.
131
+ */ removeFromDependentsIndex(holderName, deps) {
132
+ for (const dep of deps) {
133
+ const dependents = this.dependents.get(dep);
134
+ if (dependents) {
135
+ dependents.delete(holderName);
136
+ if (dependents.size === 0) this.dependents.delete(dep);
137
+ }
138
+ }
139
+ }
140
+ };
141
+
142
+ //#endregion
143
+ export { UnifiedStorage };
144
+ //# sourceMappingURL=unified-storage.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"unified-storage.mjs","names":["InjectableScope","InjectableType","DIError","InstanceStatus","UnifiedStorage","scope","holders","Map","dependents","Singleton","get","instanceName","holder","status","Destroying","instanceDestroying","Error","instance","Creating","Created","undefined","set","deps","size","registerDependencies","delete","removeFromDependentsIndex","createHolder","type","deferred","Promise","withResolvers","name","creationPromise","promise","destroyPromise","destroyListeners","createdAt","Date","now","waitingFor","Set","storeInstance","storageError","Class","onServiceDestroy","handles","getAllNames","Array","from","keys","forEach","callback","findByInstance","values","findDependents","updateDependencyReference","oldName","newName","has","add","oldDependents","newDependents","dependent","depName","entries","holderName","dep"],"sources":["../../../../src/internal/holder/unified-storage.mts"],"sourcesContent":["import type { OnServiceDestroy } from '../../interfaces/index.mjs'\nimport type {\n HolderGetResult,\n IHolderStorage,\n} from './holder-storage.interface.mjs'\nimport type { InstanceHolder } from './instance-holder.mjs'\n\nimport { InjectableScope, InjectableType } from '../../enums/index.mjs'\nimport { DIError } from '../../errors/index.mjs'\nimport { InstanceStatus } from './instance-holder.mjs'\n\n/**\n * Unified storage implementation that works the same way regardless of scope.\n * Replaces RequestContext, HolderManager, SingletonStorage, RequestStorage.\n *\n * Scope is just metadata - storage operations are identical for all scopes.\n * Different storage instances are just isolated storage spaces.\n */\nexport class UnifiedStorage implements IHolderStorage {\n readonly scope: InjectableScope\n\n private readonly holders = new Map<string, InstanceHolder>()\n /**\n * Reverse dependency index: maps a dependency name to the set of holder names that depend on it.\n * This allows O(1) lookup of dependents instead of O(n) iteration.\n */\n private readonly dependents = new Map<string, Set<string>>()\n\n constructor(scope: InjectableScope = InjectableScope.Singleton) {\n this.scope = scope\n }\n\n get<T = unknown>(instanceName: string): HolderGetResult<T> {\n const holder = this.holders.get(instanceName)\n\n if (!holder) {\n return null\n }\n\n // Check holder status for error states\n switch (holder.status) {\n case InstanceStatus.Destroying:\n return [\n DIError.instanceDestroying(instanceName),\n holder as InstanceHolder<T>,\n ]\n\n case InstanceStatus.Error:\n return [\n holder.instance as unknown as DIError,\n holder as InstanceHolder<T>,\n ]\n\n case InstanceStatus.Creating:\n case InstanceStatus.Created:\n return [undefined, holder as InstanceHolder<T>]\n\n default:\n return null\n }\n }\n\n set(instanceName: string, holder: InstanceHolder): void {\n this.holders.set(instanceName, holder)\n // Register dependencies in reverse index\n if (holder.deps.size > 0) {\n this.registerDependencies(instanceName, holder.deps)\n }\n }\n\n delete(instanceName: string): boolean {\n const holder = this.holders.get(instanceName)\n if (holder) {\n // Remove this holder from the reverse index for all its dependencies\n this.removeFromDependentsIndex(instanceName, holder.deps)\n }\n return this.holders.delete(instanceName)\n }\n\n createHolder<T>(\n instanceName: string,\n type: InjectableType,\n deps: Set<string>,\n ): [\n ReturnType<typeof Promise.withResolvers<[undefined, T]>>,\n InstanceHolder<T>,\n ] {\n const deferred = Promise.withResolvers<[undefined, T]>()\n\n const holder: InstanceHolder<T> = {\n status: InstanceStatus.Creating,\n name: instanceName,\n instance: null,\n creationPromise: deferred.promise,\n destroyPromise: null,\n type,\n scope: this.scope,\n deps,\n destroyListeners: [],\n createdAt: Date.now(),\n waitingFor: new Set(),\n }\n\n return [deferred, holder]\n }\n\n storeInstance(instanceName: string, instance: unknown): void {\n const holder = this.holders.get(instanceName)\n if (holder) {\n throw DIError.storageError(\n 'Instance already stored',\n 'storeInstance',\n instanceName,\n )\n }\n this.set(instanceName, {\n status: InstanceStatus.Created,\n name: instanceName,\n instance,\n creationPromise: null,\n destroyPromise: null,\n type: InjectableType.Class,\n scope: this.scope,\n deps: new Set(),\n destroyListeners:\n typeof instance === 'object' &&\n instance !== null &&\n 'onServiceDestroy' in instance\n ? [(instance as OnServiceDestroy).onServiceDestroy]\n : [],\n createdAt: Date.now(),\n waitingFor: new Set(),\n })\n }\n\n handles(scope: InjectableScope): boolean {\n return scope === this.scope\n }\n\n // ============================================================================\n // ITERATION AND QUERY\n // ============================================================================\n\n getAllNames(): string[] {\n return Array.from(this.holders.keys())\n }\n\n forEach(callback: (name: string, holder: InstanceHolder) => void): void {\n for (const [name, holder] of this.holders) {\n callback(name, holder)\n }\n }\n\n findByInstance(instance: unknown): InstanceHolder | null {\n for (const holder of this.holders.values()) {\n if (holder.instance === instance) {\n return holder\n }\n }\n return null\n }\n\n findDependents(instanceName: string): string[] {\n const dependents = this.dependents.get(instanceName)\n return dependents ? Array.from(dependents) : []\n }\n\n /**\n * Updates dependency references when instance names change.\n * Used during scope upgrades when instance names are regenerated with requestId.\n *\n * @param oldName The old instance name\n * @param newName The new instance name\n */\n updateDependencyReference(oldName: string, newName: string): void {\n // Update all holders that reference oldName in their deps Set\n for (const holder of this.holders.values()) {\n if (holder.deps.has(oldName)) {\n holder.deps.delete(oldName)\n holder.deps.add(newName)\n }\n }\n\n // Update reverse dependency index\n const oldDependents = this.dependents.get(oldName)\n if (oldDependents) {\n // Move dependents from old name to new name\n const newDependents = this.dependents.get(newName) || new Set<string>()\n for (const dependent of oldDependents) {\n newDependents.add(dependent)\n }\n this.dependents.set(newName, newDependents)\n this.dependents.delete(oldName)\n }\n\n // Update reverse index entries - if oldName was a dependency, update all holders that depend on it\n for (const [depName, dependents] of this.dependents.entries()) {\n if (depName === oldName) {\n // This shouldn't happen, but handle it just in case\n const newDependents = this.dependents.get(newName) || new Set<string>()\n for (const dependent of dependents) {\n newDependents.add(dependent)\n }\n this.dependents.set(newName, newDependents)\n this.dependents.delete(oldName)\n }\n }\n }\n\n // ============================================================================\n // INTERNAL HELPERS\n // ============================================================================\n\n /**\n * Registers a holder's dependencies in the reverse index.\n */\n private registerDependencies(holderName: string, deps: Set<string>): void {\n for (const dep of deps) {\n let dependents = this.dependents.get(dep)\n if (!dependents) {\n dependents = new Set()\n this.dependents.set(dep, dependents)\n }\n dependents.add(holderName)\n }\n }\n\n /**\n * Removes a holder from the reverse dependency index.\n */\n private removeFromDependentsIndex(\n holderName: string,\n deps: Set<string>,\n ): void {\n for (const dep of deps) {\n const dependents = this.dependents.get(dep)\n if (dependents) {\n dependents.delete(holderName)\n if (dependents.size === 0) {\n this.dependents.delete(dep)\n }\n }\n }\n }\n}\n"],"mappings":"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"}