ts-ioc-container 43.5.2 → 44.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.
Files changed (37) hide show
  1. package/README.md +47 -34
  2. package/cjm/container/AliasMap.js +5 -6
  3. package/cjm/container/Container.js +58 -56
  4. package/cjm/hooks/{runner/SyncHooksRunner.js → HooksRunner.js} +17 -6
  5. package/cjm/hooks/onConstruct.js +2 -2
  6. package/cjm/hooks/onDispose.js +4 -5
  7. package/cjm/index.js +5 -6
  8. package/cjm/injector/IInjector.js +7 -4
  9. package/cjm/provider/Provider.js +3 -2
  10. package/cjm/token/InstanceListToken.js +1 -9
  11. package/esm/container/AliasMap.js +5 -6
  12. package/esm/container/Container.js +59 -57
  13. package/esm/hooks/{runner/SyncHooksRunner.js → HooksRunner.js} +15 -4
  14. package/esm/hooks/onConstruct.js +2 -2
  15. package/esm/hooks/onDispose.js +3 -5
  16. package/esm/index.js +2 -2
  17. package/esm/injector/IInjector.js +7 -4
  18. package/esm/provider/Provider.js +4 -3
  19. package/esm/token/InstanceListToken.js +1 -9
  20. package/package.json +1 -1
  21. package/typings/container/AliasMap.d.ts +0 -1
  22. package/typings/container/Container.d.ts +11 -11
  23. package/typings/container/IContainer.d.ts +1 -1
  24. package/typings/hooks/HooksRunner.d.ts +17 -0
  25. package/typings/hooks/hook.d.ts +1 -1
  26. package/typings/hooks/onConstruct.d.ts +5 -5
  27. package/typings/hooks/onDispose.d.ts +5 -3
  28. package/typings/index.d.ts +2 -5
  29. package/typings/injector/IInjector.d.ts +3 -2
  30. package/typings/provider/IProvider.d.ts +1 -1
  31. package/cjm/hooks/runner/AsyncHooksRunner.js +0 -23
  32. package/cjm/hooks/runner/HooksRunner.js +0 -2
  33. package/esm/hooks/runner/AsyncHooksRunner.js +0 -19
  34. package/esm/hooks/runner/HooksRunner.js +0 -1
  35. package/typings/hooks/runner/AsyncHooksRunner.d.ts +0 -11
  36. package/typings/hooks/runner/HooksRunner.d.ts +0 -7
  37. package/typings/hooks/runner/SyncHooksRunner.d.ts +0 -6
package/README.md CHANGED
@@ -1394,28 +1394,18 @@ Sometimes you need to invoke methods after construct or dispose of class. This i
1394
1394
  ```typescript
1395
1395
  import {
1396
1396
  bindTo,
1397
- type constructor,
1398
1397
  Container,
1399
1398
  hook,
1400
- type IContainer,
1401
- type IInjector,
1402
- type InjectOptions,
1403
- MetadataInjector,
1399
+ HookContext,
1400
+ HookFn,
1401
+ HooksRunner,
1402
+ inject,
1403
+ onConstruct,
1404
1404
  register,
1405
1405
  Registration as R,
1406
- SyncHooksRunner,
1407
1406
  } from 'ts-ioc-container';
1408
1407
 
1409
- const onConstructHooksRunner = new SyncHooksRunner('onConstruct');
1410
- class MyInjector implements IInjector {
1411
- private injector = new MetadataInjector();
1412
-
1413
- resolve<T>(container: IContainer, value: constructor<T>, options: InjectOptions): T {
1414
- const instance = this.injector.resolve(container, value, options);
1415
- onConstructHooksRunner.execute(instance as object, { scope: container });
1416
- return instance;
1417
- }
1418
- }
1408
+ const onConstructHooksRunner = new HooksRunner('onConstruct');
1419
1409
 
1420
1410
  @register(bindTo('logger'))
1421
1411
  class Logger {
@@ -1435,31 +1425,54 @@ class Logger {
1435
1425
 
1436
1426
  describe('onConstruct', function () {
1437
1427
  it('should make logger be ready on resolve', function () {
1438
- const container = new Container({ injector: new MyInjector() }).addRegistration(R.fromClass(Logger));
1428
+ const container = new Container()
1429
+ .addOnConstructHook((instance, scope) => {
1430
+ onConstructHooksRunner.execute(instance as object, { scope });
1431
+ })
1432
+ .addRegistration(R.fromClass(Logger));
1439
1433
 
1440
1434
  const logger = container.resolve<Logger>('logger');
1441
1435
 
1442
1436
  expect(logger.isReady).toBe(true);
1443
1437
  });
1438
+
1439
+ it('should run methods and resolve arguments from container', function () {
1440
+ const execute: HookFn = (ctx: HookContext) => {
1441
+ ctx.invokeMethod({ args: ctx.resolveArgs() });
1442
+ };
1443
+
1444
+ class Car {
1445
+ private engine!: string;
1446
+
1447
+ @onConstruct(execute)
1448
+ setEngine(@inject('engine') engine: string) {
1449
+ this.engine = engine;
1450
+ }
1451
+
1452
+ getEngine() {
1453
+ return this.engine;
1454
+ }
1455
+ }
1456
+
1457
+ const root = new Container()
1458
+ .addOnConstructHook((instance, scope) => {
1459
+ onConstructHooksRunner.execute(instance as object, { scope });
1460
+ })
1461
+ .addRegistration(R.fromValue('bmw').bindTo('engine'));
1462
+
1463
+ const car = root.resolve(Car);
1464
+
1465
+ expect(car.getEngine()).toBe('bmw');
1466
+ });
1444
1467
  });
1445
1468
 
1446
1469
  ```
1447
1470
 
1448
1471
  ### OnDispose
1449
1472
  ```typescript
1450
- import {
1451
- bindTo,
1452
- Container,
1453
- hook,
1454
- inject,
1455
- register,
1456
- Registration as R,
1457
- select,
1458
- singleton,
1459
- SyncHooksRunner,
1460
- } from 'ts-ioc-container';
1473
+ import { bindTo, Container, hook, HooksRunner, inject, register, Registration as R, select, singleton } from 'ts-ioc-container';
1461
1474
 
1462
- const onDisposeHookRunner = new SyncHooksRunner('onDispose');
1475
+ const onDisposeHookRunner = new HooksRunner('onDispose');
1463
1476
  @register(bindTo('logsRepo'), singleton())
1464
1477
  class LogsRepo {
1465
1478
  savedLogs: string[] = [];
@@ -1515,9 +1528,9 @@ describe('onDispose', function () {
1515
1528
  ### Inject property
1516
1529
 
1517
1530
  ```typescript
