@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.
- package/CHANGELOG.md +110 -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 -1508
- package/lib/browser/index.mjs +29 -2650
- 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-Pb_Y4Z4x.mjs → container-8-z89TyQ.mjs} +1269 -1305
- package/lib/container-8-z89TyQ.mjs.map +1 -0
- package/lib/{container-BuAutHGg.d.mts → container-CNiqesCL.d.mts} +600 -569
- package/lib/container-CNiqesCL.d.mts.map +1 -0
- package/lib/{container-DnzgpfBe.cjs → container-CaY2fDuk.cjs} +1287 -1329
- package/lib/container-CaY2fDuk.cjs.map +1 -0
- package/lib/{container-oGTgX2iX.d.cts → container-D-0Ho3qL.d.cts} +601 -565
- 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 +461 -292
- 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-processor.mts → token-resolver.mts} +17 -88
- 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-BuAutHGg.d.mts.map +0 -1
- package/lib/container-DnzgpfBe.cjs.map +0 -1
- package/lib/container-Pb_Y4Z4x.mjs.map +0 -1
- package/lib/container-oGTgX2iX.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 -214
- package/src/internal/core/invalidator.mts +0 -437
- package/src/internal/core/service-locator.mts +0 -202
- package/src/internal/holder/base-holder-manager.mts +0 -238
- package/src/internal/holder/holder-manager.mts +0 -85
- package/src/internal/holder/request-storage.mts +0 -134
- package/src/internal/holder/singleton-storage.mts +0 -105
- package/src/testing/README.md +0 -80
- package/src/testing/__tests__/test-container.spec.mts +0 -173
|
@@ -1,335 +1,483 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { describe, expect, it, beforeEach } from 'vitest'
|
|
2
2
|
|
|
3
3
|
import { InjectableScope, InjectableType } from '../enums/index.mjs'
|
|
4
4
|
import { InjectionToken } from '../token/injection-token.mjs'
|
|
5
|
-
import {
|
|
6
|
-
|
|
7
|
-
class TestService {}
|
|
8
|
-
class AnotherService {}
|
|
5
|
+
import { Registry, globalRegistry } from '../token/registry.mjs'
|
|
9
6
|
|
|
10
7
|
describe('Registry', () => {
|
|
11
8
|
let registry: Registry
|
|
12
|
-
let token1: InjectionToken<TestService, undefined>
|
|
13
|
-
let token2: InjectionToken<AnotherService, undefined>
|
|
14
9
|
|
|
15
10
|
beforeEach(() => {
|
|
16
11
|
registry = new Registry()
|
|
17
|
-
token1 = new InjectionToken<TestService, undefined>(
|
|
18
|
-
'TestService',
|
|
19
|
-
undefined,
|
|
20
|
-
)
|
|
21
|
-
token2 = new InjectionToken<AnotherService, undefined>(
|
|
22
|
-
'AnotherService',
|
|
23
|
-
undefined,
|
|
24
|
-
)
|
|
25
12
|
})
|
|
26
13
|
|
|
27
|
-
describe('
|
|
28
|
-
it('should
|
|
29
|
-
const
|
|
30
|
-
expect(
|
|
14
|
+
describe('has', () => {
|
|
15
|
+
it('should return false for non-existent token', () => {
|
|
16
|
+
const token = InjectionToken.create<string>('test')
|
|
17
|
+
expect(registry.has(token)).toBe(false)
|
|
18
|
+
})
|
|
19
|
+
|
|
20
|
+
it('should return true for registered token', () => {
|
|
21
|
+
const token = InjectionToken.create<string>('test')
|
|
22
|
+
registry.set(token, InjectableScope.Singleton, class Test {}, InjectableType.Class)
|
|
23
|
+
|
|
24
|
+
expect(registry.has(token)).toBe(true)
|
|
31
25
|
})
|
|
32
26
|
|
|
33
|
-
it('should
|
|
27
|
+
it('should check parent registry', () => {
|
|
34
28
|
const parentRegistry = new Registry()
|
|
35
29
|
const childRegistry = new Registry(parentRegistry)
|
|
36
|
-
|
|
37
|
-
})
|
|
38
|
-
})
|
|
30
|
+
const token = InjectionToken.create<string>('test')
|
|
39
31
|
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
registry.set(
|
|
43
|
-
token1,
|
|
32
|
+
parentRegistry.set(
|
|
33
|
+
token,
|
|
44
34
|
InjectableScope.Singleton,
|
|
45
|
-
|
|
35
|
+
class Test {},
|
|
46
36
|
InjectableType.Class,
|
|
47
37
|
)
|
|
48
38
|
|
|
49
|
-
expect(
|
|
39
|
+
expect(childRegistry.has(token)).toBe(true)
|
|
50
40
|
})
|
|
41
|
+
})
|
|
42
|
+
|
|
43
|
+
describe('get', () => {
|
|
44
|
+
it('should return factory record for registered token', () => {
|
|
45
|
+
const token = InjectionToken.create<string>('test')
|
|
46
|
+
class TestClass {}
|
|
51
47
|
|
|
52
|
-
it('should set multiple factory records', () => {
|
|
53
48
|
registry.set(
|
|
54
|
-
|
|
49
|
+
token,
|
|
55
50
|
InjectableScope.Singleton,
|
|
56
|
-
|
|
51
|
+
TestClass,
|
|
57
52
|
InjectableType.Class,
|
|
53
|
+
10,
|
|
58
54
|
)
|
|
59
|
-
registry.set(
|
|
60
|
-
token2,
|
|
61
|
-
InjectableScope.Transient,
|
|
62
|
-
AnotherService,
|
|
63
|
-
InjectableType.Factory,
|
|
64
|
-
)
|
|
65
55
|
|
|
66
|
-
|
|
67
|
-
|
|
56
|
+
const record = registry.get(token)
|
|
57
|
+
|
|
58
|
+
expect(record.scope).toBe(InjectableScope.Singleton)
|
|
59
|
+
expect(record.target).toBe(TestClass)
|
|
60
|
+
expect(record.type).toBe(InjectableType.Class)
|
|
61
|
+
expect(record.priority).toBe(10)
|
|
62
|
+
expect(record.originalToken).toBe(token)
|
|
68
63
|
})
|
|
69
64
|
|
|
70
|
-
it('should
|
|
71
|
-
|
|
72
|
-
token1,
|
|
73
|
-
InjectableScope.Singleton,
|
|
74
|
-
TestService,
|
|
75
|
-
InjectableType.Class,
|
|
76
|
-
)
|
|
77
|
-
registry.set(
|
|
78
|
-
token1,
|
|
79
|
-
InjectableScope.Transient,
|
|
80
|
-
TestService,
|
|
81
|
-
InjectableType.Factory,
|
|
82
|
-
)
|
|
65
|
+
it('should throw for non-existent token', () => {
|
|
66
|
+
const token = InjectionToken.create<string>('test')
|
|
83
67
|
|
|
84
|
-
|
|
85
|
-
expect(record.scope).toBe(InjectableScope.Transient)
|
|
86
|
-
expect(record.type).toBe(InjectableType.Factory)
|
|
68
|
+
expect(() => registry.get(token)).toThrow()
|
|
87
69
|
})
|
|
88
|
-
})
|
|
89
70
|
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
71
|
+
it('should get from parent registry', () => {
|
|
72
|
+
const parentRegistry = new Registry()
|
|
73
|
+
const childRegistry = new Registry(parentRegistry)
|
|
74
|
+
const token = InjectionToken.create<string>('test')
|
|
75
|
+
class TestClass {}
|
|
94
76
|
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
token1,
|
|
77
|
+
parentRegistry.set(
|
|
78
|
+
token,
|
|
98
79
|
InjectableScope.Singleton,
|
|
99
|
-
|
|
80
|
+
TestClass,
|
|
100
81
|
InjectableType.Class,
|
|
101
82
|
)
|
|
102
|
-
|
|
83
|
+
|
|
84
|
+
const record = childRegistry.get(token)
|
|
85
|
+
expect(record.target).toBe(TestClass)
|
|
103
86
|
})
|
|
104
87
|
|
|
105
|
-
it('should
|
|
88
|
+
it('should prefer child registry over parent', () => {
|
|
106
89
|
const parentRegistry = new Registry()
|
|
107
90
|
const childRegistry = new Registry(parentRegistry)
|
|
91
|
+
const token = InjectionToken.create<string>('test')
|
|
92
|
+
class ParentClass {}
|
|
93
|
+
class ChildClass {}
|
|
108
94
|
|
|
109
95
|
parentRegistry.set(
|
|
110
|
-
|
|
96
|
+
token,
|
|
97
|
+
InjectableScope.Singleton,
|
|
98
|
+
ParentClass,
|
|
99
|
+
InjectableType.Class,
|
|
100
|
+
)
|
|
101
|
+
childRegistry.set(
|
|
102
|
+
token,
|
|
111
103
|
InjectableScope.Singleton,
|
|
112
|
-
|
|
104
|
+
ChildClass,
|
|
113
105
|
InjectableType.Class,
|
|
106
|
+
1, // Higher priority
|
|
114
107
|
)
|
|
115
108
|
|
|
116
|
-
|
|
109
|
+
const record = childRegistry.get(token)
|
|
110
|
+
expect(record.target).toBe(ChildClass)
|
|
117
111
|
})
|
|
112
|
+
})
|
|
118
113
|
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
const
|
|
114
|
+
describe('getAll', () => {
|
|
115
|
+
it('should return empty array for non-existent token', () => {
|
|
116
|
+
const token = InjectionToken.create<string>('test')
|
|
117
|
+
|
|
118
|
+
const records = registry.getAll(token)
|
|
119
|
+
expect(records).toEqual([])
|
|
120
|
+
})
|
|
122
121
|
|
|
123
|
-
|
|
122
|
+
it('should return all records sorted by priority (highest first)', () => {
|
|
123
|
+
const token = InjectionToken.create<string>('test')
|
|
124
|
+
class ClassA {}
|
|
125
|
+
class ClassB {}
|
|
126
|
+
class ClassC {}
|
|
127
|
+
|
|
128
|
+
registry.set(token, InjectableScope.Singleton, ClassA, InjectableType.Class, 5)
|
|
129
|
+
registry.set(token, InjectableScope.Singleton, ClassB, InjectableType.Class, 10)
|
|
130
|
+
registry.set(token, InjectableScope.Singleton, ClassC, InjectableType.Class, 1)
|
|
131
|
+
|
|
132
|
+
const records = registry.getAll(token)
|
|
133
|
+
|
|
134
|
+
expect(records).toHaveLength(3)
|
|
135
|
+
expect(records[0].target).toBe(ClassB) // priority 10
|
|
136
|
+
expect(records[1].target).toBe(ClassA) // priority 5
|
|
137
|
+
expect(records[2].target).toBe(ClassC) // priority 1
|
|
124
138
|
})
|
|
125
139
|
|
|
126
|
-
it('should
|
|
140
|
+
it('should get from parent if not in child', () => {
|
|
127
141
|
const parentRegistry = new Registry()
|
|
128
142
|
const childRegistry = new Registry(parentRegistry)
|
|
143
|
+
const token = InjectionToken.create<string>('test')
|
|
144
|
+
class TestClass {}
|
|
129
145
|
|
|
130
146
|
parentRegistry.set(
|
|
131
|
-
|
|
147
|
+
token,
|
|
132
148
|
InjectableScope.Singleton,
|
|
133
|
-
|
|
149
|
+
TestClass,
|
|
134
150
|
InjectableType.Class,
|
|
135
151
|
)
|
|
136
|
-
childRegistry.set(
|
|
137
|
-
token1,
|
|
138
|
-
InjectableScope.Transient,
|
|
139
|
-
TestService,
|
|
140
|
-
InjectableType.Factory,
|
|
141
|
-
)
|
|
142
152
|
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
expect(
|
|
153
|
+
const records = childRegistry.getAll(token)
|
|
154
|
+
expect(records).toHaveLength(1)
|
|
155
|
+
expect(records[0].target).toBe(TestClass)
|
|
146
156
|
})
|
|
147
157
|
})
|
|
148
158
|
|
|
149
|
-
describe('
|
|
150
|
-
it('should
|
|
159
|
+
describe('set', () => {
|
|
160
|
+
it('should register factory with default priority 0', () => {
|
|
161
|
+
const token = InjectionToken.create<string>('test')
|
|
162
|
+
class TestClass {}
|
|
163
|
+
|
|
164
|
+
registry.set(token, InjectableScope.Singleton, TestClass, InjectableType.Class)
|
|
165
|
+
|
|
166
|
+
const record = registry.get(token)
|
|
167
|
+
expect(record.priority).toBe(0)
|
|
168
|
+
})
|
|
169
|
+
|
|
170
|
+
it('should register factory with custom priority', () => {
|
|
171
|
+
const token = InjectionToken.create<string>('test')
|
|
172
|
+
class TestClass {}
|
|
173
|
+
|
|
151
174
|
registry.set(
|
|
152
|
-
|
|
175
|
+
token,
|
|
153
176
|
InjectableScope.Singleton,
|
|
154
|
-
|
|
177
|
+
TestClass,
|
|
155
178
|
InjectableType.Class,
|
|
179
|
+
100,
|
|
156
180
|
)
|
|
157
181
|
|
|
158
|
-
const record = registry.get(
|
|
159
|
-
expect(record.
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
182
|
+
const record = registry.get(token)
|
|
183
|
+
expect(record.priority).toBe(100)
|
|
184
|
+
})
|
|
185
|
+
|
|
186
|
+
it('should support multiple registrations for same token', () => {
|
|
187
|
+
const token = InjectionToken.create<string>('test')
|
|
188
|
+
class ClassA {}
|
|
189
|
+
class ClassB {}
|
|
190
|
+
|
|
191
|
+
registry.set(token, InjectableScope.Singleton, ClassA, InjectableType.Class, 0)
|
|
192
|
+
registry.set(token, InjectableScope.Singleton, ClassB, InjectableType.Class, 1)
|
|
193
|
+
|
|
194
|
+
const records = registry.getAll(token)
|
|
195
|
+
expect(records).toHaveLength(2)
|
|
196
|
+
})
|
|
197
|
+
|
|
198
|
+
it('should update highest priority cache when new registration is higher', () => {
|
|
199
|
+
const token = InjectionToken.create<string>('test')
|
|
200
|
+
class ClassA {}
|
|
201
|
+
class ClassB {}
|
|
202
|
+
|
|
203
|
+
registry.set(token, InjectableScope.Singleton, ClassA, InjectableType.Class, 5)
|
|
204
|
+
expect(registry.get(token).target).toBe(ClassA)
|
|
205
|
+
|
|
206
|
+
registry.set(token, InjectableScope.Singleton, ClassB, InjectableType.Class, 10)
|
|
207
|
+
expect(registry.get(token).target).toBe(ClassB)
|
|
208
|
+
})
|
|
209
|
+
|
|
210
|
+
it('should not update highest priority cache when new registration is lower', () => {
|
|
211
|
+
const token = InjectionToken.create<string>('test')
|
|
212
|
+
class ClassA {}
|
|
213
|
+
class ClassB {}
|
|
214
|
+
|
|
215
|
+
registry.set(token, InjectableScope.Singleton, ClassA, InjectableType.Class, 10)
|
|
216
|
+
registry.set(token, InjectableScope.Singleton, ClassB, InjectableType.Class, 5)
|
|
217
|
+
|
|
218
|
+
expect(registry.get(token).target).toBe(ClassA)
|
|
219
|
+
})
|
|
220
|
+
})
|
|
221
|
+
|
|
222
|
+
describe('delete', () => {
|
|
223
|
+
it('should remove token registration', () => {
|
|
224
|
+
const token = InjectionToken.create<string>('test')
|
|
225
|
+
class TestClass {}
|
|
226
|
+
|
|
227
|
+
registry.set(token, InjectableScope.Singleton, TestClass, InjectableType.Class)
|
|
228
|
+
expect(registry.has(token)).toBe(true)
|
|
229
|
+
|
|
230
|
+
registry.delete(token)
|
|
231
|
+
expect(registry.has(token)).toBe(false)
|
|
232
|
+
})
|
|
233
|
+
|
|
234
|
+
it('should handle deleting non-existent token', () => {
|
|
235
|
+
const token = InjectionToken.create<string>('test')
|
|
236
|
+
|
|
237
|
+
// Should not throw
|
|
238
|
+
registry.delete(token)
|
|
239
|
+
})
|
|
240
|
+
|
|
241
|
+
it('should remove highest priority and keep lower priority registrations', () => {
|
|
242
|
+
const token = InjectionToken.create<string>('test')
|
|
243
|
+
class ClassA {}
|
|
244
|
+
class ClassB {}
|
|
245
|
+
|
|
246
|
+
registry.set(token, InjectableScope.Singleton, ClassA, InjectableType.Class, 5)
|
|
247
|
+
registry.set(token, InjectableScope.Singleton, ClassB, InjectableType.Class, 10)
|
|
248
|
+
|
|
249
|
+
expect(registry.get(token).target).toBe(ClassB)
|
|
250
|
+
expect(registry.getAll(token)).toHaveLength(2)
|
|
251
|
+
|
|
252
|
+
// Delete removes highest priority and recalculates
|
|
253
|
+
registry.delete(token)
|
|
254
|
+
|
|
255
|
+
// Lower priority registration (ClassA) should remain
|
|
256
|
+
expect(registry.getAll(token)).toHaveLength(1)
|
|
257
|
+
expect(registry.get(token).target).toBe(ClassA)
|
|
258
|
+
})
|
|
259
|
+
})
|
|
260
|
+
|
|
261
|
+
describe('updateScope', () => {
|
|
262
|
+
it('should update scope of registered token', () => {
|
|
263
|
+
const token = InjectionToken.create<string>('test')
|
|
264
|
+
class TestClass {}
|
|
265
|
+
|
|
266
|
+
registry.set(token, InjectableScope.Singleton, TestClass, InjectableType.Class)
|
|
267
|
+
expect(registry.get(token).scope).toBe(InjectableScope.Singleton)
|
|
268
|
+
|
|
269
|
+
const result = registry.updateScope(token, InjectableScope.Request)
|
|
270
|
+
|
|
271
|
+
expect(result).toBe(true)
|
|
272
|
+
expect(registry.get(token).scope).toBe(InjectableScope.Request)
|
|
273
|
+
})
|
|
274
|
+
|
|
275
|
+
it('should return false for non-existent token', () => {
|
|
276
|
+
const token = InjectionToken.create<string>('test')
|
|
277
|
+
|
|
278
|
+
const result = registry.updateScope(token, InjectableScope.Request)
|
|
279
|
+
|
|
280
|
+
expect(result).toBe(false)
|
|
163
281
|
})
|
|
164
282
|
|
|
165
|
-
it('should
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
283
|
+
it('should update all records for the token', () => {
|
|
284
|
+
const token = InjectionToken.create<string>('test')
|
|
285
|
+
class ClassA {}
|
|
286
|
+
class ClassB {}
|
|
287
|
+
|
|
288
|
+
registry.set(token, InjectableScope.Singleton, ClassA, InjectableType.Class, 0)
|
|
289
|
+
registry.set(token, InjectableScope.Singleton, ClassB, InjectableType.Class, 1)
|
|
290
|
+
|
|
291
|
+
registry.updateScope(token, InjectableScope.Request)
|
|
292
|
+
|
|
293
|
+
const records = registry.getAll(token)
|
|
294
|
+
expect(records[0].scope).toBe(InjectableScope.Request)
|
|
295
|
+
expect(records[1].scope).toBe(InjectableScope.Request)
|
|
169
296
|
})
|
|
170
297
|
|
|
171
|
-
it('should
|
|
298
|
+
it('should delegate to parent if not found in child', () => {
|
|
172
299
|
const parentRegistry = new Registry()
|
|
173
300
|
const childRegistry = new Registry(parentRegistry)
|
|
301
|
+
const token = InjectionToken.create<string>('test')
|
|
302
|
+
class TestClass {}
|
|
174
303
|
|
|
175
304
|
parentRegistry.set(
|
|
176
|
-
|
|
305
|
+
token,
|
|
177
306
|
InjectableScope.Singleton,
|
|
178
|
-
|
|
307
|
+
TestClass,
|
|
179
308
|
InjectableType.Class,
|
|
180
309
|
)
|
|
181
310
|
|
|
182
|
-
const
|
|
183
|
-
expect(record.scope).toBe(InjectableScope.Singleton)
|
|
184
|
-
expect(record.target).toBe(TestService)
|
|
185
|
-
})
|
|
186
|
-
|
|
187
|
-
it('should throw error when token not found in parent chain', () => {
|
|
188
|
-
const parentRegistry = new Registry()
|
|
189
|
-
const childRegistry = new Registry(parentRegistry)
|
|
311
|
+
const result = childRegistry.updateScope(token, InjectableScope.Transient)
|
|
190
312
|
|
|
191
|
-
expect(()
|
|
192
|
-
|
|
193
|
-
}).toThrow(`[Registry] No factory found for ${token1.toString()}`)
|
|
313
|
+
expect(result).toBe(true)
|
|
314
|
+
expect(parentRegistry.get(token).scope).toBe(InjectableScope.Transient)
|
|
194
315
|
})
|
|
316
|
+
})
|
|
195
317
|
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
const
|
|
318
|
+
describe('priority system', () => {
|
|
319
|
+
it('should respect priority when getting the active registration', () => {
|
|
320
|
+
const token = InjectionToken.create<string>('test')
|
|
321
|
+
class DefaultImpl {}
|
|
322
|
+
class OverrideImpl {}
|
|
323
|
+
class HighPriorityImpl {}
|
|
199
324
|
|
|
200
|
-
|
|
201
|
-
|
|
325
|
+
registry.set(
|
|
326
|
+
token,
|
|
202
327
|
InjectableScope.Singleton,
|
|
203
|
-
|
|
328
|
+
DefaultImpl,
|
|
204
329
|
InjectableType.Class,
|
|
330
|
+
0,
|
|
205
331
|
)
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
InjectableScope.
|
|
209
|
-
|
|
210
|
-
InjectableType.
|
|
332
|
+
registry.set(
|
|
333
|
+
token,
|
|
334
|
+
InjectableScope.Singleton,
|
|
335
|
+
OverrideImpl,
|
|
336
|
+
InjectableType.Class,
|
|
337
|
+
1,
|
|
338
|
+
)
|
|
339
|
+
registry.set(
|
|
340
|
+
token,
|
|
341
|
+
InjectableScope.Singleton,
|
|
342
|
+
HighPriorityImpl,
|
|
343
|
+
InjectableType.Class,
|
|
344
|
+
100,
|
|
211
345
|
)
|
|
212
346
|
|
|
213
|
-
|
|
214
|
-
expect(record.scope).toBe(InjectableScope.Transient)
|
|
215
|
-
expect(record.target).toBe(AnotherService)
|
|
216
|
-
expect(record.type).toBe(InjectableType.Factory)
|
|
347
|
+
expect(registry.get(token).target).toBe(HighPriorityImpl)
|
|
217
348
|
})
|
|
218
|
-
})
|
|
219
349
|
|
|
220
|
-
|
|
221
|
-
|
|
350
|
+
it('should use first registration if priorities are equal', () => {
|
|
351
|
+
const token = InjectionToken.create<string>('test')
|
|
352
|
+
class FirstImpl {}
|
|
353
|
+
class SecondImpl {}
|
|
354
|
+
|
|
355
|
+
registry.set(
|
|
356
|
+
token,
|
|
357
|
+
InjectableScope.Singleton,
|
|
358
|
+
FirstImpl,
|
|
359
|
+
InjectableType.Class,
|
|
360
|
+
5,
|
|
361
|
+
)
|
|
222
362
|
registry.set(
|
|
223
|
-
|
|
363
|
+
token,
|
|
224
364
|
InjectableScope.Singleton,
|
|
225
|
-
|
|
365
|
+
SecondImpl,
|
|
226
366
|
InjectableType.Class,
|
|
367
|
+
5,
|
|
227
368
|
)
|
|
228
|
-
expect(registry.has(token1)).toBe(true)
|
|
229
369
|
|
|
230
|
-
|
|
231
|
-
expect(registry.
|
|
370
|
+
// With equal priority, the first one stays as highest
|
|
371
|
+
expect(registry.get(token).target).toBe(FirstImpl)
|
|
232
372
|
})
|
|
233
373
|
|
|
234
|
-
it('should
|
|
235
|
-
const
|
|
236
|
-
|
|
374
|
+
it('should support negative priorities', () => {
|
|
375
|
+
const token = InjectionToken.create<string>('test')
|
|
376
|
+
class LowPriority {}
|
|
377
|
+
class DefaultPriority {}
|
|
237
378
|
|
|
238
|
-
|
|
239
|
-
|
|
379
|
+
registry.set(
|
|
380
|
+
token,
|
|
240
381
|
InjectableScope.Singleton,
|
|
241
|
-
|
|
382
|
+
LowPriority,
|
|
242
383
|
InjectableType.Class,
|
|
384
|
+
-10,
|
|
243
385
|
)
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
InjectableScope.
|
|
247
|
-
|
|
386
|
+
registry.set(
|
|
387
|
+
token,
|
|
388
|
+
InjectableScope.Singleton,
|
|
389
|
+
DefaultPriority,
|
|
390
|
+
InjectableType.Class,
|
|
391
|
+
0,
|
|
392
|
+
)
|
|
393
|
+
|
|
394
|
+
expect(registry.get(token).target).toBe(DefaultPriority)
|
|
395
|
+
})
|
|
396
|
+
})
|
|
397
|
+
|
|
398
|
+
describe('factory types', () => {
|
|
399
|
+
it('should support Class type factories', () => {
|
|
400
|
+
const token = InjectionToken.create<string>('test')
|
|
401
|
+
class TestClass {}
|
|
402
|
+
|
|
403
|
+
registry.set(token, InjectableScope.Singleton, TestClass, InjectableType.Class)
|
|
404
|
+
|
|
405
|
+
expect(registry.get(token).type).toBe(InjectableType.Class)
|
|
406
|
+
})
|
|
407
|
+
|
|
408
|
+
it('should support Factory type factories', () => {
|
|
409
|
+
const token = InjectionToken.create<string>('test')
|
|
410
|
+
class TestFactory {
|
|
411
|
+
create() {
|
|
412
|
+
return 'test'
|
|
413
|
+
}
|
|
414
|
+
}
|
|
415
|
+
|
|
416
|
+
registry.set(
|
|
417
|
+
token,
|
|
418
|
+
InjectableScope.Singleton,
|
|
419
|
+
TestFactory,
|
|
248
420
|
InjectableType.Factory,
|
|
249
421
|
)
|
|
250
422
|
|
|
251
|
-
|
|
423
|
+
expect(registry.get(token).type).toBe(InjectableType.Factory)
|
|
424
|
+
})
|
|
425
|
+
})
|
|
252
426
|
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
const record = childRegistry.get(token1)
|
|
257
|
-
expect(record.scope).toBe(InjectableScope.Singleton) // From parent
|
|
427
|
+
describe('globalRegistry', () => {
|
|
428
|
+
it('should be a singleton Registry instance', () => {
|
|
429
|
+
expect(globalRegistry).toBeInstanceOf(Registry)
|
|
258
430
|
})
|
|
259
431
|
|
|
260
|
-
it('should
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
432
|
+
it('should not have a parent', () => {
|
|
433
|
+
// We can verify this indirectly by checking that non-existent tokens
|
|
434
|
+
// throw without delegating to a parent
|
|
435
|
+
const token = InjectionToken.create<string>('non-existent-global-test')
|
|
436
|
+
expect(() => globalRegistry.get(token)).toThrow()
|
|
264
437
|
})
|
|
265
438
|
})
|
|
266
439
|
|
|
267
|
-
describe('
|
|
268
|
-
it('should
|
|
269
|
-
const
|
|
270
|
-
const parent = new Registry(grandParent)
|
|
440
|
+
describe('parent-child relationship', () => {
|
|
441
|
+
it('should allow overriding parent registrations in child', () => {
|
|
442
|
+
const parent = new Registry()
|
|
271
443
|
const child = new Registry(parent)
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
444
|
+
const token = InjectionToken.create<string>('test')
|
|
445
|
+
class ParentImpl {}
|
|
446
|
+
class ChildImpl {}
|
|
447
|
+
|
|
448
|
+
parent.set(token, InjectableScope.Singleton, ParentImpl, InjectableType.Class)
|
|
449
|
+
child.set(
|
|
450
|
+
token,
|
|
451
|
+
InjectableScope.Request,
|
|
452
|
+
ChildImpl,
|
|
277
453
|
InjectableType.Class,
|
|
454
|
+
1,
|
|
278
455
|
)
|
|
279
456
|
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
expect(
|
|
457
|
+
// Child should return its own registration
|
|
458
|
+
expect(child.get(token).target).toBe(ChildImpl)
|
|
459
|
+
expect(child.get(token).scope).toBe(InjectableScope.Request)
|
|
460
|
+
|
|
461
|
+
// Parent should still have its original registration
|
|
462
|
+
expect(parent.get(token).target).toBe(ParentImpl)
|
|
283
463
|
})
|
|
284
464
|
|
|
285
|
-
it('should
|
|
286
|
-
const
|
|
287
|
-
const parent = new Registry(
|
|
465
|
+
it('should support multi-level hierarchy', () => {
|
|
466
|
+
const grandparent = new Registry()
|
|
467
|
+
const parent = new Registry(grandparent)
|
|
288
468
|
const child = new Registry(parent)
|
|
469
|
+
const token = InjectionToken.create<string>('test')
|
|
470
|
+
class TestClass {}
|
|
289
471
|
|
|
290
|
-
|
|
291
|
-
|
|
472
|
+
grandparent.set(
|
|
473
|
+
token,
|
|
292
474
|
InjectableScope.Singleton,
|
|
293
|
-
|
|
475
|
+
TestClass,
|
|
294
476
|
InjectableType.Class,
|
|
295
477
|
)
|
|
296
|
-
parent.set(
|
|
297
|
-
token1,
|
|
298
|
-
InjectableScope.Transient,
|
|
299
|
-
AnotherService,
|
|
300
|
-
InjectableType.Factory,
|
|
301
|
-
)
|
|
302
478
|
|
|
303
|
-
|
|
304
|
-
expect(
|
|
305
|
-
expect(record.target).toBe(AnotherService)
|
|
479
|
+
expect(child.has(token)).toBe(true)
|
|
480
|
+
expect(child.get(token).target).toBe(TestClass)
|
|
306
481
|
})
|
|
307
482
|
})
|
|
308
483
|
})
|
|
309
|
-
|
|
310
|
-
describe('globalRegistry', () => {
|
|
311
|
-
it('should be a Registry instance', () => {
|
|
312
|
-
expect(globalRegistry).toBeInstanceOf(Registry)
|
|
313
|
-
})
|
|
314
|
-
|
|
315
|
-
it('should be able to store and retrieve tokens', () => {
|
|
316
|
-
const token = new InjectionToken<TestService, undefined>(
|
|
317
|
-
'GlobalTest',
|
|
318
|
-
undefined,
|
|
319
|
-
)
|
|
320
|
-
|
|
321
|
-
globalRegistry.set(
|
|
322
|
-
token,
|
|
323
|
-
InjectableScope.Singleton,
|
|
324
|
-
TestService,
|
|
325
|
-
InjectableType.Class,
|
|
326
|
-
)
|
|
327
|
-
expect(globalRegistry.has(token)).toBe(true)
|
|
328
|
-
|
|
329
|
-
const record = globalRegistry.get(token)
|
|
330
|
-
expect(record.target).toBe(TestService)
|
|
331
|
-
|
|
332
|
-
// Clean up
|
|
333
|
-
globalRegistry.delete(token)
|
|
334
|
-
})
|
|
335
|
-
})
|