ts-ioc-container 63.0.0 → 64.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 (45) hide show
  1. package/README.md +94 -90
  2. package/cjm/container/Container.js +3 -0
  3. package/cjm/container/EmptyContainer.js +3 -0
  4. package/cjm/hooks/AsyncHookExecutionStrategy.js +15 -0
  5. package/cjm/hooks/HookContext.js +4 -4
  6. package/cjm/hooks/HookExecutionStrategy.js +68 -0
  7. package/cjm/hooks/ParallelAsync.js +17 -0
  8. package/cjm/hooks/SequentialAsync.js +15 -0
  9. package/cjm/hooks/SequentialSync.js +14 -0
  10. package/cjm/hooks/onConstruct.js +7 -9
  11. package/cjm/hooks/onResolved.js +13 -9
  12. package/cjm/hooks/onScopeDisposed.js +5 -7
  13. package/cjm/hooks/resolveHooks.js +1 -18
  14. package/cjm/index.js +14 -11
  15. package/esm/container/Container.js +3 -0
  16. package/esm/container/EmptyContainer.js +3 -0
  17. package/esm/hooks/AsyncHookExecutionStrategy.js +11 -0
  18. package/esm/hooks/HookContext.js +2 -2
  19. package/esm/hooks/HookExecutionStrategy.js +62 -0
  20. package/esm/hooks/ParallelAsync.js +13 -0
  21. package/esm/hooks/SequentialAsync.js +11 -0
  22. package/esm/hooks/SequentialSync.js +10 -0
  23. package/esm/hooks/onConstruct.js +6 -8
  24. package/esm/hooks/onResolved.js +11 -8
  25. package/esm/hooks/onScopeDisposed.js +4 -6
  26. package/esm/hooks/resolveHooks.js +1 -14
  27. package/esm/index.js +10 -6
  28. package/package.json +1 -1
  29. package/typings/container/Container.d.ts +1 -0
  30. package/typings/container/EmptyContainer.d.ts +2 -0
  31. package/typings/container/IContainer.d.ts +2 -1
  32. package/typings/hooks/AsyncHookExecutionStrategy.d.ts +10 -0
  33. package/typings/hooks/HookContext.d.ts +3 -3
  34. package/typings/hooks/HookExecutionStrategy.d.ts +35 -0
  35. package/typings/hooks/ParallelAsync.d.ts +5 -0
  36. package/typings/hooks/SequentialAsync.d.ts +5 -0
  37. package/typings/hooks/SequentialSync.d.ts +4 -0
  38. package/typings/hooks/onConstruct.d.ts +7 -8
  39. package/typings/hooks/onResolved.d.ts +5 -5
  40. package/typings/hooks/onScopeDisposed.d.ts +4 -5
  41. package/typings/hooks/resolveHooks.d.ts +0 -6
  42. package/typings/index.d.ts +10 -6
  43. package/cjm/hooks/HooksRunner.js +0 -50
  44. package/esm/hooks/HooksRunner.js +0 -45
  45. package/typings/hooks/HooksRunner.d.ts +0 -19
