@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
|
@@ -3,7 +3,7 @@ import { z } from 'zod/v4'
|
|
|
3
3
|
|
|
4
4
|
import { Injectable } from '../decorators/index.mjs'
|
|
5
5
|
import { InjectionToken } from '../token/injection-token.mjs'
|
|
6
|
-
import { asyncInject } from '../injectors.mjs'
|
|
6
|
+
import { asyncInject, inject, optional } from '../utils/default-injectors.mjs'
|
|
7
7
|
|
|
8
8
|
interface FooService {
|
|
9
9
|
makeFoo(): string
|
|
@@ -17,8 +17,6 @@ const simpleOptionalObjectSchema = z
|
|
|
17
17
|
foo: z.string(),
|
|
18
18
|
})
|
|
19
19
|
.optional()
|
|
20
|
-
// const simpleRecordSchema = z.record(z.string(), z.string())
|
|
21
|
-
// const simpleOptionalRecordSchema = z.record(z.string(), z.string()).optional()
|
|
22
20
|
|
|
23
21
|
const typelessObjectToken = InjectionToken.create(
|
|
24
22
|
Symbol.for('Typeless object token'),
|
|
@@ -28,14 +26,6 @@ const typelessOptionalObjectToken = InjectionToken.create(
|
|
|
28
26
|
Symbol.for('Typeless optional object token'),
|
|
29
27
|
simpleOptionalObjectSchema,
|
|
30
28
|
)
|
|
31
|
-
// const typelessRecordToken = InjectionToken.create(
|
|
32
|
-
// Symbol.for('Typeless record token'),
|
|
33
|
-
// simpleRecordSchema,
|
|
34
|
-
// )
|
|
35
|
-
// const typelessOptionalRecordToken = InjectionToken.create(
|
|
36
|
-
// Symbol.for('Typeless optional record token'),
|
|
37
|
-
// simpleOptionalRecordSchema,
|
|
38
|
-
// )
|
|
39
29
|
|
|
40
30
|
const typedObjectToken = InjectionToken.create<
|
|
41
31
|
FooService,
|
|
@@ -45,18 +35,10 @@ const typedOptionalObjectToken = InjectionToken.create<
|
|
|
45
35
|
FooService,
|
|
46
36
|
typeof simpleOptionalObjectSchema
|
|
47
37
|
>(Symbol.for('Typed optional object token'), simpleOptionalObjectSchema)
|
|
48
|
-
// const typedRecordToken = InjectionToken.create<
|
|
49
|
-
// FooService,
|
|
50
|
-
// typeof simpleRecordSchema
|
|
51
|
-
// >(Symbol.for('Typed record token'), simpleRecordSchema)
|
|
52
|
-
// const typedOptionalRecordToken = InjectionToken.create<
|
|
53
|
-
// FooService,
|
|
54
|
-
// typeof simpleOptionalRecordSchema
|
|
55
|
-
// >(Symbol.for('Typed optional record token'), simpleOptionalRecordSchema)
|
|
56
38
|
|
|
57
39
|
const typedToken = InjectionToken.create<FooService>(Symbol.for('Typed token'))
|
|
58
40
|
|
|
59
|
-
describe('
|
|
41
|
+
describe('asyncInject', () => {
|
|
60
42
|
describe('#1 Classes', () => {
|
|
61
43
|
test('simple class', async () => {
|
|
62
44
|
@Injectable()
|
|
@@ -68,6 +50,7 @@ describe('inject', () => {
|
|
|
68
50
|
|
|
69
51
|
assertType<Foo>(await asyncInject(Foo))
|
|
70
52
|
})
|
|
53
|
+
|
|
71
54
|
test('class with required argument', async () => {
|
|
72
55
|
@Injectable({
|
|
73
56
|
schema: simpleObjectSchema,
|
|
@@ -78,6 +61,7 @@ describe('inject', () => {
|
|
|
78
61
|
|
|
79
62
|
assertType<Foo>(await asyncInject(Foo, { foo: 'bar' }))
|
|
80
63
|
})
|
|
64
|
+
|
|
81
65
|
test('should fail if not compatible', async () => {
|
|
82
66
|
@Injectable({
|
|
83
67
|
schema: simpleObjectSchema,
|
|
@@ -90,6 +74,7 @@ describe('inject', () => {
|
|
|
90
74
|
await asyncInject(Foo, { test: 'bar' })
|
|
91
75
|
})
|
|
92
76
|
})
|
|
77
|
+
|
|
93
78
|
test('#2 Token with required Schema', async () => {
|
|
94
79
|
const result = await asyncInject(typelessObjectToken, { foo: 'bar' })
|
|
95
80
|
assertType<unknown>(result)
|
|
@@ -119,3 +104,113 @@ describe('inject', () => {
|
|
|
119
104
|
assertType<FooService>(result)
|
|
120
105
|
})
|
|
121
106
|
})
|
|
107
|
+
|
|
108
|
+
describe('inject (synchronous)', () => {
|
|
109
|
+
describe('#1 Classes', () => {
|
|
110
|
+
test('simple class', () => {
|
|
111
|
+
@Injectable()
|
|
112
|
+
class Foo {
|
|
113
|
+
makeFoo() {
|
|
114
|
+
return 'foo'
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
assertType<Foo>(inject(Foo))
|
|
119
|
+
})
|
|
120
|
+
|
|
121
|
+
test('class with required argument', () => {
|
|
122
|
+
@Injectable({
|
|
123
|
+
schema: simpleObjectSchema,
|
|
124
|
+
})
|
|
125
|
+
class Foo {
|
|
126
|
+
constructor(public arg: z.infer<typeof simpleObjectSchema>) {}
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
assertType<Foo>(inject(Foo, { foo: 'bar' }))
|
|
130
|
+
})
|
|
131
|
+
|
|
132
|
+
test('should fail if not compatible', () => {
|
|
133
|
+
@Injectable({
|
|
134
|
+
schema: simpleObjectSchema,
|
|
135
|
+
})
|
|
136
|
+
class Foo {
|
|
137
|
+
constructor(public arg: z.infer<typeof simpleObjectSchema>) {}
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
// @ts-expect-error Should fail if not compatible
|
|
141
|
+
inject(Foo, { test: 'bar' })
|
|
142
|
+
})
|
|
143
|
+
})
|
|
144
|
+
|
|
145
|
+
test('#2 Token with required Schema', () => {
|
|
146
|
+
const result = inject(typelessObjectToken, { foo: 'bar' })
|
|
147
|
+
assertType<unknown>(result)
|
|
148
|
+
|
|
149
|
+
const result2 = inject(typedObjectToken, { foo: 'bar' })
|
|
150
|
+
assertType<FooService>(result2)
|
|
151
|
+
|
|
152
|
+
// @ts-expect-error We show error when we pass the wrong type
|
|
153
|
+
inject(typedObjectToken, undefined)
|
|
154
|
+
})
|
|
155
|
+
|
|
156
|
+
test('#3 Token with optional Schema', () => {
|
|
157
|
+
const result = inject(typelessOptionalObjectToken)
|
|
158
|
+
assertType<unknown>(result)
|
|
159
|
+
|
|
160
|
+
const result2 = inject(typedOptionalObjectToken)
|
|
161
|
+
assertType<FooService>(result2)
|
|
162
|
+
|
|
163
|
+
const result3 = inject(typedObjectToken)
|
|
164
|
+
// Special case when we pass the token without args
|
|
165
|
+
// We can only return an error string
|
|
166
|
+
assertType<'Error: Your token requires args: foo'>(result3)
|
|
167
|
+
})
|
|
168
|
+
|
|
169
|
+
test('#4 Token with no Schema', () => {
|
|
170
|
+
const result = inject(typedToken)
|
|
171
|
+
assertType<FooService>(result)
|
|
172
|
+
})
|
|
173
|
+
})
|
|
174
|
+
|
|
175
|
+
describe('optional', () => {
|
|
176
|
+
describe('#1 Classes', () => {
|
|
177
|
+
test('simple class returns nullable type', () => {
|
|
178
|
+
@Injectable()
|
|
179
|
+
class Foo {
|
|
180
|
+
makeFoo() {
|
|
181
|
+
return 'foo'
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
assertType<Foo | null>(optional(Foo))
|
|
186
|
+
})
|
|
187
|
+
|
|
188
|
+
// Note: optional() does not have a class + args overload
|
|
189
|
+
// Classes with required args should use tokens instead
|
|
190
|
+
})
|
|
191
|
+
|
|
192
|
+
test('#2 Token with required Schema', () => {
|
|
193
|
+
const result = optional(typelessObjectToken, { foo: 'bar' })
|
|
194
|
+
assertType<unknown>(result)
|
|
195
|
+
|
|
196
|
+
const result2 = optional(typedObjectToken, { foo: 'bar' })
|
|
197
|
+
assertType<FooService | null>(result2)
|
|
198
|
+
})
|
|
199
|
+
|
|
200
|
+
test('#3 Token with optional Schema', () => {
|
|
201
|
+
const result = optional(typelessOptionalObjectToken)
|
|
202
|
+
assertType<unknown>(result)
|
|
203
|
+
|
|
204
|
+
const result2 = optional(typedOptionalObjectToken)
|
|
205
|
+
assertType<FooService | null>(result2)
|
|
206
|
+
|
|
207
|
+
const result3 = optional(typedObjectToken)
|
|
208
|
+
// Special case when we pass the token without args
|
|
209
|
+
assertType<'Error: Your token requires args: foo'>(result3)
|
|
210
|
+
})
|
|
211
|
+
|
|
212
|
+
test('#4 Token with no Schema', () => {
|
|
213
|
+
const result = optional(typedToken)
|
|
214
|
+
assertType<FooService | null>(result)
|
|
215
|
+
})
|
|
216
|
+
})
|
|
@@ -3,7 +3,9 @@ import { expectTypeOf, test } from 'vitest'
|
|
|
3
3
|
import { z } from 'zod/v4'
|
|
4
4
|
|
|
5
5
|
import { Injectable } from '../decorators/index.mjs'
|
|
6
|
+
import { InjectableScope } from '../enums/index.mjs'
|
|
6
7
|
import { InjectionToken } from '../token/injection-token.mjs'
|
|
8
|
+
import { Registry } from '../token/registry.mjs'
|
|
7
9
|
|
|
8
10
|
interface FooService {
|
|
9
11
|
makeFoo(): string
|
|
@@ -20,13 +22,6 @@ const simpleOptionalObjectSchema = z
|
|
|
20
22
|
const otherObjectSchema = z.object({
|
|
21
23
|
bar: z.string(),
|
|
22
24
|
})
|
|
23
|
-
const otherOptionalObjectSchema = z
|
|
24
|
-
.object({
|
|
25
|
-
bar: z.string(),
|
|
26
|
-
})
|
|
27
|
-
.optional()
|
|
28
|
-
// const simpleRecordSchema = z.record(z.string(), z.string())
|
|
29
|
-
// const simpleOptionalRecordSchema = z.record(z.string(), z.string()).optional()
|
|
30
25
|
|
|
31
26
|
const typelessObjectToken = InjectionToken.create(
|
|
32
27
|
Symbol.for('Typeless object token'),
|
|
@@ -36,14 +31,6 @@ const typelessOptionalObjectToken = InjectionToken.create(
|
|
|
36
31
|
Symbol.for('Typeless optional object token'),
|
|
37
32
|
simpleOptionalObjectSchema,
|
|
38
33
|
)
|
|
39
|
-
// const typelessRecordToken = InjectionToken.create(
|
|
40
|
-
// Symbol.for('Typeless record token'),
|
|
41
|
-
// simpleRecordSchema,
|
|
42
|
-
// )
|
|
43
|
-
// const typelessOptionalRecordToken = InjectionToken.create(
|
|
44
|
-
// Symbol.for('Typeless optional record token'),
|
|
45
|
-
// simpleOptionalRecordSchema,
|
|
46
|
-
// )
|
|
47
34
|
|
|
48
35
|
const typedObjectToken = InjectionToken.create<
|
|
49
36
|
FooService,
|
|
@@ -53,23 +40,29 @@ const typedOptionalObjectToken = InjectionToken.create<
|
|
|
53
40
|
FooService,
|
|
54
41
|
typeof simpleOptionalObjectSchema
|
|
55
42
|
>(Symbol.for('Typed optional object token'), simpleOptionalObjectSchema)
|
|
56
|
-
// const typedRecordToken = InjectionToken.create<
|
|
57
|
-
// FooService,
|
|
58
|
-
// typeof simpleRecordSchema
|
|
59
|
-
// >(Symbol.for('Typed record token'), simpleRecordSchema)
|
|
60
|
-
// const typedOptionalRecordToken = InjectionToken.create<
|
|
61
|
-
// FooService,
|
|
62
|
-
// typeof simpleOptionalRecordSchema
|
|
63
|
-
// >(Symbol.for('Typed optional record token'), simpleOptionalRecordSchema)
|
|
64
43
|
|
|
65
44
|
const typedToken = InjectionToken.create<FooService>(Symbol.for('Typed token'))
|
|
66
45
|
|
|
67
46
|
test('Injectable types', () => {
|
|
68
|
-
// #1
|
|
47
|
+
// #1 Simple class without arguments
|
|
69
48
|
expectTypeOf(
|
|
70
49
|
@Injectable()
|
|
71
50
|
class {},
|
|
72
51
|
).toBeConstructibleWith()
|
|
52
|
+
|
|
53
|
+
// #1 Injectable with scope
|
|
54
|
+
expectTypeOf(
|
|
55
|
+
@Injectable({ scope: InjectableScope.Transient })
|
|
56
|
+
class {},
|
|
57
|
+
).toBeConstructibleWith()
|
|
58
|
+
|
|
59
|
+
// #1 Injectable with registry
|
|
60
|
+
const registry = new Registry()
|
|
61
|
+
expectTypeOf(
|
|
62
|
+
@Injectable({ registry })
|
|
63
|
+
class {},
|
|
64
|
+
).toBeConstructibleWith()
|
|
65
|
+
|
|
73
66
|
// #1 Injectable w/o decorators enabled in project
|
|
74
67
|
expectTypeOf(
|
|
75
68
|
Injectable({
|
|
@@ -84,7 +77,7 @@ test('Injectable types', () => {
|
|
|
84
77
|
),
|
|
85
78
|
).toBeConstructibleWith()
|
|
86
79
|
|
|
87
|
-
// #2 required argument
|
|
80
|
+
// #2 Class with schema - required argument
|
|
88
81
|
expectTypeOf(
|
|
89
82
|
@Injectable({
|
|
90
83
|
schema: simpleObjectSchema,
|
|
@@ -95,7 +88,8 @@ test('Injectable types', () => {
|
|
|
95
88
|
).toBeConstructibleWith({
|
|
96
89
|
foo: 'something',
|
|
97
90
|
})
|
|
98
|
-
|
|
91
|
+
|
|
92
|
+
// #2 It's required in schema but optional in class allowed
|
|
99
93
|
expectTypeOf(
|
|
100
94
|
@Injectable({
|
|
101
95
|
schema: simpleObjectSchema,
|
|
@@ -106,7 +100,8 @@ test('Injectable types', () => {
|
|
|
106
100
|
).toBeConstructibleWith({
|
|
107
101
|
foo: 'something',
|
|
108
102
|
})
|
|
109
|
-
|
|
103
|
+
|
|
104
|
+
// #2 Should fail if not compatible
|
|
110
105
|
// @ts-expect-error Should fail if not compatible
|
|
111
106
|
@Injectable({
|
|
112
107
|
schema: simpleObjectSchema,
|
|
@@ -115,7 +110,7 @@ test('Injectable types', () => {
|
|
|
115
110
|
constructor(public arg: z.infer<typeof otherObjectSchema>) {}
|
|
116
111
|
}
|
|
117
112
|
|
|
118
|
-
// #3 required argument
|
|
113
|
+
// #3 Typeless token with required schema - required argument
|
|
119
114
|
expectTypeOf(
|
|
120
115
|
@Injectable({
|
|
121
116
|
token: typelessObjectToken,
|
|
@@ -126,7 +121,8 @@ test('Injectable types', () => {
|
|
|
126
121
|
).toBeConstructibleWith({
|
|
127
122
|
foo: 'something',
|
|
128
123
|
})
|
|
129
|
-
|
|
124
|
+
|
|
125
|
+
// #3 It's required in token but optional in class allowed
|
|
130
126
|
expectTypeOf(
|
|
131
127
|
@Injectable({
|
|
132
128
|
token: typelessObjectToken,
|
|
@@ -137,7 +133,8 @@ test('Injectable types', () => {
|
|
|
137
133
|
).toBeConstructibleWith({
|
|
138
134
|
foo: 'something',
|
|
139
135
|
})
|
|
140
|
-
|
|
136
|
+
|
|
137
|
+
// #3 Optional value but class accepts it
|
|
141
138
|
expectTypeOf(
|
|
142
139
|
@Injectable({
|
|
143
140
|
token: typelessOptionalObjectToken,
|
|
@@ -148,7 +145,8 @@ test('Injectable types', () => {
|
|
|
148
145
|
).toBeConstructibleWith({
|
|
149
146
|
foo: 'something',
|
|
150
147
|
})
|
|
151
|
-
|
|
148
|
+
|
|
149
|
+
// #3 Optional value and class accepts undefined
|
|
152
150
|
expectTypeOf(
|
|
153
151
|
@Injectable({
|
|
154
152
|
token: typelessOptionalObjectToken,
|
|
@@ -157,7 +155,8 @@ test('Injectable types', () => {
|
|
|
157
155
|
constructor(public arg: z.infer<typeof simpleOptionalObjectSchema>) {}
|
|
158
156
|
},
|
|
159
157
|
).toBeConstructibleWith(undefined)
|
|
160
|
-
|
|
158
|
+
|
|
159
|
+
// #3 Compatible schemas
|
|
161
160
|
expectTypeOf(
|
|
162
161
|
@Injectable({
|
|
163
162
|
token: typelessOptionalObjectToken,
|
|
@@ -166,7 +165,8 @@ test('Injectable types', () => {
|
|
|
166
165
|
constructor(public arg?: z.infer<typeof simpleObjectSchema>) {}
|
|
167
166
|
},
|
|
168
167
|
).toBeConstructibleWith(undefined)
|
|
169
|
-
|
|
168
|
+
|
|
169
|
+
// #3 Token has optional schema, but Class has required, should fail
|
|
170
170
|
expectTypeOf(
|
|
171
171
|
// @ts-expect-error token has optional schema, but Class has required, should fail
|
|
172
172
|
@Injectable({
|
|
@@ -179,7 +179,7 @@ test('Injectable types', () => {
|
|
|
179
179
|
foo: 'something',
|
|
180
180
|
})
|
|
181
181
|
|
|
182
|
-
// #3
|
|
182
|
+
// #3 Typed token with required schema - required argument
|
|
183
183
|
expectTypeOf(
|
|
184
184
|
@Injectable({
|
|
185
185
|
token: typedObjectToken,
|
|
@@ -194,7 +194,8 @@ test('Injectable types', () => {
|
|
|
194
194
|
).toBeConstructibleWith({
|
|
195
195
|
foo: 'something',
|
|
196
196
|
})
|
|
197
|
-
|
|
197
|
+
|
|
198
|
+
// #3 Typed token with optional schema
|
|
198
199
|
expectTypeOf(
|
|
199
200
|
@Injectable({
|
|
200
201
|
token: typedOptionalObjectToken,
|
|
@@ -209,7 +210,8 @@ test('Injectable types', () => {
|
|
|
209
210
|
).toBeConstructibleWith({
|
|
210
211
|
foo: 'something',
|
|
211
212
|
})
|
|
212
|
-
|
|
213
|
+
|
|
214
|
+
// #3 Should fail if class doesn't implement token type
|
|
213
215
|
expectTypeOf(
|
|
214
216
|
// @ts-expect-error class doesn't implement the token type
|
|
215
217
|
@Injectable({
|
|
@@ -221,9 +223,10 @@ test('Injectable types', () => {
|
|
|
221
223
|
).toBeConstructibleWith({
|
|
222
224
|
foo: 'something',
|
|
223
225
|
})
|
|
224
|
-
|
|
226
|
+
|
|
227
|
+
// #3 Should fail if return type doesn't match (returns undefined instead of string)
|
|
225
228
|
expectTypeOf(
|
|
226
|
-
// @ts-expect-error class doesn't implement the token type
|
|
229
|
+
// @ts-expect-error class doesn't implement the token type (wrong return type)
|
|
227
230
|
@Injectable({
|
|
228
231
|
token: typedOptionalObjectToken,
|
|
229
232
|
})
|
|
@@ -237,7 +240,8 @@ test('Injectable types', () => {
|
|
|
237
240
|
).toBeConstructibleWith({
|
|
238
241
|
foo: 'something',
|
|
239
242
|
})
|
|
240
|
-
|
|
243
|
+
|
|
244
|
+
// #3 Typed token without schema
|
|
241
245
|
expectTypeOf(
|
|
242
246
|
@Injectable({
|
|
243
247
|
token: typedToken,
|
|
@@ -249,7 +253,8 @@ test('Injectable types', () => {
|
|
|
249
253
|
}
|
|
250
254
|
},
|
|
251
255
|
).toBeConstructibleWith()
|
|
252
|
-
|
|
256
|
+
|
|
257
|
+
// #3 Typed token without schema - fail if not compatible
|
|
253
258
|
expectTypeOf(
|
|
254
259
|
// @ts-expect-error class doesn't implement the token type
|
|
255
260
|
@Injectable({
|
|
@@ -260,7 +265,9 @@ test('Injectable types', () => {
|
|
|
260
265
|
},
|
|
261
266
|
).toBeConstructibleWith()
|
|
262
267
|
|
|
263
|
-
//
|
|
268
|
+
// Function call syntax tests (without decorators)
|
|
269
|
+
|
|
270
|
+
// #3 Required argument
|
|
264
271
|
expectTypeOf(
|
|
265
272
|
Injectable({
|
|
266
273
|
token: typelessObjectToken,
|
|
@@ -272,7 +279,8 @@ test('Injectable types', () => {
|
|
|
272
279
|
).toBeConstructibleWith({
|
|
273
280
|
foo: 'something',
|
|
274
281
|
})
|
|
275
|
-
|
|
282
|
+
|
|
283
|
+
// #3 It's required in token but optional in class allowed
|
|
276
284
|
expectTypeOf(
|
|
277
285
|
Injectable({
|
|
278
286
|
token: typelessObjectToken,
|
|
@@ -284,7 +292,8 @@ test('Injectable types', () => {
|
|
|
284
292
|
).toBeConstructibleWith({
|
|
285
293
|
foo: 'something',
|
|
286
294
|
})
|
|
287
|
-
|
|
295
|
+
|
|
296
|
+
// #3 Optional value but class accepts it
|
|
288
297
|
expectTypeOf(
|
|
289
298
|
Injectable({
|
|
290
299
|
token: typelessOptionalObjectToken,
|
|
@@ -296,7 +305,8 @@ test('Injectable types', () => {
|
|
|
296
305
|
).toBeConstructibleWith({
|
|
297
306
|
foo: 'something',
|
|
298
307
|
})
|
|
299
|
-
|
|
308
|
+
|
|
309
|
+
// #3 Optional value and class accepts undefined
|
|
300
310
|
expectTypeOf(
|
|
301
311
|
Injectable({
|
|
302
312
|
token: typelessOptionalObjectToken,
|
|
@@ -306,7 +316,8 @@ test('Injectable types', () => {
|
|
|
306
316
|
},
|
|
307
317
|
),
|
|
308
318
|
).toBeConstructibleWith(undefined)
|
|
309
|
-
|
|
319
|
+
|
|
320
|
+
// #3 Compatible schemas
|
|
310
321
|
expectTypeOf(
|
|
311
322
|
Injectable({
|
|
312
323
|
token: typelessOptionalObjectToken,
|
|
@@ -316,7 +327,8 @@ test('Injectable types', () => {
|
|
|
316
327
|
},
|
|
317
328
|
),
|
|
318
329
|
).toBeConstructibleWith(undefined)
|
|
319
|
-
|
|
330
|
+
|
|
331
|
+
// #3 Token has optional schema, but Class has required, should fail
|
|
320
332
|
expectTypeOf(
|
|
321
333
|
Injectable({
|
|
322
334
|
token: typelessOptionalObjectToken,
|
|
@@ -330,7 +342,7 @@ test('Injectable types', () => {
|
|
|
330
342
|
foo: 'something',
|
|
331
343
|
})
|
|
332
344
|
|
|
333
|
-
// #3
|
|
345
|
+
// #3 Typed token with required schema - required argument
|
|
334
346
|
expectTypeOf(
|
|
335
347
|
Injectable({
|
|
336
348
|
token: typedObjectToken,
|
|
@@ -346,7 +358,8 @@ test('Injectable types', () => {
|
|
|
346
358
|
).toBeConstructibleWith({
|
|
347
359
|
foo: 'something',
|
|
348
360
|
})
|
|
349
|
-
|
|
361
|
+
|
|
362
|
+
// #3 Typed token with optional schema
|
|
350
363
|
expectTypeOf(
|
|
351
364
|
Injectable({
|
|
352
365
|
token: typedOptionalObjectToken,
|
|
@@ -362,7 +375,8 @@ test('Injectable types', () => {
|
|
|
362
375
|
).toBeConstructibleWith({
|
|
363
376
|
foo: 'something',
|
|
364
377
|
})
|
|
365
|
-
|
|
378
|
+
|
|
379
|
+
// #3 Should fail if class doesn't implement token type
|
|
366
380
|
expectTypeOf(
|
|
367
381
|
Injectable({
|
|
368
382
|
token: typedOptionalObjectToken,
|
|
@@ -375,7 +389,8 @@ test('Injectable types', () => {
|
|
|
375
389
|
).toBeConstructibleWith({
|
|
376
390
|
foo: 'something',
|
|
377
391
|
})
|
|
378
|
-
|
|
392
|
+
|
|
393
|
+
// #3 Should fail if return type doesn't match
|
|
379
394
|
expectTypeOf(
|
|
380
395
|
Injectable({
|
|
381
396
|
token: typedOptionalObjectToken,
|
|
@@ -392,7 +407,8 @@ test('Injectable types', () => {
|
|
|
392
407
|
).toBeConstructibleWith({
|
|
393
408
|
foo: 'something',
|
|
394
409
|
})
|
|
395
|
-
|
|
410
|
+
|
|
411
|
+
// #3 Typed token without schema
|
|
396
412
|
expectTypeOf(
|
|
397
413
|
Injectable({
|
|
398
414
|
token: typedToken,
|
|
@@ -405,7 +421,8 @@ test('Injectable types', () => {
|
|
|
405
421
|
},
|
|
406
422
|
),
|
|
407
423
|
).toBeConstructibleWith()
|
|
408
|
-
|
|
424
|
+
|
|
425
|
+
// #3 Typed token without schema - fail if not compatible
|
|
409
426
|
expectTypeOf(
|
|
410
427
|
Injectable({
|
|
411
428
|
token: typedToken,
|
|
@@ -0,0 +1,176 @@
|
|
|
1
|
+
import { expectTypeOf, test } from 'vitest'
|
|
2
|
+
import { z } from 'zod/v4'
|
|
3
|
+
|
|
4
|
+
import {
|
|
5
|
+
BoundInjectionToken,
|
|
6
|
+
FactoryInjectionToken,
|
|
7
|
+
InjectionToken,
|
|
8
|
+
} from '../token/injection-token.mjs'
|
|
9
|
+
|
|
10
|
+
interface FooService {
|
|
11
|
+
makeFoo(): string
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
const simpleObjectSchema = z.object({
|
|
15
|
+
foo: z.string(),
|
|
16
|
+
})
|
|
17
|
+
const simpleOptionalObjectSchema = z
|
|
18
|
+
.object({
|
|
19
|
+
foo: z.string(),
|
|
20
|
+
})
|
|
21
|
+
.optional()
|
|
22
|
+
|
|
23
|
+
test('InjectionToken.create with class', () => {
|
|
24
|
+
class MyService {
|
|
25
|
+
getValue() {
|
|
26
|
+
return 42
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
const token = InjectionToken.create(MyService)
|
|
31
|
+
expectTypeOf(token).toMatchTypeOf<InjectionToken<MyService, undefined>>()
|
|
32
|
+
})
|
|
33
|
+
|
|
34
|
+
test('InjectionToken.create with class and schema', () => {
|
|
35
|
+
class MyService {
|
|
36
|
+
constructor(public config: z.infer<typeof simpleObjectSchema>) {}
|
|
37
|
+
getValue() {
|
|
38
|
+
return 42
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
const token = InjectionToken.create(MyService, simpleObjectSchema)
|
|
43
|
+
expectTypeOf(token).toMatchTypeOf<
|
|
44
|
+
InjectionToken<MyService, typeof simpleObjectSchema, true>
|
|
45
|
+
>()
|
|
46
|
+
})
|
|
47
|
+
|
|
48
|
+
test('InjectionToken.create with class and optional schema', () => {
|
|
49
|
+
class MyService {
|
|
50
|
+
constructor(public config?: z.infer<typeof simpleOptionalObjectSchema>) {}
|
|
51
|
+
getValue() {
|
|
52
|
+
return 42
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
const token = InjectionToken.create(MyService, simpleOptionalObjectSchema)
|
|
57
|
+
expectTypeOf(token).toMatchTypeOf<
|
|
58
|
+
InjectionToken<MyService, typeof simpleOptionalObjectSchema, false>
|
|
59
|
+
>()
|
|
60
|
+
})
|
|
61
|
+
|
|
62
|
+
test('InjectionToken.create with string name', () => {
|
|
63
|
+
const token = InjectionToken.create<FooService>('FooService')
|
|
64
|
+
expectTypeOf(token).toMatchTypeOf<InjectionToken<FooService, undefined>>()
|
|
65
|
+
})
|
|
66
|
+
|
|
67
|
+
test('InjectionToken.create with symbol name', () => {
|
|
68
|
+
const token = InjectionToken.create<FooService>(Symbol.for('FooService'))
|
|
69
|
+
expectTypeOf(token).toMatchTypeOf<InjectionToken<FooService, undefined>>()
|
|
70
|
+
})
|
|
71
|
+
|
|
72
|
+
test('InjectionToken.create with string name and schema', () => {
|
|
73
|
+
const token = InjectionToken.create<FooService, typeof simpleObjectSchema>(
|
|
74
|
+
'FooService',
|
|
75
|
+
simpleObjectSchema,
|
|
76
|
+
)
|
|
77
|
+
expectTypeOf(token).toMatchTypeOf<
|
|
78
|
+
InjectionToken<FooService, typeof simpleObjectSchema>
|
|
79
|
+
>()
|
|
80
|
+
})
|
|
81
|
+
|
|
82
|
+
test('InjectionToken.bound creates BoundInjectionToken', () => {
|
|
83
|
+
const token = InjectionToken.create<FooService, typeof simpleObjectSchema>(
|
|
84
|
+
'FooService',
|
|
85
|
+
simpleObjectSchema,
|
|
86
|
+
)
|
|
87
|
+
const boundToken = InjectionToken.bound(token, { foo: 'bar' })
|
|
88
|
+
expectTypeOf(boundToken).toMatchTypeOf<
|
|
89
|
+
BoundInjectionToken<FooService, typeof simpleObjectSchema>
|
|
90
|
+
>()
|
|
91
|
+
})
|
|
92
|
+
|
|
93
|
+
test('InjectionToken.bound requires correct argument type', () => {
|
|
94
|
+
const token = InjectionToken.create<FooService, typeof simpleObjectSchema>(
|
|
95
|
+
'FooService',
|
|
96
|
+
simpleObjectSchema,
|
|
97
|
+
)
|
|
98
|
+
|
|
99
|
+
// @ts-expect-error Should fail with wrong argument type
|
|
100
|
+
InjectionToken.bound(token, { wrong: 'key' })
|
|
101
|
+
|
|
102
|
+
// @ts-expect-error Should fail with missing required property
|
|
103
|
+
InjectionToken.bound(token, {})
|
|
104
|
+
})
|
|
105
|
+
|
|
106
|
+
test('InjectionToken.factory creates FactoryInjectionToken', () => {
|
|
107
|
+
const token = InjectionToken.create<FooService, typeof simpleObjectSchema>(
|
|
108
|
+
'FooService',
|
|
109
|
+
simpleObjectSchema,
|
|
110
|
+
)
|
|
111
|
+
const factoryToken = InjectionToken.factory(token, async () => ({
|
|
112
|
+
foo: 'bar',
|
|
113
|
+
}))
|
|
114
|
+
expectTypeOf(factoryToken).toMatchTypeOf<
|
|
115
|
+
FactoryInjectionToken<FooService, typeof simpleObjectSchema>
|
|
116
|
+
>()
|
|
117
|
+
})
|
|
118
|
+
|
|
119
|
+
test('InjectionToken.factory requires correct return type', () => {
|
|
120
|
+
const token = InjectionToken.create<FooService, typeof simpleObjectSchema>(
|
|
121
|
+
'FooService',
|
|
122
|
+
simpleObjectSchema,
|
|
123
|
+
)
|
|
124
|
+
|
|
125
|
+
// @ts-expect-error Should fail with wrong return type
|
|
126
|
+
InjectionToken.factory(token, async () => ({ wrong: 'key' }))
|
|
127
|
+
})
|
|
128
|
+
|
|
129
|
+
test('InjectionToken.refineType changes BoundInjectionToken type', () => {
|
|
130
|
+
interface RefinedService {
|
|
131
|
+
doSomething(): void
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
const token = InjectionToken.create<unknown, typeof simpleObjectSchema>(
|
|
135
|
+
'Service',
|
|
136
|
+
simpleObjectSchema,
|
|
137
|
+
)
|
|
138
|
+
const boundToken = InjectionToken.bound(token, { foo: 'bar' })
|
|
139
|
+
const refinedToken = InjectionToken.refineType<RefinedService>(boundToken)
|
|
140
|
+
expectTypeOf(refinedToken).toMatchTypeOf<
|
|
141
|
+
BoundInjectionToken<RefinedService, any>
|
|
142
|
+
>()
|
|
143
|
+
})
|
|
144
|
+
|
|
145
|
+
test('BoundInjectionToken has value property with correct type', () => {
|
|
146
|
+
const token = InjectionToken.create<FooService, typeof simpleObjectSchema>(
|
|
147
|
+
'FooService',
|
|
148
|
+
simpleObjectSchema,
|
|
149
|
+
)
|
|
150
|
+
const boundToken = InjectionToken.bound(token, { foo: 'bar' })
|
|
151
|
+
|
|
152
|
+
expectTypeOf(boundToken.value).toMatchTypeOf<{ foo: string }>()
|
|
153
|
+
})
|
|
154
|
+
|
|
155
|
+
test('FactoryInjectionToken has factory property', () => {
|
|
156
|
+
const token = InjectionToken.create<FooService, typeof simpleObjectSchema>(
|
|
157
|
+
'FooService',
|
|
158
|
+
simpleObjectSchema,
|
|
159
|
+
)
|
|
160
|
+
const factoryToken = InjectionToken.factory(token, async () => ({
|
|
161
|
+
foo: 'bar',
|
|
162
|
+
}))
|
|
163
|
+
|
|
164
|
+
expectTypeOf(factoryToken.factory).toBeFunction()
|
|
165
|
+
})
|
|
166
|
+
|
|
167
|
+
test('InjectionToken properties', () => {
|
|
168
|
+
const token = InjectionToken.create<FooService, typeof simpleObjectSchema>(
|
|
169
|
+
'FooService',
|
|
170
|
+
simpleObjectSchema,
|
|
171
|
+
)
|
|
172
|
+
|
|
173
|
+
expectTypeOf(token.id).toBeString()
|
|
174
|
+
expectTypeOf(token.name).toMatchTypeOf<string | symbol | (new (...args: any[]) => any)>()
|
|
175
|
+
expectTypeOf(token.toString()).toBeString()
|
|
176
|
+
})
|