ts-ioc-container 31.10.0 → 32.0.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/README.md +6 -4
- package/cjm/by.js +26 -36
- package/cjm/container/Container.js +18 -12
- package/cjm/index.js +3 -2
- package/cjm/injector/MetadataInjector.js +1 -1
- package/cjm/injector/ProxyInjector.js +1 -1
- package/cjm/injector/SimpleInjector.js +1 -1
- package/cjm/provider/DecoratorProvider.js +2 -2
- package/cjm/provider/IProvider.js +9 -3
- package/cjm/provider/LazyProvider.js +6 -12
- package/cjm/provider/Provider.js +11 -3
- package/cjm/provider/singleton/SingletonProvider.js +3 -3
- package/cjm/utils.js +12 -1
- package/esm/by.js +26 -36
- package/esm/container/Container.js +18 -12
- package/esm/index.js +2 -2
- package/esm/injector/MetadataInjector.js +1 -1
- package/esm/injector/ProxyInjector.js +1 -1
- package/esm/injector/SimpleInjector.js +1 -1
- package/esm/provider/DecoratorProvider.js +2 -2
- package/esm/provider/IProvider.js +7 -2
- package/esm/provider/LazyProvider.js +4 -10
- package/esm/provider/Provider.js +12 -4
- package/esm/provider/singleton/SingletonProvider.js +3 -3
- package/esm/utils.js +10 -0
- package/package.json +2 -2
- package/typings/by.d.ts +16 -7
- package/typings/container/Container.d.ts +4 -3
- package/typings/container/IContainer.d.ts +1 -0
- package/typings/index.d.ts +2 -2
- package/typings/injector/IInjector.d.ts +4 -1
- package/typings/injector/MetadataInjector.d.ts +2 -2
- package/typings/injector/ProxyInjector.d.ts +2 -2
- package/typings/injector/SimpleInjector.d.ts +2 -2
- package/typings/provider/DecoratorProvider.d.ts +2 -2
- package/typings/provider/IProvider.d.ts +10 -3
- package/typings/provider/LazyProvider.d.ts +3 -3
- package/typings/provider/Provider.d.ts +4 -2
- package/typings/provider/singleton/SingletonProvider.d.ts +2 -2
- package/typings/utils.d.ts +1 -0
package/README.md
CHANGED
|
@@ -99,7 +99,7 @@ describe('Basic usage', function () {
|
|
|
99
99
|
|
|
100
100
|
it('should inject multiple dependencies', function () {
|
|
101
101
|
class App {
|
|
102
|
-
constructor(@inject(by.keys('ILogger1', 'ILogger2')) public loggers: Logger[]) {}
|
|
102
|
+
constructor(@inject(by.keys(['ILogger1', 'ILogger2'])) public loggers: Logger[]) {}
|
|
103
103
|
}
|
|
104
104
|
|
|
105
105
|
const container = new Container(new MetadataInjector())
|
|
@@ -770,9 +770,9 @@ describe('alias', () => {
|
|
|
770
770
|
.add(R.fromClass(FileLogger))
|
|
771
771
|
.add(R.fromClass(DbLogger));
|
|
772
772
|
|
|
773
|
-
const result1 = by.alias((aliases) => aliases.has('ILogger'), constant('ILogger'))(container);
|
|
773
|
+
const result1 = by.alias((aliases) => aliases.has('ILogger'), { memoize: constant('ILogger') })(container);
|
|
774
774
|
const child = container.createScope('child');
|
|
775
|
-
const result2 = by.alias((aliases) => aliases.has('ILogger'), constant('ILogger'))(child);
|
|
775
|
+
const result2 = by.alias((aliases) => aliases.has('ILogger'), { memoize: constant('ILogger') })(child);
|
|
776
776
|
const result3 = by.alias((aliases) => aliases.has('ILogger'))(child);
|
|
777
777
|
|
|
778
778
|
expect(result1).toBeInstanceOf(FileLogger);
|
|
@@ -791,7 +791,9 @@ describe('alias', () => {
|
|
|
791
791
|
class DbLogger implements ILogger {}
|
|
792
792
|
|
|
793
793
|
class App {
|
|
794
|
-
constructor(
|
|
794
|
+
constructor(
|
|
795
|
+
@inject(by.aliases((it) => it.has('ILogger'), { memoize: constant('ILogger') })) public loggers: ILogger[],
|
|
796
|
+
) {}
|
|
795
797
|
}
|
|
796
798
|
|
|
797
799
|
const container = new Container(new MetadataInjector())
|
package/cjm/by.js
CHANGED
|
@@ -5,64 +5,54 @@ const all = () => true;
|
|
|
5
5
|
exports.all = all;
|
|
6
6
|
exports.IMemoKey = Symbol('IMemo');
|
|
7
7
|
exports.by = {
|
|
8
|
-
aliases: (predicate, memoize) => (c, ...args) => {
|
|
8
|
+
aliases: (predicate, { memoize, lazy } = {}) => (c, ...args) => {
|
|
9
9
|
const predicateFn = (aliases) => predicate(aliases, c);
|
|
10
10
|
const memoKey = memoize?.(c);
|
|
11
|
-
if (memoKey) {
|
|
12
|
-
|
|
13
|
-
const memoized = memo.get(memoKey);
|
|
14
|
-
if (memoized) {
|
|
15
|
-
return memoized.map((key) => c.resolve(key, { args }));
|
|
16
|
-
}
|
|
17
|
-
const result = c.resolveManyByAlias(predicateFn, { args });
|
|
18
|
-
memo.set(memoKey, Array.from(result.keys()));
|
|
19
|
-
return Array.from(result.values());
|
|
11
|
+
if (memoKey === undefined) {
|
|
12
|
+
return Array.from(c.resolveManyByAlias(predicateFn, { args, lazy }).values());
|
|
20
13
|
}
|
|
21
|
-
|
|
14
|
+
const memo = c.resolve(exports.IMemoKey);
|
|
15
|
+
const memoized = memo.get(memoKey);
|
|
16
|
+
if (memoized) {
|
|
17
|
+
return memoized.map((key) => c.resolve(key, { args, lazy }));
|
|
18
|
+
}
|
|
19
|
+
const result = c.resolveManyByAlias(predicateFn, { args, lazy });
|
|
20
|
+
memo.set(memoKey, Array.from(result.keys()));
|
|
21
|
+
return Array.from(result.values());
|
|
22
22
|
},
|
|
23
23
|
/**
|
|
24
24
|
* Get the instance that matches the given alias or fail
|
|
25
25
|
* @param predicate
|
|
26
26
|
* @param memoize
|
|
27
27
|
*/
|
|
28
|
-
alias: (predicate, memoize) => (c, ...args) => {
|
|
28
|
+
alias: (predicate, { memoize, lazy } = {}) => (c, ...args) => {
|
|
29
29
|
const predicateFn = (aliases) => predicate(aliases, c);
|
|
30
30
|
const memoKey = memoize?.(c);
|
|
31
|
-
if (memoKey) {
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
memo.set(memoKey, [key]);
|
|
39
|
-
return result;
|
|
31
|
+
if (memoKey === undefined) {
|
|
32
|
+
return c.resolveOneByAlias(predicateFn, { args, lazy })[1];
|
|
33
|
+
}
|
|
34
|
+
const memo = c.resolve(exports.IMemoKey);
|
|
35
|
+
const memoized = memo.get(memoKey);
|
|
36
|
+
if (memoized) {
|
|
37
|
+
return c.resolve(memoized[0], { args, lazy });
|
|
40
38
|
}
|
|
41
|
-
|
|
39
|
+
const [key, result] = c.resolveOneByAlias(predicateFn, { args, lazy });
|
|
40
|
+
memo.set(memoKey, [key]);
|
|
41
|
+
return result;
|
|
42
42
|
},
|
|
43
43
|
/**
|
|
44
44
|
* Get all instances that match the given keys
|
|
45
45
|
* @param keys
|
|
46
|
+
* @param lazy
|
|
46
47
|
*/
|
|
47
|
-
keys: (
|
|
48
|
+
keys: (keys, { lazy } = {}) => (с, ...args) => keys.map((t) => с.resolve(t, { args, lazy })),
|
|
48
49
|
/**
|
|
49
50
|
* Get the instance that matches the given key
|
|
50
51
|
* @param key
|
|
51
52
|
* @param deps
|
|
53
|
+
* @param lazy
|
|
52
54
|
*/
|
|
53
|
-
key: (key,
|
|
54
|
-
lazy: {
|
|
55
|
-
key: (key, ...deps) => (c, ...args) => {
|
|
56
|
-
let instance;
|
|
57
|
-
return new Proxy({}, {
|
|
58
|
-
get: (_, prop) => {
|
|
59
|
-
instance = instance ?? c.resolve(key, { args: [...deps, ...args] });
|
|
60
|
-
// @ts-ignore
|
|
61
|
-
return instance[prop];
|
|
62
|
-
},
|
|
63
|
-
});
|
|
64
|
-
},
|
|
65
|
-
},
|
|
55
|
+
key: (key, { args: deps = [], lazy } = {}) => (c, ...args) => c.resolve(key, { args: [...deps, ...args], lazy }),
|
|
66
56
|
/**
|
|
67
57
|
* Get all instances that match the given predicate
|
|
68
58
|
* @param predicate
|
|
@@ -4,6 +4,7 @@ exports.Container = void 0;
|
|
|
4
4
|
const IContainer_1 = require("./IContainer");
|
|
5
5
|
const EmptyContainer_1 = require("./EmptyContainer");
|
|
6
6
|
const ContainerDisposedError_1 = require("../errors/ContainerDisposedError");
|
|
7
|
+
const utils_1 = require("../utils");
|
|
7
8
|
class Container {
|
|
8
9
|
constructor(injector, options = {}) {
|
|
9
10
|
this.injector = injector;
|
|
@@ -25,17 +26,22 @@ class Container {
|
|
|
25
26
|
this.providers.set(key, provider);
|
|
26
27
|
return this;
|
|
27
28
|
}
|
|
28
|
-
resolve(token, { args = [], child = this } = {}) {
|
|
29
|
+
resolve(token, { args = [], child = this, lazy } = {}) {
|
|
29
30
|
this.validateContainer();
|
|
30
31
|
if ((0, IContainer_1.isConstructor)(token)) {
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
32
|
+
return lazy
|
|
33
|
+
? (0, utils_1.lazyInstance)(() => this.resolveByInjector(token, { args }))
|
|
34
|
+
: this.resolveByInjector(token, { args });
|
|
34
35
|
}
|
|
35
36
|
const provider = this.providers.get(token);
|
|
36
37
|
return provider?.isVisible(this, child)
|
|
37
|
-
? provider.resolve(this,
|
|
38
|
-
: this.parent.resolve(token, { args, child });
|
|
38
|
+
? provider.resolve(this, { args, lazy })
|
|
39
|
+
: this.parent.resolve(token, { args, child, lazy });
|
|
40
|
+
}
|
|
41
|
+
resolveByInjector(token, options) {
|
|
42
|
+
const instance = this.injector.resolve(this, token, options);
|
|
43
|
+
this.instances.add(instance);
|
|
44
|
+
return instance;
|
|
39
45
|
}
|
|
40
46
|
createScope(...tags) {
|
|
41
47
|
this.validateContainer();
|
|
@@ -73,21 +79,21 @@ class Container {
|
|
|
73
79
|
hasDependency(key) {
|
|
74
80
|
return this.providers.has(key) ?? this.parent.hasDependency(key);
|
|
75
81
|
}
|
|
76
|
-
resolveManyByAlias(predicate, { args = [], child = this } = {}, result = new Map()) {
|
|
82
|
+
resolveManyByAlias(predicate, { args = [], child = this, lazy } = {}, result = new Map()) {
|
|
77
83
|
for (const [key, provider] of this.providers.entries()) {
|
|
78
84
|
if (!result.has(key) && provider.matchAliases(predicate) && provider.isVisible(this, child)) {
|
|
79
|
-
result.set(key, provider.resolve(this,
|
|
85
|
+
result.set(key, provider.resolve(this, { args, lazy }));
|
|
80
86
|
}
|
|
81
87
|
}
|
|
82
|
-
return this.parent.resolveManyByAlias(predicate, { args, child }, result);
|
|
88
|
+
return this.parent.resolveManyByAlias(predicate, { args, child, lazy }, result);
|
|
83
89
|
}
|
|
84
|
-
resolveOneByAlias(predicate, { args = [], child = this } = {}) {
|
|
90
|
+
resolveOneByAlias(predicate, { args = [], child = this, lazy } = {}) {
|
|
85
91
|
for (const [key, provider] of this.providers.entries()) {
|
|
86
92
|
if (provider.matchAliases(predicate) && provider.isVisible(this, child)) {
|
|
87
|
-
return [key, provider.resolve(this,
|
|
93
|
+
return [key, provider.resolve(this, { args, lazy })];
|
|
88
94
|
}
|
|
89
95
|
}
|
|
90
|
-
return this.parent.resolveOneByAlias(predicate, { args, child });
|
|
96
|
+
return this.parent.resolveOneByAlias(predicate, { args, child, lazy });
|
|
91
97
|
}
|
|
92
98
|
/**
|
|
93
99
|
* @private
|
package/cjm/index.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.getParameterMetadata = exports.getMethodMetadata = exports.setMethodMetadata = exports.setParameterMetadata = exports.getMetadata = exports.setMetadata = exports.IMemoKey = exports.by = exports.hasHooks = exports.hook = exports.getHooks = exports.ContainerDisposedError = exports.MethodNotImplementedError = exports.DependencyNotFoundError = exports.Registration = exports.register = exports.scope = exports.key = exports.decorate = exports.
|
|
3
|
+
exports.getParameterMetadata = exports.getMethodMetadata = exports.setMethodMetadata = exports.setParameterMetadata = exports.getMetadata = exports.setMetadata = exports.IMemoKey = exports.by = exports.hasHooks = exports.hook = exports.getHooks = exports.ContainerDisposedError = exports.MethodNotImplementedError = exports.DependencyNotFoundError = exports.Registration = exports.register = exports.scope = exports.key = exports.decorate = exports.makeProviderLazy = exports.multiCache = exports.MultiCache = exports.SingletonProvider = exports.singleton = exports.Provider = exports.ProviderDecorator = exports.lazy = exports.args = exports.argsFn = exports.alias = exports.visible = exports.provider = exports.ProxyInjector = exports.SimpleInjector = exports.inject = exports.MetadataInjector = exports.AutoMockedContainer = exports.EmptyContainer = exports.Container = exports.isDependencyKey = void 0;
|
|
4
4
|
// Containers
|
|
5
5
|
var IContainer_1 = require("./container/IContainer");
|
|
6
6
|
Object.defineProperty(exports, "isDependencyKey", { enumerable: true, get: function () { return IContainer_1.isDependencyKey; } });
|
|
@@ -24,6 +24,7 @@ Object.defineProperty(exports, "visible", { enumerable: true, get: function () {
|
|
|
24
24
|
Object.defineProperty(exports, "alias", { enumerable: true, get: function () { return IProvider_1.alias; } });
|
|
25
25
|
Object.defineProperty(exports, "argsFn", { enumerable: true, get: function () { return IProvider_1.argsFn; } });
|
|
26
26
|
Object.defineProperty(exports, "args", { enumerable: true, get: function () { return IProvider_1.args; } });
|
|
27
|
+
Object.defineProperty(exports, "lazy", { enumerable: true, get: function () { return IProvider_1.lazy; } });
|
|
27
28
|
Object.defineProperty(exports, "ProviderDecorator", { enumerable: true, get: function () { return IProvider_1.ProviderDecorator; } });
|
|
28
29
|
var Provider_1 = require("./provider/Provider");
|
|
29
30
|
Object.defineProperty(exports, "Provider", { enumerable: true, get: function () { return Provider_1.Provider; } });
|
|
@@ -34,7 +35,7 @@ var MultiCache_1 = require("./provider/singleton/MultiCache");
|
|
|
34
35
|
Object.defineProperty(exports, "MultiCache", { enumerable: true, get: function () { return MultiCache_1.MultiCache; } });
|
|
35
36
|
Object.defineProperty(exports, "multiCache", { enumerable: true, get: function () { return MultiCache_1.multiCache; } });
|
|
36
37
|
var LazyProvider_1 = require("./provider/LazyProvider");
|
|
37
|
-
Object.defineProperty(exports, "
|
|
38
|
+
Object.defineProperty(exports, "makeProviderLazy", { enumerable: true, get: function () { return LazyProvider_1.makeProviderLazy; } });
|
|
38
39
|
var DecoratorProvider_1 = require("./provider/DecoratorProvider");
|
|
39
40
|
Object.defineProperty(exports, "decorate", { enumerable: true, get: function () { return DecoratorProvider_1.decorate; } });
|
|
40
41
|
// Registrations
|
|
@@ -8,7 +8,7 @@ const getInjectFns = (Target) => (0, metadata_1.getParameterMetadata)(METADATA_K
|
|
|
8
8
|
const inject = (fn) => (0, metadata_1.setParameterMetadata)(METADATA_KEY, fn);
|
|
9
9
|
exports.inject = inject;
|
|
10
10
|
class MetadataInjector {
|
|
11
|
-
resolve(container, Target,
|
|
11
|
+
resolve(container, Target, { args: deps }) {
|
|
12
12
|
const injectionFns = getInjectFns(Target);
|
|
13
13
|
const args = (0, utils_1.fillEmptyIndexes)(injectionFns, deps.map(utils_1.constant)).map((fn) => fn(container));
|
|
14
14
|
return new Target(...args);
|
|
@@ -8,7 +8,7 @@ function getProp(target, key) {
|
|
|
8
8
|
}
|
|
9
9
|
class ProxyInjector {
|
|
10
10
|
// eslint-disable-next-line @typescript-eslint/ban-types
|
|
11
|
-
resolve(container, Target,
|
|
11
|
+
resolve(container, Target, { args: deps }) {
|
|
12
12
|
const args = deps.reduce((acc, it) => ({ ...acc, ...it }), {});
|
|
13
13
|
const proxy = new Proxy({}, {
|
|
14
14
|
// eslint-disable-next-line @typescript-eslint/ban-types
|
|
@@ -8,8 +8,8 @@ class DecoratorProvider extends IProvider_1.ProviderDecorator {
|
|
|
8
8
|
this.provider = provider;
|
|
9
9
|
this.decorateFn = decorateFn;
|
|
10
10
|
}
|
|
11
|
-
resolve(scope,
|
|
12
|
-
const dependency = this.provider.resolve(scope,
|
|
11
|
+
resolve(scope, options) {
|
|
12
|
+
const dependency = this.provider.resolve(scope, options);
|
|
13
13
|
return this.decorateFn(dependency, scope);
|
|
14
14
|
}
|
|
15
15
|
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.ProviderDecorator = exports.visible = exports.alias = exports.getTransformers = exports.provider = exports.argsFn = exports.args = void 0;
|
|
3
|
+
exports.ProviderDecorator = exports.visible = exports.alias = exports.getTransformers = exports.provider = exports.lazy = exports.argsFn = exports.args = void 0;
|
|
4
4
|
const utils_1 = require("../utils");
|
|
5
5
|
const metadata_1 = require("../metadata");
|
|
6
6
|
function args(...extraArgs) {
|
|
@@ -11,6 +11,8 @@ function argsFn(fn) {
|
|
|
11
11
|
return (provider) => provider.setArgs(fn);
|
|
12
12
|
}
|
|
13
13
|
exports.argsFn = argsFn;
|
|
14
|
+
const lazy = (provider) => provider.setLazy(true);
|
|
15
|
+
exports.lazy = lazy;
|
|
14
16
|
const METADATA_KEY = 'provider';
|
|
15
17
|
const provider = (...mappers) => (0, metadata_1.setMetadata)(METADATA_KEY, mappers);
|
|
16
18
|
exports.provider = provider;
|
|
@@ -31,8 +33,8 @@ class ProviderDecorator {
|
|
|
31
33
|
isVisible(parent, child) {
|
|
32
34
|
return this.decorated.isVisible(parent, child);
|
|
33
35
|
}
|
|
34
|
-
resolve(container,
|
|
35
|
-
return this.decorated.resolve(container,
|
|
36
|
+
resolve(container, options) {
|
|
37
|
+
return this.decorated.resolve(container, options);
|
|
36
38
|
}
|
|
37
39
|
pipe(...mappers) {
|
|
38
40
|
return (0, utils_1.pipe)(...mappers)(this);
|
|
@@ -48,5 +50,9 @@ class ProviderDecorator {
|
|
|
48
50
|
this.decorated.setArgs(argsFn);
|
|
49
51
|
return this;
|
|
50
52
|
}
|
|
53
|
+
setLazy(lazy) {
|
|
54
|
+
this.decorated.setLazy(lazy);
|
|
55
|
+
return this;
|
|
56
|
+
}
|
|
51
57
|
}
|
|
52
58
|
exports.ProviderDecorator = ProviderDecorator;
|
|
@@ -1,23 +1,17 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.
|
|
3
|
+
exports.makeProviderLazy = exports.LazyProvider = void 0;
|
|
4
4
|
const IProvider_1 = require("./IProvider");
|
|
5
|
+
const utils_1 = require("../utils");
|
|
5
6
|
class LazyProvider extends IProvider_1.ProviderDecorator {
|
|
6
7
|
constructor(provider) {
|
|
7
8
|
super(provider);
|
|
8
9
|
this.provider = provider;
|
|
9
10
|
}
|
|
10
|
-
resolve(container,
|
|
11
|
-
|
|
12
|
-
return new Proxy({}, {
|
|
13
|
-
get: (_, prop) => {
|
|
14
|
-
instance = instance ?? this.provider.resolve(container, ...args);
|
|
15
|
-
// @ts-ignore
|
|
16
|
-
return instance[prop];
|
|
17
|
-
},
|
|
18
|
-
});
|
|
11
|
+
resolve(container, options) {
|
|
12
|
+
return (0, utils_1.lazyInstance)(() => this.provider.resolve(container, options));
|
|
19
13
|
}
|
|
20
14
|
}
|
|
21
15
|
exports.LazyProvider = LazyProvider;
|
|
22
|
-
const
|
|
23
|
-
exports.
|
|
16
|
+
const makeProviderLazy = (provider) => new LazyProvider(provider);
|
|
17
|
+
exports.makeProviderLazy = makeProviderLazy;
|
package/cjm/provider/Provider.js
CHANGED
|
@@ -6,7 +6,7 @@ const utils_1 = require("../utils");
|
|
|
6
6
|
class Provider {
|
|
7
7
|
static fromClass(Target) {
|
|
8
8
|
const transformers = (0, IProvider_1.getTransformers)(Target);
|
|
9
|
-
return new Provider((container,
|
|
9
|
+
return new Provider((container, options) => container.resolve(Target, options)).pipe(...transformers);
|
|
10
10
|
}
|
|
11
11
|
static fromValue(value) {
|
|
12
12
|
const mappers = (0, utils_1.isConstructor)(value) ? (0, IProvider_1.getTransformers)(value) ?? [] : [];
|
|
@@ -16,18 +16,26 @@ class Provider {
|
|
|
16
16
|
this.resolveDependency = resolveDependency;
|
|
17
17
|
this.aliases = new Set();
|
|
18
18
|
this.argsFn = () => [];
|
|
19
|
+
this.isLazy = false;
|
|
19
20
|
this.isVisibleWhen = () => true;
|
|
20
21
|
}
|
|
21
22
|
pipe(...mappers) {
|
|
22
23
|
return (0, utils_1.pipe)(...mappers)(this);
|
|
23
24
|
}
|
|
24
|
-
resolve(container,
|
|
25
|
-
return this.resolveDependency(container,
|
|
25
|
+
resolve(container, { args, lazy }) {
|
|
26
|
+
return this.resolveDependency(container, {
|
|
27
|
+
args: [...this.argsFn(container, ...args), ...args],
|
|
28
|
+
lazy: lazy ?? this.isLazy ?? false,
|
|
29
|
+
});
|
|
26
30
|
}
|
|
27
31
|
setVisibility(predicate) {
|
|
28
32
|
this.isVisibleWhen = predicate;
|
|
29
33
|
return this;
|
|
30
34
|
}
|
|
35
|
+
setLazy(lazy) {
|
|
36
|
+
this.isLazy = lazy;
|
|
37
|
+
return this;
|
|
38
|
+
}
|
|
31
39
|
setArgs(argsFn) {
|
|
32
40
|
this.argsFn = argsFn;
|
|
33
41
|
return this;
|
|
@@ -13,10 +13,10 @@ class SingletonProvider extends IProvider_1.ProviderDecorator {
|
|
|
13
13
|
this.provider = provider;
|
|
14
14
|
this.cache = cache;
|
|
15
15
|
}
|
|
16
|
-
resolve(container,
|
|
17
|
-
const key = this.cache.getKey(...args);
|
|
16
|
+
resolve(container, options) {
|
|
17
|
+
const key = this.cache.getKey(...options.args);
|
|
18
18
|
if (!this.cache.hasValue(key)) {
|
|
19
|
-
this.cache.setValue(key, this.provider.resolve(container,
|
|
19
|
+
this.cache.setValue(key, this.provider.resolve(container, options));
|
|
20
20
|
}
|
|
21
21
|
return this.cache.getValue(key);
|
|
22
22
|
}
|
package/cjm/utils.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.isConstructor = exports.constant = exports.fillEmptyIndexes = exports.pipe = void 0;
|
|
3
|
+
exports.lazyInstance = exports.isConstructor = exports.constant = exports.fillEmptyIndexes = exports.pipe = void 0;
|
|
4
4
|
const pipe = (...mappers) => (value) => mappers.reduce((acc, current) => current(acc), value);
|
|
5
5
|
exports.pipe = pipe;
|
|
6
6
|
function fillEmptyIndexes(baseArr, insertArr) {
|
|
@@ -18,3 +18,14 @@ const constant = (value) => () => value;
|
|
|
18
18
|
exports.constant = constant;
|
|
19
19
|
const isConstructor = (T) => typeof T === 'function' && !!T.prototype;
|
|
20
20
|
exports.isConstructor = isConstructor;
|
|
21
|
+
function lazyInstance(resolveInstance) {
|
|
22
|
+
let instance;
|
|
23
|
+
return new Proxy({}, {
|
|
24
|
+
get: (_, prop) => {
|
|
25
|
+
instance = instance ?? resolveInstance();
|
|
26
|
+
// @ts-ignore
|
|
27
|
+
return instance[prop];
|
|
28
|
+
},
|
|
29
|
+
});
|
|
30
|
+
}
|
|
31
|
+
exports.lazyInstance = lazyInstance;
|
package/esm/by.js
CHANGED
|
@@ -1,64 +1,54 @@
|
|
|
1
1
|
export const all = () => true;
|
|
2
2
|
export const IMemoKey = Symbol('IMemo');
|
|
3
3
|
export const by = {
|
|
4
|
-
aliases: (predicate, memoize) => (c, ...args) => {
|
|
4
|
+
aliases: (predicate, { memoize, lazy } = {}) => (c, ...args) => {
|
|
5
5
|
const predicateFn = (aliases) => predicate(aliases, c);
|
|
6
6
|
const memoKey = memoize?.(c);
|
|
7
|
-
if (memoKey) {
|
|
8
|
-
|
|
9
|
-
const memoized = memo.get(memoKey);
|
|
10
|
-
if (memoized) {
|
|
11
|
-
return memoized.map((key) => c.resolve(key, { args }));
|
|
12
|
-
}
|
|
13
|
-
const result = c.resolveManyByAlias(predicateFn, { args });
|
|
14
|
-
memo.set(memoKey, Array.from(result.keys()));
|
|
15
|
-
return Array.from(result.values());
|
|
7
|
+
if (memoKey === undefined) {
|
|
8
|
+
return Array.from(c.resolveManyByAlias(predicateFn, { args, lazy }).values());
|
|
16
9
|
}
|
|
17
|
-
|
|
10
|
+
const memo = c.resolve(IMemoKey);
|
|
11
|
+
const memoized = memo.get(memoKey);
|
|
12
|
+
if (memoized) {
|
|
13
|
+
return memoized.map((key) => c.resolve(key, { args, lazy }));
|
|
14
|
+
}
|
|
15
|
+
const result = c.resolveManyByAlias(predicateFn, { args, lazy });
|
|
16
|
+
memo.set(memoKey, Array.from(result.keys()));
|
|
17
|
+
return Array.from(result.values());
|
|
18
18
|
},
|
|
19
19
|
/**
|
|
20
20
|
* Get the instance that matches the given alias or fail
|
|
21
21
|
* @param predicate
|
|
22
22
|
* @param memoize
|
|
23
23
|
*/
|
|
24
|
-
alias: (predicate, memoize) => (c, ...args) => {
|
|
24
|
+
alias: (predicate, { memoize, lazy } = {}) => (c, ...args) => {
|
|
25
25
|
const predicateFn = (aliases) => predicate(aliases, c);
|
|
26
26
|
const memoKey = memoize?.(c);
|
|
27
|
-
if (memoKey) {
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
memo.set(memoKey, [key]);
|
|
35
|
-
return result;
|
|
27
|
+
if (memoKey === undefined) {
|
|
28
|
+
return c.resolveOneByAlias(predicateFn, { args, lazy })[1];
|
|
29
|
+
}
|
|
30
|
+
const memo = c.resolve(IMemoKey);
|
|
31
|
+
const memoized = memo.get(memoKey);
|
|
32
|
+
if (memoized) {
|
|
33
|
+
return c.resolve(memoized[0], { args, lazy });
|
|
36
34
|
}
|
|
37
|
-
|
|
35
|
+
const [key, result] = c.resolveOneByAlias(predicateFn, { args, lazy });
|
|
36
|
+
memo.set(memoKey, [key]);
|
|
37
|
+
return result;
|
|
38
38
|
},
|
|
39
39
|
/**
|
|
40
40
|
* Get all instances that match the given keys
|
|
41
41
|
* @param keys
|
|
42
|
+
* @param lazy
|
|
42
43
|
*/
|
|
43
|
-
keys: (
|
|
44
|
+
keys: (keys, { lazy } = {}) => (с, ...args) => keys.map((t) => с.resolve(t, { args, lazy })),
|
|
44
45
|
/**
|
|
45
46
|
* Get the instance that matches the given key
|
|
46
47
|
* @param key
|
|
47
48
|
* @param deps
|
|
49
|
+
* @param lazy
|
|
48
50
|
*/
|
|
49
|
-
key: (key,
|
|
50
|
-
lazy: {
|
|
51
|
-
key: (key, ...deps) => (c, ...args) => {
|
|
52
|
-
let instance;
|
|
53
|
-
return new Proxy({}, {
|
|
54
|
-
get: (_, prop) => {
|
|
55
|
-
instance = instance ?? c.resolve(key, { args: [...deps, ...args] });
|
|
56
|
-
// @ts-ignore
|
|
57
|
-
return instance[prop];
|
|
58
|
-
},
|
|
59
|
-
});
|
|
60
|
-
},
|
|
61
|
-
},
|
|
51
|
+
key: (key, { args: deps = [], lazy } = {}) => (c, ...args) => c.resolve(key, { args: [...deps, ...args], lazy }),
|
|
62
52
|
/**
|
|
63
53
|
* Get all instances that match the given predicate
|
|
64
54
|
* @param predicate
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { isConstructor, } from './IContainer';
|
|
2
2
|
import { EmptyContainer } from './EmptyContainer';
|
|
3
3
|
import { ContainerDisposedError } from '../errors/ContainerDisposedError';
|
|
4
|
+
import { lazyInstance } from '../utils';
|
|
4
5
|
export class Container {
|
|
5
6
|
constructor(injector, options = {}) {
|
|
6
7
|
this.injector = injector;
|
|
@@ -22,17 +23,22 @@ export class Container {
|
|
|
22
23
|
this.providers.set(key, provider);
|
|
23
24
|
return this;
|
|
24
25
|
}
|
|
25
|
-
resolve(token, { args = [], child = this } = {}) {
|
|
26
|
+
resolve(token, { args = [], child = this, lazy } = {}) {
|
|
26
27
|
this.validateContainer();
|
|
27
28
|
if (isConstructor(token)) {
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
29
|
+
return lazy
|
|
30
|
+
? lazyInstance(() => this.resolveByInjector(token, { args }))
|
|
31
|
+
: this.resolveByInjector(token, { args });
|
|
31
32
|
}
|
|
32
33
|
const provider = this.providers.get(token);
|
|
33
34
|
return provider?.isVisible(this, child)
|
|
34
|
-
? provider.resolve(this,
|
|
35
|
-
: this.parent.resolve(token, { args, child });
|
|
35
|
+
? provider.resolve(this, { args, lazy })
|
|
36
|
+
: this.parent.resolve(token, { args, child, lazy });
|
|
37
|
+
}
|
|
38
|
+
resolveByInjector(token, options) {
|
|
39
|
+
const instance = this.injector.resolve(this, token, options);
|
|
40
|
+
this.instances.add(instance);
|
|
41
|
+
return instance;
|
|
36
42
|
}
|
|
37
43
|
createScope(...tags) {
|
|
38
44
|
this.validateContainer();
|
|
@@ -70,21 +76,21 @@ export class Container {
|
|
|
70
76
|
hasDependency(key) {
|
|
71
77
|
return this.providers.has(key) ?? this.parent.hasDependency(key);
|
|
72
78
|
}
|
|
73
|
-
resolveManyByAlias(predicate, { args = [], child = this } = {}, result = new Map()) {
|
|
79
|
+
resolveManyByAlias(predicate, { args = [], child = this, lazy } = {}, result = new Map()) {
|
|
74
80
|
for (const [key, provider] of this.providers.entries()) {
|
|
75
81
|
if (!result.has(key) && provider.matchAliases(predicate) && provider.isVisible(this, child)) {
|
|
76
|
-
result.set(key, provider.resolve(this,
|
|
82
|
+
result.set(key, provider.resolve(this, { args, lazy }));
|
|
77
83
|
}
|
|
78
84
|
}
|
|
79
|
-
return this.parent.resolveManyByAlias(predicate, { args, child }, result);
|
|
85
|
+
return this.parent.resolveManyByAlias(predicate, { args, child, lazy }, result);
|
|
80
86
|
}
|
|
81
|
-
resolveOneByAlias(predicate, { args = [], child = this } = {}) {
|
|
87
|
+
resolveOneByAlias(predicate, { args = [], child = this, lazy } = {}) {
|
|
82
88
|
for (const [key, provider] of this.providers.entries()) {
|
|
83
89
|
if (provider.matchAliases(predicate) && provider.isVisible(this, child)) {
|
|
84
|
-
return [key, provider.resolve(this,
|
|
90
|
+
return [key, provider.resolve(this, { args, lazy })];
|
|
85
91
|
}
|
|
86
92
|
}
|
|
87
|
-
return this.parent.resolveOneByAlias(predicate, { args, child });
|
|
93
|
+
return this.parent.resolveOneByAlias(predicate, { args, child, lazy });
|
|
88
94
|
}
|
|
89
95
|
/**
|
|
90
96
|
* @private
|
package/esm/index.js
CHANGED
|
@@ -7,11 +7,11 @@ export { MetadataInjector, inject } from './injector/MetadataInjector';
|
|
|
7
7
|
export { SimpleInjector } from './injector/SimpleInjector';
|
|
8
8
|
export { ProxyInjector } from './injector/ProxyInjector';
|
|
9
9
|
// Providers
|
|
10
|
-
export { provider, visible, alias, argsFn, args, ProviderDecorator, } from './provider/IProvider';
|
|
10
|
+
export { provider, visible, alias, argsFn, args, lazy, ProviderDecorator, } from './provider/IProvider';
|
|
11
11
|
export { Provider } from './provider/Provider';
|
|
12
12
|
export { singleton, SingletonProvider } from './provider/singleton/SingletonProvider';
|
|
13
13
|
export { MultiCache, multiCache } from './provider/singleton/MultiCache';
|
|
14
|
-
export {
|
|
14
|
+
export { makeProviderLazy } from './provider/LazyProvider';
|
|
15
15
|
export { decorate } from './provider/DecoratorProvider';
|
|
16
16
|
// Registrations
|
|
17
17
|
export { key, scope, register } from './registration/IRegistration';
|
|
@@ -4,7 +4,7 @@ const METADATA_KEY = 'inject';
|
|
|
4
4
|
const getInjectFns = (Target) => getParameterMetadata(METADATA_KEY, Target);
|
|
5
5
|
export const inject = (fn) => setParameterMetadata(METADATA_KEY, fn);
|
|
6
6
|
export class MetadataInjector {
|
|
7
|
-
resolve(container, Target,
|
|
7
|
+
resolve(container, Target, { args: deps }) {
|
|
8
8
|
const injectionFns = getInjectFns(Target);
|
|
9
9
|
const args = fillEmptyIndexes(injectionFns, deps.map(constant)).map((fn) => fn(container));
|
|
10
10
|
return new Target(...args);
|
|
@@ -5,7 +5,7 @@ function getProp(target, key) {
|
|
|
5
5
|
}
|
|
6
6
|
export class ProxyInjector {
|
|
7
7
|
// eslint-disable-next-line @typescript-eslint/ban-types
|
|
8
|
-
resolve(container, Target,
|
|
8
|
+
resolve(container, Target, { args: deps }) {
|
|
9
9
|
const args = deps.reduce((acc, it) => ({ ...acc, ...it }), {});
|
|
10
10
|
const proxy = new Proxy({}, {
|
|
11
11
|
// eslint-disable-next-line @typescript-eslint/ban-types
|
|
@@ -5,8 +5,8 @@ export class DecoratorProvider extends ProviderDecorator {
|
|
|
5
5
|
this.provider = provider;
|
|
6
6
|
this.decorateFn = decorateFn;
|
|
7
7
|
}
|
|
8
|
-
resolve(scope,
|
|
9
|
-
const dependency = this.provider.resolve(scope,
|
|
8
|
+
resolve(scope, options) {
|
|
9
|
+
const dependency = this.provider.resolve(scope, options);
|
|
10
10
|
return this.decorateFn(dependency, scope);
|
|
11
11
|
}
|
|
12
12
|
}
|
|
@@ -6,6 +6,7 @@ export function args(...extraArgs) {
|
|
|
6
6
|
export function argsFn(fn) {
|
|
7
7
|
return (provider) => provider.setArgs(fn);
|
|
8
8
|
}
|
|
9
|
+
export const lazy = (provider) => provider.setLazy(true);
|
|
9
10
|
const METADATA_KEY = 'provider';
|
|
10
11
|
export const provider = (...mappers) => setMetadata(METADATA_KEY, mappers);
|
|
11
12
|
export const getTransformers = (Target) => getMetadata(Target, METADATA_KEY) ?? [];
|
|
@@ -22,8 +23,8 @@ export class ProviderDecorator {
|
|
|
22
23
|
isVisible(parent, child) {
|
|
23
24
|
return this.decorated.isVisible(parent, child);
|
|
24
25
|
}
|
|
25
|
-
resolve(container,
|
|
26
|
-
return this.decorated.resolve(container,
|
|
26
|
+
resolve(container, options) {
|
|
27
|
+
return this.decorated.resolve(container, options);
|
|
27
28
|
}
|
|
28
29
|
pipe(...mappers) {
|
|
29
30
|
return pipe(...mappers)(this);
|
|
@@ -39,4 +40,8 @@ export class ProviderDecorator {
|
|
|
39
40
|
this.decorated.setArgs(argsFn);
|
|
40
41
|
return this;
|
|
41
42
|
}
|
|
43
|
+
setLazy(lazy) {
|
|
44
|
+
this.decorated.setLazy(lazy);
|
|
45
|
+
return this;
|
|
46
|
+
}
|
|
42
47
|
}
|
|
@@ -1,18 +1,12 @@
|
|
|
1
1
|
import { ProviderDecorator } from './IProvider';
|
|
2
|
+
import { lazyInstance } from '../utils';
|
|
2
3
|
export class LazyProvider extends ProviderDecorator {
|
|
3
4
|
constructor(provider) {
|
|
4
5
|
super(provider);
|
|
5
6
|
this.provider = provider;
|
|
6
7
|
}
|
|
7
|
-
resolve(container,
|
|
8
|
-
|
|
9
|
-
return new Proxy({}, {
|
|
10
|
-
get: (_, prop) => {
|
|
11
|
-
instance = instance ?? this.provider.resolve(container, ...args);
|
|
12
|
-
// @ts-ignore
|
|
13
|
-
return instance[prop];
|
|
14
|
-
},
|
|
15
|
-
});
|
|
8
|
+
resolve(container, options) {
|
|
9
|
+
return lazyInstance(() => this.provider.resolve(container, options));
|
|
16
10
|
}
|
|
17
11
|
}
|
|
18
|
-
export const
|
|
12
|
+
export const makeProviderLazy = (provider) => new LazyProvider(provider);
|
package/esm/provider/Provider.js
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
import { getTransformers } from './IProvider';
|
|
1
|
+
import { getTransformers, } from './IProvider';
|
|
2
2
|
import { isConstructor, pipe } from '../utils';
|
|
3
3
|
export class Provider {
|
|
4
4
|
static fromClass(Target) {
|
|
5
5
|
const transformers = getTransformers(Target);
|
|
6
|
-
return new Provider((container,
|
|
6
|
+
return new Provider((container, options) => container.resolve(Target, options)).pipe(...transformers);
|
|
7
7
|
}
|
|
8
8
|
static fromValue(value) {
|
|
9
9
|
const mappers = isConstructor(value) ? getTransformers(value) ?? [] : [];
|
|
@@ -13,18 +13,26 @@ export class Provider {
|
|
|
13
13
|
this.resolveDependency = resolveDependency;
|
|
14
14
|
this.aliases = new Set();
|
|
15
15
|
this.argsFn = () => [];
|
|
16
|
+
this.isLazy = false;
|
|
16
17
|
this.isVisibleWhen = () => true;
|
|
17
18
|
}
|
|
18
19
|
pipe(...mappers) {
|
|
19
20
|
return pipe(...mappers)(this);
|
|
20
21
|
}
|
|
21
|
-
resolve(container,
|
|
22
|
-
return this.resolveDependency(container,
|
|
22
|
+
resolve(container, { args, lazy }) {
|
|
23
|
+
return this.resolveDependency(container, {
|
|
24
|
+
args: [...this.argsFn(container, ...args), ...args],
|
|
25
|
+
lazy: lazy ?? this.isLazy ?? false,
|
|
26
|
+
});
|
|
23
27
|
}
|
|
24
28
|
setVisibility(predicate) {
|
|
25
29
|
this.isVisibleWhen = predicate;
|
|
26
30
|
return this;
|
|
27
31
|
}
|
|
32
|
+
setLazy(lazy) {
|
|
33
|
+
this.isLazy = lazy;
|
|
34
|
+
return this;
|
|
35
|
+
}
|
|
28
36
|
setArgs(argsFn) {
|
|
29
37
|
this.argsFn = argsFn;
|
|
30
38
|
return this;
|
|
@@ -9,10 +9,10 @@ export class SingletonProvider extends ProviderDecorator {
|
|
|
9
9
|
this.provider = provider;
|
|
10
10
|
this.cache = cache;
|
|
11
11
|
}
|
|
12
|
-
resolve(container,
|
|
13
|
-
const key = this.cache.getKey(...args);
|
|
12
|
+
resolve(container, options) {
|
|
13
|
+
const key = this.cache.getKey(...options.args);
|
|
14
14
|
if (!this.cache.hasValue(key)) {
|
|
15
|
-
this.cache.setValue(key, this.provider.resolve(container,
|
|
15
|
+
this.cache.setValue(key, this.provider.resolve(container, options));
|
|
16
16
|
}
|
|
17
17
|
return this.cache.getValue(key);
|
|
18
18
|
}
|
package/esm/utils.js
CHANGED
|
@@ -11,3 +11,13 @@ export function fillEmptyIndexes(baseArr, insertArr) {
|
|
|
11
11
|
}
|
|
12
12
|
export const constant = (value) => () => value;
|
|
13
13
|
export const isConstructor = (T) => typeof T === 'function' && !!T.prototype;
|
|
14
|
+
export function lazyInstance(resolveInstance) {
|
|
15
|
+
let instance;
|
|
16
|
+
return new Proxy({}, {
|
|
17
|
+
get: (_, prop) => {
|
|
18
|
+
instance = instance ?? resolveInstance();
|
|
19
|
+
// @ts-ignore
|
|
20
|
+
return instance[prop];
|
|
21
|
+
},
|
|
22
|
+
});
|
|
23
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "ts-ioc-container",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "32.0.0",
|
|
4
4
|
"description": "Typescript IoC container",
|
|
5
5
|
"publishConfig": {
|
|
6
6
|
"access": "public",
|
|
@@ -59,5 +59,5 @@
|
|
|
59
59
|
"ts-node": "^10.9.1",
|
|
60
60
|
"typescript": "5.4.3"
|
|
61
61
|
},
|
|
62
|
-
"gitHead": "
|
|
62
|
+
"gitHead": "4bdbd1e91d3f7ea7b1b671bc2140d193748ce2a1"
|
|
63
63
|
}
|
package/typings/by.d.ts
CHANGED
|
@@ -1,30 +1,39 @@
|
|
|
1
1
|
import { DependencyKey, IContainer, InjectionToken } from './container/IContainer';
|
|
2
|
+
import { ProviderResolveOptions } from './provider/IProvider';
|
|
2
3
|
export type InstancePredicate = (dep: unknown) => boolean;
|
|
3
4
|
export declare const all: InstancePredicate;
|
|
4
5
|
export type IMemo = Map<string, DependencyKey[]>;
|
|
5
6
|
export declare const IMemoKey: unique symbol;
|
|
6
7
|
export declare const by: {
|
|
7
|
-
aliases: (predicate: (it: Set<string>, s: IContainer) => boolean, memoize
|
|
8
|
+
aliases: (predicate: (it: Set<string>, s: IContainer) => boolean, { memoize, lazy }?: {
|
|
9
|
+
memoize?: ((c: IContainer) => string) | undefined;
|
|
10
|
+
lazy?: boolean | undefined;
|
|
11
|
+
}) => (c: IContainer, ...args: unknown[]) => unknown[];
|
|
8
12
|
/**
|
|
9
13
|
* Get the instance that matches the given alias or fail
|
|
10
14
|
* @param predicate
|
|
11
15
|
* @param memoize
|
|
12
16
|
*/
|
|
13
|
-
alias: (predicate: (it: Set<string>, s: IContainer) => boolean, memoize
|
|
17
|
+
alias: (predicate: (it: Set<string>, s: IContainer) => boolean, { memoize, lazy }?: {
|
|
18
|
+
memoize?: ((c: IContainer) => string) | undefined;
|
|
19
|
+
lazy?: boolean | undefined;
|
|
20
|
+
}) => (c: IContainer, ...args: unknown[]) => unknown;
|
|
14
21
|
/**
|
|
15
22
|
* Get all instances that match the given keys
|
|
16
23
|
* @param keys
|
|
24
|
+
* @param lazy
|
|
17
25
|
*/
|
|
18
|
-
keys: (
|
|
26
|
+
keys: (keys: InjectionToken[], { lazy }?: Pick<ProviderResolveOptions, 'lazy'>) => (с: IContainer, ...args: unknown[]) => unknown[];
|
|
19
27
|
/**
|
|
20
28
|
* Get the instance that matches the given key
|
|
21
29
|
* @param key
|
|
22
30
|
* @param deps
|
|
31
|
+
* @param lazy
|
|
23
32
|
*/
|
|
24
|
-
key: <T>(key: InjectionToken<T>,
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
};
|
|
33
|
+
key: <T>(key: InjectionToken<T>, { args: deps, lazy }?: {
|
|
34
|
+
args?: unknown[] | undefined;
|
|
35
|
+
lazy?: boolean | undefined;
|
|
36
|
+
}) => (c: IContainer, ...args: unknown[]) => T;
|
|
28
37
|
/**
|
|
29
38
|
* Get all instances that match the given predicate
|
|
30
39
|
* @param predicate
|
|
@@ -17,15 +17,16 @@ export declare class Container implements IContainer {
|
|
|
17
17
|
});
|
|
18
18
|
add(registration: IRegistration): this;
|
|
19
19
|
register(key: DependencyKey, provider: IProvider): this;
|
|
20
|
-
resolve<T>(token: InjectionToken<T>, { args, child }?: ResolveOptions): T;
|
|
20
|
+
resolve<T>(token: InjectionToken<T>, { args, child, lazy }?: ResolveOptions): T;
|
|
21
|
+
private resolveByInjector;
|
|
21
22
|
createScope(...tags: Tag[]): Container;
|
|
22
23
|
dispose(): void;
|
|
23
24
|
getInstances(): unknown[];
|
|
24
25
|
hasTag(tag: Tag): boolean;
|
|
25
26
|
use(module: IContainerModule): this;
|
|
26
27
|
hasDependency(key: DependencyKey): boolean;
|
|
27
|
-
resolveManyByAlias(predicate: AliasPredicate, { args, child }?: ResolveOptions, result?: Map<DependencyKey, unknown>): Map<DependencyKey, unknown>;
|
|
28
|
-
resolveOneByAlias<T>(predicate: AliasPredicate, { args, child }?: ResolveOptions): [DependencyKey, T];
|
|
28
|
+
resolveManyByAlias(predicate: AliasPredicate, { args, child, lazy }?: ResolveOptions, result?: Map<DependencyKey, unknown>): Map<DependencyKey, unknown>;
|
|
29
|
+
resolveOneByAlias<T>(predicate: AliasPredicate, { args, child, lazy }?: ResolveOptions): [DependencyKey, T];
|
|
29
30
|
/**
|
|
30
31
|
* @private
|
|
31
32
|
*/
|
|
@@ -9,6 +9,7 @@ export type InjectionToken<T = unknown> = constructor<T> | DependencyKey;
|
|
|
9
9
|
export type ResolveOptions = {
|
|
10
10
|
args?: unknown[];
|
|
11
11
|
child?: Tagged;
|
|
12
|
+
lazy?: boolean;
|
|
12
13
|
};
|
|
13
14
|
export interface Resolvable {
|
|
14
15
|
resolve<T>(key: InjectionToken<T>, options?: ResolveOptions): T;
|
package/typings/index.d.ts
CHANGED
|
@@ -6,12 +6,12 @@ export { IInjector } from './injector/IInjector';
|
|
|
6
6
|
export { MetadataInjector, inject } from './injector/MetadataInjector';
|
|
7
7
|
export { SimpleInjector } from './injector/SimpleInjector';
|
|
8
8
|
export { ProxyInjector } from './injector/ProxyInjector';
|
|
9
|
-
export { ResolveDependency, IProvider, provider, visible, alias, argsFn, args, ArgsFn, ProviderDecorator, } from './provider/IProvider';
|
|
9
|
+
export { ResolveDependency, IProvider, provider, visible, alias, argsFn, args, ArgsFn, lazy, ProviderDecorator, } from './provider/IProvider';
|
|
10
10
|
export { Provider } from './provider/Provider';
|
|
11
11
|
export { singleton, SingletonProvider } from './provider/singleton/SingletonProvider';
|
|
12
12
|
export { MultiCache, multiCache } from './provider/singleton/MultiCache';
|
|
13
13
|
export { Cache } from './provider/singleton/Cache';
|
|
14
|
-
export {
|
|
14
|
+
export { makeProviderLazy } from './provider/LazyProvider';
|
|
15
15
|
export { decorate, DecorateFn } from './provider/DecoratorProvider';
|
|
16
16
|
export { key, IRegistration, scope, register } from './registration/IRegistration';
|
|
17
17
|
export { Registration } from './registration/Registration';
|
|
@@ -1,5 +1,8 @@
|
|
|
1
1
|
import { constructor } from '../utils';
|
|
2
2
|
import { IContainer } from '../container/IContainer';
|
|
3
|
+
export type InjectOptions = {
|
|
4
|
+
args: unknown[];
|
|
5
|
+
};
|
|
3
6
|
export interface IInjector {
|
|
4
|
-
resolve<T>(container: IContainer, value: constructor<T>,
|
|
7
|
+
resolve<T>(container: IContainer, value: constructor<T>, options: InjectOptions): T;
|
|
5
8
|
}
|
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
import { IInjector } from './IInjector';
|
|
1
|
+
import { IInjector, InjectOptions } from './IInjector';
|
|
2
2
|
import { IContainer } from '../container/IContainer';
|
|
3
3
|
import { constructor } from '../utils';
|
|
4
4
|
type InjectFn<T = unknown> = (l: IContainer, ...args: unknown[]) => T;
|
|
5
5
|
export declare const inject: (fn: InjectFn) => ParameterDecorator;
|
|
6
6
|
export declare class MetadataInjector implements IInjector {
|
|
7
|
-
resolve<T>(container: IContainer, Target: constructor<T>,
|
|
7
|
+
resolve<T>(container: IContainer, Target: constructor<T>, { args: deps }: InjectOptions): T;
|
|
8
8
|
}
|
|
9
9
|
export {};
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { IInjector } from './IInjector';
|
|
1
|
+
import { IInjector, InjectOptions } from './IInjector';
|
|
2
2
|
import { IContainer } from '../container/IContainer';
|
|
3
3
|
import { constructor } from '../utils';
|
|
4
4
|
export declare class ProxyInjector implements IInjector {
|
|
5
|
-
resolve<T>(container: IContainer, Target: constructor<T>,
|
|
5
|
+
resolve<T>(container: IContainer, Target: constructor<T>, { args: deps }: InjectOptions): T;
|
|
6
6
|
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { IInjector } from './IInjector';
|
|
1
|
+
import { IInjector, InjectOptions } from './IInjector';
|
|
2
2
|
import { IContainer } from '../container/IContainer';
|
|
3
3
|
import { constructor } from '../utils';
|
|
4
4
|
export declare class SimpleInjector implements IInjector {
|
|
5
|
-
resolve<T>(container: IContainer, Target: constructor<T>,
|
|
5
|
+
resolve<T>(container: IContainer, Target: constructor<T>, { args: deps }: InjectOptions): T;
|
|
6
6
|
}
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
import { IContainer } from '../container/IContainer';
|
|
2
|
-
import { IProvider, ProviderDecorator } from './IProvider';
|
|
2
|
+
import { IProvider, ProviderDecorator, ProviderResolveOptions } from './IProvider';
|
|
3
3
|
export type DecorateFn<Instance> = (dep: Instance, scope: IContainer) => Instance;
|
|
4
4
|
export declare class DecoratorProvider<Instance> extends ProviderDecorator<Instance> {
|
|
5
5
|
private provider;
|
|
6
6
|
private decorateFn;
|
|
7
7
|
constructor(provider: IProvider<Instance>, decorateFn: DecorateFn<Instance>);
|
|
8
|
-
resolve(scope: IContainer,
|
|
8
|
+
resolve(scope: IContainer, options: ProviderResolveOptions): Instance;
|
|
9
9
|
}
|
|
10
10
|
export declare const decorate: <Instance>(decorateFn: DecorateFn<Instance>) => (provider: IProvider<Instance>) => DecoratorProvider<Instance>;
|
|
@@ -1,6 +1,10 @@
|
|
|
1
1
|
import { Alias, AliasPredicate, IContainer, Tagged } from '../container/IContainer';
|
|
2
2
|
import { constructor, MapFn } from '../utils';
|
|
3
|
-
export type
|
|
3
|
+
export type ProviderResolveOptions = {
|
|
4
|
+
args: unknown[];
|
|
5
|
+
lazy?: boolean;
|
|
6
|
+
};
|
|
7
|
+
export type ResolveDependency<T = unknown> = (container: IContainer, options: ProviderResolveOptions) => T;
|
|
4
8
|
export type ChildrenVisibilityPredicate = (options: {
|
|
5
9
|
child: Tagged;
|
|
6
10
|
isParent: boolean;
|
|
@@ -8,14 +12,16 @@ export type ChildrenVisibilityPredicate = (options: {
|
|
|
8
12
|
export type ArgsFn = (l: IContainer, ...args: unknown[]) => unknown[];
|
|
9
13
|
export declare function args<T = unknown>(...extraArgs: unknown[]): MapFn<IProvider<T>>;
|
|
10
14
|
export declare function argsFn<T = unknown>(fn: ArgsFn): MapFn<IProvider<T>>;
|
|
15
|
+
export declare const lazy: <T>(provider: IProvider<T>) => IProvider<T>;
|
|
11
16
|
export interface IProvider<T = unknown> {
|
|
12
|
-
resolve(container: IContainer,
|
|
17
|
+
resolve(container: IContainer, options: ProviderResolveOptions): T;
|
|
13
18
|
isVisible(parent: Tagged, child: Tagged): boolean;
|
|
14
19
|
pipe(...mappers: MapFn<IProvider<T>>[]): IProvider<T>;
|
|
15
20
|
setVisibility(isVisibleWhen: ChildrenVisibilityPredicate): this;
|
|
16
21
|
setArgs(argsFn: ArgsFn): this;
|
|
17
22
|
matchAliases(predicate: AliasPredicate): boolean;
|
|
18
23
|
addAliases(...aliases: Alias[]): this;
|
|
24
|
+
setLazy(lazy: boolean): this;
|
|
19
25
|
}
|
|
20
26
|
export declare const provider: (...mappers: MapFn<IProvider>[]) => ClassDecorator;
|
|
21
27
|
export declare const getTransformers: <T>(Target: constructor<T>) => MapFn<IProvider<T>>[];
|
|
@@ -26,9 +32,10 @@ export declare abstract class ProviderDecorator<T> implements IProvider<T> {
|
|
|
26
32
|
protected constructor(decorated: IProvider<T>);
|
|
27
33
|
setVisibility(predicate: ChildrenVisibilityPredicate): this;
|
|
28
34
|
isVisible(parent: IContainer, child: Tagged): boolean;
|
|
29
|
-
resolve(container: IContainer,
|
|
35
|
+
resolve(container: IContainer, options: ProviderResolveOptions): T;
|
|
30
36
|
pipe(...mappers: MapFn<IProvider<T>>[]): IProvider<T>;
|
|
31
37
|
matchAliases(predicate: AliasPredicate): boolean;
|
|
32
38
|
addAliases(...aliases: Alias[]): this;
|
|
33
39
|
setArgs(argsFn: ArgsFn): this;
|
|
40
|
+
setLazy(lazy: boolean): this;
|
|
34
41
|
}
|
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import { IProvider, ProviderDecorator } from './IProvider';
|
|
1
|
+
import { IProvider, ProviderDecorator, ProviderResolveOptions } from './IProvider';
|
|
2
2
|
import { IContainer } from '../container/IContainer';
|
|
3
3
|
export declare class LazyProvider<Instance> extends ProviderDecorator<Instance> {
|
|
4
4
|
private provider;
|
|
5
5
|
constructor(provider: IProvider<Instance>);
|
|
6
|
-
resolve(container: IContainer,
|
|
6
|
+
resolve(container: IContainer, options: ProviderResolveOptions): Instance;
|
|
7
7
|
}
|
|
8
|
-
export declare const
|
|
8
|
+
export declare const makeProviderLazy: <Instance>(provider: IProvider<Instance>) => LazyProvider<Instance>;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { ArgsFn, ChildrenVisibilityPredicate, IProvider, ResolveDependency } from './IProvider';
|
|
1
|
+
import { ArgsFn, ChildrenVisibilityPredicate, IProvider, ProviderResolveOptions, ResolveDependency } from './IProvider';
|
|
2
2
|
import { Alias, AliasPredicate, IContainer, Tagged } from '../container/IContainer';
|
|
3
3
|
import { constructor, MapFn } from '../utils';
|
|
4
4
|
export declare class Provider<T> implements IProvider<T> {
|
|
@@ -7,11 +7,13 @@ export declare class Provider<T> implements IProvider<T> {
|
|
|
7
7
|
static fromValue<T>(value: T): IProvider<T>;
|
|
8
8
|
private readonly aliases;
|
|
9
9
|
private argsFn;
|
|
10
|
+
private isLazy;
|
|
10
11
|
private isVisibleWhen;
|
|
11
12
|
constructor(resolveDependency: ResolveDependency<T>);
|
|
12
13
|
pipe(...mappers: MapFn<IProvider<T>>[]): IProvider<T>;
|
|
13
|
-
resolve(container: IContainer,
|
|
14
|
+
resolve(container: IContainer, { args, lazy }: ProviderResolveOptions): T;
|
|
14
15
|
setVisibility(predicate: ChildrenVisibilityPredicate): this;
|
|
16
|
+
setLazy(lazy: boolean): this;
|
|
15
17
|
setArgs(argsFn: ArgsFn): this;
|
|
16
18
|
isVisible(parent: Tagged, child: Tagged): boolean;
|
|
17
19
|
matchAliases(predicate: AliasPredicate): boolean;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { IContainer } from '../../container/IContainer';
|
|
2
|
-
import { IProvider, ProviderDecorator } from '../IProvider';
|
|
2
|
+
import { IProvider, ProviderDecorator, ProviderResolveOptions } from '../IProvider';
|
|
3
3
|
import { MapFn } from '../../utils';
|
|
4
4
|
import { Cache } from './Cache';
|
|
5
5
|
export declare function singleton<T = unknown>(cacheProvider?: () => Cache<unknown, T>): MapFn<IProvider<T>>;
|
|
@@ -7,5 +7,5 @@ export declare class SingletonProvider<T> extends ProviderDecorator<T> {
|
|
|
7
7
|
private readonly provider;
|
|
8
8
|
private readonly cache;
|
|
9
9
|
constructor(provider: IProvider<T>, cache: Cache<unknown, T>);
|
|
10
|
-
resolve(container: IContainer,
|
|
10
|
+
resolve(container: IContainer, options: ProviderResolveOptions): T;
|
|
11
11
|
}
|
package/typings/utils.d.ts
CHANGED
|
@@ -4,3 +4,4 @@ export declare const pipe: <T>(...mappers: MapFn<T>[]) => MapFn<T>;
|
|
|
4
4
|
export declare function fillEmptyIndexes<T>(baseArr: (T | undefined)[], insertArr: T[]): T[];
|
|
5
5
|
export declare const constant: <T>(value: T) => () => T;
|
|
6
6
|
export declare const isConstructor: (T: unknown) => T is constructor<unknown>;
|
|
7
|
+
export declare function lazyInstance<T>(resolveInstance: () => T): T;
|