package/cjm/index.js CHANGED
@@ -1,8 +1,8 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.createHookContext = exports.createHookContextFactory = exports.HookContext = exports.prepend = exports.append = exports.prependHooks = exports.appendHooks = exports.hasHooks = exports.hook = exports.getHooks = exports.UnsupportedTokenTypeError = exports.CannonSingletonApplyTwiceError = exports.ProviderDisposedError = exports.ContainerDisposedError = exports.MethodNotImplementedError = exports.DependencyMissingKeyError = exports.ContainerNotFoundError = exports.DependencyNotFoundError = exports.ContainerError = exports.Registration = exports.onResolve = exports.appendArgsFn = exports.appendArgs = exports.decorate = exports.singleton = exports.autoResolve = exports.lazy = exports.scopeAccess = exports.scope = exports.bindTo = exports.register = exports.toRegistrationFn = exports.toProviderFn = exports.toBindToken = exports.registerPipe = exports.isProviderPipe = exports.Provider = exports.ProxyInjector = exports.SimpleInjector = exports.resolveArgs = exports.argsFn = exports.args = exports.arg = exports.inject = exports.MetadataInjector = exports.Injector = exports.EmptyContainer = exports.AutoResolveModule = exports.Container = exports.isDependencyKey = void 0;
4
- exports.throttle = exports.handleAsyncError = exports.handleError = exports.getMethodTags = exports.addMethodTag = exports.getMethodLabels = exports.addMethodLabel = exports.getMethodMeta = exports.addMethodMeta = exports.getParamTags = exports.addParamTag = exports.getParamLabels = exports.addParamLabel = exports.getParamMeta = exports.addParamMeta = exports.getClassTags = exports.addClassTag = exports.getClassLabels = exports.addClassLabel = exports.getClassMeta = exports.addClassMeta = exports.resolveConstructor = exports.GroupInstanceToken = exports.ConstantToken = exports.FunctionToken = exports.SingleToken = exports.ClassToken = exports.toSingleAlias = exports.SingleAliasToken = exports.toGroupAlias = exports.GroupAliasToken = exports.argToToken = exports.toMappedToken = exports.toToken = exports.InjectionToken = exports.runHooks = exports.HooksRunner = exports.oncePerInstance = exports.invokeMethod = exports.resolved = exports.OnResolvedModule = exports.onResolved = exports.onResolvedHooksRunner = exports.OnDisposeModule = exports.onScopeDisposed = exports.onScopeDisposedHooksRunner = exports.OnConstructModule = exports.onConstruct = exports.onConstructHooksRunner = exports.injectProp = void 0;
5
- exports.Is = exports.unwrapProxy = exports.ProxyRegistry = exports.pipe = exports.select = exports.once = exports.shallowCache = exports.debounce = void 0;
3
+ exports.createHookExecutionContext = exports.createHookContextFactory = exports.HookContext = exports.prepend = exports.append = exports.prependHooks = exports.appendHooks = exports.hasHooks = exports.hook = exports.getHooks = exports.UnsupportedTokenTypeError = exports.CannonSingletonApplyTwiceError = exports.ProviderDisposedError = exports.ContainerDisposedError = exports.MethodNotImplementedError = exports.DependencyMissingKeyError = exports.ContainerNotFoundError = exports.DependencyNotFoundError = exports.ContainerError = exports.Registration = exports.onResolve = exports.appendArgsFn = exports.appendArgs = exports.decorate = exports.singleton = exports.autoResolve = exports.lazy = exports.scopeAccess = exports.scope = exports.bindTo = exports.register = exports.toRegistrationFn = exports.toProviderFn = exports.toBindToken = exports.registerPipe = exports.isProviderPipe = exports.Provider = exports.ProxyInjector = exports.SimpleInjector = exports.resolveArgs = exports.argsFn = exports.args = exports.arg = exports.inject = exports.MetadataInjector = exports.Injector = exports.EmptyContainer = exports.AutoResolveModule = exports.Container = exports.isDependencyKey = void 0;
4
+ exports.debounce = exports.throttle = exports.handleAsyncError = exports.handleError = exports.getMethodTags = exports.addMethodTag = exports.getMethodLabels = exports.addMethodLabel = exports.getMethodMeta = exports.addMethodMeta = exports.getParamTags = exports.addParamTag = exports.getParamLabels = exports.addParamLabel = exports.getParamMeta = exports.addParamMeta = exports.getClassTags = exports.addClassTag = exports.getClassLabels = exports.addClassLabel = exports.getClassMeta = exports.addClassMeta = exports.resolveConstructor = exports.GroupInstanceToken = exports.ConstantToken = exports.FunctionToken = exports.SingleToken = exports.ClassToken = exports.toSingleAlias = exports.SingleAliasToken = exports.toGroupAlias = exports.GroupAliasToken = exports.argToToken = exports.toMappedToken = exports.toToken = exports.InjectionToken = exports.ParallelAsync = exports.SequentialAsync = exports.SequentialSync = exports.AsyncHookExecutionStrategy = exports.HookExecutionStrategy = exports.oncePerInstance = exports.resolved = exports.OnResolvedModule = exports.onResolved = exports.OnDisposeModule = exports.onScopeDisposed = exports.OnConstructModule = exports.onConstruct = exports.injectProp = void 0;
5
+ exports.Is = exports.unwrapProxy = exports.ProxyRegistry = exports.pipe = exports.select = exports.once = exports.shallowCache = void 0;
6
6
  var IContainer_1 = require("./container/IContainer");
7
7
  Object.defineProperty(exports, "isDependencyKey", { enumerable: true, get: function () { return IContainer_1.isDependencyKey; } });
8
8
  var Container_1 = require("./container/Container");
