@navios/di 0.8.0 → 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 (264) hide show
  1. package/CHANGELOG.md +87 -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 -1558
  40. package/lib/browser/index.mjs +29 -2749
  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-DAKOvAgr.mjs → container-8-z89TyQ.mjs} +1325 -1462
  138. package/lib/container-8-z89TyQ.mjs.map +1 -0
  139. package/lib/{container-Bp1W-pWJ.d.mts → container-CNiqesCL.d.mts} +598 -617
  140. package/lib/container-CNiqesCL.d.mts.map +1 -0
  141. package/lib/{container-DENMeJ87.cjs → container-CaY2fDuk.cjs} +1369 -1512
  142. package/lib/container-CaY2fDuk.cjs.map +1 -0
  143. package/lib/{container-YPwvmlK2.d.cts → container-D-0Ho3qL.d.cts} +598 -612
  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 +460 -302
  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-resolver.mts +122 -0
  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-Bp1W-pWJ.d.mts.map +0 -1
  239. package/lib/container-DAKOvAgr.mjs.map +0 -1
  240. package/lib/container-DENMeJ87.cjs.map +0 -1
  241. package/lib/container-YPwvmlK2.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 -225
  256. package/src/internal/core/invalidator.mts +0 -437
  257. package/src/internal/core/service-locator.mts +0 -202
  258. package/src/internal/core/token-processor.mts +0 -252
  259. package/src/internal/holder/base-holder-manager.mts +0 -334
  260. package/src/internal/holder/holder-manager.mts +0 -85
  261. package/src/internal/holder/request-storage.mts +0 -127
  262. package/src/internal/holder/singleton-storage.mts +0 -92
  263. package/src/testing/README.md +0 -80
  264. package/src/testing/__tests__/test-container.spec.mts +0 -173
