@navios/di 0.7.1 → 0.9.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (263) hide show
  1. package/CHANGELOG.md +110 -0
  2. package/README.md +117 -17
  3. package/lib/browser/container/abstract-container.d.mts +112 -0
  4. package/lib/browser/container/abstract-container.d.mts.map +1 -0
  5. package/lib/browser/container/abstract-container.mjs +100 -0
  6. package/lib/browser/container/abstract-container.mjs.map +1 -0
  7. package/lib/browser/container/container.d.mts +100 -0
  8. package/lib/browser/container/container.d.mts.map +1 -0
  9. package/lib/browser/container/container.mjs +424 -0
  10. package/lib/browser/container/container.mjs.map +1 -0
  11. package/lib/browser/container/scoped-container.d.mts +93 -0
  12. package/lib/browser/container/scoped-container.d.mts.map +1 -0
  13. package/lib/browser/container/scoped-container.mjs +119 -0
  14. package/lib/browser/container/scoped-container.mjs.map +1 -0
  15. package/lib/browser/decorators/factory.decorator.d.mts +26 -0
  16. package/lib/browser/decorators/factory.decorator.d.mts.map +1 -0
  17. package/lib/browser/decorators/factory.decorator.mjs +20 -0
  18. package/lib/browser/decorators/factory.decorator.mjs.map +1 -0
  19. package/lib/browser/decorators/injectable.decorator.d.mts +38 -0
  20. package/lib/browser/decorators/injectable.decorator.d.mts.map +1 -0
  21. package/lib/browser/decorators/injectable.decorator.mjs +21 -0
  22. package/lib/browser/decorators/injectable.decorator.mjs.map +1 -0
  23. package/lib/browser/enums/injectable-scope.enum.d.mts +18 -0
  24. package/lib/browser/enums/injectable-scope.enum.d.mts.map +1 -0
  25. package/lib/browser/enums/injectable-scope.enum.mjs +20 -0
  26. package/lib/browser/enums/injectable-scope.enum.mjs.map +1 -0
  27. package/lib/browser/enums/injectable-type.enum.d.mts +8 -0
  28. package/lib/browser/enums/injectable-type.enum.d.mts.map +1 -0
  29. package/lib/browser/enums/injectable-type.enum.mjs +10 -0
  30. package/lib/browser/enums/injectable-type.enum.mjs.map +1 -0
  31. package/lib/browser/errors/di-error.d.mts +43 -0
  32. package/lib/browser/errors/di-error.d.mts.map +1 -0
  33. package/lib/browser/errors/di-error.mjs +98 -0
  34. package/lib/browser/errors/di-error.mjs.map +1 -0
  35. package/lib/browser/event-emitter.d.mts +16 -0
  36. package/lib/browser/event-emitter.d.mts.map +1 -0
  37. package/lib/browser/event-emitter.mjs +320 -0
  38. package/lib/browser/event-emitter.mjs.map +1 -0
  39. package/lib/browser/index.d.mts +37 -1508
  40. package/lib/browser/index.mjs +29 -2650
  41. package/lib/browser/interfaces/container.interface.d.mts +59 -0
  42. package/lib/browser/interfaces/container.interface.d.mts.map +1 -0
  43. package/lib/browser/interfaces/factory.interface.d.mts +14 -0
  44. package/lib/browser/interfaces/factory.interface.d.mts.map +1 -0
  45. package/lib/browser/interfaces/on-service-destroy.interface.d.mts +7 -0
  46. package/lib/browser/interfaces/on-service-destroy.interface.d.mts.map +1 -0
  47. package/lib/browser/interfaces/on-service-init.interface.d.mts +7 -0
  48. package/lib/browser/interfaces/on-service-init.interface.d.mts.map +1 -0
  49. package/lib/browser/internal/context/async-local-storage.browser.mjs +20 -0
  50. package/lib/browser/internal/context/async-local-storage.browser.mjs.map +1 -0
  51. package/lib/browser/internal/context/async-local-storage.d.mts +9 -0
  52. package/lib/browser/internal/context/async-local-storage.d.mts.map +1 -0
  53. package/lib/browser/internal/context/async-local-storage.types.d.mts +11 -0
  54. package/lib/browser/internal/context/async-local-storage.types.d.mts.map +1 -0
  55. package/lib/browser/internal/context/factory-context.d.mts +23 -0
  56. package/lib/browser/internal/context/factory-context.d.mts.map +1 -0
  57. package/lib/browser/internal/context/resolution-context.d.mts +43 -0
  58. package/lib/browser/internal/context/resolution-context.d.mts.map +1 -0
  59. package/lib/browser/internal/context/resolution-context.mjs +56 -0
  60. package/lib/browser/internal/context/resolution-context.mjs.map +1 -0
  61. package/lib/browser/internal/context/service-initialization-context.d.mts +48 -0
  62. package/lib/browser/internal/context/service-initialization-context.d.mts.map +1 -0
  63. package/lib/browser/internal/context/sync-local-storage.mjs +53 -0
  64. package/lib/browser/internal/context/sync-local-storage.mjs.map +1 -0
  65. package/lib/browser/internal/core/instance-resolver.d.mts +119 -0
  66. package/lib/browser/internal/core/instance-resolver.d.mts.map +1 -0
  67. package/lib/browser/internal/core/instance-resolver.mjs +306 -0
  68. package/lib/browser/internal/core/instance-resolver.mjs.map +1 -0
  69. package/lib/browser/internal/core/name-resolver.d.mts +52 -0
  70. package/lib/browser/internal/core/name-resolver.d.mts.map +1 -0
  71. package/lib/browser/internal/core/name-resolver.mjs +118 -0
  72. package/lib/browser/internal/core/name-resolver.mjs.map +1 -0
  73. package/lib/browser/internal/core/scope-tracker.d.mts +65 -0
  74. package/lib/browser/internal/core/scope-tracker.d.mts.map +1 -0
  75. package/lib/browser/internal/core/scope-tracker.mjs +120 -0
  76. package/lib/browser/internal/core/scope-tracker.mjs.map +1 -0
  77. package/lib/browser/internal/core/service-initializer.d.mts +44 -0
  78. package/lib/browser/internal/core/service-initializer.d.mts.map +1 -0
  79. package/lib/browser/internal/core/service-initializer.mjs +109 -0
  80. package/lib/browser/internal/core/service-initializer.mjs.map +1 -0
  81. package/lib/browser/internal/core/service-invalidator.d.mts +81 -0
  82. package/lib/browser/internal/core/service-invalidator.d.mts.map +1 -0
  83. package/lib/browser/internal/core/service-invalidator.mjs +142 -0
  84. package/lib/browser/internal/core/service-invalidator.mjs.map +1 -0
  85. package/lib/browser/internal/core/token-resolver.d.mts +54 -0
  86. package/lib/browser/internal/core/token-resolver.d.mts.map +1 -0
  87. package/lib/browser/internal/core/token-resolver.mjs +77 -0
  88. package/lib/browser/internal/core/token-resolver.mjs.map +1 -0
  89. package/lib/browser/internal/holder/holder-storage.interface.d.mts +99 -0
  90. package/lib/browser/internal/holder/holder-storage.interface.d.mts.map +1 -0
  91. package/lib/browser/internal/holder/instance-holder.d.mts +101 -0
  92. package/lib/browser/internal/holder/instance-holder.d.mts.map +1 -0
  93. package/lib/browser/internal/holder/instance-holder.mjs +19 -0
  94. package/lib/browser/internal/holder/instance-holder.mjs.map +1 -0
  95. package/lib/browser/internal/holder/unified-storage.d.mts +53 -0
  96. package/lib/browser/internal/holder/unified-storage.d.mts.map +1 -0
  97. package/lib/browser/internal/holder/unified-storage.mjs +144 -0
  98. package/lib/browser/internal/holder/unified-storage.mjs.map +1 -0
  99. package/lib/browser/internal/lifecycle/circular-detector.d.mts +39 -0
  100. package/lib/browser/internal/lifecycle/circular-detector.d.mts.map +1 -0
  101. package/lib/browser/internal/lifecycle/circular-detector.mjs +55 -0
  102. package/lib/browser/internal/lifecycle/circular-detector.mjs.map +1 -0
  103. package/lib/browser/internal/lifecycle/lifecycle-event-bus.d.mts +18 -0
  104. package/lib/browser/internal/lifecycle/lifecycle-event-bus.d.mts.map +1 -0
  105. package/lib/browser/internal/lifecycle/lifecycle-event-bus.mjs +43 -0
  106. package/lib/browser/internal/lifecycle/lifecycle-event-bus.mjs.map +1 -0
  107. package/lib/browser/internal/stub-factory-class.d.mts +14 -0
  108. package/lib/browser/internal/stub-factory-class.d.mts.map +1 -0
  109. package/lib/browser/internal/stub-factory-class.mjs +18 -0
  110. package/lib/browser/internal/stub-factory-class.mjs.map +1 -0
  111. package/lib/browser/symbols/injectable-token.d.mts +5 -0
  112. package/lib/browser/symbols/injectable-token.d.mts.map +1 -0
  113. package/lib/browser/symbols/injectable-token.mjs +6 -0
  114. package/lib/browser/symbols/injectable-token.mjs.map +1 -0
  115. package/lib/browser/token/injection-token.d.mts +55 -0
  116. package/lib/browser/token/injection-token.d.mts.map +1 -0
  117. package/lib/browser/token/injection-token.mjs +100 -0
  118. package/lib/browser/token/injection-token.mjs.map +1 -0
  119. package/lib/browser/token/registry.d.mts +37 -0
  120. package/lib/browser/token/registry.d.mts.map +1 -0
  121. package/lib/browser/token/registry.mjs +86 -0
  122. package/lib/browser/token/registry.mjs.map +1 -0
  123. package/lib/browser/utils/default-injectors.d.mts +12 -0
  124. package/lib/browser/utils/default-injectors.d.mts.map +1 -0
  125. package/lib/browser/utils/default-injectors.mjs +13 -0
  126. package/lib/browser/utils/default-injectors.mjs.map +1 -0
  127. package/lib/browser/utils/get-injectable-token.d.mts +9 -0
  128. package/lib/browser/utils/get-injectable-token.d.mts.map +1 -0
  129. package/lib/browser/utils/get-injectable-token.mjs +13 -0
  130. package/lib/browser/utils/get-injectable-token.mjs.map +1 -0
  131. package/lib/browser/utils/get-injectors.d.mts +55 -0
  132. package/lib/browser/utils/get-injectors.d.mts.map +1 -0
  133. package/lib/browser/utils/get-injectors.mjs +121 -0
  134. package/lib/browser/utils/get-injectors.mjs.map +1 -0
  135. package/lib/browser/utils/types.d.mts +23 -0
  136. package/lib/browser/utils/types.d.mts.map +1 -0
  137. package/lib/{container-Pb_Y4Z4x.mjs → container-8-z89TyQ.mjs} +1269 -1305
  138. package/lib/container-8-z89TyQ.mjs.map +1 -0
  139. package/lib/{container-BuAutHGg.d.mts → container-CNiqesCL.d.mts} +600 -569
  140. package/lib/container-CNiqesCL.d.mts.map +1 -0
  141. package/lib/{container-DnzgpfBe.cjs → container-CaY2fDuk.cjs} +1287 -1329
  142. package/lib/container-CaY2fDuk.cjs.map +1 -0
  143. package/lib/{container-oGTgX2iX.d.cts → container-D-0Ho3qL.d.cts} +601 -565
  144. package/lib/container-D-0Ho3qL.d.cts.map +1 -0
  145. package/lib/index.cjs +13 -15
  146. package/lib/index.cjs.map +1 -1
  147. package/lib/index.d.cts +58 -223
  148. package/lib/index.d.cts.map +1 -1
  149. package/lib/index.d.mts +62 -222
  150. package/lib/index.d.mts.map +1 -1
  151. package/lib/index.mjs +5 -6
  152. package/lib/index.mjs.map +1 -1
  153. package/lib/testing/index.cjs +569 -311
  154. package/lib/testing/index.cjs.map +1 -1
  155. package/lib/testing/index.d.cts +370 -41
  156. package/lib/testing/index.d.cts.map +1 -1
  157. package/lib/testing/index.d.mts +370 -41
  158. package/lib/testing/index.d.mts.map +1 -1
  159. package/lib/testing/index.mjs +568 -305
  160. package/lib/testing/index.mjs.map +1 -1
  161. package/package.json +2 -1
  162. package/src/__tests__/circular-detector.spec.mts +193 -0
  163. package/src/__tests__/concurrent.spec.mts +368 -0
  164. package/src/__tests__/container.spec.mts +32 -30
  165. package/src/__tests__/di-error.spec.mts +351 -0
  166. package/src/__tests__/e2e.browser.spec.mts +0 -4
  167. package/src/__tests__/e2e.spec.mts +10 -19
  168. package/src/__tests__/event-emitter.spec.mts +232 -109
  169. package/src/__tests__/get-injectors.spec.mts +250 -39
  170. package/src/__tests__/injection-token.spec.mts +293 -349
  171. package/src/__tests__/library-findings.spec.mts +8 -8
  172. package/src/__tests__/registry.spec.mts +358 -210
  173. package/src/__tests__/resolution-context.spec.mts +255 -0
  174. package/src/__tests__/scope-tracker.spec.mts +598 -0
  175. package/src/__tests__/scope-upgrade.spec.mts +808 -0
  176. package/src/__tests__/scoped-container.spec.mts +595 -0
  177. package/src/__tests__/test-container.spec.mts +293 -0
  178. package/src/__tests__/token-resolver.spec.mts +207 -0
  179. package/src/__tests__/unified-storage.spec.mts +535 -0
  180. package/src/__tests__/unit-test-container.spec.mts +405 -0
  181. package/src/__type-tests__/container.spec-d.mts +180 -0
  182. package/src/__type-tests__/factory.spec-d.mts +15 -3
  183. package/src/__type-tests__/inject.spec-d.mts +115 -20
  184. package/src/__type-tests__/injectable.spec-d.mts +69 -52
  185. package/src/__type-tests__/injection-token.spec-d.mts +176 -0
  186. package/src/__type-tests__/scoped-container.spec-d.mts +212 -0
  187. package/src/container/abstract-container.mts +327 -0
  188. package/src/container/container.mts +142 -170
  189. package/src/container/scoped-container.mts +126 -208
  190. package/src/decorators/factory.decorator.mts +16 -11
  191. package/src/decorators/injectable.decorator.mts +20 -16
  192. package/src/enums/index.mts +2 -2
  193. package/src/enums/injectable-scope.enum.mts +1 -0
  194. package/src/enums/injectable-type.enum.mts +1 -0
  195. package/src/errors/di-error.mts +96 -0
  196. package/src/event-emitter.mts +3 -27
  197. package/src/index.mts +6 -153
  198. package/src/interfaces/container.interface.mts +13 -0
  199. package/src/interfaces/factory.interface.mts +1 -1
  200. package/src/interfaces/index.mts +1 -1
  201. package/src/internal/context/async-local-storage.mts +3 -2
  202. package/src/internal/context/async-local-storage.types.mts +1 -0
  203. package/src/internal/context/factory-context.mts +1 -0
  204. package/src/internal/context/index.mts +3 -1
  205. package/src/internal/context/resolution-context.mts +1 -0
  206. package/src/internal/context/service-initialization-context.mts +43 -0
  207. package/src/internal/core/index.mts +5 -4
  208. package/src/internal/core/instance-resolver.mts +461 -292
  209. package/src/internal/core/name-resolver.mts +196 -0
  210. package/src/internal/core/scope-tracker.mts +242 -0
  211. package/src/internal/core/{instantiator.mts → service-initializer.mts} +51 -29
  212. package/src/internal/core/service-invalidator.mts +290 -0
  213. package/src/internal/core/{token-processor.mts → token-resolver.mts} +17 -88
  214. package/src/internal/holder/holder-storage.interface.mts +11 -5
  215. package/src/internal/holder/index.mts +2 -5
  216. package/src/internal/holder/instance-holder.mts +1 -3
  217. package/src/internal/holder/unified-storage.mts +245 -0
  218. package/src/internal/index.mts +2 -1
  219. package/src/internal/lifecycle/circular-detector.mts +1 -0
  220. package/src/internal/lifecycle/index.mts +1 -1
  221. package/src/internal/lifecycle/lifecycle-event-bus.mts +1 -0
  222. package/src/internal/stub-factory-class.mts +16 -0
  223. package/src/symbols/injectable-token.mts +3 -1
  224. package/src/testing/index.mts +2 -0
  225. package/src/testing/test-container.mts +546 -85
  226. package/src/testing/types.mts +117 -0
  227. package/src/testing/unit-test-container.mts +509 -0
  228. package/src/token/injection-token.mts +41 -4
  229. package/src/token/registry.mts +75 -9
  230. package/src/utils/default-injectors.mts +16 -0
  231. package/src/utils/get-injectable-token.mts +2 -3
  232. package/src/utils/get-injectors.mts +26 -15
  233. package/src/utils/index.mts +3 -1
  234. package/src/utils/types.mts +1 -0
  235. package/tsdown.config.mts +11 -1
  236. package/lib/browser/index.d.mts.map +0 -1
  237. package/lib/browser/index.mjs.map +0 -1
  238. package/lib/container-BuAutHGg.d.mts.map +0 -1
  239. package/lib/container-DnzgpfBe.cjs.map +0 -1
  240. package/lib/container-Pb_Y4Z4x.mjs.map +0 -1
  241. package/lib/container-oGTgX2iX.d.cts.map +0 -1
  242. package/src/__tests__/async-local-storage.browser.spec.mts +0 -166
  243. package/src/__tests__/async-local-storage.spec.mts +0 -333
  244. package/src/__tests__/errors.spec.mts +0 -87
  245. package/src/__tests__/factory.spec.mts +0 -137
  246. package/src/__tests__/injectable.spec.mts +0 -246
  247. package/src/__tests__/request-scope.spec.mts +0 -416
  248. package/src/__tests__/service-instantiator.spec.mts +0 -410
  249. package/src/__tests__/service-locator-event-bus.spec.mts +0 -242
  250. package/src/__tests__/service-locator-manager.spec.mts +0 -300
  251. package/src/__tests__/service-locator.spec.mts +0 -966
  252. package/src/__tests__/unified-api.spec.mts +0 -130
  253. package/src/browser.mts +0 -11
  254. package/src/injectors.mts +0 -18
  255. package/src/internal/context/request-context.mts +0 -214
  256. package/src/internal/core/invalidator.mts +0 -437
  257. package/src/internal/core/service-locator.mts +0 -202
  258. package/src/internal/holder/base-holder-manager.mts +0 -238
  259. package/src/internal/holder/holder-manager.mts +0 -85
  260. package/src/internal/holder/request-storage.mts +0 -134
  261. package/src/internal/holder/singleton-storage.mts +0 -105
  262. package/src/testing/README.md +0 -80
  263. package/src/testing/__tests__/test-container.spec.mts +0 -173