@@ -74,28 +74,31 @@ Object.defineProperty(exports, "prepend", { enumerable: true, get: function () {
74
74
  var HookContext_1 = require("./hooks/HookContext");
75
75
  Object.defineProperty(exports, "HookContext", { enumerable: true, get: function () { return HookContext_1.HookContext; } });
76
76
  Object.defineProperty(exports, "createHookContextFactory", { enumerable: true, get: function () { return HookContext_1.createHookContextFactory; } });
77
- Object.defineProperty(exports, "createHookContext", { enumerable: true, get: function () { return HookContext_1.createHookContext; } });
77
+ Object.defineProperty(exports, "createHookExecutionContext", { enumerable: true, get: function () { return HookContext_1.createHookExecutionContext; } });
78
78
  var injectProp_1 = require("./hooks/injectProp");
79
79
  Object.defineProperty(exports, "injectProp", { enumerable: true, get: function () { return injectProp_1.injectProp; } });
80
80
  var onConstruct_1 = require("./hooks/onConstruct");
81
- Object.defineProperty(exports, "onConstructHooksRunner", { enumerable: true, get: function () { return onConstruct_1.onConstructHooksRunner; } });
82
81
  Object.defineProperty(exports, "onConstruct", { enumerable: true, get: function () { return onConstruct_1.onConstruct; } });
83
82
  Object.defineProperty(exports, "OnConstructModule", { enumerable: true, get: function () { return onConstruct_1.OnConstructModule; } });
84
83
  var onScopeDisposed_1 = require("./hooks/onScopeDisposed");
85
- Object.defineProperty(exports, "onScopeDisposedHooksRunner", { enumerable: true, get: function () { return onScopeDisposed_1.onScopeDisposedHooksRunner; } });
86
84
  Object.defineProperty(exports, "onScopeDisposed", { enumerable: true, get: function () { return onScopeDisposed_1.onScopeDisposed; } });
87
85
  Object.defineProperty(exports, "OnDisposeModule", { enumerable: true, get: function () { return onScopeDisposed_1.OnDisposeModule; } });
88
86
  var onResolved_1 = require("./hooks/onResolved");
89
- Object.defineProperty(exports, "onResolvedHooksRunner", { enumerable: true, get: function () { return onResolved_1.onResolvedHooksRunner; } });
90
87
  Object.defineProperty(exports, "onResolved", { enumerable: true, get: function () { return onResolved_1.onResolved; } });
91
88
  Object.defineProperty(exports, "OnResolvedModule", { enumerable: true, get: function () { return onResolved_1.OnResolvedModule; } });
92
89
  Object.defineProperty(exports, "resolved", { enumerable: true, get: function () { return onResolved_1.resolved; } });
93
90
  var resolveHooks_1 = require("./hooks/resolveHooks");
94
- Object.defineProperty(exports, "invokeMethod", { enumerable: true, get: function () { return resolveHooks_1.invokeMethod; } });
95
91
  Object.defineProperty(exports, "oncePerInstance", { enumerable: true, get: function () { return resolveHooks_1.oncePerInstance; } });
96
- var HooksRunner_1 = require("./hooks/HooksRunner");
97
- Object.defineProperty(exports, "HooksRunner", { enumerable: true, get: function () { return HooksRunner_1.HooksRunner; } });
98
- Object.defineProperty(exports, "runHooks", { enumerable: true, get: function () { return HooksRunner_1.runHooks; } });
92
+ var HookExecutionStrategy_1 = require("./hooks/HookExecutionStrategy");
93
+ Object.defineProperty(exports, "HookExecutionStrategy", { enumerable: true, get: function () { return HookExecutionStrategy_1.HookExecutionStrategy; } });
94
+ var AsyncHookExecutionStrategy_1 = require("./hooks/AsyncHookExecutionStrategy");
95
+ Object.defineProperty(exports, "AsyncHookExecutionStrategy", { enumerable: true, get: function () { return AsyncHookExecutionStrategy_1.AsyncHookExecutionStrategy; } });
96
+ var SequentialSync_1 = require("./hooks/SequentialSync");
97
+ Object.defineProperty(exports, "SequentialSync", { enumerable: true, get: function () { return SequentialSync_1.SequentialSync; } });
98
+ var SequentialAsync_1 = require("./hooks/SequentialAsync");
99
+ Object.defineProperty(exports, "SequentialAsync", { enumerable: true, get: function () { return SequentialAsync_1.SequentialAsync; } });
100
+ var ParallelAsync_1 = require("./hooks/ParallelAsync");
101
+ Object.defineProperty(exports, "ParallelAsync", { enumerable: true, get: function () { return ParallelAsync_1.ParallelAsync; } });
99
102
  var InjectionToken_1 = require("./token/InjectionToken");
100
103
  Object.defineProperty(exports, "InjectionToken", { enumerable: true, get: function () { return InjectionToken_1.InjectionToken; } });
101
104
  var toToken_1 = require("./token/toToken");
@@ -122,6 +122,9 @@ export class Container {
122
122
  getRegistrations() {
123
123
  return [...this.parent.getRegistrations(), ...this.registrations];
124
124
  }
125
+ getInjector() {
126
+ return this.injector;
127
+ }
125
128
  hasRegistration(key) {
126
129
  return this.registrations.some((r) => r.getKeyOrFail() === key) || this.parent.hasRegistration(key);
127
130
  }
@@ -20,6 +20,9 @@ export class EmptyContainer {
20
20
  createScope() {
21
21
  throw new MethodNotImplementedError();
22
22
  }
23
+ getInjector() {
24
+ throw new MethodNotImplementedError();
25
+ }
23
26
  autoResolve(options) {
24
27
  throw new MethodNotImplementedError();
25
28
  }
@@ -0,0 +1,11 @@
1
+ import { HookExecutionStrategy, runAtOnce, runInOrder, } from './HookExecutionStrategy.js';
2
+ export class AsyncHookExecutionStrategy extends HookExecutionStrategy {
3
+ methodStrategy;
4
+ constructor({ methodStrategy = 'sequential', ...props }) {
5
+ super(props);
6
+ this.methodStrategy = methodStrategy;
7
+ }
8
+ runMember({ hooks, context }) {
9
+ return this.methodStrategy === 'parallel' ? runAtOnce(hooks, context) : runInOrder(hooks, context);
10
+ }
11
+ }
@@ -31,5 +31,5 @@ export class HookContext {
31
31
  return this.initialArgs;
32
32
  }
33
33
  }
34
- export const createHookContext = (Target, scope, methodName = 'constructor') => new HookContext(Target, scope, methodName);
35
- export const createHookContextFactory = ({ args = [] } = {}) => (Target, scope, methodName) => createHookContext(Target, scope, methodName).setInitialArgs(...args);
34
+ export const createHookExecutionContext = (Target, scope, methodName = 'constructor') => new HookContext(Target, scope, methodName);
35
+ export const createHookContextFactory = ({ args = [] } = {}) => (Target, scope, methodName) => createHookExecutionContext(Target, scope, methodName).setInitialArgs(...args);
@@ -0,0 +1,62 @@
1
+ import { resolveConstructor } from '../metadata/target.js';
2
+ import { getHooks, hasHooks, toHookFn } from './hook.js';
3
+ import { createHookExecutionContext } from './HookContext.js';
4
+ export const runInOrder = (hooks, context, from = 0) => {
5
+ for (let i = from; i < hooks.length; i++) {
6
+ const result = hooks[i](context);
7
+ if (result instanceof Promise) {
8
+ return result.then(() => runInOrder(hooks, context, i + 1));
9
+ }
10
+ }
11
+ };
12
+ export const runAtOnce = (hooks, context) => {
13
+ const pending = [];
14
+ for (const hook of hooks) {
15
+ const result = hook(context);
16
+ if (result instanceof Promise) {
17
+ pending.push(result);
18
+ }
19
+ }
20
+ return pending.length > 0 ? Promise.all(pending).then(() => undefined) : undefined;
21
+ };
22
+ export class HookExecutionStrategy {
23
+ key;
24
+ onError;
25
+ options;
26
+ hooksByClass = new WeakMap();
27
+ constructor({ key, onError, createExecutionContext = createHookExecutionContext, mapExecutionContext = (context) => context, predicate = () => true, }) {
28
+ this.key = key;
29
+ this.onError = onError;
30
+ this.options = { createExecutionContext, mapExecutionContext, predicate };
31
+ }
32
+ hasHooks(target) {
33
+ return hasHooks(target, this.key);
34
+ }
35
+ execute(target, { scope, ...overrides }) {
36
+ const report = (ex) => this.onError?.(scope)(ex);
37
+ try {
38
+ this.processHooks(this.collect(target, scope, overrides))?.catch(report);
39
+ }
40
+ catch (ex) {
41
+ report(ex);
42
+ }
43
+ }
44
+ collect(target, scope, { createExecutionContext = this.options.createExecutionContext, mapExecutionContext = this.options.mapExecutionContext, predicate = this.options.predicate, }) {
45
+ const members = [];
46
+ for (const { methodName, hooks } of this.hooksOf(target)) {
47
+ if (predicate(methodName)) {
48
+ members.push({ hooks, context: mapExecutionContext(createExecutionContext(target, scope, methodName)) });
49
+ }
50
+ }
51
+ return members;
52
+ }
53
+ hooksOf(target) {
54
+ const Target = resolveConstructor(target);
55
+ let hooks = this.hooksByClass.get(Target);
56
+ if (!hooks) {
57
+ hooks = Array.from(getHooks(Target, this.key), ([methodName, fns]) => ({ methodName, hooks: fns.map(toHookFn) }));
58
+ this.hooksByClass.set(Target, hooks);
59
+ }
60
+ return hooks;
61
+ }
62
+ }
@@ -0,0 +1,13 @@
1
+ import { AsyncHookExecutionStrategy } from './AsyncHookExecutionStrategy.js';
2
+ export class ParallelAsync extends AsyncHookExecutionStrategy {
3
+ processHooks(members) {
4
+ const pending = [];
5
+ for (const member of members) {
6
+ const result = this.runMember(member);
7
+ if (result) {
8
+ pending.push(result);
9
+ }
10
+ }
11
+ return pending.length > 0 ? Promise.all(pending).then(() => undefined) : undefined;
12
+ }
13
+ }
@@ -0,0 +1,11 @@
1
+ import { AsyncHookExecutionStrategy } from './AsyncHookExecutionStrategy.js';
2
+ export class SequentialAsync extends AsyncHookExecutionStrategy {
3
+ processHooks(members, from = 0) {
4
+ for (let i = from; i < members.length; i++) {
5
+ const result = this.runMember(members[i]);
6
+ if (result) {
7
+ return result.then(() => this.processHooks(members, i + 1));
8
+ }
9
+ }
10
+ }
11
+ }
@@ -0,0 +1,10 @@
1
+ import { HookExecutionStrategy } from './HookExecutionStrategy.js';
2
+ export class SequentialSync extends HookExecutionStrategy {
3
+ processHooks(members) {
4
+ for (const { hooks, context } of members) {
5
+ for (const hook of hooks) {
6
+ hook(context);
7
+ }
8
+ }
9
+ }
10
+ }
@@ -1,15 +1,13 @@
1
1
  import { hook, prependHooks } from './hook.js';
2
- import { HooksRunner, runHooks } from './HooksRunner.js';
3
- export const onConstructHooksRunner = new HooksRunner('onConstruct');
4
2
  export const onConstruct = (...fns) => hook('onConstruct', prependHooks(...fns));
5
3
  export class OnConstructModule {
6
- onException;
7
- constructor(onException) {
8
- this.onException = onException;
4
+ strategy;
5
+ constructor(strategy) {
6
+ this.strategy = strategy;
9
7
  }
10
- applyTo(injector) {
11
- injector.onConstructed((instance, scope) => {
12
- runHooks(onConstructHooksRunner, instance, scope, this.onException);
8
+ applyTo(container) {
9
+ container.getInjector().onConstructed((instance, scope) => {
10
+ this.strategy.execute(instance, { scope });
13
11
  });
14
12
  }
15
13
  }
@@ -1,13 +1,16 @@
1
- import { HooksRunner } from './HooksRunner.js';
2
1
  import { registerPipe } from '../registration/IRegistration.js';
3
- import { executeHooks, forEachResolvedObject, resolvedHook } from './resolveHooks.js';
4
- export const onResolvedHooksRunner = new HooksRunner('onResolved');
5
- export const onResolved = resolvedHook('onResolved');
6
- const runHooks = (onException) => forEachResolvedObject(executeHooks(onResolvedHooksRunner, onException));
2
+ import { Is } from '../utils/basic.js';
3
+ import { hook, prependHooks } from './hook.js';
4
+ export const onResolved = (...hooks) => hook('onResolved', prependHooks(...hooks));
5
+ const runHooks = (strategy) => (dependency, scope) => {
6
+ if (Is.object(dependency)) {
7
+ strategy.execute(dependency, { scope });
8
+ }
9
+ };
7
10
  export class OnResolvedModule {
8
11
  runHooks;
9
- constructor(onException) {
10
- this.runHooks = runHooks(onException);
12
+ constructor(strategy) {
13
+ this.runHooks = runHooks(strategy);
11
14
  }
12
15
  applyTo(container) {
13
16
  container.onRegistered((provider) => {
@@ -15,4 +18,4 @@ export class OnResolvedModule {
15
18
  });
16
19
  }
17
20
  }
18
- export const resolved = (onException) => registerPipe((p) => p.onResolved(runHooks(onException)));
21
+ export const resolved = (strategy) => registerPipe((p) => p.onResolved(runHooks(strategy)));
@@ -1,16 +1,14 @@
1
1
  import { hook, prependHooks } from './hook.js';
2
- import { HooksRunner, runHooks } from './HooksRunner.js';
3
- export const onScopeDisposedHooksRunner = new HooksRunner('onScopeDisposed');
4
2
  export const onScopeDisposed = (...fns) => hook('onScopeDisposed', prependHooks(...fns));
5
3
  export class OnDisposeModule {
6
- onException;
7
- constructor(onException) {
8
- this.onException = onException;
4
+ strategy;
5
+ constructor(strategy) {
6
+ this.strategy = strategy;
9
7
  }
10
8
  applyTo(container) {
11
9
  container.onScopeDisposed((scope) => {
12
10
  for (const instance of scope.getInstances()) {
13
- runHooks(onScopeDisposedHooksRunner, instance, scope, this.onException);
11
+ this.strategy.execute(instance, { scope });
14
12
  }
15
13
  });
16
14
  }
@@ -1,10 +1,4 @@
1
- import { runHooks } from './HooksRunner.js';
2
- import { hook, prependHooks, toHookFn } from './hook.js';
3
- import { Is } from '../utils/basic.js';
4
- export const invokeMethod = (context) => {
5
- context.invokeMethod();
6
- };
7
- const toHooks = (hooks) => (hooks.length > 0 ? hooks : [invokeMethod]);
1
+ import { toHookFn } from './hook.js';
8
2
  export const oncePerInstance = (execute) => {
9
3
  const invokedInstances = new WeakSet();
10
4
  return (context) => {
@@ -15,10 +9,3 @@ export const oncePerInstance = (execute) => {
15
9
  return toHookFn(execute)(context);
16
10
  };
17
11
  };
18
- export const resolvedHook = (key) => (...hooks) => hook(key, prependHooks(...toHooks(hooks)));
19
- export const forEachResolvedObject = (run) => (dependency, scope) => {
20
- if (Is.object(dependency)) {
21
- run(dependency, scope);
22
- }
23
- };
24
- export const executeHooks = (runner, onException) => (dependency, scope) => runHooks(runner, dependency, scope, onException);
package/esm/index.js CHANGED
@@ -19,13 +19,17 @@ export { ProviderDisposedError } from './errors/ProviderDisposedError.js';
19
19
  export { CannonSingletonApplyTwiceError } from './errors/CannonSingletonApplyTwiceError.js';
20
20
  export { UnsupportedTokenTypeError } from './errors/UnsupportedTokenTypeError.js';
21
21
  export { getHooks, hook, hasHooks, appendHooks, prependHooks, append, prepend, } from './hooks/hook.js';
22
- export { HookContext, createHookContextFactory, createHookContext } from './hooks/HookContext.js';
22
+ export { HookContext, createHookContextFactory, createHookExecutionContext, } from './hooks/HookContext.js';
23
23
  export { injectProp } from './hooks/injectProp.js';
24
- export { onConstructHooksRunner, onConstruct, OnConstructModule } from './hooks/onConstruct.js';
25
- export { onScopeDisposedHooksRunner, onScopeDisposed, OnDisposeModule } from './hooks/onScopeDisposed.js';
26
- export { onResolvedHooksRunner, onResolved, OnResolvedModule, resolved } from './hooks/onResolved.js';
27
- export { invokeMethod, oncePerInstance } from './hooks/resolveHooks.js';
28
- export { HooksRunner, runHooks, } from './hooks/HooksRunner.js';
24
+ export { onConstruct, OnConstructModule } from './hooks/onConstruct.js';
25
+ export { onScopeDisposed, OnDisposeModule } from './hooks/onScopeDisposed.js';
26
+ export { onResolved, OnResolvedModule, resolved } from './hooks/onResolved.js';
27
+ export { oncePerInstance } from './hooks/resolveHooks.js';
28
+ export { HookExecutionStrategy, } from './hooks/HookExecutionStrategy.js';
29
+ export { AsyncHookExecutionStrategy, } from './hooks/AsyncHookExecutionStrategy.js';
30
+ export { SequentialSync } from './hooks/SequentialSync.js';
31
+ export { SequentialAsync } from './hooks/SequentialAsync.js';
32
+ export { ParallelAsync } from './hooks/ParallelAsync.js';
29
33
  export { InjectionToken } from './token/InjectionToken.js';
30
34
  export { toToken, toMappedToken, argToToken } from './token/toToken.js';
31
35
  export { GroupAliasToken, toGroupAlias } from './token/GroupAliasToken.js';
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ts-ioc-container",
3
- "version": "63.0.0",
3
+ "version": "64.0.0",
4
4
  "description": "Fast, lightweight TypeScript dependency injection container with a clean API, scoped lifecycles, decorators, tokens, hooks, lazy injection, customizable providers, and no global container objects.",
5
5
  "publishConfig": {
6
6
  "access": "public",
@@ -30,6 +30,7 @@ export declare class Container implements IContainer {
30
30
  dispose(): void;
31
31
  addRegistration(registration: IRegistration): this;
32
32
  getRegistrations(): IRegistration[];
33
+ getInjector(): IInjector;
33
34
  hasRegistration(key: DependencyKey): boolean;
34
35
  onScopeCreated(...hooks: ScopeHook[]): this;
35
36
  onScopeDisposed(...hooks: ScopeHook[]): this;
@@ -2,6 +2,7 @@ import { type AutoResolveOptions, type DependencyKey, type IContainer, type ICon
2
2
  import { type IProvider } from '../provider/IProvider.js';
3
3
  import { type IRegistration } from '../registration/IRegistration.js';
4
4
  import { type constructor, type Instance } from '../utils/basic.js';
5
+ import { type IInjector } from '../injector/IInjector.js';
5
6
  export declare class EmptyContainer implements IContainer {
6
7
  get isDisposed(): boolean;
7
8
  addInstance(instance: Instance): void;
@@ -10,6 +11,7 @@ export declare class EmptyContainer implements IContainer {
10
11
  getInstances(): never[];
11
12
  hasInstance(instance: Instance): boolean;
12
13
  createScope(): IContainer;
14
+ getInjector(): IInjector;
13
15
  autoResolve(options?: AutoResolveOptions): this;
14
16
  dispose(): void;
15
17
  register(key: DependencyKey, value: IProvider): this;
@@ -1,6 +1,6 @@
1
1
  import { type IProvider, ProviderOptions } from '../provider/IProvider.js';
2
2
  import { type IRegistration } from '../registration/IRegistration.js';
3
- import { type WithArgs } from '../injector/IInjector.js';
3
+ import { IInjector, type WithArgs } from '../injector/IInjector.js';
4
4
  import { type constructor, Instance } from '../utils/basic.js';
5
5
  export type DependencyKey = string | symbol;
6
6
  export declare function isDependencyKey(target: unknown): target is DependencyKey;
@@ -55,5 +55,6 @@ export interface IContainer extends Tagged {
55
55
  hasInstance(instance: Instance): boolean;
56
56
  dispose(): void;
57
57
  addInstance(instance: Instance): void;
58
+ getInjector(): IInjector;
58
59
  }
59
60
  export {};
@@ -0,0 +1,10 @@
1
+ import { HookExecutionStrategy, type HookExecutionStrategyProps, type MemberHooks } from './HookExecutionStrategy.js';
2
+ export type MethodStrategy = 'sequential' | 'parallel';
3
+ export type AsyncHookExecutionStrategyProps = HookExecutionStrategyProps & {
4
+ methodStrategy?: MethodStrategy;
5
+ };
6
+ export declare abstract class AsyncHookExecutionStrategy extends HookExecutionStrategy {
7
+ private readonly methodStrategy;
8
+ constructor({ methodStrategy, ...props }: AsyncHookExecutionStrategyProps);
9
+ protected runMember({ hooks, context }: MemberHooks): void | Promise<void>;
10
+ }
@@ -29,8 +29,8 @@ export declare class HookContext implements IHookContext {
29
29
  setInitialArgs(...args: unknown[]): this;
30
30
  getInitialArgs(): unknown[];
31
31
  }
32
- export type CreateHookContext = (Target: Instance, scope: IContainer, methodName?: string) => IHookContext;
33
- export declare const createHookContext: CreateHookContext;
32
+ export type CreateHookExecutionContext = (Target: Instance, scope: IContainer, methodName?: string) => IHookContext;
33
+ export declare const createHookExecutionContext: CreateHookExecutionContext;
34
34
  export declare const createHookContextFactory: ({ args }?: {
35
35
  args?: unknown[];
36
- }) => CreateHookContext;
36
+ }) => CreateHookExecutionContext;
@@ -0,0 +1,35 @@
1
+ import type { IContainer } from '../container/IContainer.js';
2
+ import type { ExecutionContext } from '../ExecutionContext.js';
3
+ import { type Instance } from '../utils/basic.js';
4
+ import { type HookFn } from './hook.js';
5
+ import { type CreateHookExecutionContext, type IHookContext } from './HookContext.js';
6
+ export type MapHookExecutionContext = (context: IHookContext) => IHookContext;
7
+ export type OnErrorHandler = (scope: IContainer) => (error: unknown) => void;
8
+ export type HookExecutionOptions = {
9
+ createExecutionContext?: CreateHookExecutionContext;
10
+ mapExecutionContext?: MapHookExecutionContext;
11
+ predicate?: (methodName: string) => boolean;
12
+ };
13
+ export type HookExecutionContext = ExecutionContext & HookExecutionOptions;
14
+ export type HookExecutionStrategyProps = HookExecutionOptions & {
15
+ key: string | symbol;
16
+ onError?: OnErrorHandler;
17
+ };
18
+ export type MemberHooks = {
19
+ hooks: HookFn[];
20
+ context: IHookContext;
21
+ };
22
+ export declare const runInOrder: (hooks: HookFn[], context: IHookContext, from?: number) => void | Promise<void>;
23
+ export declare const runAtOnce: (hooks: HookFn[], context: IHookContext) => void | Promise<void>;
24
+ export declare abstract class HookExecutionStrategy {
25
+ private readonly key;
26
+ private readonly onError?;
27
+ private readonly options;
28
+ private readonly hooksByClass;
29
+ constructor({ key, onError, createExecutionContext, mapExecutionContext, predicate, }: HookExecutionStrategyProps);
30
+ hasHooks(target: Instance): boolean;
31
+ execute(target: Instance, { scope, ...overrides }: HookExecutionContext): void;
32
+ protected abstract processHooks(members: MemberHooks[]): void | Promise<void>;
33
+ private collect;
34
+ private hooksOf;
35
+ }
@@ -0,0 +1,5 @@
1
+ import { AsyncHookExecutionStrategy } from './AsyncHookExecutionStrategy.js';
2
+ import { type MemberHooks } from './HookExecutionStrategy.js';
3
+ export declare class ParallelAsync extends AsyncHookExecutionStrategy {
4
+ protected processHooks(members: MemberHooks[]): void | Promise<void>;
5
+ }
@@ -0,0 +1,5 @@
1
+ import { AsyncHookExecutionStrategy } from './AsyncHookExecutionStrategy.js';
2
+ import { type MemberHooks } from './HookExecutionStrategy.js';
3
+ export declare class SequentialAsync extends AsyncHookExecutionStrategy {
4
+ protected processHooks(members: MemberHooks[], from?: number): void | Promise<void>;
5
+ }
@@ -0,0 +1,4 @@
1
+ import { HookExecutionStrategy, type MemberHooks } from './HookExecutionStrategy.js';
2
+ export declare class SequentialSync extends HookExecutionStrategy {
3
+ protected processHooks(members: MemberHooks[]): void;
4
+ }
@@ -1,10 +1,9 @@
1
- import { HookType } from './hook.js';
2
- import type { IInjector, IInjectorModule } from '../injector/IInjector.js';
3
- import { HooksRunner, type OnExceptionHandler } from './HooksRunner.js';
4
- export declare const onConstructHooksRunner: HooksRunner;
1
+ import { type HookType } from './hook.js';
2
+ import type { IContainer, IContainerModule } from '../container/IContainer.js';
3
+ import { type HookExecutionStrategy } from './HookExecutionStrategy.js';
5
4
  export declare const onConstruct: (...fns: HookType[]) => (target: object, propertyKey: string | symbol) => void;
6
- export declare class OnConstructModule implements IInjectorModule {
7
- private readonly onException?;
8
- constructor(onException?: OnExceptionHandler | undefined);
9
- applyTo(injector: IInjector): void;
5
+ export declare class OnConstructModule implements IContainerModule {
6
+ private readonly strategy;
7
+ constructor(strategy: HookExecutionStrategy);
8
+ applyTo(container: IContainer): void;
10
9
  }
@@ -1,10 +1,10 @@
1
1
  import type { IContainer, IContainerModule } from '../container/IContainer.js';
2
- import { HooksRunner, type OnExceptionHandler } from './HooksRunner.js';
3
- export declare const onResolvedHooksRunner: HooksRunner;
4
- export declare const onResolved: (...hooks: import("./hook.js").HookType[]) => (target: object, propertyKey: string | symbol) => void;
2
+ import { type HookExecutionStrategy } from './HookExecutionStrategy.js';
3
+ import { type HookType } from './hook.js';
4
+ export declare const onResolved: (...hooks: HookType[]) => (target: object, propertyKey: string | symbol) => void;
5
5
  export declare class OnResolvedModule implements IContainerModule {
6
6
  private readonly runHooks;
7
- constructor(onException?: OnExceptionHandler);
7
+ constructor(strategy: HookExecutionStrategy);
8
8
  applyTo(container: IContainer): void;
9
9
  }
10
- export declare const resolved: <T = unknown>(onException?: OnExceptionHandler) => import("../registration/IRegistration.js").ProviderPipe<T>;
10
+ export declare const resolved: <T = unknown>(strategy: HookExecutionStrategy) => import("../registration/IRegistration.js").ProviderPipe<T>;
@@ -1,10 +1,9 @@
1
- import { HookType } from './hook.js';
1
+ import { type HookType } from './hook.js';
2
2
  import type { IContainer, IContainerModule } from '../container/IContainer.js';
3
- import { HooksRunner, type OnExceptionHandler } from './HooksRunner.js';
4
- export declare const onScopeDisposedHooksRunner: HooksRunner;
3
+ import { type HookExecutionStrategy } from './HookExecutionStrategy.js';
5
4
  export declare const onScopeDisposed: (...fns: HookType[]) => (target: object, propertyKey: string | symbol) => void;
6
5
  export declare class OnDisposeModule implements IContainerModule {
7
- private readonly onException?;
8
- constructor(onException?: OnExceptionHandler | undefined);
6
+ private readonly strategy;
7
+ constructor(strategy: HookExecutionStrategy);
9
8
  applyTo(container: IContainer): void;
10
9
  }
@@ -1,10 +1,4 @@
1
1
  import type { IContainer } from '../container/IContainer.js';
2
- import type { ProviderHook } from '../provider/IProvider.js';
3
- import { type HooksRunner, type OnExceptionHandler } from './HooksRunner.js';
4
2
  import { type HookFn, type HookType } from './hook.js';
5
3
  export type ResolvedObjectHook = (dependency: object, scope: IContainer) => void;
6
- export declare const invokeMethod: HookFn;
7
4
  export declare const oncePerInstance: (execute: HookType) => HookFn;
8
- export declare const resolvedHook: (key: string) => (...hooks: HookType[]) => (target: object, propertyKey: string | symbol) => void;
9
- export declare const forEachResolvedObject: (run: ResolvedObjectHook) => ProviderHook;
10
- export declare const executeHooks: (runner: HooksRunner, onException?: OnExceptionHandler) => ResolvedObjectHook;
@@ -20,13 +20,17 @@ export { ProviderDisposedError } from './errors/ProviderDisposedError.js';
20
20
  export { CannonSingletonApplyTwiceError } from './errors/CannonSingletonApplyTwiceError.js';
21
21
  export { UnsupportedTokenTypeError } from './errors/UnsupportedTokenTypeError.js';
22
22
  export { getHooks, hook, hasHooks, appendHooks, prependHooks, append, prepend, type HookFn, type HookClass, type HookType, type MapHooksFn, type InjectFn, type HooksOfClass, } from './hooks/hook.js';
23
- export { HookContext, createHookContextFactory, createHookContext, type IHookContext } from './hooks/HookContext.js';
23
+ export { HookContext, createHookContextFactory, createHookExecutionContext, type CreateHookExecutionContext, type IHookContext, } from './hooks/HookContext.js';
24
24
  export { injectProp } from './hooks/injectProp.js';
25
- export { onConstructHooksRunner, onConstruct, OnConstructModule } from './hooks/onConstruct.js';
26
- export { onScopeDisposedHooksRunner, onScopeDisposed, OnDisposeModule } from './hooks/onScopeDisposed.js';
27
- export { onResolvedHooksRunner, onResolved, OnResolvedModule, resolved } from './hooks/onResolved.js';
28
- export { invokeMethod, oncePerInstance, type ResolvedObjectHook } from './hooks/resolveHooks.js';
29
- export { HooksRunner, runHooks, type HooksRunnerContext, type MapHookContext, type OnExceptionHandler, } from './hooks/HooksRunner.js';
25
+ export { onConstruct, OnConstructModule } from './hooks/onConstruct.js';
26
+ export { onScopeDisposed, OnDisposeModule } from './hooks/onScopeDisposed.js';
27
+ export { onResolved, OnResolvedModule, resolved } from './hooks/onResolved.js';
28
+ export { oncePerInstance, type ResolvedObjectHook } from './hooks/resolveHooks.js';
29
+ export { HookExecutionStrategy, type HookExecutionContext, type HookExecutionOptions, type HookExecutionStrategyProps, type MapHookExecutionContext, type MemberHooks, type OnErrorHandler, } from './hooks/HookExecutionStrategy.js';
30
+ export { AsyncHookExecutionStrategy, type AsyncHookExecutionStrategyProps, type MethodStrategy, } from './hooks/AsyncHookExecutionStrategy.js';
31
+ export { SequentialSync } from './hooks/SequentialSync.js';
32
+ export { SequentialAsync } from './hooks/SequentialAsync.js';
33
+ export { ParallelAsync } from './hooks/ParallelAsync.js';
30
34
  export { InjectionToken } from './token/InjectionToken.js';
31
35
  export { type Injectable, toToken, toMappedToken, argToToken } from './token/toToken.js';
32
36
  export { GroupAliasToken, toGroupAlias } from './token/GroupAliasToken.js';
@@ -1,50 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.runHooks = exports.HooksRunner = void 0;
4
- const HookContext_1 = require("./HookContext");
5
- const hook_1 = require("./hook");
6
- const runFrom = (fns, index, context) => {
7
- for (let i = index; i < fns.length; i++) {
8
- const result = fns[i](context);
9
- if (result instanceof Promise) {
10
- return result.then(() => runFrom(fns, i + 1, context));
11
- }
12
- }
13
- };
14
- class HooksRunner {
15
- key;
16
- constructor(key) {
17
- this.key = key;
18
- }
19
- hasHooks(target) {
20
- return (0, hook_1.hasHooks)(target, this.key);
21
- }
22
- execute(target, { scope, createContext = HookContext_1.createHookContext, mapContext = (context) => context, predicate = () => true, }) {
23
- const hooks = Array.from((0, hook_1.getHooks)(target, this.key).entries()).filter(([methodName]) => predicate(methodName));
24
- const pending = [];
25
- for (const [methodName, executions] of hooks) {
26
- const context = mapContext(createContext(target, scope, methodName));
27
- const result = runFrom(executions.map(hook_1.toHookFn), 0, context);
28
- if (result) {
29
- pending.push(result);
30
- }
31
- }
32
- return pending.length > 0 ? Promise.all(pending).then(() => undefined) : undefined;
33
- }
34
- }
35
- exports.HooksRunner = HooksRunner;
36
- const runHooks = (runner, target, scope, onException) => {
37
- const report = (ex) => {
38
- if (!onException) {
39
- throw ex;
40
- }
41
- onException(ex, { scope });
42
- };
43
- try {
44
- runner.execute(target, { scope })?.catch(report);
45
- }
46
- catch (ex) {
47
- report(ex);
48
- }
49
- };
50
- exports.runHooks = runHooks;