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.
- package/README.md +77 -23
- package/cjm/container/Container.js +16 -26
- package/cjm/container/EmptyContainer.js +3 -6
- package/cjm/hooks/onConstruct.js +2 -2
- package/cjm/hooks/onConstructAsync.js +2 -2
- package/cjm/hooks/onContainerDisposed.js +1 -1
- package/cjm/hooks/onResolved.js +20 -0
- package/cjm/hooks/onResolvedAsync.js +24 -0
- package/cjm/hooks/resolveHooks.js +44 -0
- package/cjm/index.js +16 -2
- package/cjm/injector/IInjector.js +12 -0
- package/cjm/provider/Provider.js +6 -6
- package/cjm/registration/IRegistration.js +1 -1
- package/esm/container/Container.js +16 -26
- package/esm/container/EmptyContainer.js +3 -6
- package/esm/hooks/onConstruct.js +2 -2
- package/esm/hooks/onConstructAsync.js +2 -2
- package/esm/hooks/onContainerDisposed.js +1 -1
- package/esm/hooks/onResolved.js +15 -0
- package/esm/hooks/onResolvedAsync.js +19 -0
- package/esm/hooks/resolveHooks.js +35 -0
- package/esm/index.js +4 -1
- package/esm/injector/IInjector.js +12 -0
- package/esm/provider/Provider.js +6 -6
- package/esm/registration/IRegistration.js +2 -2
- package/package.json +1 -1
- package/typings/container/Container.d.ts +5 -8
- package/typings/container/EmptyContainer.d.ts +3 -5
- package/typings/container/IContainer.d.ts +3 -7
- package/typings/hooks/onConstruct.d.ts +3 -3
- package/typings/hooks/onConstructAsync.d.ts +3 -3
- package/typings/hooks/onContainerDisposed.d.ts +0 -1
- package/typings/hooks/onResolved.d.ts +9 -0
- package/typings/hooks/onResolvedAsync.d.ts +12 -0
- package/typings/hooks/resolveHooks.d.ts +12 -0
- package/typings/index.d.ts +6 -3
- package/typings/injector/IInjector.d.ts +9 -1
- package/typings/provider/IProvider.d.ts +3 -2
- package/typings/provider/Provider.d.ts +4 -4
- 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 `
|
|
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
|
-
|
|
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(
|
|
2890
|
-
new
|
|
2891
|
-
|
|
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(
|
|
2925
|
-
new
|
|
2926
|
-
|
|
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
|
-
|
|
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(
|
|
3010
|
-
new
|
|
3011
|
-
|
|
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
|
-
|
|
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
|
|
36
|
-
|
|
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
|
-
.
|
|
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
|
|
107
|
-
|
|
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.
|
|
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
|
-
|
|
147
|
-
this.
|
|
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
|
-
|
|
64
|
-
throw new MethodNotImplementedError_1.MethodNotImplementedError();
|
|
65
|
-
}
|
|
66
|
-
onConstruct(...hooks) {
|
|
63
|
+
onScopeCreated(...hooks) {
|
|
67
64
|
throw new MethodNotImplementedError_1.MethodNotImplementedError();
|
|
68
65
|
}
|
|
69
|
-
|
|
66
|
+
onScopeDisposed(...hooks) {
|
|
70
67
|
throw new MethodNotImplementedError_1.MethodNotImplementedError();
|
|
71
68
|
}
|
|
72
|
-
|
|
69
|
+
onRegistered(...hooks) {
|
|
73
70
|
throw new MethodNotImplementedError_1.MethodNotImplementedError();
|
|
74
71
|
}
|
|
75
72
|
}
|
package/cjm/hooks/onConstruct.js
CHANGED
|
@@ -11,8 +11,8 @@ class OnConstructModule {
|
|
|
11
11
|
constructor(onException) {
|
|
12
12
|
this.onException = onException;
|
|
13
13
|
}
|
|
14
|
-
applyTo(
|
|
15
|
-
|
|
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(
|
|
15
|
-
|
|
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.
|
|
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.
|
|
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;
|
package/cjm/provider/Provider.js
CHANGED
|
@@ -22,7 +22,7 @@ class Provider {
|
|
|
22
22
|
cache = new Map();
|
|
23
23
|
getKey;
|
|
24
24
|
isDisposed = false;
|
|
25
|
-
|
|
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
|
|
47
|
-
|
|
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
|
-
|
|
85
|
-
this.
|
|
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.
|
|
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.
|
|
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
|
-
|
|
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
|
|
33
|
-
|
|
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
|
-
.
|
|
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
|
|
104
|
-
|
|
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.
|
|
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
|
-
|
|
144
|
-
this.
|
|
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
|
-
|
|
61
|
-
throw new MethodNotImplementedError();
|
|
62
|
-
}
|
|
63
|
-
onConstruct(...hooks) {
|
|
60
|
+
onScopeCreated(...hooks) {
|
|
64
61
|
throw new MethodNotImplementedError();
|
|
65
62
|
}
|
|
66
|
-
|
|
63
|
+
onScopeDisposed(...hooks) {
|
|
67
64
|
throw new MethodNotImplementedError();
|
|
68
65
|
}
|
|
69
|
-
|
|
66
|
+
onRegistered(...hooks) {
|
|
70
67
|
throw new MethodNotImplementedError();
|
|
71
68
|
}
|
|
72
69
|
}
|
package/esm/hooks/onConstruct.js
CHANGED
|
@@ -7,8 +7,8 @@ export class OnConstructModule {
|
|
|
7
7
|
constructor(onException) {
|
|
8
8
|
this.onException = onException;
|
|
9
9
|
}
|
|
10
|
-
applyTo(
|
|
11
|
-
|
|
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(
|
|
11
|
-
|
|
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.
|
|
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
|
}
|
package/esm/provider/Provider.js
CHANGED
|
@@ -19,7 +19,7 @@ export class Provider {
|
|
|
19
19
|
cache = new Map();
|
|
20
20
|
getKey;
|
|
21
21
|
isDisposed = false;
|
|
22
|
-
|
|
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
|
|
44
|
-
|
|
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
|
-
|
|
82
|
-
this.
|
|
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.
|
|
94
|
+
this.onResolvedHookList.splice(0, this.onResolvedHookList.length);
|
|
95
95
|
}
|
|
96
96
|
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { isDependencyKey
|
|
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.
|
|
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": "
|
|
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
|
|
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
|
|
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
|
-
|
|
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
|
|
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
|
-
|
|
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
|
|
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
|
-
|
|
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 {
|
|
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
|
|
8
|
+
export declare class OnConstructModule implements IInjectorModule {
|
|
9
9
|
private readonly onException?;
|
|
10
10
|
constructor(onException?: OnExceptionHandler | undefined);
|
|
11
|
-
applyTo(
|
|
11
|
+
applyTo(injector: IInjector): void;
|
|
12
12
|
}
|
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
import { HookType } from './hook.js';
|
|
2
|
-
import type {
|
|
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
|
|
7
|
+
export declare class OnConstructAsyncModule implements IInjectorModule {
|
|
8
8
|
private readonly onException?;
|
|
9
9
|
constructor(onException?: OnExceptionHandler | undefined);
|
|
10
|
-
applyTo(
|
|
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;
|
package/typings/index.d.ts
CHANGED
|
@@ -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
|
|
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 {
|
|
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
|
-
|
|
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 {
|
|
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
|
|
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
|
-
|
|
29
|
+
onResolved(...hooks: ProviderHook[]): this;
|
|
30
30
|
dispose(): void;
|
|
31
31
|
}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { type
|
|
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:
|
|
39
|
+
export declare const onResolve: <T = unknown>(...hooks: ProviderHook[]) => ProviderPipe<T>;
|