ts-ioc-container 60.2.0 → 61.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 (40) hide show
  1. package/README.md +77 -23
  2. package/cjm/container/Container.js +16 -26
  3. package/cjm/container/EmptyContainer.js +3 -6
  4. package/cjm/hooks/onConstruct.js +2 -2
  5. package/cjm/hooks/onConstructAsync.js +2 -2
  6. package/cjm/hooks/onContainerDisposed.js +1 -1
  7. package/cjm/hooks/onResolved.js +20 -0
  8. package/cjm/hooks/onResolvedAsync.js +24 -0
  9. package/cjm/hooks/resolveHooks.js +44 -0
  10. package/cjm/index.js +16 -2
  11. package/cjm/injector/IInjector.js +12 -0
  12. package/cjm/provider/Provider.js +6 -6
  13. package/cjm/registration/IRegistration.js +1 -1
  14. package/esm/container/Container.js +16 -26
  15. package/esm/container/EmptyContainer.js +3 -6
  16. package/esm/hooks/onConstruct.js +2 -2
  17. package/esm/hooks/onConstructAsync.js +2 -2
  18. package/esm/hooks/onContainerDisposed.js +1 -1
  19. package/esm/hooks/onResolved.js +15 -0
  20. package/esm/hooks/onResolvedAsync.js +19 -0
  21. package/esm/hooks/resolveHooks.js +35 -0
  22. package/esm/index.js +4 -1
  23. package/esm/injector/IInjector.js +12 -0
  24. package/esm/provider/Provider.js +6 -6
  25. package/esm/registration/IRegistration.js +2 -2
  26. package/package.json +1 -1
  27. package/typings/container/Container.d.ts +5 -8
  28. package/typings/container/EmptyContainer.d.ts +3 -5
  29. package/typings/container/IContainer.d.ts +3 -7
  30. package/typings/hooks/onConstruct.d.ts +3 -3
  31. package/typings/hooks/onConstructAsync.d.ts +3 -3
  32. package/typings/hooks/onContainerDisposed.d.ts +0 -1
  33. package/typings/hooks/onResolved.d.ts +9 -0
  34. package/typings/hooks/onResolvedAsync.d.ts +12 -0
  35. package/typings/hooks/resolveHooks.d.ts +12 -0
  36. package/typings/index.d.ts +6 -3
  37. package/typings/injector/IInjector.d.ts +9 -1
  38. package/typings/provider/IProvider.d.ts +3 -2
  39. package/typings/provider/Provider.d.ts +4 -4
  40. package/typings/registration/IRegistration.d.ts +3 -3
