@navios/di 0.5.1 → 0.6.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 (123) hide show
  1. package/CHANGELOG.md +146 -0
  2. package/README.md +196 -219
  3. package/docs/README.md +69 -11
  4. package/docs/api-reference.md +281 -117
  5. package/docs/container.md +220 -56
  6. package/docs/examples/request-scope-example.mts +2 -2
  7. package/docs/factory.md +3 -8
  8. package/docs/getting-started.md +37 -8
  9. package/docs/migration.md +318 -37
  10. package/docs/request-contexts.md +263 -175
  11. package/docs/scopes.md +79 -42
  12. package/lib/browser/index.d.mts +1577 -0
  13. package/lib/browser/index.d.mts.map +1 -0
  14. package/lib/browser/index.mjs +3012 -0
  15. package/lib/browser/index.mjs.map +1 -0
  16. package/lib/index-S_qX2VLI.d.mts +1211 -0
  17. package/lib/index-S_qX2VLI.d.mts.map +1 -0
  18. package/lib/index-fKPuT65j.d.cts +1206 -0
  19. package/lib/index-fKPuT65j.d.cts.map +1 -0
  20. package/lib/index.cjs +389 -0
  21. package/lib/index.cjs.map +1 -0
  22. package/lib/index.d.cts +376 -0
  23. package/lib/index.d.cts.map +1 -0
  24. package/lib/index.d.mts +371 -78
  25. package/lib/index.d.mts.map +1 -0
  26. package/lib/index.mjs +325 -63
  27. package/lib/index.mjs.map +1 -1
  28. package/lib/testing/index.cjs +9 -0
  29. package/lib/testing/index.d.cts +2 -0
  30. package/lib/testing/index.d.mts +2 -2
  31. package/lib/testing/index.mjs +2 -72
  32. package/lib/testing-BMGmmxH7.cjs +2895 -0
  33. package/lib/testing-BMGmmxH7.cjs.map +1 -0
  34. package/lib/testing-DCXz8AJD.mjs +2655 -0
  35. package/lib/testing-DCXz8AJD.mjs.map +1 -0
  36. package/package.json +23 -1
  37. package/project.json +2 -2
  38. package/src/__tests__/async-local-storage.browser.spec.mts +240 -0
  39. package/src/__tests__/async-local-storage.spec.mts +333 -0
  40. package/src/__tests__/container.spec.mts +30 -25
  41. package/src/__tests__/e2e.browser.spec.mts +790 -0
  42. package/src/__tests__/e2e.spec.mts +1222 -0
  43. package/src/__tests__/errors.spec.mts +6 -6
  44. package/src/__tests__/factory.spec.mts +1 -1
  45. package/src/__tests__/get-injectors.spec.mts +1 -1
  46. package/src/__tests__/injectable.spec.mts +1 -1
  47. package/src/__tests__/injection-token.spec.mts +1 -1
  48. package/src/__tests__/library-findings.spec.mts +563 -0
  49. package/src/__tests__/registry.spec.mts +2 -2
  50. package/src/__tests__/request-scope.spec.mts +266 -274
  51. package/src/__tests__/service-instantiator.spec.mts +18 -17
  52. package/src/__tests__/service-locator-event-bus.spec.mts +9 -9
  53. package/src/__tests__/service-locator-manager.spec.mts +15 -15
  54. package/src/__tests__/service-locator.spec.mts +167 -244
  55. package/src/__tests__/unified-api.spec.mts +27 -27
  56. package/src/__type-tests__/factory.spec-d.mts +2 -2
  57. package/src/__type-tests__/inject.spec-d.mts +2 -2
  58. package/src/__type-tests__/injectable.spec-d.mts +1 -1
  59. package/src/browser.mts +16 -0
  60. package/src/container/container.mts +319 -0
  61. package/src/container/index.mts +2 -0
  62. package/src/container/scoped-container.mts +350 -0
  63. package/src/decorators/factory.decorator.mts +4 -4
  64. package/src/decorators/injectable.decorator.mts +5 -5
  65. package/src/errors/di-error.mts +13 -7
  66. package/src/errors/index.mts +0 -8
  67. package/src/index.mts +156 -15
  68. package/src/interfaces/container.interface.mts +82 -0
  69. package/src/interfaces/factory.interface.mts +2 -2
  70. package/src/interfaces/index.mts +1 -0
  71. package/src/internal/context/async-local-storage.mts +120 -0
  72. package/src/internal/context/factory-context.mts +18 -0
  73. package/src/internal/context/index.mts +3 -0
  74. package/src/{request-context-holder.mts → internal/context/request-context.mts} +40 -27
  75. package/src/internal/context/resolution-context.mts +63 -0
  76. package/src/internal/context/sync-local-storage.mts +51 -0
  77. package/src/internal/core/index.mts +5 -0
  78. package/src/internal/core/instance-resolver.mts +641 -0
  79. package/src/{service-instantiator.mts → internal/core/instantiator.mts} +31 -27
  80. package/src/internal/core/invalidator.mts +437 -0
  81. package/src/internal/core/service-locator.mts +202 -0
  82. package/src/{token-processor.mts → internal/core/token-processor.mts} +79 -60
  83. package/src/{base-instance-holder-manager.mts → internal/holder/base-holder-manager.mts} +91 -21
  84. package/src/internal/holder/holder-manager.mts +85 -0
  85. package/src/internal/holder/holder-storage.interface.mts +116 -0
  86. package/src/internal/holder/index.mts +6 -0
  87. package/src/internal/holder/instance-holder.mts +109 -0
  88. package/src/internal/holder/request-storage.mts +134 -0
  89. package/src/internal/holder/singleton-storage.mts +105 -0
  90. package/src/internal/index.mts +4 -0
  91. package/src/internal/lifecycle/circular-detector.mts +77 -0
  92. package/src/internal/lifecycle/index.mts +2 -0
  93. package/src/{service-locator-event-bus.mts → internal/lifecycle/lifecycle-event-bus.mts} +11 -4
  94. package/src/testing/__tests__/test-container.spec.mts +2 -2
  95. package/src/testing/test-container.mts +4 -4
  96. package/src/token/index.mts +2 -0
  97. package/src/{injection-token.mts → token/injection-token.mts} +1 -1
  98. package/src/{registry.mts → token/registry.mts} +1 -1
  99. package/src/utils/get-injectable-token.mts +1 -1
  100. package/src/utils/get-injectors.mts +32 -15
  101. package/src/utils/types.mts +1 -1
  102. package/tsdown.config.mts +67 -0
  103. package/lib/_tsup-dts-rollup.d.mts +0 -1283
  104. package/lib/_tsup-dts-rollup.d.ts +0 -1283
  105. package/lib/chunk-2M576LCC.mjs +0 -2043
  106. package/lib/chunk-2M576LCC.mjs.map +0 -1
  107. package/lib/index.d.ts +0 -78
  108. package/lib/index.js +0 -2127
  109. package/lib/index.js.map +0 -1
  110. package/lib/testing/index.d.ts +0 -2
  111. package/lib/testing/index.js +0 -2060
  112. package/lib/testing/index.js.map +0 -1
  113. package/lib/testing/index.mjs.map +0 -1
  114. package/src/container.mts +0 -227
  115. package/src/factory-context.mts +0 -8
  116. package/src/instance-resolver.mts +0 -559
  117. package/src/request-context-manager.mts +0 -149
  118. package/src/service-invalidator.mts +0 -429
  119. package/src/service-locator-instance-holder.mts +0 -70
  120. package/src/service-locator-manager.mts +0 -85
  121. package/src/service-locator.mts +0 -246
  122. package/tsup.config.mts +0 -12
  123. /package/src/{injector.mts → injectors.mts} +0 -0
