proxydi 0.0.11 → 0.0.12

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 CHANGED
@@ -5,11 +5,17 @@ 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.10](https://www.npmjs.com/package/proxydi/v/0.0.11)] - 2025-03-03
8
+ ## [[0.0.12](https://www.npmjs.com/package/proxydi/v/0.0.12)] - 2025-03-04
9
9
 
10
10
  ### Added
11
11
 
12
- - resolveInjectables() method [#12](https://github.com/proxy-di/proxydi/pull/13)
12
+ - Experimental @middleware [#14](https://github.com/proxy-di/proxydi/pull/14)
13
+
14
+ ## [[0.0.11](https://www.npmjs.com/package/proxydi/v/0.0.11)] - 2025-03-03
15
+
16
+ ### Added
17
+
18
+ - resolveInjectables() method [#13](https://github.com/proxy-di/proxydi/pull/13)
13
19
 
14
20
  ## [[0.0.10](https://www.npmjs.com/package/proxydi/v/0.0.10)] - 2025-03-02
15
21
 
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.
@@ -47,12 +48,6 @@ export declare class ProxyDiContainer implements IProxyDiContainer {
47
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
@@ -190,6 +190,72 @@ function makeConstructorDependencyProxy(container, dependencyId) {
190
190
  });
191
191
  }
192
192
 
193
+ const middlewaresClasses = {};
194
+ function middleware() {
195
+ return function (value, context) {
196
+ if ((context === null || context === undefined ? undefined : context.kind) !== 'class') {
197
+ throw new Error('@middleware decorator should decorate classes');
198
+ }
199
+ const name = context.name;
200
+ if (middlewaresClasses[name]) {
201
+ throw new Error(`ProxyDi has already regisered middleware ${String(name)} by @middleware`);
202
+ }
203
+ middlewaresClasses[name] = value;
204
+ };
205
+ }
206
+
207
+ class MiddlewareListener {
208
+ constructor(parent) {
209
+ this.parent = parent;
210
+ this.listeners = {
211
+ register: [],
212
+ remove: [],
213
+ };
214
+ }
215
+ add(middleware) {
216
+ if (isRegistingMiddleware(middleware)) {
217
+ middleware.onRegister && this.on('register', middleware.onRegister);
218
+ }
219
+ if (isRemovingMiddleware(middleware)) {
220
+ middleware.onRemove && this.on('remove', middleware.onRemove);
221
+ }
222
+ }
223
+ remove(middleware) {
224
+ if (isRegistingMiddleware(middleware)) {
225
+ middleware.onRegister &&
226
+ this.off('register', middleware.onRegister);
227
+ }
228
+ if (isRemovingMiddleware(middleware)) {
229
+ middleware.onRemove && this.off('remove', middleware.onRemove);
230
+ }
231
+ }
232
+ on(event, listener) {
233
+ this.listeners[event].push(listener);
234
+ }
235
+ onRegister(container, dependencyId, dependency) {
236
+ var _a;
237
+ this.listeners.register.forEach((listener) => listener(container, dependencyId, dependency));
238
+ (_a = this.parent) === null || _a === undefined ? undefined : _a.onRegister(container, dependencyId, dependency);
239
+ }
240
+ onRemove(container, dependencyId) {
241
+ var _a;
242
+ this.listeners.remove.forEach((listener) => listener(container, dependencyId));
243
+ (_a = this.parent) === null || _a === undefined ? undefined : _a.onRemove(container, dependencyId);
244
+ }
245
+ off(event, listener) {
246
+ const index = this.listeners[event].indexOf(listener);
247
+ if (index !== -1) {
248
+ this.listeners[event].splice(index, 1);
249
+ }
250
+ }
251
+ }
252
+ function isRegistingMiddleware(middleware) {
253
+ return middleware.onRegister;
254
+ }
255
+ function isRemovingMiddleware(middleware) {
256
+ return middleware.onRemove;
257
+ }
258
+
193
259
  /**
194
260
  * A dependency injection container
195
261
  */
@@ -210,6 +276,7 @@ class ProxyDiContainer {
210
276
  */
211
277
  this.parentDependencyProxies = {};
212
278
  this.id = ProxyDiContainer.idCounter++;
279
+ this.middlewareListener = new MiddlewareListener(parent === null || parent === undefined ? undefined : parent.middlewareListener);
213
280
  if (parent) {
214
281
  this.parent = parent;
215
282
  this.parent.addChild(this);
@@ -217,28 +284,36 @@ class ProxyDiContainer {
217
284
  this.settings = Object.assign(Object.assign({}, DEFAULT_SETTINGS), settings);
218
285
  }
219
286
  register(dependency, dependencyId) {
287
+ var _a;
220
288
  if (this.dependencies[dependencyId]) {
221
289
  if (!this.settings.allowRewriteDependencies) {
222
290
  throw new Error(`ProxyDi already has dependency for ${String(dependencyId)}`);
223
291
  }
224
292
  }
225
- let dependencyInstance;
293
+ let instance;
226
294
  const isClass = typeof dependency === 'function';
227
295
  if (isClass) {
228
- dependencyInstance = this.createInstance(dependency, dependencyId);
296
+ instance = this.createInstance(dependency, dependencyId);
229
297
  }
230
298
  else {
231
- dependencyInstance = dependency;
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
- }
299
+ instance = dependency;
236
300
  }
237
- if (typeof dependencyInstance === 'object') {
238
- dependencyInstance[PROXYDI_CONTAINER] = this;
301
+ const isObject = typeof instance === 'object';
302
+ if (!isObject && !this.settings.allowRegisterAnything) {
303
+ throw new Error(`Can't register as dependency (allowRegisterAnything is off for this contatiner): ${instance}`);
239
304
  }
240
- this.registerImpl(dependencyInstance, dependencyId);
241
- return dependencyInstance;
305
+ if (isObject) {
306
+ instance[PROXYDI_CONTAINER] = this;
307
+ instance[DEPENDENCY_ID] = dependencyId;
308
+ }
309
+ this.injectDependenciesTo(instance);
310
+ this.dependencies[dependencyId] = instance;
311
+ const constructorName = (_a = instance.constructor) === null || _a === undefined ? undefined : _a.name;
312
+ if (constructorName && middlewaresClasses[constructorName]) {
313
+ this.middlewareListener.add(instance);
314
+ }
315
+ this.middlewareListener.onRegister(this, dependencyId, instance);
316
+ return instance;
242
317
  }
243
318
  createInstance(Dependency, dependencyId) {
244
319
  const paramIds = constructorInjections[dependencyId] || [];
@@ -249,18 +324,6 @@ class ProxyDiContainer {
249
324
  }
250
325
  return new Dependency(...params);
251
326
  }
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
327
  /**
265
328
  * 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
329
  * @param dependencyId The identifier of the dependency.
@@ -349,11 +412,16 @@ class ProxyDiContainer {
349
412
  * @param dependencyOrId The dependency instance or dependency identifier to remove.
350
413
  */
351
414
  remove(dependencyOrId) {
415
+ var _a;
352
416
  const id = isDependency(dependencyOrId)
353
417
  ? dependencyOrId[DEPENDENCY_ID]
354
418
  : dependencyOrId;
355
419
  const dependency = this.dependencies[id];
356
420
  if (dependency) {
421
+ const constructorName = (_a = dependency.constructor) === null || _a === undefined ? undefined : _a.name;
422
+ if (constructorName && middlewaresClasses[constructorName]) {
423
+ this.middlewareListener.remove(dependency);
424
+ }
357
425
  const dependencyInjects = dependency[INJECTIONS]
358
426
  ? dependency[INJECTIONS]
359
427
  : {};
@@ -362,6 +430,7 @@ class ProxyDiContainer {
362
430
  });
363
431
  delete dependency[DEPENDENCY_ID];
364
432
  delete this.dependencies[id];
433
+ this.middlewareListener.onRemove(this, id);
365
434
  }
366
435
  }
367
436
  /**
@@ -477,4 +546,5 @@ exports.PROXYDI_CONTAINER = PROXYDI_CONTAINER;
477
546
  exports.ProxyDiContainer = ProxyDiContainer;
478
547
  exports.inject = inject;
479
548
  exports.injectable = injectable;
549
+ exports.middleware = middleware;
480
550
  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
@@ -188,6 +188,72 @@ function makeConstructorDependencyProxy(container, dependencyId) {
188
188
  });
189
189
  }
190
190
 
191
+ const middlewaresClasses = {};
192
+ function middleware() {
193
+ return function (value, context) {
194
+ if ((context === null || context === undefined ? undefined : context.kind) !== 'class') {
195
+ throw new Error('@middleware decorator should decorate classes');
196
+ }
197
+ const name = context.name;
198
+ if (middlewaresClasses[name]) {
199
+ throw new Error(`ProxyDi has already regisered middleware ${String(name)} by @middleware`);
200
+ }
201
+ middlewaresClasses[name] = value;
202
+ };
203
+ }
204
+
205
+ class MiddlewareListener {
206
+ constructor(parent) {
207
+ this.parent = parent;
208
+ this.listeners = {
209
+ register: [],
210
+ remove: [],
211
+ };
212
+ }
213
+ add(middleware) {
214
+ if (isRegistingMiddleware(middleware)) {
215
+ middleware.onRegister && this.on('register', middleware.onRegister);
216
+ }
217
+ if (isRemovingMiddleware(middleware)) {
218
+ middleware.onRemove && this.on('remove', middleware.onRemove);
219
+ }
220
+ }
221
+ remove(middleware) {
222
+ if (isRegistingMiddleware(middleware)) {
223
+ middleware.onRegister &&
224
+ this.off('register', middleware.onRegister);
225
+ }
226
+ if (isRemovingMiddleware(middleware)) {
227
+ middleware.onRemove && this.off('remove', middleware.onRemove);
228
+ }
229
+ }
230
+ on(event, listener) {
231
+ this.listeners[event].push(listener);
232
+ }
233
+ onRegister(container, dependencyId, dependency) {
234
+ var _a;
235
+ this.listeners.register.forEach((listener) => listener(container, dependencyId, dependency));
236
+ (_a = this.parent) === null || _a === undefined ? undefined : _a.onRegister(container, dependencyId, dependency);
237
+ }
238
+ onRemove(container, dependencyId) {
239
+ var _a;
240
+ this.listeners.remove.forEach((listener) => listener(container, dependencyId));
241
+ (_a = this.parent) === null || _a === undefined ? undefined : _a.onRemove(container, dependencyId);
242
+ }
243
+ off(event, listener) {
244
+ const index = this.listeners[event].indexOf(listener);
245
+ if (index !== -1) {
246
+ this.listeners[event].splice(index, 1);
247
+ }
248
+ }
249
+ }
250
+ function isRegistingMiddleware(middleware) {
251
+ return middleware.onRegister;
252
+ }
253
+ function isRemovingMiddleware(middleware) {
254
+ return middleware.onRemove;
255
+ }
256
+
191
257
  /**
192
258
  * A dependency injection container
193
259
  */
@@ -208,6 +274,7 @@ class ProxyDiContainer {
208
274
  */
209
275
  this.parentDependencyProxies = {};
210
276
  this.id = ProxyDiContainer.idCounter++;
277
+ this.middlewareListener = new MiddlewareListener(parent === null || parent === undefined ? undefined : parent.middlewareListener);
211
278
  if (parent) {
212
279
  this.parent = parent;
213
280
  this.parent.addChild(this);
@@ -215,28 +282,36 @@ class ProxyDiContainer {
215
282
  this.settings = Object.assign(Object.assign({}, DEFAULT_SETTINGS), settings);
216
283
  }
217
284
  register(dependency, dependencyId) {
285
+ var _a;
218
286
  if (this.dependencies[dependencyId]) {
219
287
  if (!this.settings.allowRewriteDependencies) {
220
288
  throw new Error(`ProxyDi already has dependency for ${String(dependencyId)}`);
221
289
  }
222
290
  }
223
- let dependencyInstance;
291
+ let instance;
224
292
  const isClass = typeof dependency === 'function';
225
293
  if (isClass) {
226
- dependencyInstance = this.createInstance(dependency, dependencyId);
294
+ instance = this.createInstance(dependency, dependencyId);
227
295
  }
228
296
  else {
229
- dependencyInstance = dependency;
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
- }
297
+ instance = dependency;
234
298
  }
235
- if (typeof dependencyInstance === 'object') {
236
- dependencyInstance[PROXYDI_CONTAINER] = this;
299
+ const isObject = typeof instance === 'object';
300
+ if (!isObject && !this.settings.allowRegisterAnything) {
301
+ throw new Error(`Can't register as dependency (allowRegisterAnything is off for this contatiner): ${instance}`);
237
302
  }
238
- this.registerImpl(dependencyInstance, dependencyId);
239
- return dependencyInstance;
303
+ if (isObject) {
304
+ instance[PROXYDI_CONTAINER] = this;
305
+ instance[DEPENDENCY_ID] = dependencyId;
306
+ }
307
+ this.injectDependenciesTo(instance);
308
+ this.dependencies[dependencyId] = instance;
309
+ const constructorName = (_a = instance.constructor) === null || _a === undefined ? undefined : _a.name;
310
+ if (constructorName && middlewaresClasses[constructorName]) {
311
+ this.middlewareListener.add(instance);
312
+ }
313
+ this.middlewareListener.onRegister(this, dependencyId, instance);
314
+ return instance;
240
315
  }
241
316
  createInstance(Dependency, dependencyId) {
242
317
  const paramIds = constructorInjections[dependencyId] || [];
@@ -247,18 +322,6 @@ class ProxyDiContainer {
247
322
  }
248
323
  return new Dependency(...params);
249
324
  }
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
325
  /**
263
326
  * 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
327
  * @param dependencyId The identifier of the dependency.
@@ -347,11 +410,16 @@ class ProxyDiContainer {
347
410
  * @param dependencyOrId The dependency instance or dependency identifier to remove.
348
411
  */
349
412
  remove(dependencyOrId) {
413
+ var _a;
350
414
  const id = isDependency(dependencyOrId)
351
415
  ? dependencyOrId[DEPENDENCY_ID]
352
416
  : dependencyOrId;
353
417
  const dependency = this.dependencies[id];
354
418
  if (dependency) {
419
+ const constructorName = (_a = dependency.constructor) === null || _a === undefined ? undefined : _a.name;
420
+ if (constructorName && middlewaresClasses[constructorName]) {
421
+ this.middlewareListener.remove(dependency);
422
+ }
355
423
  const dependencyInjects = dependency[INJECTIONS]
356
424
  ? dependency[INJECTIONS]
357
425
  : {};
@@ -360,6 +428,7 @@ class ProxyDiContainer {
360
428
  });
361
429
  delete dependency[DEPENDENCY_ID];
362
430
  delete this.dependencies[id];
431
+ this.middlewareListener.onRemove(this, id);
363
432
  }
364
433
  }
365
434
  /**
@@ -470,4 +539,4 @@ function recursiveResolveAll(container, dependencyId) {
470
539
  return all;
471
540
  }
472
541
 
473
- export { DEPENDENCY_ID, PROXYDI_CONTAINER, ProxyDiContainer, inject, injectable, resolveAll };
542
+ export { DEPENDENCY_ID, PROXYDI_CONTAINER, ProxyDiContainer, inject, injectable, middleware, resolveAll };
package/dist/index.umd.js CHANGED
@@ -194,6 +194,72 @@
194
194
  });
195
195
  }
196
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) {
245
+ var _a;
246
+ this.listeners.remove.forEach((listener) => listener(container, dependencyId));
247
+ (_a = this.parent) === null || _a === undefined ? undefined : _a.onRemove(container, dependencyId);
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
+
197
263
  /**
198
264
  * A dependency injection container
199
265
  */
@@ -214,6 +280,7 @@
214
280
  */
215
281
  this.parentDependencyProxies = {};
216
282
  this.id = ProxyDiContainer.idCounter++;
283
+ this.middlewareListener = new MiddlewareListener(parent === null || parent === undefined ? undefined : parent.middlewareListener);
217
284
  if (parent) {
218
285
  this.parent = parent;
219
286
  this.parent.addChild(this);
@@ -221,28 +288,36 @@
221
288
  this.settings = Object.assign(Object.assign({}, DEFAULT_SETTINGS), settings);
222
289
  }
223
290
  register(dependency, dependencyId) {
291
+ var _a;
224
292
  if (this.dependencies[dependencyId]) {
225
293
  if (!this.settings.allowRewriteDependencies) {
226
294
  throw new Error(`ProxyDi already has dependency for ${String(dependencyId)}`);
227
295
  }
228
296
  }
229
- let dependencyInstance;
297
+ let instance;
230
298
  const isClass = typeof dependency === 'function';
231
299
  if (isClass) {
232
- dependencyInstance = this.createInstance(dependency, dependencyId);
300
+ instance = this.createInstance(dependency, dependencyId);
233
301
  }
234
302
  else {
235
- dependencyInstance = dependency;
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
- }
303
+ instance = dependency;
240
304
  }
241
- if (typeof dependencyInstance === 'object') {
242
- dependencyInstance[PROXYDI_CONTAINER] = this;
305
+ const isObject = typeof instance === 'object';
306
+ if (!isObject && !this.settings.allowRegisterAnything) {
307
+ throw new Error(`Can't register as dependency (allowRegisterAnything is off for this contatiner): ${instance}`);
243
308
  }
244
- this.registerImpl(dependencyInstance, dependencyId);
245
- return dependencyInstance;
309
+ if (isObject) {
310
+ instance[PROXYDI_CONTAINER] = this;
311
+ instance[DEPENDENCY_ID] = dependencyId;
312
+ }
313
+ this.injectDependenciesTo(instance);
314
+ this.dependencies[dependencyId] = instance;
315
+ const constructorName = (_a = instance.constructor) === null || _a === undefined ? undefined : _a.name;
316
+ if (constructorName && middlewaresClasses[constructorName]) {
317
+ this.middlewareListener.add(instance);
318
+ }
319
+ this.middlewareListener.onRegister(this, dependencyId, instance);
320
+ return instance;
246
321
  }
247
322
  createInstance(Dependency, dependencyId) {
248
323
  const paramIds = constructorInjections[dependencyId] || [];
@@ -253,18 +328,6 @@
253
328
  }
254
329
  return new Dependency(...params);
255
330
  }
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
331
  /**
269
332
  * 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
333
  * @param dependencyId The identifier of the dependency.
@@ -353,11 +416,16 @@
353
416
  * @param dependencyOrId The dependency instance or dependency identifier to remove.
354
417
  */
355
418
  remove(dependencyOrId) {
419
+ var _a;
356
420
  const id = isDependency(dependencyOrId)
357
421
  ? dependencyOrId[DEPENDENCY_ID]
358
422
  : dependencyOrId;
359
423
  const dependency = this.dependencies[id];
360
424
  if (dependency) {
425
+ const constructorName = (_a = dependency.constructor) === null || _a === undefined ? undefined : _a.name;
426
+ if (constructorName && middlewaresClasses[constructorName]) {
427
+ this.middlewareListener.remove(dependency);
428
+ }
361
429
  const dependencyInjects = dependency[INJECTIONS]
362
430
  ? dependency[INJECTIONS]
363
431
  : {};
@@ -366,6 +434,7 @@
366
434
  });
367
435
  delete dependency[DEPENDENCY_ID];
368
436
  delete this.dependencies[id];
437
+ this.middlewareListener.onRemove(this, id);
369
438
  }
370
439
  }
371
440
  /**
@@ -481,6 +550,7 @@
481
550
  exports.ProxyDiContainer = ProxyDiContainer;
482
551
  exports.inject = inject;
483
552
  exports.injectable = injectable;
553
+ exports.middleware = middleware;
484
554
  exports.resolveAll = resolveAll;
485
555
 
486
556
  }));
@@ -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) => 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): 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): void;
28
+ private off;
29
+ }
@@ -0,0 +1,3 @@
1
+ import { DependencyClass, DependencyId } from '../types';
2
+ export declare const middlewaresClasses: Record<DependencyId, DependencyClass<any>>;
3
+ export declare function middleware(): any;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "proxydi",
3
- "version": "0.0.11",
3
+ "version": "0.0.12",
4
4
  "description": "A typed hierarchical DI container that resolves circular dependencies via Proxy",
5
5
  "type": "module",
6
6
  "main": "./dist/index.cjs",