package/README.md CHANGED
@@ -54,6 +54,7 @@ provider pipelines, aliases, and custom injector strategies.
54
54
  - [Scope](#scope) `scope`
55
55
  - [Module](#module)
56
56
  - [Hook](#hook) `@hook`
57
+ - [Hook domains](#hook-domains) `ScopeHook` `InjectorHook` `ProviderHook`
57
58
  - [OnConstruct](#onconstruct) `@onConstruct`
58
59
  - [OnConstructAsync](#onconstructasync) `@onConstructAsync`
59
60
  - [OnContainerDisposed](#oncontainerdisposed) `@onContainerDisposed`
@@ -2379,7 +2380,7 @@ describe('Decorator Pattern', () => {
2379
2380
 
2380
2381
  ### On resolve
2381
2382
 
2382
- Sometimes you don't want to change the dependency, only to react to it. Use the `onResolve(...)` pipe — it appends a `DependencyHook` that receives the resolved dependency and the resolving scope.
2383
+ Sometimes you don't want to change the dependency, only to react to it. Use the `onResolve(...)` pipe — it appends a `ProviderHook` that receives the resolved dependency and the resolving scope.
2383
2384
 
2384
2385
  - `provider(onResolve((instance, scope) => tracker.track(instance)))`
2385
2386
 
@@ -2833,11 +2834,57 @@ variadic signature and compensate for the bottom-up application order, so
2833
2834
  stacked decorators run in declaration order: `@onConstruct(h1) @onConstruct(h2)`
2834
2835
  runs `h1` before `h2`.
2835
2836
 
2837
+ ### Hook domains
2838
+
2839
+ The decorators above declare hook *metadata* on a class. The imperative side —
2840
+ the callbacks the container machinery runs — is registered on whichever
2841
+ abstraction raises the event, one hook type per domain:
2842
+
2843
+ | Domain | Registered on | Type | Methods |
2844
+ | ------------ | ------------- | --------------- | -------------------------------------------------------- |
2845
+ | **Scope** | `IContainer` | `ScopeHook` | `onScopeCreated(...)`, `onScopeDisposed(...)` |
2846
+ | **Scope** | `IContainer` | `RegisteredHook`| `onRegistered(...)` |
2847
+ | **Injector** | `IInjector` | `InjectorHook` | `onConstructed(...)` |
2848
+ | **Provider** | `IProvider` | `ProviderHook` | `onResolved(...)`, or the [`onResolve`](#on-resolve) pipe |
2849
+
2850
+ A container never hands its injector out — the injector is configured first and
2851
+ passed in at construction:
2852
+
2853
+ ```typescript
2854
+ // Construction is the injector's event, not a scope's
2855
+ const injector = new MetadataInjector().onConstructed((instance, scope) => metrics.built(instance, scope));
2856
+
2857
+ const container = new Container({ injector, tags: ['application'] })
2858
+ .onScopeCreated((scope) => audit.scopeOpened(scope))
2859
+ .onScopeDisposed((scope) => audit.scopeClosed(scope))
2860
+ .onRegistered((provider, key) => audit.registered(key));
2861
+ ```
2862
+
2863
+ A container passes its injector to every scope it creates, so **one injector**
2864
+ backs the whole scope tree and an `onConstructed` hook covers all of it, whenever
2865
+ it was added. Scope hooks, by contrast, are copied into a child at `createScope`
2866
+ time, so a child inherits what its parent held then and later additions to either
2867
+ stay local.
2868
+
2869
+ The built-in modules follow the same split. `OnConstructModule` and
2870
+ `OnConstructAsyncModule` are **injector** modules (`IInjectorModule`), applied
2871
+ with `injector.useModule(...)`:
2872
+
2873
+ ```typescript
2874
+ const injector = new MetadataInjector().useModule(new OnConstructModule());
2875
+ const container = new Container({ injector });
2876
+ ```
2877
+
2878
+ `OnDisposeModule` is a container module hooking `onScopeDisposed`, and
2879
+ `OnResolvedModule` / `OnResolvedAsyncModule` are container modules reaching every
2880
+ provider through `onRegistered`.
2881
+
2836
2882
  ### OnConstruct
2837
2883
 
2838
2884
  ```typescript
2839
2885
  import 'reflect-metadata';
2840
2886
  import {
2887
+ MetadataInjector,
2841
2888
  OnConstructModule,
2842
2889
  Container,
2843
2890
  type ExecutionContext,
@@ -2865,9 +2912,9 @@ describe('onConstruct', function () {
2865
2912
  }
2866
2913
  }
2867
2914
 
2868
- const container = new Container()
2869
- .useModule(new OnConstructModule())
2870
- .addRegistration(R.fromValue('postgres://localhost:5432').bindTo('ConnectionString'));
2915
+ const container = new Container({
2916
+ injector: new MetadataInjector().useModule(new OnConstructModule()),
2917
+ }).addRegistration(R.fromValue('postgres://localhost:5432').bindTo('ConnectionString'));
2871
2918
 
2872
2919
  const db = container.resolve(DatabaseConnection);
2873
2920
 
@@ -2886,11 +2933,13 @@ describe('onConstruct', function () {
2886
2933
  }
2887
2934
 
2888
2935
  let captured: { ex: unknown; context: ExecutionContext } | undefined;
2889
- const container = new Container().useModule(
2890
- new OnConstructModule((ex, context) => {
2891
- captured = { ex, context };
2892
- }),
2893
- );
2936
+ const container = new Container({
2937
+ injector: new MetadataInjector().useModule(
2938
+ new OnConstructModule((ex, context) => {
2939
+ captured = { ex, context };
2940
+ }),
2941
+ ),
2942
+ });
2894
2943
 
2895
2944
  expect(() => container.resolve(BrokenService)).not.toThrow();
2896
2945
  expect(captured?.ex).toBe(failure);
@@ -2907,7 +2956,7 @@ describe('onConstruct', function () {
2907
2956
  init() {}
2908
2957
  }
2909
2958
 
2910
- const container = new Container().useModule(new OnConstructModule());
2959
+ const container = new Container({ injector: new MetadataInjector().useModule(new OnConstructModule()) });
2911
2960
 
2912
2961
  expect(() => container.resolve(BrokenService)).toThrow(failure);
2913
2962
  });
@@ -2921,11 +2970,13 @@ describe('onConstruct', function () {
2921
2970
  }
2922
2971
 
2923
2972
  let scope: IContainer | undefined;
2924
- const container = new Container().useModule(
2925
- new OnConstructModule((_ex, context) => {
2926
- scope = context.scope;
2927
- }),
2928
- );
2973
+ const container = new Container({
2974
+ injector: new MetadataInjector().useModule(
2975
+ new OnConstructModule((_ex, context) => {
2976
+ scope = context.scope;
2977
+ }),
2978
+ ),
2979
+ });
2929
2980
  const child = container.createScope();
2930
2981
 
2931
2982
  child.resolve(BrokenService);
@@ -2945,6 +2996,7 @@ is created and they settle afterwards, so `resolve` returns before they finish.
2945
2996
  ```typescript
2946
2997
  import 'reflect-metadata';
2947
2998
  import {
2999
+ MetadataInjector,
2948
3000
  OnConstructAsyncModule,
2949
3001
  Container,
2950
3002
  type ExecutionContext,
@@ -2982,9 +3034,9 @@ describe('onConstructAsync', function () {
2982
3034
  }
2983
3035
  }
2984
3036
 
2985
- const container = new Container()
2986
- .useModule(new OnConstructAsyncModule())
2987
- .addRegistration(R.fromValue('postgres://localhost:5432').bindTo('ConnectionString'));
3037
+ const container = new Container({
3038
+ injector: new MetadataInjector().useModule(new OnConstructAsyncModule()),
3039
+ }).addRegistration(R.fromValue('postgres://localhost:5432').bindTo('ConnectionString'));
2988
3040
 
2989
3041
  const db = container.resolve(DatabaseConnection);
2990
3042
 
@@ -3006,11 +3058,13 @@ describe('onConstructAsync', function () {
3006
3058
  }
3007
3059
 
3008
3060
  let captured: { ex: unknown; context: ExecutionContext } | undefined;
3009
- const container = new Container().useModule(
3010
- new OnConstructAsyncModule((ex, context) => {
3011
- captured = { ex, context };
3012
- }),
3013
- );
3061
+ const container = new Container({
3062
+ injector: new MetadataInjector().useModule(
3063
+ new OnConstructAsyncModule((ex, context) => {
3064
+ captured = { ex, context };
3065
+ }),
3066
+ ),
3067
+ });
3014
3068
 
3015
3069
  const child = container.createScope();
3016
3070
  child.resolve(BrokenService);
@@ -19,10 +19,9 @@ class Container {
19
19
  providers = new Map();
20
20
  aliases = new AliasMap_1.AliasMap();
21
21
  injector;
22
- onConstructHookList = [];
23
- onDisposeHookList = [];
24
22
  onScopeCreatedHookList = [];
25
- onProviderRegisteredHookList = [];
23
+ onScopeDisposedHookList = [];
24
+ onRegisteredHookList = [];
26
25
  constructor(options = {}) {
27
26
  this.injector = options.injector ?? new MetadataInjector_1.MetadataInjector();
28
27
  this.parent = options.parent ?? new EmptyContainer_1.EmptyContainer();
@@ -32,8 +31,8 @@ class Container {
32
31
  this.validateContainer();
33
32
  this.providers.set(key, provider);
34
33
  this.aliases.setAliasesByKey(key, aliases);
35
- for (const onProviderRegistered of this.onProviderRegisteredHookList) {
36
- onProviderRegistered(provider, key, this);
34
+ for (const onRegistered of this.onRegisteredHookList) {
35
+ onRegistered(provider, key, this);
37
36
  }
38
37
  return this;
39
38
  }
@@ -78,10 +77,9 @@ class Container {
78
77
  createScope({ tags } = {}) {
79
78
  this.validateContainer();
80
79
  const scope = new Container({ injector: this.injector, parent: this, tags })
81
- .onConstruct(...this.onConstructHookList)
82
- .onInstanceDisposed(...this.onDisposeHookList)
83
80
  .onScopeCreated(...this.onScopeCreatedHookList)
84
- .onProviderRegistered(...this.onProviderRegisteredHookList);
81
+ .onScopeDisposed(...this.onScopeDisposedHookList)
82
+ .onRegistered(...this.onRegisteredHookList);
85
83
  for (const registration of this.getRegistrations()) {
86
84
  registration.applyTo(scope);
87
85
  }
@@ -103,8 +101,8 @@ class Container {
103
101
  dispose() {
104
102
  this.validateContainer();
105
103
  this.isDisposed = true;
106
- for (const hook of this.onDisposeHookList) {
107
- hook(this);
104
+ for (const onScopeDisposed of this.onScopeDisposedHookList) {
105
+ onScopeDisposed(this);
108
106
  }
109
107
  this.parent.removeScope(this);
110
108
  this.parent = new EmptyContainer_1.EmptyContainer();
@@ -115,10 +113,9 @@ class Container {
115
113
  this.aliases.destroy();
116
114
  this.instances.clear();
117
115
  this.registrations = [];
118
- this.onConstructHookList.length = 0;
119
- this.onDisposeHookList.length = 0;
120
116
  this.onScopeCreatedHookList.length = 0;
121
- this.onProviderRegisteredHookList.length = 0;
117
+ this.onScopeDisposedHookList.length = 0;
118
+ this.onRegisteredHookList.length = 0;
122
119
  }
123
120
  addRegistration(registration) {
124
121
  this.registrations.push(registration);
@@ -131,27 +128,20 @@ class Container {
131
128
  hasRegistration(key) {
132
129
  return this.registrations.some((r) => r.getKeyOrFail() === key) || this.parent.hasRegistration(key);
133
130
  }
134
- onConstruct(...hooks) {
135
- this.onConstructHookList.push(...hooks);
136
- return this;
137
- }
138
- onInstanceDisposed(...hooks) {
139
- this.onDisposeHookList.push(...hooks);
140
- return this;
141
- }
142
131
  onScopeCreated(...hooks) {
143
132
  this.onScopeCreatedHookList.push(...hooks);
144
133
  return this;
145
134
  }
146
- onProviderRegistered(...hooks) {
147
- this.onProviderRegisteredHookList.push(...hooks);
135
+ onScopeDisposed(...hooks) {
136
+ this.onScopeDisposedHookList.push(...hooks);
137
+ return this;
138
+ }
139
+ onRegistered(...hooks) {
140
+ this.onRegisteredHookList.push(...hooks);
148
141
  return this;
149
142
  }
150
143
  addInstance(instance) {
151
144
  this.instances.add(instance);
152
- for (const onConstruct of this.onConstructHookList) {
153
- onConstruct(instance, this);
154
- }
155
145
  }
156
146
  getScopes() {
157
147
  return [...this.scopes];
@@ -60,16 +60,13 @@ class EmptyContainer {
60
60
  resolveOneByAlias(alias, options) {
61
61
  throw new DependencyNotFoundError_1.DependencyNotFoundError(`Cannot find alias ${alias.toString()}`);
62
62
  }
63
- onInstanceDisposed(...hooks) {
64
- throw new MethodNotImplementedError_1.MethodNotImplementedError();
65
- }
66
- onConstruct(...hooks) {
63
+ onScopeCreated(...hooks) {
67
64
  throw new MethodNotImplementedError_1.MethodNotImplementedError();
68
65
  }
69
- onScopeCreated(...hooks) {
66
+ onScopeDisposed(...hooks) {
70
67
  throw new MethodNotImplementedError_1.MethodNotImplementedError();
71
68
  }
72
- onProviderRegistered(...hooks) {
69
+ onRegistered(...hooks) {
73
70
  throw new MethodNotImplementedError_1.MethodNotImplementedError();
74
71
  }
75
72
  }
@@ -11,8 +11,8 @@ class OnConstructModule {
11
11
  constructor(onException) {
12
12
  this.onException = onException;
13
13
  }
14
- applyTo(container) {
15
- container.onConstruct((instance, scope) => {
14
+ applyTo(injector) {
15
+ injector.onConstructed((instance, scope) => {
16
16
  try {
17
17
  exports.onConstructHooksRunner.execute(instance, { scope });
18
18
  }
@@ -11,8 +11,8 @@ class OnConstructAsyncModule {
11
11
  constructor(onException) {
12
12
  this.onException = onException;
13
13
  }
14
- applyTo(container) {
15
- container.onConstruct((instance, scope) => {
14
+ applyTo(injector) {
15
+ injector.onConstructed((instance, scope) => {
16
16
  if (!exports.onConstructAsyncHooksRunner.hasHooks(instance)) {
17
17
  return;
18
18
  }
@@ -8,7 +8,7 @@ const onContainerDisposed = (...fns) => (0, hook_1.hook)('onContainerDisposed',
8
8
  exports.onContainerDisposed = onContainerDisposed;
9
9
  class OnDisposeModule {
10
10
  applyTo(container) {
11
- container.onInstanceDisposed((scope) => {
11
+ container.onScopeDisposed((scope) => {
12
12
  for (const instance of scope.getInstances()) {
13
13
  exports.onContainerDisposedHooksRunner.execute(instance, { scope });
14
14
  }
@@ -0,0 +1,20 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.resolved = exports.OnResolvedModule = exports.onceResolved = exports.onResolved = exports.onResolvedHooksRunner = void 0;
4
+ const HooksRunner_1 = require("./HooksRunner");
5
+ const IRegistration_1 = require("../registration/IRegistration");
6
+ const resolveHooks_1 = require("./resolveHooks");
7
+ exports.onResolvedHooksRunner = new HooksRunner_1.HooksRunner('onResolved');
8
+ exports.onResolved = (0, resolveHooks_1.resolvedHook)('onResolved');
9
+ exports.onceResolved = (0, resolveHooks_1.onceResolvedHook)('onResolved');
10
+ const runHooks = (0, resolveHooks_1.forEachResolvedObject)((0, resolveHooks_1.executeHooks)(exports.onResolvedHooksRunner));
11
+ class OnResolvedModule {
12
+ applyTo(container) {
13
+ container.onRegistered((provider) => {
14
+ provider.onResolved(runHooks);
15
+ });
16
+ }
17
+ }
18
+ exports.OnResolvedModule = OnResolvedModule;
19
+ const resolved = () => (0, IRegistration_1.registerPipe)((p) => p.onResolved(runHooks));
20
+ exports.resolved = resolved;
@@ -0,0 +1,24 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.resolvedAsync = exports.OnResolvedAsyncModule = exports.onceResolvedAsync = exports.onResolvedAsync = exports.onResolvedAsyncHooksRunner = void 0;
4
+ const HooksRunner_1 = require("./HooksRunner");
5
+ const IRegistration_1 = require("../registration/IRegistration");
6
+ const resolveHooks_1 = require("./resolveHooks");
7
+ exports.onResolvedAsyncHooksRunner = new HooksRunner_1.HooksRunner('onResolvedAsync');
8
+ exports.onResolvedAsync = (0, resolveHooks_1.resolvedHook)('onResolvedAsync');
9
+ exports.onceResolvedAsync = (0, resolveHooks_1.onceResolvedHook)('onResolvedAsync');
10
+ const runHooks = (onException) => (0, resolveHooks_1.forEachResolvedObject)((0, resolveHooks_1.executeHooksAsync)(exports.onResolvedAsyncHooksRunner, onException));
11
+ class OnResolvedAsyncModule {
12
+ runHooks;
13
+ constructor(onException) {
14
+ this.runHooks = runHooks(onException);
15
+ }
16
+ applyTo(container) {
17
+ container.onRegistered((provider) => {
18
+ provider.onResolved(this.runHooks);
19
+ });
20
+ }
21
+ }
22
+ exports.OnResolvedAsyncModule = OnResolvedAsyncModule;
23
+ const resolvedAsync = (onException) => (0, IRegistration_1.registerPipe)((p) => p.onResolved(runHooks(onException)));
24
+ exports.resolvedAsync = resolvedAsync;
@@ -0,0 +1,44 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.executeHooksAsync = exports.executeHooks = exports.forEachResolvedObject = exports.onceResolvedHook = exports.resolvedHook = exports.invokeMethod = void 0;
4
+ const hook_1 = require("./hook");
5
+ const basic_1 = require("../utils/basic");
6
+ const invokeMethod = (context) => {
7
+ context.invokeMethod();
8
+ };
9
+ exports.invokeMethod = invokeMethod;
10
+ const toHooks = (hooks) => (hooks.length > 0 ? hooks : [exports.invokeMethod]);
11
+ const onceForEachInstance = (execute) => {
12
+ const invokedInstances = new WeakSet();
13
+ return (context) => {
14
+ if (invokedInstances.has(context.instance)) {
15
+ return;
16
+ }
17
+ invokedInstances.add(context.instance);
18
+ return (0, hook_1.toHookFn)(execute)(context);
19
+ };
20
+ };
21
+ const resolvedHook = (key) => (...hooks) => (0, hook_1.hook)(key, (0, hook_1.prependHooks)(...toHooks(hooks)));
22
+ exports.resolvedHook = resolvedHook;
23
+ const onceResolvedHook = (key) => (...hooks) => (0, hook_1.hook)(key, (0, hook_1.prependHooks)(...toHooks(hooks).map(onceForEachInstance)));
24
+ exports.onceResolvedHook = onceResolvedHook;
25
+ const forEachResolvedObject = (run) => (dependency, scope) => {
26
+ if (basic_1.Is.object(dependency)) {
27
+ run(dependency, scope);
28
+ }
29
+ };
30
+ exports.forEachResolvedObject = forEachResolvedObject;
31
+ const executeHooks = (runner) => (dependency, scope) => runner.execute(dependency, { scope });
32
+ exports.executeHooks = executeHooks;
33
+ const executeHooksAsync = (runner, onException) => (dependency, scope) => {
34
+ if (!runner.hasHooks(dependency)) {
35
+ return;
36
+ }
37
+ runner.executeAsync(dependency, { scope }).catch((ex) => {
38
+ if (!onException) {
39
+ throw ex;
40
+ }
41
+ onException(ex, { scope });
42
+ });
43
+ };
44
+ exports.executeHooksAsync = executeHooksAsync;
package/cjm/index.js CHANGED
@@ -1,8 +1,8 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.createHookContextFactory = exports.HookContext = exports.prepend = exports.append = exports.prependHooks = exports.appendHooks = exports.hasHooks = exports.hook = exports.getHooks = exports.UnsupportedTokenTypeError = exports.CannonSingletonApplyTwiceError = exports.UnexpectedHookResultError = 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.once = exports.shallowCache = 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.HooksRunner = exports.OnDisposeModule = exports.onContainerDisposed = exports.onContainerDisposedHooksRunner = exports.OnConstructAsyncModule = exports.onConstructAsync = exports.onConstructAsyncHooksRunner = exports.OnConstructModule = exports.onConstruct = exports.onConstructHooksRunner = exports.injectProp = exports.createHookContext = void 0;
5
- exports.Is = exports.unwrapProxy = exports.ProxyRegistry = exports.pipe = exports.select = void 0;
4
+ 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.HooksRunner = exports.invokeMethod = exports.resolvedAsync = exports.OnResolvedAsyncModule = exports.onceResolvedAsync = exports.onResolvedAsync = exports.onResolvedAsyncHooksRunner = exports.resolved = exports.OnResolvedModule = exports.onceResolved = exports.onResolved = exports.onResolvedHooksRunner = exports.OnDisposeModule = exports.onContainerDisposed = exports.onContainerDisposedHooksRunner = exports.OnConstructAsyncModule = exports.onConstructAsync = exports.onConstructAsyncHooksRunner = exports.OnConstructModule = exports.onConstruct = exports.onConstructHooksRunner = exports.injectProp = exports.createHookContext = void 0;
5
+ exports.Is = exports.unwrapProxy = exports.ProxyRegistry = exports.pipe = exports.select = exports.once = exports.shallowCache = exports.debounce = exports.throttle = exports.handleAsyncError = exports.handleError = exports.getMethodTags = exports.addMethodTag = exports.getMethodLabels = exports.addMethodLabel = exports.getMethodMeta = 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");
@@ -91,6 +91,20 @@ var onContainerDisposed_1 = require("./hooks/onContainerDisposed");
91
91
  Object.defineProperty(exports, "onContainerDisposedHooksRunner", { enumerable: true, get: function () { return onContainerDisposed_1.onContainerDisposedHooksRunner; } });
92
92
  Object.defineProperty(exports, "onContainerDisposed", { enumerable: true, get: function () { return onContainerDisposed_1.onContainerDisposed; } });
93
93
  Object.defineProperty(exports, "OnDisposeModule", { enumerable: true, get: function () { return onContainerDisposed_1.OnDisposeModule; } });
94
+ var onResolved_1 = require("./hooks/onResolved");
95
+ Object.defineProperty(exports, "onResolvedHooksRunner", { enumerable: true, get: function () { return onResolved_1.onResolvedHooksRunner; } });
96
+ Object.defineProperty(exports, "onResolved", { enumerable: true, get: function () { return onResolved_1.onResolved; } });
97
+ Object.defineProperty(exports, "onceResolved", { enumerable: true, get: function () { return onResolved_1.onceResolved; } });
98
+ Object.defineProperty(exports, "OnResolvedModule", { enumerable: true, get: function () { return onResolved_1.OnResolvedModule; } });
99
+ Object.defineProperty(exports, "resolved", { enumerable: true, get: function () { return onResolved_1.resolved; } });
100
+ var onResolvedAsync_1 = require("./hooks/onResolvedAsync");
101
+ Object.defineProperty(exports, "onResolvedAsyncHooksRunner", { enumerable: true, get: function () { return onResolvedAsync_1.onResolvedAsyncHooksRunner; } });
102
+ Object.defineProperty(exports, "onResolvedAsync", { enumerable: true, get: function () { return onResolvedAsync_1.onResolvedAsync; } });
103
+ Object.defineProperty(exports, "onceResolvedAsync", { enumerable: true, get: function () { return onResolvedAsync_1.onceResolvedAsync; } });
104
+ Object.defineProperty(exports, "OnResolvedAsyncModule", { enumerable: true, get: function () { return onResolvedAsync_1.OnResolvedAsyncModule; } });
105
+ Object.defineProperty(exports, "resolvedAsync", { enumerable: true, get: function () { return onResolvedAsync_1.resolvedAsync; } });
106
+ var resolveHooks_1 = require("./hooks/resolveHooks");
107
+ Object.defineProperty(exports, "invokeMethod", { enumerable: true, get: function () { return resolveHooks_1.invokeMethod; } });
94
108
  var HooksRunner_1 = require("./hooks/HooksRunner");
95
109
  Object.defineProperty(exports, "HooksRunner", { enumerable: true, get: function () { return HooksRunner_1.HooksRunner; } });
96
110
  var InjectionToken_1 = require("./token/InjectionToken");
@@ -4,6 +4,7 @@ exports.Injector = void 0;
4
4
  const ProxyRegistry_1 = require("../utils/ProxyRegistry");
5
5
  class Injector {
6
6
  proxyRegistry;
7
+ onConstructedHookList = [];
7
8
  constructor(proxyRegistry = ProxyRegistry_1.ProxyRegistry.getInstance()) {
8
9
  this.proxyRegistry = proxyRegistry;
9
10
  }
@@ -11,8 +12,19 @@ class Injector {
11
12
  return this.proxyRegistry.toLazyIf(() => {
12
13
  const instance = this.createInstance(scope, Target, { args });
13
14
  scope.addInstance(instance);
15
+ for (const onConstructed of this.onConstructedHookList) {
16
+ onConstructed(instance, scope);
17
+ }
14
18
  return instance;
15
19
  }, lazy);
16
20
  }
21
+ onConstructed(...hooks) {
22
+ this.onConstructedHookList.push(...hooks);
23
+ return this;
24
+ }
25
+ useModule(module) {
26
+ module.applyTo(this);
27
+ return this;
28
+ }
17
29
  }
18
30
  exports.Injector = Injector;
@@ -22,7 +22,7 @@ class Provider {
22
22
  cache = new Map();
23
23
  getKey;
24
24
  isDisposed = false;
25
- onResolveHookList = [];
25
+ onResolvedHookList = [];
26
26
  constructor(resolveDependency) {
27
27
  this.resolveDependency = resolveDependency;
28
28
  }
@@ -43,8 +43,8 @@ class Provider {
43
43
  lazy: lazy ?? this.isLazy,
44
44
  });
45
45
  dependency = this.mappers.reduce((acc, current) => current(acc, scope), dependency);
46
- for (const onResolve of this.onResolveHookList) {
47
- onResolve(dependency, scope);
46
+ for (const onResolved of this.onResolvedHookList) {
47
+ onResolved(dependency, scope);
48
48
  }
49
49
  return dependency;
50
50
  }
@@ -81,8 +81,8 @@ class Provider {
81
81
  this.getKey = getCacheKey;
82
82
  return this;
83
83
  }
84
- onResolve(...hooks) {
85
- this.onResolveHookList.push(...hooks);
84
+ onResolved(...hooks) {
85
+ this.onResolvedHookList.push(...hooks);
86
86
  return this;
87
87
  }
88
88
  dispose() {
@@ -94,7 +94,7 @@ class Provider {
94
94
  this.accessRules.splice(0, this.accessRules.length);
95
95
  this.mappers.splice(0, this.mappers.length);
96
96
  this.argsFnList.splice(0, this.argsFnList.length);
97
- this.onResolveHookList.splice(0, this.onResolveHookList.length);
97
+ this.onResolvedHookList.splice(0, this.onResolvedHookList.length);
98
98
  }
99
99
  }
100
100
  exports.Provider = Provider;
@@ -54,5 +54,5 @@ const decorate = (...fns) => (0, exports.registerPipe)((p) => p.map(...fns));
54
54
  exports.decorate = decorate;
55
55
  const singleton = (getCacheKey) => (0, exports.registerPipe)((p) => p.singleton(getCacheKey));
56
56
  exports.singleton = singleton;
57
- const onResolve = (...hooks) => (0, exports.registerPipe)((p) => p.onResolve(...hooks));
57
+ const onResolve = (...hooks) => (0, exports.registerPipe)((p) => p.onResolved(...hooks));
58
58
  exports.onResolve = onResolve;
@@ -16,10 +16,9 @@ export class Container {
16
16
  providers = new Map();
17
17
  aliases = new AliasMap();
18
18
  injector;
19
- onConstructHookList = [];
20
- onDisposeHookList = [];
21
19
  onScopeCreatedHookList = [];
22
- onProviderRegisteredHookList = [];
20
+ onScopeDisposedHookList = [];
21
+ onRegisteredHookList = [];
23
22
  constructor(options = {}) {
24
23
  this.injector = options.injector ?? new MetadataInjector();
25
24
  this.parent = options.parent ?? new EmptyContainer();
@@ -29,8 +28,8 @@ export class Container {
29
28
  this.validateContainer();
30
29
  this.providers.set(key, provider);
31
30
  this.aliases.setAliasesByKey(key, aliases);
32
- for (const onProviderRegistered of this.onProviderRegisteredHookList) {
33
- onProviderRegistered(provider, key, this);
31
+ for (const onRegistered of this.onRegisteredHookList) {
32
+ onRegistered(provider, key, this);
34
33
  }
35
34
  return this;
36
35
  }
@@ -75,10 +74,9 @@ export class Container {
75
74
  createScope({ tags } = {}) {
76
75
  this.validateContainer();
77
76
  const scope = new Container({ injector: this.injector, parent: this, tags })
78
- .onConstruct(...this.onConstructHookList)
79
- .onInstanceDisposed(...this.onDisposeHookList)
80
77
  .onScopeCreated(...this.onScopeCreatedHookList)
81
- .onProviderRegistered(...this.onProviderRegisteredHookList);
78
+ .onScopeDisposed(...this.onScopeDisposedHookList)
79
+ .onRegistered(...this.onRegisteredHookList);
82
80
  for (const registration of this.getRegistrations()) {
83
81
  registration.applyTo(scope);
84
82
  }
@@ -100,8 +98,8 @@ export class Container {
100
98
  dispose() {
101
99
  this.validateContainer();
102
100
  this.isDisposed = true;
103
- for (const hook of this.onDisposeHookList) {
104
- hook(this);
101
+ for (const onScopeDisposed of this.onScopeDisposedHookList) {
102
+ onScopeDisposed(this);
105
103
  }
106
104
  this.parent.removeScope(this);
107
105
  this.parent = new EmptyContainer();
@@ -112,10 +110,9 @@ export class Container {
112
110
  this.aliases.destroy();
113
111
  this.instances.clear();
114
112
  this.registrations = [];
115
- this.onConstructHookList.length = 0;
116
- this.onDisposeHookList.length = 0;
117
113
  this.onScopeCreatedHookList.length = 0;
118
- this.onProviderRegisteredHookList.length = 0;
114
+ this.onScopeDisposedHookList.length = 0;
115
+ this.onRegisteredHookList.length = 0;
119
116
  }
120
117
  addRegistration(registration) {
121
118
  this.registrations.push(registration);
@@ -128,27 +125,20 @@ export class Container {
128
125
  hasRegistration(key) {
129
126
  return this.registrations.some((r) => r.getKeyOrFail() === key) || this.parent.hasRegistration(key);
130
127
  }
131
- onConstruct(...hooks) {
132
- this.onConstructHookList.push(...hooks);
133
- return this;
134
- }
135
- onInstanceDisposed(...hooks) {
136
- this.onDisposeHookList.push(...hooks);
137
- return this;
138
- }
139
128
  onScopeCreated(...hooks) {
140
129
  this.onScopeCreatedHookList.push(...hooks);
141
130
  return this;
142
131
  }
143
- onProviderRegistered(...hooks) {
144
- this.onProviderRegisteredHookList.push(...hooks);
132
+ onScopeDisposed(...hooks) {
133
+ this.onScopeDisposedHookList.push(...hooks);
134
+ return this;
135
+ }
136
+ onRegistered(...hooks) {
137
+ this.onRegisteredHookList.push(...hooks);
145
138
  return this;
146
139
  }
147
140
  addInstance(instance) {
148
141
  this.instances.add(instance);
149
- for (const onConstruct of this.onConstructHookList) {
150
- onConstruct(instance, this);
151
- }
152
142
  }
153
143
  getScopes() {
154
144
  return [...this.scopes];
@@ -57,16 +57,13 @@ export class EmptyContainer {
57
57
  resolveOneByAlias(alias, options) {
58
58
  throw new DependencyNotFoundError(`Cannot find alias ${alias.toString()}`);
59
59
  }
60
- onInstanceDisposed(...hooks) {
61
- throw new MethodNotImplementedError();
62
- }
63
- onConstruct(...hooks) {
60
+ onScopeCreated(...hooks) {
64
61
  throw new MethodNotImplementedError();
65
62
  }
66
- onScopeCreated(...hooks) {
63
+ onScopeDisposed(...hooks) {
67
64
  throw new MethodNotImplementedError();
68
65
  }
69
- onProviderRegistered(...hooks) {
66
+ onRegistered(...hooks) {
70
67
  throw new MethodNotImplementedError();
71
68
  }
72
69
  }
@@ -7,8 +7,8 @@ export class OnConstructModule {
7
7
  constructor(onException) {
8
8
  this.onException = onException;
9
9
  }
10
- applyTo(container) {
11
- container.onConstruct((instance, scope) => {
10
+ applyTo(injector) {
11
+ injector.onConstructed((instance, scope) => {
12
12
  try {
13
13
  onConstructHooksRunner.execute(instance, { scope });
14
14
  }
@@ -7,8 +7,8 @@ export class OnConstructAsyncModule {
7
7
  constructor(onException) {
8
8
  this.onException = onException;
9
9
  }
10
- applyTo(container) {
11
- container.onConstruct((instance, scope) => {
10
+ applyTo(injector) {
11
+ injector.onConstructed((instance, scope) => {
12
12
  if (!onConstructAsyncHooksRunner.hasHooks(instance)) {
13
13
  return;
14
14
  }
@@ -4,7 +4,7 @@ export const onContainerDisposedHooksRunner = new HooksRunner('onContainerDispos
4
4
  export const onContainerDisposed = (...fns) => hook('onContainerDisposed', prependHooks(...fns));
5
5
  export class OnDisposeModule {
6
6
  applyTo(container) {
7
- container.onInstanceDisposed((scope) => {
7
+ container.onScopeDisposed((scope) => {
8
8
  for (const instance of scope.getInstances()) {
9
9
  onContainerDisposedHooksRunner.execute(instance, { scope });
10
10
  }
@@ -0,0 +1,15 @@
1
+ import { HooksRunner } from './HooksRunner.js';
2
+ import { registerPipe } from '../registration/IRegistration.js';
3
+ import { executeHooks, forEachResolvedObject, onceResolvedHook, resolvedHook } from './resolveHooks.js';
4
+ export const onResolvedHooksRunner = new HooksRunner('onResolved');
5
+ export const onResolved = resolvedHook('onResolved');
6
+ export const onceResolved = onceResolvedHook('onResolved');
7
+ const runHooks = forEachResolvedObject(executeHooks(onResolvedHooksRunner));
8
+ export class OnResolvedModule {
9
+ applyTo(container) {
10
+ container.onRegistered((provider) => {
11
+ provider.onResolved(runHooks);
12
+ });
13
+ }
14
+ }
15
+ export const resolved = () => registerPipe((p) => p.onResolved(runHooks));
@@ -0,0 +1,19 @@
1
+ import { HooksRunner } from './HooksRunner.js';
2
+ import { registerPipe } from '../registration/IRegistration.js';
3
+ import { executeHooksAsync, forEachResolvedObject, onceResolvedHook, resolvedHook } from './resolveHooks.js';
4
+ export const onResolvedAsyncHooksRunner = new HooksRunner('onResolvedAsync');
5
+ export const onResolvedAsync = resolvedHook('onResolvedAsync');
6
+ export const onceResolvedAsync = onceResolvedHook('onResolvedAsync');
7
+ const runHooks = (onException) => forEachResolvedObject(executeHooksAsync(onResolvedAsyncHooksRunner, onException));
8
+ export class OnResolvedAsyncModule {
9
+ runHooks;
10
+ constructor(onException) {
11
+ this.runHooks = runHooks(onException);
12
+ }
13
+ applyTo(container) {
14
+ container.onRegistered((provider) => {
15
+ provider.onResolved(this.runHooks);
16
+ });
17
+ }
18
+ }
19
+ export const resolvedAsync = (onException) => registerPipe((p) => p.onResolved(runHooks(onException)));
@@ -0,0 +1,35 @@
1
+ import { hook, prependHooks, toHookFn } from './hook.js';
2
+ import { Is } from '../utils/basic.js';
3
+ export const invokeMethod = (context) => {
4
+ context.invokeMethod();
5
+ };
6
+ const toHooks = (hooks) => (hooks.length > 0 ? hooks : [invokeMethod]);
7
+ const onceForEachInstance = (execute) => {
8
+ const invokedInstances = new WeakSet();
9
+ return (context) => {
10
+ if (invokedInstances.has(context.instance)) {
11
+ return;
12
+ }
13
+ invokedInstances.add(context.instance);
14
+ return toHookFn(execute)(context);
15
+ };
16
+ };
17
+ export const resolvedHook = (key) => (...hooks) => hook(key, prependHooks(...toHooks(hooks)));
18
+ export const onceResolvedHook = (key) => (...hooks) => hook(key, prependHooks(...toHooks(hooks).map(onceForEachInstance)));
19
+ export const forEachResolvedObject = (run) => (dependency, scope) => {
20
+ if (Is.object(dependency)) {
21
+ run(dependency, scope);
22
+ }
23
+ };
24
+ export const executeHooks = (runner) => (dependency, scope) => runner.execute(dependency, { scope });
25
+ export const executeHooksAsync = (runner, onException) => (dependency, scope) => {
26
+ if (!runner.hasHooks(dependency)) {
27
+ return;
28
+ }
29
+ runner.executeAsync(dependency, { scope }).catch((ex) => {
30
+ if (!onException) {
31
+ throw ex;
32
+ }
33
+ onException(ex, { scope });
34
+ });
35
+ };
package/esm/index.js CHANGED
@@ -2,7 +2,7 @@ export { isDependencyKey, } from './container/IContainer.js';
2
2
  export { Container } from './container/Container.js';
3
3
  export { AutoResolveModule } from './container/AutoResolveModule.js';
4
4
  export { EmptyContainer } from './container/EmptyContainer.js';
5
- export { Injector } from './injector/IInjector.js';
5
+ export { Injector, } from './injector/IInjector.js';
6
6
  export { MetadataInjector, inject, arg, args, argsFn, resolveArgs } from './injector/MetadataInjector.js';
7
7
  export { SimpleInjector } from './injector/SimpleInjector.js';
8
8
  export { ProxyInjector } from './injector/ProxyInjector.js';
@@ -25,6 +25,9 @@ export { injectProp } from './hooks/injectProp.js';
25
25
  export { onConstructHooksRunner, onConstruct, OnConstructModule } from './hooks/onConstruct.js';
26
26
  export { onConstructAsyncHooksRunner, onConstructAsync, OnConstructAsyncModule } from './hooks/onConstructAsync.js';
27
27
  export { onContainerDisposedHooksRunner, onContainerDisposed, OnDisposeModule } from './hooks/onContainerDisposed.js';
28
+ export { onResolvedHooksRunner, onResolved, onceResolved, OnResolvedModule, resolved } from './hooks/onResolved.js';
29
+ export { onResolvedAsyncHooksRunner, onResolvedAsync, onceResolvedAsync, OnResolvedAsyncModule, resolvedAsync, } from './hooks/onResolvedAsync.js';
30
+ export { invokeMethod } from './hooks/resolveHooks.js';
28
31
  export { HooksRunner } from './hooks/HooksRunner.js';
29
32
  export { InjectionToken } from './token/InjectionToken.js';
30
33
  export { toToken, toMappedToken, argToToken } from './token/toToken.js';
@@ -1,6 +1,7 @@
1
1
  import { ProxyRegistry } from '../utils/ProxyRegistry.js';
2
2
  export class Injector {
3
3
  proxyRegistry;
4
+ onConstructedHookList = [];
4
5
  constructor(proxyRegistry = ProxyRegistry.getInstance()) {
5
6
  this.proxyRegistry = proxyRegistry;
6
7
  }
@@ -8,7 +9,18 @@ export class Injector {
8
9
  return this.proxyRegistry.toLazyIf(() => {
9
10
  const instance = this.createInstance(scope, Target, { args });
10
11
  scope.addInstance(instance);
12
+ for (const onConstructed of this.onConstructedHookList) {
13
+ onConstructed(instance, scope);
14
+ }
11
15
  return instance;
12
16
  }, lazy);
13
17
  }
18
+ onConstructed(...hooks) {
19
+ this.onConstructedHookList.push(...hooks);
20
+ return this;
21
+ }
22
+ useModule(module) {
23
+ module.applyTo(this);
24
+ return this;
25
+ }
14
26
  }
@@ -19,7 +19,7 @@ export class Provider {
19
19
  cache = new Map();
20
20
  getKey;
21
21
  isDisposed = false;
22
- onResolveHookList = [];
22
+ onResolvedHookList = [];
23
23
  constructor(resolveDependency) {
24
24
  this.resolveDependency = resolveDependency;
25
25
  }
@@ -40,8 +40,8 @@ export class Provider {
40
40
  lazy: lazy ?? this.isLazy,
41
41
  });
42
42
  dependency = this.mappers.reduce((acc, current) => current(acc, scope), dependency);
43
- for (const onResolve of this.onResolveHookList) {
44
- onResolve(dependency, scope);
43
+ for (const onResolved of this.onResolvedHookList) {
44
+ onResolved(dependency, scope);
45
45
  }
46
46
  return dependency;
47
47
  }
@@ -78,8 +78,8 @@ export class Provider {
78
78
  this.getKey = getCacheKey;
79
79
  return this;
80
80
  }
81
- onResolve(...hooks) {
82
- this.onResolveHookList.push(...hooks);
81
+ onResolved(...hooks) {
82
+ this.onResolvedHookList.push(...hooks);
83
83
  return this;
84
84
  }
85
85
  dispose() {
@@ -91,6 +91,6 @@ export class Provider {
91
91
  this.accessRules.splice(0, this.accessRules.length);
92
92
  this.mappers.splice(0, this.mappers.length);
93
93
  this.argsFnList.splice(0, this.argsFnList.length);
94
- this.onResolveHookList.splice(0, this.onResolveHookList.length);
94
+ this.onResolvedHookList.splice(0, this.onResolvedHookList.length);
95
95
  }
96
96
  }
@@ -1,4 +1,4 @@
1
- import { isDependencyKey, } from '../container/IContainer.js';
1
+ import { isDependencyKey } from '../container/IContainer.js';
2
2
  import { SingleToken } from '../token/SingleToken.js';
3
3
  import { addClassMeta, getClassMeta } from '../metadata/class.js';
4
4
  export const isProviderPipe = (obj) => obj !== null && typeof obj === 'object' && 'mapProvider' in obj;
@@ -35,4 +35,4 @@ export const lazy = () => registerPipe((p) => p.lazy());
35
35
  export const autoResolve = () => registerPipe((p) => p.autoResolve());
36
36
  export const decorate = (...fns) => registerPipe((p) => p.map(...fns));
37
37
  export const singleton = (getCacheKey) => registerPipe((p) => p.singleton(getCacheKey));
38
- export const onResolve = (...hooks) => registerPipe((p) => p.onResolve(...hooks));
38
+ export const onResolve = (...hooks) => registerPipe((p) => p.onResolved(...hooks));
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ts-ioc-container",
3
- "version": "60.2.0",
3
+ "version": "61.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",
@@ -1,8 +1,7 @@
1
- import { type AutoResolveOptions, type CreateScopeOptions, type DependencyKey, type IContainer, type IContainerModule, type InstanceHook, type ProviderHook, type RegisterOptions, ResolveManyOptions, type ResolveOneOptions, type ScopeHook, type Tag } from './IContainer.js';
1
+ import { type AutoResolveOptions, type CreateScopeOptions, type DependencyKey, type IContainer, type IContainerModule, type RegisteredHook, type RegisterOptions, ResolveManyOptions, type ResolveOneOptions, type ScopeHook, type Tag } from './IContainer.js';
2
2
  import { type IInjector } from '../injector/IInjector.js';
3
3
  import { type IProvider } from '../provider/IProvider.js';
4
4
  import { type IRegistration } from '../registration/IRegistration.js';
5
- import { OnDisposeHook } from '../hooks/onContainerDisposed.js';
6
5
  import { constructor, Instance } from '../utils/basic.js';
7
6
  export declare class Container implements IContainer {
8
7
  isDisposed: boolean;
@@ -14,10 +13,9 @@ export declare class Container implements IContainer {
14
13
  private readonly providers;
15
14
  private readonly aliases;
16
15
  private readonly injector;
17
- private readonly onConstructHookList;
18
- private readonly onDisposeHookList;
19
16
  private readonly onScopeCreatedHookList;
20
- private readonly onProviderRegisteredHookList;
17
+ private readonly onScopeDisposedHookList;
18
+ private readonly onRegisteredHookList;
21
19
  constructor(options?: {
22
20
  injector?: IInjector;
23
21
  parent?: IContainer;
@@ -33,10 +31,9 @@ export declare class Container implements IContainer {
33
31
  addRegistration(registration: IRegistration): this;
34
32
  getRegistrations(): IRegistration[];
35
33
  hasRegistration(key: DependencyKey): boolean;
36
- onConstruct(...hooks: InstanceHook[]): this;
37
- onInstanceDisposed(...hooks: OnDisposeHook[]): this;
38
34
  onScopeCreated(...hooks: ScopeHook[]): this;
39
- onProviderRegistered(...hooks: ProviderHook[]): this;
35
+ onScopeDisposed(...hooks: ScopeHook[]): this;
36
+ onRegistered(...hooks: RegisteredHook[]): this;
40
37
  addInstance(instance: Instance): void;
41
38
  getScopes(): IContainer[];
42
39
  hasInstance(instance: Instance): boolean;
@@ -1,7 +1,6 @@
1
- import { type AutoResolveOptions, type DependencyKey, type IContainer, type IContainerModule, type ScopeHook, type ProviderHook, type ResolveManyOptions, type ResolveOneOptions, type Tag, type InstanceHook } from './IContainer.js';
1
+ import { type AutoResolveOptions, type DependencyKey, type IContainer, type IContainerModule, type ScopeHook, type RegisteredHook, type ResolveManyOptions, type ResolveOneOptions, type Tag } from './IContainer.js';
2
2
  import { type IProvider } from '../provider/IProvider.js';
3
3
  import { type IRegistration } from '../registration/IRegistration.js';
4
- import { OnDisposeHook } from '../hooks/onContainerDisposed.js';
5
4
  import { type constructor, type Instance } from '../utils/basic.js';
6
5
  export declare class EmptyContainer implements IContainer {
7
6
  get isDisposed(): boolean;
@@ -24,8 +23,7 @@ export declare class EmptyContainer implements IContainer {
24
23
  resolve<T>(key: constructor<T> | DependencyKey, options?: ResolveOneOptions): T;
25
24
  resolveByAlias<T>(alias: DependencyKey, options?: ResolveManyOptions): T[];
26
25
  resolveOneByAlias<T>(alias: DependencyKey, options?: ResolveOneOptions): T;
27
- onInstanceDisposed(...hooks: OnDisposeHook[]): this;
28
- onConstruct(...hooks: InstanceHook[]): this;
29
26
  onScopeCreated(...hooks: ScopeHook[]): this;
30
- onProviderRegistered(...hooks: ProviderHook[]): this;
27
+ onScopeDisposed(...hooks: ScopeHook[]): this;
28
+ onRegistered(...hooks: RegisteredHook[]): this;
31
29
  }
@@ -1,6 +1,5 @@
1
1
  import { type IProvider, ProviderOptions } from '../provider/IProvider.js';
2
2
  import { type IRegistration } from '../registration/IRegistration.js';
3
- import { OnDisposeHook } from '../hooks/onContainerDisposed.js';
4
3
  import { type WithArgs } from '../injector/IInjector.js';
5
4
  import { type constructor, Instance } from '../utils/basic.js';
6
5
  export type DependencyKey = string | symbol;
@@ -33,15 +32,12 @@ export type RegisterOptions = {
33
32
  aliases?: DependencyKey[];
34
33
  };
35
34
  export type ScopeHook = (scope: IContainer) => void;
36
- export type InstanceHook = (instance: Instance, scope: IContainer) => void;
37
- export type DependencyHook = (dependency: unknown, scope: IContainer) => void;
38
- export type ProviderHook = (provider: IProvider, key: DependencyKey, scope: IContainer) => void;
35
+ export type RegisteredHook = (provider: IProvider, key: DependencyKey, scope: IContainer) => void;
39
36
  export interface IContainer extends Tagged {
40
37
  readonly isDisposed: boolean;
41
- onConstruct(...hooks: InstanceHook[]): this;
42
- onInstanceDisposed(...hooks: OnDisposeHook[]): this;
43
38
  onScopeCreated(...hooks: ScopeHook[]): this;
44
- onProviderRegistered(...hooks: ProviderHook[]): this;
39
+ onScopeDisposed(...hooks: ScopeHook[]): this;
40
+ onRegistered(...hooks: RegisteredHook[]): this;
45
41
  register(key: DependencyKey, value: IProvider, options?: RegisterOptions): this;
46
42
  addRegistration(registration: IRegistration): this;
47
43
  getRegistrations(): IRegistration[];
@@ -1,12 +1,12 @@
1
1
  import { HookType } from './hook.js';
2
- import type { IContainer, IContainerModule } from '../container/IContainer.js';
2
+ import type { IInjector, IInjectorModule } from '../injector/IInjector.js';
3
3
  import { HooksRunner } from './HooksRunner.js';
4
4
  import type { ExecutionContext } from '../ExecutionContext.js';
5
5
  export declare const onConstructHooksRunner: HooksRunner;
6
6
  export declare const onConstruct: (...fns: HookType[]) => (target: object, propertyKey: string | symbol) => void;
7
7
  export type OnExceptionHandler = (ex: unknown, context: ExecutionContext) => void;
8
- export declare class OnConstructModule implements IContainerModule {
8
+ export declare class OnConstructModule implements IInjectorModule {
9
9
  private readonly onException?;
10
10
  constructor(onException?: OnExceptionHandler | undefined);
11
- applyTo(container: IContainer): void;
11
+ applyTo(injector: IInjector): void;
12
12
  }
@@ -1,11 +1,11 @@
1
1
  import { HookType } from './hook.js';
2
- import type { IContainer, IContainerModule } from '../container/IContainer.js';
2
+ import type { IInjector, IInjectorModule } from '../injector/IInjector.js';
3
3
  import { HooksRunner } from './HooksRunner.js';
4
4
  import type { OnExceptionHandler } from './onConstruct.js';
5
5
  export declare const onConstructAsyncHooksRunner: HooksRunner;
6
6
  export declare const onConstructAsync: (...fns: HookType[]) => (target: object, propertyKey: string | symbol) => void;
7
- export declare class OnConstructAsyncModule implements IContainerModule {
7
+ export declare class OnConstructAsyncModule implements IInjectorModule {
8
8
  private readonly onException?;
9
9
  constructor(onException?: OnExceptionHandler | undefined);
10
- applyTo(container: IContainer): void;
10
+ applyTo(injector: IInjector): void;
11
11
  }
@@ -3,7 +3,6 @@ import type { IContainer, IContainerModule } from '../container/IContainer.js';
3
3
  import { HooksRunner } from './HooksRunner.js';
4
4
  export declare const onContainerDisposedHooksRunner: HooksRunner;
5
5
  export declare const onContainerDisposed: (...fns: HookType[]) => (target: object, propertyKey: string | symbol) => void;
6
- export type OnDisposeHook = (scope: IContainer) => void;
7
6
  export declare class OnDisposeModule implements IContainerModule {
8
7
  applyTo(container: IContainer): void;
9
8
  }
@@ -0,0 +1,9 @@
1
+ import type { IContainer, IContainerModule } from '../container/IContainer.js';
2
+ import { HooksRunner } 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;
5
+ export declare const onceResolved: (...hooks: import("./hook.js").HookType[]) => (target: object, propertyKey: string | symbol) => void;
6
+ export declare class OnResolvedModule implements IContainerModule {
7
+ applyTo(container: IContainer): void;
8
+ }
9
+ export declare const resolved: <T = unknown>() => import("../registration/IRegistration.js").ProviderPipe<T>;
@@ -0,0 +1,12 @@
1
+ import type { IContainer, IContainerModule } from '../container/IContainer.js';
2
+ import { HooksRunner } from './HooksRunner.js';
3
+ import type { OnExceptionHandler } from './onConstruct.js';
4
+ export declare const onResolvedAsyncHooksRunner: HooksRunner;
5
+ export declare const onResolvedAsync: (...hooks: import("./hook.js").HookType[]) => (target: object, propertyKey: string | symbol) => void;
6
+ export declare const onceResolvedAsync: (...hooks: import("./hook.js").HookType[]) => (target: object, propertyKey: string | symbol) => void;
7
+ export declare class OnResolvedAsyncModule implements IContainerModule {
8
+ private readonly runHooks;
9
+ constructor(onException?: OnExceptionHandler);
10
+ applyTo(container: IContainer): void;
11
+ }
12
+ export declare const resolvedAsync: <T = unknown>(onException?: OnExceptionHandler) => import("../registration/IRegistration.js").ProviderPipe<T>;
@@ -0,0 +1,12 @@
1
+ import type { IContainer } from '../container/IContainer.js';
2
+ import type { ProviderHook } from '../provider/IProvider.js';
3
+ import type { HooksRunner } from './HooksRunner.js';
4
+ import { type HookFn, type HookType } from './hook.js';
5
+ import type { OnExceptionHandler } from './onConstruct.js';
6
+ export type ResolvedObjectHook = (dependency: object, scope: IContainer) => void;
7
+ export declare const invokeMethod: HookFn;
8
+ export declare const resolvedHook: (key: string) => (...hooks: HookType[]) => (target: object, propertyKey: string | symbol) => void;
9
+ export declare const onceResolvedHook: (key: string) => (...hooks: HookType[]) => (target: object, propertyKey: string | symbol) => void;
10
+ export declare const forEachResolvedObject: (run: ResolvedObjectHook) => ProviderHook;
11
+ export declare const executeHooks: (runner: HooksRunner) => ResolvedObjectHook;
12
+ export declare const executeHooksAsync: (runner: HooksRunner, onException?: OnExceptionHandler) => ResolvedObjectHook;
@@ -1,12 +1,12 @@
1
- export { type IContainer, type Resolvable, type IContainerModule, type DependencyKey, type Tag, type Tagged, type ResolveOneOptions, type ResolveManyOptions, type ScopeHook, type InstanceHook, type DependencyHook, type ProviderHook, type AutoResolveOptions, isDependencyKey, } from './container/IContainer.js';
1
+ export { type IContainer, type Resolvable, type IContainerModule, type DependencyKey, type Tag, type Tagged, type ResolveOneOptions, type ResolveManyOptions, type ScopeHook, type RegisteredHook, type AutoResolveOptions, isDependencyKey, } from './container/IContainer.js';
2
2
  export { Container } from './container/Container.js';
3
3
  export { AutoResolveModule } from './container/AutoResolveModule.js';
4
4
  export { EmptyContainer } from './container/EmptyContainer.js';
5
- export { type IInjector, type InjectOptions, type IInjectFnResolver, Injector } from './injector/IInjector.js';
5
+ export { type IInjector, type InjectOptions, type IInjectFnResolver, type IInjectorModule, type InjectorHook, Injector, } from './injector/IInjector.js';
6
6
  export { MetadataInjector, inject, arg, args, argsFn, resolveArgs } from './injector/MetadataInjector.js';
7
7
  export { SimpleInjector } from './injector/SimpleInjector.js';
8
8
  export { ProxyInjector } from './injector/ProxyInjector.js';
9
- export { type ResolveDependency, type IProvider, type DecorateFn, type ArgsFn, type ProviderOptions, type GetCacheKey, type ScopeAccessOptions, type ScopeAccessRule, } from './provider/IProvider.js';
9
+ export { type ResolveDependency, type IProvider, type DecorateFn, type ArgsFn, type ProviderOptions, type GetCacheKey, type ScopeAccessOptions, type ScopeAccessRule, type ProviderHook, } from './provider/IProvider.js';
10
10
  export { Provider } from './provider/Provider.js';
11
11
  export { type IRegistration, type ReturnTypeOfRegistration, type ScopeMatchRule, type ProviderPipe, type Bindable, type ProviderMapper, type RegistrationMapper, isProviderPipe, registerPipe, toBindToken, toProviderFn, toRegistrationFn, register, bindTo, scope, scopeAccess, lazy, autoResolve, singleton, decorate, appendArgs, appendArgsFn, onResolve, } from './registration/IRegistration.js';
12
12
  export { Registration } from './registration/Registration.js';
@@ -26,6 +26,9 @@ export { injectProp } from './hooks/injectProp.js';
26
26
  export { onConstructHooksRunner, onConstruct, OnConstructModule, type OnExceptionHandler } from './hooks/onConstruct.js';
27
27
  export { onConstructAsyncHooksRunner, onConstructAsync, OnConstructAsyncModule } from './hooks/onConstructAsync.js';
28
28
  export { onContainerDisposedHooksRunner, onContainerDisposed, OnDisposeModule } from './hooks/onContainerDisposed.js';
29
+ export { onResolvedHooksRunner, onResolved, onceResolved, OnResolvedModule, resolved } from './hooks/onResolved.js';
30
+ export { onResolvedAsyncHooksRunner, onResolvedAsync, onceResolvedAsync, OnResolvedAsyncModule, resolvedAsync, } from './hooks/onResolvedAsync.js';
31
+ export { invokeMethod, type ResolvedObjectHook } from './hooks/resolveHooks.js';
29
32
  export { HooksRunner, type HooksRunnerContext, type MapHookContext } from './hooks/HooksRunner.js';
30
33
  export { InjectionToken } from './token/InjectionToken.js';
31
34
  export { type Injectable, toToken, toMappedToken, argToToken } from './token/toToken.js';
@@ -1,20 +1,28 @@
1
1
  import { type IContainer, ResolveOneOptions } from '../container/IContainer.js';
2
2
  import { ProviderOptions } from '../provider/IProvider.js';
3
3
  import { type IProxyRegistry } from '../utils/ProxyRegistry.js';
4
- import { type constructor } from '../utils/basic.js';
4
+ import { type constructor, Instance } from '../utils/basic.js';
5
5
  export type WithArgs = {
6
6
  args: unknown[];
7
7
  };
8
8
  export type InjectOptions = Partial<WithArgs>;
9
+ export type InjectorHook = (instance: Instance, scope: IContainer) => void;
9
10
  export interface IInjector {
10
11
  resolve<T>(container: IContainer, value: constructor<T>, options?: ProviderOptions): T;
12
+ onConstructed(...hooks: InjectorHook[]): this;
13
+ }
14
+ export interface IInjectorModule {
15
+ applyTo(injector: IInjector): void;
11
16
  }
12
17
  export interface IInjectFnResolver<T> {
13
18
  resolve(s: IContainer, options?: ResolveOneOptions): T;
14
19
  }
15
20
  export declare abstract class Injector {
16
21
  private readonly proxyRegistry;
22
+ private readonly onConstructedHookList;
17
23
  constructor(proxyRegistry?: IProxyRegistry);
18
24
  resolve<T>(scope: IContainer, Target: constructor<T>, { args, lazy }?: ProviderOptions): T;
25
+ onConstructed(...hooks: InjectorHook[]): this;
26
+ useModule(module: IInjectorModule): this;
19
27
  protected abstract createInstance<T>(scope: IContainer, Target: constructor<T>, options?: InjectOptions): T;
20
28
  }
@@ -1,4 +1,4 @@
1
- import { type DependencyHook, IContainer, Tagged } from '../container/IContainer.js';
1
+ import { IContainer, Tagged } from '../container/IContainer.js';
2
2
  import { InjectOptions } from '../injector/IInjector.js';
3
3
  export type WithLazy = {
4
4
  lazy: boolean;
@@ -14,6 +14,7 @@ export type ScopeAccessRule = (options: ScopeAccessOptions, prev: boolean) => bo
14
14
  export type ArgsFn = (l: IContainer, options?: InjectOptions) => unknown[];
15
15
  export type GetCacheKey = (...args: unknown[]) => string | symbol;
16
16
  export type DecorateFn<Instance = any> = (dep: Instance, scope: IContainer) => Instance;
17
+ export type ProviderHook = (dependency: unknown, scope: IContainer) => void;
17
18
  export interface IProvider<T = any> {
18
19
  resolve(container: IContainer, options: ProviderOptions): T;
19
20
  hasAccess(options: ScopeAccessOptions): boolean;
@@ -25,5 +26,5 @@ export interface IProvider<T = any> {
25
26
  isAutoResolvable(): boolean;
26
27
  singleton(getCacheKey?: GetCacheKey): this;
27
28
  dispose(): void;
28
- onResolve(...hooks: DependencyHook[]): this;
29
+ onResolved(...hooks: ProviderHook[]): this;
29
30
  }
@@ -1,5 +1,5 @@
1
- import { type ArgsFn, type DecorateFn, type GetCacheKey, type IProvider, type ProviderOptions, type ResolveDependency, type ScopeAccessOptions, type ScopeAccessRule } from './IProvider.js';
2
- import type { DependencyHook, DependencyKey, IContainer } from '../container/IContainer.js';
1
+ import { type ArgsFn, type DecorateFn, type GetCacheKey, type IProvider, type ProviderOptions, type ResolveDependency, type ScopeAccessOptions, type ScopeAccessRule, type ProviderHook } from './IProvider.js';
2
+ import type { DependencyKey, IContainer } from '../container/IContainer.js';
3
3
  import { type constructor } from '../utils/basic.js';
4
4
  export declare class Provider<T = any> implements IProvider<T> {
5
5
  private readonly resolveDependency;
@@ -14,7 +14,7 @@ export declare class Provider<T = any> implements IProvider<T> {
14
14
  private cache;
15
15
  private getKey;
16
16
  private isDisposed;
17
- private readonly onResolveHookList;
17
+ private readonly onResolvedHookList;
18
18
  constructor(resolveDependency: ResolveDependency<T>);
19
19
  resolve(scope: IContainer, options: ProviderOptions): T;
20
20
  private resolveDep;
@@ -26,6 +26,6 @@ export declare class Provider<T = any> implements IProvider<T> {
26
26
  addArgsFn(...fns: ArgsFn[]): this;
27
27
  hasAccess(options: ScopeAccessOptions): boolean;
28
28
  singleton(getCacheKey?: GetCacheKey): this;
29
- onResolve(...hooks: DependencyHook[]): this;
29
+ onResolved(...hooks: ProviderHook[]): this;
30
30
  dispose(): void;
31
31
  }
@@ -1,5 +1,5 @@
1
- import { type DependencyHook, type DependencyKey, type IContainer, type IContainerModule } from '../container/IContainer.js';
2
- import type { ArgsFn, DecorateFn, GetCacheKey, IProvider, ScopeAccessRule } from '../provider/IProvider.js';
1
+ import { type DependencyKey, type IContainer, type IContainerModule } from '../container/IContainer.js';
2
+ import type { ArgsFn, DecorateFn, GetCacheKey, IProvider, ProviderHook, ScopeAccessRule } from '../provider/IProvider.js';
3
3
  import { BindToken } from '../token/BindToken.js';
4
4
  import { MapFn } from '../utils/fp.js';
5
5
  import { type constructor } from '../utils/basic.js';
@@ -36,4 +36,4 @@ export declare const lazy: <T>() => ProviderPipe<T>;
36
36
  export declare const autoResolve: <T>() => ProviderPipe<T>;
37
37
  export declare const decorate: (...fns: DecorateFn[]) => ProviderPipe<unknown>;
38
38
  export declare const singleton: <T = unknown>(getCacheKey?: GetCacheKey) => ProviderPipe<T>;
39
- export declare const onResolve: <T = unknown>(...hooks: DependencyHook[]) => ProviderPipe<T>;
39
+ export declare const onResolve: <T = unknown>(...hooks: ProviderHook[]) => ProviderPipe<T>;