@@ -1,238 +0,0 @@
1
- import type { InstanceHolder } from './instance-holder.mjs'
2
-
3
- import { InjectableScope, InjectableType } from '../../enums/index.mjs'
4
- import { DIError } from '../../errors/index.mjs'
5
- import { CircularDetector } from '../lifecycle/circular-detector.mjs'
6
- import { InstanceStatus } from './instance-holder.mjs'
7
-
8
- /**
9
- * Result type for waitForHolderReady.
10
- * Returns either [undefined, holder] on success or [error] on failure.
11
- */
12
- export type HolderReadyResult<T> = [undefined, InstanceHolder<T>] | [DIError]
13
-
14
- /**
15
- * Abstract base class providing common functionality for managing InstanceHolder objects.
16
- *
17
- * Provides shared patterns for holder storage, creation, and lifecycle management
18
- * used by both singleton (HolderManager) and request-scoped (RequestContext) managers.
19
- */
20
- export abstract class BaseHolderManager {
21
- protected readonly _holders: Map<string, InstanceHolder>
22
-
23
- constructor(protected readonly logger: Console | null = null) {
24
- this._holders = new Map()
25
- }
26
-
27
- /**
28
- * Protected getter for accessing the holders map from subclasses.
29
- */
30
- protected get holders(): Map<string, InstanceHolder> {
31
- return this._holders
32
- }
33
-
34
- /**
35
- * Abstract method to get a holder by name. Each implementation defines its own return type
36
- * based on their specific error handling and validation needs.
37
- */
38
- abstract get(name: string): any
39
-
40
- /**
41
- * Abstract method to set a holder by name. Each implementation may have different validation logic.
42
- */
43
- abstract set(name: string, holder: InstanceHolder): void
44
-
45
- /**
46
- * Abstract method to check if a holder exists. Each implementation may have different validation logic.
47
- */
48
- abstract has(name: string): any
49
-
50
- /**
51
- * Deletes a holder by name.
52
- * @param name The name of the holder to delete
53
- * @returns true if the holder was deleted, false if it didn't exist
54
- */
55
- delete(name: string): boolean {
56
- return this._holders.delete(name)
57
- }
58
-
59
- /**
60
- * Filters holders based on a predicate function.
61
- * @param predicate Function to test each holder
62
- * @returns A new Map containing only the holders that match the predicate
63
- */
64
- filter(
65
- predicate: (value: InstanceHolder<any>, key: string) => boolean,
66
- ): Map<string, InstanceHolder> {
67
- return new Map(
68
- [...this._holders].filter(([key, value]) => predicate(value, key)),
69
- )
70
- }
71
-
72
- /**
73
- * Clears all holders from this manager.
74
- */
75
- clear(): void {
76
- this._holders.clear()
77
- }
78
-
79
- /**
80
- * Gets the number of holders currently managed.
81
- */
82
- size(): number {
83
- return this._holders.size
84
- }
85
-
86
- /**
87
- * Creates a new holder with Creating status and a deferred creation promise.
88
- * This is useful for creating placeholder holders that can be fulfilled later.
89
- * @param name The name of the instance
90
- * @param type The injectable type
91
- * @param scope The injectable scope
92
- * @param deps Optional set of dependencies
93
- * @returns A tuple containing the deferred promise and the holder
94
- */
95
- createCreatingHolder<Instance>(
96
- name: string,
97
- type: InjectableType,
98
- scope: InjectableScope,
99
- deps: Set<string> = new Set(),
100
- ): [
101
- ReturnType<typeof Promise.withResolvers<[undefined, Instance]>>,
102
- InstanceHolder<Instance>,
103
- ] {
104
- const deferred = Promise.withResolvers<[undefined, Instance]>()
105
-
106
- const holder: InstanceHolder<Instance> = {
107
- status: InstanceStatus.Creating,
108
- name,
109
- instance: null,
110
- creationPromise: deferred.promise,
111
- destroyPromise: null,
112
- type,
113
- scope,
114
- deps,
115
- destroyListeners: [],
116
- createdAt: Date.now(),
117
- waitingFor: new Set(),
118
- }
119
-
120
- return [deferred, holder]
121
- }
122
-
123
- /**
124
- * Creates a new holder with Created status and an actual instance.
125
- * This is useful for creating holders that already have their instance ready.
126
- * @param name The name of the instance
127
- * @param instance The actual instance to store
128
- * @param type The injectable type
129
- * @param scope The injectable scope
130
- * @param deps Optional set of dependencies
131
- * @returns The created holder
132
- */
133
- protected createCreatedHolder<Instance>(
134
- name: string,
135
- instance: Instance,
136
- type: InjectableType,
137
- scope: InjectableScope,
138
- deps: Set<string> = new Set(),
139
- ): InstanceHolder<Instance> {
140
- const holder: InstanceHolder<Instance> = {
141
- status: InstanceStatus.Created,
142
- name,
143
- instance,
144
- creationPromise: null,
145
- destroyPromise: null,
146
- type,
147
- scope,
148
- deps,
149
- destroyListeners: [],
150
- createdAt: Date.now(),
151
- waitingFor: new Set(),
152
- }
153
-
154
- return holder
155
- }
156
-
157
- /**
158
- * Gets all holder names currently managed.
159
- */
160
- getAllNames(): string[] {
161
- return Array.from(this._holders.keys())
162
- }
163
-
164
- /**
165
- * Gets all holders currently managed.
166
- */
167
- getAllHolders(): InstanceHolder[] {
168
- return Array.from(this._holders.values())
169
- }
170
-
171
- /**
172
- * Checks if this manager has any holders.
173
- */
174
- isEmpty(): boolean {
175
- return this._holders.size === 0
176
- }
177
-
178
- /**
179
- * Waits for a holder to be ready and returns the appropriate result.
180
- * This is a shared utility used by both singleton and request-scoped resolution.
181
- *
182
- * @param holder The holder to wait for
183
- * @param waiterHolder Optional holder that is doing the waiting (for circular dependency detection)
184
- * @param getHolder Optional function to retrieve holders by name (required if waiterHolder is provided)
185
- * @returns A promise that resolves with [undefined, holder] on success or [DIError] on failure
186
- */
187
- static async waitForHolderReady<T>(
188
- holder: InstanceHolder<T>,
189
- waiterHolder?: InstanceHolder,
190
- getHolder?: (name: string) => InstanceHolder | undefined,
191
- ): Promise<HolderReadyResult<T>> {
192
- switch (holder.status) {
193
- case InstanceStatus.Creating: {
194
- // Check for circular dependency before waiting
195
- if (waiterHolder && getHolder) {
196
- const cycle = CircularDetector.detectCycle(
197
- waiterHolder.name,
198
- holder.name,
199
- getHolder,
200
- )
201
- if (cycle) {
202
- return [DIError.circularDependency(cycle)]
203
- }
204
-
205
- // Track the waiting relationship
206
- waiterHolder.waitingFor.add(holder.name)
207
- }
208
-
209
- try {
210
- await holder.creationPromise
211
- } finally {
212
- // Clean up the waiting relationship
213
- if (waiterHolder) {
214
- waiterHolder.waitingFor.delete(holder.name)
215
- }
216
- }
217
-
218
- return BaseHolderManager.waitForHolderReady(
219
- holder,
220
- waiterHolder,
221
- getHolder,
222
- )
223
- }
224
-
225
- case InstanceStatus.Destroying:
226
- return [DIError.instanceDestroying(holder.name)]
227
-
228
- case InstanceStatus.Error:
229
- return [holder.instance as unknown as DIError]
230
-
231
- case InstanceStatus.Created:
232
- return [undefined, holder]
233
-
234
- default:
235
- return [DIError.instanceNotFound('unknown')]
236
- }
237
- }
238
- }
@@ -1,85 +0,0 @@
1
- import type { InstanceHolder } from './instance-holder.mjs'
2
-
3
- import { InjectableScope, InjectableType } from '../../enums/index.mjs'
4
- import { DIError, DIErrorCode } from '../../errors/index.mjs'
5
- import { BaseHolderManager } from './base-holder-manager.mjs'
6
- import { InstanceStatus } from './instance-holder.mjs'
7
-
8
- /**
9
- * Manages the storage and retrieval of singleton instance holders.
10
- *
11
- * Provides CRUD operations and filtering for the holder map.
12
- * Handles holder state validation (destroying, error states) on retrieval.
13
- */
14
- export class HolderManager extends BaseHolderManager {
15
- constructor(logger: Console | null = null) {
16
- super(logger)
17
- }
18
-
19
- get(
20
- name: string,
21
- ): [DIError, InstanceHolder] | [DIError] | [undefined, InstanceHolder] {
22
- const holder = this._holders.get(name)
23
- if (holder) {
24
- if (holder.status === InstanceStatus.Destroying) {
25
- this.logger?.log(
26
- `[HolderManager]#get() Instance ${holder.name} is destroying`,
27
- )
28
- return [DIError.instanceDestroying(holder.name), holder]
29
- } else if (holder.status === InstanceStatus.Error) {
30
- this.logger?.log(
31
- `[HolderManager]#get() Instance ${holder.name} is in error state`,
32
- )
33
- return [holder.instance as unknown as DIError, holder]
34
- }
35
-
36
- return [undefined, holder]
37
- } else {
38
- this.logger?.log(`[HolderManager]#get() Instance ${name} not found`)
39
- return [DIError.instanceNotFound(name)]
40
- }
41
- }
42
-
43
- set(name: string, holder: InstanceHolder): void {
44
- this._holders.set(name, holder)
45
- }
46
-
47
- has(name: string): [DIError] | [undefined, boolean] {
48
- const [error, holder] = this.get(name)
49
- if (!error) {
50
- return [undefined, true]
51
- }
52
- if (error.code === DIErrorCode.InstanceDestroying) {
53
- return [error]
54
- }
55
- return [undefined, !!holder]
56
- }
57
-
58
- // delete and filter methods are inherited from BaseHolderManager
59
-
60
- // createCreatingHolder method is inherited from BaseHolderManager
61
-
62
- /**
63
- * Creates a new holder with Created status and stores it.
64
- * This is useful for creating holders that already have their instance ready.
65
- * @param name The name of the instance
66
- * @param instance The actual instance to store
67
- * @param type The injectable type
68
- * @param scope The injectable scope
69
- * @param deps Optional set of dependencies
70
- * @returns The created holder
71
- */
72
- storeCreatedHolder<Instance>(
73
- name: string,
74
- instance: Instance,
75
- type: InjectableType,
76
- scope: InjectableScope,
77
- deps: Set<string> = new Set(),
78
- ): InstanceHolder<Instance> {
79
- const holder = this.createCreatedHolder(name, instance, type, scope, deps)
80
-
81
- this._holders.set(name, holder)
82
-
83
- return holder
84
- }
85
- }
@@ -1,134 +0,0 @@
1
- import type { RequestContext } from '../context/request-context.mjs'
2
- import type { BaseHolderManager } from './base-holder-manager.mjs'
3
- import type {
4
- HolderGetResult,
5
- IHolderStorage,
6
- } from './holder-storage.interface.mjs'
7
- import type { InstanceHolder } from './instance-holder.mjs'
8
-
9
- import { InjectableScope, InjectableType } from '../../enums/index.mjs'
10
- import { DIError } from '../../errors/index.mjs'
11
- import { InstanceStatus } from './instance-holder.mjs'
12
-
13
- /**
14
- * Storage implementation for Request-scoped services.
15
- *
16
- * Wraps a RequestContext instance from a ScopedContainer and provides
17
- * the IHolderStorage interface. This allows the InstanceResolver to work
18
- * with request-scoped storage using the same interface as singleton storage.
19
- */
20
- export class RequestStorage implements IHolderStorage {
21
- readonly scope = InjectableScope.Request
22
-
23
- constructor(
24
- private readonly contextHolder: RequestContext,
25
- private readonly holderManager: BaseHolderManager,
26
- ) {}
27
-
28
- get<T = unknown>(instanceName: string): HolderGetResult<T> {
29
- const holder = this.contextHolder.get(instanceName)
30
-
31
- if (!holder) {
32
- return null
33
- }
34
-
35
- // Check holder status for error states
36
- switch (holder.status) {
37
- case InstanceStatus.Destroying:
38
- return [
39
- DIError.instanceDestroying(instanceName),
40
- holder as InstanceHolder<T>,
41
- ]
42
-
43
- case InstanceStatus.Error:
44
- return [
45
- holder.instance as unknown as DIError,
46
- holder as InstanceHolder<T>,
47
- ]
48
-
49
- case InstanceStatus.Creating:
50
- case InstanceStatus.Created:
51
- return [undefined, holder as InstanceHolder<T>]
52
-
53
- default:
54
- return null
55
- }
56
- }
57
-
58
- set(instanceName: string, holder: InstanceHolder): void {
59
- this.contextHolder.set(instanceName, holder)
60
- }
61
-
62
- delete(instanceName: string): boolean {
63
- return this.contextHolder.delete(instanceName)
64
- }
65
-
66
- createHolder<T>(
67
- instanceName: string,
68
- type: InjectableType,
69
- deps: Set<string>,
70
- ): [
71
- ReturnType<typeof Promise.withResolvers<[undefined, T]>>,
72
- InstanceHolder<T>,
73
- ] {
74
- // Use the holderManager's createCreatingHolder method
75
- // which is inherited from BaseHolderManager
76
- return this.holderManager.createCreatingHolder<T>(
77
- instanceName,
78
- type,
79
- this.scope,
80
- deps,
81
- )
82
- }
83
-
84
- handles(scope: InjectableScope): boolean {
85
- return scope === InjectableScope.Request
86
- }
87
-
88
- // ============================================================================
89
- // ITERATION AND QUERY
90
- // ============================================================================
91
-
92
- getAllNames(): string[] {
93
- const names: string[] = []
94
- for (const [name] of this.contextHolder.holders) {
95
- names.push(name)
96
- }
97
- return names
98
- }
99
-
100
- forEach(callback: (name: string, holder: InstanceHolder) => void): void {
101
- for (const [name, holder] of this.contextHolder.holders) {
102
- callback(name, holder)
103
- }
104
- }
105
-
106
- findByInstance(instance: unknown): InstanceHolder | null {
107
- for (const holder of this.contextHolder.holders.values()) {
108
- if (holder.instance === instance) {
109
- return holder
110
- }
111
- }
112
- return null
113
- }
114
-
115
- findDependents(instanceName: string): string[] {
116
- const dependents: string[] = []
117
-
118
- // Check request-scoped holders
119
- for (const [name, holder] of this.contextHolder.holders) {
120
- if (holder.deps.has(instanceName)) {
121
- dependents.push(name)
122
- }
123
- }
124
-
125
- // Also check singleton holders - a singleton may depend on this request-scoped service
126
- for (const [name, holder] of this.holderManager.filter(() => true)) {
127
- if (holder.deps.has(instanceName)) {
128
- dependents.push(name)
129
- }
130
- }
131
-
132
- return dependents
133
- }
134
- }
@@ -1,105 +0,0 @@
1
- import type { HolderManager } from './holder-manager.mjs'
2
- import type {
3
- HolderGetResult,
4
- IHolderStorage,
5
- } from './holder-storage.interface.mjs'
6
- import type { InstanceHolder } from './instance-holder.mjs'
7
-
8
- import { InjectableScope, InjectableType } from '../../enums/index.mjs'
9
- import { DIErrorCode } from '../../errors/index.mjs'
10
-
11
- /**
12
- * Storage implementation for Singleton-scoped services.
13
- *
14
- * Wraps a HolderManager instance and provides the IHolderStorage interface.
15
- * This allows the InstanceResolver to work with singleton storage
16
- * using the same interface as request-scoped storage.
17
- */
18
- export class SingletonStorage implements IHolderStorage {
19
- readonly scope = InjectableScope.Singleton
20
-
21
- constructor(private readonly manager: HolderManager) {}
22
-
23
- get<T = unknown>(instanceName: string): HolderGetResult<T> {
24
- const [error, holder] = this.manager.get(instanceName)
25
-
26
- if (!error) {
27
- return [undefined, holder as InstanceHolder<T>]
28
- }
29
-
30
- // Handle different error types
31
- switch (error.code) {
32
- case DIErrorCode.InstanceNotFound:
33
- return null
34
-
35
- case DIErrorCode.InstanceDestroying:
36
- return [error, holder as InstanceHolder<T> | undefined]
37
-
38
- default:
39
- return [error]
40
- }
41
- }
42
-
43
- set(instanceName: string, holder: InstanceHolder): void {
44
- this.manager.set(instanceName, holder)
45
- }
46
-
47
- delete(instanceName: string): boolean {
48
- return this.manager.delete(instanceName)
49
- }
50
-
51
- createHolder<T>(
52
- instanceName: string,
53
- type: InjectableType,
54
- deps: Set<string>,
55
- ): [
56
- ReturnType<typeof Promise.withResolvers<[undefined, T]>>,
57
- InstanceHolder<T>,
58
- ] {
59
- return this.manager.createCreatingHolder<T>(
60
- instanceName,
61
- type,
62
- this.scope,
63
- deps,
64
- )
65
- }
66
-
67
- handles(scope: InjectableScope): boolean {
68
- return scope === InjectableScope.Singleton
69
- }
70
-
71
- // ============================================================================
72
- // ITERATION AND QUERY
73
- // ============================================================================
74
-
75
- getAllNames(): string[] {
76
- return this.manager.getAllNames()
77
- }
78
-
79
- forEach(
80
- callback: (name: string, holder: InstanceHolder) => void,
81
- ): void {
82
- for (const [name, holder] of this.manager.filter(() => true)) {
83
- callback(name, holder)
84
- }
85
- }
86
-
87
- findByInstance(instance: unknown): InstanceHolder | null {
88
- for (const [, holder] of this.manager.filter(
89
- (h) => h.instance === instance,
90
- )) {
91
- return holder
92
- }
93
- return null
94
- }
95
-
96
- findDependents(instanceName: string): string[] {
97
- const dependents: string[] = []
98
- for (const [name, holder] of this.manager.filter(() => true)) {
99
- if (holder.deps.has(instanceName)) {
100
- dependents.push(name)
101
- }
102
- }
103
- return dependents
104
- }
105
- }
@@ -1,80 +0,0 @@
1
- # Testing Infrastructure
2
-
3
- The `@navios/di/testing` package provides a `TestContainer` class that extends the base `Container` with additional methods useful for testing.
4
-
5
- ## Features
6
-
7
- - **TestContainer**: A specialized container for testing with simplified binding methods
8
- - **bind().toValue()**: Bind tokens to specific values (useful for mocks)
9
- - **bind().toClass()**: Bind tokens to class constructors
10
- - **clear()**: Clear all instances and bindings from the container
11
- - **Convenience methods**: `bindValue()`, `bindClass()`, `createChild()`
12
-
13
- ## Usage
14
-
15
- ```typescript
16
- import { Injectable, InjectionToken } from '@navios/di'
17
- import { TestContainer } from '@navios/di/testing'
18
-
19
- // Create a test container
20
- const container = new TestContainer()
21
-
22
- // Create injection tokens
23
- const API_URL_TOKEN = InjectionToken.create<string>('api-url')
24
- const HTTP_CLIENT_TOKEN = InjectionToken.create<HttpClient>('http-client')
25
-
26
- // Mock implementations
27
- class MockHttpClient implements HttpClient {
28
- async get(url: string) {
29
- return { data: 'mocked response' }
30
- }
31
- }
32
-
33
- // Bind values for testing
34
- container.bindValue(API_URL_TOKEN, 'https://test-api.com')
35
- container.bindClass(HTTP_CLIENT_TOKEN, MockHttpClient)
36
-
37
- // Or use the fluent API
38
- container.bind(API_URL_TOKEN).toValue('https://test-api.com')
39
-
40
- container.bind(HTTP_CLIENT_TOKEN).toClass(MockHttpClient)
41
-
42
- // Bind a class to itself
43
- @Injectable()
44
- class UserService {
45
- constructor(
46
- @Inject(API_URL_TOKEN) private apiUrl: string,
47
- @Inject(HTTP_CLIENT_TOKEN) private httpClient: HttpClient,
48
- ) {}
49
- }
50
-
51
- container.bindSelf(UserService)
52
-
53
- // Clear the container between tests
54
- container.clear()
55
-
56
- // Create isolated child containers
57
- const childContainer = container.createChild()
58
- ```
59
-
60
- ## API Reference
61
-
62
- ### TestContainer
63
-
64
- #### Methods
65
-
66
- - `bind<T>(token: InjectionToken<T, any>): TestBindingBuilder<T>` - Creates a binding builder
67
- - `bind<T>(token: ClassType): TestBindingBuilder<T>` - Creates a binding builder
68
- - `bindValue<T>(token: InjectionToken<T, any>, value: T): TestContainer` - Binds a value to a token
69
- - `bindValue<T>(token: ClassType, value: T): TestContainer` - Binds a value to a token
70
- - `bindClass<T>(token: InjectionToken<T, any>, target: ClassType): TestContainer` - Binds a class to a token
71
- - `bindClass<T>(token: ClassType, target: ClassType): TestContainer` - Binds a class to a token
72
- - `createChild(): TestContainer` - Creates a new isolated test container
73
- - `clear(): void` - Clears all instances and bindings
74
-
75
- ### TestBindingBuilder
76
-
77
- #### Methods
78
-
79
- - `toValue(value: T): TestContainer` - Binds the token to a specific value
80
- - `toClass(target: ClassType): TestContainer` - Binds the token to a class constructor