1518
- import { Container, hook, injectProp, Registration, SyncHooksRunner } from 'ts-ioc-container';
1531
+ import { Container, hook, HooksRunner, injectProp, Registration } from 'ts-ioc-container';
1519
1532
 
1520
- const onInitHookRunner = new SyncHooksRunner('onInit');
1533
+ const onInitHookRunner = new HooksRunner('onInit');
1521
1534
  describe('inject property', () => {
1522
1535
  it('should inject property', () => {
1523
1536
  class App {
@@ -1526,9 +1539,9 @@ describe('inject property', () => {
1526
1539
  }
1527
1540
  const expected = 'Hello world!';
1528
1541
 
1529
- const container = new Container().addRegistration(Registration.fromValue(expected).bindToKey('greeting'));
1530
- const app = container.resolve(App);
1531
- onInitHookRunner.execute(app as object, { scope: container });
1542
+ const scope = new Container().addRegistration(Registration.fromValue(expected).bindToKey('greeting'));
1543
+ const app = scope.resolve(App);
1544
+ onInitHookRunner.execute(app, { scope });
1532
1545
 
1533
1546
  expect(app.greeting).toBe(expected);
1534
1547
  });
@@ -3,18 +3,17 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.AliasMap = void 0;
4
4
  class AliasMap {
5
5
  aliasToKeySet = new Map();
6
- deleteAliasesByKey(key) {
6
+ getKeysByAlias(alias) {
7
+ return [...(this.aliasToKeySet.get(alias) ?? [])];
8
+ }
9
+ setAliasesByKey(key, aliases) {
10
+ // reset existing key's aliases
7
11
  for (const [alias, keySet] of this.aliasToKeySet) {
8
12
  keySet.delete(key);
9
13
  if (keySet.size === 0) {
10
14
  this.aliasToKeySet.delete(alias);
11
15
  }
12
16
  }
13
- }
14
- getKeysByAlias(alias) {
15
- return [...(this.aliasToKeySet.get(alias) ?? [])];
16
- }
17
- setAliasesByKey(key, aliases) {
18
17
  for (const alias of aliases) {
19
18
  const dependencyKeySet = this.aliasToKeySet.get(alias) ?? new Set();
20
19
  this.aliasToKeySet.set(alias, dependencyKeySet.add(key));
@@ -10,12 +10,12 @@ const DependencyNotFoundError_1 = require("../errors/DependencyNotFoundError");
10
10
  class Container {
11
11
  isDisposed = false;
12
12
  parent;
13
- scopes = new Set();
14
- instances = new Set();
13
+ scopes = [];
14
+ instances = [];
15
+ registrations = [];
15
16
  tags;
16
17
  providers = new Map();
17
18
  aliases = new AliasMap_1.AliasMap();
18
- registrations = new Set();
19
19
  injector;
20
20
  onConstructHookList = [];
21
21
  onDisposeHookList = [];
@@ -24,45 +24,21 @@ class Container {
24
24
  this.parent = options.parent ?? new EmptyContainer_1.EmptyContainer();
25
25
  this.tags = new Set(options.tags ?? []);
26
26
  }
27
- addOnConstructHook(...hooks) {
28
- this.onConstructHookList.push(...hooks);
29
- return this;
30
- }
31
- addOnDisposeHook(...hooks) {
32
- this.onDisposeHookList.push(...hooks);
33
- return this;
34
- }
35
- addInstance(instance) {
36
- this.instances.add(instance);
37
- // Execute onConstruct hooks
38
- for (const onConstruct of this.onConstructHookList) {
39
- onConstruct(instance, this);
40
- }
41
- }
42
27
  register(key, provider, { aliases = [] } = {}) {
43
28
  this.validateContainer();
44
29
  this.providers.set(key, provider);
45
- this.aliases.deleteAliasesByKey(key);
46
30
  this.aliases.setAliasesByKey(key, aliases);
47
31
  return this;
48
32
  }
49
- addRegistration(registration) {
50
- this.registrations.add(registration);
51
- registration.applyTo(this);
52
- return this;
53
- }
54
- getRegistrations() {
55
- return [...this.parent.getRegistrations(), ...this.registrations];
56
- }
57
- resolve(keyOrAlias, { args = [], child = this, lazy } = {}) {
33
+ resolve(key, { args = [], child = this, lazy } = {}) {
58
34
  this.validateContainer();
59
- if (utils_1.Is.constructor(keyOrAlias)) {
60
- return (0, utils_1.toLazyIf)(() => this.injector.resolve(this, keyOrAlias, { args }), lazy);
35
+ if (utils_1.Is.constructor(key)) {
36
+ return this.injector.resolve(this, key, { args, lazy });
61
37
  }
62
- const provider = this.providers.get(keyOrAlias);
38
+ const provider = this.providers.get(key);
63
39
  return provider?.hasAccess({ invocationScope: child, providerScope: this })
64
40
  ? provider.resolve(this, { args, lazy })
65
- : this.parent.resolve(keyOrAlias, { args, child, lazy });
41
+ : this.parent.resolve(key, { args, child, lazy });
66
42
  }
67
43
  resolveByAlias(alias, { args = [], child = this, lazy, excludedKeys = [] } = {}) {
68
44
  this.validateContainer();
@@ -87,7 +63,7 @@ class Container {
87
63
  resolveOneByAlias(alias, { args = [], child = this, lazy } = {}) {
88
64
  this.validateContainer();
89
65
  const [key, ..._] = this.aliases.getKeysByAlias(alias);
90
- const provider = key !== undefined ? this.findProviderByKeyOrFail(key) : undefined;
66
+ const provider = key ? this.findProviderByKeyOrFail(key) : undefined;
91
67
  return provider?.hasAccess({ invocationScope: child, providerScope: this })
92
68
  ? provider.resolve(this, { args, lazy })
93
69
  : this.parent.resolveOneByAlias(key, { args, child, lazy });
@@ -100,14 +76,56 @@ class Container {
100
76
  for (const registration of this.getRegistrations()) {
101
77
  registration.applyTo(scope);
102
78
  }
103
- this.scopes.add(scope);
79
+ this.scopes.push(scope);
104
80
  return scope;
105
81
  }
82
+ dispose() {
83
+ this.validateContainer();
84
+ this.isDisposed = true;
85
+ // Execute onDispose hooks
86
+ while (this.onDisposeHookList.length) {
87
+ const onDispose = this.onDisposeHookList.shift();
88
+ onDispose(this);
89
+ }
90
+ // Detach from parent
91
+ this.parent.removeScope(this);
92
+ this.parent = new EmptyContainer_1.EmptyContainer();
93
+ // Reset the state
94
+ this.providers.clear();
95
+ this.aliases.destroy();
96
+ this.instances = [];
97
+ this.registrations = [];
98
+ // Clear hooks
99
+ this.onConstructHookList.splice(0, this.onConstructHookList.length);
100
+ }
101
+ addRegistration(registration) {
102
+ this.registrations.push(registration);
103
+ registration.applyTo(this);
104
+ return this;
105
+ }
106
+ getRegistrations() {
107
+ return [...this.parent.getRegistrations(), ...this.registrations];
108
+ }
109
+ addOnConstructHook(...hooks) {
110
+ this.onConstructHookList.push(...hooks);
111
+ return this;
112
+ }
113
+ addOnDisposeHook(...hooks) {
114
+ this.onDisposeHookList.push(...hooks);
115
+ return this;
116
+ }
117
+ addInstance(instance) {
118
+ this.instances.push(instance);
119
+ // Execute onConstruct hooks
120
+ for (const onConstruct of this.onConstructHookList) {
121
+ onConstruct(instance, this);
122
+ }
123
+ }
106
124
  getScopes() {
107
125
  return [...this.scopes];
108
126
  }
109
127
  removeScope(child) {
110
- this.scopes.delete(child);
128
+ this.scopes = this.scopes.filter((s) => s !== child);
111
129
  }
112
130
  useModule(module) {
113
131
  module.applyTo(this);
@@ -116,31 +134,15 @@ class Container {
116
134
  getParent() {
117
135
  return this.parent;
118
136
  }
119
- getInstances() {
120
- return [...this.instances];
137
+ getInstances(cascade = false) {
138
+ if (!cascade) {
139
+ return [...this.instances];
140
+ }
141
+ return [...this.instances, ...this.scopes.flatMap((s) => s.getInstances(true))];
121
142
  }
122
143
  hasTag(tag) {
123
144
  return this.tags.has(tag);
124
145
  }
125
- dispose() {
126
- this.validateContainer();
127
- this.isDisposed = true;
128
- // Detach from parent
129
- this.parent.removeScope(this);
130
- this.parent = new EmptyContainer_1.EmptyContainer();
131
- // Reset the state
132
- this.providers.clear();
133
- this.aliases.destroy();
134
- this.instances.clear();
135
- this.registrations.clear();
136
- // Clear hooks
137
- this.onConstructHookList.splice(0, this.onConstructHookList.length);
138
- // Execute onDispose hooks
139
- while (this.onDisposeHookList.length) {
140
- const onDispose = this.onDisposeHookList.shift();
141
- onDispose(this);
142
- }
143
- }
144
146
  validateContainer() {
145
147
  if (this.isDisposed) {
146
148
  throw new ContainerDisposedError_1.ContainerDisposedError('Container is already disposed');
@@ -1,10 +1,11 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.SyncHooksRunner = void 0;
4
- const HookContext_1 = require("../HookContext");
5
- const hook_1 = require("../hook");
6
- const UnexpectedHookResultError_1 = require("../../errors/UnexpectedHookResultError");
7
- class SyncHooksRunner {
3
+ exports.HooksRunner = void 0;
4
+ const HookContext_1 = require("./HookContext");
5
+ const hook_1 = require("./hook");
6
+ const UnexpectedHookResultError_1 = require("../errors/UnexpectedHookResultError");
7
+ const utils_1 = require("../utils");
8
+ class HooksRunner {
8
9
  key;
9
10
  constructor(key) {
10
11
  this.key = key;
@@ -24,5 +25,15 @@ class SyncHooksRunner {
24
25
  runMethodHooks(methodName, executions.map(hook_1.toHookFn));
25
26
  }
26
27
  }
28
+ async executeAsync(target, { scope, createContext = HookContext_1.createHookContext, predicate = () => true, }) {
29
+ const hooks = Array.from((0, hook_1.getHooks)(target, this.key).entries()).filter(([methodName]) => predicate(methodName));
30
+ const runMethodHooks = async (methodName, executions) => {
31
+ const context = createContext(target, scope, methodName);
32
+ for (const execute of executions) {
33
+ await (0, utils_1.promisify)(execute(context));
34
+ }
35
+ };
36
+ return Promise.all(hooks.map(([methodName, executions]) => runMethodHooks(methodName, executions.map(hook_1.toHookFn))));
37
+ }
27
38
  }
28
- exports.SyncHooksRunner = SyncHooksRunner;
39
+ exports.HooksRunner = HooksRunner;
@@ -2,7 +2,7 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.onConstruct = exports.onConstructHooksRunner = void 0;
4
4
  const hook_1 = require("./hook");
5
- const SyncHooksRunner_1 = require("./runner/SyncHooksRunner");
6
- exports.onConstructHooksRunner = new SyncHooksRunner_1.SyncHooksRunner('onConstruct');
5
+ const HooksRunner_1 = require("./HooksRunner");
6
+ exports.onConstructHooksRunner = new HooksRunner_1.HooksRunner('onConstruct');
7
7
  const onConstruct = (fn) => (0, hook_1.hook)('onConstruct', fn);
8
8
  exports.onConstruct = onConstruct;
@@ -2,8 +2,7 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.onDispose = exports.onDisposeHooksRunner = void 0;
4
4
  const hook_1 = require("./hook");
5
- const SyncHooksRunner_1 = require("./runner/SyncHooksRunner");
6
- exports.onDisposeHooksRunner = new SyncHooksRunner_1.SyncHooksRunner('onDispose');
7
- exports.onDispose = (0, hook_1.hook)('onDispose', (context) => {
8
- context.invokeMethod({});
9
- });
5
+ const HooksRunner_1 = require("./HooksRunner");
6
+ exports.onDisposeHooksRunner = new HooksRunner_1.HooksRunner('onDispose');
7
+ const onDispose = (fn) => (0, hook_1.hook)('onDispose', fn);
8
+ exports.onDispose = onDispose;
package/cjm/index.js CHANGED
@@ -1,7 +1,7 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.AliasUniqToken = exports.toAlias = exports.AliasToken = exports.InjectionToken = exports.getParameterMetadata = exports.getMethodMetadata = exports.setMethodMetadata = exports.setParameterMetadata = exports.getMetadata = exports.setMetadata = exports.SyncHooksRunner = exports.AsyncHooksRunner = exports.onDispose = exports.onDisposeHooksRunner = exports.onConstruct = exports.onConstructHooksRunner = exports.injectProp = exports.HookContext = exports.hasHooks = exports.hook = exports.getHooks = exports.UnexpectedHookResultError = exports.ContainerDisposedError = exports.MethodNotImplementedError = exports.DependencyMissingKeyError = exports.DependencyNotFoundError = exports.Registration = exports.bindTo = exports.register = exports.scope = exports.decorate = exports.MultiCache = exports.multiCache = exports.SingletonProvider = exports.singleton = exports.Provider = exports.resolveByArgs = exports.ProviderDecorator = exports.args = exports.argsFn = exports.lazy = exports.scopeAccess = exports.ProxyInjector = exports.SimpleInjector = exports.MetadataInjector = exports.resolveArgs = exports.inject = exports.EmptyContainer = exports.Container = exports.isDependencyKey = void 0;
4
- exports.Is = exports.select = exports.toToken = exports.InstanceListToken = exports.ConstantToken = exports.FunctionToken = exports.IDToken = exports.ClassToken = exports.toAliasUniq = void 0;
3
+ exports.toAliasUniq = exports.AliasUniqToken = exports.toAlias = exports.AliasToken = exports.InjectionToken = exports.getParameterMetadata = exports.getMethodMetadata = exports.setMethodMetadata = exports.setParameterMetadata = exports.getMetadata = exports.setMetadata = exports.HooksRunner = exports.onDispose = exports.onDisposeHooksRunner = exports.onConstruct = exports.onConstructHooksRunner = exports.injectProp = exports.HookContext = exports.hasHooks = exports.hook = exports.getHooks = exports.UnexpectedHookResultError = exports.ContainerDisposedError = exports.MethodNotImplementedError = exports.DependencyMissingKeyError = exports.DependencyNotFoundError = exports.Registration = exports.bindTo = exports.register = exports.scope = exports.decorate = exports.MultiCache = exports.multiCache = exports.SingletonProvider = exports.singleton = exports.Provider = exports.resolveByArgs = exports.ProviderDecorator = exports.args = exports.argsFn = exports.lazy = exports.scopeAccess = exports.ProxyInjector = exports.SimpleInjector = exports.MetadataInjector = exports.resolveArgs = exports.inject = exports.EmptyContainer = exports.Container = exports.isDependencyKey = void 0;
4
+ exports.Is = exports.select = exports.toToken = exports.InstanceListToken = exports.ConstantToken = exports.FunctionToken = exports.IDToken = exports.ClassToken = void 0;
5
5
  // Containers
6
6
  var IContainer_1 = require("./container/IContainer");
7
7
  Object.defineProperty(exports, "isDependencyKey", { enumerable: true, get: function () { return IContainer_1.isDependencyKey; } });
@@ -70,10 +70,9 @@ Object.defineProperty(exports, "onConstruct", { enumerable: true, get: function
70
70
  var onDispose_1 = require("./hooks/onDispose");
71
71
  Object.defineProperty(exports, "onDisposeHooksRunner", { enumerable: true, get: function () { return onDispose_1.onDisposeHooksRunner; } });
72
72
  Object.defineProperty(exports, "onDispose", { enumerable: true, get: function () { return onDispose_1.onDispose; } });
73
- var AsyncHooksRunner_1 = require("./hooks/runner/AsyncHooksRunner");
74
- Object.defineProperty(exports, "AsyncHooksRunner", { enumerable: true, get: function () { return AsyncHooksRunner_1.AsyncHooksRunner; } });
75
- var SyncHooksRunner_1 = require("./hooks/runner/SyncHooksRunner");
76
- Object.defineProperty(exports, "SyncHooksRunner", { enumerable: true, get: function () { return SyncHooksRunner_1.SyncHooksRunner; } });
73
+ // Hooks runner
74
+ var HooksRunner_1 = require("./hooks/HooksRunner");
75
+ Object.defineProperty(exports, "HooksRunner", { enumerable: true, get: function () { return HooksRunner_1.HooksRunner; } });
77
76
  // Metadata
78
77
  var metadata_1 = require("./metadata");
79
78
  Object.defineProperty(exports, "setMetadata", { enumerable: true, get: function () { return metadata_1.setMetadata; } });
@@ -1,11 +1,14 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.Injector = void 0;
4
+ const utils_1 = require("../utils");
4
5
  class Injector {
5
- resolve(scope, Target, options) {
6
- const instance = this.createInstance(scope, Target, options);
7
- scope.addInstance(instance);
8
- return instance;
6
+ resolve(scope, Target, { args, lazy } = {}) {
7
+ return (0, utils_1.toLazyIf)(() => {
8
+ const instance = this.createInstance(scope, Target, { args });
9
+ scope.addInstance(instance);
10
+ return instance;
11
+ }, lazy);
9
12
  }
10
13
  }
11
14
  exports.Injector = Injector;
@@ -25,9 +25,10 @@ class Provider {
25
25
  return (0, utils_1.pipe)(...fns)(this);
26
26
  }
27
27
  resolve(container, { args = [], lazy } = {}) {
28
- return (0, utils_1.toLazyIf)(() => this.resolveDependency(container, {
28
+ return this.resolveDependency(container, {
29
29
  args: [...this.argsFn(container, ...args), ...args],
30
- }), lazy ?? this.isLazy);
30
+ lazy: lazy ?? this.isLazy,
31
+ });
31
32
  }
32
33
  setAccessPredicate(predicate) {
33
34
  this.checkAccess = predicate;
@@ -24,15 +24,7 @@ class InstanceListToken extends InjectionToken_1.InjectionToken {
24
24
  return this;
25
25
  }
26
26
  resolve(c) {
27
- const result = new Set(c.getInstances().filter(this.predicate));
28
- if (this.isCascade) {
29
- for (const s of c.getScopes()) {
30
- for (const instance of s.getInstances().filter(this.predicate)) {
31
- result.add(instance);
32
- }
33
- }
34
- }
35
- return [...result];
27
+ return c.getInstances(this.isCascade).filter(this.predicate);
36
28
  }
37
29
  }
38
30
  exports.InstanceListToken = InstanceListToken;
@@ -1,17 +1,16 @@
1
1
  export class AliasMap {
2
2
  aliasToKeySet = new Map();
3
- deleteAliasesByKey(key) {
3
+ getKeysByAlias(alias) {
4
+ return [...(this.aliasToKeySet.get(alias) ?? [])];
5
+ }
6
+ setAliasesByKey(key, aliases) {
7
+ // reset existing key's aliases
4
8
  for (const [alias, keySet] of this.aliasToKeySet) {
5
9
  keySet.delete(key);
6
10
  if (keySet.size === 0) {
7
11
  this.aliasToKeySet.delete(alias);
8
12
  }
9
13
  }
10
- }
11
- getKeysByAlias(alias) {
12
- return [...(this.aliasToKeySet.get(alias) ?? [])];
13
- }
14
- setAliasesByKey(key, aliases) {
15
14
  for (const alias of aliases) {
16
15
  const dependencyKeySet = this.aliasToKeySet.get(alias) ?? new Set();
17
16
  this.aliasToKeySet.set(alias, dependencyKeySet.add(key));
@@ -1,18 +1,18 @@
1
1
  import { EmptyContainer } from './EmptyContainer';
2
2
  import { ContainerDisposedError } from '../errors/ContainerDisposedError';
3
3
  import { MetadataInjector } from '../injector/MetadataInjector';
4
- import { Filter as F, Is, toLazyIf } from '../utils';
4
+ import { Filter as F, Is } from '../utils';
5
5
  import { AliasMap } from './AliasMap';
6
6
  import { DependencyNotFoundError } from '../errors/DependencyNotFoundError';
7
7
  export class Container {
8
8
  isDisposed = false;
9
9
  parent;
10
- scopes = new Set();
11
- instances = new Set();
10
+ scopes = [];
11
+ instances = [];
12
+ registrations = [];
12
13
  tags;
13
14
  providers = new Map();
14
15
  aliases = new AliasMap();
15
- registrations = new Set();
16
16
  injector;
17
17
  onConstructHookList = [];
18
18
  onDisposeHookList = [];
@@ -21,45 +21,21 @@ export class Container {
21
21
  this.parent = options.parent ?? new EmptyContainer();
22
22
  this.tags = new Set(options.tags ?? []);
23
23
  }
24
- addOnConstructHook(...hooks) {
25
- this.onConstructHookList.push(...hooks);
26
- return this;
27
- }
28
- addOnDisposeHook(...hooks) {
29
- this.onDisposeHookList.push(...hooks);
30
- return this;
31
- }
32
- addInstance(instance) {
33
- this.instances.add(instance);
34
- // Execute onConstruct hooks
35
- for (const onConstruct of this.onConstructHookList) {
36
- onConstruct(instance, this);
37
- }
38
- }
39
24
  register(key, provider, { aliases = [] } = {}) {
40
25
  this.validateContainer();
41
26
  this.providers.set(key, provider);
42
- this.aliases.deleteAliasesByKey(key);
43
27
  this.aliases.setAliasesByKey(key, aliases);
44
28
  return this;
45
29
  }
46
- addRegistration(registration) {
47
- this.registrations.add(registration);
48
- registration.applyTo(this);
49
- return this;
50
- }
51
- getRegistrations() {
52
- return [...this.parent.getRegistrations(), ...this.registrations];
53
- }
54
- resolve(keyOrAlias, { args = [], child = this, lazy } = {}) {
30
+ resolve(key, { args = [], child = this, lazy } = {}) {
55
31
  this.validateContainer();
56
- if (Is.constructor(keyOrAlias)) {
57
- return toLazyIf(() => this.injector.resolve(this, keyOrAlias, { args }), lazy);
32
+ if (Is.constructor(key)) {
33
+ return this.injector.resolve(this, key, { args, lazy });
58
34
  }
59
- const provider = this.providers.get(keyOrAlias);
35
+ const provider = this.providers.get(key);
60
36
  return provider?.hasAccess({ invocationScope: child, providerScope: this })
61
37
  ? provider.resolve(this, { args, lazy })
62
- : this.parent.resolve(keyOrAlias, { args, child, lazy });
38
+ : this.parent.resolve(key, { args, child, lazy });
63
39
  }
64
40
  resolveByAlias(alias, { args = [], child = this, lazy, excludedKeys = [] } = {}) {
65
41
  this.validateContainer();
@@ -84,7 +60,7 @@ export class Container {
84
60
  resolveOneByAlias(alias, { args = [], child = this, lazy } = {}) {
85
61
  this.validateContainer();
86
62
  const [key, ..._] = this.aliases.getKeysByAlias(alias);
87
- const provider = key !== undefined ? this.findProviderByKeyOrFail(key) : undefined;
63
+ const provider = key ? this.findProviderByKeyOrFail(key) : undefined;
88
64
  return provider?.hasAccess({ invocationScope: child, providerScope: this })
89
65
  ? provider.resolve(this, { args, lazy })
90
66
  : this.parent.resolveOneByAlias(key, { args, child, lazy });
@@ -97,14 +73,56 @@ export class Container {
97
73
  for (const registration of this.getRegistrations()) {
98
74
  registration.applyTo(scope);
99
75
  }
100
- this.scopes.add(scope);
76
+ this.scopes.push(scope);
101
77
  return scope;
102
78
  }
79
+ dispose() {
80
+ this.validateContainer();
81
+ this.isDisposed = true;
82
+ // Execute onDispose hooks
83
+ while (this.onDisposeHookList.length) {
84
+ const onDispose = this.onDisposeHookList.shift();
85
+ onDispose(this);
86
+ }
87
+ // Detach from parent
88
+ this.parent.removeScope(this);
89
+ this.parent = new EmptyContainer();
90
+ // Reset the state
91
+ this.providers.clear();
92
+ this.aliases.destroy();
93
+ this.instances = [];
94
+ this.registrations = [];
95
+ // Clear hooks
96
+ this.onConstructHookList.splice(0, this.onConstructHookList.length);
97
+ }
98
+ addRegistration(registration) {
99
+ this.registrations.push(registration);
100
+ registration.applyTo(this);
101
+ return this;
102
+ }
103
+ getRegistrations() {
104
+ return [...this.parent.getRegistrations(), ...this.registrations];
105
+ }
106
+ addOnConstructHook(...hooks) {
107
+ this.onConstructHookList.push(...hooks);
108
+ return this;
109
+ }
110
+ addOnDisposeHook(...hooks) {
111
+ this.onDisposeHookList.push(...hooks);
112
+ return this;
113
+ }
114
+ addInstance(instance) {
115
+ this.instances.push(instance);
116
+ // Execute onConstruct hooks
117
+ for (const onConstruct of this.onConstructHookList) {
118
+ onConstruct(instance, this);
119
+ }
120
+ }
103
121
  getScopes() {
104
122
  return [...this.scopes];
105
123
  }
106
124
  removeScope(child) {
107
- this.scopes.delete(child);
125
+ this.scopes = this.scopes.filter((s) => s !== child);
108
126
  }
109
127
  useModule(module) {
110
128
  module.applyTo(this);
@@ -113,31 +131,15 @@ export class Container {
113
131
  getParent() {
114
132
  return this.parent;
115
133
  }
116
- getInstances() {
117
- return [...this.instances];
134
+ getInstances(cascade = false) {
135
+ if (!cascade) {
136
+ return [...this.instances];
137
+ }
138
+ return [...this.instances, ...this.scopes.flatMap((s) => s.getInstances(true))];
118
139
  }
119
140
  hasTag(tag) {
120
141
  return this.tags.has(tag);
121
142
  }
122
- dispose() {
123
- this.validateContainer();
124
- this.isDisposed = true;
125
- // Detach from parent
126
- this.parent.removeScope(this);
127
- this.parent = new EmptyContainer();
128
- // Reset the state
129
- this.providers.clear();
130
- this.aliases.destroy();
131
- this.instances.clear();
132
- this.registrations.clear();
133
- // Clear hooks
134
- this.onConstructHookList.splice(0, this.onConstructHookList.length);
135
- // Execute onDispose hooks
136
- while (this.onDisposeHookList.length) {
137
- const onDispose = this.onDisposeHookList.shift();
138
- onDispose(this);
139
- }
140
- }
141
143
  validateContainer() {
142
144
  if (this.isDisposed) {
143
145
  throw new ContainerDisposedError('Container is already disposed');
@@ -1,7 +1,8 @@
1
- import { createHookContext } from '../HookContext';
2
- import { getHooks, toHookFn } from '../hook';
3
- import { UnexpectedHookResultError } from '../../errors/UnexpectedHookResultError';
4
- export class SyncHooksRunner {
1
+ import { createHookContext } from './HookContext';
2
+ import { getHooks, toHookFn } from './hook';
3
+ import { UnexpectedHookResultError } from '../errors/UnexpectedHookResultError';
4
+ import { promisify } from '../utils';
5
+ export class HooksRunner {
5
6
  key;
6
7
  constructor(key) {
7
8
  this.key = key;
@@ -21,4 +22,14 @@ export class SyncHooksRunner {
21
22
  runMethodHooks(methodName, executions.map(toHookFn));
22
23
  }
23
24
  }
25
+ async executeAsync(target, { scope, createContext = createHookContext, predicate = () => true, }) {
26
+ const hooks = Array.from(getHooks(target, this.key).entries()).filter(([methodName]) => predicate(methodName));
27
+ const runMethodHooks = async (methodName, executions) => {
28
+ const context = createContext(target, scope, methodName);
29
+ for (const execute of executions) {
30
+ await promisify(execute(context));
31
+ }
32
+ };
33
+ return Promise.all(hooks.map(([methodName, executions]) => runMethodHooks(methodName, executions.map(toHookFn))));
34
+ }
24
35
  }
@@ -1,4 +1,4 @@
1
1
  import { hook } from './hook';
2
- import { SyncHooksRunner } from './runner/SyncHooksRunner';
3
- export const onConstructHooksRunner = new SyncHooksRunner('onConstruct');
2
+ import { HooksRunner } from './HooksRunner';
3
+ export const onConstructHooksRunner = new HooksRunner('onConstruct');
4
4
  export const onConstruct = (fn) => hook('onConstruct', fn);
@@ -1,6 +1,4 @@
1
1
  import { hook } from './hook';
2
- import { SyncHooksRunner } from './runner/SyncHooksRunner';
3
- export const onDisposeHooksRunner = new SyncHooksRunner('onDispose');
4
- export const onDispose = hook('onDispose', (context) => {
5
- context.invokeMethod({});
6
- });
2
+ import { HooksRunner } from './HooksRunner';
3
+ export const onDisposeHooksRunner = new HooksRunner('onDispose');
4
+ export const onDispose = (fn) => hook('onDispose', fn);
package/esm/index.js CHANGED
@@ -28,8 +28,8 @@ export { HookContext } from './hooks/HookContext';
28
28
  export { injectProp } from './hooks/injectProp';
29
29
  export { onConstructHooksRunner, onConstruct } from './hooks/onConstruct';
30
30
  export { onDisposeHooksRunner, onDispose } from './hooks/onDispose';
31
- export { AsyncHooksRunner } from './hooks/runner/AsyncHooksRunner';
32
- export { SyncHooksRunner } from './hooks/runner/SyncHooksRunner';
31
+ // Hooks runner
32
+ export { HooksRunner } from './hooks/HooksRunner';
33
33
  // Metadata
34
34
  export { setMetadata, getMetadata, setParameterMetadata, setMethodMetadata, getMethodMetadata, getParameterMetadata, } from './metadata';
35
35
  // InjectionToken
@@ -1,7 +1,10 @@
1
+ import { toLazyIf } from '../utils';
1
2
  export class Injector {
2
- resolve(scope, Target, options) {
3
- const instance = this.createInstance(scope, Target, options);
4
- scope.addInstance(instance);
5
- return instance;
3
+ resolve(scope, Target, { args, lazy } = {}) {
4
+ return toLazyIf(() => {
5
+ const instance = this.createInstance(scope, Target, { args });
6
+ scope.addInstance(instance);
7
+ return instance;
8
+ }, lazy);
6
9
  }
7
10
  }
@@ -1,4 +1,4 @@
1
- import { pipe, toLazyIf } from '../utils';
1
+ import { pipe } from '../utils';
2
2
  import { isProviderPipe } from './ProviderPipe';
3
3
  export class Provider {
4
4
  resolveDependency;
@@ -22,9 +22,10 @@ export class Provider {
22
22
  return pipe(...fns)(this);
23
23
  }
24
24
  resolve(container, { args = [], lazy } = {}) {
25
- return toLazyIf(() => this.resolveDependency(container, {
25
+ return this.resolveDependency(container, {
26
26
  args: [...this.argsFn(container, ...args), ...args],
27
- }), lazy ?? this.isLazy);
27
+ lazy: lazy ?? this.isLazy,
28
+ });
28
29
  }
29
30
  setAccessPredicate(predicate) {
30
31
  this.checkAccess = predicate;
@@ -21,14 +21,6 @@ export class InstanceListToken extends InjectionToken {
21
21
  return this;
22
22
  }
23
23
  resolve(c) {
24
- const result = new Set(c.getInstances().filter(this.predicate));
25
- if (this.isCascade) {
26
- for (const s of c.getScopes()) {
27
- for (const instance of s.getInstances().filter(this.predicate)) {
28
- result.add(instance);
29
- }
30
- }
31
- }
32
- return [...result];
24
+ return c.getInstances(this.isCascade).filter(this.predicate);
33
25
  }
34
26
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ts-ioc-container",
3
- "version": "43.5.2",
3
+ "version": "44.0.0",
4
4
  "description": "Typescript IoC container",
5
5
  "publishConfig": {
6
6
  "access": "public",
@@ -2,7 +2,6 @@ import { type DependencyKey } from './IContainer';
2
2
  export type Alias = DependencyKey;
3
3
  export declare class AliasMap {
4
4
  private readonly aliasToKeySet;
5
- deleteAliasesByKey(key: DependencyKey): void;
6
5
  getKeysByAlias(alias: DependencyKey): DependencyKey[];
7
6
  setAliasesByKey(key: DependencyKey, aliases: DependencyKey[]): void;
8
7
  destroy(): void;
@@ -8,12 +8,12 @@ import { constructor, Instance } from '../types';
8
8
  export declare class Container implements IContainer {
9
9
  isDisposed: boolean;
10
10
  private parent;
11
- private readonly scopes;
12
- private readonly instances;
11
+ private scopes;
12
+ private instances;
13
+ private registrations;
13
14
  private readonly tags;
14
15
  private readonly providers;
15
16
  private readonly aliases;
16
- private readonly registrations;
17
17
  private readonly injector;
18
18
  private readonly onConstructHookList;
19
19
  private readonly onDisposeHookList;
@@ -22,23 +22,23 @@ export declare class Container implements IContainer {
22
22
  parent?: IContainer;
23
23
  tags?: Tag[];
24
24
  });
25
- addOnConstructHook(...hooks: OnConstructHook[]): this;
26
- addOnDisposeHook(...hooks: OnDisposeHook[]): this;
27
- addInstance(instance: Instance): void;
28
25
  register(key: DependencyKey, provider: IProvider, { aliases }?: RegisterOptions): this;
29
- addRegistration(registration: IRegistration): this;
30
- getRegistrations(): IRegistration[];
31
- resolve<T>(keyOrAlias: constructor<T> | DependencyKey, { args, child, lazy }?: ResolveOneOptions): T;
26
+ resolve<T>(key: constructor<T> | DependencyKey, { args, child, lazy }?: ResolveOneOptions): T;
32
27
  resolveByAlias<T>(alias: DependencyKey, { args, child, lazy, excludedKeys }?: ResolveManyOptions): T[];
33
28
  resolveOneByAlias<T>(alias: DependencyKey, { args, child, lazy }?: ResolveOneOptions): T;
34
29
  createScope({ tags }?: CreateScopeOptions): IContainer;
30
+ dispose(): void;
31
+ addRegistration(registration: IRegistration): this;
32
+ getRegistrations(): IRegistration[];
33
+ addOnConstructHook(...hooks: OnConstructHook[]): this;
34
+ addOnDisposeHook(...hooks: OnDisposeHook[]): this;
35
+ addInstance(instance: Instance): void;
35
36
  getScopes(): IContainer[];
36
37
  removeScope(child: IContainer): void;
37
38
  useModule(module: IContainerModule): this;
38
39
  getParent(): IContainer;
39
- getInstances(): Instance<unknown>[];
40
+ getInstances(cascade?: boolean): Instance<unknown>[];
40
41
  hasTag(tag: Tag): boolean;
41
- dispose(): void;
42
42
  private validateContainer;
43
43
  private findProviderByKeyOrFail;
44
44
  }
@@ -41,7 +41,7 @@ export interface IContainer extends Tagged {
41
41
  removeScope(child: IContainer): void;
42
42
  useModule(module: IContainerModule): this;
43
43
  getParent(): IContainer | undefined;
44
- getInstances(): Instance[];
44
+ getInstances(cascade?: boolean): Instance[];
45
45
  dispose(): void;
46
46
  addInstance(instance: Instance): void;
47
47
  }
@@ -0,0 +1,17 @@
1
+ import { createHookContext, type CreateHookContext } from './HookContext';
2
+ import type { IContainer } from '../container/IContainer';
3
+ export type HooksRunnerContext = {
4
+ scope: IContainer;
5
+ createContext?: CreateHookContext;
6
+ predicate?: (methodName: string) => boolean;
7
+ };
8
+ export declare class HooksRunner {
9
+ private readonly key;
10
+ constructor(key: string | symbol);
11
+ execute(target: object, { scope, createContext, predicate }: HooksRunnerContext): void;
12
+ executeAsync(target: object, { scope, createContext, predicate, }: {
13
+ scope: IContainer;
14
+ createContext?: typeof createHookContext;
15
+ predicate?: (methodName: string) => boolean;
16
+ }): Promise<void[]>;
17
+ }
@@ -6,8 +6,8 @@ export type HookFn<T extends IHookContext = IHookContext> = (context: T) => void
6
6
  export interface HookClass<T extends IHookContext = IHookContext> {
7
7
  execute(context: Omit<T, 'scope'>): void | Promise<void>;
8
8
  }
9
- export declare const toHookFn: <C extends IHookContext>(execute: HookFn<C> | constructor<HookClass<C>>) => HookFn<C>;
10
9
  type HooksOfClass = Map<string, (HookFn | constructor<HookClass>)[]>;
10
+ export declare const toHookFn: <C extends IHookContext>(execute: HookFn<C> | constructor<HookClass<C>>) => HookFn<C>;
11
11
  export declare function getHooks(target: object, key: string | symbol): HooksOfClass;
12
12
  export declare function hasHooks(target: object, key: string | symbol): boolean;
13
13
  export declare const hook: (key: string | symbol, ...fns: (HookFn | constructor<HookClass>)[]) => (target: object, propertyKey: string | symbol) => void;
@@ -1,7 +1,7 @@
1
- import { HookFn } from './hook';
2
- import { SyncHooksRunner } from './runner/SyncHooksRunner';
1
+ import { HookClass, HookFn } from './hook';
3
2
  import type { IContainer } from '../container/IContainer';
4
- import { Instance } from '../types';
5
- export declare const onConstructHooksRunner: SyncHooksRunner;
6
- export declare const onConstruct: (fn: HookFn) => (target: object, propertyKey: string | symbol) => void;
3
+ import { constructor, Instance } from '../types';
4
+ import { HooksRunner } from './HooksRunner';
5
+ export declare const onConstructHooksRunner: HooksRunner;
6
+ export declare const onConstruct: (fn: HookFn | constructor<HookClass>) => (target: object, propertyKey: string | symbol) => void;
7
7
  export type OnConstructHook = (instance: Instance, scope: IContainer) => void;
@@ -1,5 +1,7 @@
1
- import { SyncHooksRunner } from './runner/SyncHooksRunner';
1
+ import { HookClass, HookFn } from './hook';
2
2
  import type { IContainer } from '../container/IContainer';
3
- export declare const onDisposeHooksRunner: SyncHooksRunner;
4
- export declare const onDispose: (target: object, propertyKey: string | symbol) => void;
3
+ import { constructor } from '../types';
4
+ import { HooksRunner } from './HooksRunner';
5
+ export declare const onDisposeHooksRunner: HooksRunner;
6
+ export declare const onDispose: (fn: HookFn | constructor<HookClass>) => (target: object, propertyKey: string | symbol) => void;
5
7
  export type OnDisposeHook = (scope: IContainer) => void;
@@ -24,9 +24,7 @@ export { HookContext, type IHookContext } from './hooks/HookContext';
24
24
  export { injectProp } from './hooks/injectProp';
25
25
  export { onConstructHooksRunner, onConstruct } from './hooks/onConstruct';
26
26
  export { onDisposeHooksRunner, onDispose } from './hooks/onDispose';
27
- export { HooksRunnerContext } from './hooks/runner/HooksRunner';
28
- export { AsyncHooksRunner } from './hooks/runner/AsyncHooksRunner';
29
- export { SyncHooksRunner } from './hooks/runner/SyncHooksRunner';
27
+ export { HooksRunnerContext, HooksRunner } from './hooks/HooksRunner';
30
28
  export { setMetadata, getMetadata, setParameterMetadata, setMethodMetadata, getMethodMetadata, getParameterMetadata, } from './metadata';
31
29
  export { InjectionToken } from './token/InjectionToken';
32
30
  export { AliasToken, toAlias } from './token/AliasToken';
@@ -40,5 +38,4 @@ export { toToken } from './token/toToken';
40
38
  export { select } from './select';
41
39
  export { Is } from './utils';
42
40
  export { InjectFn } from './hooks/hook';
43
- export { Instance } from './types';
44
- export { constructor } from './types';
41
+ export { Instance, constructor } from './types';
@@ -1,17 +1,18 @@
1
1
  import { type IContainer, ResolveOneOptions } from '../container/IContainer';
2
2
  import { constructor } from '../types';
3
+ import { ProviderOptions } from '../provider/IProvider';
3
4
  type WithArgs = {
4
5
  args: unknown[];
5
6
  };
6
7
  export type InjectOptions = Partial<WithArgs>;
7
8
  export interface IInjector {
8
- resolve<T>(container: IContainer, value: constructor<T>, options?: InjectOptions): T;
9
+ resolve<T>(container: IContainer, value: constructor<T>, options?: ProviderOptions): T;
9
10
  }
10
11
  export interface IInjectFnResolver<T> {
11
12
  resolve(s: IContainer, options?: ResolveOneOptions): T;
12
13
  }
13
14
  export declare abstract class Injector {
14
- resolve<T>(scope: IContainer, Target: constructor<T>, options?: InjectOptions): T;
15
+ resolve<T>(scope: IContainer, Target: constructor<T>, { args, lazy }?: ProviderOptions): T;
15
16
  protected abstract createInstance<T>(scope: IContainer, Target: constructor<T>, options?: InjectOptions): T;
16
17
  }
17
18
  export {};
@@ -6,7 +6,7 @@ export type WithLazy = {
6
6
  lazy: boolean;
7
7
  };
8
8
  export type ProviderOptions = InjectOptions & Partial<WithLazy>;
9
- export type ResolveDependency<T = unknown> = (container: IContainer, options: InjectOptions) => T;
9
+ export type ResolveDependency<T = unknown> = (container: IContainer, options: ProviderOptions) => T;
10
10
  export type ScopeAccessOptions = {
11
11
  invocationScope: Tagged;
12
12
  providerScope: Tagged;
@@ -1,23 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.AsyncHooksRunner = void 0;
4
- const HookContext_1 = require("../HookContext");
5
- const hook_1 = require("../hook");
6
- const utils_1 = require("../../utils");
7
- class AsyncHooksRunner {
8
- key;
9
- constructor(key) {
10
- this.key = key;
11
- }
12
- async execute(target, { scope, createContext = HookContext_1.createHookContext, predicate = () => true, }) {
13
- const hooks = Array.from((0, hook_1.getHooks)(target, this.key).entries()).filter(([methodName]) => predicate(methodName));
14
- const runMethodHooks = async (methodName, executions) => {
15
- const context = createContext(target, scope, methodName);
16
- for (const execute of executions) {
17
- await (0, utils_1.promisify)(execute(context));
18
- }
19
- };
20
- return Promise.all(hooks.map(([methodName, executions]) => runMethodHooks(methodName, executions.map(hook_1.toHookFn))));
21
- }
22
- }
23
- exports.AsyncHooksRunner = AsyncHooksRunner;
@@ -1,2 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
@@ -1,19 +0,0 @@
1
- import { createHookContext } from '../HookContext';
2
- import { getHooks, toHookFn } from '../hook';
3
- import { promisify } from '../../utils';
4
- export class AsyncHooksRunner {
5
- key;
6
- constructor(key) {
7
- this.key = key;
8
- }
9
- async execute(target, { scope, createContext = createHookContext, predicate = () => true, }) {
10
- const hooks = Array.from(getHooks(target, this.key).entries()).filter(([methodName]) => predicate(methodName));
11
- const runMethodHooks = async (methodName, executions) => {
12
- const context = createContext(target, scope, methodName);
13
- for (const execute of executions) {
14
- await promisify(execute(context));
15
- }
16
- };
17
- return Promise.all(hooks.map(([methodName, executions]) => runMethodHooks(methodName, executions.map(toHookFn))));
18
- }
19
- }
@@ -1 +0,0 @@
1
- export {};
@@ -1,11 +0,0 @@
1
- import { createHookContext } from '../HookContext';
2
- import type { IContainer } from '../../container/IContainer';
3
- export declare class AsyncHooksRunner {
4
- private readonly key;
5
- constructor(key: string | symbol);
6
- execute(target: object, { scope, createContext, predicate, }: {
7
- scope: IContainer;
8
- createContext?: typeof createHookContext;
9
- predicate?: (methodName: string) => boolean;
10
- }): Promise<void[]>;
11
- }
@@ -1,7 +0,0 @@
1
- import { type CreateHookContext } from '../HookContext';
2
- import type { IContainer } from '../../container/IContainer';
3
- export type HooksRunnerContext = {
4
- scope: IContainer;
5
- createContext?: CreateHookContext;
6
- predicate?: (methodName: string) => boolean;
7
- };
@@ -1,6 +0,0 @@
1
- import { HooksRunnerContext } from './HooksRunner';
2
- export declare class SyncHooksRunner {
3
- private readonly key;
4
- constructor(key: string | symbol);
5
- execute(target: object, { scope, createContext, predicate }: HooksRunnerContext): void;
6
- }