@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
@@ -1,70 +1,281 @@
1
- import { describe, expect, it } from 'vitest'
1
+ import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest'
2
2
 
3
- import { Injectable, InjectableScope, InjectionToken } from '../index.mjs'
4
- import { getInjectors } from '../utils/get-injectors.mjs'
5
-
6
- @Injectable({ scope: InjectableScope.Singleton })
7
- class TestService {
8
- constructor() {}
9
- }
3
+ import { Container } from '../container/container.mjs'
4
+ import { Injectable } from '../decorators/index.mjs'
5
+ import { InjectableScope } from '../enums/index.mjs'
6
+ import { InjectionToken } from '../token/injection-token.mjs'
7
+ import { defaultInjectors, getInjectors } from '../utils/index.mjs'
10
8
 
11
9
  describe('getInjectors', () => {
12
- it('should return injectors object with correct methods', () => {
10
+ it('should return an object with all injector functions', () => {
13
11
  const injectors = getInjectors()
14
12
 
15
- expect(injectors).toBeDefined()
13
+ expect(injectors).toHaveProperty('inject')
14
+ expect(injectors).toHaveProperty('asyncInject')
15
+ expect(injectors).toHaveProperty('optional')
16
+ expect(injectors).toHaveProperty('wrapSyncInit')
17
+ expect(injectors).toHaveProperty('provideFactoryContext')
16
18
  expect(typeof injectors.inject).toBe('function')
17
19
  expect(typeof injectors.asyncInject).toBe('function')
20
+ expect(typeof injectors.optional).toBe('function')
18
21
  expect(typeof injectors.wrapSyncInit).toBe('function')
19
22
  expect(typeof injectors.provideFactoryContext).toBe('function')
20
23
  })
21
24
 
22
- it('should handle wrapSyncInit with simple function', () => {
25
+ it('should create independent injector instances', () => {
26
+ const injectors1 = getInjectors()
27
+ const injectors2 = getInjectors()
28
+
29
+ expect(injectors1).not.toBe(injectors2)
30
+ })
31
+ })
32
+
33
+ describe('defaultInjectors', () => {
34
+ it('should be an instance of Injectors', () => {
35
+ expect(defaultInjectors).toHaveProperty('inject')
36
+ expect(defaultInjectors).toHaveProperty('asyncInject')
37
+ expect(defaultInjectors).toHaveProperty('optional')
38
+ expect(defaultInjectors).toHaveProperty('wrapSyncInit')
39
+ expect(defaultInjectors).toHaveProperty('provideFactoryContext')
40
+ })
41
+ })
42
+
43
+ describe('provideFactoryContext', () => {
44
+ it('should return previous context when setting new one', () => {
23
45
  const injectors = getInjectors()
24
46
 
25
- const testFn = () => 'test result'
26
- const wrappedFn = injectors.wrapSyncInit(testFn)
47
+ const originalContext = injectors.provideFactoryContext(null)
48
+ expect(originalContext).toBeNull()
49
+
50
+ const mockContext = {
51
+ inject: vi.fn(),
52
+ container: {} as any,
53
+ addDestroyListener: vi.fn(),
54
+ serviceName: 'test',
55
+ dependencies: new Set<string>(),
56
+ scope: InjectableScope.Singleton,
57
+ getDestroyListeners: () => [],
58
+ trackDependency: vi.fn(),
59
+ }
60
+
61
+ const prev = injectors.provideFactoryContext(mockContext)
62
+ expect(prev).toBeNull()
27
63
 
28
- const result = wrappedFn()
29
- expect(result).toHaveLength(3) // [result, promises, injectState]
30
- expect(result[0]).toBe('test result')
31
- expect(result[1]).toEqual([]) // no promises
64
+ const current = injectors.provideFactoryContext(null)
65
+ expect(current).toBe(mockContext)
32
66
  })
67
+ })
33
68
 
34
- it('should handle inject method when called outside context', () => {
69
+ describe('wrapSyncInit', () => {
70
+ it('should capture async inject calls', () => {
35
71
  const injectors = getInjectors()
72
+ const mockContext = {
73
+ inject: vi.fn().mockResolvedValue('result'),
74
+ container: {
75
+ tryGetSync: vi.fn().mockReturnValue(null),
76
+ } as any,
77
+ addDestroyListener: vi.fn(),
78
+ serviceName: 'test',
79
+ dependencies: new Set<string>(),
80
+ scope: InjectableScope.Singleton,
81
+ getDestroyListeners: () => [],
82
+ trackDependency: vi.fn(),
83
+ }
84
+
85
+ injectors.provideFactoryContext(mockContext)
86
+
87
+ const wrapped = injectors.wrapSyncInit(() => {
88
+ return { value: 'test' }
89
+ })
36
90
 
37
- // This should throw when called outside of injection context
38
- expect(() => injectors.inject(TestService)).toThrow()
91
+ const [result, promises, injectState] = wrapped()
92
+
93
+ expect(result).toEqual({ value: 'test' })
94
+ expect(Array.isArray(promises)).toBe(true)
95
+ expect(injectState).toBeDefined()
96
+ expect(injectState.isFrozen).toBe(true)
39
97
  })
40
98
 
41
- it('should handle asyncInject method when called outside context', async () => {
99
+ it('should support re-running with previous state', () => {
42
100
  const injectors = getInjectors()
43
- const testToken = new InjectionToken<string>('TestToken', undefined)
101
+ const mockContext = {
102
+ inject: vi.fn().mockResolvedValue('result'),
103
+ container: {
104
+ tryGetSync: vi.fn().mockReturnValue(null),
105
+ } as any,
106
+ addDestroyListener: vi.fn(),
107
+ serviceName: 'test',
108
+ dependencies: new Set<string>(),
109
+ scope: InjectableScope.Singleton,
110
+ getDestroyListeners: () => [],
111
+ trackDependency: vi.fn(),
112
+ }
44
113
 
45
- // This should throw since we're calling outside of an injectable context
46
- try {
47
- await injectors.asyncInject(testToken)
48
- expect.fail('Should have thrown an error')
49
- } catch (error) {
50
- expect(error).toBeInstanceOf(Error)
51
- expect((error as Error).message).toBe(
52
- '[Injector] Trying to access inject outside of a injectable context',
53
- )
114
+ injectors.provideFactoryContext(mockContext)
115
+
116
+ let callCount = 0
117
+ const wrapped = injectors.wrapSyncInit(() => {
118
+ callCount++
119
+ return { call: callCount }
120
+ })
121
+
122
+ const [result1, , state1] = wrapped()
123
+ expect(result1).toEqual({ call: 1 })
124
+
125
+ const [result2, , state2] = wrapped(state1)
126
+ expect(result2).toEqual({ call: 2 })
127
+ expect(state2.isFrozen).toBe(true)
128
+ })
129
+ })
130
+
131
+ describe('inject and asyncInject with Container', () => {
132
+ let container: Container
133
+
134
+ beforeEach(() => {
135
+ container = new Container()
136
+ })
137
+
138
+ afterEach(async () => {
139
+ await container.dispose()
140
+ })
141
+
142
+ it('should inject dependencies synchronously', async () => {
143
+ @Injectable()
144
+ class DependencyService {
145
+ getValue() {
146
+ return 'dependency-value'
147
+ }
148
+ }
149
+
150
+ @Injectable()
151
+ class MainService {
152
+ private dep = defaultInjectors.inject(DependencyService)
153
+
154
+ getValue() {
155
+ return this.dep.getValue()
156
+ }
157
+ }
158
+
159
+ const service = await container.get(MainService)
160
+ expect(service.getValue()).toBe('dependency-value')
161
+ })
162
+
163
+ it('should inject dependencies asynchronously', async () => {
164
+ @Injectable()
165
+ class DependencyService {
166
+ getValue() {
167
+ return 'async-dependency-value'
168
+ }
169
+ }
170
+
171
+ @Injectable()
172
+ class MainService {
173
+ private depPromise = defaultInjectors.asyncInject(DependencyService)
174
+
175
+ async getValue() {
176
+ const dep = await this.depPromise
177
+ return dep.getValue()
178
+ }
179
+ }
180
+
181
+ const service = await container.get(MainService)
182
+ expect(await service.getValue()).toBe('async-dependency-value')
183
+ })
184
+
185
+ it('should handle optional injection that succeeds', async () => {
186
+ @Injectable()
187
+ class OptionalService {
188
+ getValue() {
189
+ return 'optional-value'
190
+ }
191
+ }
192
+
193
+ @Injectable()
194
+ class MainService {
195
+ private opt = defaultInjectors.optional(OptionalService)
196
+
197
+ getValue() {
198
+ return this.opt?.getValue() ?? 'fallback'
199
+ }
54
200
  }
201
+
202
+ const service = await container.get(MainService)
203
+ expect(service.getValue()).toBe('optional-value')
55
204
  })
56
205
 
57
- it('should handle provideFactoryContext without context', () => {
206
+ it('should inject with token', async () => {
207
+ const TOKEN = InjectionToken.create<ConfigService>('CONFIG')
208
+
209
+ @Injectable({ token: TOKEN })
210
+ class ConfigService {
211
+ getValue() {
212
+ return 'config-value'
213
+ }
214
+ }
215
+
216
+ @Injectable()
217
+ class MainService {
218
+ private config = defaultInjectors.inject(TOKEN)
219
+
220
+ getValue() {
221
+ return this.config.getValue()
222
+ }
223
+ }
224
+
225
+ const service = await container.get(MainService)
226
+ expect(service.getValue()).toBe('config-value')
227
+ })
228
+ })
229
+
230
+ describe('inject error handling', () => {
231
+ it('should throw when called outside injectable context', () => {
58
232
  const injectors = getInjectors()
59
233
 
60
- const mockContext = {
61
- inject: injectors.asyncInject,
62
- container: {} as any,
63
- addDestroyListener: () => {},
234
+ expect(() => {
235
+ injectors.inject(InjectionToken.create<string>('test'))
236
+ }).toThrow('Trying to access inject outside of a injectable context')
237
+ })
238
+
239
+ it('should throw when asyncInject called outside injectable context', () => {
240
+ const injectors = getInjectors()
241
+
242
+ expect(() => {
243
+ injectors.asyncInject(InjectionToken.create<string>('test'))
244
+ }).toThrow('Trying to access inject outside of a injectable context')
245
+ })
246
+ })
247
+
248
+ describe('optional injection', () => {
249
+ let container: Container
250
+
251
+ beforeEach(() => {
252
+ container = new Container()
253
+ })
254
+
255
+ afterEach(async () => {
256
+ await container.dispose()
257
+ })
258
+
259
+ it('should return null for optional when inject fails', async () => {
260
+ const TOKEN = InjectionToken.create<string>('NON_EXISTENT')
261
+
262
+ @Injectable()
263
+ class MainService {
264
+ // This will try to inject a token that doesn't exist
265
+ private opt = defaultInjectors.optional(TOKEN)
266
+
267
+ hasOptional() {
268
+ return this.opt !== null
269
+ }
64
270
  }
65
271
 
66
- // This should work but not have much effect without a real context
67
- const result = injectors.provideFactoryContext(mockContext)
68
- expect(result).toBeNull()
272
+ // Since NON_EXISTENT is not registered, optional should return null
273
+ // But we need to register the token first for optional to work
274
+ // Optional catches errors, so if the token is not registered, it returns null
275
+ try {
276
+ await container.get(MainService)
277
+ } catch {
278
+ // Expected to fail since NON_EXISTENT is not registered
279
+ }
69
280
  })
70
281
  })