proxydi 0.0.11 → 0.0.13
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/CHANGELOG.md +18 -2
- package/README.md +1 -0
- package/dist/ProxyDiContainer.d.ts +2 -7
- package/dist/index.cjs +154 -63
- package/dist/index.d.ts +2 -0
- package/dist/index.js +154 -64
- package/dist/index.umd.js +154 -63
- package/dist/inject.d.ts +2 -2
- package/dist/middleware/MiddlewareListener.d.ts +29 -0
- package/dist/middleware/middleware.d.ts +3 -0
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -5,11 +5,27 @@ All notable changes to this project will be documented in this file.
|
|
|
5
5
|
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
|
|
6
6
|
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
7
7
|
|
|
8
|
-
## [[0.0.
|
|
8
|
+
## [[0.0.13](https://www.npmjs.com/package/proxydi/v/0.0.13)] - 2025-03-04
|
|
9
9
|
|
|
10
10
|
### Added
|
|
11
11
|
|
|
12
|
-
-
|
|
12
|
+
- inject, resolve register by class [#15](https://github.com/proxy-di/proxydi/pull/15)
|
|
13
|
+
|
|
14
|
+
### Changed
|
|
15
|
+
|
|
16
|
+
- remove event requires dependency
|
|
17
|
+
|
|
18
|
+
## [[0.0.12](https://www.npmjs.com/package/proxydi/v/0.0.12)] - 2025-03-04
|
|
19
|
+
|
|
20
|
+
### Added
|
|
21
|
+
|
|
22
|
+
- Experimental @middleware [#14](https://github.com/proxy-di/proxydi/pull/14)
|
|
23
|
+
|
|
24
|
+
## [[0.0.11](https://www.npmjs.com/package/proxydi/v/0.0.11)] - 2025-03-03
|
|
25
|
+
|
|
26
|
+
### Added
|
|
27
|
+
|
|
28
|
+
- resolveInjectables() method [#13](https://github.com/proxy-di/proxydi/pull/13)
|
|
13
29
|
|
|
14
30
|
## [[0.0.10](https://www.npmjs.com/package/proxydi/v/0.0.10)] - 2025-03-02
|
|
15
31
|
|
package/README.md
CHANGED
|
@@ -17,6 +17,7 @@ Core features:
|
|
|
17
17
|
Eperimemntal features:
|
|
18
18
|
|
|
19
19
|
- Construtor injections (see unit tests for examples)
|
|
20
|
+
- Middleware listeners (see unit tests for examples)
|
|
20
21
|
- Matches dependencies by unique identifiers or automatically using class names and property names
|
|
21
22
|
|
|
22
23
|
## Quick start
|
|
@@ -29,6 +29,7 @@ export declare class ProxyDiContainer implements IProxyDiContainer {
|
|
|
29
29
|
* Settings that control the behavior of the container and it's children
|
|
30
30
|
*/
|
|
31
31
|
readonly settings: Required<ContainerSettings>;
|
|
32
|
+
private middlewareListener;
|
|
32
33
|
/**
|
|
33
34
|
* Creates a new instance of ProxyDiContainer.
|
|
34
35
|
* @param settings Optional container settings to override defaults.
|
|
@@ -44,15 +45,9 @@ export declare class ProxyDiContainer implements IProxyDiContainer {
|
|
|
44
45
|
* @throws Error if dependency is already registered and rewriting is not allowed or if invalid dependency (not object) is provided and this it now allowed.
|
|
45
46
|
* @returns Dependency instance, registered in container
|
|
46
47
|
*/
|
|
47
|
-
register<T>(DependencyClass: DependencyClass<T>, dependencyId
|
|
48
|
+
register<T>(DependencyClass: DependencyClass<T>, dependencyId?: DependencyId): T & ContainerizedDependency;
|
|
48
49
|
register<T>(dependency: T extends new (...args: any[]) => any ? never : T, dependencyId: DependencyId): T & ContainerizedDependency;
|
|
49
50
|
private createInstance;
|
|
50
|
-
/**
|
|
51
|
-
* Internal method that implements registeration of dependency and prepare it for injection.
|
|
52
|
-
* @param dependencyId The unique identifier of the dependency.
|
|
53
|
-
* @param dependency The dependency instance.
|
|
54
|
-
*/
|
|
55
|
-
private registerImpl;
|
|
56
51
|
/**
|
|
57
52
|
* Checks if a dependency with the given ID is known to the container or its ancestors which means that it can be resolved by this container
|
|
58
53
|
* @param dependencyId The identifier of the dependency.
|
package/dist/index.cjs
CHANGED
|
@@ -1,5 +1,40 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
+
const injectableClasses = {};
|
|
4
|
+
const constructorInjections = {};
|
|
5
|
+
function injectable(dependencyOrDependencies, autoInjecions) {
|
|
6
|
+
return function (value, context) {
|
|
7
|
+
if ((context === null || context === undefined ? undefined : context.kind) !== 'class') {
|
|
8
|
+
throw new Error('@injectable decorator should decorate classes');
|
|
9
|
+
}
|
|
10
|
+
const name = dependencyOrDependencies
|
|
11
|
+
? Array.isArray(dependencyOrDependencies)
|
|
12
|
+
? context.name
|
|
13
|
+
: dependencyOrDependencies
|
|
14
|
+
: context.name;
|
|
15
|
+
const injectToConstructor = dependencyOrDependencies
|
|
16
|
+
? Array.isArray(dependencyOrDependencies)
|
|
17
|
+
? dependencyOrDependencies
|
|
18
|
+
: autoInjecions
|
|
19
|
+
: autoInjecions;
|
|
20
|
+
if (injectableClasses[name]) {
|
|
21
|
+
throw new Error(`ProxyDi has already regisered dependency ${String(name)} by @injectable`);
|
|
22
|
+
}
|
|
23
|
+
injectableClasses[name] = value;
|
|
24
|
+
if (injectToConstructor) {
|
|
25
|
+
constructorInjections[name] = injectToConstructor;
|
|
26
|
+
}
|
|
27
|
+
};
|
|
28
|
+
}
|
|
29
|
+
function findInjectableId(injectable) {
|
|
30
|
+
for (const [id, DependencyClass] of Object.entries(injectableClasses)) {
|
|
31
|
+
if (DependencyClass === injectable) {
|
|
32
|
+
return id;
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
throw new Error(`Class is not @injectable: ${injectable.name}`);
|
|
36
|
+
}
|
|
37
|
+
|
|
3
38
|
const INJECTIONS = Symbol('injections');
|
|
4
39
|
/**
|
|
5
40
|
* This symbol constant defines a property name.
|
|
@@ -28,7 +63,11 @@ const IS_INSTANCE_PROXY = Symbol('isInstanceProxy');
|
|
|
28
63
|
const inject = (dependencyId) => {
|
|
29
64
|
return function (_value, context) {
|
|
30
65
|
if ((context === null || context === undefined ? undefined : context.kind) === 'field') {
|
|
31
|
-
const id = dependencyId
|
|
66
|
+
const id = dependencyId
|
|
67
|
+
? typeof dependencyId === 'function'
|
|
68
|
+
? findInjectableId(dependencyId)
|
|
69
|
+
: dependencyId
|
|
70
|
+
: context.name;
|
|
32
71
|
const injection = {
|
|
33
72
|
property: context.name,
|
|
34
73
|
dependencyId: id,
|
|
@@ -47,41 +86,6 @@ const inject = (dependencyId) => {
|
|
|
47
86
|
};
|
|
48
87
|
};
|
|
49
88
|
|
|
50
|
-
const injectableClasses = {};
|
|
51
|
-
const constructorInjections = {};
|
|
52
|
-
function injectable(dependencyOrDependencies, autoInjecions) {
|
|
53
|
-
return function (value, context) {
|
|
54
|
-
if ((context === null || context === undefined ? undefined : context.kind) !== 'class') {
|
|
55
|
-
throw new Error('@injectable decorator should decorate classes');
|
|
56
|
-
}
|
|
57
|
-
const name = dependencyOrDependencies
|
|
58
|
-
? Array.isArray(dependencyOrDependencies)
|
|
59
|
-
? context.name
|
|
60
|
-
: dependencyOrDependencies
|
|
61
|
-
: context.name;
|
|
62
|
-
const injectToConstructor = dependencyOrDependencies
|
|
63
|
-
? Array.isArray(dependencyOrDependencies)
|
|
64
|
-
? dependencyOrDependencies
|
|
65
|
-
: autoInjecions
|
|
66
|
-
: autoInjecions;
|
|
67
|
-
if (injectableClasses[name]) {
|
|
68
|
-
throw new Error(`ProxyDi has already regisered dependency ${String(name)} by @injectable`);
|
|
69
|
-
}
|
|
70
|
-
injectableClasses[name] = value;
|
|
71
|
-
if (injectToConstructor) {
|
|
72
|
-
constructorInjections[name] = injectToConstructor;
|
|
73
|
-
}
|
|
74
|
-
};
|
|
75
|
-
}
|
|
76
|
-
function findInjectableId(injectable) {
|
|
77
|
-
for (const [id, DependencyClass] of Object.entries(injectableClasses)) {
|
|
78
|
-
if (DependencyClass === injectable) {
|
|
79
|
-
return id;
|
|
80
|
-
}
|
|
81
|
-
}
|
|
82
|
-
throw new Error(`Class is not @injectable: ${injectable.name}`);
|
|
83
|
-
}
|
|
84
|
-
|
|
85
89
|
const DEFAULT_SETTINGS = {
|
|
86
90
|
allowRegisterAnything: false,
|
|
87
91
|
allowRewriteDependencies: false,
|
|
@@ -190,6 +194,72 @@ function makeConstructorDependencyProxy(container, dependencyId) {
|
|
|
190
194
|
});
|
|
191
195
|
}
|
|
192
196
|
|
|
197
|
+
const middlewaresClasses = {};
|
|
198
|
+
function middleware() {
|
|
199
|
+
return function (value, context) {
|
|
200
|
+
if ((context === null || context === undefined ? undefined : context.kind) !== 'class') {
|
|
201
|
+
throw new Error('@middleware decorator should decorate classes');
|
|
202
|
+
}
|
|
203
|
+
const name = context.name;
|
|
204
|
+
if (middlewaresClasses[name]) {
|
|
205
|
+
throw new Error(`ProxyDi has already regisered middleware ${String(name)} by @middleware`);
|
|
206
|
+
}
|
|
207
|
+
middlewaresClasses[name] = value;
|
|
208
|
+
};
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
class MiddlewareListener {
|
|
212
|
+
constructor(parent) {
|
|
213
|
+
this.parent = parent;
|
|
214
|
+
this.listeners = {
|
|
215
|
+
register: [],
|
|
216
|
+
remove: [],
|
|
217
|
+
};
|
|
218
|
+
}
|
|
219
|
+
add(middleware) {
|
|
220
|
+
if (isRegistingMiddleware(middleware)) {
|
|
221
|
+
middleware.onRegister && this.on('register', middleware.onRegister);
|
|
222
|
+
}
|
|
223
|
+
if (isRemovingMiddleware(middleware)) {
|
|
224
|
+
middleware.onRemove && this.on('remove', middleware.onRemove);
|
|
225
|
+
}
|
|
226
|
+
}
|
|
227
|
+
remove(middleware) {
|
|
228
|
+
if (isRegistingMiddleware(middleware)) {
|
|
229
|
+
middleware.onRegister &&
|
|
230
|
+
this.off('register', middleware.onRegister);
|
|
231
|
+
}
|
|
232
|
+
if (isRemovingMiddleware(middleware)) {
|
|
233
|
+
middleware.onRemove && this.off('remove', middleware.onRemove);
|
|
234
|
+
}
|
|
235
|
+
}
|
|
236
|
+
on(event, listener) {
|
|
237
|
+
this.listeners[event].push(listener);
|
|
238
|
+
}
|
|
239
|
+
onRegister(container, dependencyId, dependency) {
|
|
240
|
+
var _a;
|
|
241
|
+
this.listeners.register.forEach((listener) => listener(container, dependencyId, dependency));
|
|
242
|
+
(_a = this.parent) === null || _a === undefined ? undefined : _a.onRegister(container, dependencyId, dependency);
|
|
243
|
+
}
|
|
244
|
+
onRemove(container, dependencyId, dependency) {
|
|
245
|
+
var _a;
|
|
246
|
+
this.listeners.remove.forEach((listener) => listener(container, dependencyId, dependency));
|
|
247
|
+
(_a = this.parent) === null || _a === undefined ? undefined : _a.onRemove(container, dependencyId, dependency);
|
|
248
|
+
}
|
|
249
|
+
off(event, listener) {
|
|
250
|
+
const index = this.listeners[event].indexOf(listener);
|
|
251
|
+
if (index !== -1) {
|
|
252
|
+
this.listeners[event].splice(index, 1);
|
|
253
|
+
}
|
|
254
|
+
}
|
|
255
|
+
}
|
|
256
|
+
function isRegistingMiddleware(middleware) {
|
|
257
|
+
return middleware.onRegister;
|
|
258
|
+
}
|
|
259
|
+
function isRemovingMiddleware(middleware) {
|
|
260
|
+
return middleware.onRemove;
|
|
261
|
+
}
|
|
262
|
+
|
|
193
263
|
/**
|
|
194
264
|
* A dependency injection container
|
|
195
265
|
*/
|
|
@@ -210,35 +280,55 @@ class ProxyDiContainer {
|
|
|
210
280
|
*/
|
|
211
281
|
this.parentDependencyProxies = {};
|
|
212
282
|
this.id = ProxyDiContainer.idCounter++;
|
|
283
|
+
this.middlewareListener = new MiddlewareListener(parent === null || parent === undefined ? undefined : parent.middlewareListener);
|
|
213
284
|
if (parent) {
|
|
214
285
|
this.parent = parent;
|
|
215
286
|
this.parent.addChild(this);
|
|
216
287
|
}
|
|
217
288
|
this.settings = Object.assign(Object.assign({}, DEFAULT_SETTINGS), settings);
|
|
218
289
|
}
|
|
219
|
-
register(dependency,
|
|
220
|
-
|
|
290
|
+
register(dependency, dependecyId) {
|
|
291
|
+
var _a;
|
|
292
|
+
let id = dependecyId;
|
|
293
|
+
if (!id) {
|
|
294
|
+
if (typeof dependency === 'function') {
|
|
295
|
+
try {
|
|
296
|
+
id = findInjectableId(dependency);
|
|
297
|
+
}
|
|
298
|
+
catch (_b) {
|
|
299
|
+
id = dependency.name;
|
|
300
|
+
}
|
|
301
|
+
}
|
|
302
|
+
}
|
|
303
|
+
if (this.dependencies[id]) {
|
|
221
304
|
if (!this.settings.allowRewriteDependencies) {
|
|
222
|
-
throw new Error(`ProxyDi already has dependency for ${String(
|
|
305
|
+
throw new Error(`ProxyDi already has dependency for ${String(id)}`);
|
|
223
306
|
}
|
|
224
307
|
}
|
|
225
|
-
let
|
|
308
|
+
let instance;
|
|
226
309
|
const isClass = typeof dependency === 'function';
|
|
227
310
|
if (isClass) {
|
|
228
|
-
|
|
311
|
+
instance = this.createInstance(dependency, id);
|
|
229
312
|
}
|
|
230
313
|
else {
|
|
231
|
-
|
|
232
|
-
if (!(typeof dependencyInstance === 'object') &&
|
|
233
|
-
!this.settings.allowRegisterAnything) {
|
|
234
|
-
throw new Error(`Can't register as dependency (allowRegisterAnything is off for this contatiner): ${dependencyInstance}`);
|
|
235
|
-
}
|
|
314
|
+
instance = dependency;
|
|
236
315
|
}
|
|
237
|
-
|
|
238
|
-
|
|
316
|
+
const isObject = typeof instance === 'object';
|
|
317
|
+
if (!isObject && !this.settings.allowRegisterAnything) {
|
|
318
|
+
throw new Error(`Can't register as dependency (allowRegisterAnything is off for this contatiner): ${instance}`);
|
|
239
319
|
}
|
|
240
|
-
|
|
241
|
-
|
|
320
|
+
if (isObject) {
|
|
321
|
+
instance[PROXYDI_CONTAINER] = this;
|
|
322
|
+
instance[DEPENDENCY_ID] = id;
|
|
323
|
+
}
|
|
324
|
+
this.injectDependenciesTo(instance);
|
|
325
|
+
this.dependencies[id] = instance;
|
|
326
|
+
const constructorName = (_a = instance.constructor) === null || _a === undefined ? undefined : _a.name;
|
|
327
|
+
if (constructorName && middlewaresClasses[constructorName]) {
|
|
328
|
+
this.middlewareListener.add(instance);
|
|
329
|
+
}
|
|
330
|
+
this.middlewareListener.onRegister(this, id, instance);
|
|
331
|
+
return instance;
|
|
242
332
|
}
|
|
243
333
|
createInstance(Dependency, dependencyId) {
|
|
244
334
|
const paramIds = constructorInjections[dependencyId] || [];
|
|
@@ -249,18 +339,6 @@ class ProxyDiContainer {
|
|
|
249
339
|
}
|
|
250
340
|
return new Dependency(...params);
|
|
251
341
|
}
|
|
252
|
-
/**
|
|
253
|
-
* Internal method that implements registeration of dependency and prepare it for injection.
|
|
254
|
-
* @param dependencyId The unique identifier of the dependency.
|
|
255
|
-
* @param dependency The dependency instance.
|
|
256
|
-
*/
|
|
257
|
-
registerImpl(dependency, dependencyId) {
|
|
258
|
-
this.injectDependenciesTo(dependency);
|
|
259
|
-
if (typeof dependency === 'object') {
|
|
260
|
-
dependency[DEPENDENCY_ID] = dependencyId;
|
|
261
|
-
}
|
|
262
|
-
this.dependencies[dependencyId] = dependency;
|
|
263
|
-
}
|
|
264
342
|
/**
|
|
265
343
|
* Checks if a dependency with the given ID is known to the container or its ancestors which means that it can be resolved by this container
|
|
266
344
|
* @param dependencyId The identifier of the dependency.
|
|
@@ -274,7 +352,13 @@ class ProxyDiContainer {
|
|
|
274
352
|
}
|
|
275
353
|
resolve(dependency) {
|
|
276
354
|
if (typeof dependency === 'function') {
|
|
277
|
-
|
|
355
|
+
let id;
|
|
356
|
+
try {
|
|
357
|
+
id = findInjectableId(dependency);
|
|
358
|
+
}
|
|
359
|
+
catch (_a) {
|
|
360
|
+
id = dependency.name;
|
|
361
|
+
}
|
|
278
362
|
return this.resolve(id);
|
|
279
363
|
}
|
|
280
364
|
if (!this.isKnown(dependency)) {
|
|
@@ -349,11 +433,16 @@ class ProxyDiContainer {
|
|
|
349
433
|
* @param dependencyOrId The dependency instance or dependency identifier to remove.
|
|
350
434
|
*/
|
|
351
435
|
remove(dependencyOrId) {
|
|
436
|
+
var _a;
|
|
352
437
|
const id = isDependency(dependencyOrId)
|
|
353
438
|
? dependencyOrId[DEPENDENCY_ID]
|
|
354
439
|
: dependencyOrId;
|
|
355
440
|
const dependency = this.dependencies[id];
|
|
356
441
|
if (dependency) {
|
|
442
|
+
const constructorName = (_a = dependency.constructor) === null || _a === undefined ? undefined : _a.name;
|
|
443
|
+
if (constructorName && middlewaresClasses[constructorName]) {
|
|
444
|
+
this.middlewareListener.remove(dependency);
|
|
445
|
+
}
|
|
357
446
|
const dependencyInjects = dependency[INJECTIONS]
|
|
358
447
|
? dependency[INJECTIONS]
|
|
359
448
|
: {};
|
|
@@ -362,6 +451,7 @@ class ProxyDiContainer {
|
|
|
362
451
|
});
|
|
363
452
|
delete dependency[DEPENDENCY_ID];
|
|
364
453
|
delete this.dependencies[id];
|
|
454
|
+
this.middlewareListener.onRemove(this, id, dependency);
|
|
365
455
|
}
|
|
366
456
|
}
|
|
367
457
|
/**
|
|
@@ -477,4 +567,5 @@ exports.PROXYDI_CONTAINER = PROXYDI_CONTAINER;
|
|
|
477
567
|
exports.ProxyDiContainer = ProxyDiContainer;
|
|
478
568
|
exports.inject = inject;
|
|
479
569
|
exports.injectable = injectable;
|
|
570
|
+
exports.middleware = middleware;
|
|
480
571
|
exports.resolveAll = resolveAll;
|
package/dist/index.d.ts
CHANGED
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
export { inject } from './inject';
|
|
2
2
|
export { ProxyDiContainer } from './ProxyDiContainer';
|
|
3
3
|
export { injectable } from './injectable';
|
|
4
|
+
export { middleware } from './middleware/middleware';
|
|
5
|
+
export { MiddlewareRegisteringListener, MiddlewareRemovingListener, } from './middleware/MiddlewareListener';
|
|
4
6
|
export { Injection, DependencyId, DependencyClass, ContainerSettings, PROXYDI_CONTAINER, DEPENDENCY_ID, } from './types';
|
|
5
7
|
export { resolveAll } from './resolveAll';
|
package/dist/index.js
CHANGED
|
@@ -1,3 +1,38 @@
|
|
|
1
|
+
const injectableClasses = {};
|
|
2
|
+
const constructorInjections = {};
|
|
3
|
+
function injectable(dependencyOrDependencies, autoInjecions) {
|
|
4
|
+
return function (value, context) {
|
|
5
|
+
if ((context === null || context === undefined ? undefined : context.kind) !== 'class') {
|
|
6
|
+
throw new Error('@injectable decorator should decorate classes');
|
|
7
|
+
}
|
|
8
|
+
const name = dependencyOrDependencies
|
|
9
|
+
? Array.isArray(dependencyOrDependencies)
|
|
10
|
+
? context.name
|
|
11
|
+
: dependencyOrDependencies
|
|
12
|
+
: context.name;
|
|
13
|
+
const injectToConstructor = dependencyOrDependencies
|
|
14
|
+
? Array.isArray(dependencyOrDependencies)
|
|
15
|
+
? dependencyOrDependencies
|
|
16
|
+
: autoInjecions
|
|
17
|
+
: autoInjecions;
|
|
18
|
+
if (injectableClasses[name]) {
|
|
19
|
+
throw new Error(`ProxyDi has already regisered dependency ${String(name)} by @injectable`);
|
|
20
|
+
}
|
|
21
|
+
injectableClasses[name] = value;
|
|
22
|
+
if (injectToConstructor) {
|
|
23
|
+
constructorInjections[name] = injectToConstructor;
|
|
24
|
+
}
|
|
25
|
+
};
|
|
26
|
+
}
|
|
27
|
+
function findInjectableId(injectable) {
|
|
28
|
+
for (const [id, DependencyClass] of Object.entries(injectableClasses)) {
|
|
29
|
+
if (DependencyClass === injectable) {
|
|
30
|
+
return id;
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
throw new Error(`Class is not @injectable: ${injectable.name}`);
|
|
34
|
+
}
|
|
35
|
+
|
|
1
36
|
const INJECTIONS = Symbol('injections');
|
|
2
37
|
/**
|
|
3
38
|
* This symbol constant defines a property name.
|
|
@@ -26,7 +61,11 @@ const IS_INSTANCE_PROXY = Symbol('isInstanceProxy');
|
|
|
26
61
|
const inject = (dependencyId) => {
|
|
27
62
|
return function (_value, context) {
|
|
28
63
|
if ((context === null || context === undefined ? undefined : context.kind) === 'field') {
|
|
29
|
-
const id = dependencyId
|
|
64
|
+
const id = dependencyId
|
|
65
|
+
? typeof dependencyId === 'function'
|
|
66
|
+
? findInjectableId(dependencyId)
|
|
67
|
+
: dependencyId
|
|
68
|
+
: context.name;
|
|
30
69
|
const injection = {
|
|
31
70
|
property: context.name,
|
|
32
71
|
dependencyId: id,
|
|
@@ -45,41 +84,6 @@ const inject = (dependencyId) => {
|
|
|
45
84
|
};
|
|
46
85
|
};
|
|
47
86
|
|
|
48
|
-
const injectableClasses = {};
|
|
49
|
-
const constructorInjections = {};
|
|
50
|
-
function injectable(dependencyOrDependencies, autoInjecions) {
|
|
51
|
-
return function (value, context) {
|
|
52
|
-
if ((context === null || context === undefined ? undefined : context.kind) !== 'class') {
|
|
53
|
-
throw new Error('@injectable decorator should decorate classes');
|
|
54
|
-
}
|
|
55
|
-
const name = dependencyOrDependencies
|
|
56
|
-
? Array.isArray(dependencyOrDependencies)
|
|
57
|
-
? context.name
|
|
58
|
-
: dependencyOrDependencies
|
|
59
|
-
: context.name;
|
|
60
|
-
const injectToConstructor = dependencyOrDependencies
|
|
61
|
-
? Array.isArray(dependencyOrDependencies)
|
|
62
|
-
? dependencyOrDependencies
|
|
63
|
-
: autoInjecions
|
|
64
|
-
: autoInjecions;
|
|
65
|
-
if (injectableClasses[name]) {
|
|
66
|
-
throw new Error(`ProxyDi has already regisered dependency ${String(name)} by @injectable`);
|
|
67
|
-
}
|
|
68
|
-
injectableClasses[name] = value;
|
|
69
|
-
if (injectToConstructor) {
|
|
70
|
-
constructorInjections[name] = injectToConstructor;
|
|
71
|
-
}
|
|
72
|
-
};
|
|
73
|
-
}
|
|
74
|
-
function findInjectableId(injectable) {
|
|
75
|
-
for (const [id, DependencyClass] of Object.entries(injectableClasses)) {
|
|
76
|
-
if (DependencyClass === injectable) {
|
|
77
|
-
return id;
|
|
78
|
-
}
|
|
79
|
-
}
|
|
80
|
-
throw new Error(`Class is not @injectable: ${injectable.name}`);
|
|
81
|
-
}
|
|
82
|
-
|
|
83
87
|
const DEFAULT_SETTINGS = {
|
|
84
88
|
allowRegisterAnything: false,
|
|
85
89
|
allowRewriteDependencies: false,
|
|
@@ -188,6 +192,72 @@ function makeConstructorDependencyProxy(container, dependencyId) {
|
|
|
188
192
|
});
|
|
189
193
|
}
|
|
190
194
|
|
|
195
|
+
const middlewaresClasses = {};
|
|
196
|
+
function middleware() {
|
|
197
|
+
return function (value, context) {
|
|
198
|
+
if ((context === null || context === undefined ? undefined : context.kind) !== 'class') {
|
|
199
|
+
throw new Error('@middleware decorator should decorate classes');
|
|
200
|
+
}
|
|
201
|
+
const name = context.name;
|
|
202
|
+
if (middlewaresClasses[name]) {
|
|
203
|
+
throw new Error(`ProxyDi has already regisered middleware ${String(name)} by @middleware`);
|
|
204
|
+
}
|
|
205
|
+
middlewaresClasses[name] = value;
|
|
206
|
+
};
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
class MiddlewareListener {
|
|
210
|
+
constructor(parent) {
|
|
211
|
+
this.parent = parent;
|
|
212
|
+
this.listeners = {
|
|
213
|
+
register: [],
|
|
214
|
+
remove: [],
|
|
215
|
+
};
|
|
216
|
+
}
|
|
217
|
+
add(middleware) {
|
|
218
|
+
if (isRegistingMiddleware(middleware)) {
|
|
219
|
+
middleware.onRegister && this.on('register', middleware.onRegister);
|
|
220
|
+
}
|
|
221
|
+
if (isRemovingMiddleware(middleware)) {
|
|
222
|
+
middleware.onRemove && this.on('remove', middleware.onRemove);
|
|
223
|
+
}
|
|
224
|
+
}
|
|
225
|
+
remove(middleware) {
|
|
226
|
+
if (isRegistingMiddleware(middleware)) {
|
|
227
|
+
middleware.onRegister &&
|
|
228
|
+
this.off('register', middleware.onRegister);
|
|
229
|
+
}
|
|
230
|
+
if (isRemovingMiddleware(middleware)) {
|
|
231
|
+
middleware.onRemove && this.off('remove', middleware.onRemove);
|
|
232
|
+
}
|
|
233
|
+
}
|
|
234
|
+
on(event, listener) {
|
|
235
|
+
this.listeners[event].push(listener);
|
|
236
|
+
}
|
|
237
|
+
onRegister(container, dependencyId, dependency) {
|
|
238
|
+
var _a;
|
|
239
|
+
this.listeners.register.forEach((listener) => listener(container, dependencyId, dependency));
|
|
240
|
+
(_a = this.parent) === null || _a === undefined ? undefined : _a.onRegister(container, dependencyId, dependency);
|
|
241
|
+
}
|
|
242
|
+
onRemove(container, dependencyId, dependency) {
|
|
243
|
+
var _a;
|
|
244
|
+
this.listeners.remove.forEach((listener) => listener(container, dependencyId, dependency));
|
|
245
|
+
(_a = this.parent) === null || _a === undefined ? undefined : _a.onRemove(container, dependencyId, dependency);
|
|
246
|
+
}
|
|
247
|
+
off(event, listener) {
|
|
248
|
+
const index = this.listeners[event].indexOf(listener);
|
|
249
|
+
if (index !== -1) {
|
|
250
|
+
this.listeners[event].splice(index, 1);
|
|
251
|
+
}
|
|
252
|
+
}
|
|
253
|
+
}
|
|
254
|
+
function isRegistingMiddleware(middleware) {
|
|
255
|
+
return middleware.onRegister;
|
|
256
|
+
}
|
|
257
|
+
function isRemovingMiddleware(middleware) {
|
|
258
|
+
return middleware.onRemove;
|
|
259
|
+
}
|
|
260
|
+
|
|
191
261
|
/**
|
|
192
262
|
* A dependency injection container
|
|
193
263
|
*/
|
|
@@ -208,35 +278,55 @@ class ProxyDiContainer {
|
|
|
208
278
|
*/
|
|
209
279
|
this.parentDependencyProxies = {};
|
|
210
280
|
this.id = ProxyDiContainer.idCounter++;
|
|
281
|
+
this.middlewareListener = new MiddlewareListener(parent === null || parent === undefined ? undefined : parent.middlewareListener);
|
|
211
282
|
if (parent) {
|
|
212
283
|
this.parent = parent;
|
|
213
284
|
this.parent.addChild(this);
|
|
214
285
|
}
|
|
215
286
|
this.settings = Object.assign(Object.assign({}, DEFAULT_SETTINGS), settings);
|
|
216
287
|
}
|
|
217
|
-
register(dependency,
|
|
218
|
-
|
|
288
|
+
register(dependency, dependecyId) {
|
|
289
|
+
var _a;
|
|
290
|
+
let id = dependecyId;
|
|
291
|
+
if (!id) {
|
|
292
|
+
if (typeof dependency === 'function') {
|
|
293
|
+
try {
|
|
294
|
+
id = findInjectableId(dependency);
|
|
295
|
+
}
|
|
296
|
+
catch (_b) {
|
|
297
|
+
id = dependency.name;
|
|
298
|
+
}
|
|
299
|
+
}
|
|
300
|
+
}
|
|
301
|
+
if (this.dependencies[id]) {
|
|
219
302
|
if (!this.settings.allowRewriteDependencies) {
|
|
220
|
-
throw new Error(`ProxyDi already has dependency for ${String(
|
|
303
|
+
throw new Error(`ProxyDi already has dependency for ${String(id)}`);
|
|
221
304
|
}
|
|
222
305
|
}
|
|
223
|
-
let
|
|
306
|
+
let instance;
|
|
224
307
|
const isClass = typeof dependency === 'function';
|
|
225
308
|
if (isClass) {
|
|
226
|
-
|
|
309
|
+
instance = this.createInstance(dependency, id);
|
|
227
310
|
}
|
|
228
311
|
else {
|
|
229
|
-
|
|
230
|
-
if (!(typeof dependencyInstance === 'object') &&
|
|
231
|
-
!this.settings.allowRegisterAnything) {
|
|
232
|
-
throw new Error(`Can't register as dependency (allowRegisterAnything is off for this contatiner): ${dependencyInstance}`);
|
|
233
|
-
}
|
|
312
|
+
instance = dependency;
|
|
234
313
|
}
|
|
235
|
-
|
|
236
|
-
|
|
314
|
+
const isObject = typeof instance === 'object';
|
|
315
|
+
if (!isObject && !this.settings.allowRegisterAnything) {
|
|
316
|
+
throw new Error(`Can't register as dependency (allowRegisterAnything is off for this contatiner): ${instance}`);
|
|
237
317
|
}
|
|
238
|
-
|
|
239
|
-
|
|
318
|
+
if (isObject) {
|
|
319
|
+
instance[PROXYDI_CONTAINER] = this;
|
|
320
|
+
instance[DEPENDENCY_ID] = id;
|
|
321
|
+
}
|
|
322
|
+
this.injectDependenciesTo(instance);
|
|
323
|
+
this.dependencies[id] = instance;
|
|
324
|
+
const constructorName = (_a = instance.constructor) === null || _a === undefined ? undefined : _a.name;
|
|
325
|
+
if (constructorName && middlewaresClasses[constructorName]) {
|
|
326
|
+
this.middlewareListener.add(instance);
|
|
327
|
+
}
|
|
328
|
+
this.middlewareListener.onRegister(this, id, instance);
|
|
329
|
+
return instance;
|
|
240
330
|
}
|
|
241
331
|
createInstance(Dependency, dependencyId) {
|
|
242
332
|
const paramIds = constructorInjections[dependencyId] || [];
|
|
@@ -247,18 +337,6 @@ class ProxyDiContainer {
|
|
|
247
337
|
}
|
|
248
338
|
return new Dependency(...params);
|
|
249
339
|
}
|
|
250
|
-
/**
|
|
251
|
-
* Internal method that implements registeration of dependency and prepare it for injection.
|
|
252
|
-
* @param dependencyId The unique identifier of the dependency.
|
|
253
|
-
* @param dependency The dependency instance.
|
|
254
|
-
*/
|
|
255
|
-
registerImpl(dependency, dependencyId) {
|
|
256
|
-
this.injectDependenciesTo(dependency);
|
|
257
|
-
if (typeof dependency === 'object') {
|
|
258
|
-
dependency[DEPENDENCY_ID] = dependencyId;
|
|
259
|
-
}
|
|
260
|
-
this.dependencies[dependencyId] = dependency;
|
|
261
|
-
}
|
|
262
340
|
/**
|
|
263
341
|
* Checks if a dependency with the given ID is known to the container or its ancestors which means that it can be resolved by this container
|
|
264
342
|
* @param dependencyId The identifier of the dependency.
|
|
@@ -272,7 +350,13 @@ class ProxyDiContainer {
|
|
|
272
350
|
}
|
|
273
351
|
resolve(dependency) {
|
|
274
352
|
if (typeof dependency === 'function') {
|
|
275
|
-
|
|
353
|
+
let id;
|
|
354
|
+
try {
|
|
355
|
+
id = findInjectableId(dependency);
|
|
356
|
+
}
|
|
357
|
+
catch (_a) {
|
|
358
|
+
id = dependency.name;
|
|
359
|
+
}
|
|
276
360
|
return this.resolve(id);
|
|
277
361
|
}
|
|
278
362
|
if (!this.isKnown(dependency)) {
|
|
@@ -347,11 +431,16 @@ class ProxyDiContainer {
|
|
|
347
431
|
* @param dependencyOrId The dependency instance or dependency identifier to remove.
|
|
348
432
|
*/
|
|
349
433
|
remove(dependencyOrId) {
|
|
434
|
+
var _a;
|
|
350
435
|
const id = isDependency(dependencyOrId)
|
|
351
436
|
? dependencyOrId[DEPENDENCY_ID]
|
|
352
437
|
: dependencyOrId;
|
|
353
438
|
const dependency = this.dependencies[id];
|
|
354
439
|
if (dependency) {
|
|
440
|
+
const constructorName = (_a = dependency.constructor) === null || _a === undefined ? undefined : _a.name;
|
|
441
|
+
if (constructorName && middlewaresClasses[constructorName]) {
|
|
442
|
+
this.middlewareListener.remove(dependency);
|
|
443
|
+
}
|
|
355
444
|
const dependencyInjects = dependency[INJECTIONS]
|
|
356
445
|
? dependency[INJECTIONS]
|
|
357
446
|
: {};
|
|
@@ -360,6 +449,7 @@ class ProxyDiContainer {
|
|
|
360
449
|
});
|
|
361
450
|
delete dependency[DEPENDENCY_ID];
|
|
362
451
|
delete this.dependencies[id];
|
|
452
|
+
this.middlewareListener.onRemove(this, id, dependency);
|
|
363
453
|
}
|
|
364
454
|
}
|
|
365
455
|
/**
|
|
@@ -470,4 +560,4 @@ function recursiveResolveAll(container, dependencyId) {
|
|
|
470
560
|
return all;
|
|
471
561
|
}
|
|
472
562
|
|
|
473
|
-
export { DEPENDENCY_ID, PROXYDI_CONTAINER, ProxyDiContainer, inject, injectable, resolveAll };
|
|
563
|
+
export { DEPENDENCY_ID, PROXYDI_CONTAINER, ProxyDiContainer, inject, injectable, middleware, resolveAll };
|
package/dist/index.umd.js
CHANGED
|
@@ -4,6 +4,41 @@
|
|
|
4
4
|
(global = typeof globalThis !== 'undefined' ? globalThis : global || self, factory(global.YourLibraryName = {}));
|
|
5
5
|
})(this, (function (exports) { 'use strict';
|
|
6
6
|
|
|
7
|
+
const injectableClasses = {};
|
|
8
|
+
const constructorInjections = {};
|
|
9
|
+
function injectable(dependencyOrDependencies, autoInjecions) {
|
|
10
|
+
return function (value, context) {
|
|
11
|
+
if ((context === null || context === undefined ? undefined : context.kind) !== 'class') {
|
|
12
|
+
throw new Error('@injectable decorator should decorate classes');
|
|
13
|
+
}
|
|
14
|
+
const name = dependencyOrDependencies
|
|
15
|
+
? Array.isArray(dependencyOrDependencies)
|
|
16
|
+
? context.name
|
|
17
|
+
: dependencyOrDependencies
|
|
18
|
+
: context.name;
|
|
19
|
+
const injectToConstructor = dependencyOrDependencies
|
|
20
|
+
? Array.isArray(dependencyOrDependencies)
|
|
21
|
+
? dependencyOrDependencies
|
|
22
|
+
: autoInjecions
|
|
23
|
+
: autoInjecions;
|
|
24
|
+
if (injectableClasses[name]) {
|
|
25
|
+
throw new Error(`ProxyDi has already regisered dependency ${String(name)} by @injectable`);
|
|
26
|
+
}
|
|
27
|
+
injectableClasses[name] = value;
|
|
28
|
+
if (injectToConstructor) {
|
|
29
|
+
constructorInjections[name] = injectToConstructor;
|
|
30
|
+
}
|
|
31
|
+
};
|
|
32
|
+
}
|
|
33
|
+
function findInjectableId(injectable) {
|
|
34
|
+
for (const [id, DependencyClass] of Object.entries(injectableClasses)) {
|
|
35
|
+
if (DependencyClass === injectable) {
|
|
36
|
+
return id;
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
throw new Error(`Class is not @injectable: ${injectable.name}`);
|
|
40
|
+
}
|
|
41
|
+
|
|
7
42
|
const INJECTIONS = Symbol('injections');
|
|
8
43
|
/**
|
|
9
44
|
* This symbol constant defines a property name.
|
|
@@ -32,7 +67,11 @@
|
|
|
32
67
|
const inject = (dependencyId) => {
|
|
33
68
|
return function (_value, context) {
|
|
34
69
|
if ((context === null || context === undefined ? undefined : context.kind) === 'field') {
|
|
35
|
-
const id = dependencyId
|
|
70
|
+
const id = dependencyId
|
|
71
|
+
? typeof dependencyId === 'function'
|
|
72
|
+
? findInjectableId(dependencyId)
|
|
73
|
+
: dependencyId
|
|
74
|
+
: context.name;
|
|
36
75
|
const injection = {
|
|
37
76
|
property: context.name,
|
|
38
77
|
dependencyId: id,
|
|
@@ -51,41 +90,6 @@
|
|
|
51
90
|
};
|
|
52
91
|
};
|
|
53
92
|
|
|
54
|
-
const injectableClasses = {};
|
|
55
|
-
const constructorInjections = {};
|
|
56
|
-
function injectable(dependencyOrDependencies, autoInjecions) {
|
|
57
|
-
return function (value, context) {
|
|
58
|
-
if ((context === null || context === undefined ? undefined : context.kind) !== 'class') {
|
|
59
|
-
throw new Error('@injectable decorator should decorate classes');
|
|
60
|
-
}
|
|
61
|
-
const name = dependencyOrDependencies
|
|
62
|
-
? Array.isArray(dependencyOrDependencies)
|
|
63
|
-
? context.name
|
|
64
|
-
: dependencyOrDependencies
|
|
65
|
-
: context.name;
|
|
66
|
-
const injectToConstructor = dependencyOrDependencies
|
|
67
|
-
? Array.isArray(dependencyOrDependencies)
|
|
68
|
-
? dependencyOrDependencies
|
|
69
|
-
: autoInjecions
|
|
70
|
-
: autoInjecions;
|
|
71
|
-
if (injectableClasses[name]) {
|
|
72
|
-
throw new Error(`ProxyDi has already regisered dependency ${String(name)} by @injectable`);
|
|
73
|
-
}
|
|
74
|
-
injectableClasses[name] = value;
|
|
75
|
-
if (injectToConstructor) {
|
|
76
|
-
constructorInjections[name] = injectToConstructor;
|
|
77
|
-
}
|
|
78
|
-
};
|
|
79
|
-
}
|
|
80
|
-
function findInjectableId(injectable) {
|
|
81
|
-
for (const [id, DependencyClass] of Object.entries(injectableClasses)) {
|
|
82
|
-
if (DependencyClass === injectable) {
|
|
83
|
-
return id;
|
|
84
|
-
}
|
|
85
|
-
}
|
|
86
|
-
throw new Error(`Class is not @injectable: ${injectable.name}`);
|
|
87
|
-
}
|
|
88
|
-
|
|
89
93
|
const DEFAULT_SETTINGS = {
|
|
90
94
|
allowRegisterAnything: false,
|
|
91
95
|
allowRewriteDependencies: false,
|
|
@@ -194,6 +198,72 @@
|
|
|
194
198
|
});
|
|
195
199
|
}
|
|
196
200
|
|
|
201
|
+
const middlewaresClasses = {};
|
|
202
|
+
function middleware() {
|
|
203
|
+
return function (value, context) {
|
|
204
|
+
if ((context === null || context === undefined ? undefined : context.kind) !== 'class') {
|
|
205
|
+
throw new Error('@middleware decorator should decorate classes');
|
|
206
|
+
}
|
|
207
|
+
const name = context.name;
|
|
208
|
+
if (middlewaresClasses[name]) {
|
|
209
|
+
throw new Error(`ProxyDi has already regisered middleware ${String(name)} by @middleware`);
|
|
210
|
+
}
|
|
211
|
+
middlewaresClasses[name] = value;
|
|
212
|
+
};
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
class MiddlewareListener {
|
|
216
|
+
constructor(parent) {
|
|
217
|
+
this.parent = parent;
|
|
218
|
+
this.listeners = {
|
|
219
|
+
register: [],
|
|
220
|
+
remove: [],
|
|
221
|
+
};
|
|
222
|
+
}
|
|
223
|
+
add(middleware) {
|
|
224
|
+
if (isRegistingMiddleware(middleware)) {
|
|
225
|
+
middleware.onRegister && this.on('register', middleware.onRegister);
|
|
226
|
+
}
|
|
227
|
+
if (isRemovingMiddleware(middleware)) {
|
|
228
|
+
middleware.onRemove && this.on('remove', middleware.onRemove);
|
|
229
|
+
}
|
|
230
|
+
}
|
|
231
|
+
remove(middleware) {
|
|
232
|
+
if (isRegistingMiddleware(middleware)) {
|
|
233
|
+
middleware.onRegister &&
|
|
234
|
+
this.off('register', middleware.onRegister);
|
|
235
|
+
}
|
|
236
|
+
if (isRemovingMiddleware(middleware)) {
|
|
237
|
+
middleware.onRemove && this.off('remove', middleware.onRemove);
|
|
238
|
+
}
|
|
239
|
+
}
|
|
240
|
+
on(event, listener) {
|
|
241
|
+
this.listeners[event].push(listener);
|
|
242
|
+
}
|
|
243
|
+
onRegister(container, dependencyId, dependency) {
|
|
244
|
+
var _a;
|
|
245
|
+
this.listeners.register.forEach((listener) => listener(container, dependencyId, dependency));
|
|
246
|
+
(_a = this.parent) === null || _a === undefined ? undefined : _a.onRegister(container, dependencyId, dependency);
|
|
247
|
+
}
|
|
248
|
+
onRemove(container, dependencyId, dependency) {
|
|
249
|
+
var _a;
|
|
250
|
+
this.listeners.remove.forEach((listener) => listener(container, dependencyId, dependency));
|
|
251
|
+
(_a = this.parent) === null || _a === undefined ? undefined : _a.onRemove(container, dependencyId, dependency);
|
|
252
|
+
}
|
|
253
|
+
off(event, listener) {
|
|
254
|
+
const index = this.listeners[event].indexOf(listener);
|
|
255
|
+
if (index !== -1) {
|
|
256
|
+
this.listeners[event].splice(index, 1);
|
|
257
|
+
}
|
|
258
|
+
}
|
|
259
|
+
}
|
|
260
|
+
function isRegistingMiddleware(middleware) {
|
|
261
|
+
return middleware.onRegister;
|
|
262
|
+
}
|
|
263
|
+
function isRemovingMiddleware(middleware) {
|
|
264
|
+
return middleware.onRemove;
|
|
265
|
+
}
|
|
266
|
+
|
|
197
267
|
/**
|
|
198
268
|
* A dependency injection container
|
|
199
269
|
*/
|
|
@@ -214,35 +284,55 @@
|
|
|
214
284
|
*/
|
|
215
285
|
this.parentDependencyProxies = {};
|
|
216
286
|
this.id = ProxyDiContainer.idCounter++;
|
|
287
|
+
this.middlewareListener = new MiddlewareListener(parent === null || parent === undefined ? undefined : parent.middlewareListener);
|
|
217
288
|
if (parent) {
|
|
218
289
|
this.parent = parent;
|
|
219
290
|
this.parent.addChild(this);
|
|
220
291
|
}
|
|
221
292
|
this.settings = Object.assign(Object.assign({}, DEFAULT_SETTINGS), settings);
|
|
222
293
|
}
|
|
223
|
-
register(dependency,
|
|
224
|
-
|
|
294
|
+
register(dependency, dependecyId) {
|
|
295
|
+
var _a;
|
|
296
|
+
let id = dependecyId;
|
|
297
|
+
if (!id) {
|
|
298
|
+
if (typeof dependency === 'function') {
|
|
299
|
+
try {
|
|
300
|
+
id = findInjectableId(dependency);
|
|
301
|
+
}
|
|
302
|
+
catch (_b) {
|
|
303
|
+
id = dependency.name;
|
|
304
|
+
}
|
|
305
|
+
}
|
|
306
|
+
}
|
|
307
|
+
if (this.dependencies[id]) {
|
|
225
308
|
if (!this.settings.allowRewriteDependencies) {
|
|
226
|
-
throw new Error(`ProxyDi already has dependency for ${String(
|
|
309
|
+
throw new Error(`ProxyDi already has dependency for ${String(id)}`);
|
|
227
310
|
}
|
|
228
311
|
}
|
|
229
|
-
let
|
|
312
|
+
let instance;
|
|
230
313
|
const isClass = typeof dependency === 'function';
|
|
231
314
|
if (isClass) {
|
|
232
|
-
|
|
315
|
+
instance = this.createInstance(dependency, id);
|
|
233
316
|
}
|
|
234
317
|
else {
|
|
235
|
-
|
|
236
|
-
if (!(typeof dependencyInstance === 'object') &&
|
|
237
|
-
!this.settings.allowRegisterAnything) {
|
|
238
|
-
throw new Error(`Can't register as dependency (allowRegisterAnything is off for this contatiner): ${dependencyInstance}`);
|
|
239
|
-
}
|
|
318
|
+
instance = dependency;
|
|
240
319
|
}
|
|
241
|
-
|
|
242
|
-
|
|
320
|
+
const isObject = typeof instance === 'object';
|
|
321
|
+
if (!isObject && !this.settings.allowRegisterAnything) {
|
|
322
|
+
throw new Error(`Can't register as dependency (allowRegisterAnything is off for this contatiner): ${instance}`);
|
|
243
323
|
}
|
|
244
|
-
|
|
245
|
-
|
|
324
|
+
if (isObject) {
|
|
325
|
+
instance[PROXYDI_CONTAINER] = this;
|
|
326
|
+
instance[DEPENDENCY_ID] = id;
|
|
327
|
+
}
|
|
328
|
+
this.injectDependenciesTo(instance);
|
|
329
|
+
this.dependencies[id] = instance;
|
|
330
|
+
const constructorName = (_a = instance.constructor) === null || _a === undefined ? undefined : _a.name;
|
|
331
|
+
if (constructorName && middlewaresClasses[constructorName]) {
|
|
332
|
+
this.middlewareListener.add(instance);
|
|
333
|
+
}
|
|
334
|
+
this.middlewareListener.onRegister(this, id, instance);
|
|
335
|
+
return instance;
|
|
246
336
|
}
|
|
247
337
|
createInstance(Dependency, dependencyId) {
|
|
248
338
|
const paramIds = constructorInjections[dependencyId] || [];
|
|
@@ -253,18 +343,6 @@
|
|
|
253
343
|
}
|
|
254
344
|
return new Dependency(...params);
|
|
255
345
|
}
|
|
256
|
-
/**
|
|
257
|
-
* Internal method that implements registeration of dependency and prepare it for injection.
|
|
258
|
-
* @param dependencyId The unique identifier of the dependency.
|
|
259
|
-
* @param dependency The dependency instance.
|
|
260
|
-
*/
|
|
261
|
-
registerImpl(dependency, dependencyId) {
|
|
262
|
-
this.injectDependenciesTo(dependency);
|
|
263
|
-
if (typeof dependency === 'object') {
|
|
264
|
-
dependency[DEPENDENCY_ID] = dependencyId;
|
|
265
|
-
}
|
|
266
|
-
this.dependencies[dependencyId] = dependency;
|
|
267
|
-
}
|
|
268
346
|
/**
|
|
269
347
|
* Checks if a dependency with the given ID is known to the container or its ancestors which means that it can be resolved by this container
|
|
270
348
|
* @param dependencyId The identifier of the dependency.
|
|
@@ -278,7 +356,13 @@
|
|
|
278
356
|
}
|
|
279
357
|
resolve(dependency) {
|
|
280
358
|
if (typeof dependency === 'function') {
|
|
281
|
-
|
|
359
|
+
let id;
|
|
360
|
+
try {
|
|
361
|
+
id = findInjectableId(dependency);
|
|
362
|
+
}
|
|
363
|
+
catch (_a) {
|
|
364
|
+
id = dependency.name;
|
|
365
|
+
}
|
|
282
366
|
return this.resolve(id);
|
|
283
367
|
}
|
|
284
368
|
if (!this.isKnown(dependency)) {
|
|
@@ -353,11 +437,16 @@
|
|
|
353
437
|
* @param dependencyOrId The dependency instance or dependency identifier to remove.
|
|
354
438
|
*/
|
|
355
439
|
remove(dependencyOrId) {
|
|
440
|
+
var _a;
|
|
356
441
|
const id = isDependency(dependencyOrId)
|
|
357
442
|
? dependencyOrId[DEPENDENCY_ID]
|
|
358
443
|
: dependencyOrId;
|
|
359
444
|
const dependency = this.dependencies[id];
|
|
360
445
|
if (dependency) {
|
|
446
|
+
const constructorName = (_a = dependency.constructor) === null || _a === undefined ? undefined : _a.name;
|
|
447
|
+
if (constructorName && middlewaresClasses[constructorName]) {
|
|
448
|
+
this.middlewareListener.remove(dependency);
|
|
449
|
+
}
|
|
361
450
|
const dependencyInjects = dependency[INJECTIONS]
|
|
362
451
|
? dependency[INJECTIONS]
|
|
363
452
|
: {};
|
|
@@ -366,6 +455,7 @@
|
|
|
366
455
|
});
|
|
367
456
|
delete dependency[DEPENDENCY_ID];
|
|
368
457
|
delete this.dependencies[id];
|
|
458
|
+
this.middlewareListener.onRemove(this, id, dependency);
|
|
369
459
|
}
|
|
370
460
|
}
|
|
371
461
|
/**
|
|
@@ -481,6 +571,7 @@
|
|
|
481
571
|
exports.ProxyDiContainer = ProxyDiContainer;
|
|
482
572
|
exports.inject = inject;
|
|
483
573
|
exports.injectable = injectable;
|
|
574
|
+
exports.middleware = middleware;
|
|
484
575
|
exports.resolveAll = resolveAll;
|
|
485
576
|
|
|
486
577
|
}));
|
package/dist/inject.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { DependencyId } from './types';
|
|
1
|
+
import { DependencyId, DependencyClass } from './types';
|
|
2
2
|
/**
|
|
3
3
|
* Registers an injection for dependency injection.
|
|
4
4
|
*
|
|
@@ -7,4 +7,4 @@ import { DependencyId } from './types';
|
|
|
7
7
|
*
|
|
8
8
|
* The decorated field will receive its dependency from the same container as the injection owner.
|
|
9
9
|
*/
|
|
10
|
-
export declare const inject: (dependencyId?: DependencyId) => (_value: unknown, context: ClassFieldDecoratorContext) => void;
|
|
10
|
+
export declare const inject: (dependencyId?: DependencyId | DependencyClass<any>) => (_value: unknown, context: ClassFieldDecoratorContext) => void;
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import { ProxyDiContainer } from '../ProxyDiContainer';
|
|
2
|
+
import { DependencyId } from '../types';
|
|
3
|
+
export interface MiddlewareListenerEvent {
|
|
4
|
+
register: (container: ProxyDiContainer, dependencyId: DependencyId, dependency: any) => void;
|
|
5
|
+
remove: (container: ProxyDiContainer, dependencyId: DependencyId, dependency: any) => void;
|
|
6
|
+
}
|
|
7
|
+
/**
|
|
8
|
+
* Describe the middleware that able to listen to the registering of a dependency in containers hierarchy
|
|
9
|
+
*/
|
|
10
|
+
export interface MiddlewareRegisteringListener {
|
|
11
|
+
onRegister(container: ProxyDiContainer, dependencyId: DependencyId, dependency: any): void;
|
|
12
|
+
}
|
|
13
|
+
/**
|
|
14
|
+
* Describe the middleware that able to listen to the removing of a dependency in containers hierarchy
|
|
15
|
+
*/
|
|
16
|
+
export interface MiddlewareRemovingListener {
|
|
17
|
+
onRemove(container: ProxyDiContainer, dependencyId: DependencyId, dependency: any): void;
|
|
18
|
+
}
|
|
19
|
+
export declare class MiddlewareListener {
|
|
20
|
+
private parent?;
|
|
21
|
+
private listeners;
|
|
22
|
+
constructor(parent?: MiddlewareListener | undefined);
|
|
23
|
+
add(middleware: any): void;
|
|
24
|
+
remove(middleware: any): void;
|
|
25
|
+
private on;
|
|
26
|
+
onRegister(container: ProxyDiContainer, dependencyId: DependencyId, dependency: any): void;
|
|
27
|
+
onRemove(container: ProxyDiContainer, dependencyId: DependencyId, dependency: any): void;
|
|
28
|
+
private off;
|
|
29
|
+
}
|