@@ -0,0 +1,255 @@
1
+ import { describe, expect, it, vi } from 'vitest'
2
+
3
+ import type { InstanceHolder } from '../internal/holder/instance-holder.mjs'
4
+
5
+ import { InjectableScope, InjectableType } from '../enums/index.mjs'
6
+ import {
7
+ getCurrentResolutionContext,
8
+ withoutResolutionContext,
9
+ withResolutionContext,
10
+ } from '../internal/context/resolution-context.mjs'
11
+ import { InstanceStatus } from '../internal/holder/instance-holder.mjs'
12
+
13
+ function createMockHolder(name: string): InstanceHolder {
14
+ return {
15
+ status: InstanceStatus.Creating,
16
+ name,
17
+ instance: null,
18
+ creationPromise: Promise.resolve([undefined, {}]) as any,
19
+ destroyPromise: null,
20
+ type: InjectableType.Class,
21
+ scope: InjectableScope.Singleton,
22
+ deps: new Set(),
23
+ destroyListeners: [],
24
+ createdAt: Date.now(),
25
+ waitingFor: new Set(),
26
+ }
27
+ }
28
+
29
+ describe('ResolutionContext', () => {
30
+ describe('withResolutionContext', () => {
31
+ it('should run function within context', () => {
32
+ const holder = createMockHolder('TestService')
33
+ const getHolder = vi.fn()
34
+
35
+ const result = withResolutionContext(holder, getHolder, () => {
36
+ return 'result'
37
+ })
38
+
39
+ expect(result).toBe('result')
40
+ })
41
+
42
+ it('should make context available via getCurrentResolutionContext', () => {
43
+ const holder = createMockHolder('TestService')
44
+ const getHolder = vi.fn()
45
+
46
+ withResolutionContext(holder, getHolder, () => {
47
+ const ctx = getCurrentResolutionContext()
48
+ expect(ctx).toBeDefined()
49
+ expect(ctx?.waiterHolder).toBe(holder)
50
+ expect(ctx?.getHolder).toBe(getHolder)
51
+ })
52
+ })
53
+
54
+ it('should properly nest contexts', () => {
55
+ const outerHolder = createMockHolder('OuterService')
56
+ const innerHolder = createMockHolder('InnerService')
57
+ const getHolder = vi.fn()
58
+
59
+ withResolutionContext(outerHolder, getHolder, () => {
60
+ const outerCtx = getCurrentResolutionContext()
61
+ expect(outerCtx?.waiterHolder.name).toBe('OuterService')
62
+
63
+ withResolutionContext(innerHolder, getHolder, () => {
64
+ const innerCtx = getCurrentResolutionContext()
65
+ expect(innerCtx?.waiterHolder.name).toBe('InnerService')
66
+ })
67
+
68
+ // After inner context, we should still have outer context
69
+ // (AsyncLocalStorage automatically restores)
70
+ const restoredCtx = getCurrentResolutionContext()
71
+ expect(restoredCtx?.waiterHolder.name).toBe('OuterService')
72
+ })
73
+ })
74
+
75
+ it('should handle async operations', async () => {
76
+ const holder = createMockHolder('AsyncService')
77
+ const getHolder = vi.fn()
78
+
79
+ await withResolutionContext(holder, getHolder, async () => {
80
+ await new Promise((resolve) => setTimeout(resolve, 10))
81
+
82
+ const ctx = getCurrentResolutionContext()
83
+ expect(ctx?.waiterHolder.name).toBe('AsyncService')
84
+ })
85
+ })
86
+
87
+ it('should propagate errors', () => {
88
+ const holder = createMockHolder('ErrorService')
89
+ const getHolder = vi.fn()
90
+
91
+ expect(() => {
92
+ withResolutionContext(holder, getHolder, () => {
93
+ throw new Error('Test error')
94
+ })
95
+ }).toThrow('Test error')
96
+ })
97
+
98
+ it('should return function result', () => {
99
+ const holder = createMockHolder('TestService')
100
+ const getHolder = vi.fn()
101
+
102
+ const result = withResolutionContext(holder, getHolder, () => {
103
+ return { data: 'test', value: 42 }
104
+ })
105
+
106
+ expect(result).toEqual({ data: 'test', value: 42 })
107
+ })
108
+ })
109
+
110
+ describe('getCurrentResolutionContext', () => {
111
+ it('should return context data inside withResolutionContext', () => {
112
+ const holder = createMockHolder('TestService')
113
+ // oxlint-disable-next-line no-unused-vars
114
+ const getHolder = (name: string) => undefined
115
+
116
+ withResolutionContext(holder, getHolder, () => {
117
+ const ctx = getCurrentResolutionContext()
118
+
119
+ expect(ctx).toBeDefined()
120
+ expect(ctx?.waiterHolder).toBe(holder)
121
+ expect(typeof ctx?.getHolder).toBe('function')
122
+ })
123
+ })
124
+ })
125
+
126
+ describe('withoutResolutionContext', () => {
127
+ it('should clear context within callback', () => {
128
+ const holder = createMockHolder('TestService')
129
+ const getHolder = vi.fn()
130
+
131
+ withResolutionContext(holder, getHolder, () => {
132
+ // Inside context
133
+ expect(getCurrentResolutionContext()?.waiterHolder).toBe(holder)
134
+
135
+ withoutResolutionContext(() => {
136
+ // Context should be cleared (undefined)
137
+ const ctx = getCurrentResolutionContext()
138
+ expect(ctx).toBeUndefined()
139
+ })
140
+
141
+ // After withoutResolutionContext, original context should be restored
142
+ expect(getCurrentResolutionContext()?.waiterHolder).toBe(holder)
143
+ })
144
+ })
145
+
146
+ it('should return function result', () => {
147
+ const holder = createMockHolder('TestService')
148
+ const getHolder = vi.fn()
149
+
150
+ const result = withResolutionContext(holder, getHolder, () => {
151
+ return withoutResolutionContext(() => {
152
+ return 'inner-result'
153
+ })
154
+ })
155
+
156
+ expect(result).toBe('inner-result')
157
+ })
158
+
159
+ it('should handle async operations', async () => {
160
+ const holder = createMockHolder('TestService')
161
+ const getHolder = vi.fn()
162
+
163
+ await withResolutionContext(holder, getHolder, async () => {
164
+ await withoutResolutionContext(async () => {
165
+ await new Promise((resolve) => setTimeout(resolve, 10))
166
+ const ctx = getCurrentResolutionContext()
167
+ expect(ctx).toBeUndefined()
168
+ })
169
+
170
+ // Context should be restored after async withoutResolutionContext
171
+ expect(getCurrentResolutionContext()?.waiterHolder).toBe(holder)
172
+ })
173
+ })
174
+ })
175
+
176
+ describe('getHolder function usage', () => {
177
+ it('should allow context to lookup holders by name', () => {
178
+ const holderA = createMockHolder('ServiceA')
179
+ const holderB = createMockHolder('ServiceB')
180
+ const holders = new Map([
181
+ ['ServiceA', holderA],
182
+ ['ServiceB', holderB],
183
+ ])
184
+
185
+ const getHolder = (name: string) => holders.get(name)
186
+
187
+ withResolutionContext(holderA, getHolder, () => {
188
+ const ctx = getCurrentResolutionContext()
189
+
190
+ const foundA = ctx?.getHolder('ServiceA')
191
+ const foundB = ctx?.getHolder('ServiceB')
192
+ const notFound = ctx?.getHolder('NonExistent')
193
+
194
+ expect(foundA).toBe(holderA)
195
+ expect(foundB).toBe(holderB)
196
+ expect(notFound).toBeUndefined()
197
+ })
198
+ })
199
+ })
200
+
201
+ describe('concurrent contexts', () => {
202
+ it('should isolate contexts between concurrent operations', async () => {
203
+ const holder1 = createMockHolder('Service1')
204
+ const holder2 = createMockHolder('Service2')
205
+ const getHolder = vi.fn()
206
+
207
+ const results: string[] = []
208
+
209
+ await Promise.all([
210
+ withResolutionContext(holder1, getHolder, async () => {
211
+ await new Promise((resolve) => setTimeout(resolve, 20))
212
+ const ctx = getCurrentResolutionContext()
213
+ results.push(`1: ${ctx?.waiterHolder.name}`)
214
+ }),
215
+ withResolutionContext(holder2, getHolder, async () => {
216
+ await new Promise((resolve) => setTimeout(resolve, 10))
217
+ const ctx = getCurrentResolutionContext()
218
+ results.push(`2: ${ctx?.waiterHolder.name}`)
219
+ }),
220
+ ])
221
+
222
+ // Each context should maintain its own holder
223
+ expect(results).toContain('1: Service1')
224
+ expect(results).toContain('2: Service2')
225
+ })
226
+ })
227
+
228
+ describe('ResolutionContextData interface', () => {
229
+ it('should provide waiterHolder property', () => {
230
+ const holder = createMockHolder('TestService')
231
+ const getHolder = vi.fn()
232
+
233
+ withResolutionContext(holder, getHolder, () => {
234
+ const ctx = getCurrentResolutionContext()
235
+
236
+ expect(ctx?.waiterHolder).toBeDefined()
237
+ expect(ctx?.waiterHolder.name).toBe('TestService')
238
+ expect(ctx?.waiterHolder.status).toBe(InstanceStatus.Creating)
239
+ })
240
+ })
241
+
242
+ it('should provide getHolder function', () => {
243
+ const holder = createMockHolder('TestService')
244
+ const mockGetHolder = vi.fn().mockReturnValue(holder)
245
+
246
+ withResolutionContext(holder, mockGetHolder, () => {
247
+ const ctx = getCurrentResolutionContext()
248
+
249
+ ctx?.getHolder('TestService')
250
+
251
+ expect(mockGetHolder).toHaveBeenCalledWith('TestService')
252
+ })
253
+ })
254
+ })
255
+ })