@navios/di 0.8.0 → 0.9.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +87 -0
- package/README.md +117 -17
- package/lib/browser/container/abstract-container.d.mts +112 -0
- package/lib/browser/container/abstract-container.d.mts.map +1 -0
- package/lib/browser/container/abstract-container.mjs +100 -0
- package/lib/browser/container/abstract-container.mjs.map +1 -0
- package/lib/browser/container/container.d.mts +100 -0
- package/lib/browser/container/container.d.mts.map +1 -0
- package/lib/browser/container/container.mjs +424 -0
- package/lib/browser/container/container.mjs.map +1 -0
- package/lib/browser/container/scoped-container.d.mts +93 -0
- package/lib/browser/container/scoped-container.d.mts.map +1 -0
- package/lib/browser/container/scoped-container.mjs +119 -0
- package/lib/browser/container/scoped-container.mjs.map +1 -0
- package/lib/browser/decorators/factory.decorator.d.mts +26 -0
- package/lib/browser/decorators/factory.decorator.d.mts.map +1 -0
- package/lib/browser/decorators/factory.decorator.mjs +20 -0
- package/lib/browser/decorators/factory.decorator.mjs.map +1 -0
- package/lib/browser/decorators/injectable.decorator.d.mts +38 -0
- package/lib/browser/decorators/injectable.decorator.d.mts.map +1 -0
- package/lib/browser/decorators/injectable.decorator.mjs +21 -0
- package/lib/browser/decorators/injectable.decorator.mjs.map +1 -0
- package/lib/browser/enums/injectable-scope.enum.d.mts +18 -0
- package/lib/browser/enums/injectable-scope.enum.d.mts.map +1 -0
- package/lib/browser/enums/injectable-scope.enum.mjs +20 -0
- package/lib/browser/enums/injectable-scope.enum.mjs.map +1 -0
- package/lib/browser/enums/injectable-type.enum.d.mts +8 -0
- package/lib/browser/enums/injectable-type.enum.d.mts.map +1 -0
- package/lib/browser/enums/injectable-type.enum.mjs +10 -0
- package/lib/browser/enums/injectable-type.enum.mjs.map +1 -0
- package/lib/browser/errors/di-error.d.mts +43 -0
- package/lib/browser/errors/di-error.d.mts.map +1 -0
- package/lib/browser/errors/di-error.mjs +98 -0
- package/lib/browser/errors/di-error.mjs.map +1 -0
- package/lib/browser/event-emitter.d.mts +16 -0
- package/lib/browser/event-emitter.d.mts.map +1 -0
- package/lib/browser/event-emitter.mjs +320 -0
- package/lib/browser/event-emitter.mjs.map +1 -0
- package/lib/browser/index.d.mts +37 -1558
- package/lib/browser/index.mjs +29 -2749
- package/lib/browser/interfaces/container.interface.d.mts +59 -0
- package/lib/browser/interfaces/container.interface.d.mts.map +1 -0
- package/lib/browser/interfaces/factory.interface.d.mts +14 -0
- package/lib/browser/interfaces/factory.interface.d.mts.map +1 -0
- package/lib/browser/interfaces/on-service-destroy.interface.d.mts +7 -0
- package/lib/browser/interfaces/on-service-destroy.interface.d.mts.map +1 -0
- package/lib/browser/interfaces/on-service-init.interface.d.mts +7 -0
- package/lib/browser/interfaces/on-service-init.interface.d.mts.map +1 -0
- package/lib/browser/internal/context/async-local-storage.browser.mjs +20 -0
- package/lib/browser/internal/context/async-local-storage.browser.mjs.map +1 -0
- package/lib/browser/internal/context/async-local-storage.d.mts +9 -0
- package/lib/browser/internal/context/async-local-storage.d.mts.map +1 -0
- package/lib/browser/internal/context/async-local-storage.types.d.mts +11 -0
- package/lib/browser/internal/context/async-local-storage.types.d.mts.map +1 -0
- package/lib/browser/internal/context/factory-context.d.mts +23 -0
- package/lib/browser/internal/context/factory-context.d.mts.map +1 -0
- package/lib/browser/internal/context/resolution-context.d.mts +43 -0
- package/lib/browser/internal/context/resolution-context.d.mts.map +1 -0
- package/lib/browser/internal/context/resolution-context.mjs +56 -0
- package/lib/browser/internal/context/resolution-context.mjs.map +1 -0
- package/lib/browser/internal/context/service-initialization-context.d.mts +48 -0
- package/lib/browser/internal/context/service-initialization-context.d.mts.map +1 -0
- package/lib/browser/internal/context/sync-local-storage.mjs +53 -0
- package/lib/browser/internal/context/sync-local-storage.mjs.map +1 -0
- package/lib/browser/internal/core/instance-resolver.d.mts +119 -0
- package/lib/browser/internal/core/instance-resolver.d.mts.map +1 -0
- package/lib/browser/internal/core/instance-resolver.mjs +306 -0
- package/lib/browser/internal/core/instance-resolver.mjs.map +1 -0
- package/lib/browser/internal/core/name-resolver.d.mts +52 -0
- package/lib/browser/internal/core/name-resolver.d.mts.map +1 -0
- package/lib/browser/internal/core/name-resolver.mjs +118 -0
- package/lib/browser/internal/core/name-resolver.mjs.map +1 -0
- package/lib/browser/internal/core/scope-tracker.d.mts +65 -0
- package/lib/browser/internal/core/scope-tracker.d.mts.map +1 -0
- package/lib/browser/internal/core/scope-tracker.mjs +120 -0
- package/lib/browser/internal/core/scope-tracker.mjs.map +1 -0
- package/lib/browser/internal/core/service-initializer.d.mts +44 -0
- package/lib/browser/internal/core/service-initializer.d.mts.map +1 -0
- package/lib/browser/internal/core/service-initializer.mjs +109 -0
- package/lib/browser/internal/core/service-initializer.mjs.map +1 -0
- package/lib/browser/internal/core/service-invalidator.d.mts +81 -0
- package/lib/browser/internal/core/service-invalidator.d.mts.map +1 -0
- package/lib/browser/internal/core/service-invalidator.mjs +142 -0
- package/lib/browser/internal/core/service-invalidator.mjs.map +1 -0
- package/lib/browser/internal/core/token-resolver.d.mts +54 -0
- package/lib/browser/internal/core/token-resolver.d.mts.map +1 -0
- package/lib/browser/internal/core/token-resolver.mjs +77 -0
- package/lib/browser/internal/core/token-resolver.mjs.map +1 -0
- package/lib/browser/internal/holder/holder-storage.interface.d.mts +99 -0
- package/lib/browser/internal/holder/holder-storage.interface.d.mts.map +1 -0
- package/lib/browser/internal/holder/instance-holder.d.mts +101 -0
- package/lib/browser/internal/holder/instance-holder.d.mts.map +1 -0
- package/lib/browser/internal/holder/instance-holder.mjs +19 -0
- package/lib/browser/internal/holder/instance-holder.mjs.map +1 -0
- package/lib/browser/internal/holder/unified-storage.d.mts +53 -0
- package/lib/browser/internal/holder/unified-storage.d.mts.map +1 -0
- package/lib/browser/internal/holder/unified-storage.mjs +144 -0
- package/lib/browser/internal/holder/unified-storage.mjs.map +1 -0
- package/lib/browser/internal/lifecycle/circular-detector.d.mts +39 -0
- package/lib/browser/internal/lifecycle/circular-detector.d.mts.map +1 -0
- package/lib/browser/internal/lifecycle/circular-detector.mjs +55 -0
- package/lib/browser/internal/lifecycle/circular-detector.mjs.map +1 -0
- package/lib/browser/internal/lifecycle/lifecycle-event-bus.d.mts +18 -0
- package/lib/browser/internal/lifecycle/lifecycle-event-bus.d.mts.map +1 -0
- package/lib/browser/internal/lifecycle/lifecycle-event-bus.mjs +43 -0
- package/lib/browser/internal/lifecycle/lifecycle-event-bus.mjs.map +1 -0
- package/lib/browser/internal/stub-factory-class.d.mts +14 -0
- package/lib/browser/internal/stub-factory-class.d.mts.map +1 -0
- package/lib/browser/internal/stub-factory-class.mjs +18 -0
- package/lib/browser/internal/stub-factory-class.mjs.map +1 -0
- package/lib/browser/symbols/injectable-token.d.mts +5 -0
- package/lib/browser/symbols/injectable-token.d.mts.map +1 -0
- package/lib/browser/symbols/injectable-token.mjs +6 -0
- package/lib/browser/symbols/injectable-token.mjs.map +1 -0
- package/lib/browser/token/injection-token.d.mts +55 -0
- package/lib/browser/token/injection-token.d.mts.map +1 -0
- package/lib/browser/token/injection-token.mjs +100 -0
- package/lib/browser/token/injection-token.mjs.map +1 -0
- package/lib/browser/token/registry.d.mts +37 -0
- package/lib/browser/token/registry.d.mts.map +1 -0
- package/lib/browser/token/registry.mjs +86 -0
- package/lib/browser/token/registry.mjs.map +1 -0
- package/lib/browser/utils/default-injectors.d.mts +12 -0
- package/lib/browser/utils/default-injectors.d.mts.map +1 -0
- package/lib/browser/utils/default-injectors.mjs +13 -0
- package/lib/browser/utils/default-injectors.mjs.map +1 -0
- package/lib/browser/utils/get-injectable-token.d.mts +9 -0
- package/lib/browser/utils/get-injectable-token.d.mts.map +1 -0
- package/lib/browser/utils/get-injectable-token.mjs +13 -0
- package/lib/browser/utils/get-injectable-token.mjs.map +1 -0
- package/lib/browser/utils/get-injectors.d.mts +55 -0
- package/lib/browser/utils/get-injectors.d.mts.map +1 -0
- package/lib/browser/utils/get-injectors.mjs +121 -0
- package/lib/browser/utils/get-injectors.mjs.map +1 -0
- package/lib/browser/utils/types.d.mts +23 -0
- package/lib/browser/utils/types.d.mts.map +1 -0
- package/lib/{container-DAKOvAgr.mjs → container-8-z89TyQ.mjs} +1325 -1462
- package/lib/container-8-z89TyQ.mjs.map +1 -0
- package/lib/{container-Bp1W-pWJ.d.mts → container-CNiqesCL.d.mts} +598 -617
- package/lib/container-CNiqesCL.d.mts.map +1 -0
- package/lib/{container-DENMeJ87.cjs → container-CaY2fDuk.cjs} +1369 -1512
- package/lib/container-CaY2fDuk.cjs.map +1 -0
- package/lib/{container-YPwvmlK2.d.cts → container-D-0Ho3qL.d.cts} +598 -612
- package/lib/container-D-0Ho3qL.d.cts.map +1 -0
- package/lib/index.cjs +13 -15
- package/lib/index.cjs.map +1 -1
- package/lib/index.d.cts +58 -223
- package/lib/index.d.cts.map +1 -1
- package/lib/index.d.mts +62 -222
- package/lib/index.d.mts.map +1 -1
- package/lib/index.mjs +5 -6
- package/lib/index.mjs.map +1 -1
- package/lib/testing/index.cjs +569 -311
- package/lib/testing/index.cjs.map +1 -1
- package/lib/testing/index.d.cts +370 -41
- package/lib/testing/index.d.cts.map +1 -1
- package/lib/testing/index.d.mts +370 -41
- package/lib/testing/index.d.mts.map +1 -1
- package/lib/testing/index.mjs +568 -305
- package/lib/testing/index.mjs.map +1 -1
- package/package.json +2 -1
- package/src/__tests__/circular-detector.spec.mts +193 -0
- package/src/__tests__/concurrent.spec.mts +368 -0
- package/src/__tests__/container.spec.mts +32 -30
- package/src/__tests__/di-error.spec.mts +351 -0
- package/src/__tests__/e2e.browser.spec.mts +0 -4
- package/src/__tests__/e2e.spec.mts +10 -19
- package/src/__tests__/event-emitter.spec.mts +232 -109
- package/src/__tests__/get-injectors.spec.mts +250 -39
- package/src/__tests__/injection-token.spec.mts +293 -349
- package/src/__tests__/library-findings.spec.mts +8 -8
- package/src/__tests__/registry.spec.mts +358 -210
- package/src/__tests__/resolution-context.spec.mts +255 -0
- package/src/__tests__/scope-tracker.spec.mts +598 -0
- package/src/__tests__/scope-upgrade.spec.mts +808 -0
- package/src/__tests__/scoped-container.spec.mts +595 -0
- package/src/__tests__/test-container.spec.mts +293 -0
- package/src/__tests__/token-resolver.spec.mts +207 -0
- package/src/__tests__/unified-storage.spec.mts +535 -0
- package/src/__tests__/unit-test-container.spec.mts +405 -0
- package/src/__type-tests__/container.spec-d.mts +180 -0
- package/src/__type-tests__/factory.spec-d.mts +15 -3
- package/src/__type-tests__/inject.spec-d.mts +115 -20
- package/src/__type-tests__/injectable.spec-d.mts +69 -52
- package/src/__type-tests__/injection-token.spec-d.mts +176 -0
- package/src/__type-tests__/scoped-container.spec-d.mts +212 -0
- package/src/container/abstract-container.mts +327 -0
- package/src/container/container.mts +142 -170
- package/src/container/scoped-container.mts +126 -208
- package/src/decorators/factory.decorator.mts +16 -11
- package/src/decorators/injectable.decorator.mts +20 -16
- package/src/enums/index.mts +2 -2
- package/src/enums/injectable-scope.enum.mts +1 -0
- package/src/enums/injectable-type.enum.mts +1 -0
- package/src/errors/di-error.mts +96 -0
- package/src/event-emitter.mts +3 -27
- package/src/index.mts +6 -153
- package/src/interfaces/container.interface.mts +13 -0
- package/src/interfaces/factory.interface.mts +1 -1
- package/src/interfaces/index.mts +1 -1
- package/src/internal/context/async-local-storage.mts +3 -2
- package/src/internal/context/async-local-storage.types.mts +1 -0
- package/src/internal/context/factory-context.mts +1 -0
- package/src/internal/context/index.mts +3 -1
- package/src/internal/context/resolution-context.mts +1 -0
- package/src/internal/context/service-initialization-context.mts +43 -0
- package/src/internal/core/index.mts +5 -4
- package/src/internal/core/instance-resolver.mts +460 -302
- package/src/internal/core/name-resolver.mts +196 -0
- package/src/internal/core/scope-tracker.mts +242 -0
- package/src/internal/core/{instantiator.mts → service-initializer.mts} +51 -29
- package/src/internal/core/service-invalidator.mts +290 -0
- package/src/internal/core/token-resolver.mts +122 -0
- package/src/internal/holder/holder-storage.interface.mts +11 -5
- package/src/internal/holder/index.mts +2 -5
- package/src/internal/holder/instance-holder.mts +1 -3
- package/src/internal/holder/unified-storage.mts +245 -0
- package/src/internal/index.mts +2 -1
- package/src/internal/lifecycle/circular-detector.mts +1 -0
- package/src/internal/lifecycle/index.mts +1 -1
- package/src/internal/lifecycle/lifecycle-event-bus.mts +1 -0
- package/src/internal/stub-factory-class.mts +16 -0
- package/src/symbols/injectable-token.mts +3 -1
- package/src/testing/index.mts +2 -0
- package/src/testing/test-container.mts +546 -85
- package/src/testing/types.mts +117 -0
- package/src/testing/unit-test-container.mts +509 -0
- package/src/token/injection-token.mts +41 -4
- package/src/token/registry.mts +75 -9
- package/src/utils/default-injectors.mts +16 -0
- package/src/utils/get-injectable-token.mts +2 -3
- package/src/utils/get-injectors.mts +26 -15
- package/src/utils/index.mts +3 -1
- package/src/utils/types.mts +1 -0
- package/tsdown.config.mts +11 -1
- package/lib/browser/index.d.mts.map +0 -1
- package/lib/browser/index.mjs.map +0 -1
- package/lib/container-Bp1W-pWJ.d.mts.map +0 -1
- package/lib/container-DAKOvAgr.mjs.map +0 -1
- package/lib/container-DENMeJ87.cjs.map +0 -1
- package/lib/container-YPwvmlK2.d.cts.map +0 -1
- package/src/__tests__/async-local-storage.browser.spec.mts +0 -166
- package/src/__tests__/async-local-storage.spec.mts +0 -333
- package/src/__tests__/errors.spec.mts +0 -87
- package/src/__tests__/factory.spec.mts +0 -137
- package/src/__tests__/injectable.spec.mts +0 -246
- package/src/__tests__/request-scope.spec.mts +0 -416
- package/src/__tests__/service-instantiator.spec.mts +0 -410
- package/src/__tests__/service-locator-event-bus.spec.mts +0 -242
- package/src/__tests__/service-locator-manager.spec.mts +0 -300
- package/src/__tests__/service-locator.spec.mts +0 -966
- package/src/__tests__/unified-api.spec.mts +0 -130
- package/src/browser.mts +0 -11
- package/src/injectors.mts +0 -18
- package/src/internal/context/request-context.mts +0 -225
- package/src/internal/core/invalidator.mts +0 -437
- package/src/internal/core/service-locator.mts +0 -202
- package/src/internal/core/token-processor.mts +0 -252
- package/src/internal/holder/base-holder-manager.mts +0 -334
- package/src/internal/holder/holder-manager.mts +0 -85
- package/src/internal/holder/request-storage.mts +0 -127
- package/src/internal/holder/singleton-storage.mts +0 -92
- package/src/testing/README.md +0 -80
- package/src/testing/__tests__/test-container.spec.mts +0 -173
|
@@ -1,252 +0,0 @@
|
|
|
1
|
-
/* eslint-disable @typescript-eslint/no-explicit-any */
|
|
2
|
-
/* eslint-disable @typescript-eslint/no-empty-object-type */
|
|
3
|
-
|
|
4
|
-
import type { FactoryContext } from '../context/factory-context.mjs'
|
|
5
|
-
import type {
|
|
6
|
-
AnyInjectableType,
|
|
7
|
-
InjectionTokenType,
|
|
8
|
-
} from '../../token/injection-token.mjs'
|
|
9
|
-
import type { IContainer } from '../../interfaces/container.interface.mjs'
|
|
10
|
-
|
|
11
|
-
import { DIError } from '../../errors/index.mjs'
|
|
12
|
-
import {
|
|
13
|
-
BoundInjectionToken,
|
|
14
|
-
FactoryInjectionToken,
|
|
15
|
-
InjectionToken,
|
|
16
|
-
} from '../../token/injection-token.mjs'
|
|
17
|
-
import { getInjectableToken } from '../../utils/index.mjs'
|
|
18
|
-
|
|
19
|
-
/**
|
|
20
|
-
* Simple LRU cache for instance name generation.
|
|
21
|
-
* Uses a Map which maintains insertion order for efficient LRU eviction.
|
|
22
|
-
*/
|
|
23
|
-
class InstanceNameCache {
|
|
24
|
-
private readonly cache = new Map<string, string>()
|
|
25
|
-
private readonly maxSize: number
|
|
26
|
-
|
|
27
|
-
constructor(maxSize = 1000) {
|
|
28
|
-
this.maxSize = maxSize
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
get(key: string): string | undefined {
|
|
32
|
-
const value = this.cache.get(key)
|
|
33
|
-
if (value !== undefined) {
|
|
34
|
-
// Move to end (most recently used)
|
|
35
|
-
this.cache.delete(key)
|
|
36
|
-
this.cache.set(key, value)
|
|
37
|
-
}
|
|
38
|
-
return value
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
set(key: string, value: string): void {
|
|
42
|
-
if (this.cache.has(key)) {
|
|
43
|
-
this.cache.delete(key)
|
|
44
|
-
} else if (this.cache.size >= this.maxSize) {
|
|
45
|
-
// Remove least recently used (first item)
|
|
46
|
-
const firstKey = this.cache.keys().next().value
|
|
47
|
-
if (firstKey !== undefined) {
|
|
48
|
-
this.cache.delete(firstKey)
|
|
49
|
-
}
|
|
50
|
-
}
|
|
51
|
-
this.cache.set(key, value)
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
clear(): void {
|
|
55
|
-
this.cache.clear()
|
|
56
|
-
}
|
|
57
|
-
}
|
|
58
|
-
|
|
59
|
-
/**
|
|
60
|
-
* Handles token validation, normalization, and instance name generation.
|
|
61
|
-
*
|
|
62
|
-
* Provides utilities for resolving tokens to their underlying InjectionToken,
|
|
63
|
-
* validating arguments against schemas, and generating unique instance identifiers.
|
|
64
|
-
*/
|
|
65
|
-
export class TokenProcessor {
|
|
66
|
-
private readonly instanceNameCache = new InstanceNameCache()
|
|
67
|
-
|
|
68
|
-
constructor(private readonly logger: Console | null = null) {}
|
|
69
|
-
|
|
70
|
-
// ============================================================================
|
|
71
|
-
// TOKEN NORMALIZATION
|
|
72
|
-
// ============================================================================
|
|
73
|
-
|
|
74
|
-
/**
|
|
75
|
-
* Normalizes a token to an InjectionToken.
|
|
76
|
-
* Handles class constructors by getting their injectable token.
|
|
77
|
-
*
|
|
78
|
-
* @param token A class constructor, InjectionToken, BoundInjectionToken, or FactoryInjectionToken
|
|
79
|
-
* @returns The normalized InjectionTokenType
|
|
80
|
-
*/
|
|
81
|
-
normalizeToken(token: AnyInjectableType): InjectionTokenType {
|
|
82
|
-
if (typeof token === 'function') {
|
|
83
|
-
return getInjectableToken(token)
|
|
84
|
-
}
|
|
85
|
-
return token as InjectionTokenType
|
|
86
|
-
}
|
|
87
|
-
|
|
88
|
-
/**
|
|
89
|
-
* Gets the underlying "real" token from wrapped tokens.
|
|
90
|
-
* For BoundInjectionToken and FactoryInjectionToken, returns the wrapped token.
|
|
91
|
-
* For other tokens, returns the token itself.
|
|
92
|
-
*
|
|
93
|
-
* @param token The token to unwrap
|
|
94
|
-
* @returns The underlying InjectionToken
|
|
95
|
-
*/
|
|
96
|
-
getRealToken<T = unknown>(token: InjectionTokenType): InjectionToken<T> {
|
|
97
|
-
if (
|
|
98
|
-
token instanceof BoundInjectionToken ||
|
|
99
|
-
token instanceof FactoryInjectionToken
|
|
100
|
-
) {
|
|
101
|
-
return token.token as InjectionToken<T>
|
|
102
|
-
}
|
|
103
|
-
return token as InjectionToken<T>
|
|
104
|
-
}
|
|
105
|
-
|
|
106
|
-
/**
|
|
107
|
-
* Convenience method that normalizes a token and then gets the real token.
|
|
108
|
-
* Useful for checking registry entries where you need the actual registered token.
|
|
109
|
-
*
|
|
110
|
-
* @param token Any injectable type
|
|
111
|
-
* @returns The underlying InjectionToken
|
|
112
|
-
*/
|
|
113
|
-
getRegistryToken<T = unknown>(token: AnyInjectableType): InjectionToken<T> {
|
|
114
|
-
return this.getRealToken(this.normalizeToken(token))
|
|
115
|
-
}
|
|
116
|
-
|
|
117
|
-
// ============================================================================
|
|
118
|
-
// TOKEN VALIDATION
|
|
119
|
-
// ============================================================================
|
|
120
|
-
|
|
121
|
-
/**
|
|
122
|
-
* Validates and resolves token arguments, handling factory token resolution and validation.
|
|
123
|
-
*/
|
|
124
|
-
validateAndResolveTokenArgs(
|
|
125
|
-
token: AnyInjectableType,
|
|
126
|
-
args?: any,
|
|
127
|
-
): [
|
|
128
|
-
DIError | undefined,
|
|
129
|
-
{ actualToken: InjectionTokenType; validatedArgs?: any },
|
|
130
|
-
] {
|
|
131
|
-
let actualToken = token as InjectionToken<any, any>
|
|
132
|
-
if (typeof token === 'function') {
|
|
133
|
-
actualToken = getInjectableToken(token)
|
|
134
|
-
}
|
|
135
|
-
let realArgs = args
|
|
136
|
-
if (actualToken instanceof BoundInjectionToken) {
|
|
137
|
-
realArgs = actualToken.value
|
|
138
|
-
} else if (actualToken instanceof FactoryInjectionToken) {
|
|
139
|
-
if (actualToken.resolved) {
|
|
140
|
-
realArgs = actualToken.value
|
|
141
|
-
} else {
|
|
142
|
-
return [DIError.factoryTokenNotResolved(token.name), { actualToken }]
|
|
143
|
-
}
|
|
144
|
-
}
|
|
145
|
-
if (!actualToken.schema) {
|
|
146
|
-
return [undefined, { actualToken, validatedArgs: realArgs }]
|
|
147
|
-
}
|
|
148
|
-
const validatedArgs = actualToken.schema?.safeParse(realArgs)
|
|
149
|
-
if (validatedArgs && !validatedArgs.success) {
|
|
150
|
-
this.logger?.error(
|
|
151
|
-
`[TokenProcessor]#validateAndResolveTokenArgs(): Error validating args for ${actualToken.name.toString()}`,
|
|
152
|
-
validatedArgs.error,
|
|
153
|
-
)
|
|
154
|
-
return [DIError.unknown(validatedArgs.error), { actualToken }]
|
|
155
|
-
}
|
|
156
|
-
return [undefined, { actualToken, validatedArgs: validatedArgs?.data }]
|
|
157
|
-
}
|
|
158
|
-
|
|
159
|
-
/**
|
|
160
|
-
* Generates a unique instance name based on token and arguments.
|
|
161
|
-
* Results are cached using an LRU cache for performance.
|
|
162
|
-
*/
|
|
163
|
-
generateInstanceName(token: InjectionTokenType, args: any): string {
|
|
164
|
-
if (!args) {
|
|
165
|
-
return token.toString()
|
|
166
|
-
}
|
|
167
|
-
|
|
168
|
-
// Create a cache key from token id and args
|
|
169
|
-
const tokenStr = token.toString()
|
|
170
|
-
const cacheKey = `${tokenStr}:${JSON.stringify(args)}`
|
|
171
|
-
|
|
172
|
-
// Check cache first
|
|
173
|
-
const cached = this.instanceNameCache.get(cacheKey)
|
|
174
|
-
if (cached !== undefined) {
|
|
175
|
-
return cached
|
|
176
|
-
}
|
|
177
|
-
|
|
178
|
-
// Generate the instance name
|
|
179
|
-
const formattedArgs = Object.entries(args)
|
|
180
|
-
.sort(([keyA], [keyB]) => keyA.localeCompare(keyB))
|
|
181
|
-
.map(([key, value]) => `${key}=${this.formatArgValue(value)}`)
|
|
182
|
-
.join(',')
|
|
183
|
-
|
|
184
|
-
const result = `${tokenStr}:${formattedArgs.replaceAll(/"/g, '').replaceAll(/:/g, '=')}`
|
|
185
|
-
|
|
186
|
-
// Cache the result
|
|
187
|
-
this.instanceNameCache.set(cacheKey, result)
|
|
188
|
-
|
|
189
|
-
return result
|
|
190
|
-
}
|
|
191
|
-
|
|
192
|
-
/**
|
|
193
|
-
* Formats a single argument value for instance name generation.
|
|
194
|
-
*/
|
|
195
|
-
formatArgValue(value: any): string {
|
|
196
|
-
if (typeof value === 'function') {
|
|
197
|
-
return `fn_${value.name}(${value.length})`
|
|
198
|
-
}
|
|
199
|
-
if (typeof value === 'symbol') {
|
|
200
|
-
return value.toString()
|
|
201
|
-
}
|
|
202
|
-
return JSON.stringify(value).slice(0, 40)
|
|
203
|
-
}
|
|
204
|
-
|
|
205
|
-
/**
|
|
206
|
-
* Creates a factory context for dependency injection during service instantiation.
|
|
207
|
-
* @param container The container instance (Container or ScopedContainer) for dependency resolution
|
|
208
|
-
* @param onDependencyResolved Callback when a dependency is resolved, receives the instance name
|
|
209
|
-
*/
|
|
210
|
-
createFactoryContext(
|
|
211
|
-
container: IContainer,
|
|
212
|
-
onDependencyResolved?: (instanceName: string) => void,
|
|
213
|
-
): FactoryContext & {
|
|
214
|
-
getDestroyListeners: () => (() => void)[]
|
|
215
|
-
deps: Set<string>
|
|
216
|
-
} {
|
|
217
|
-
const destroyListeners = new Set<() => void>()
|
|
218
|
-
const deps = new Set<string>()
|
|
219
|
-
|
|
220
|
-
function addDestroyListener(listener: () => void) {
|
|
221
|
-
destroyListeners.add(listener)
|
|
222
|
-
}
|
|
223
|
-
|
|
224
|
-
function getDestroyListeners() {
|
|
225
|
-
return Array.from(destroyListeners)
|
|
226
|
-
}
|
|
227
|
-
|
|
228
|
-
const self = this
|
|
229
|
-
|
|
230
|
-
return {
|
|
231
|
-
// @ts-expect-error This is correct type
|
|
232
|
-
async inject(token, args) {
|
|
233
|
-
// Get the instance name for dependency tracking
|
|
234
|
-
const actualToken =
|
|
235
|
-
typeof token === 'function' ? getInjectableToken(token) : token
|
|
236
|
-
const instanceName = self.generateInstanceName(actualToken, args)
|
|
237
|
-
deps.add(instanceName)
|
|
238
|
-
|
|
239
|
-
if (onDependencyResolved) {
|
|
240
|
-
onDependencyResolved(instanceName)
|
|
241
|
-
}
|
|
242
|
-
|
|
243
|
-
// Use the container's get method for resolution
|
|
244
|
-
return container.get(token, args)
|
|
245
|
-
},
|
|
246
|
-
addDestroyListener,
|
|
247
|
-
getDestroyListeners,
|
|
248
|
-
container,
|
|
249
|
-
deps,
|
|
250
|
-
}
|
|
251
|
-
}
|
|
252
|
-
}
|
|
@@ -1,334 +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
|
-
* Reverse dependency index: maps a dependency name to the set of holder names that depend on it.
|
|
24
|
-
* This allows O(1) lookup of dependents instead of O(n) iteration.
|
|
25
|
-
*/
|
|
26
|
-
protected readonly _dependents: Map<string, Set<string>>
|
|
27
|
-
|
|
28
|
-
constructor(protected readonly logger: Console | null = null) {
|
|
29
|
-
this._holders = new Map()
|
|
30
|
-
this._dependents = new Map()
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
/**
|
|
34
|
-
* Protected getter for accessing the holders map from subclasses.
|
|
35
|
-
*/
|
|
36
|
-
protected get holders(): Map<string, InstanceHolder> {
|
|
37
|
-
return this._holders
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
/**
|
|
41
|
-
* Abstract method to get a holder by name. Each implementation defines its own return type
|
|
42
|
-
* based on their specific error handling and validation needs.
|
|
43
|
-
*/
|
|
44
|
-
abstract get(name: string): any
|
|
45
|
-
|
|
46
|
-
/**
|
|
47
|
-
* Abstract method to set a holder by name. Each implementation may have different validation logic.
|
|
48
|
-
*/
|
|
49
|
-
abstract set(name: string, holder: InstanceHolder): void
|
|
50
|
-
|
|
51
|
-
/**
|
|
52
|
-
* Abstract method to check if a holder exists. Each implementation may have different validation logic.
|
|
53
|
-
*/
|
|
54
|
-
abstract has(name: string): any
|
|
55
|
-
|
|
56
|
-
/**
|
|
57
|
-
* Deletes a holder by name and cleans up the reverse dependency index.
|
|
58
|
-
* @param name The name of the holder to delete
|
|
59
|
-
* @returns true if the holder was deleted, false if it didn't exist
|
|
60
|
-
*/
|
|
61
|
-
delete(name: string): boolean {
|
|
62
|
-
const holder = this._holders.get(name)
|
|
63
|
-
if (holder) {
|
|
64
|
-
// Remove this holder from the reverse index for all its dependencies
|
|
65
|
-
this.removeFromDependentsIndex(name, holder.deps)
|
|
66
|
-
}
|
|
67
|
-
return this._holders.delete(name)
|
|
68
|
-
}
|
|
69
|
-
|
|
70
|
-
/**
|
|
71
|
-
* Registers a holder's dependencies in the reverse index.
|
|
72
|
-
* Call this after creating a holder with dependencies.
|
|
73
|
-
* @param holderName The name of the holder that has dependencies
|
|
74
|
-
* @param deps The set of dependency names
|
|
75
|
-
*/
|
|
76
|
-
registerDependencies(holderName: string, deps: Set<string>): void {
|
|
77
|
-
for (const dep of deps) {
|
|
78
|
-
let dependents = this._dependents.get(dep)
|
|
79
|
-
if (!dependents) {
|
|
80
|
-
dependents = new Set()
|
|
81
|
-
this._dependents.set(dep, dependents)
|
|
82
|
-
}
|
|
83
|
-
dependents.add(holderName)
|
|
84
|
-
}
|
|
85
|
-
}
|
|
86
|
-
|
|
87
|
-
/**
|
|
88
|
-
* Removes a holder from the reverse dependency index.
|
|
89
|
-
* @param holderName The name of the holder to remove
|
|
90
|
-
* @param deps The set of dependency names to clean up
|
|
91
|
-
*/
|
|
92
|
-
protected removeFromDependentsIndex(holderName: string, deps: Set<string>): void {
|
|
93
|
-
for (const dep of deps) {
|
|
94
|
-
const dependents = this._dependents.get(dep)
|
|
95
|
-
if (dependents) {
|
|
96
|
-
dependents.delete(holderName)
|
|
97
|
-
if (dependents.size === 0) {
|
|
98
|
-
this._dependents.delete(dep)
|
|
99
|
-
}
|
|
100
|
-
}
|
|
101
|
-
}
|
|
102
|
-
}
|
|
103
|
-
|
|
104
|
-
/**
|
|
105
|
-
* Gets all holder names that depend on the given instance name.
|
|
106
|
-
* O(1) lookup using the reverse dependency index.
|
|
107
|
-
* @param instanceName The instance name to find dependents for
|
|
108
|
-
* @returns Array of holder names that depend on this instance
|
|
109
|
-
*/
|
|
110
|
-
getDependents(instanceName: string): string[] {
|
|
111
|
-
const dependents = this._dependents.get(instanceName)
|
|
112
|
-
return dependents ? Array.from(dependents) : []
|
|
113
|
-
}
|
|
114
|
-
|
|
115
|
-
/**
|
|
116
|
-
* Filters holders based on a predicate function.
|
|
117
|
-
* @param predicate Function to test each holder
|
|
118
|
-
* @returns A new Map containing only the holders that match the predicate
|
|
119
|
-
* @deprecated Use forEachHolder() for iteration to avoid allocations
|
|
120
|
-
*/
|
|
121
|
-
filter(
|
|
122
|
-
predicate: (value: InstanceHolder<any>, key: string) => boolean,
|
|
123
|
-
): Map<string, InstanceHolder> {
|
|
124
|
-
const result = new Map<string, InstanceHolder>()
|
|
125
|
-
for (const [key, value] of this._holders) {
|
|
126
|
-
if (predicate(value, key)) {
|
|
127
|
-
result.set(key, value)
|
|
128
|
-
}
|
|
129
|
-
}
|
|
130
|
-
return result
|
|
131
|
-
}
|
|
132
|
-
|
|
133
|
-
/**
|
|
134
|
-
* Iterates over holders with a callback. More efficient than filter() as it
|
|
135
|
-
* avoids creating intermediate arrays and Maps.
|
|
136
|
-
* @param callback Function called for each holder with (holder, name)
|
|
137
|
-
*/
|
|
138
|
-
forEachHolder(
|
|
139
|
-
callback: (holder: InstanceHolder<any>, name: string) => void,
|
|
140
|
-
): void {
|
|
141
|
-
for (const [name, holder] of this._holders) {
|
|
142
|
-
callback(holder, name)
|
|
143
|
-
}
|
|
144
|
-
}
|
|
145
|
-
|
|
146
|
-
/**
|
|
147
|
-
* Finds the first holder matching a predicate. More efficient than filter()
|
|
148
|
-
* when only one result is needed.
|
|
149
|
-
* @param predicate Function to test each holder
|
|
150
|
-
* @returns The first matching holder or undefined
|
|
151
|
-
*/
|
|
152
|
-
findHolder(
|
|
153
|
-
predicate: (holder: InstanceHolder<any>, name: string) => boolean,
|
|
154
|
-
): InstanceHolder | undefined {
|
|
155
|
-
for (const [name, holder] of this._holders) {
|
|
156
|
-
if (predicate(holder, name)) {
|
|
157
|
-
return holder
|
|
158
|
-
}
|
|
159
|
-
}
|
|
160
|
-
return undefined
|
|
161
|
-
}
|
|
162
|
-
|
|
163
|
-
/**
|
|
164
|
-
* Clears all holders from this manager and the reverse dependency index.
|
|
165
|
-
*/
|
|
166
|
-
clear(): void {
|
|
167
|
-
this._holders.clear()
|
|
168
|
-
this._dependents.clear()
|
|
169
|
-
}
|
|
170
|
-
|
|
171
|
-
/**
|
|
172
|
-
* Gets the number of holders currently managed.
|
|
173
|
-
*/
|
|
174
|
-
size(): number {
|
|
175
|
-
return this._holders.size
|
|
176
|
-
}
|
|
177
|
-
|
|
178
|
-
/**
|
|
179
|
-
* Creates a new holder with Creating status and a deferred creation promise.
|
|
180
|
-
* This is useful for creating placeholder holders that can be fulfilled later.
|
|
181
|
-
* @param name The name of the instance
|
|
182
|
-
* @param type The injectable type
|
|
183
|
-
* @param scope The injectable scope
|
|
184
|
-
* @param deps Optional set of dependencies
|
|
185
|
-
* @returns A tuple containing the deferred promise and the holder
|
|
186
|
-
*/
|
|
187
|
-
createCreatingHolder<Instance>(
|
|
188
|
-
name: string,
|
|
189
|
-
type: InjectableType,
|
|
190
|
-
scope: InjectableScope,
|
|
191
|
-
deps: Set<string> = new Set(),
|
|
192
|
-
): [
|
|
193
|
-
ReturnType<typeof Promise.withResolvers<[undefined, Instance]>>,
|
|
194
|
-
InstanceHolder<Instance>,
|
|
195
|
-
] {
|
|
196
|
-
const deferred = Promise.withResolvers<[undefined, Instance]>()
|
|
197
|
-
|
|
198
|
-
const holder: InstanceHolder<Instance> = {
|
|
199
|
-
status: InstanceStatus.Creating,
|
|
200
|
-
name,
|
|
201
|
-
instance: null,
|
|
202
|
-
creationPromise: deferred.promise,
|
|
203
|
-
destroyPromise: null,
|
|
204
|
-
type,
|
|
205
|
-
scope,
|
|
206
|
-
deps,
|
|
207
|
-
destroyListeners: [],
|
|
208
|
-
createdAt: Date.now(),
|
|
209
|
-
waitingFor: new Set(),
|
|
210
|
-
}
|
|
211
|
-
|
|
212
|
-
return [deferred, holder]
|
|
213
|
-
}
|
|
214
|
-
|
|
215
|
-
/**
|
|
216
|
-
* Creates a new holder with Created status and an actual instance.
|
|
217
|
-
* This is useful for creating holders that already have their instance ready.
|
|
218
|
-
* @param name The name of the instance
|
|
219
|
-
* @param instance The actual instance to store
|
|
220
|
-
* @param type The injectable type
|
|
221
|
-
* @param scope The injectable scope
|
|
222
|
-
* @param deps Optional set of dependencies
|
|
223
|
-
* @returns The created holder
|
|
224
|
-
*/
|
|
225
|
-
protected createCreatedHolder<Instance>(
|
|
226
|
-
name: string,
|
|
227
|
-
instance: Instance,
|
|
228
|
-
type: InjectableType,
|
|
229
|
-
scope: InjectableScope,
|
|
230
|
-
deps: Set<string> = new Set(),
|
|
231
|
-
): InstanceHolder<Instance> {
|
|
232
|
-
const holder: InstanceHolder<Instance> = {
|
|
233
|
-
status: InstanceStatus.Created,
|
|
234
|
-
name,
|
|
235
|
-
instance,
|
|
236
|
-
creationPromise: null,
|
|
237
|
-
destroyPromise: null,
|
|
238
|
-
type,
|
|
239
|
-
scope,
|
|
240
|
-
deps,
|
|
241
|
-
destroyListeners: [],
|
|
242
|
-
createdAt: Date.now(),
|
|
243
|
-
waitingFor: new Set(),
|
|
244
|
-
}
|
|
245
|
-
|
|
246
|
-
return holder
|
|
247
|
-
}
|
|
248
|
-
|
|
249
|
-
/**
|
|
250
|
-
* Gets all holder names currently managed.
|
|
251
|
-
*/
|
|
252
|
-
getAllNames(): string[] {
|
|
253
|
-
return Array.from(this._holders.keys())
|
|
254
|
-
}
|
|
255
|
-
|
|
256
|
-
/**
|
|
257
|
-
* Gets all holders currently managed.
|
|
258
|
-
*/
|
|
259
|
-
getAllHolders(): InstanceHolder[] {
|
|
260
|
-
return Array.from(this._holders.values())
|
|
261
|
-
}
|
|
262
|
-
|
|
263
|
-
/**
|
|
264
|
-
* Checks if this manager has any holders.
|
|
265
|
-
*/
|
|
266
|
-
isEmpty(): boolean {
|
|
267
|
-
return this._holders.size === 0
|
|
268
|
-
}
|
|
269
|
-
|
|
270
|
-
/**
|
|
271
|
-
* Waits for a holder to be ready and returns the appropriate result.
|
|
272
|
-
* This is a shared utility used by both singleton and request-scoped resolution.
|
|
273
|
-
*
|
|
274
|
-
* @param holder The holder to wait for
|
|
275
|
-
* @param waiterHolder Optional holder that is doing the waiting (for circular dependency detection)
|
|
276
|
-
* @param getHolder Optional function to retrieve holders by name (required if waiterHolder is provided)
|
|
277
|
-
* @returns A promise that resolves with [undefined, holder] on success or [DIError] on failure
|
|
278
|
-
*/
|
|
279
|
-
static async waitForHolderReady<T>(
|
|
280
|
-
holder: InstanceHolder<T>,
|
|
281
|
-
waiterHolder?: InstanceHolder,
|
|
282
|
-
getHolder?: (name: string) => InstanceHolder | undefined,
|
|
283
|
-
): Promise<HolderReadyResult<T>> {
|
|
284
|
-
switch (holder.status) {
|
|
285
|
-
case InstanceStatus.Creating: {
|
|
286
|
-
// Check for circular dependency before waiting
|
|
287
|
-
if (waiterHolder && getHolder) {
|
|
288
|
-
const cycle = CircularDetector.detectCycle(
|
|
289
|
-
waiterHolder.name,
|
|
290
|
-
holder.name,
|
|
291
|
-
getHolder,
|
|
292
|
-
)
|
|
293
|
-
if (cycle) {
|
|
294
|
-
return [DIError.circularDependency(cycle)]
|
|
295
|
-
}
|
|
296
|
-
|
|
297
|
-
if (process.env.NODE_ENV !== 'production') {
|
|
298
|
-
// Track the waiting relationship
|
|
299
|
-
waiterHolder.waitingFor.add(holder.name)
|
|
300
|
-
}
|
|
301
|
-
}
|
|
302
|
-
|
|
303
|
-
try {
|
|
304
|
-
await holder.creationPromise
|
|
305
|
-
} finally {
|
|
306
|
-
if (process.env.NODE_ENV !== 'production') {
|
|
307
|
-
// Clean up the waiting relationship
|
|
308
|
-
if (waiterHolder) {
|
|
309
|
-
waiterHolder.waitingFor.delete(holder.name)
|
|
310
|
-
}
|
|
311
|
-
}
|
|
312
|
-
}
|
|
313
|
-
|
|
314
|
-
return BaseHolderManager.waitForHolderReady(
|
|
315
|
-
holder,
|
|
316
|
-
waiterHolder,
|
|
317
|
-
getHolder,
|
|
318
|
-
)
|
|
319
|
-
}
|
|
320
|
-
|
|
321
|
-
case InstanceStatus.Destroying:
|
|
322
|
-
return [DIError.instanceDestroying(holder.name)]
|
|
323
|
-
|
|
324
|
-
case InstanceStatus.Error:
|
|
325
|
-
return [holder.instance as unknown as DIError]
|
|
326
|
-
|
|
327
|
-
case InstanceStatus.Created:
|
|
328
|
-
return [undefined, holder]
|
|
329
|
-
|
|
330
|
-
default:
|
|
331
|
-
return [DIError.instanceNotFound('unknown')]
|
|
332
|
-
}
|
|
333
|
-
}
|
|
334
|
-
}
|
|
@@ -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
|
-
}
|