nano-injector 1.0.3 → 1.0.5
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/LICENSE +21 -21
- package/README.md +240 -221
- package/lib/Binder.js +83 -86
- package/lib/Injector.js +158 -159
- package/lib/InjectorsStack.js +33 -33
- package/lib/Provider.js +60 -59
- package/lib/index.js +18 -14
- package/package.json +52 -57
- package/typings/Binder.d.ts +44 -47
- package/typings/Injector.d.ts +93 -96
- package/typings/InjectorsStack.d.ts +16 -16
- package/typings/Provider.d.ts +48 -50
- package/typings/index.d.ts +2 -2
package/lib/Binder.js
CHANGED
|
@@ -1,86 +1,83 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.Binder = exports.NoCreationMethodSpecifiedError = void 0;
|
|
4
|
-
class NoCreationMethodSpecifiedError extends Error {
|
|
5
|
-
constructor() {
|
|
6
|
-
super('No creation method specified');
|
|
7
|
-
}
|
|
8
|
-
}
|
|
9
|
-
exports.NoCreationMethodSpecifiedError = NoCreationMethodSpecifiedError;
|
|
10
|
-
/**
|
|
11
|
-
*
|
|
12
|
-
*/
|
|
13
|
-
class Binder {
|
|
14
|
-
constructor(injector) {
|
|
15
|
-
this.injector = injector;
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
*
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
this.
|
|
37
|
-
this.
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
*
|
|
43
|
-
* @param ctor
|
|
44
|
-
*/
|
|
45
|
-
toConstructor(ctor) {
|
|
46
|
-
this.ctor = ctor;
|
|
47
|
-
this.factory = undefined;
|
|
48
|
-
this.value = undefined;
|
|
49
|
-
return this;
|
|
50
|
-
}
|
|
51
|
-
/**
|
|
52
|
-
*
|
|
53
|
-
*
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
this.
|
|
58
|
-
this.
|
|
59
|
-
this
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
*
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
return
|
|
79
|
-
}
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
}
|
|
85
|
-
}
|
|
86
|
-
exports.Binder = Binder;
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.Binder = exports.NoCreationMethodSpecifiedError = void 0;
|
|
4
|
+
class NoCreationMethodSpecifiedError extends Error {
|
|
5
|
+
constructor() {
|
|
6
|
+
super('No creation method specified');
|
|
7
|
+
}
|
|
8
|
+
}
|
|
9
|
+
exports.NoCreationMethodSpecifiedError = NoCreationMethodSpecifiedError;
|
|
10
|
+
/**
|
|
11
|
+
* A class that defines how to create a value for this binder.
|
|
12
|
+
*/
|
|
13
|
+
class Binder {
|
|
14
|
+
constructor(injector) {
|
|
15
|
+
this.injector = injector;
|
|
16
|
+
this.isSingleton = false;
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* Creates a new value (if needed) using the defined creation method, and returns it.
|
|
20
|
+
*/
|
|
21
|
+
getValue() {
|
|
22
|
+
if (this.value !== undefined) {
|
|
23
|
+
return this.value;
|
|
24
|
+
}
|
|
25
|
+
if (this.isSingleton) {
|
|
26
|
+
this.value = this.createValue();
|
|
27
|
+
return this.value;
|
|
28
|
+
}
|
|
29
|
+
return this.createValue();
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* Sets a specific value for this binder.
|
|
33
|
+
* @param value
|
|
34
|
+
*/
|
|
35
|
+
toValue(value) {
|
|
36
|
+
this.value = value;
|
|
37
|
+
this.factory = undefined;
|
|
38
|
+
this.ctor = undefined;
|
|
39
|
+
return this;
|
|
40
|
+
}
|
|
41
|
+
/**
|
|
42
|
+
* Use a class constructor to create the value. Previous creation methods are cleared.
|
|
43
|
+
* @param ctor
|
|
44
|
+
*/
|
|
45
|
+
toConstructor(ctor) {
|
|
46
|
+
this.ctor = ctor;
|
|
47
|
+
this.factory = undefined;
|
|
48
|
+
this.value = undefined;
|
|
49
|
+
return this;
|
|
50
|
+
}
|
|
51
|
+
/**
|
|
52
|
+
* Use a factory function to create the value. Previous creation methods are cleared.
|
|
53
|
+
* @param factory
|
|
54
|
+
*/
|
|
55
|
+
toFactory(factory) {
|
|
56
|
+
this.factory = factory;
|
|
57
|
+
this.ctor = undefined;
|
|
58
|
+
this.value = undefined;
|
|
59
|
+
return this;
|
|
60
|
+
}
|
|
61
|
+
/**
|
|
62
|
+
* Configures whether the value should be a singleton. If true, the value is created once and reused for all subsequent requests.
|
|
63
|
+
* @param value
|
|
64
|
+
*/
|
|
65
|
+
asSingleton(value = true) {
|
|
66
|
+
this.isSingleton = value;
|
|
67
|
+
return this;
|
|
68
|
+
}
|
|
69
|
+
/**
|
|
70
|
+
* Creates the value using the configured creation method.
|
|
71
|
+
* @private
|
|
72
|
+
*/
|
|
73
|
+
createValue() {
|
|
74
|
+
if (this.ctor != null) {
|
|
75
|
+
return new this.ctor();
|
|
76
|
+
}
|
|
77
|
+
if (this.factory != null) {
|
|
78
|
+
return this.factory(this.injector);
|
|
79
|
+
}
|
|
80
|
+
throw new NoCreationMethodSpecifiedError();
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
exports.Binder = Binder;
|
package/lib/Injector.js
CHANGED
|
@@ -1,159 +1,158 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.Injector = exports.$Injector = exports.NoBinderError = exports.CircularDependencyError = void 0;
|
|
4
|
-
const Binder_1 = require("./Binder");
|
|
5
|
-
const Provider_1 = require("./Provider");
|
|
6
|
-
const InjectorsStack_1 = require("./InjectorsStack");
|
|
7
|
-
/**
|
|
8
|
-
*
|
|
9
|
-
*/
|
|
10
|
-
class CircularDependencyError extends Error {
|
|
11
|
-
constructor(providers) {
|
|
12
|
-
const providerNames = providers.map(Provider_1.getProviderName)
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
* @param params.
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
this.
|
|
43
|
-
|
|
44
|
-
this.
|
|
45
|
-
this.
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
*
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
*
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
*
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
}
|
|
112
|
-
|
|
113
|
-
this.
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
exports.Injector = Injector;
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.Injector = exports.$Injector = exports.NoBinderError = exports.CircularDependencyError = void 0;
|
|
4
|
+
const Binder_1 = require("./Binder");
|
|
5
|
+
const Provider_1 = require("./Provider");
|
|
6
|
+
const InjectorsStack_1 = require("./InjectorsStack");
|
|
7
|
+
/**
|
|
8
|
+
* Error thrown when a circular dependency is detected.
|
|
9
|
+
*/
|
|
10
|
+
class CircularDependencyError extends Error {
|
|
11
|
+
constructor(providers) {
|
|
12
|
+
const providerNames = providers.map(Provider_1.getProviderName).map((name) => name !== null && name !== void 0 ? name : '?');
|
|
13
|
+
super(`Circular dependency detected: ${providerNames.join('->')}`);
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
exports.CircularDependencyError = CircularDependencyError;
|
|
17
|
+
class NoBinderError extends Error {
|
|
18
|
+
constructor(provider) {
|
|
19
|
+
var _a;
|
|
20
|
+
const providerName = (_a = (0, Provider_1.getProviderName)(provider)) !== null && _a !== void 0 ? _a : 'unknown';
|
|
21
|
+
super(`Value of ${providerName} provider is not found`);
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
exports.NoBinderError = NoBinderError;
|
|
25
|
+
/**
|
|
26
|
+
* The provider to which every injector binds itself.
|
|
27
|
+
*/
|
|
28
|
+
exports.$Injector = (0, Provider_1.createProvider)();
|
|
29
|
+
/**
|
|
30
|
+
* The central entity of the library. It holds provider bindings and resolves dependencies.
|
|
31
|
+
*/
|
|
32
|
+
class Injector {
|
|
33
|
+
/**
|
|
34
|
+
* @param params.name Name of the injector (useful for debugging).
|
|
35
|
+
* @param params.parent Parent injector for composing injectors.
|
|
36
|
+
* @param params.logger Custom logger function.
|
|
37
|
+
*/
|
|
38
|
+
constructor(params = {}) {
|
|
39
|
+
this.binders = new Map();
|
|
40
|
+
this.resolvingProviders = [];
|
|
41
|
+
const { name, parent, logger = console.warn } = params;
|
|
42
|
+
this.name = name;
|
|
43
|
+
this.parent = parent;
|
|
44
|
+
this.logger = logger;
|
|
45
|
+
this.bindProvider(exports.$Injector).toValue(this);
|
|
46
|
+
}
|
|
47
|
+
/**
|
|
48
|
+
* Creates a new binder and links it to the specified providers.
|
|
49
|
+
* If a provider is already bound, the binding is overridden.
|
|
50
|
+
* @param providers The providers to bind.
|
|
51
|
+
*/
|
|
52
|
+
bindProvider(...providers) {
|
|
53
|
+
const binder = new Binder_1.Binder(this);
|
|
54
|
+
providers.forEach((provider) => this.binders.set(provider, binder));
|
|
55
|
+
return binder;
|
|
56
|
+
}
|
|
57
|
+
/**
|
|
58
|
+
* Resolves specific providers to their values and assigns them to the instance's properties.
|
|
59
|
+
* @param instance
|
|
60
|
+
* @param providers
|
|
61
|
+
*/
|
|
62
|
+
injectValues(instance, providers) {
|
|
63
|
+
Object.keys(providers).forEach((key) => {
|
|
64
|
+
const provider = providers[key];
|
|
65
|
+
if ((0, Provider_1.isProvider)(provider)) {
|
|
66
|
+
instance[key] = this.getValue(provider);
|
|
67
|
+
}
|
|
68
|
+
});
|
|
69
|
+
}
|
|
70
|
+
/**
|
|
71
|
+
* Activates the injector and creates a new instance of the given class using the provided arguments.
|
|
72
|
+
* @param type
|
|
73
|
+
* @param args
|
|
74
|
+
*/
|
|
75
|
+
createInstance(type, ...args) {
|
|
76
|
+
return this.activateAndCall(() => new type(...args));
|
|
77
|
+
}
|
|
78
|
+
/**
|
|
79
|
+
* Activates the injector and calls the given function with the provided arguments.
|
|
80
|
+
* @param func function which should be called
|
|
81
|
+
* @param args args which should be passed to the called function
|
|
82
|
+
*/
|
|
83
|
+
callFunc(func, ...args) {
|
|
84
|
+
return this.activateAndCall(() => func(...args));
|
|
85
|
+
}
|
|
86
|
+
/**
|
|
87
|
+
* Returns the value bound to the specified provider. Throws an exception if the value is not found.
|
|
88
|
+
* @param provider
|
|
89
|
+
*/
|
|
90
|
+
getValue(provider) {
|
|
91
|
+
const binder = this.getBinder(provider);
|
|
92
|
+
this.pushResolvingProvider(provider);
|
|
93
|
+
const value = this.activateAndCall(() => binder.getValue());
|
|
94
|
+
this.popResolvingProvder();
|
|
95
|
+
return value;
|
|
96
|
+
}
|
|
97
|
+
tryGetValue(provider, defValue) {
|
|
98
|
+
try {
|
|
99
|
+
return this.getValue(provider);
|
|
100
|
+
}
|
|
101
|
+
catch (err) {
|
|
102
|
+
if (err instanceof NoBinderError) {
|
|
103
|
+
return defValue;
|
|
104
|
+
}
|
|
105
|
+
throw err;
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
pushResolvingProvider(provider) {
|
|
109
|
+
this.checkCircularDependency(provider);
|
|
110
|
+
this.resolvingProviders.push(provider);
|
|
111
|
+
}
|
|
112
|
+
popResolvingProvder() {
|
|
113
|
+
this.resolvingProviders.pop();
|
|
114
|
+
}
|
|
115
|
+
getBinder(provider) {
|
|
116
|
+
const binder = this.tryGetBinderRecursively(provider);
|
|
117
|
+
if (binder == null) {
|
|
118
|
+
throw new NoBinderError(provider);
|
|
119
|
+
}
|
|
120
|
+
return binder;
|
|
121
|
+
}
|
|
122
|
+
/**
|
|
123
|
+
* Recursively looks up the binder for the specified provider, traversing up to the root injector.
|
|
124
|
+
* @param provider
|
|
125
|
+
* @private
|
|
126
|
+
*/
|
|
127
|
+
tryGetBinderRecursively(provider) {
|
|
128
|
+
var _a, _b;
|
|
129
|
+
return ((_a = this.binders.get(provider)) !== null && _a !== void 0 ? _a : (_b = this.parent) === null || _b === void 0 ? void 0 : _b.tryGetBinderRecursively(provider));
|
|
130
|
+
}
|
|
131
|
+
/**
|
|
132
|
+
* Checks for circular dependencies and throws an error if one is detected.
|
|
133
|
+
* @param provider
|
|
134
|
+
* @private
|
|
135
|
+
*/
|
|
136
|
+
checkCircularDependency(provider) {
|
|
137
|
+
const i = this.resolvingProviders.indexOf(provider);
|
|
138
|
+
if (i !== -1) {
|
|
139
|
+
const providers = [...this.resolvingProviders.slice(i), provider];
|
|
140
|
+
throw new CircularDependencyError(providers);
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
/**
|
|
144
|
+
* Temporarily activates this injector to execute the provided function and return its result.
|
|
145
|
+
* @param func
|
|
146
|
+
* @private
|
|
147
|
+
*/
|
|
148
|
+
activateAndCall(func) {
|
|
149
|
+
InjectorsStack_1.InjectorsStack.push(this);
|
|
150
|
+
try {
|
|
151
|
+
return func();
|
|
152
|
+
}
|
|
153
|
+
finally {
|
|
154
|
+
InjectorsStack_1.InjectorsStack.pop();
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
exports.Injector = Injector;
|
package/lib/InjectorsStack.js
CHANGED
|
@@ -1,33 +1,33 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.InjectorsStack = exports.NoActiveInjectorError = void 0;
|
|
4
|
-
class NoActiveInjectorError extends Error {
|
|
5
|
-
constructor() {
|
|
6
|
-
super('No active injector found');
|
|
7
|
-
}
|
|
8
|
-
}
|
|
9
|
-
exports.NoActiveInjectorError = NoActiveInjectorError;
|
|
10
|
-
/**
|
|
11
|
-
* Private class
|
|
12
|
-
*/
|
|
13
|
-
class _InjectorsStack {
|
|
14
|
-
constructor() {
|
|
15
|
-
this.injectors = [];
|
|
16
|
-
}
|
|
17
|
-
get activeInjector() {
|
|
18
|
-
if (this._activeInjector == null) {
|
|
19
|
-
throw new NoActiveInjectorError();
|
|
20
|
-
}
|
|
21
|
-
return this._activeInjector;
|
|
22
|
-
}
|
|
23
|
-
push(injector) {
|
|
24
|
-
if (this._activeInjector != null) {
|
|
25
|
-
this.injectors.push(this._activeInjector);
|
|
26
|
-
}
|
|
27
|
-
this._activeInjector = injector;
|
|
28
|
-
}
|
|
29
|
-
pop() {
|
|
30
|
-
this._activeInjector = this.injectors.pop();
|
|
31
|
-
}
|
|
32
|
-
}
|
|
33
|
-
exports.InjectorsStack = new _InjectorsStack();
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.InjectorsStack = exports.NoActiveInjectorError = void 0;
|
|
4
|
+
class NoActiveInjectorError extends Error {
|
|
5
|
+
constructor() {
|
|
6
|
+
super('No active injector found');
|
|
7
|
+
}
|
|
8
|
+
}
|
|
9
|
+
exports.NoActiveInjectorError = NoActiveInjectorError;
|
|
10
|
+
/**
|
|
11
|
+
* Private class to manage the stack of active injectors.
|
|
12
|
+
*/
|
|
13
|
+
class _InjectorsStack {
|
|
14
|
+
constructor() {
|
|
15
|
+
this.injectors = [];
|
|
16
|
+
}
|
|
17
|
+
get activeInjector() {
|
|
18
|
+
if (this._activeInjector == null) {
|
|
19
|
+
throw new NoActiveInjectorError();
|
|
20
|
+
}
|
|
21
|
+
return this._activeInjector;
|
|
22
|
+
}
|
|
23
|
+
push(injector) {
|
|
24
|
+
if (this._activeInjector != null) {
|
|
25
|
+
this.injectors.push(this._activeInjector);
|
|
26
|
+
}
|
|
27
|
+
this._activeInjector = injector;
|
|
28
|
+
}
|
|
29
|
+
pop() {
|
|
30
|
+
this._activeInjector = this.injectors.pop();
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
exports.InjectorsStack = new _InjectorsStack();
|