ts-ioc-container 41.0.0 → 41.1.1
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/README.md +109 -16
- package/cjm/container/AliasMap.js +1 -1
- package/cjm/container/Container.js +23 -15
- package/cjm/container/EmptyContainer.js +1 -1
- package/cjm/container/IContainer.js +1 -1
- package/cjm/injector/inject.js +1 -1
- package/cjm/provider/Provider.js +1 -1
- package/esm/container/AliasMap.js +1 -1
- package/esm/container/Container.js +24 -16
- package/esm/container/EmptyContainer.js +1 -1
- package/esm/container/IContainer.js +1 -1
- package/esm/injector/inject.js +1 -1
- package/esm/provider/Provider.js +1 -1
- package/esm/resolve.js +1 -1
- package/package.json +1 -1
- package/typings/container/AutoMockedContainer.d.ts +1 -1
- package/typings/container/Container.d.ts +8 -3
- package/typings/container/EmptyContainer.d.ts +1 -1
- package/typings/container/IContainer.d.ts +1 -1
- package/typings/resolve.d.ts +3 -3
- package/cjm/container/ProviderMap.js +0 -26
- package/esm/container/ProviderMap.js +0 -22
- package/typings/container/ProviderMap.d.ts +0 -10
package/README.md
CHANGED
|
@@ -522,7 +522,6 @@ describe('ProxyInjector', function () {
|
|
|
522
522
|
mockContainer.addRegistration(R.fromClass(Service).bindToKey('service'));
|
|
523
523
|
|
|
524
524
|
const app = mockContainer.resolveOne(App);
|
|
525
|
-
console.log('App loggers:', app.loggers);
|
|
526
525
|
expect(app.loggers).toBeInstanceOf(Array);
|
|
527
526
|
expect(app.loggers.length).toBe(1);
|
|
528
527
|
expect(app.loggers[0]).toBe(mockLogger);
|
|
@@ -543,34 +542,37 @@ Provider is dependency factory which creates dependency.
|
|
|
543
542
|
|
|
544
543
|
```typescript
|
|
545
544
|
import 'reflect-metadata';
|
|
546
|
-
import {
|
|
545
|
+
import {
|
|
546
|
+
args,
|
|
547
|
+
argsFn,
|
|
548
|
+
Container,
|
|
549
|
+
inject,
|
|
550
|
+
Provider,
|
|
551
|
+
scopeAccess,
|
|
552
|
+
singleton,
|
|
553
|
+
Registration as R,
|
|
554
|
+
register,
|
|
555
|
+
asKey,
|
|
556
|
+
lazy,
|
|
557
|
+
by,
|
|
558
|
+
} from 'ts-ioc-container';
|
|
547
559
|
|
|
548
560
|
class Logger {}
|
|
561
|
+
|
|
549
562
|
class ConfigService {
|
|
550
563
|
constructor(private readonly configPath: string) {}
|
|
564
|
+
|
|
551
565
|
getPath(): string {
|
|
552
566
|
return this.configPath;
|
|
553
567
|
}
|
|
554
568
|
}
|
|
569
|
+
|
|
555
570
|
class UserService {}
|
|
556
571
|
|
|
557
572
|
class TestClass {}
|
|
558
573
|
|
|
559
574
|
class ClassWithoutTransformers {}
|
|
560
575
|
|
|
561
|
-
jest.mock('../../lib/provider/IProvider', () => {
|
|
562
|
-
const originalModule = jest.requireActual('../../lib/provider/IProvider');
|
|
563
|
-
return {
|
|
564
|
-
...originalModule,
|
|
565
|
-
getTransformers: jest.fn().mockImplementation((target) => {
|
|
566
|
-
if (target === ClassWithoutTransformers) {
|
|
567
|
-
return null;
|
|
568
|
-
}
|
|
569
|
-
return originalModule.getTransformers(target);
|
|
570
|
-
}),
|
|
571
|
-
};
|
|
572
|
-
});
|
|
573
|
-
|
|
574
576
|
describe('Provider', () => {
|
|
575
577
|
it('can be registered as a function', () => {
|
|
576
578
|
const container = new Container().register('ILogger', new Provider(() => new Logger()));
|
|
@@ -719,6 +721,97 @@ describe('Provider', () => {
|
|
|
719
721
|
const result = container.resolveOne('NoTransformers');
|
|
720
722
|
expect(result).toBe(ClassWithoutTransformers);
|
|
721
723
|
});
|
|
724
|
+
|
|
725
|
+
it('allows to register lazy provider', () => {
|
|
726
|
+
let isLoggerCreated = false;
|
|
727
|
+
|
|
728
|
+
@register(asKey('Logger'), lazy())
|
|
729
|
+
class Logger {
|
|
730
|
+
private logs: string[] = [];
|
|
731
|
+
|
|
732
|
+
constructor() {
|
|
733
|
+
isLoggerCreated = true;
|
|
734
|
+
}
|
|
735
|
+
|
|
736
|
+
info(message: string, context: Record<string, unknown>): void {
|
|
737
|
+
this.logs.push(JSON.stringify({ ...context, level: 'info', message }));
|
|
738
|
+
}
|
|
739
|
+
|
|
740
|
+
serialize(): string {
|
|
741
|
+
return this.logs.join('\n');
|
|
742
|
+
}
|
|
743
|
+
}
|
|
744
|
+
|
|
745
|
+
class Main {
|
|
746
|
+
constructor(@inject('Logger') private logger: Logger) {}
|
|
747
|
+
|
|
748
|
+
getLogs(): string {
|
|
749
|
+
return this.logger.serialize();
|
|
750
|
+
}
|
|
751
|
+
}
|
|
752
|
+
|
|
753
|
+
const root = new Container({ tags: ['root'] }).addRegistration(R.fromClass(Logger));
|
|
754
|
+
const main = root.resolveClass(Main);
|
|
755
|
+
|
|
756
|
+
expect(isLoggerCreated).toBe(false);
|
|
757
|
+
|
|
758
|
+
main.getLogs();
|
|
759
|
+
|
|
760
|
+
expect(isLoggerCreated).toBe(true);
|
|
761
|
+
});
|
|
762
|
+
|
|
763
|
+
it('allows to resolve with args', () => {
|
|
764
|
+
@register(asKey('ILogger'))
|
|
765
|
+
class Logger {
|
|
766
|
+
readonly channel: string;
|
|
767
|
+
|
|
768
|
+
constructor(options: { channel: string }) {
|
|
769
|
+
this.channel = options.channel;
|
|
770
|
+
}
|
|
771
|
+
}
|
|
772
|
+
|
|
773
|
+
class Main {
|
|
774
|
+
constructor(@inject(by.one('ILogger').args({ channel: 'file' })) private logger: Logger) {}
|
|
775
|
+
|
|
776
|
+
getChannel(): string {
|
|
777
|
+
return this.logger.channel;
|
|
778
|
+
}
|
|
779
|
+
}
|
|
780
|
+
|
|
781
|
+
const root = new Container({ tags: ['root'] }).addRegistration(R.fromClass(Logger));
|
|
782
|
+
const main = root.resolveClass(Main);
|
|
783
|
+
|
|
784
|
+
expect(main.getChannel()).toBe('file');
|
|
785
|
+
});
|
|
786
|
+
|
|
787
|
+
it('allows to resolve with argsFn', () => {
|
|
788
|
+
@register(asKey('ILogger'))
|
|
789
|
+
class Logger {
|
|
790
|
+
readonly channel: string;
|
|
791
|
+
|
|
792
|
+
constructor(options: { channel: string }) {
|
|
793
|
+
this.channel = options.channel;
|
|
794
|
+
}
|
|
795
|
+
}
|
|
796
|
+
|
|
797
|
+
class Main {
|
|
798
|
+
constructor(
|
|
799
|
+
@inject(by.one('ILogger').argsFn((s) => [{ channel: s.resolveOne('channel') }])) private logger: Logger,
|
|
800
|
+
) {}
|
|
801
|
+
|
|
802
|
+
getChannel(): string {
|
|
803
|
+
return this.logger.channel;
|
|
804
|
+
}
|
|
805
|
+
}
|
|
806
|
+
|
|
807
|
+
const root = new Container({ tags: ['root'] })
|
|
808
|
+
.addRegistration(R.fromValue('file').bindToKey('channel'))
|
|
809
|
+
.addRegistration(R.fromClass(Logger));
|
|
810
|
+
|
|
811
|
+
const main = root.resolveClass(Main);
|
|
812
|
+
|
|
813
|
+
expect(main.getChannel()).toBe('file');
|
|
814
|
+
});
|
|
722
815
|
});
|
|
723
816
|
|
|
724
817
|
```
|
|
@@ -1458,7 +1551,7 @@ export class MoqContainer extends AutoMockedContainer {
|
|
|
1458
1551
|
return this.mocks.get(key) as IMock<T>;
|
|
1459
1552
|
}
|
|
1460
1553
|
|
|
1461
|
-
|
|
1554
|
+
resolveClass<T>(target: any, options?: { args?: unknown[] }): T {
|
|
1462
1555
|
throw new Error('Method not implemented.');
|
|
1463
1556
|
}
|
|
1464
1557
|
|
|
@@ -5,7 +5,7 @@ const utils_1 = require("../utils");
|
|
|
5
5
|
class AliasMap {
|
|
6
6
|
aliasToKeySet = new Map();
|
|
7
7
|
deleteKeyFromAliases(key) {
|
|
8
|
-
for (const [depKey, aliasSet] of [...this.aliasToKeySet].filter(([
|
|
8
|
+
for (const [depKey, aliasSet] of [...this.aliasToKeySet].filter(([, aliasSet]) => aliasSet.has(key))) {
|
|
9
9
|
aliasSet.delete(key);
|
|
10
10
|
if (aliasSet.size === 0) {
|
|
11
11
|
this.aliasToKeySet.delete(depKey);
|
|
@@ -6,32 +6,34 @@ const EmptyContainer_1 = require("./EmptyContainer");
|
|
|
6
6
|
const ContainerDisposedError_1 = require("../errors/ContainerDisposedError");
|
|
7
7
|
const MetadataInjector_1 = require("../injector/MetadataInjector");
|
|
8
8
|
const utils_1 = require("../utils");
|
|
9
|
-
const ProviderMap_1 = require("./ProviderMap");
|
|
10
9
|
const AliasMap_1 = require("./AliasMap");
|
|
10
|
+
const DependencyNotFoundError_1 = require("../errors/DependencyNotFoundError");
|
|
11
11
|
class Container {
|
|
12
12
|
isDisposed = false;
|
|
13
13
|
parent;
|
|
14
14
|
scopes = new Set();
|
|
15
15
|
instances = new Set();
|
|
16
16
|
tags;
|
|
17
|
-
|
|
18
|
-
|
|
17
|
+
providers = new Map();
|
|
18
|
+
aliases = new AliasMap_1.AliasMap();
|
|
19
19
|
registrations = new Set();
|
|
20
20
|
onConstruct;
|
|
21
21
|
onDispose;
|
|
22
22
|
injector;
|
|
23
|
+
resolveOneStrategy;
|
|
23
24
|
constructor(options = {}) {
|
|
24
25
|
this.injector = options.injector ?? new MetadataInjector_1.MetadataInjector();
|
|
25
26
|
this.parent = options.parent ?? new EmptyContainer_1.EmptyContainer();
|
|
26
27
|
this.tags = new Set(options.tags ?? []);
|
|
27
28
|
this.onConstruct = options.onConstruct ?? (() => { });
|
|
28
29
|
this.onDispose = options.onDispose ?? (() => { });
|
|
30
|
+
this.resolveOneStrategy = options.resolveOneStrategy ?? IContainer_1.DEFAULT_CONTAINER_RESOLVER;
|
|
29
31
|
}
|
|
30
32
|
register(key, provider, { aliases = [] } = {}) {
|
|
31
33
|
this.validateContainer();
|
|
32
|
-
this.
|
|
33
|
-
this.
|
|
34
|
-
this.
|
|
34
|
+
this.providers.set(key, provider);
|
|
35
|
+
this.aliases.deleteKeyFromAliases(key);
|
|
36
|
+
this.aliases.addAliases(key, aliases);
|
|
35
37
|
return this;
|
|
36
38
|
}
|
|
37
39
|
addRegistration(registration) {
|
|
@@ -42,7 +44,7 @@ class Container {
|
|
|
42
44
|
getRegistrations() {
|
|
43
45
|
return [...this.parent.getRegistrations(), ...this.registrations];
|
|
44
46
|
}
|
|
45
|
-
|
|
47
|
+
resolveClass(token, { args = [] } = {}) {
|
|
46
48
|
this.validateContainer();
|
|
47
49
|
const instance = this.injector.resolve(this, token, { args });
|
|
48
50
|
this.instances.add(instance);
|
|
@@ -50,19 +52,19 @@ class Container {
|
|
|
50
52
|
return instance;
|
|
51
53
|
}
|
|
52
54
|
resolveOne(keyOrAlias, options) {
|
|
53
|
-
return
|
|
55
|
+
return this.resolveOneStrategy(this, keyOrAlias, options);
|
|
54
56
|
}
|
|
55
57
|
resolveOneByKey(keyOrAlias, { args = [], child = this, lazy } = {}) {
|
|
56
58
|
this.validateContainer();
|
|
57
|
-
const provider = this.
|
|
59
|
+
const provider = this.providers.get(keyOrAlias);
|
|
58
60
|
return provider?.hasAccess({ invocationScope: child, providerScope: this })
|
|
59
61
|
? provider.resolve(this, { args, lazy })
|
|
60
62
|
: this.parent.resolveOneByKey(keyOrAlias, { args, child, lazy });
|
|
61
63
|
}
|
|
62
64
|
resolveOneByAlias(keyOrAlias, { args = [], child = this, lazy } = {}) {
|
|
63
65
|
this.validateContainer();
|
|
64
|
-
const key = this.
|
|
65
|
-
const provider = key !== undefined ? this.
|
|
66
|
+
const key = this.aliases.findLastKeyByAlias(keyOrAlias);
|
|
67
|
+
const provider = key !== undefined ? this.findProviderByKeyOrFail(key) : undefined;
|
|
66
68
|
return provider?.hasAccess({ invocationScope: child, providerScope: this })
|
|
67
69
|
? provider.resolve(this, { args, lazy })
|
|
68
70
|
: this.parent.resolveOneByAlias(keyOrAlias, { args, child, lazy });
|
|
@@ -71,8 +73,8 @@ class Container {
|
|
|
71
73
|
this.validateContainer();
|
|
72
74
|
const keys = [];
|
|
73
75
|
const deps = [];
|
|
74
|
-
for (const key of this.
|
|
75
|
-
const provider = this.
|
|
76
|
+
for (const key of this.aliases.findManyKeysByAlias(alias).filter(utils_1.Filter.exclude(excludedKeys))) {
|
|
77
|
+
const provider = this.findProviderByKeyOrFail(key);
|
|
76
78
|
if (!provider.hasAccess({ invocationScope: child, providerScope: this })) {
|
|
77
79
|
continue;
|
|
78
80
|
}
|
|
@@ -126,8 +128,8 @@ class Container {
|
|
|
126
128
|
this.parent.removeScope(this);
|
|
127
129
|
this.parent = new EmptyContainer_1.EmptyContainer();
|
|
128
130
|
// Reset the state
|
|
129
|
-
this.
|
|
130
|
-
this.
|
|
131
|
+
this.providers.clear();
|
|
132
|
+
this.aliases.destroy();
|
|
131
133
|
this.instances.clear();
|
|
132
134
|
this.registrations.clear();
|
|
133
135
|
this.onDispose(this);
|
|
@@ -145,5 +147,11 @@ class Container {
|
|
|
145
147
|
throw new ContainerDisposedError_1.ContainerDisposedError('Container is already disposed');
|
|
146
148
|
}
|
|
147
149
|
}
|
|
150
|
+
findProviderByKeyOrFail(key) {
|
|
151
|
+
if (!this.providers.has(key)) {
|
|
152
|
+
throw new DependencyNotFoundError_1.DependencyNotFoundError(`Provider ${key.toString()} does not exist`);
|
|
153
|
+
}
|
|
154
|
+
return this.providers.get(key);
|
|
155
|
+
}
|
|
148
156
|
}
|
|
149
157
|
exports.Container = Container;
|
|
@@ -9,7 +9,7 @@ function isDependencyKey(token) {
|
|
|
9
9
|
}
|
|
10
10
|
const DEFAULT_CONTAINER_RESOLVER = (scope, keyOrAlias, options) => {
|
|
11
11
|
if ((0, utils_1.isConstructor)(keyOrAlias)) {
|
|
12
|
-
return scope.
|
|
12
|
+
return scope.resolveClass(keyOrAlias, options);
|
|
13
13
|
}
|
|
14
14
|
try {
|
|
15
15
|
return scope.resolveOneByKey(keyOrAlias, options);
|
package/cjm/injector/inject.js
CHANGED
|
@@ -17,7 +17,7 @@ const toInjectFn = (target) => {
|
|
|
17
17
|
return (s) => target.resolve(s);
|
|
18
18
|
}
|
|
19
19
|
if ((0, utils_1.isConstructor)(target)) {
|
|
20
|
-
return (scope) => scope.
|
|
20
|
+
return (scope) => scope.resolveClass(target);
|
|
21
21
|
}
|
|
22
22
|
if ((0, IContainer_1.isDependencyKey)(target)) {
|
|
23
23
|
return (scope) => scope.resolveOne(target);
|
package/cjm/provider/Provider.js
CHANGED
|
@@ -6,7 +6,7 @@ const ProviderPipe_1 = require("./ProviderPipe");
|
|
|
6
6
|
class Provider {
|
|
7
7
|
resolveDependency;
|
|
8
8
|
static fromClass(Target) {
|
|
9
|
-
return new Provider((container, options) => container.
|
|
9
|
+
return new Provider((container, options) => container.resolveClass(Target, options));
|
|
10
10
|
}
|
|
11
11
|
static fromValue(value) {
|
|
12
12
|
return new Provider(() => value);
|
|
@@ -2,7 +2,7 @@ import { List as L } from '../utils';
|
|
|
2
2
|
export class AliasMap {
|
|
3
3
|
aliasToKeySet = new Map();
|
|
4
4
|
deleteKeyFromAliases(key) {
|
|
5
|
-
for (const [depKey, aliasSet] of [...this.aliasToKeySet].filter(([
|
|
5
|
+
for (const [depKey, aliasSet] of [...this.aliasToKeySet].filter(([, aliasSet]) => aliasSet.has(key))) {
|
|
6
6
|
aliasSet.delete(key);
|
|
7
7
|
if (aliasSet.size === 0) {
|
|
8
8
|
this.aliasToKeySet.delete(depKey);
|
|
@@ -1,34 +1,36 @@
|
|
|
1
|
-
import { DEFAULT_CONTAINER_RESOLVER
|
|
1
|
+
import { DEFAULT_CONTAINER_RESOLVER, } from './IContainer';
|
|
2
2
|
import { EmptyContainer } from './EmptyContainer';
|
|
3
3
|
import { ContainerDisposedError } from '../errors/ContainerDisposedError';
|
|
4
4
|
import { MetadataInjector } from '../injector/MetadataInjector';
|
|
5
5
|
import { Filter as F } from '../utils';
|
|
6
|
-
import { ProviderMap } from './ProviderMap';
|
|
7
6
|
import { AliasMap } from './AliasMap';
|
|
7
|
+
import { DependencyNotFoundError } from '../errors/DependencyNotFoundError';
|
|
8
8
|
export class Container {
|
|
9
9
|
isDisposed = false;
|
|
10
10
|
parent;
|
|
11
11
|
scopes = new Set();
|
|
12
12
|
instances = new Set();
|
|
13
13
|
tags;
|
|
14
|
-
|
|
15
|
-
|
|
14
|
+
providers = new Map();
|
|
15
|
+
aliases = new AliasMap();
|
|
16
16
|
registrations = new Set();
|
|
17
17
|
onConstruct;
|
|
18
18
|
onDispose;
|
|
19
19
|
injector;
|
|
20
|
+
resolveOneStrategy;
|
|
20
21
|
constructor(options = {}) {
|
|
21
22
|
this.injector = options.injector ?? new MetadataInjector();
|
|
22
23
|
this.parent = options.parent ?? new EmptyContainer();
|
|
23
24
|
this.tags = new Set(options.tags ?? []);
|
|
24
25
|
this.onConstruct = options.onConstruct ?? (() => { });
|
|
25
26
|
this.onDispose = options.onDispose ?? (() => { });
|
|
27
|
+
this.resolveOneStrategy = options.resolveOneStrategy ?? DEFAULT_CONTAINER_RESOLVER;
|
|
26
28
|
}
|
|
27
29
|
register(key, provider, { aliases = [] } = {}) {
|
|
28
30
|
this.validateContainer();
|
|
29
|
-
this.
|
|
30
|
-
this.
|
|
31
|
-
this.
|
|
31
|
+
this.providers.set(key, provider);
|
|
32
|
+
this.aliases.deleteKeyFromAliases(key);
|
|
33
|
+
this.aliases.addAliases(key, aliases);
|
|
32
34
|
return this;
|
|
33
35
|
}
|
|
34
36
|
addRegistration(registration) {
|
|
@@ -39,7 +41,7 @@ export class Container {
|
|
|
39
41
|
getRegistrations() {
|
|
40
42
|
return [...this.parent.getRegistrations(), ...this.registrations];
|
|
41
43
|
}
|
|
42
|
-
|
|
44
|
+
resolveClass(token, { args = [] } = {}) {
|
|
43
45
|
this.validateContainer();
|
|
44
46
|
const instance = this.injector.resolve(this, token, { args });
|
|
45
47
|
this.instances.add(instance);
|
|
@@ -47,19 +49,19 @@ export class Container {
|
|
|
47
49
|
return instance;
|
|
48
50
|
}
|
|
49
51
|
resolveOne(keyOrAlias, options) {
|
|
50
|
-
return
|
|
52
|
+
return this.resolveOneStrategy(this, keyOrAlias, options);
|
|
51
53
|
}
|
|
52
54
|
resolveOneByKey(keyOrAlias, { args = [], child = this, lazy } = {}) {
|
|
53
55
|
this.validateContainer();
|
|
54
|
-
const provider = this.
|
|
56
|
+
const provider = this.providers.get(keyOrAlias);
|
|
55
57
|
return provider?.hasAccess({ invocationScope: child, providerScope: this })
|
|
56
58
|
? provider.resolve(this, { args, lazy })
|
|
57
59
|
: this.parent.resolveOneByKey(keyOrAlias, { args, child, lazy });
|
|
58
60
|
}
|
|
59
61
|
resolveOneByAlias(keyOrAlias, { args = [], child = this, lazy } = {}) {
|
|
60
62
|
this.validateContainer();
|
|
61
|
-
const key = this.
|
|
62
|
-
const provider = key !== undefined ? this.
|
|
63
|
+
const key = this.aliases.findLastKeyByAlias(keyOrAlias);
|
|
64
|
+
const provider = key !== undefined ? this.findProviderByKeyOrFail(key) : undefined;
|
|
63
65
|
return provider?.hasAccess({ invocationScope: child, providerScope: this })
|
|
64
66
|
? provider.resolve(this, { args, lazy })
|
|
65
67
|
: this.parent.resolveOneByAlias(keyOrAlias, { args, child, lazy });
|
|
@@ -68,8 +70,8 @@ export class Container {
|
|
|
68
70
|
this.validateContainer();
|
|
69
71
|
const keys = [];
|
|
70
72
|
const deps = [];
|
|
71
|
-
for (const key of this.
|
|
72
|
-
const provider = this.
|
|
73
|
+
for (const key of this.aliases.findManyKeysByAlias(alias).filter(F.exclude(excludedKeys))) {
|
|
74
|
+
const provider = this.findProviderByKeyOrFail(key);
|
|
73
75
|
if (!provider.hasAccess({ invocationScope: child, providerScope: this })) {
|
|
74
76
|
continue;
|
|
75
77
|
}
|
|
@@ -123,8 +125,8 @@ export class Container {
|
|
|
123
125
|
this.parent.removeScope(this);
|
|
124
126
|
this.parent = new EmptyContainer();
|
|
125
127
|
// Reset the state
|
|
126
|
-
this.
|
|
127
|
-
this.
|
|
128
|
+
this.providers.clear();
|
|
129
|
+
this.aliases.destroy();
|
|
128
130
|
this.instances.clear();
|
|
129
131
|
this.registrations.clear();
|
|
130
132
|
this.onDispose(this);
|
|
@@ -142,4 +144,10 @@ export class Container {
|
|
|
142
144
|
throw new ContainerDisposedError('Container is already disposed');
|
|
143
145
|
}
|
|
144
146
|
}
|
|
147
|
+
findProviderByKeyOrFail(key) {
|
|
148
|
+
if (!this.providers.has(key)) {
|
|
149
|
+
throw new DependencyNotFoundError(`Provider ${key.toString()} does not exist`);
|
|
150
|
+
}
|
|
151
|
+
return this.providers.get(key);
|
|
152
|
+
}
|
|
145
153
|
}
|
|
@@ -5,7 +5,7 @@ export function isDependencyKey(token) {
|
|
|
5
5
|
}
|
|
6
6
|
export const DEFAULT_CONTAINER_RESOLVER = (scope, keyOrAlias, options) => {
|
|
7
7
|
if (isConstructor(keyOrAlias)) {
|
|
8
|
-
return scope.
|
|
8
|
+
return scope.resolveClass(keyOrAlias, options);
|
|
9
9
|
}
|
|
10
10
|
try {
|
|
11
11
|
return scope.resolveOneByKey(keyOrAlias, options);
|
package/esm/injector/inject.js
CHANGED
|
@@ -13,7 +13,7 @@ export const toInjectFn = (target) => {
|
|
|
13
13
|
return (s) => target.resolve(s);
|
|
14
14
|
}
|
|
15
15
|
if (isConstructor(target)) {
|
|
16
|
-
return (scope) => scope.
|
|
16
|
+
return (scope) => scope.resolveClass(target);
|
|
17
17
|
}
|
|
18
18
|
if (isDependencyKey(target)) {
|
|
19
19
|
return (scope) => scope.resolveOne(target);
|
package/esm/provider/Provider.js
CHANGED
|
@@ -3,7 +3,7 @@ import { isProviderPipe } from './ProviderPipe';
|
|
|
3
3
|
export class Provider {
|
|
4
4
|
resolveDependency;
|
|
5
5
|
static fromClass(Target) {
|
|
6
|
-
return new Provider((container, options) => container.
|
|
6
|
+
return new Provider((container, options) => container.resolveClass(Target, options));
|
|
7
7
|
}
|
|
8
8
|
static fromValue(value) {
|
|
9
9
|
return new Provider(() => value);
|
package/esm/resolve.js
CHANGED
package/package.json
CHANGED
|
@@ -15,7 +15,7 @@ export declare abstract class AutoMockedContainer implements IContainer {
|
|
|
15
15
|
getRegistrations(): never[];
|
|
16
16
|
addRegistration(registration: IRegistration): this;
|
|
17
17
|
abstract resolveMany<T>(alias: DependencyKey, options?: ResolveManyOptions): T[];
|
|
18
|
-
abstract
|
|
18
|
+
abstract resolveClass<T>(target: constructor<T>, options?: {
|
|
19
19
|
args?: unknown[];
|
|
20
20
|
}): T;
|
|
21
21
|
abstract resolveOneByKey<T>(keyOrAlias: DependencyKey, options?: ResolveOneOptions): T;
|
|
@@ -3,29 +3,32 @@ import { type IInjector } from '../injector/IInjector';
|
|
|
3
3
|
import { type IProvider } from '../provider/IProvider';
|
|
4
4
|
import { type IRegistration } from '../registration/IRegistration';
|
|
5
5
|
import { type constructor } from '../utils';
|
|
6
|
+
type ResolveOneStrategy = <T>(scope: IContainer, keyOrAlias: constructor<T> | DependencyKey, options?: ResolveOneOptions) => T;
|
|
6
7
|
export declare class Container implements IContainer {
|
|
7
8
|
isDisposed: boolean;
|
|
8
9
|
private parent;
|
|
9
10
|
private readonly scopes;
|
|
10
11
|
private readonly instances;
|
|
11
12
|
private readonly tags;
|
|
12
|
-
private readonly
|
|
13
|
-
private readonly
|
|
13
|
+
private readonly providers;
|
|
14
|
+
private readonly aliases;
|
|
14
15
|
private readonly registrations;
|
|
15
16
|
private readonly onConstruct;
|
|
16
17
|
private readonly onDispose;
|
|
17
18
|
private readonly injector;
|
|
19
|
+
private readonly resolveOneStrategy;
|
|
18
20
|
constructor(options?: {
|
|
19
21
|
injector?: IInjector;
|
|
20
22
|
parent?: IContainer;
|
|
21
23
|
tags?: Tag[];
|
|
22
24
|
onConstruct?: (instance: Instance, scope: IContainer) => void;
|
|
23
25
|
onDispose?: (scope: IContainer) => void;
|
|
26
|
+
resolveOneStrategy?: ResolveOneStrategy;
|
|
24
27
|
});
|
|
25
28
|
register(key: DependencyKey, provider: IProvider, { aliases }?: RegisterOptions): this;
|
|
26
29
|
addRegistration(registration: IRegistration): this;
|
|
27
30
|
getRegistrations(): IRegistration[];
|
|
28
|
-
|
|
31
|
+
resolveClass<T>(token: constructor<T>, { args }?: {
|
|
29
32
|
args?: unknown[];
|
|
30
33
|
}): T;
|
|
31
34
|
resolveOne<T>(keyOrAlias: constructor<T> | DependencyKey, options?: ResolveOneOptions): T;
|
|
@@ -45,4 +48,6 @@ export declare class Container implements IContainer {
|
|
|
45
48
|
*/
|
|
46
49
|
applyRegistrationsFrom(source: Container): void;
|
|
47
50
|
private validateContainer;
|
|
51
|
+
private findProviderByKeyOrFail;
|
|
48
52
|
}
|
|
53
|
+
export {};
|
|
@@ -5,7 +5,7 @@ import { type constructor } from '../utils';
|
|
|
5
5
|
export declare class EmptyContainer implements IContainer {
|
|
6
6
|
get isDisposed(): boolean;
|
|
7
7
|
getParent(): undefined;
|
|
8
|
-
|
|
8
|
+
resolveClass<T>(token: constructor<T>, options?: {
|
|
9
9
|
args?: [];
|
|
10
10
|
}): T;
|
|
11
11
|
getScopes(): never[];
|
|
@@ -36,7 +36,7 @@ export interface IContainer extends Tagged {
|
|
|
36
36
|
register(key: DependencyKey, value: IProvider, options?: RegisterOptions): this;
|
|
37
37
|
addRegistration(registration: IRegistration): this;
|
|
38
38
|
getRegistrations(): IRegistration[];
|
|
39
|
-
|
|
39
|
+
resolveClass<T>(target: constructor<T>, options?: {
|
|
40
40
|
args?: unknown[];
|
|
41
41
|
}): T;
|
|
42
42
|
resolveOne<T>(alias: constructor<T> | DependencyKey, options?: ResolveManyOptions): T;
|
package/typings/resolve.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import type
|
|
2
|
-
import type
|
|
3
|
-
import type
|
|
1
|
+
import { type CreateScopeOptions, type DependencyKey, type IContainer, type Instance } from './container/IContainer';
|
|
2
|
+
import { type constructor } from './utils';
|
|
3
|
+
import { type DepKey } from './DepKey';
|
|
4
4
|
import type { IInjectFnResolver } from './injector/IInjector';
|
|
5
5
|
export type InstancePredicate = (dep: unknown) => boolean;
|
|
6
6
|
export type InjectOptions = {
|
|
@@ -1,26 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.ProviderMap = void 0;
|
|
4
|
-
const DependencyNotFoundError_1 = require("../errors/DependencyNotFoundError");
|
|
5
|
-
class ProviderMap {
|
|
6
|
-
providers = new Map();
|
|
7
|
-
register(key, provider) {
|
|
8
|
-
this.providers.set(key, provider);
|
|
9
|
-
}
|
|
10
|
-
findOneByKey(key) {
|
|
11
|
-
return this.providers.get(key);
|
|
12
|
-
}
|
|
13
|
-
findOneByKeyOrFail(key) {
|
|
14
|
-
if (!this.providers.has(key)) {
|
|
15
|
-
throw new DependencyNotFoundError_1.DependencyNotFoundError(`Provider ${key.toString()} does not exist`);
|
|
16
|
-
}
|
|
17
|
-
return this.providers.get(key);
|
|
18
|
-
}
|
|
19
|
-
destroy() {
|
|
20
|
-
this.providers.clear();
|
|
21
|
-
}
|
|
22
|
-
has(keyOrAlias) {
|
|
23
|
-
return this.providers.has(keyOrAlias);
|
|
24
|
-
}
|
|
25
|
-
}
|
|
26
|
-
exports.ProviderMap = ProviderMap;
|
|
@@ -1,22 +0,0 @@
|
|
|
1
|
-
import { DependencyNotFoundError } from '../errors/DependencyNotFoundError';
|
|
2
|
-
export class ProviderMap {
|
|
3
|
-
providers = new Map();
|
|
4
|
-
register(key, provider) {
|
|
5
|
-
this.providers.set(key, provider);
|
|
6
|
-
}
|
|
7
|
-
findOneByKey(key) {
|
|
8
|
-
return this.providers.get(key);
|
|
9
|
-
}
|
|
10
|
-
findOneByKeyOrFail(key) {
|
|
11
|
-
if (!this.providers.has(key)) {
|
|
12
|
-
throw new DependencyNotFoundError(`Provider ${key.toString()} does not exist`);
|
|
13
|
-
}
|
|
14
|
-
return this.providers.get(key);
|
|
15
|
-
}
|
|
16
|
-
destroy() {
|
|
17
|
-
this.providers.clear();
|
|
18
|
-
}
|
|
19
|
-
has(keyOrAlias) {
|
|
20
|
-
return this.providers.has(keyOrAlias);
|
|
21
|
-
}
|
|
22
|
-
}
|
|
@@ -1,10 +0,0 @@
|
|
|
1
|
-
import { type DependencyKey } from './IContainer';
|
|
2
|
-
import { type IProvider } from '../provider/IProvider';
|
|
3
|
-
export declare class ProviderMap {
|
|
4
|
-
private readonly providers;
|
|
5
|
-
register(key: DependencyKey, provider: IProvider): void;
|
|
6
|
-
findOneByKey<T>(key: DependencyKey): IProvider<T> | undefined;
|
|
7
|
-
findOneByKeyOrFail<T>(key: DependencyKey): IProvider<T>;
|
|
8
|
-
destroy(): void;
|
|
9
|
-
has(keyOrAlias: DependencyKey): boolean;
|
|
10
|
-
}
|