@navios/di 0.8.0 → 0.9.1

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 +102 -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 +582 -311
  154. package/lib/testing/index.cjs.map +1 -1
  155. package/lib/testing/index.d.cts +371 -41
  156. package/lib/testing/index.d.cts.map +1 -1
  157. package/lib/testing/index.d.mts +371 -41
  158. package/lib/testing/index.d.mts.map +1 -1
  159. package/lib/testing/index.mjs +581 -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 +529 -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 +564 -85
  226. package/src/testing/types.mts +123 -0
  227. package/src/testing/unit-test-container.mts +601 -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,176 @@
1
+ import { expectTypeOf, test } from 'vitest'
2
+ import { z } from 'zod/v4'
3
+
4
+ import {
5
+ BoundInjectionToken,
6
+ FactoryInjectionToken,
7
+ InjectionToken,
8
+ } from '../token/injection-token.mjs'
9
+
10
+ interface FooService {
11
+ makeFoo(): string
12
+ }
13
+
14
+ const simpleObjectSchema = z.object({
15
+ foo: z.string(),
16
+ })
17
+ const simpleOptionalObjectSchema = z
18
+ .object({
19
+ foo: z.string(),
20
+ })
21
+ .optional()
22
+
23
+ test('InjectionToken.create with class', () => {
24
+ class MyService {
25
+ getValue() {
26
+ return 42
27
+ }
28
+ }
29
+
30
+ const token = InjectionToken.create(MyService)
31
+ expectTypeOf(token).toMatchTypeOf<InjectionToken<MyService, undefined>>()
32
+ })
33
+
34
+ test('InjectionToken.create with class and schema', () => {
35
+ class MyService {
36
+ constructor(public config: z.infer<typeof simpleObjectSchema>) {}
37
+ getValue() {
38
+ return 42
39
+ }
40
+ }
41
+
42
+ const token = InjectionToken.create(MyService, simpleObjectSchema)
43
+ expectTypeOf(token).toMatchTypeOf<
44
+ InjectionToken<MyService, typeof simpleObjectSchema, true>
45
+ >()
46
+ })
47
+
48
+ test('InjectionToken.create with class and optional schema', () => {
49
+ class MyService {
50
+ constructor(public config?: z.infer<typeof simpleOptionalObjectSchema>) {}
51
+ getValue() {
52
+ return 42
53
+ }
54
+ }
55
+
56
+ const token = InjectionToken.create(MyService, simpleOptionalObjectSchema)
57
+ expectTypeOf(token).toMatchTypeOf<
58
+ InjectionToken<MyService, typeof simpleOptionalObjectSchema, false>
59
+ >()
60
+ })
61
+
62
+ test('InjectionToken.create with string name', () => {
63
+ const token = InjectionToken.create<FooService>('FooService')
64
+ expectTypeOf(token).toMatchTypeOf<InjectionToken<FooService, undefined>>()
65
+ })
66
+
67
+ test('InjectionToken.create with symbol name', () => {
68
+ const token = InjectionToken.create<FooService>(Symbol.for('FooService'))
69
+ expectTypeOf(token).toMatchTypeOf<InjectionToken<FooService, undefined>>()
70
+ })
71
+
72
+ test('InjectionToken.create with string name and schema', () => {
73
+ const token = InjectionToken.create<FooService, typeof simpleObjectSchema>(
74
+ 'FooService',
75
+ simpleObjectSchema,
76
+ )
77
+ expectTypeOf(token).toMatchTypeOf<
78
+ InjectionToken<FooService, typeof simpleObjectSchema>
79
+ >()
80
+ })
81
+
82
+ test('InjectionToken.bound creates BoundInjectionToken', () => {
83
+ const token = InjectionToken.create<FooService, typeof simpleObjectSchema>(
84
+ 'FooService',
85
+ simpleObjectSchema,
86
+ )
87
+ const boundToken = InjectionToken.bound(token, { foo: 'bar' })
88
+ expectTypeOf(boundToken).toMatchTypeOf<
89
+ BoundInjectionToken<FooService, typeof simpleObjectSchema>
90
+ >()
91
+ })
92
+
93
+ test('InjectionToken.bound requires correct argument type', () => {
94
+ const token = InjectionToken.create<FooService, typeof simpleObjectSchema>(
95
+ 'FooService',
96
+ simpleObjectSchema,
97
+ )
98
+
99
+ // @ts-expect-error Should fail with wrong argument type
100
+ InjectionToken.bound(token, { wrong: 'key' })
101
+
102
+ // @ts-expect-error Should fail with missing required property
103
+ InjectionToken.bound(token, {})
104
+ })
105
+
106
+ test('InjectionToken.factory creates FactoryInjectionToken', () => {
107
+ const token = InjectionToken.create<FooService, typeof simpleObjectSchema>(
108
+ 'FooService',
109
+ simpleObjectSchema,
110
+ )
111
+ const factoryToken = InjectionToken.factory(token, async () => ({
112
+ foo: 'bar',
113
+ }))
114
+ expectTypeOf(factoryToken).toMatchTypeOf<
115
+ FactoryInjectionToken<FooService, typeof simpleObjectSchema>
116
+ >()
117
+ })
118
+
119
+ test('InjectionToken.factory requires correct return type', () => {
120
+ const token = InjectionToken.create<FooService, typeof simpleObjectSchema>(
121
+ 'FooService',
122
+ simpleObjectSchema,
123
+ )
124
+
125
+ // @ts-expect-error Should fail with wrong return type
126
+ InjectionToken.factory(token, async () => ({ wrong: 'key' }))
127
+ })
128
+
129
+ test('InjectionToken.refineType changes BoundInjectionToken type', () => {
130
+ interface RefinedService {
131
+ doSomething(): void
132
+ }
133
+
134
+ const token = InjectionToken.create<unknown, typeof simpleObjectSchema>(
135
+ 'Service',
136
+ simpleObjectSchema,
137
+ )
138
+ const boundToken = InjectionToken.bound(token, { foo: 'bar' })
139
+ const refinedToken = InjectionToken.refineType<RefinedService>(boundToken)
140
+ expectTypeOf(refinedToken).toMatchTypeOf<
141
+ BoundInjectionToken<RefinedService, any>
142
+ >()
143
+ })
144
+
145
+ test('BoundInjectionToken has value property with correct type', () => {
146
+ const token = InjectionToken.create<FooService, typeof simpleObjectSchema>(
147
+ 'FooService',
148
+ simpleObjectSchema,
149
+ )
150
+ const boundToken = InjectionToken.bound(token, { foo: 'bar' })
151
+
152
+ expectTypeOf(boundToken.value).toMatchTypeOf<{ foo: string }>()
153
+ })
154
+
155
+ test('FactoryInjectionToken has factory property', () => {
156
+ const token = InjectionToken.create<FooService, typeof simpleObjectSchema>(
157
+ 'FooService',
158
+ simpleObjectSchema,
159
+ )
160
+ const factoryToken = InjectionToken.factory(token, async () => ({
161
+ foo: 'bar',
162
+ }))
163
+
164
+ expectTypeOf(factoryToken.factory).toBeFunction()
165
+ })
166
+
167
+ test('InjectionToken properties', () => {
168
+ const token = InjectionToken.create<FooService, typeof simpleObjectSchema>(
169
+ 'FooService',
170
+ simpleObjectSchema,
171
+ )
172
+
173
+ expectTypeOf(token.id).toBeString()
174
+ expectTypeOf(token.name).toMatchTypeOf<string | symbol | (new (...args: any[]) => any)>()
175
+ expectTypeOf(token.toString()).toBeString()
176
+ })
@@ -0,0 +1,212 @@
1
+ import { assertType, describe, test } from 'vitest'
2
+ import { z } from 'zod/v4'
3
+
4
+ import type { Factorable } from '../interfaces/index.mjs'
5
+
6
+ import { Container } from '../container/container.mjs'
7
+ import { Factory, Injectable } from '../decorators/index.mjs'
8
+ import { InjectionToken } from '../token/injection-token.mjs'
9
+
10
+ interface FooService {
11
+ makeFoo(): string
12
+ }
13
+
14
+ const simpleObjectSchema = z.object({
15
+ foo: z.string(),
16
+ })
17
+ const simpleOptionalObjectSchema = z
18
+ .object({
19
+ foo: z.string(),
20
+ })
21
+ .optional()
22
+
23
+ const typelessObjectToken = InjectionToken.create(
24
+ Symbol.for('Typeless object token'),
25
+ simpleObjectSchema,
26
+ )
27
+ const typelessOptionalObjectToken = InjectionToken.create(
28
+ Symbol.for('Typeless optional object token'),
29
+ simpleOptionalObjectSchema,
30
+ )
31
+
32
+ const typedObjectToken = InjectionToken.create<
33
+ FooService,
34
+ typeof simpleObjectSchema
35
+ >(Symbol.for('Typed object token'), simpleObjectSchema)
36
+ const typedOptionalObjectToken = InjectionToken.create<
37
+ FooService,
38
+ typeof simpleOptionalObjectSchema
39
+ >(Symbol.for('Typed optional object token'), simpleOptionalObjectSchema)
40
+
41
+ const typedToken = InjectionToken.create<FooService>(Symbol.for('Typed token'))
42
+
43
+ describe('ScopedContainer.get', () => {
44
+ describe('#1 Classes', () => {
45
+ test('simple class', async () => {
46
+ @Injectable()
47
+ class Foo {
48
+ makeFoo() {
49
+ return 'foo'
50
+ }
51
+ }
52
+
53
+ const container = new Container()
54
+ const scopedContainer = container.beginRequest('req-1')
55
+ assertType<Foo>(await scopedContainer.get(Foo))
56
+ })
57
+
58
+ test('class with required argument', async () => {
59
+ @Injectable({
60
+ schema: simpleObjectSchema,
61
+ })
62
+ class Foo {
63
+ constructor(public arg: z.infer<typeof simpleObjectSchema>) {}
64
+ }
65
+
66
+ const container = new Container()
67
+ const scopedContainer = container.beginRequest('req-1')
68
+ assertType<Foo>(await scopedContainer.get(Foo, { foo: 'bar' }))
69
+ })
70
+
71
+ test('should fail if not compatible', async () => {
72
+ @Injectable({
73
+ schema: simpleObjectSchema,
74
+ })
75
+ class Foo {
76
+ constructor(public arg: z.infer<typeof simpleObjectSchema>) {}
77
+ }
78
+
79
+ const container = new Container()
80
+ const scopedContainer = container.beginRequest('req-1')
81
+ // @ts-expect-error Should fail if not compatible
82
+ await scopedContainer.get(Foo, { test: 'bar' })
83
+ })
84
+
85
+ test('factory class returns unwrapped type', async () => {
86
+ @Factory()
87
+ class FooFactory implements Factorable<string> {
88
+ create() {
89
+ return 'created'
90
+ }
91
+ }
92
+
93
+ const container = new Container()
94
+ const scopedContainer = container.beginRequest('req-1')
95
+ // When getting a Factorable class, we get the created type, not the factory
96
+ assertType<string>(await scopedContainer.get(FooFactory))
97
+ })
98
+ })
99
+
100
+ test('#2 Token with required Schema', async () => {
101
+ const container = new Container()
102
+ const scopedContainer = container.beginRequest('req-1')
103
+
104
+ const result = await scopedContainer.get(typelessObjectToken, {
105
+ foo: 'bar',
106
+ })
107
+ assertType<unknown>(result)
108
+
109
+ const result2 = await scopedContainer.get(typedObjectToken, { foo: 'bar' })
110
+ assertType<FooService>(result2)
111
+
112
+ // @ts-expect-error We show error when we pass the wrong type
113
+ await scopedContainer.get(typedObjectToken, undefined)
114
+ })
115
+
116
+ test('#3 Token with optional Schema', async () => {
117
+ const container = new Container()
118
+ const scopedContainer = container.beginRequest('req-1')
119
+
120
+ const result = await scopedContainer.get(typelessOptionalObjectToken)
121
+ assertType<unknown>(result)
122
+
123
+ const result2 = await scopedContainer.get(typedOptionalObjectToken)
124
+ assertType<FooService>(result2)
125
+
126
+ const result3 = await scopedContainer.get(typedObjectToken)
127
+ // Special case when we pass the token without args
128
+ // We can only return an error string
129
+ assertType<'Error: Your token requires args: foo'>(result3)
130
+ })
131
+
132
+ test('#4 Token with no Schema', async () => {
133
+ const container = new Container()
134
+ const scopedContainer = container.beginRequest('req-1')
135
+
136
+ const result = await scopedContainer.get(typedToken)
137
+ assertType<FooService>(result)
138
+ })
139
+
140
+ test('#5 BoundInjectionToken', async () => {
141
+ const container = new Container()
142
+ const scopedContainer = container.beginRequest('req-1')
143
+
144
+ const boundToken = InjectionToken.bound(typedObjectToken, { foo: 'bar' })
145
+ const result = await scopedContainer.get(boundToken)
146
+ assertType<FooService>(result)
147
+ })
148
+
149
+ test('#6 FactoryInjectionToken', async () => {
150
+ const container = new Container()
151
+ const scopedContainer = container.beginRequest('req-1')
152
+
153
+ const factoryToken = InjectionToken.factory(typedObjectToken, async () => ({
154
+ foo: 'bar',
155
+ }))
156
+ const result = await scopedContainer.get(factoryToken)
157
+ assertType<FooService>(result)
158
+ })
159
+ })
160
+
161
+ describe('ScopedContainer methods', () => {
162
+ test('getRequestId returns string', () => {
163
+ const container = new Container()
164
+ const scopedContainer = container.beginRequest('req-1')
165
+ assertType<string>(scopedContainer.getRequestId())
166
+ })
167
+
168
+ test('getParent returns Container', () => {
169
+ const container = new Container()
170
+ const scopedContainer = container.beginRequest('req-1')
171
+ assertType<Container>(scopedContainer.getParent())
172
+ })
173
+
174
+ test('getMetadata returns any', () => {
175
+ const container = new Container()
176
+ const scopedContainer = container.beginRequest('req-1', { userId: '123' })
177
+ // eslint-disable-next-line @typescript-eslint/no-redundant-type-constituents
178
+ assertType<any | undefined>(scopedContainer.getMetadata('userId'))
179
+ })
180
+
181
+ test('setMetadata accepts any value', () => {
182
+ const container = new Container()
183
+ const scopedContainer = container.beginRequest('req-1')
184
+ scopedContainer.setMetadata('userId', '123')
185
+ scopedContainer.setMetadata('count', 42)
186
+ scopedContainer.setMetadata('data', { nested: true })
187
+ })
188
+
189
+ test('dispose returns Promise<void>', async () => {
190
+ const container = new Container()
191
+ const scopedContainer = container.beginRequest('req-1')
192
+ assertType<Promise<void>>(scopedContainer.dispose())
193
+ })
194
+
195
+ test('endRequest returns Promise<void>', async () => {
196
+ const container = new Container()
197
+ const scopedContainer = container.beginRequest('req-1')
198
+ assertType<Promise<void>>(scopedContainer.endRequest())
199
+ })
200
+
201
+ test('invalidate returns Promise<void>', async () => {
202
+ const container = new Container()
203
+ const scopedContainer = container.beginRequest('req-1')
204
+ assertType<Promise<void>>(scopedContainer.invalidate({}))
205
+ })
206
+
207
+ test('requestId property is string', () => {
208
+ const container = new Container()
209
+ const scopedContainer = container.beginRequest('req-1')
210
+ assertType<string>(scopedContainer.requestId)
211
+ })
212
+ })