nano-injector 1.0.4 → 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/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
- * Class through which is defined how to create value for this binder
12
- */
13
- class Binder {
14
- constructor(injector) {
15
- this.injector = injector;
16
- }
17
- /**
18
- * Creates the new value if needed through previously defined method, and returns it
19
- */
20
- getValue() {
21
- if (this.value !== undefined) {
22
- return this.value;
23
- }
24
- if (this.isSingleton) {
25
- this.value = this.createValue();
26
- return this.value;
27
- }
28
- return this.createValue();
29
- }
30
- /**
31
- * Directly defines value for this binder
32
- * @param value
33
- */
34
- toValue(value) {
35
- this.value = value;
36
- this.factory = undefined;
37
- this.ctor = undefined;
38
- return this;
39
- }
40
- /**
41
- * Defines constructor as a method for creating value. All previously defined methods
42
- * will be ignored
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
- * Defines factory as a method for creating value. All previously defined methods
53
- * will be ignored
54
- * @param factory
55
- */
56
- toFactory(factory) {
57
- this.factory = factory;
58
- this.ctor = undefined;
59
- this.value = undefined;
60
- return this;
61
- }
62
- /**
63
- * Defines whether value should be a singleton. If yes the value will be created only once
64
- * and the same instance will be returned forever
65
- * @param value
66
- */
67
- asSingleton(value = true) {
68
- this.isSingleton = value;
69
- return this;
70
- }
71
- /**
72
- * Creates value through previously defined method
73
- * @private
74
- */
75
- createValue() {
76
- if (this.ctor != null) {
77
- // eslint-disable-next-line new-cap
78
- return new this.ctor();
79
- }
80
- if (this.factory != null) {
81
- return this.factory(this.injector);
82
- }
83
- throw new NoCreationMethodSpecifiedError();
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
- * Thrown when circular dependency is detected
9
- */
10
- class CircularDependencyError extends Error {
11
- constructor(providers) {
12
- const providerNames = providers.map(Provider_1.getProviderName)
13
- .map((name) => name !== null && name !== void 0 ? name : '?');
14
- super(`Circular dependency detected: ${providerNames.join('->')}`);
15
- }
16
- }
17
- exports.CircularDependencyError = CircularDependencyError;
18
- class NoBinderError extends Error {
19
- constructor(provider) {
20
- var _a;
21
- const providerName = (_a = (0, Provider_1.getProviderName)(provider)) !== null && _a !== void 0 ? _a : 'unknown';
22
- super(`Value of ${providerName} provider is not found`);
23
- }
24
- }
25
- exports.NoBinderError = NoBinderError;
26
- /**
27
- * Provider which every injector binds itself to
28
- */
29
- exports.$Injector = (0, Provider_1.createProvider)();
30
- /**
31
- * Main entity in the library, which holds provider's bindings and through which
32
- * dependencies are resolved
33
- */
34
- class Injector {
35
- /**
36
- * @param params.name name of the injector which can be useful mainly for debugging purposes
37
- * @param params.parent parent injector for the composition of injectors
38
- * @param params.logger specific log function if the custom output is required
39
- */
40
- constructor(params = {}) {
41
- this.binders = new Map();
42
- this.resolvingProviders = [];
43
- const { name, parent, logger = console.warn } = params;
44
- this.name = name;
45
- this.parent = parent;
46
- this.logger = logger;
47
- this.bindProvider(exports.$Injector).toValue(this);
48
- }
49
- /**
50
- * Creates new binder and joins it to the specified providers. If the provider
51
- * is already bound, then overriding occurs
52
- * @param providers providers which the binder should be joined to
53
- */
54
- bindProvider(...providers) {
55
- const binder = new Binder_1.Binder(this);
56
- providers.forEach((provider) => this.binders.set(provider, binder));
57
- return binder;
58
- }
59
- /**
60
- * Resolves all providers to their values and assigns them to the specified instance
61
- * @param instance
62
- * @param providers
63
- */
64
- injectValues(instance, providers) {
65
- Object.entries(providers)
66
- .filter(([, value]) => (0, Provider_1.isProvider)(value))
67
- .forEach(([name, provider]) => {
68
- // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
69
- instance[name] = this.getValue(provider);
70
- });
71
- }
72
- /**
73
- * Activates this injector and creates new instance of the type with the provided arguments
74
- * @param type
75
- * @param args
76
- */
77
- createInstance(type, ...args) {
78
- // eslint-disable-next-line new-cap
79
- return this.activateAndCall(() => new type(...args));
80
- }
81
- /**
82
- * Activates this injector and calls the function with provided arguments
83
- * @param func function which should be called
84
- * @param args args which should be passed to the called function
85
- */
86
- callFunc(func, ...args) {
87
- return this.activateAndCall(() => func(...args));
88
- }
89
- /**
90
- * Returns bound to the specified provider value. If the value is not found
91
- * exception is thrown
92
- * @param provider
93
- */
94
- getValue(provider) {
95
- const binder = this.getBinder(provider);
96
- this.pushResolvingProvider(provider);
97
- const value = this.activateAndCall(() => binder.getValue());
98
- this.popResolvingProvder();
99
- return value;
100
- }
101
- tryGetValue(provider, defValue) {
102
- try {
103
- return this.getValue(provider);
104
- }
105
- catch (err) {
106
- if (err instanceof NoBinderError) {
107
- return defValue;
108
- }
109
- throw err;
110
- }
111
- }
112
- pushResolvingProvider(provider) {
113
- this.checkCircularDependency(provider);
114
- this.resolvingProviders.push(provider);
115
- }
116
- popResolvingProvder() {
117
- this.resolvingProviders.pop();
118
- }
119
- getBinder(provider) {
120
- const binder = this.tryGetBinderRecursively(provider);
121
- if (binder == null) {
122
- throw new NoBinderError(provider);
123
- }
124
- return binder;
125
- }
126
- /**
127
- * Finds binder for the specified provider recursively up to the root injector
128
- * @param provider
129
- * @private
130
- */
131
- tryGetBinderRecursively(provider) {
132
- var _a, _b;
133
- return ((_a = this.binders.get(provider)) !== null && _a !== void 0 ? _a : (_b = this.parent) === null || _b === void 0 ? void 0 : _b.tryGetBinderRecursively(provider));
134
- }
135
- /**
136
- * Checks is there circular dependency and throws error if so
137
- * @param provider
138
- * @private
139
- */
140
- checkCircularDependency(provider) {
141
- const i = this.resolvingProviders.indexOf(provider);
142
- if (i !== -1) {
143
- const providers = [...this.resolvingProviders.slice(i), provider];
144
- throw new CircularDependencyError(providers);
145
- }
146
- }
147
- /**
148
- * Temporary activates this injector calls provided function and returns its value
149
- * @param func
150
- * @private
151
- */
152
- activateAndCall(func) {
153
- InjectorsStack_1.InjectorsStack.push(this);
154
- const value = func();
155
- InjectorsStack_1.InjectorsStack.pop();
156
- return value;
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;
@@ -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 for holding current active injector
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();