async-injection 2.2.0 → 3.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 +134 -194
- package/lib/async-factory-provider.d.ts +4 -4
- package/lib/bindable-provider.d.ts +4 -4
- package/lib/binding.d.ts +80 -0
- package/lib/cjs/async-factory-provider.js +5 -5
- package/lib/cjs/async-factory-provider.js.map +1 -1
- package/lib/cjs/bindable-provider.js +23 -36
- package/lib/cjs/bindable-provider.js.map +1 -1
- package/lib/cjs/{binder.js → binding.js} +1 -1
- package/lib/cjs/binding.js.map +1 -0
- package/lib/cjs/class-provider.js +168 -66
- package/lib/cjs/class-provider.js.map +1 -1
- package/lib/cjs/constant-provider.js +4 -4
- package/lib/cjs/constant-provider.js.map +1 -1
- package/lib/cjs/container.js +81 -45
- package/lib/cjs/container.js.map +1 -1
- package/lib/cjs/decorators.js +80 -40
- package/lib/cjs/decorators.js.map +1 -1
- package/lib/cjs/index.js +10 -10
- package/lib/cjs/index.js.map +1 -1
- package/lib/cjs/injector.js +5 -5
- package/lib/cjs/injector.js.map +1 -1
- package/lib/cjs/provider.js +16 -11
- package/lib/cjs/provider.js.map +1 -1
- package/lib/cjs/state.js +2 -2
- package/lib/cjs/state.js.map +1 -1
- package/lib/cjs/sync-factory-provider.js +7 -7
- package/lib/cjs/sync-factory-provider.js.map +1 -1
- package/lib/cjs/utils.js +10 -13
- package/lib/cjs/utils.js.map +1 -1
- package/lib/class-provider.d.ts +20 -6
- package/lib/constant-provider.d.ts +2 -2
- package/lib/container.d.ts +45 -19
- package/lib/decorators.d.ts +16 -3
- package/lib/esm/async-factory-provider.js +1 -1
- package/lib/esm/async-factory-provider.js.map +1 -1
- package/lib/esm/bindable-provider.js +19 -32
- package/lib/esm/bindable-provider.js.map +1 -1
- package/lib/esm/binding.js +2 -0
- package/lib/esm/binding.js.map +1 -0
- package/lib/esm/class-provider.js +155 -53
- package/lib/esm/class-provider.js.map +1 -1
- package/lib/esm/constant-provider.js.map +1 -1
- package/lib/esm/container.js +63 -27
- package/lib/esm/container.js.map +1 -1
- package/lib/esm/decorators.js +61 -22
- package/lib/esm/decorators.js.map +1 -1
- package/lib/esm/index.js.map +1 -1
- package/lib/esm/injector.js +5 -5
- package/lib/esm/injector.js.map +1 -1
- package/lib/esm/provider.js +14 -9
- package/lib/esm/provider.js.map +1 -1
- package/lib/esm/state.js.map +1 -1
- package/lib/esm/sync-factory-provider.js +1 -1
- package/lib/esm/sync-factory-provider.js.map +1 -1
- package/lib/esm/utils.js +6 -8
- package/lib/esm/utils.js.map +1 -1
- package/lib/index.d.ts +4 -3
- package/lib/injector.d.ts +1 -1
- package/lib/provider.d.ts +4 -4
- package/lib/state.d.ts +3 -3
- package/lib/sync-factory-provider.d.ts +5 -5
- package/package.json +7 -18
- package/lib/binder.d.ts +0 -106
- package/lib/cjs/binder.js.map +0 -1
- package/lib/esm/binder.js +0 -2
- package/lib/esm/binder.js.map +0 -1
package/lib/cjs/container.js
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.Container = void 0;
|
|
4
|
-
const
|
|
5
|
-
const
|
|
6
|
-
const
|
|
7
|
-
const
|
|
8
|
-
const
|
|
9
|
-
const
|
|
10
|
-
const
|
|
11
|
-
const
|
|
4
|
+
const async_factory_provider_1 = require("./async-factory-provider");
|
|
5
|
+
const bindable_provider_1 = require("./bindable-provider");
|
|
6
|
+
const class_provider_1 = require("./class-provider");
|
|
7
|
+
const constant_provider_1 = require("./constant-provider");
|
|
8
|
+
const constants_1 = require("./constants");
|
|
9
|
+
const state_1 = require("./state");
|
|
10
|
+
const sync_factory_provider_1 = require("./sync-factory-provider");
|
|
11
|
+
const utils_1 = require("./utils");
|
|
12
12
|
/**
|
|
13
13
|
* Helper class to ensure we can distinguish between Error instances legitimately returned from Providers, and Errors thrown by Providers.
|
|
14
14
|
*
|
|
@@ -20,7 +20,7 @@ class ReasonWrapper {
|
|
|
20
20
|
}
|
|
21
21
|
}
|
|
22
22
|
/**
|
|
23
|
-
*
|
|
23
|
+
* Injector (aka Container) to handle (a)synchronous dependency management.
|
|
24
24
|
*/
|
|
25
25
|
class Container {
|
|
26
26
|
/**
|
|
@@ -34,7 +34,7 @@ class Container {
|
|
|
34
34
|
* @inheritDoc
|
|
35
35
|
*/
|
|
36
36
|
isIdKnown(id, ascending) {
|
|
37
|
-
if (
|
|
37
|
+
if (this.providers.has(id))
|
|
38
38
|
return true;
|
|
39
39
|
if (ascending && this.parent)
|
|
40
40
|
return this.parent.isIdKnown(id, true);
|
|
@@ -62,7 +62,7 @@ class Container {
|
|
|
62
62
|
*/
|
|
63
63
|
resolve(id) {
|
|
64
64
|
const state = this.resolveState(id);
|
|
65
|
-
if ((0,
|
|
65
|
+
if ((0, utils_1.isPromise)(state.promise)) {
|
|
66
66
|
return state.promise;
|
|
67
67
|
}
|
|
68
68
|
if (state.rejected) {
|
|
@@ -70,53 +70,93 @@ class Container {
|
|
|
70
70
|
}
|
|
71
71
|
return Promise.resolve(state.fulfilled);
|
|
72
72
|
}
|
|
73
|
-
// noinspection JSUnusedGlobalSymbols
|
|
74
73
|
/**
|
|
75
|
-
*
|
|
76
|
-
*
|
|
74
|
+
* Removes a binding from this Container (and optionally its ancestor chain).
|
|
75
|
+
* Most useful in unit tests to replace or clear bindings between test cases.
|
|
76
|
+
* **Caution:** Removing a binding after initialization may have unexpected consequences if other parts of the application still hold or expect to obtain an instance of the removed id.
|
|
77
77
|
*
|
|
78
|
-
* @param id The id to
|
|
79
|
-
* @param ascending If true,
|
|
80
|
-
* @param releaseIfSingleton If true,
|
|
78
|
+
* @param id The id of the binding to remove.
|
|
79
|
+
* @param ascending If true, the binding is also removed from every Container in the parent chain.
|
|
80
|
+
* @param releaseIfSingleton If true, Provider.releaseIfSingleton is called before removal.
|
|
81
81
|
*/
|
|
82
82
|
removeBinding(id, ascending, releaseIfSingleton) {
|
|
83
|
-
var _a;
|
|
84
83
|
if (releaseIfSingleton) {
|
|
85
84
|
const p = this.providers.get(id);
|
|
86
85
|
if (p)
|
|
87
86
|
p.releaseIfSingleton();
|
|
88
87
|
}
|
|
89
88
|
this.providers.delete(id);
|
|
90
|
-
if (ascending && this.parent) {
|
|
91
|
-
|
|
92
|
-
(_a = this.parent) === null || _a === void 0 ? void 0 : _a.removeBinding(id, true, releaseIfSingleton);
|
|
89
|
+
if (ascending && this.parent instanceof Container) {
|
|
90
|
+
this.parent.removeBinding(id, true, releaseIfSingleton);
|
|
93
91
|
}
|
|
94
92
|
}
|
|
93
|
+
/**
|
|
94
|
+
* Alias for {@link isIdKnown}. Familiar to users migrating from TypeDI.
|
|
95
|
+
*/
|
|
96
|
+
has(id, ascending) {
|
|
97
|
+
return this.isIdKnown(id, ascending);
|
|
98
|
+
}
|
|
99
|
+
/**
|
|
100
|
+
* Alias for {@link removeBinding}. Familiar to users migrating from InversifyJS.
|
|
101
|
+
*/
|
|
102
|
+
unbind(id, ascending, releaseIfSingleton) {
|
|
103
|
+
this.removeBinding(id, ascending, releaseIfSingleton);
|
|
104
|
+
}
|
|
105
|
+
/**
|
|
106
|
+
* Creates a new child Container that inherits unbound ids from this Container.
|
|
107
|
+
* Familiar to users migrating from TSyringe.
|
|
108
|
+
*/
|
|
109
|
+
createChildContainer() {
|
|
110
|
+
return new Container(this);
|
|
111
|
+
}
|
|
112
|
+
/**
|
|
113
|
+
* Descriptor-based binding dispatching to the appropriate bindXXX method.
|
|
114
|
+
* Familiar to users migrating from TSyringe.
|
|
115
|
+
* Returns a {@link BindAs} chain for class and factory bindings; returns undefined for value bindings (which are always singletons).
|
|
116
|
+
*/
|
|
117
|
+
register(id, descriptor) {
|
|
118
|
+
if ('useClass' in descriptor)
|
|
119
|
+
return this.bindClass(id, descriptor.useClass);
|
|
120
|
+
if ('useValue' in descriptor) {
|
|
121
|
+
this.bindConstant(id, descriptor.useValue);
|
|
122
|
+
return undefined;
|
|
123
|
+
}
|
|
124
|
+
if ('useFactory' in descriptor)
|
|
125
|
+
return this.bindFactory(id, descriptor.useFactory);
|
|
126
|
+
// useAsyncFactory
|
|
127
|
+
return this.bindAsyncFactory(id, descriptor.useAsyncFactory);
|
|
128
|
+
}
|
|
129
|
+
/**
|
|
130
|
+
* Binds a class as a singleton in one step.
|
|
131
|
+
* Shorthand for {@link bindClass}(...).{@link BindAs.asSingleton asSingleton}().
|
|
132
|
+
* Familiar to users migrating from TSyringe.
|
|
133
|
+
*/
|
|
134
|
+
registerSingleton(id, constructor) {
|
|
135
|
+
this.bindClass(id, constructor).asSingleton();
|
|
136
|
+
}
|
|
95
137
|
/**
|
|
96
138
|
* @inheritDoc
|
|
97
139
|
*/
|
|
98
140
|
bindConstant(id, value) {
|
|
99
|
-
this.providers.set(id, new
|
|
141
|
+
this.providers.set(id, new constant_provider_1.ConstantProvider(value));
|
|
100
142
|
return value;
|
|
101
143
|
}
|
|
102
144
|
bindClass(id, constructor) {
|
|
103
145
|
if (typeof constructor === 'undefined') {
|
|
104
146
|
constructor = id;
|
|
105
147
|
}
|
|
106
|
-
if (!Reflect.getMetadata(
|
|
148
|
+
if (!Reflect.getMetadata(constants_1.INJECTABLE_METADATA_KEY, constructor)) {
|
|
107
149
|
throw new Error('Class not decorated with @Injectable [' + constructor.toString() + ']');
|
|
108
150
|
}
|
|
109
|
-
|
|
110
|
-
const provider = new class_provider_js_1.ClassBasedProvider(this, id, constructor);
|
|
151
|
+
const provider = new class_provider_1.ClassBasedProvider(this, id, constructor);
|
|
111
152
|
this.providers.set(id, provider);
|
|
112
|
-
/* eslint-disable @typescript-eslint/no-unsafe-return */
|
|
113
153
|
return provider.makeBindAs();
|
|
114
154
|
}
|
|
115
155
|
/**
|
|
116
156
|
* @inheritDoc
|
|
117
157
|
*/
|
|
118
158
|
bindFactory(id, factory) {
|
|
119
|
-
const provider = new
|
|
159
|
+
const provider = new sync_factory_provider_1.FactoryBasedProvider(this, id, factory);
|
|
120
160
|
this.providers.set(id, provider);
|
|
121
161
|
return provider.makeBindAs();
|
|
122
162
|
}
|
|
@@ -124,7 +164,7 @@ class Container {
|
|
|
124
164
|
* @inheritDoc
|
|
125
165
|
*/
|
|
126
166
|
bindAsyncFactory(id, factory) {
|
|
127
|
-
const provider = new
|
|
167
|
+
const provider = new async_factory_provider_1.AsyncFactoryBasedProvider(this, id, factory);
|
|
128
168
|
this.providers.set(id, provider);
|
|
129
169
|
return provider.makeBindAs();
|
|
130
170
|
}
|
|
@@ -132,14 +172,13 @@ class Container {
|
|
|
132
172
|
* @inheritDoc
|
|
133
173
|
*/
|
|
134
174
|
resolveSingletons(asyncOnly, parentRecursion) {
|
|
135
|
-
var _a;
|
|
136
175
|
const makePromiseToResolve = () => {
|
|
137
176
|
return new Promise((resolve, reject) => {
|
|
138
177
|
const pending = new Map();
|
|
139
178
|
// Ask each provider to resolve itself *IF* it is a singleton.
|
|
140
179
|
this.providers.forEach((value, key) => {
|
|
141
180
|
// If the provider is a singleton *and* if resolution is being handled asynchronously, the provider will return a completion promise.
|
|
142
|
-
const p = value.resolveIfSingleton(asyncOnly);
|
|
181
|
+
const p = value.resolveIfSingleton(asyncOnly !== null && asyncOnly !== void 0 ? asyncOnly : false);
|
|
143
182
|
if (p !== null && typeof p !== 'undefined')
|
|
144
183
|
pending.set(key, p);
|
|
145
184
|
});
|
|
@@ -166,9 +205,8 @@ class Container {
|
|
|
166
205
|
});
|
|
167
206
|
});
|
|
168
207
|
};
|
|
169
|
-
if (parentRecursion &&
|
|
170
|
-
|
|
171
|
-
return pb.resolveSingletons(asyncOnly, parentRecursion).then(() => {
|
|
208
|
+
if (parentRecursion && this.parent instanceof Container) {
|
|
209
|
+
return this.parent.resolveSingletons(asyncOnly, parentRecursion).then(() => {
|
|
172
210
|
return makePromiseToResolve().then(() => this);
|
|
173
211
|
});
|
|
174
212
|
}
|
|
@@ -188,24 +226,23 @@ class Container {
|
|
|
188
226
|
// This code (below) will only ever execute if the creator of this container passes in their own implementation of an Injector.
|
|
189
227
|
/* istanbul ignore next */
|
|
190
228
|
try {
|
|
191
|
-
return
|
|
229
|
+
return state_1.State.MakeState(this.parent.resolve(id), undefined, undefined);
|
|
192
230
|
}
|
|
193
231
|
catch (err) {
|
|
194
|
-
return
|
|
232
|
+
return state_1.State.MakeState(null, err);
|
|
195
233
|
}
|
|
196
234
|
}
|
|
197
|
-
return
|
|
235
|
+
return state_1.State.MakeState(null, new Error('Symbol not bound: ' + id.toString()));
|
|
198
236
|
}
|
|
199
237
|
return provider.provideAsState();
|
|
200
238
|
}
|
|
201
|
-
// noinspection JSUnusedGlobalSymbols
|
|
202
239
|
/**
|
|
203
240
|
* Convenience method to assist in releasing non-garbage-collectable resources that Singletons in this Container may have allocated.
|
|
204
|
-
* It will walk through all registered Providers (of this Container only), and invoke their
|
|
205
|
-
* This method is not part of the
|
|
241
|
+
* It will walk through all registered Providers (of this Container only), and invoke their Provider.releaseIfSingleton method.
|
|
242
|
+
* This method is not part of the Injector interface, because you normally only create (and release) from Containers.
|
|
206
243
|
* NOTE:
|
|
207
244
|
* This *only* releases active/pending Singleton's that have already been created by this Container.
|
|
208
|
-
* The most likely use of this method would be when you have created a new child Container for a limited
|
|
245
|
+
* The most likely use of this method would be when you have created a new child Container for a limited-duration transaction, and you want to easily clean up temporary resources.
|
|
209
246
|
* For example, your service object may need to know when it should unsubscribe from an RxJs stream (failure to do so can result in your Singleton not being garbage collected at the end of a transaction).
|
|
210
247
|
* In theory, you could handle all unsubscription and cleanup yourself, but the @Release decorator and this method are meant to simply make that easier.
|
|
211
248
|
*/
|
|
@@ -216,7 +253,7 @@ class Container {
|
|
|
216
253
|
}
|
|
217
254
|
/**
|
|
218
255
|
* Releases a Singleton instance if it exists.
|
|
219
|
-
* However, it does **not** remove the binding, so if you call
|
|
256
|
+
* However, it does **not** remove the binding, so if you call get or resolve (directly or indirectly) on the id, a new Singleton will be created.
|
|
220
257
|
* If not a singleton, this method returns undefined.
|
|
221
258
|
* If the singleton has been resolved, it is returned, otherwise null is returned.
|
|
222
259
|
* If the singleton is pending resolution, a Promise for the singleton (or for null) is returned.
|
|
@@ -229,7 +266,7 @@ class Container {
|
|
|
229
266
|
return undefined;
|
|
230
267
|
}
|
|
231
268
|
/**
|
|
232
|
-
* Make a copy of this
|
|
269
|
+
* Make a copy of this Container.
|
|
233
270
|
* This is an experimental feature!
|
|
234
271
|
* I have not thought through all the dark corners, so use at your own peril!
|
|
235
272
|
* Here are some notes:
|
|
@@ -241,16 +278,15 @@ class Container {
|
|
|
241
278
|
* If released by the clone, they will be considered released by "this" container.
|
|
242
279
|
* If a singleton is currently being asynchronously constructed any callbacks will reference "this" Container, however both Containers should have no problem awaiting resolution.
|
|
243
280
|
* If a singleton is not resolved when the container is cloned, then if both containers resolve, you will create *two* "singletons".
|
|
244
|
-
* The way to avoid this last effect is to
|
|
281
|
+
* The way to avoid this last effect is to call resolveSingletons first
|
|
245
282
|
*/
|
|
246
283
|
clone(clazz) {
|
|
247
284
|
if (!clazz)
|
|
248
285
|
clazz = Container;
|
|
249
286
|
const retVal = new clazz(this.parent);
|
|
250
287
|
this.providers.forEach((v, k) => {
|
|
251
|
-
if (v instanceof
|
|
288
|
+
if (v instanceof bindable_provider_1.BindableProvider) {
|
|
252
289
|
v = Object.assign(Object.create(Object.getPrototypeOf(v)), v);
|
|
253
|
-
// eslint-disable-next-line @typescript-eslint/no-unsafe-member-access
|
|
254
290
|
v.injector = retVal;
|
|
255
291
|
}
|
|
256
292
|
retVal.providers.set(k, v);
|
package/lib/cjs/container.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"container.js","sourceRoot":"","sources":["../../src/container.ts"],"names":[],"mappings":"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","sourcesContent":["import {AsyncFactoryBasedProvider} from './async-factory-provider.js';\nimport {BindableProvider} from './bindable-provider.js';\nimport {AsyncFactory, BindAs, Binder, SyncFactory} from './binder.js';\nimport {ClassBasedProvider} from './class-provider.js';\nimport {ConstantProvider} from './constant-provider.js';\nimport {INJECTABLE_METADATA_KEY} from './constants.js';\nimport {AbstractConstructor, ClassConstructor, InjectableId, Injector} from './injector.js';\nimport {Provider} from './provider.js';\nimport {State} from './state.js';\nimport {FactoryBasedProvider} from './sync-factory-provider.js';\nimport {isPromise} from './utils.js';\n\n/**\n * Helper class to ensure we can distinguish between Error instances legitimately returned from Providers, and Errors thrown by Providers.\n *\n * @see resolveSingletons.\n */\nclass ReasonWrapper {\n\tconstructor(public reason: any) {\n\t}\n}\n\n/**\n * Binder and Injector (aka Container) to handle (a)synchronous dependency management.\n */\nexport class Container implements Binder {\n\n\t/**\n\t * Create a new Container, with an optional parent Injector which will be searched if any given InjectableId is not bound within this Container.\n\t */\n\tpublic constructor(protected parent?: Injector) {\n\t}\n\n\tprotected providers = new Map<InjectableId<any>, Provider>();\n\n\t/**\n\t * @inheritDoc\n\t */\n\tpublic isIdKnown<T>(id: InjectableId<T>, ascending?: boolean): boolean {\n\t\tif (!!this.providers.get(id))\n\t\t\treturn true;\n\t\tif (ascending && this.parent)\n\t\t\treturn this.parent.isIdKnown(id, true);\n\t\treturn false;\n\t}\n\n\t/**\n\t * @inheritDoc\n\t */\n\tpublic get<T>(id: InjectableId<T>): T {\n\t\tconst provider = this.providers.get(id);\n\t\tif (!provider) {\n\t\t\tif (this.parent)\n\t\t\t\treturn this.parent.get<T>(id);\n\t\t\tthrow new Error('Symbol not bound: ' + id.toString());\n\t\t}\n\t\tconst state = provider.provideAsState();\n\t\tif (state.pending)\n\t\t\tthrow new Error('Synchronous request on unresolved asynchronous dependency tree: ' + id.toString());\n\t\tif (state.rejected)\n\t\t\tthrow state.rejected;\n\t\treturn state.fulfilled as T;\n\t}\n\n\t/**\n\t * @inheritDoc\n\t */\n\tpublic resolve<T>(id: InjectableId<T>): Promise<T> {\n\t\tconst state = this.resolveState(id);\n\t\tif (isPromise(state.promise)) {\n\t\t\treturn state.promise;\n\t\t}\n\n\t\tif (state.rejected) {\n\t\t\treturn Promise.reject(state.rejected);\n\t\t}\n\n\t\treturn Promise.resolve(state.fulfilled);\n\t}\n\n\t// noinspection JSUnusedGlobalSymbols\n\t/**\n\t * This method is not part of the Binding interface, because it is highly unusual.\n\t * But that doesn't mean we can't imagine scenarios where you might require it.\n\t *\n\t * @param id The id to be removed.\n\t * @param ascending If true, this will remove all bindings of the specified id all the way up the parent container chain (if it exists).\n\t * @param releaseIfSingleton If true, @Provider.releaseIfSingleton will be invoked before the binding is removed.\n\t */\n\tpublic removeBinding<T>(id: InjectableId<T>, ascending?: boolean, releaseIfSingleton?: boolean): void {\n\t\tif (releaseIfSingleton) {\n\t\t\tconst p = this.providers.get(id);\n\t\t\tif (p)\n\t\t\t\tp.releaseIfSingleton();\n\t\t}\n\t\tthis.providers.delete(id);\n\n\t\tif (ascending && this.parent) {\n\t\t\t// eslint-disable-next-line @typescript-eslint/no-unsafe-member-access, @typescript-eslint/no-unsafe-call\n\t\t\t(this.parent as any)?.removeBinding(id, true, releaseIfSingleton);\n\t\t}\n\t}\n\n\t/**\n\t * @inheritDoc\n\t */\n\tpublic bindConstant<T>(id: InjectableId<T>, value: T): T {\n\t\tthis.providers.set(id, new ConstantProvider(value));\n\t\treturn value;\n\t}\n\n\t/**\n\t * @inheritDoc\n\t */\n\tpublic bindClass<T>(id: ClassConstructor<T>, constructor?: ClassConstructor<T>): BindAs<T, ClassConstructor<T>>;\n\tpublic bindClass<T>(id: string | symbol | AbstractConstructor<T> | InjectableId<T>, constructor: ClassConstructor<T>): BindAs<T, ClassConstructor<T>>;\n\tpublic bindClass<T>(id: string | symbol | AbstractConstructor<T> | ClassConstructor<T>, constructor: ClassConstructor<T>): BindAs<T, ClassConstructor<T>> {\n\t\tif (typeof constructor === 'undefined') {\n\t\t\tconstructor = id as new (...args: any[]) => T;\n\t\t}\n\t\tif (!Reflect.getMetadata(INJECTABLE_METADATA_KEY, constructor)) {\n\t\t\tthrow new Error('Class not decorated with @Injectable [' + constructor.toString() + ']');\n\t\t}\n\t\t/* eslint-disable @typescript-eslint/no-unsafe-argument */\n\t\tconst provider = new ClassBasedProvider(this as any, id, constructor);\n\t\tthis.providers.set(id, provider);\n\t\t/* eslint-disable @typescript-eslint/no-unsafe-return */\n\t\treturn provider.makeBindAs();\n\t}\n\n\t/**\n\t * @inheritDoc\n\t */\n\tpublic bindFactory<T>(id: InjectableId<T>, factory: SyncFactory<T>): BindAs<T, SyncFactory<T>> {\n\t\tconst provider = new FactoryBasedProvider(this, id, factory);\n\t\tthis.providers.set(id, provider);\n\t\treturn provider.makeBindAs();\n\t}\n\n\t/**\n\t * @inheritDoc\n\t */\n\tpublic bindAsyncFactory<T>(id: InjectableId<T>, factory: AsyncFactory<T>): BindAs<T, AsyncFactory<T>> {\n\t\tconst provider = new AsyncFactoryBasedProvider(this, id, factory);\n\t\tthis.providers.set(id, provider);\n\t\treturn provider.makeBindAs();\n\t}\n\n\t/**\n\t * @inheritDoc\n\t */\n\tpublic resolveSingletons(asyncOnly?: boolean, parentRecursion?: boolean): Promise<this> {\n\t\tconst makePromiseToResolve = () => {\n\t\t\treturn new Promise<void>((resolve, reject) => {\n\t\t\t\tconst pending = new Map<InjectableId<any>, Promise<void>>();\n\t\t\t\t// Ask each provider to resolve itself *IF* it is a singleton.\n\t\t\t\tthis.providers.forEach((value: Provider, key: InjectableId<any>) => {\n\t\t\t\t\t// If the provider is a singleton *and* if resolution is being handled asynchronously, the provider will return a completion promise.\n\t\t\t\t\tconst p = value.resolveIfSingleton(asyncOnly);\n\t\t\t\t\tif (p !== null && typeof p !== 'undefined')\n\t\t\t\t\t\tpending.set(key, p);\n\t\t\t\t});\n\t\t\t\t// The contract for this method is that it behaves somewhat like Promise.allSettled (e.g. won't complete until all pending Singletons have settled).\n\t\t\t\t// Further the contract states that if any of the asynchronous Singletons rejected, that we will also return a rejected Promise, and that the rejection reason will be a Map of the InjectableId's that did not resolve, and the Error they emitted.\n\t\t\t\tconst pp = Array.from(pending.values());\n\t\t\t\tconst keys = Array.from(pending.keys());\n\t\t\t\t// Mapping the catch is an alternate version of Promise.allSettled (e.g. keeps Promise.all from short-circuiting).\n\t\t\t\tPromise.all(pp\n\t\t\t\t\t.map(p => p.catch(e => new ReasonWrapper(e))))\n\t\t\t\t\t.then((results) => {\n\t\t\t\t\t\tconst rejects = new Map<InjectableId<any>, Error>();\n\t\t\t\t\t\t// Check the results. Since we don't export ReasonWrapper, it is safe to assume that an instance of that was produced by our map => catch code above, so it's a rejected Singleton error.\n\t\t\t\t\t\tresults.forEach((result, idx) => {\n\t\t\t\t\t\t\tif (result instanceof ReasonWrapper) {\n\t\t\t\t\t\t\t\trejects.set(keys[idx], result.reason);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t});\n\t\t\t\t\t\t// If we had rejections, notify our caller what they were.\n\t\t\t\t\t\tif (rejects.size > 0)\n\t\t\t\t\t\t\treject(rejects);\n\t\t\t\t\t\telse\n\t\t\t\t\t\t\tresolve(); // All good.\n\t\t\t\t\t});\n\t\t\t});\n\t\t};\n\t\tif (parentRecursion && typeof (this.parent as Binder)?.resolveSingletons === 'function') {\n\t\t\tconst pb: Binder = this.parent as Binder;\n\t\t\treturn pb.resolveSingletons(asyncOnly, parentRecursion).then(() => {\n\t\t\t\treturn makePromiseToResolve().then(() => this);\n\t\t\t});\n\t\t}\n\t\treturn makePromiseToResolve().then(() => this);\n\t}\n\n\t/**\n\t * As implied by the name prefix, this is a factored out method invoked only by the 'resolve' method.\n\t * It makes searching our parent (if it exists) easier (and quicker) IF our parent is a fellow instance of Container.\n\t */\n\tprotected resolveState<T>(id: InjectableId<T>): State<T> {\n\t\tconst provider = this.providers.get(id);\n\t\tif (!provider) {\n\t\t\tif (this.parent) {\n\t\t\t\tif (this.parent instanceof Container) {\n\t\t\t\t\treturn this.parent.resolveState<T>(id);\n\t\t\t\t}\n\t\t\t\t// This code (below) will only ever execute if the creator of this container passes in their own implementation of an Injector.\n\t\t\t\t/* istanbul ignore next */\n\t\t\t\ttry {\n\t\t\t\t\treturn State.MakeState<T>(this.parent.resolve<T>(id), undefined, undefined);\n\t\t\t\t}\n\t\t\t\tcatch (err) {\n\t\t\t\t\treturn State.MakeState<T>(null, err);\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn State.MakeState<T>(null, new Error('Symbol not bound: ' + id.toString()));\n\t\t}\n\t\treturn provider.provideAsState() as State<T>;\n\t}\n\n\t// noinspection JSUnusedGlobalSymbols\n\t/**\n\t * Convenience method to assist in releasing non-garbage-collectable resources that Singletons in this Container may have allocated.\n\t * It will walk through all registered Providers (of this Container only), and invoke their @see Provider.releaseIfSingleton method.\n\t * This method is not part of the Binding interface, because you normally only create (and release) Containers.\n\t * NOTE:\n\t * This *only* releases active/pending Singleton's that have already been created by this Container.\n\t * The most likely use of this method would be when you have created a new child Container for a limited duration transaction, and you want to easily cleanup temporary resources.\n\t * For example, your service object may need to know when it should unsubscribe from an RxJs stream (failure to do so can result in your Singleton not being garbage collected at the end of a transaction).\n\t * In theory, you could handle all unsubscription and cleanup yourself, but the @Release decorator and this method are meant to simply make that easier.\n\t */\n\tpublic releaseSingletons(): void {\n\t\tthis.providers.forEach((value: Provider) => {\n\t\t\tvalue.releaseIfSingleton();\n\t\t});\n\t}\n\n\t/**\n\t * Releases a Singleton instance if it exists.\n\t * However, it does **not** remove the binding, so if you call @get or @resolve (directly or indirectly) on the id, a new Singleton will be created.\n\t * If not a singleton, this method returns undefined.\n\t * If the singleton has been resolved, it is returned, otherwise null is returned.\n\t * If the singleton is pending resolution, a Promise for the singleton (or for null) is returned.\n\t * Note that if a singleton is returned, its Release method will already have been invoked.\n\t */\n\tpublic releaseSingleton<T>(id: InjectableId<T>): T | undefined | null | Promise<T | null> {\n\t\tconst provider = this.providers.get(id);\n\t\tif (provider)\n\t\t\treturn provider.releaseIfSingleton();\n\t\treturn undefined;\n\t}\n\n\t/**\n\t * Make a copy of this @see Container.\n\t * This is an experimental feature!\n\t * I have not thought through all the dark corners, so use at your own peril!\n\t * Here are some notes:\n\t * The injector parameter for SyncFactory and AsyncFactory callbacks will be the Container invoking the factory.\n\t * So a factory that uses a parent closure instead of the supplied injector may get unexpected results.\n\t * The injector parameter for OnSuccess and OnError callbacks will be the Container performing the resolution.\n\t * Singletons are cloned at their *existing* state..\n\t * If resolved in \"this\" container, they will not be re-resolved for the clone.\n\t * If released by the clone, they will be considered released by \"this\" container.\n\t * If a singleton is currently being asynchronously constructed any callbacks will reference \"this\" Container, however both Containers should have no problem awaiting resolution.\n\t * If a singleton is not resolved when the container is cloned, then if both containers resolve, you will create *two* \"singletons\".\n\t * The way to avoid this last effect is to @see resolveSingletons\n\t */\n\tclone(clazz?: ClassConstructor<Container>): Container {\n\t\tif (!clazz)\n\t\t\tclazz = Container;\n\t\tconst retVal = new clazz(this.parent);\n\t\tthis.providers.forEach((v, k) => {\n\t\t\tif (v instanceof BindableProvider) {\n\t\t\t\tv = Object.assign(Object.create(Object.getPrototypeOf(v)), v);\n\t\t\t\t// eslint-disable-next-line @typescript-eslint/no-unsafe-member-access\n\t\t\t\t(v as any).injector = retVal;\n\t\t\t}\n\t\t\tretVal.providers.set(k, v);\n\t\t});\n\t\treturn retVal;\n\t}\n}\n"]}
|
|
1
|
+
{"version":3,"file":"container.js","sourceRoot":"","sources":["../../src/container.ts"],"names":[],"mappings":"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","sourcesContent":["import {AsyncFactoryBasedProvider} from './async-factory-provider';\nimport {BindableProvider} from './bindable-provider';\nimport {AsyncFactory, BindAs, RegisterDescriptor, SyncFactory} from './binding';\nimport {ClassBasedProvider} from './class-provider';\nimport {ConstantProvider} from './constant-provider';\nimport {INJECTABLE_METADATA_KEY} from './constants';\nimport {AbstractConstructor, ClassConstructor, InjectableId, Injector} from './injector';\nimport {Provider} from './provider';\nimport {State} from './state';\nimport {FactoryBasedProvider} from './sync-factory-provider';\nimport {isPromise} from './utils';\n\n/**\n * Helper class to ensure we can distinguish between Error instances legitimately returned from Providers, and Errors thrown by Providers.\n *\n * @see resolveSingletons.\n */\nclass ReasonWrapper {\n\tconstructor(public reason: any) {\n\t}\n}\n\n/**\n * Injector (aka Container) to handle (a)synchronous dependency management.\n */\nexport class Container implements Injector {\n\n\t/**\n\t * Create a new Container, with an optional parent Injector which will be searched if any given InjectableId is not bound within this Container.\n\t */\n\tpublic constructor(protected parent?: Injector) {\n\t}\n\n\tprotected providers = new Map<InjectableId<any>, Provider>();\n\n\t/**\n\t * @inheritDoc\n\t */\n\tpublic isIdKnown<T>(id: InjectableId<T>, ascending?: boolean): boolean {\n\t\tif (this.providers.has(id))\n\t\t\treturn true;\n\t\tif (ascending && this.parent)\n\t\t\treturn this.parent.isIdKnown(id, true);\n\t\treturn false;\n\t}\n\n\t/**\n\t * @inheritDoc\n\t */\n\tpublic get<T>(id: InjectableId<T>): T {\n\t\tconst provider = this.providers.get(id);\n\t\tif (!provider) {\n\t\t\tif (this.parent)\n\t\t\t\treturn this.parent.get<T>(id);\n\t\t\tthrow new Error('Symbol not bound: ' + id.toString());\n\t\t}\n\t\tconst state = provider.provideAsState();\n\t\tif (state.pending)\n\t\t\tthrow new Error('Synchronous request on unresolved asynchronous dependency tree: ' + id.toString());\n\t\tif (state.rejected)\n\t\t\tthrow state.rejected;\n\t\treturn state.fulfilled as T;\n\t}\n\n\t/**\n\t * @inheritDoc\n\t */\n\tpublic resolve<T>(id: InjectableId<T>): Promise<T> {\n\t\tconst state = this.resolveState(id);\n\t\tif (isPromise(state.promise)) {\n\t\t\treturn state.promise;\n\t\t}\n\n\t\tif (state.rejected) {\n\t\t\treturn Promise.reject(state.rejected);\n\t\t}\n\n\t\treturn Promise.resolve(state.fulfilled);\n\t}\n\n\t/**\n\t * Removes a binding from this Container (and optionally its ancestor chain).\n\t * Most useful in unit tests to replace or clear bindings between test cases.\n\t * **Caution:** Removing a binding after initialization may have unexpected consequences if other parts of the application still hold or expect to obtain an instance of the removed id.\n\t *\n\t * @param id The id of the binding to remove.\n\t * @param ascending If true, the binding is also removed from every Container in the parent chain.\n\t * @param releaseIfSingleton If true, Provider.releaseIfSingleton is called before removal.\n\t */\n\tpublic removeBinding<T>(id: InjectableId<T>, ascending?: boolean, releaseIfSingleton?: boolean): void {\n\t\tif (releaseIfSingleton) {\n\t\t\tconst p = this.providers.get(id);\n\t\t\tif (p)\n\t\t\t\tp.releaseIfSingleton();\n\t\t}\n\t\tthis.providers.delete(id);\n\n\t\tif (ascending && this.parent instanceof Container) {\n\t\t\tthis.parent.removeBinding(id, true, releaseIfSingleton);\n\t\t}\n\t}\n\n\n\t/**\n\t * Alias for {@link isIdKnown}. Familiar to users migrating from TypeDI.\n\t */\n\tpublic has<T>(id: InjectableId<T>, ascending?: boolean): boolean {\n\t\treturn this.isIdKnown(id, ascending);\n\t}\n\n\t/**\n\t * Alias for {@link removeBinding}. Familiar to users migrating from InversifyJS.\n\t */\n\tpublic unbind<T>(id: InjectableId<T>, ascending?: boolean, releaseIfSingleton?: boolean): void {\n\t\tthis.removeBinding(id, ascending, releaseIfSingleton);\n\t}\n\n\t/**\n\t * Creates a new child Container that inherits unbound ids from this Container.\n\t * Familiar to users migrating from TSyringe.\n\t */\n\tpublic createChildContainer(): Container {\n\t\treturn new Container(this);\n\t}\n\n\t/**\n\t * Descriptor-based binding dispatching to the appropriate bindXXX method.\n\t * Familiar to users migrating from TSyringe.\n\t * Returns a {@link BindAs} chain for class and factory bindings; returns undefined for value bindings (which are always singletons).\n\t */\n\tpublic register<T>(id: InjectableId<T>, descriptor: RegisterDescriptor<T>): BindAs<T, any> | undefined {\n\t\tif ('useClass' in descriptor)\n\t\t\treturn this.bindClass(id as any, descriptor.useClass);\n\t\tif ('useValue' in descriptor) {\n\t\t\tthis.bindConstant(id, descriptor.useValue);\n\t\t\treturn undefined;\n\t\t}\n\t\tif ('useFactory' in descriptor)\n\t\t\treturn this.bindFactory(id, descriptor.useFactory);\n\t\t// useAsyncFactory\n\t\treturn this.bindAsyncFactory(id, (descriptor as {useAsyncFactory: AsyncFactory<T>}).useAsyncFactory);\n\t}\n\n\t/**\n\t * Binds a class as a singleton in one step.\n\t * Shorthand for {@link bindClass}(...).{@link BindAs.asSingleton asSingleton}().\n\t * Familiar to users migrating from TSyringe.\n\t */\n\tpublic registerSingleton<T>(id: InjectableId<T>, constructor: ClassConstructor<T>): void {\n\t\tthis.bindClass(id as any, constructor).asSingleton();\n\t}\n\t/**\n\t * @inheritDoc\n\t */\n\tpublic bindConstant<T>(id: InjectableId<T>, value: T): T {\n\t\tthis.providers.set(id, new ConstantProvider(value));\n\t\treturn value;\n\t}\n\n\t/**\n\t * @inheritDoc\n\t */\n\tpublic bindClass<T>(id: ClassConstructor<T>, constructor?: ClassConstructor<T>): BindAs<T, ClassConstructor<T>>;\n\tpublic bindClass<T>(id: string | symbol | AbstractConstructor<T> | InjectableId<T>, constructor: ClassConstructor<T>): BindAs<T, ClassConstructor<T>>;\n\tpublic bindClass<T>(id: string | symbol | AbstractConstructor<T> | ClassConstructor<T>, constructor: ClassConstructor<T>): BindAs<T, ClassConstructor<T>> {\n\t\tif (typeof constructor === 'undefined') {\n\t\t\tconstructor = id as new (...args: any[]) => T;\n\t\t}\n\t\tif (!Reflect.getMetadata(INJECTABLE_METADATA_KEY, constructor)) {\n\t\t\tthrow new Error('Class not decorated with @Injectable [' + constructor.toString() + ']');\n\t\t}\n\t\tconst provider = new ClassBasedProvider(this as any, id, constructor);\n\t\tthis.providers.set(id, provider);\n\t\treturn provider.makeBindAs();\n\t}\n\n\t/**\n\t * @inheritDoc\n\t */\n\tpublic bindFactory<T>(id: InjectableId<T>, factory: SyncFactory<T>): BindAs<T, SyncFactory<T>> {\n\t\tconst provider = new FactoryBasedProvider(this, id, factory);\n\t\tthis.providers.set(id, provider);\n\t\treturn provider.makeBindAs();\n\t}\n\n\t/**\n\t * @inheritDoc\n\t */\n\tpublic bindAsyncFactory<T>(id: InjectableId<T>, factory: AsyncFactory<T>): BindAs<T, AsyncFactory<T>> {\n\t\tconst provider = new AsyncFactoryBasedProvider(this, id, factory);\n\t\tthis.providers.set(id, provider);\n\t\treturn provider.makeBindAs();\n\t}\n\n\t/**\n\t * @inheritDoc\n\t */\n\tpublic resolveSingletons(asyncOnly?: boolean, parentRecursion?: boolean): Promise<this> {\n\t\tconst makePromiseToResolve = () => {\n\t\t\treturn new Promise<void>((resolve, reject) => {\n\t\t\t\tconst pending = new Map<InjectableId<any>, Promise<void>>();\n\t\t\t\t// Ask each provider to resolve itself *IF* it is a singleton.\n\t\t\t\tthis.providers.forEach((value: Provider, key: InjectableId<any>) => {\n\t\t\t\t\t// If the provider is a singleton *and* if resolution is being handled asynchronously, the provider will return a completion promise.\n\t\t\t\t\tconst p = value.resolveIfSingleton(asyncOnly ?? false);\n\t\t\t\t\tif (p !== null && typeof p !== 'undefined')\n\t\t\t\t\t\tpending.set(key, p);\n\t\t\t\t});\n\t\t\t\t// The contract for this method is that it behaves somewhat like Promise.allSettled (e.g. won't complete until all pending Singletons have settled).\n\t\t\t\t// Further the contract states that if any of the asynchronous Singletons rejected, that we will also return a rejected Promise, and that the rejection reason will be a Map of the InjectableId's that did not resolve, and the Error they emitted.\n\t\t\t\tconst pp = Array.from(pending.values());\n\t\t\t\tconst keys = Array.from(pending.keys());\n\t\t\t\t// Mapping the catch is an alternate version of Promise.allSettled (e.g. keeps Promise.all from short-circuiting).\n\t\t\t\tPromise.all(pp\n\t\t\t\t\t.map(p => p.catch(e => new ReasonWrapper(e))))\n\t\t\t\t\t.then((results) => {\n\t\t\t\t\t\tconst rejects = new Map<InjectableId<any>, Error>();\n\t\t\t\t\t\t// Check the results. Since we don't export ReasonWrapper, it is safe to assume that an instance of that was produced by our map => catch code above, so it's a rejected Singleton error.\n\t\t\t\t\t\tresults.forEach((result, idx) => {\n\t\t\t\t\t\t\tif (result instanceof ReasonWrapper) {\n\t\t\t\t\t\t\t\trejects.set(keys[idx], result.reason);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t});\n\t\t\t\t\t\t// If we had rejections, notify our caller what they were.\n\t\t\t\t\t\tif (rejects.size > 0)\n\t\t\t\t\t\t\treject(rejects);\n\t\t\t\t\t\telse\n\t\t\t\t\t\t\tresolve(); // All good.\n\t\t\t\t\t});\n\t\t\t});\n\t\t};\n\t\tif (parentRecursion && this.parent instanceof Container) {\n\t\t\treturn this.parent.resolveSingletons(asyncOnly, parentRecursion).then(() => {\n\t\t\t\treturn makePromiseToResolve().then(() => this);\n\t\t\t});\n\t\t}\n\t\treturn makePromiseToResolve().then(() => this);\n\t}\n\n\t/**\n\t * As implied by the name prefix, this is a factored out method invoked only by the 'resolve' method.\n\t * It makes searching our parent (if it exists) easier (and quicker) IF our parent is a fellow instance of Container.\n\t */\n\tprotected resolveState<T>(id: InjectableId<T>): State<T> {\n\t\tconst provider = this.providers.get(id);\n\t\tif (!provider) {\n\t\t\tif (this.parent) {\n\t\t\t\tif (this.parent instanceof Container) {\n\t\t\t\t\treturn this.parent.resolveState<T>(id);\n\t\t\t\t}\n\t\t\t\t// This code (below) will only ever execute if the creator of this container passes in their own implementation of an Injector.\n\t\t\t\t/* istanbul ignore next */\n\t\t\t\ttry {\n\t\t\t\t\treturn State.MakeState<T>(this.parent.resolve<T>(id), undefined, undefined);\n\t\t\t\t}\n\t\t\t\tcatch (err) {\n\t\t\t\t\treturn State.MakeState<T>(null, err);\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn State.MakeState<T>(null, new Error('Symbol not bound: ' + id.toString()));\n\t\t}\n\t\treturn provider.provideAsState() as State<T>;\n\t}\n\n\t/**\n\t * Convenience method to assist in releasing non-garbage-collectable resources that Singletons in this Container may have allocated.\n\t * It will walk through all registered Providers (of this Container only), and invoke their Provider.releaseIfSingleton method.\n\t * This method is not part of the Injector interface, because you normally only create (and release) from Containers.\n\t * NOTE:\n\t * This *only* releases active/pending Singleton's that have already been created by this Container.\n\t * The most likely use of this method would be when you have created a new child Container for a limited-duration transaction, and you want to easily clean up temporary resources.\n\t * For example, your service object may need to know when it should unsubscribe from an RxJs stream (failure to do so can result in your Singleton not being garbage collected at the end of a transaction).\n\t * In theory, you could handle all unsubscription and cleanup yourself, but the @Release decorator and this method are meant to simply make that easier.\n\t */\n\tpublic releaseSingletons(): void {\n\t\tthis.providers.forEach((value: Provider) => {\n\t\t\tvalue.releaseIfSingleton();\n\t\t});\n\t}\n\n\t/**\n\t * Releases a Singleton instance if it exists.\n\t * However, it does **not** remove the binding, so if you call get or resolve (directly or indirectly) on the id, a new Singleton will be created.\n\t * If not a singleton, this method returns undefined.\n\t * If the singleton has been resolved, it is returned, otherwise null is returned.\n\t * If the singleton is pending resolution, a Promise for the singleton (or for null) is returned.\n\t * Note that if a singleton is returned, its Release method will already have been invoked.\n\t */\n\tpublic releaseSingleton<T>(id: InjectableId<T>): T | undefined | null | Promise<T | null> {\n\t\tconst provider = this.providers.get(id);\n\t\tif (provider)\n\t\t\treturn provider.releaseIfSingleton();\n\t\treturn undefined;\n\t}\n\n\t/**\n\t * Make a copy of this Container.\n\t * This is an experimental feature!\n\t * I have not thought through all the dark corners, so use at your own peril!\n\t * Here are some notes:\n\t * The injector parameter for SyncFactory and AsyncFactory callbacks will be the Container invoking the factory.\n\t * So a factory that uses a parent closure instead of the supplied injector may get unexpected results.\n\t * The injector parameter for OnSuccess and OnError callbacks will be the Container performing the resolution.\n\t * Singletons are cloned at their *existing* state..\n\t * If resolved in \"this\" container, they will not be re-resolved for the clone.\n\t * If released by the clone, they will be considered released by \"this\" container.\n\t * If a singleton is currently being asynchronously constructed any callbacks will reference \"this\" Container, however both Containers should have no problem awaiting resolution.\n\t * If a singleton is not resolved when the container is cloned, then if both containers resolve, you will create *two* \"singletons\".\n\t * The way to avoid this last effect is to call resolveSingletons first\n\t */\n\tclone(clazz?: ClassConstructor<Container>): Container {\n\t\tif (!clazz)\n\t\t\tclazz = Container;\n\t\tconst retVal = new clazz(this.parent);\n\t\tthis.providers.forEach((v, k) => {\n\t\t\tif (v instanceof BindableProvider) {\n\t\t\t\tv = Object.assign(Object.create(Object.getPrototypeOf(v)), v);\n\t\t\t\t(v as any).injector = retVal;\n\t\t\t}\n\t\t\tretVal.providers.set(k, v);\n\t\t});\n\t\treturn retVal;\n\t}\n}\n"]}
|
package/lib/cjs/decorators.js
CHANGED
|
@@ -1,11 +1,18 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.
|
|
4
|
-
|
|
3
|
+
exports.Injectable = Injectable;
|
|
4
|
+
exports.Inject = Inject;
|
|
5
|
+
exports._getInjectedIdAt = _getInjectedIdAt;
|
|
6
|
+
exports._getInjectedIdForMethod = _getInjectedIdForMethod;
|
|
7
|
+
exports.Optional = Optional;
|
|
8
|
+
exports._getOptionalDefaultAt = _getOptionalDefaultAt;
|
|
9
|
+
exports._getOptionalDefaultForMethod = _getOptionalDefaultForMethod;
|
|
10
|
+
exports.PostConstruct = PostConstruct;
|
|
11
|
+
exports.Release = Release;
|
|
5
12
|
/**
|
|
6
13
|
* These decorators all apply the information they collect (whether class, method, or parameter data) as tagged metadata on the class's constructor
|
|
7
14
|
*/
|
|
8
|
-
const
|
|
15
|
+
const constants_1 = require("./constants");
|
|
9
16
|
// Help user locate misapplied decorators.
|
|
10
17
|
function targetHint(target) {
|
|
11
18
|
let hint;
|
|
@@ -15,13 +22,11 @@ function targetHint(target) {
|
|
|
15
22
|
hint = target.constructor.name;
|
|
16
23
|
}
|
|
17
24
|
}
|
|
18
|
-
return hint;
|
|
25
|
+
return hint !== null && hint !== void 0 ? hint : '';
|
|
19
26
|
}
|
|
20
27
|
// Validate that 'target' is a class constructor function.
|
|
21
28
|
function isClassConstructor(target) {
|
|
22
|
-
// eslint-disable-next-line @typescript-eslint/no-unsafe-call, @typescript-eslint/no-unsafe-member-access
|
|
23
29
|
if (typeof target === 'function' && target.hasOwnProperty('prototype')) {
|
|
24
|
-
// eslint-disable-next-line @typescript-eslint/no-unsafe-member-access
|
|
25
30
|
return target.prototype.constructor === target;
|
|
26
31
|
}
|
|
27
32
|
return false;
|
|
@@ -30,6 +35,10 @@ function isClassConstructor(target) {
|
|
|
30
35
|
function makeParamIdxKey(idx) {
|
|
31
36
|
return `index-${idx}`;
|
|
32
37
|
}
|
|
38
|
+
// Key for @Inject/@Optional metadata stored on a method parameter.
|
|
39
|
+
function makeMethodParamIdxKey(methodName, idx) {
|
|
40
|
+
return `${String(methodName)}:index-${idx}`;
|
|
41
|
+
}
|
|
33
42
|
// Validate that the specified target is a parameter of a class constructor
|
|
34
43
|
function validateConstructorParam(decorator, target, idx) {
|
|
35
44
|
if (!isClassConstructor(target)) {
|
|
@@ -37,6 +46,16 @@ function validateConstructorParam(decorator, target, idx) {
|
|
|
37
46
|
}
|
|
38
47
|
return makeParamIdxKey(idx);
|
|
39
48
|
}
|
|
49
|
+
// Validate that the target is an instance method parameter (non-constructor).
|
|
50
|
+
function validateMethodParam(decorator, target, methodName, idx) {
|
|
51
|
+
if (typeof target !== 'object' || typeof target.constructor !== 'function') {
|
|
52
|
+
throw new Error('@' + decorator + ' is not valid here [' + targetHint(target) + ']');
|
|
53
|
+
}
|
|
54
|
+
if (!Reflect.hasOwnMetadata(constants_1.REFLECT_PARAMS, target, methodName)) {
|
|
55
|
+
// REFLECT_PARAMS not yet set (decoration order), so we cannot pre-validate the method; accept silently.
|
|
56
|
+
}
|
|
57
|
+
return makeMethodParamIdxKey(methodName, idx);
|
|
58
|
+
}
|
|
40
59
|
// Validate the decorator was only applied once.
|
|
41
60
|
function validateSingleConstructorParam(decorator, target, idx) {
|
|
42
61
|
const propKey = validateConstructorParam(decorator, target, idx);
|
|
@@ -55,23 +74,23 @@ function Injectable() {
|
|
|
55
74
|
* @returns Undefined (nothing), as this decorator does not modify the constructor in any way.
|
|
56
75
|
*/
|
|
57
76
|
return function (target) {
|
|
58
|
-
if (Reflect.hasOwnMetadata(
|
|
77
|
+
if (Reflect.hasOwnMetadata(constants_1.INJECTABLE_METADATA_KEY, target)) {
|
|
59
78
|
throw new Error('@Injectable applied multiple times [' + targetHint(target) + ']');
|
|
60
79
|
}
|
|
61
|
-
Reflect.defineMetadata(
|
|
80
|
+
Reflect.defineMetadata(constants_1.INJECTABLE_METADATA_KEY, true, target);
|
|
62
81
|
};
|
|
63
82
|
}
|
|
64
|
-
exports.Injectable = Injectable;
|
|
65
83
|
/**
|
|
66
|
-
* Placed just before a constructor parameter, this parameter decorator allows for specificity and control over the type of
|
|
84
|
+
* Placed just before a constructor parameter, this parameter decorator allows for specificity and control over the type of Object that will be injected into the parameter.
|
|
67
85
|
* In the absence of this decorator the container will use whatever is bound to a parameter's type (or throw an error if it is unable to recognize the type).
|
|
86
|
+
* This decorator may also be placed on a parameter of a method annotated with @PostConstruct, in which case the container will resolve and inject the value before invoking that method.
|
|
68
87
|
*
|
|
69
88
|
* @param id The identifier of the bound type that should be injected.
|
|
70
89
|
*/
|
|
71
90
|
function Inject(id) {
|
|
72
91
|
/**
|
|
73
|
-
* @param target The constructor function of the class (
|
|
74
|
-
* @param parameterName The name of the parameter
|
|
92
|
+
* @param target The constructor function of the class (for constructor params), or the class prototype (for method params).
|
|
93
|
+
* @param parameterName The name of the parameter (undefined for constructor params, the method name for method params)
|
|
75
94
|
* @param parameterIndex The ordinal index of the parameter in the function’s parameter list
|
|
76
95
|
* @returns Undefined (nothing), as this decorator does not modify the parameter in any way.
|
|
77
96
|
*/
|
|
@@ -79,11 +98,18 @@ function Inject(id) {
|
|
|
79
98
|
if (id === undefined) {
|
|
80
99
|
throw new Error('Undefined id passed to @Inject [' + targetHint(target) + ']');
|
|
81
100
|
}
|
|
82
|
-
|
|
83
|
-
|
|
101
|
+
if (parameterName === undefined) {
|
|
102
|
+
// Constructor parameter
|
|
103
|
+
const paramKey = validateSingleConstructorParam('Inject', target, parameterIndex);
|
|
104
|
+
Reflect.defineMetadata(constants_1.INJECT_METADATA_KEY, id, target, paramKey);
|
|
105
|
+
}
|
|
106
|
+
else {
|
|
107
|
+
// Method parameter — silently accepted (intended for @PostConstruct methods)
|
|
108
|
+
const paramKey = validateMethodParam('Inject', target, parameterName, parameterIndex);
|
|
109
|
+
Reflect.defineMetadata(constants_1.INJECT_METADATA_KEY, id, target, paramKey);
|
|
110
|
+
}
|
|
84
111
|
};
|
|
85
112
|
}
|
|
86
|
-
exports.Inject = Inject;
|
|
87
113
|
/**
|
|
88
114
|
* This is a helper function used by the container to retrieve the @Inject metadata for a specifically indexed constructor parameter
|
|
89
115
|
*
|
|
@@ -92,26 +118,39 @@ exports.Inject = Inject;
|
|
|
92
118
|
* @see Inject
|
|
93
119
|
*/
|
|
94
120
|
function _getInjectedIdAt(target, parameterIndex) {
|
|
95
|
-
return Reflect.getMetadata(
|
|
121
|
+
return Reflect.getMetadata(constants_1.INJECT_METADATA_KEY, target, makeParamIdxKey(parameterIndex));
|
|
122
|
+
}
|
|
123
|
+
/**
|
|
124
|
+
* Retrieve the @Inject metadata for a specifically indexed parameter of a named method.
|
|
125
|
+
*/
|
|
126
|
+
function _getInjectedIdForMethod(prototype, methodName, parameterIndex) {
|
|
127
|
+
return Reflect.getMetadata(constants_1.INJECT_METADATA_KEY, prototype, makeMethodParamIdxKey(methodName, parameterIndex));
|
|
96
128
|
}
|
|
97
|
-
exports._getInjectedIdAt = _getInjectedIdAt;
|
|
98
129
|
/**
|
|
99
130
|
* Placed just before a constructor parameter, this parameter decorator signals the container that it should supply the 'alt' constant value (undefined by default) if for *any* reason it is unable to otherwise resolve the type of the parameter.
|
|
131
|
+
* This decorator may also be placed on a parameter of a method annotated with @PostConstruct.
|
|
100
132
|
* WARNING! It is your responsibility to ensure that alt is of the appropriate type/value.
|
|
101
133
|
*/
|
|
102
134
|
function Optional(alt) {
|
|
103
135
|
/**
|
|
104
|
-
* @param target The constructor function of the class (
|
|
105
|
-
* @param parameterName The name of the parameter
|
|
136
|
+
* @param target The constructor function of the class (for constructor params), or the class prototype (for method params).
|
|
137
|
+
* @param parameterName The name of the parameter (undefined for constructor params, the method name for method params)
|
|
106
138
|
* @param parameterIndex The ordinal index of the parameter in the function’s parameter list
|
|
107
139
|
* @returns Undefined (nothing), as this decorator does not modify the parameter in any way.
|
|
108
140
|
*/
|
|
109
141
|
return function (target, parameterName, parameterIndex) {
|
|
110
|
-
|
|
111
|
-
|
|
142
|
+
if (parameterName === undefined) {
|
|
143
|
+
// Constructor parameter
|
|
144
|
+
const paramKey = validateSingleConstructorParam('Optional', target, parameterIndex);
|
|
145
|
+
Reflect.defineMetadata(constants_1.OPTIONAL_METADATA_KEY, { value: alt }, target, paramKey);
|
|
146
|
+
}
|
|
147
|
+
else {
|
|
148
|
+
// Method parameter — silently accepted (intended for @PostConstruct methods)
|
|
149
|
+
const paramKey = validateMethodParam('Optional', target, parameterName, parameterIndex);
|
|
150
|
+
Reflect.defineMetadata(constants_1.OPTIONAL_METADATA_KEY, { value: alt }, target, paramKey);
|
|
151
|
+
}
|
|
112
152
|
};
|
|
113
153
|
}
|
|
114
|
-
exports.Optional = Optional;
|
|
115
154
|
/**
|
|
116
155
|
* This is a helper function used by the container to retrieve the @Optional metadata for a specifically indexed constructor parameter
|
|
117
156
|
*
|
|
@@ -121,40 +160,43 @@ exports.Optional = Optional;
|
|
|
121
160
|
* @returns an object containing the value provided in the decorator, or undefined if no annotation was present.
|
|
122
161
|
*/
|
|
123
162
|
function _getOptionalDefaultAt(target, parameterIndex) {
|
|
124
|
-
return Reflect.getMetadata(
|
|
163
|
+
return Reflect.getMetadata(constants_1.OPTIONAL_METADATA_KEY, target, makeParamIdxKey(parameterIndex)); // See the @Optional decorator before making any changes here.
|
|
164
|
+
}
|
|
165
|
+
/**
|
|
166
|
+
* Retrieve the @Optional metadata for a specifically indexed parameter of a named method.
|
|
167
|
+
*/
|
|
168
|
+
function _getOptionalDefaultForMethod(prototype, methodName, parameterIndex) {
|
|
169
|
+
return Reflect.getMetadata(constants_1.OPTIONAL_METADATA_KEY, prototype, makeMethodParamIdxKey(methodName, parameterIndex));
|
|
125
170
|
}
|
|
126
|
-
exports._getOptionalDefaultAt = _getOptionalDefaultAt;
|
|
127
171
|
/**
|
|
128
172
|
* Placed just before a class method, this method decorator flags a method that should be called after an object has been instantiated by the container, but before it is put into service.
|
|
129
|
-
* The method will be assumed to be synchronous unless the method signature explicitly declares
|
|
173
|
+
* The method will be assumed to be synchronous unless the method signature explicitly declares its return type to be ": Promise<something>".
|
|
174
|
+
* Parameters will be resolved by the container just as they are for constructors.
|
|
130
175
|
* This decorator will throw if placed on a non-method or a static method of a class, or if placed on a method more than once, or if placed on more than one method for a class.
|
|
131
176
|
*/
|
|
132
177
|
function PostConstruct() {
|
|
133
178
|
/**
|
|
134
179
|
* @param prototypeOrConstructor The prototype of the class (we don't allow @PostConstruct on anything other than a class instance method.
|
|
135
180
|
* @param methodName The name of the method.
|
|
136
|
-
* @param
|
|
181
|
+
* @param _descriptor The Property Descriptor for the method.
|
|
137
182
|
* @returns Undefined (nothing), as this decorator does not modify the method in any way.
|
|
138
183
|
*/
|
|
139
|
-
|
|
140
|
-
return function (target, methodName, descriptor) {
|
|
184
|
+
return function (target, methodName, _descriptor) {
|
|
141
185
|
if (typeof target !== 'object' || typeof target.constructor !== 'function') {
|
|
142
186
|
throw new Error('@PostConstruct not applied to instance method [' + target.toString() + '/' + methodName.toString() + ']');
|
|
143
187
|
}
|
|
144
|
-
if (Reflect.hasOwnMetadata(
|
|
188
|
+
if (Reflect.hasOwnMetadata(constants_1.POSTCONSTRUCT_SYNC_METADATA_KEY, target.constructor) || Reflect.hasOwnMetadata(constants_1.POSTCONSTRUCT_ASYNC_METADATA_KEY, target.constructor)) {
|
|
145
189
|
throw new Error('@PostConstruct applied multiple times [' + targetHint(target.constructor) + ']');
|
|
146
190
|
}
|
|
147
|
-
const rt = Reflect.getMetadata(
|
|
191
|
+
const rt = Reflect.getMetadata(constants_1.REFLECT_RETURN, target, methodName);
|
|
148
192
|
if (typeof rt === 'function') {
|
|
149
|
-
Reflect.defineMetadata(
|
|
193
|
+
Reflect.defineMetadata(constants_1.POSTCONSTRUCT_ASYNC_METADATA_KEY, methodName, target.constructor);
|
|
150
194
|
}
|
|
151
195
|
else {
|
|
152
|
-
Reflect.defineMetadata(
|
|
196
|
+
Reflect.defineMetadata(constants_1.POSTCONSTRUCT_SYNC_METADATA_KEY, methodName, target.constructor);
|
|
153
197
|
}
|
|
154
198
|
};
|
|
155
199
|
}
|
|
156
|
-
exports.PostConstruct = PostConstruct;
|
|
157
|
-
// noinspection JSUnusedGlobalSymbols
|
|
158
200
|
/**
|
|
159
201
|
* Placed just before a class method, this decorator identifies a method which should be called when an object is removed from service.
|
|
160
202
|
* If invoked by the container, the container will drop any references it has to the object when the method returns.
|
|
@@ -171,19 +213,17 @@ function Release() {
|
|
|
171
213
|
/**
|
|
172
214
|
* @param prototypeOrConstructor The prototype of the class (we don't allow @Release on anything other than a class instance method.
|
|
173
215
|
* @param methodName The name of the method.
|
|
174
|
-
* @param
|
|
216
|
+
* @param _descriptor The Property Descriptor for the method.
|
|
175
217
|
* @returns Undefined (nothing), as this decorator does not modify the method in any way.
|
|
176
218
|
*/
|
|
177
|
-
|
|
178
|
-
return function (target, methodName, descriptor) {
|
|
219
|
+
return function (target, methodName, _descriptor) {
|
|
179
220
|
if (typeof target !== 'object' || typeof target.constructor !== 'function') {
|
|
180
221
|
throw new Error('@Release not applied to instance method [' + target.toString() + '/' + methodName.toString() + ']');
|
|
181
222
|
}
|
|
182
|
-
if (Reflect.hasOwnMetadata(
|
|
223
|
+
if (Reflect.hasOwnMetadata(constants_1.RELEASE_METADATA_KEY, target.constructor)) {
|
|
183
224
|
throw new Error('@Release applied multiple times [' + targetHint(target.constructor) + ']');
|
|
184
225
|
}
|
|
185
|
-
Reflect.defineMetadata(
|
|
226
|
+
Reflect.defineMetadata(constants_1.RELEASE_METADATA_KEY, methodName, target.constructor);
|
|
186
227
|
};
|
|
187
228
|
}
|
|
188
|
-
exports.Release = Release;
|
|
189
229
|
//# sourceMappingURL=decorators.js.map
|