@@ -1,429 +0,0 @@
1
- /* eslint-disable @typescript-eslint/no-explicit-any */
2
- import type { RequestContextManager } from './request-context-manager.mjs'
3
- import type { ServiceLocatorEventBus } from './service-locator-event-bus.mjs'
4
- import type { ServiceLocatorInstanceHolder } from './service-locator-instance-holder.mjs'
5
- import type { ServiceLocatorManager } from './service-locator-manager.mjs'
6
-
7
- import { ServiceLocatorInstanceHolderStatus } from './service-locator-instance-holder.mjs'
8
-
9
- export interface ClearAllOptions {
10
- /** Whether to also clear request contexts (default: true) */
11
- clearRequestContexts?: boolean
12
- /** Maximum number of invalidation rounds to prevent infinite loops (default: 10) */
13
- maxRounds?: number
14
- /** Whether to wait for all services to settle before starting (default: true) */
15
- waitForSettlement?: boolean
16
- }
17
-
18
- /**
19
- * ServiceInvalidator handles service invalidation, cleanup, and graceful clearing.
20
- * Extracted from ServiceLocator to improve separation of concerns.
21
- */
22
- export class ServiceInvalidator {
23
- constructor(
24
- private readonly manager: ServiceLocatorManager,
25
- private readonly requestContextManager: RequestContextManager,
26
- private readonly eventBus: ServiceLocatorEventBus,
27
- private readonly logger: Console | null = null,
28
- ) {}
29
-
30
- /**
31
- * Invalidates a service and all its dependencies.
32
- */
33
- invalidate(service: string, round = 1): Promise<any> {
34
- this.logger?.log(
35
- `[ServiceInvalidator] Starting invalidation process for ${service}`,
36
- )
37
- const [, toInvalidate] = this.manager.get(service)
38
-
39
- const promises = []
40
- if (toInvalidate) {
41
- promises.push(this.invalidateHolder(service, toInvalidate, round))
42
- }
43
-
44
- // Also invalidate request-scoped instances that depend on the service or match the service name
45
- const requestContexts = this.requestContextManager.getRequestContexts()
46
- for (const [requestId, requestContext] of requestContexts.entries()) {
47
- const holder = requestContext.get(service)
48
- if (holder) {
49
- this.logger?.log(
50
- `[ServiceInvalidator] Invalidating request-scoped instance ${service} in request ${requestId}`,
51
- )
52
- promises.push(
53
- this.invalidateRequestHolder(requestId, service, holder, round),
54
- )
55
- }
56
- }
57
-
58
- return Promise.all(promises)
59
- }
60
-
61
- /**
62
- * Gracefully clears all services in the ServiceLocator using invalidation logic.
63
- * This method respects service dependencies and ensures proper cleanup order.
64
- * Services that depend on others will be invalidated first, then their dependencies.
65
- */
66
- async clearAll(options: ClearAllOptions = {}): Promise<void> {
67
- const {
68
- clearRequestContexts = true,
69
- maxRounds = 10,
70
- waitForSettlement = true,
71
- } = options
72
-
73
- this.logger?.log(
74
- '[ServiceInvalidator] Starting graceful clearing of all services',
75
- )
76
-
77
- // Wait for all services to settle if requested
78
- if (waitForSettlement) {
79
- this.logger?.log(
80
- '[ServiceInvalidator] Waiting for all services to settle...',
81
- )
82
- await this.ready()
83
- }
84
-
85
- // Get all service names that need to be cleared
86
- const allServiceNames = this.getAllServiceNames()
87
-
88
- if (allServiceNames.length === 0) {
89
- this.logger?.log('[ServiceInvalidator] No singleton services to clear')
90
- } else {
91
- this.logger?.log(
92
- `[ServiceInvalidator] Found ${allServiceNames.length} services to clear: ${allServiceNames.join(', ')}`,
93
- )
94
-
95
- // Clear services using dependency-aware invalidation
96
- await this.clearServicesWithDependencyAwareness(
97
- allServiceNames,
98
- maxRounds,
99
- )
100
- }
101
-
102
- // Clear request contexts if requested
103
- if (clearRequestContexts) {
104
- await this.requestContextManager.clearAllRequestContexts()
105
- }
106
-
107
- this.logger?.log('[ServiceInvalidator] Graceful clearing completed')
108
- }
109
-
110
- /**
111
- * Waits for all services to settle (either created, destroyed, or error state).
112
- */
113
- async ready(): Promise<void> {
114
- const holders = Array.from(this.manager.filter(() => true)).map(
115
- ([, holder]) => holder,
116
- )
117
- await Promise.all(
118
- holders.map((holder) => this.waitForHolderToSettle(holder)),
119
- )
120
- }
121
-
122
- /**
123
- * Invalidates a single holder based on its current status.
124
- */
125
- private async invalidateHolder(
126
- key: string,
127
- holder: ServiceLocatorInstanceHolder<any>,
128
- round: number,
129
- ): Promise<void> {
130
- await this.invalidateHolderByStatus(holder, round, {
131
- context: key,
132
- isRequestScoped: false,
133
- onCreationError: () =>
134
- this.logger?.error(
135
- `[ServiceInvalidator] ${key} creation triggered too many invalidation rounds`,
136
- ),
137
- onRecursiveInvalidate: () => this.invalidate(key, round + 1),
138
- onDestroy: () => this.destroyHolder(key, holder),
139
- })
140
- }
141
-
142
- /**
143
- * Invalidates a request-scoped holder based on its current status.
144
- */
145
- private async invalidateRequestHolder(
146
- requestId: string,
147
- instanceName: string,
148
- holder: ServiceLocatorInstanceHolder<any>,
149
- round: number,
150
- ): Promise<void> {
151
- await this.invalidateHolderByStatus(holder, round, {
152
- context: `Request-scoped ${instanceName} in ${requestId}`,
153
- isRequestScoped: true,
154
- onCreationError: () =>
155
- this.logger?.error(
156
- `[ServiceInvalidator] Request-scoped ${instanceName} in ${requestId} creation triggered too many invalidation rounds`,
157
- ),
158
- onRecursiveInvalidate: () =>
159
- this.invalidateRequestHolder(
160
- requestId,
161
- instanceName,
162
- holder,
163
- round + 1,
164
- ),
165
- onDestroy: () =>
166
- this.destroyRequestHolder(requestId, instanceName, holder),
167
- })
168
- }
169
-
170
- /**
171
- * Common invalidation logic for holders based on their status.
172
- */
173
- private async invalidateHolderByStatus(
174
- holder: ServiceLocatorInstanceHolder<any>,
175
- round: number,
176
- options: {
177
- context: string
178
- isRequestScoped: boolean
179
- onCreationError: () => void
180
- onRecursiveInvalidate: () => Promise<void>
181
- onDestroy: () => Promise<void>
182
- },
183
- ): Promise<void> {
184
- switch (holder.status) {
185
- case ServiceLocatorInstanceHolderStatus.Destroying:
186
- await holder.destroyPromise
187
- break
188
-
189
- case ServiceLocatorInstanceHolderStatus.Creating:
190
- await holder.creationPromise
191
- if (round > 3) {
192
- options.onCreationError()
193
- return
194
- }
195
- await options.onRecursiveInvalidate()
196
- break
197
-
198
- default:
199
- await options.onDestroy()
200
- break
201
- }
202
- }
203
-
204
- /**
205
- * Destroys a holder and cleans up its resources.
206
- */
207
- private async destroyHolder(
208
- key: string,
209
- holder: ServiceLocatorInstanceHolder<any>,
210
- ): Promise<void> {
211
- await this.destroyHolderWithCleanup(holder, {
212
- context: key,
213
- logMessage: `[ServiceInvalidator] Invalidating ${key} and notifying listeners`,
214
- cleanup: () => this.manager.delete(key),
215
- eventName: key,
216
- })
217
- }
218
-
219
- /**
220
- * Destroys a request-scoped holder and cleans up its resources.
221
- */
222
- private async destroyRequestHolder(
223
- requestId: string,
224
- instanceName: string,
225
- holder: ServiceLocatorInstanceHolder<any>,
226
- ): Promise<void> {
227
- await this.destroyHolderWithCleanup(holder, {
228
- context: `Request-scoped ${instanceName} in ${requestId}`,
229
- logMessage: `[ServiceInvalidator] Invalidating request-scoped ${instanceName} in ${requestId} and notifying listeners`,
230
- cleanup: () => {
231
- const requestContext = this.requestContextManager
232
- .getRequestContexts()
233
- .get(requestId)
234
- if (requestContext) {
235
- requestContext.delete(instanceName)
236
- }
237
- },
238
- eventName: instanceName,
239
- })
240
- }
241
-
242
- /**
243
- * Common destroy logic for holders with customizable cleanup.
244
- */
245
- private async destroyHolderWithCleanup(
246
- holder: ServiceLocatorInstanceHolder<any>,
247
- options: {
248
- context: string
249
- logMessage: string
250
- cleanup: () => void
251
- eventName: string
252
- },
253
- ): Promise<void> {
254
- holder.status = ServiceLocatorInstanceHolderStatus.Destroying
255
- this.logger?.log(options.logMessage)
256
-
257
- holder.destroyPromise = Promise.all(
258
- holder.destroyListeners.map((listener) => listener()),
259
- ).then(async () => {
260
- holder.destroyListeners = []
261
- holder.deps.clear()
262
- options.cleanup()
263
- await this.emitInstanceEvent(options.eventName, 'destroy')
264
- })
265
-
266
- await holder.destroyPromise
267
- }
268
-
269
- /**
270
- * Waits for a holder to settle (either created, destroyed, or error state).
271
- */
272
- private async waitForHolderToSettle(
273
- holder: ServiceLocatorInstanceHolder<any>,
274
- ): Promise<void> {
275
- switch (holder.status) {
276
- case ServiceLocatorInstanceHolderStatus.Creating:
277
- await holder.creationPromise
278
- break
279
- case ServiceLocatorInstanceHolderStatus.Destroying:
280
- await holder.destroyPromise
281
- break
282
- // Already settled states
283
- case ServiceLocatorInstanceHolderStatus.Created:
284
- case ServiceLocatorInstanceHolderStatus.Error:
285
- break
286
- }
287
- }
288
-
289
- /**
290
- * Clears services with dependency awareness, ensuring proper cleanup order.
291
- * Services with no dependencies are cleared first, then services that depend on them.
292
- */
293
- private async clearServicesWithDependencyAwareness(
294
- serviceNames: string[],
295
- maxRounds: number,
296
- ): Promise<void> {
297
- const clearedServices = new Set<string>()
298
- let round = 1
299
-
300
- while (clearedServices.size < serviceNames.length && round <= maxRounds) {
301
- this.logger?.log(
302
- `[ServiceInvalidator] Clearing round ${round}/${maxRounds}, ${clearedServices.size}/${serviceNames.length} services cleared`,
303
- )
304
-
305
- // Find services that can be cleared in this round
306
- const servicesToClearThisRound = this.findServicesReadyForClearing(
307
- serviceNames,
308
- clearedServices,
309
- )
310
-
311
- if (servicesToClearThisRound.length === 0) {
312
- // If no services can be cleared, try to clear remaining services anyway
313
- // This handles circular dependencies or other edge cases
314
- const remainingServices = serviceNames.filter(
315
- (name) => !clearedServices.has(name),
316
- )
317
-
318
- if (remainingServices.length > 0) {
319
- this.logger?.warn(
320
- `[ServiceInvalidator] No services ready for clearing, forcing cleanup of remaining: ${remainingServices.join(', ')}`,
321
- )
322
- await this.forceClearServices(remainingServices)
323
- remainingServices.forEach((name) => clearedServices.add(name))
324
- }
325
- break
326
- }
327
-
328
- // Clear services in this round
329
- const clearPromises = servicesToClearThisRound.map(
330
- async (serviceName) => {
331
- try {
332
- await this.invalidate(serviceName, round)
333
- clearedServices.add(serviceName)
334
- this.logger?.log(
335
- `[ServiceInvalidator] Successfully cleared service: ${serviceName}`,
336
- )
337
- } catch (error) {
338
- this.logger?.error(
339
- `[ServiceInvalidator] Error clearing service ${serviceName}:`,
340
- error,
341
- )
342
- // Still mark as cleared to avoid infinite loops
343
- clearedServices.add(serviceName)
344
- }
345
- },
346
- )
347
-
348
- await Promise.all(clearPromises)
349
- round++
350
- }
351
-
352
- if (clearedServices.size < serviceNames.length) {
353
- this.logger?.warn(
354
- `[ServiceInvalidator] Clearing completed after ${maxRounds} rounds, but ${serviceNames.length - clearedServices.size} services may not have been properly cleared`,
355
- )
356
- }
357
- }
358
-
359
- /**
360
- * Finds services that are ready to be cleared in the current round.
361
- * A service is ready if all its dependencies have already been cleared.
362
- */
363
- private findServicesReadyForClearing(
364
- allServiceNames: string[],
365
- clearedServices: Set<string>,
366
- ): string[] {
367
- return allServiceNames.filter((serviceName) => {
368
- if (clearedServices.has(serviceName)) {
369
- return false // Already cleared
370
- }
371
-
372
- // Check if this service has any dependencies that haven't been cleared yet
373
- const [error, holder] = this.manager.get(serviceName)
374
- if (error) {
375
- return true // Service not found or in error state, can be cleared
376
- }
377
-
378
- // Check if all dependencies have been cleared
379
- const hasUnclearedDependencies = Array.from(holder.deps).some(
380
- (dep) => !clearedServices.has(dep),
381
- )
382
-
383
- return !hasUnclearedDependencies
384
- })
385
- }
386
-
387
- /**
388
- * Force clears services that couldn't be cleared through normal dependency resolution.
389
- * This handles edge cases like circular dependencies.
390
- */
391
- private async forceClearServices(serviceNames: string[]): Promise<void> {
392
- const promises = serviceNames.map(async (serviceName) => {
393
- try {
394
- // Directly destroy the holder without going through normal invalidation
395
- const [error, holder] = this.manager.get(serviceName)
396
- if (!error && holder) {
397
- await this.destroyHolder(serviceName, holder)
398
- }
399
- } catch (error) {
400
- this.logger?.error(
401
- `[ServiceInvalidator] Error force clearing service ${serviceName}:`,
402
- error,
403
- )
404
- }
405
- })
406
-
407
- await Promise.all(promises)
408
- }
409
-
410
- /**
411
- * Gets all service names currently managed by the ServiceLocator.
412
- */
413
- private getAllServiceNames(): string[] {
414
- return this.manager.getAllNames()
415
- }
416
-
417
- /**
418
- * Emits events to listeners for instance lifecycle events.
419
- */
420
- private emitInstanceEvent(
421
- name: string,
422
- event: 'create' | 'destroy' = 'create',
423
- ) {
424
- this.logger?.log(
425
- `[ServiceInvalidator]#emitInstanceEvent() Notifying listeners for ${name} with event ${event}`,
426
- )
427
- return this.eventBus.emit(name, event)
428
- }
429
- }
@@ -1,70 +0,0 @@
1
- import type { InjectableScope, InjectableType } from './enums/index.mjs'
2
-
3
- /* eslint-disable @typescript-eslint/no-empty-object-type */
4
- export enum ServiceLocatorInstanceHolderStatus {
5
- Created = 'created',
6
- Creating = 'creating',
7
- Destroying = 'destroying',
8
- Error = 'error',
9
- }
10
-
11
- export type ServiceLocatorInstanceEffect = () => void
12
- export type ServiceLocatorInstanceDestroyListener = () => void | Promise<void>
13
-
14
- export interface ServiceLocatorInstanceHolderCreating<Instance> {
15
- status: ServiceLocatorInstanceHolderStatus.Creating
16
- name: string
17
- instance: null
18
- creationPromise: Promise<[undefined, Instance]> | null
19
- destroyPromise: null
20
- type: InjectableType
21
- scope: InjectableScope
22
- deps: Set<string>
23
- destroyListeners: ServiceLocatorInstanceDestroyListener[]
24
- createdAt: number
25
- }
26
-
27
- export interface ServiceLocatorInstanceHolderCreated<Instance> {
28
- status: ServiceLocatorInstanceHolderStatus.Created
29
- name: string
30
- instance: Instance
31
- creationPromise: null
32
- destroyPromise: null
33
- type: InjectableType
34
- scope: InjectableScope
35
- deps: Set<string>
36
- destroyListeners: ServiceLocatorInstanceDestroyListener[]
37
- createdAt: number
38
- }
39
-
40
- export interface ServiceLocatorInstanceHolderDestroying<Instance> {
41
- status: ServiceLocatorInstanceHolderStatus.Destroying
42
- name: string
43
- instance: Instance | null
44
- creationPromise: null
45
- destroyPromise: Promise<void>
46
- type: InjectableType
47
- scope: InjectableScope
48
- deps: Set<string>
49
- destroyListeners: ServiceLocatorInstanceDestroyListener[]
50
- createdAt: number
51
- }
52
-
53
- export interface ServiceLocatorInstanceHolderError {
54
- status: ServiceLocatorInstanceHolderStatus.Error
55
- name: string
56
- instance: Error
57
- creationPromise: null
58
- destroyPromise: null
59
- type: InjectableType
60
- scope: InjectableScope
61
- deps: Set<string>
62
- destroyListeners: ServiceLocatorInstanceDestroyListener[]
63
- createdAt: number
64
- }
65
-
66
- export type ServiceLocatorInstanceHolder<Instance = unknown> =
67
- | ServiceLocatorInstanceHolderCreating<Instance>
68
- | ServiceLocatorInstanceHolderCreated<Instance>
69
- | ServiceLocatorInstanceHolderDestroying<Instance>
70
- | ServiceLocatorInstanceHolderError
@@ -1,85 +0,0 @@
1
- /* eslint-disable @typescript-eslint/no-empty-object-type */
2
- import type { ServiceLocatorInstanceHolder } from './service-locator-instance-holder.mjs'
3
-
4
- import { BaseInstanceHolderManager } from './base-instance-holder-manager.mjs'
5
- import { InjectableScope, InjectableType } from './enums/index.mjs'
6
- import { DIError, DIErrorCode } from './errors/index.mjs'
7
- import { ServiceLocatorInstanceHolderStatus } from './service-locator-instance-holder.mjs'
8
-
9
- export class ServiceLocatorManager extends BaseInstanceHolderManager {
10
- constructor(logger: Console | null = null) {
11
- super(logger)
12
- }
13
-
14
- get(
15
- name: string,
16
- ):
17
- | [DIError, ServiceLocatorInstanceHolder]
18
- | [DIError]
19
- | [undefined, ServiceLocatorInstanceHolder] {
20
- const holder = this._holders.get(name)
21
- if (holder) {
22
- if (holder.status === ServiceLocatorInstanceHolderStatus.Destroying) {
23
- this.logger?.log(
24
- `[ServiceLocatorManager]#getInstanceHolder() Instance ${holder.name} is destroying`,
25
- )
26
- return [DIError.instanceDestroying(holder.name), holder]
27
- } else if (holder.status === ServiceLocatorInstanceHolderStatus.Error) {
28
- this.logger?.log(
29
- `[ServiceLocatorManager]#getInstanceHolder() Instance ${holder.name} is in error state`,
30
- )
31
- return [holder.instance as DIError, holder]
32
- }
33
-
34
- return [undefined, holder]
35
- } else {
36
- this.logger?.log(
37
- `[ServiceLocatorManager]#getInstanceHolder() Instance ${name} not found`,
38
- )
39
- return [DIError.instanceNotFound(name)]
40
- }
41
- }
42
-
43
- set(name: string, holder: ServiceLocatorInstanceHolder): 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 BaseInstanceHolderManager
59
-
60
- // createCreatingHolder method is inherited from BaseInstanceHolderManager
61
-
62
- /**
63
- * Creates a new holder with Created status and an actual instance.
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
- ): ServiceLocatorInstanceHolder<Instance> {
79
- const holder = this.createCreatedHolder(name, instance, type, scope, deps)
80
-
81
- this._holders.set(name, holder)
82
-
83
- return holder
84
- }
85
- }