ts-ioc-container 59.0.0 → 60.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 +90 -11
- package/cjm/container/AutoResolveModule.js +1 -1
- package/cjm/container/Container.js +9 -16
- package/cjm/container/EmptyContainer.js +3 -7
- package/cjm/hooks/onConstruct.js +4 -4
- package/cjm/hooks/onConstructAsync.js +4 -4
- package/cjm/hooks/onContainerDisposed.js +4 -4
- package/cjm/index.js +7 -6
- package/cjm/provider/Provider.js +12 -2
- package/cjm/registration/IRegistration.js +3 -1
- package/esm/container/AutoResolveModule.js +1 -1
- package/esm/container/Container.js +9 -16
- package/esm/container/EmptyContainer.js +3 -7
- package/esm/hooks/onConstruct.js +2 -2
- package/esm/hooks/onConstructAsync.js +2 -2
- package/esm/hooks/onContainerDisposed.js +2 -2
- package/esm/index.js +4 -4
- package/esm/provider/Provider.js +12 -2
- package/esm/registration/IRegistration.js +2 -1
- package/package.json +1 -1
- package/typings/container/Container.d.ts +4 -6
- package/typings/container/EmptyContainer.d.ts +4 -6
- package/typings/container/IContainer.d.ts +6 -6
- package/typings/hooks/onConstruct.d.ts +1 -3
- package/typings/hooks/onConstructAsync.d.ts +1 -1
- package/typings/hooks/onContainerDisposed.d.ts +1 -1
- package/typings/index.d.ts +5 -5
- package/typings/provider/IProvider.d.ts +2 -1
- package/typings/provider/Provider.d.ts +3 -1
- package/typings/registration/IRegistration.d.ts +2 -1
package/README.md
CHANGED
|
@@ -48,6 +48,7 @@ provider pipelines, aliases, and custom injector strategies.
|
|
|
48
48
|
- [Visibility](#visibility) `visible`
|
|
49
49
|
- [Alias](#alias) `asAlias`
|
|
50
50
|
- [Decorator](#decorator) `decorate`
|
|
51
|
+
- [On resolve](#on-resolve) `onResolve`
|
|
51
52
|
- [Registration](#registration) `@register`
|
|
52
53
|
- [Token](#token) `bindTo`
|
|
53
54
|
- [Scope](#scope) `scope`
|
|
@@ -2376,6 +2377,84 @@ describe('Decorator Pattern', () => {
|
|
|
2376
2377
|
|
|
2377
2378
|
```
|
|
2378
2379
|
|
|
2380
|
+
### On resolve
|
|
2381
|
+
|
|
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
|
+
|
|
2384
|
+
- `provider(onResolve((instance, scope) => tracker.track(instance)))`
|
|
2385
|
+
|
|
2386
|
+
Hooks run after the whole `decorate(...)` chain, so they always observe the fully decorated dependency, and their return value is ignored — `onResolve` can never swap the dependency out. They fire per resolution, which means a `singleton()` provider runs them only on the resolve that fills the cache.
|
|
2387
|
+
|
|
2388
|
+
```typescript
|
|
2389
|
+
import 'reflect-metadata';
|
|
2390
|
+
import { Container, type IContainer, onResolve, register, Registration as R, singleton } from 'ts-ioc-container';
|
|
2391
|
+
|
|
2392
|
+
/**
|
|
2393
|
+
* Observability Domain - onResolve hooks
|
|
2394
|
+
*
|
|
2395
|
+
* `onResolve(...)` attaches side effects to a provider. Every time the provider
|
|
2396
|
+
* hands a dependency back, each hook is called with that dependency and the
|
|
2397
|
+
* resolving scope.
|
|
2398
|
+
*
|
|
2399
|
+
* Unlike `decorate(...)`, a hook cannot replace the dependency - its return
|
|
2400
|
+
* value is ignored. Use `decorate` to change what the caller gets, and
|
|
2401
|
+
* `onResolve` to react to what the caller got: tracking, metrics, registering
|
|
2402
|
+
* the instance with an external bus.
|
|
2403
|
+
*
|
|
2404
|
+
* Hooks always run after the whole `decorate` chain, so they observe the fully
|
|
2405
|
+
* decorated dependency no matter where `onResolve` sits in the pipe list.
|
|
2406
|
+
*/
|
|
2407
|
+
describe('onResolve', () => {
|
|
2408
|
+
it('should observe every resolved dependency without changing it', () => {
|
|
2409
|
+
const resolved: Array<{ name: string; fromRequest: boolean }> = [];
|
|
2410
|
+
|
|
2411
|
+
const track = (dependency: unknown, scope: IContainer) => {
|
|
2412
|
+
resolved.push({ name: (dependency as Connection).name, fromRequest: scope.hasTag('request') });
|
|
2413
|
+
};
|
|
2414
|
+
|
|
2415
|
+
@register(onResolve(track))
|
|
2416
|
+
class Connection {
|
|
2417
|
+
readonly name = 'Connection';
|
|
2418
|
+
}
|
|
2419
|
+
|
|
2420
|
+
const app = new Container({ tags: ['application'] }).addRegistration(R.fromClass(Connection));
|
|
2421
|
+
const request = app.createScope({ tags: ['request'] });
|
|
2422
|
+
|
|
2423
|
+
const connection = request.resolve<Connection>('Connection');
|
|
2424
|
+
|
|
2425
|
+
// The caller still receives the untouched instance
|
|
2426
|
+
expect(connection).toBeInstanceOf(Connection);
|
|
2427
|
+
// ...and the hook saw it, together with the scope it was resolved from
|
|
2428
|
+
expect(resolved).toEqual([{ name: 'Connection', fromRequest: true }]);
|
|
2429
|
+
});
|
|
2430
|
+
|
|
2431
|
+
it('should run once for a singleton and on every resolve otherwise', () => {
|
|
2432
|
+
let poolCount = 0;
|
|
2433
|
+
let sessionCount = 0;
|
|
2434
|
+
|
|
2435
|
+
@register(singleton(), onResolve(() => poolCount++))
|
|
2436
|
+
class ConnectionPool {}
|
|
2437
|
+
|
|
2438
|
+
@register(onResolve(() => sessionCount++))
|
|
2439
|
+
class Session {}
|
|
2440
|
+
|
|
2441
|
+
const app = new Container({ tags: ['application'] })
|
|
2442
|
+
.addRegistration(R.fromClass(ConnectionPool))
|
|
2443
|
+
.addRegistration(R.fromClass(Session));
|
|
2444
|
+
|
|
2445
|
+
app.resolve('ConnectionPool');
|
|
2446
|
+
app.resolve('ConnectionPool');
|
|
2447
|
+
app.resolve('Session');
|
|
2448
|
+
app.resolve('Session');
|
|
2449
|
+
|
|
2450
|
+
// A singleton caches the dependency, so hooks fire on the resolve that filled the cache
|
|
2451
|
+
expect(poolCount).toBe(1);
|
|
2452
|
+
expect(sessionCount).toBe(2);
|
|
2453
|
+
});
|
|
2454
|
+
});
|
|
2455
|
+
|
|
2456
|
+
```
|
|
2457
|
+
|
|
2379
2458
|
## Registration
|
|
2380
2459
|
|
|
2381
2460
|
Registration is provider factory which registers provider in container.
|
|
@@ -2759,7 +2838,7 @@ runs `h1` before `h2`.
|
|
|
2759
2838
|
```typescript
|
|
2760
2839
|
import 'reflect-metadata';
|
|
2761
2840
|
import {
|
|
2762
|
-
|
|
2841
|
+
OnConstructModule,
|
|
2763
2842
|
Container,
|
|
2764
2843
|
type ExecutionContext,
|
|
2765
2844
|
type HookFn,
|
|
@@ -2787,7 +2866,7 @@ describe('onConstruct', function () {
|
|
|
2787
2866
|
}
|
|
2788
2867
|
|
|
2789
2868
|
const container = new Container()
|
|
2790
|
-
.useModule(new
|
|
2869
|
+
.useModule(new OnConstructModule())
|
|
2791
2870
|
.addRegistration(R.fromValue('postgres://localhost:5432').bindTo('ConnectionString'));
|
|
2792
2871
|
|
|
2793
2872
|
const db = container.resolve(DatabaseConnection);
|
|
@@ -2808,7 +2887,7 @@ describe('onConstruct', function () {
|
|
|
2808
2887
|
|
|
2809
2888
|
let captured: { ex: unknown; context: ExecutionContext } | undefined;
|
|
2810
2889
|
const container = new Container().useModule(
|
|
2811
|
-
new
|
|
2890
|
+
new OnConstructModule((ex, context) => {
|
|
2812
2891
|
captured = { ex, context };
|
|
2813
2892
|
}),
|
|
2814
2893
|
);
|
|
@@ -2828,7 +2907,7 @@ describe('onConstruct', function () {
|
|
|
2828
2907
|
init() {}
|
|
2829
2908
|
}
|
|
2830
2909
|
|
|
2831
|
-
const container = new Container().useModule(new
|
|
2910
|
+
const container = new Container().useModule(new OnConstructModule());
|
|
2832
2911
|
|
|
2833
2912
|
expect(() => container.resolve(BrokenService)).toThrow(failure);
|
|
2834
2913
|
});
|
|
@@ -2843,7 +2922,7 @@ describe('onConstruct', function () {
|
|
|
2843
2922
|
|
|
2844
2923
|
let scope: IContainer | undefined;
|
|
2845
2924
|
const container = new Container().useModule(
|
|
2846
|
-
new
|
|
2925
|
+
new OnConstructModule((_ex, context) => {
|
|
2847
2926
|
scope = context.scope;
|
|
2848
2927
|
}),
|
|
2849
2928
|
);
|
|
@@ -2860,13 +2939,13 @@ describe('onConstruct', function () {
|
|
|
2860
2939
|
### OnConstructAsync
|
|
2861
2940
|
|
|
2862
2941
|
`@onConstructAsync` runs promise-returning initialization. Resolution stays
|
|
2863
|
-
synchronous: `
|
|
2942
|
+
synchronous: `OnConstructAsyncModule` starts the hooks when the instance
|
|
2864
2943
|
is created and they settle afterwards, so `resolve` returns before they finish.
|
|
2865
2944
|
|
|
2866
2945
|
```typescript
|
|
2867
2946
|
import 'reflect-metadata';
|
|
2868
2947
|
import {
|
|
2869
|
-
|
|
2948
|
+
OnConstructAsyncModule,
|
|
2870
2949
|
Container,
|
|
2871
2950
|
type ExecutionContext,
|
|
2872
2951
|
type HookFn,
|
|
@@ -2904,7 +2983,7 @@ describe('onConstructAsync', function () {
|
|
|
2904
2983
|
}
|
|
2905
2984
|
|
|
2906
2985
|
const container = new Container()
|
|
2907
|
-
.useModule(new
|
|
2986
|
+
.useModule(new OnConstructAsyncModule())
|
|
2908
2987
|
.addRegistration(R.fromValue('postgres://localhost:5432').bindTo('ConnectionString'));
|
|
2909
2988
|
|
|
2910
2989
|
const db = container.resolve(DatabaseConnection);
|
|
@@ -2928,7 +3007,7 @@ describe('onConstructAsync', function () {
|
|
|
2928
3007
|
|
|
2929
3008
|
let captured: { ex: unknown; context: ExecutionContext } | undefined;
|
|
2930
3009
|
const container = new Container().useModule(
|
|
2931
|
-
new
|
|
3010
|
+
new OnConstructAsyncModule((ex, context) => {
|
|
2932
3011
|
captured = { ex, context };
|
|
2933
3012
|
}),
|
|
2934
3013
|
);
|
|
@@ -2950,7 +3029,7 @@ describe('onConstructAsync', function () {
|
|
|
2950
3029
|
```typescript
|
|
2951
3030
|
import 'reflect-metadata';
|
|
2952
3031
|
import {
|
|
2953
|
-
|
|
3032
|
+
OnDisposeModule,
|
|
2954
3033
|
bindTo,
|
|
2955
3034
|
Container,
|
|
2956
3035
|
type HookFn,
|
|
@@ -2993,7 +3072,7 @@ class Logger {
|
|
|
2993
3072
|
describe('onContainerDisposed', function () {
|
|
2994
3073
|
it('should invoke hooks on all instances when container is disposed', function () {
|
|
2995
3074
|
const container = new Container()
|
|
2996
|
-
.useModule(new
|
|
3075
|
+
.useModule(new OnDisposeModule())
|
|
2997
3076
|
.addRegistration(R.fromClass(Logger))
|
|
2998
3077
|
.addRegistration(R.fromClass(LogsRepo));
|
|
2999
3078
|
|
|
@@ -7,7 +7,7 @@ class AutoResolveModule {
|
|
|
7
7
|
this.options = options;
|
|
8
8
|
}
|
|
9
9
|
applyTo(container) {
|
|
10
|
-
container.
|
|
10
|
+
container.onScopeCreated((scope) => scope.autoResolve(this.options));
|
|
11
11
|
}
|
|
12
12
|
}
|
|
13
13
|
exports.AutoResolveModule = AutoResolveModule;
|
|
@@ -73,9 +73,9 @@ class Container {
|
|
|
73
73
|
createScope({ tags } = {}) {
|
|
74
74
|
this.validateContainer();
|
|
75
75
|
const scope = new Container({ injector: this.injector, parent: this, tags })
|
|
76
|
-
.
|
|
77
|
-
.
|
|
78
|
-
.
|
|
76
|
+
.onConstruct(...this.onConstructHookList)
|
|
77
|
+
.onInstanceDisposed(...this.onDisposeHookList)
|
|
78
|
+
.onScopeCreated(...this.onScopeCreatedHookList);
|
|
79
79
|
for (const registration of this.getRegistrations()) {
|
|
80
80
|
registration.applyTo(scope);
|
|
81
81
|
}
|
|
@@ -97,9 +97,8 @@ class Container {
|
|
|
97
97
|
dispose() {
|
|
98
98
|
this.validateContainer();
|
|
99
99
|
this.isDisposed = true;
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
onDispose(this);
|
|
100
|
+
for (const hook of this.onDisposeHookList) {
|
|
101
|
+
hook(this);
|
|
103
102
|
}
|
|
104
103
|
this.parent.removeScope(this);
|
|
105
104
|
this.parent = new EmptyContainer_1.EmptyContainer();
|
|
@@ -111,6 +110,7 @@ class Container {
|
|
|
111
110
|
this.instances.clear();
|
|
112
111
|
this.registrations = [];
|
|
113
112
|
this.onConstructHookList.length = 0;
|
|
113
|
+
this.onDisposeHookList.length = 0;
|
|
114
114
|
this.onScopeCreatedHookList.length = 0;
|
|
115
115
|
}
|
|
116
116
|
addRegistration(registration) {
|
|
@@ -124,15 +124,15 @@ class Container {
|
|
|
124
124
|
hasRegistration(key) {
|
|
125
125
|
return this.registrations.some((r) => r.getKeyOrFail() === key) || this.parent.hasRegistration(key);
|
|
126
126
|
}
|
|
127
|
-
|
|
127
|
+
onConstruct(...hooks) {
|
|
128
128
|
this.onConstructHookList.push(...hooks);
|
|
129
129
|
return this;
|
|
130
130
|
}
|
|
131
|
-
|
|
131
|
+
onInstanceDisposed(...hooks) {
|
|
132
132
|
this.onDisposeHookList.push(...hooks);
|
|
133
133
|
return this;
|
|
134
134
|
}
|
|
135
|
-
|
|
135
|
+
onScopeCreated(...hooks) {
|
|
136
136
|
this.onScopeCreatedHookList.push(...hooks);
|
|
137
137
|
return this;
|
|
138
138
|
}
|
|
@@ -148,13 +148,6 @@ class Container {
|
|
|
148
148
|
hasInstance(instance) {
|
|
149
149
|
return this.instances.has(instance);
|
|
150
150
|
}
|
|
151
|
-
getScopeByInstanceOrFail(instance) {
|
|
152
|
-
this.validateContainer();
|
|
153
|
-
if (this.hasInstance(instance)) {
|
|
154
|
-
return this;
|
|
155
|
-
}
|
|
156
|
-
return this.parent.getScopeByInstanceOrFail(instance);
|
|
157
|
-
}
|
|
158
151
|
removeScope(child) {
|
|
159
152
|
this.scopes = this.scopes.filter((s) => s !== child);
|
|
160
153
|
}
|
|
@@ -3,7 +3,6 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
3
3
|
exports.EmptyContainer = void 0;
|
|
4
4
|
const MethodNotImplementedError_1 = require("../errors/MethodNotImplementedError");
|
|
5
5
|
const DependencyNotFoundError_1 = require("../errors/DependencyNotFoundError");
|
|
6
|
-
const ContainerNotFoundError_1 = require("../errors/ContainerNotFoundError");
|
|
7
6
|
class EmptyContainer {
|
|
8
7
|
get isDisposed() {
|
|
9
8
|
throw new MethodNotImplementedError_1.MethodNotImplementedError();
|
|
@@ -15,9 +14,6 @@ class EmptyContainer {
|
|
|
15
14
|
getScopes() {
|
|
16
15
|
return [];
|
|
17
16
|
}
|
|
18
|
-
getScopeByInstanceOrFail(instance) {
|
|
19
|
-
throw new ContainerNotFoundError_1.ContainerNotFoundError('Cannot find scope for the given instance');
|
|
20
|
-
}
|
|
21
17
|
getInstances() {
|
|
22
18
|
return [];
|
|
23
19
|
}
|
|
@@ -64,13 +60,13 @@ class EmptyContainer {
|
|
|
64
60
|
resolveOneByAlias(alias, options) {
|
|
65
61
|
throw new DependencyNotFoundError_1.DependencyNotFoundError(`Cannot find alias ${alias.toString()}`);
|
|
66
62
|
}
|
|
67
|
-
|
|
63
|
+
onInstanceDisposed(...hooks) {
|
|
68
64
|
throw new MethodNotImplementedError_1.MethodNotImplementedError();
|
|
69
65
|
}
|
|
70
|
-
|
|
66
|
+
onConstruct(...hooks) {
|
|
71
67
|
throw new MethodNotImplementedError_1.MethodNotImplementedError();
|
|
72
68
|
}
|
|
73
|
-
|
|
69
|
+
onScopeCreated(...hooks) {
|
|
74
70
|
throw new MethodNotImplementedError_1.MethodNotImplementedError();
|
|
75
71
|
}
|
|
76
72
|
}
|
package/cjm/hooks/onConstruct.js
CHANGED
|
@@ -1,18 +1,18 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.
|
|
3
|
+
exports.OnConstructModule = exports.onConstruct = exports.onConstructHooksRunner = void 0;
|
|
4
4
|
const hook_1 = require("./hook");
|
|
5
5
|
const HooksRunner_1 = require("./HooksRunner");
|
|
6
6
|
exports.onConstructHooksRunner = new HooksRunner_1.HooksRunner('onConstruct');
|
|
7
7
|
const onConstruct = (...fns) => (0, hook_1.hook)('onConstruct', (0, hook_1.prependHooks)(...fns));
|
|
8
8
|
exports.onConstruct = onConstruct;
|
|
9
|
-
class
|
|
9
|
+
class OnConstructModule {
|
|
10
10
|
onException;
|
|
11
11
|
constructor(onException) {
|
|
12
12
|
this.onException = onException;
|
|
13
13
|
}
|
|
14
14
|
applyTo(container) {
|
|
15
|
-
container.
|
|
15
|
+
container.onConstruct((instance, scope) => {
|
|
16
16
|
try {
|
|
17
17
|
exports.onConstructHooksRunner.execute(instance, { scope });
|
|
18
18
|
}
|
|
@@ -25,4 +25,4 @@ class AddOnConstructHookModule {
|
|
|
25
25
|
});
|
|
26
26
|
}
|
|
27
27
|
}
|
|
28
|
-
exports.
|
|
28
|
+
exports.OnConstructModule = OnConstructModule;
|
|
@@ -1,18 +1,18 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.
|
|
3
|
+
exports.OnConstructAsyncModule = exports.onConstructAsync = exports.onConstructAsyncHooksRunner = void 0;
|
|
4
4
|
const hook_1 = require("./hook");
|
|
5
5
|
const HooksRunner_1 = require("./HooksRunner");
|
|
6
6
|
exports.onConstructAsyncHooksRunner = new HooksRunner_1.HooksRunner('onConstructAsync');
|
|
7
7
|
const onConstructAsync = (...fns) => (0, hook_1.hook)('onConstructAsync', (0, hook_1.prependHooks)(...fns));
|
|
8
8
|
exports.onConstructAsync = onConstructAsync;
|
|
9
|
-
class
|
|
9
|
+
class OnConstructAsyncModule {
|
|
10
10
|
onException;
|
|
11
11
|
constructor(onException) {
|
|
12
12
|
this.onException = onException;
|
|
13
13
|
}
|
|
14
14
|
applyTo(container) {
|
|
15
|
-
container.
|
|
15
|
+
container.onConstruct((instance, scope) => {
|
|
16
16
|
if (!exports.onConstructAsyncHooksRunner.hasHooks(instance)) {
|
|
17
17
|
return;
|
|
18
18
|
}
|
|
@@ -25,4 +25,4 @@ class AddOnConstructAsyncHookModule {
|
|
|
25
25
|
});
|
|
26
26
|
}
|
|
27
27
|
}
|
|
28
|
-
exports.
|
|
28
|
+
exports.OnConstructAsyncModule = OnConstructAsyncModule;
|
|
@@ -1,18 +1,18 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.
|
|
3
|
+
exports.OnDisposeModule = exports.onContainerDisposed = exports.onContainerDisposedHooksRunner = void 0;
|
|
4
4
|
const hook_1 = require("./hook");
|
|
5
5
|
const HooksRunner_1 = require("./HooksRunner");
|
|
6
6
|
exports.onContainerDisposedHooksRunner = new HooksRunner_1.HooksRunner('onContainerDisposed');
|
|
7
7
|
const onContainerDisposed = (...fns) => (0, hook_1.hook)('onContainerDisposed', (0, hook_1.prependHooks)(...fns));
|
|
8
8
|
exports.onContainerDisposed = onContainerDisposed;
|
|
9
|
-
class
|
|
9
|
+
class OnDisposeModule {
|
|
10
10
|
applyTo(container) {
|
|
11
|
-
container.
|
|
11
|
+
container.onInstanceDisposed((scope) => {
|
|
12
12
|
for (const instance of scope.getInstances()) {
|
|
13
13
|
exports.onContainerDisposedHooksRunner.execute(instance, { scope });
|
|
14
14
|
}
|
|
15
15
|
});
|
|
16
16
|
}
|
|
17
17
|
}
|
|
18
|
-
exports.
|
|
18
|
+
exports.OnDisposeModule = OnDisposeModule;
|
package/cjm/index.js
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.
|
|
4
|
-
exports.
|
|
5
|
-
exports.resolveConstructor = exports.Is = exports.ProxyRegistry = void 0;
|
|
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.select = 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.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.resolveConstructor = exports.Is = exports.ProxyRegistry = exports.pipe = 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");
|
|
@@ -42,6 +42,7 @@ Object.defineProperty(exports, "singleton", { enumerable: true, get: function ()
|
|
|
42
42
|
Object.defineProperty(exports, "decorate", { enumerable: true, get: function () { return IRegistration_1.decorate; } });
|
|
43
43
|
Object.defineProperty(exports, "appendArgs", { enumerable: true, get: function () { return IRegistration_1.appendArgs; } });
|
|
44
44
|
Object.defineProperty(exports, "appendArgsFn", { enumerable: true, get: function () { return IRegistration_1.appendArgsFn; } });
|
|
45
|
+
Object.defineProperty(exports, "onResolve", { enumerable: true, get: function () { return IRegistration_1.onResolve; } });
|
|
45
46
|
var Registration_1 = require("./registration/Registration");
|
|
46
47
|
Object.defineProperty(exports, "Registration", { enumerable: true, get: function () { return Registration_1.Registration; } });
|
|
47
48
|
var ContainerError_1 = require("./errors/ContainerError");
|
|
@@ -81,15 +82,15 @@ Object.defineProperty(exports, "injectProp", { enumerable: true, get: function (
|
|
|
81
82
|
var onConstruct_1 = require("./hooks/onConstruct");
|
|
82
83
|
Object.defineProperty(exports, "onConstructHooksRunner", { enumerable: true, get: function () { return onConstruct_1.onConstructHooksRunner; } });
|
|
83
84
|
Object.defineProperty(exports, "onConstruct", { enumerable: true, get: function () { return onConstruct_1.onConstruct; } });
|
|
84
|
-
Object.defineProperty(exports, "
|
|
85
|
+
Object.defineProperty(exports, "OnConstructModule", { enumerable: true, get: function () { return onConstruct_1.OnConstructModule; } });
|
|
85
86
|
var onConstructAsync_1 = require("./hooks/onConstructAsync");
|
|
86
87
|
Object.defineProperty(exports, "onConstructAsyncHooksRunner", { enumerable: true, get: function () { return onConstructAsync_1.onConstructAsyncHooksRunner; } });
|
|
87
88
|
Object.defineProperty(exports, "onConstructAsync", { enumerable: true, get: function () { return onConstructAsync_1.onConstructAsync; } });
|
|
88
|
-
Object.defineProperty(exports, "
|
|
89
|
+
Object.defineProperty(exports, "OnConstructAsyncModule", { enumerable: true, get: function () { return onConstructAsync_1.OnConstructAsyncModule; } });
|
|
89
90
|
var onContainerDisposed_1 = require("./hooks/onContainerDisposed");
|
|
90
91
|
Object.defineProperty(exports, "onContainerDisposedHooksRunner", { enumerable: true, get: function () { return onContainerDisposed_1.onContainerDisposedHooksRunner; } });
|
|
91
92
|
Object.defineProperty(exports, "onContainerDisposed", { enumerable: true, get: function () { return onContainerDisposed_1.onContainerDisposed; } });
|
|
92
|
-
Object.defineProperty(exports, "
|
|
93
|
+
Object.defineProperty(exports, "OnDisposeModule", { enumerable: true, get: function () { return onContainerDisposed_1.OnDisposeModule; } });
|
|
93
94
|
var HooksRunner_1 = require("./hooks/HooksRunner");
|
|
94
95
|
Object.defineProperty(exports, "HooksRunner", { enumerable: true, get: function () { return HooksRunner_1.HooksRunner; } });
|
|
95
96
|
var InjectionToken_1 = require("./token/InjectionToken");
|
package/cjm/provider/Provider.js
CHANGED
|
@@ -22,6 +22,7 @@ class Provider {
|
|
|
22
22
|
cache = new Map();
|
|
23
23
|
getKey;
|
|
24
24
|
isDisposed = false;
|
|
25
|
+
onResolveHookList = [];
|
|
25
26
|
constructor(resolveDependency) {
|
|
26
27
|
this.resolveDependency = resolveDependency;
|
|
27
28
|
}
|
|
@@ -37,11 +38,15 @@ class Provider {
|
|
|
37
38
|
return this.cache.get(key);
|
|
38
39
|
}
|
|
39
40
|
resolveDep(scope, { args = [], lazy } = {}) {
|
|
40
|
-
|
|
41
|
+
let dependency = this.resolveDependency(scope, {
|
|
41
42
|
args: this.argsFnList.reduce((acc, current) => current(scope, { args: acc }), args),
|
|
42
43
|
lazy: lazy ?? this.isLazy,
|
|
43
44
|
});
|
|
44
|
-
|
|
45
|
+
dependency = this.mappers.reduce((acc, current) => current(acc, scope), dependency);
|
|
46
|
+
for (const onResolve of this.onResolveHookList) {
|
|
47
|
+
onResolve(dependency, scope);
|
|
48
|
+
}
|
|
49
|
+
return dependency;
|
|
45
50
|
}
|
|
46
51
|
map(...mappers) {
|
|
47
52
|
this.mappers.push(...mappers);
|
|
@@ -76,6 +81,10 @@ class Provider {
|
|
|
76
81
|
this.getKey = getCacheKey;
|
|
77
82
|
return this;
|
|
78
83
|
}
|
|
84
|
+
onResolve(...hooks) {
|
|
85
|
+
this.onResolveHookList.push(...hooks);
|
|
86
|
+
return this;
|
|
87
|
+
}
|
|
79
88
|
dispose() {
|
|
80
89
|
ProviderDisposedError_1.ProviderDisposedError.assert(!this.isDisposed, 'Provider is already disposed');
|
|
81
90
|
this.isDisposed = true;
|
|
@@ -85,6 +94,7 @@ class Provider {
|
|
|
85
94
|
this.accessRules.splice(0, this.accessRules.length);
|
|
86
95
|
this.mappers.splice(0, this.mappers.length);
|
|
87
96
|
this.argsFnList.splice(0, this.argsFnList.length);
|
|
97
|
+
this.onResolveHookList.splice(0, this.onResolveHookList.length);
|
|
88
98
|
}
|
|
89
99
|
}
|
|
90
100
|
exports.Provider = Provider;
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.singleton = exports.decorate = exports.autoResolve = exports.lazy = exports.scopeAccess = exports.appendArgsFn = exports.appendArgs = exports.scope = exports.bindTo = exports.register = exports.getTransformers = exports.toRegistrationFn = exports.toProviderFn = exports.toBindToken = exports.registerPipe = exports.isProviderPipe = void 0;
|
|
3
|
+
exports.onResolve = exports.singleton = exports.decorate = exports.autoResolve = exports.lazy = exports.scopeAccess = exports.appendArgsFn = exports.appendArgs = exports.scope = exports.bindTo = exports.register = exports.getTransformers = exports.toRegistrationFn = exports.toProviderFn = exports.toBindToken = exports.registerPipe = exports.isProviderPipe = void 0;
|
|
4
4
|
const IContainer_1 = require("../container/IContainer");
|
|
5
5
|
const SingleToken_1 = require("../token/SingleToken");
|
|
6
6
|
const class_1 = require("../metadata/class");
|
|
@@ -54,3 +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));
|
|
58
|
+
exports.onResolve = onResolve;
|
|
@@ -70,9 +70,9 @@ export class Container {
|
|
|
70
70
|
createScope({ tags } = {}) {
|
|
71
71
|
this.validateContainer();
|
|
72
72
|
const scope = new Container({ injector: this.injector, parent: this, tags })
|
|
73
|
-
.
|
|
74
|
-
.
|
|
75
|
-
.
|
|
73
|
+
.onConstruct(...this.onConstructHookList)
|
|
74
|
+
.onInstanceDisposed(...this.onDisposeHookList)
|
|
75
|
+
.onScopeCreated(...this.onScopeCreatedHookList);
|
|
76
76
|
for (const registration of this.getRegistrations()) {
|
|
77
77
|
registration.applyTo(scope);
|
|
78
78
|
}
|
|
@@ -94,9 +94,8 @@ export class Container {
|
|
|
94
94
|
dispose() {
|
|
95
95
|
this.validateContainer();
|
|
96
96
|
this.isDisposed = true;
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
onDispose(this);
|
|
97
|
+
for (const hook of this.onDisposeHookList) {
|
|
98
|
+
hook(this);
|
|
100
99
|
}
|
|
101
100
|
this.parent.removeScope(this);
|
|
102
101
|
this.parent = new EmptyContainer();
|
|
@@ -108,6 +107,7 @@ export class Container {
|
|
|
108
107
|
this.instances.clear();
|
|
109
108
|
this.registrations = [];
|
|
110
109
|
this.onConstructHookList.length = 0;
|
|
110
|
+
this.onDisposeHookList.length = 0;
|
|
111
111
|
this.onScopeCreatedHookList.length = 0;
|
|
112
112
|
}
|
|
113
113
|
addRegistration(registration) {
|
|
@@ -121,15 +121,15 @@ export class Container {
|
|
|
121
121
|
hasRegistration(key) {
|
|
122
122
|
return this.registrations.some((r) => r.getKeyOrFail() === key) || this.parent.hasRegistration(key);
|
|
123
123
|
}
|
|
124
|
-
|
|
124
|
+
onConstruct(...hooks) {
|
|
125
125
|
this.onConstructHookList.push(...hooks);
|
|
126
126
|
return this;
|
|
127
127
|
}
|
|
128
|
-
|
|
128
|
+
onInstanceDisposed(...hooks) {
|
|
129
129
|
this.onDisposeHookList.push(...hooks);
|
|
130
130
|
return this;
|
|
131
131
|
}
|
|
132
|
-
|
|
132
|
+
onScopeCreated(...hooks) {
|
|
133
133
|
this.onScopeCreatedHookList.push(...hooks);
|
|
134
134
|
return this;
|
|
135
135
|
}
|
|
@@ -145,13 +145,6 @@ export class Container {
|
|
|
145
145
|
hasInstance(instance) {
|
|
146
146
|
return this.instances.has(instance);
|
|
147
147
|
}
|
|
148
|
-
getScopeByInstanceOrFail(instance) {
|
|
149
|
-
this.validateContainer();
|
|
150
|
-
if (this.hasInstance(instance)) {
|
|
151
|
-
return this;
|
|
152
|
-
}
|
|
153
|
-
return this.parent.getScopeByInstanceOrFail(instance);
|
|
154
|
-
}
|
|
155
148
|
removeScope(child) {
|
|
156
149
|
this.scopes = this.scopes.filter((s) => s !== child);
|
|
157
150
|
}
|
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import { MethodNotImplementedError } from '../errors/MethodNotImplementedError.js';
|
|
2
2
|
import { DependencyNotFoundError } from '../errors/DependencyNotFoundError.js';
|
|
3
|
-
import { ContainerNotFoundError } from '../errors/ContainerNotFoundError.js';
|
|
4
3
|
export class EmptyContainer {
|
|
5
4
|
get isDisposed() {
|
|
6
5
|
throw new MethodNotImplementedError();
|
|
@@ -12,9 +11,6 @@ export class EmptyContainer {
|
|
|
12
11
|
getScopes() {
|
|
13
12
|
return [];
|
|
14
13
|
}
|
|
15
|
-
getScopeByInstanceOrFail(instance) {
|
|
16
|
-
throw new ContainerNotFoundError('Cannot find scope for the given instance');
|
|
17
|
-
}
|
|
18
14
|
getInstances() {
|
|
19
15
|
return [];
|
|
20
16
|
}
|
|
@@ -61,13 +57,13 @@ export class EmptyContainer {
|
|
|
61
57
|
resolveOneByAlias(alias, options) {
|
|
62
58
|
throw new DependencyNotFoundError(`Cannot find alias ${alias.toString()}`);
|
|
63
59
|
}
|
|
64
|
-
|
|
60
|
+
onInstanceDisposed(...hooks) {
|
|
65
61
|
throw new MethodNotImplementedError();
|
|
66
62
|
}
|
|
67
|
-
|
|
63
|
+
onConstruct(...hooks) {
|
|
68
64
|
throw new MethodNotImplementedError();
|
|
69
65
|
}
|
|
70
|
-
|
|
66
|
+
onScopeCreated(...hooks) {
|
|
71
67
|
throw new MethodNotImplementedError();
|
|
72
68
|
}
|
|
73
69
|
}
|
package/esm/hooks/onConstruct.js
CHANGED
|
@@ -2,13 +2,13 @@ import { hook, prependHooks } from './hook.js';
|
|
|
2
2
|
import { HooksRunner } from './HooksRunner.js';
|
|
3
3
|
export const onConstructHooksRunner = new HooksRunner('onConstruct');
|
|
4
4
|
export const onConstruct = (...fns) => hook('onConstruct', prependHooks(...fns));
|
|
5
|
-
export class
|
|
5
|
+
export class OnConstructModule {
|
|
6
6
|
onException;
|
|
7
7
|
constructor(onException) {
|
|
8
8
|
this.onException = onException;
|
|
9
9
|
}
|
|
10
10
|
applyTo(container) {
|
|
11
|
-
container.
|
|
11
|
+
container.onConstruct((instance, scope) => {
|
|
12
12
|
try {
|
|
13
13
|
onConstructHooksRunner.execute(instance, { scope });
|
|
14
14
|
}
|
|
@@ -2,13 +2,13 @@ import { hook, prependHooks } from './hook.js';
|
|
|
2
2
|
import { HooksRunner } from './HooksRunner.js';
|
|
3
3
|
export const onConstructAsyncHooksRunner = new HooksRunner('onConstructAsync');
|
|
4
4
|
export const onConstructAsync = (...fns) => hook('onConstructAsync', prependHooks(...fns));
|
|
5
|
-
export class
|
|
5
|
+
export class OnConstructAsyncModule {
|
|
6
6
|
onException;
|
|
7
7
|
constructor(onException) {
|
|
8
8
|
this.onException = onException;
|
|
9
9
|
}
|
|
10
10
|
applyTo(container) {
|
|
11
|
-
container.
|
|
11
|
+
container.onConstruct((instance, scope) => {
|
|
12
12
|
if (!onConstructAsyncHooksRunner.hasHooks(instance)) {
|
|
13
13
|
return;
|
|
14
14
|
}
|
|
@@ -2,9 +2,9 @@ import { hook, prependHooks } from './hook.js';
|
|
|
2
2
|
import { HooksRunner } from './HooksRunner.js';
|
|
3
3
|
export const onContainerDisposedHooksRunner = new HooksRunner('onContainerDisposed');
|
|
4
4
|
export const onContainerDisposed = (...fns) => hook('onContainerDisposed', prependHooks(...fns));
|
|
5
|
-
export class
|
|
5
|
+
export class OnDisposeModule {
|
|
6
6
|
applyTo(container) {
|
|
7
|
-
container.
|
|
7
|
+
container.onInstanceDisposed((scope) => {
|
|
8
8
|
for (const instance of scope.getInstances()) {
|
|
9
9
|
onContainerDisposedHooksRunner.execute(instance, { scope });
|
|
10
10
|
}
|
package/esm/index.js
CHANGED
|
@@ -7,7 +7,7 @@ export { MetadataInjector, inject, arg, args, argsFn, resolveArgs } from './inje
|
|
|
7
7
|
export { SimpleInjector } from './injector/SimpleInjector.js';
|
|
8
8
|
export { ProxyInjector } from './injector/ProxyInjector.js';
|
|
9
9
|
export { Provider } from './provider/Provider.js';
|
|
10
|
-
export { isProviderPipe, registerPipe, toBindToken, toProviderFn, toRegistrationFn, register, bindTo, scope, scopeAccess, lazy, autoResolve, singleton, decorate, appendArgs, appendArgsFn, } from './registration/IRegistration.js';
|
|
10
|
+
export { isProviderPipe, registerPipe, toBindToken, toProviderFn, toRegistrationFn, register, bindTo, scope, scopeAccess, lazy, autoResolve, singleton, decorate, appendArgs, appendArgsFn, onResolve, } from './registration/IRegistration.js';
|
|
11
11
|
export { Registration } from './registration/Registration.js';
|
|
12
12
|
export { ContainerError } from './errors/ContainerError.js';
|
|
13
13
|
export { DependencyNotFoundError } from './errors/DependencyNotFoundError.js';
|
|
@@ -22,9 +22,9 @@ export { UnsupportedTokenTypeError } from './errors/UnsupportedTokenTypeError.js
|
|
|
22
22
|
export { getHooks, hook, hasHooks, appendHooks, prependHooks, append, prepend, } from './hooks/hook.js';
|
|
23
23
|
export { HookContext, createHookContextFactory, createHookContext } from './hooks/HookContext.js';
|
|
24
24
|
export { injectProp } from './hooks/injectProp.js';
|
|
25
|
-
export { onConstructHooksRunner, onConstruct,
|
|
26
|
-
export { onConstructAsyncHooksRunner, onConstructAsync,
|
|
27
|
-
export { onContainerDisposedHooksRunner, onContainerDisposed,
|
|
25
|
+
export { onConstructHooksRunner, onConstruct, OnConstructModule } from './hooks/onConstruct.js';
|
|
26
|
+
export { onConstructAsyncHooksRunner, onConstructAsync, OnConstructAsyncModule } from './hooks/onConstructAsync.js';
|
|
27
|
+
export { onContainerDisposedHooksRunner, onContainerDisposed, OnDisposeModule } from './hooks/onContainerDisposed.js';
|
|
28
28
|
export { HooksRunner } from './hooks/HooksRunner.js';
|
|
29
29
|
export { InjectionToken } from './token/InjectionToken.js';
|
|
30
30
|
export { toToken, toMappedToken, argToToken } from './token/toToken.js';
|
package/esm/provider/Provider.js
CHANGED
|
@@ -19,6 +19,7 @@ export class Provider {
|
|
|
19
19
|
cache = new Map();
|
|
20
20
|
getKey;
|
|
21
21
|
isDisposed = false;
|
|
22
|
+
onResolveHookList = [];
|
|
22
23
|
constructor(resolveDependency) {
|
|
23
24
|
this.resolveDependency = resolveDependency;
|
|
24
25
|
}
|
|
@@ -34,11 +35,15 @@ export class Provider {
|
|
|
34
35
|
return this.cache.get(key);
|
|
35
36
|
}
|
|
36
37
|
resolveDep(scope, { args = [], lazy } = {}) {
|
|
37
|
-
|
|
38
|
+
let dependency = this.resolveDependency(scope, {
|
|
38
39
|
args: this.argsFnList.reduce((acc, current) => current(scope, { args: acc }), args),
|
|
39
40
|
lazy: lazy ?? this.isLazy,
|
|
40
41
|
});
|
|
41
|
-
|
|
42
|
+
dependency = this.mappers.reduce((acc, current) => current(acc, scope), dependency);
|
|
43
|
+
for (const onResolve of this.onResolveHookList) {
|
|
44
|
+
onResolve(dependency, scope);
|
|
45
|
+
}
|
|
46
|
+
return dependency;
|
|
42
47
|
}
|
|
43
48
|
map(...mappers) {
|
|
44
49
|
this.mappers.push(...mappers);
|
|
@@ -73,6 +78,10 @@ export class Provider {
|
|
|
73
78
|
this.getKey = getCacheKey;
|
|
74
79
|
return this;
|
|
75
80
|
}
|
|
81
|
+
onResolve(...hooks) {
|
|
82
|
+
this.onResolveHookList.push(...hooks);
|
|
83
|
+
return this;
|
|
84
|
+
}
|
|
76
85
|
dispose() {
|
|
77
86
|
ProviderDisposedError.assert(!this.isDisposed, 'Provider is already disposed');
|
|
78
87
|
this.isDisposed = true;
|
|
@@ -82,5 +91,6 @@ export class Provider {
|
|
|
82
91
|
this.accessRules.splice(0, this.accessRules.length);
|
|
83
92
|
this.mappers.splice(0, this.mappers.length);
|
|
84
93
|
this.argsFnList.splice(0, this.argsFnList.length);
|
|
94
|
+
this.onResolveHookList.splice(0, this.onResolveHookList.length);
|
|
85
95
|
}
|
|
86
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,3 +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));
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "ts-ioc-container",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "60.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 InstanceHook, 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 { OnConstructHook } from '../hooks/onConstruct.js';
|
|
6
5
|
import { OnDisposeHook } from '../hooks/onContainerDisposed.js';
|
|
7
6
|
import { constructor, Instance } from '../utils/basic.js';
|
|
8
7
|
export declare class Container implements IContainer {
|
|
@@ -33,13 +32,12 @@ export declare class Container implements IContainer {
|
|
|
33
32
|
addRegistration(registration: IRegistration): this;
|
|
34
33
|
getRegistrations(): IRegistration[];
|
|
35
34
|
hasRegistration(key: DependencyKey): boolean;
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
35
|
+
onConstruct(...hooks: InstanceHook[]): this;
|
|
36
|
+
onInstanceDisposed(...hooks: OnDisposeHook[]): this;
|
|
37
|
+
onScopeCreated(...hooks: ScopeHook[]): this;
|
|
39
38
|
addInstance(instance: Instance): void;
|
|
40
39
|
getScopes(): IContainer[];
|
|
41
40
|
hasInstance(instance: Instance): boolean;
|
|
42
|
-
getScopeByInstanceOrFail(instance: Instance): IContainer;
|
|
43
41
|
removeScope(child: IContainer): void;
|
|
44
42
|
useModule(module: IContainerModule): this;
|
|
45
43
|
getParent(): IContainer;
|
|
@@ -1,15 +1,13 @@
|
|
|
1
|
-
import { type AutoResolveOptions, type DependencyKey, type IContainer, type IContainerModule, type
|
|
1
|
+
import { type AutoResolveOptions, type DependencyKey, type IContainer, type IContainerModule, type ScopeHook, type ResolveManyOptions, type ResolveOneOptions, type Tag, type InstanceHook } from './IContainer.js';
|
|
2
2
|
import { type IProvider } from '../provider/IProvider.js';
|
|
3
3
|
import { type IRegistration } from '../registration/IRegistration.js';
|
|
4
4
|
import { OnDisposeHook } from '../hooks/onContainerDisposed.js';
|
|
5
|
-
import { OnConstructHook } from '../hooks/onConstruct.js';
|
|
6
5
|
import { type constructor, type Instance } from '../utils/basic.js';
|
|
7
6
|
export declare class EmptyContainer implements IContainer {
|
|
8
7
|
get isDisposed(): boolean;
|
|
9
8
|
addInstance(instance: Instance): void;
|
|
10
9
|
getParent(): undefined;
|
|
11
10
|
getScopes(): never[];
|
|
12
|
-
getScopeByInstanceOrFail(instance: Instance): IContainer;
|
|
13
11
|
getInstances(): never[];
|
|
14
12
|
hasInstance(instance: Instance): boolean;
|
|
15
13
|
createScope(): IContainer;
|
|
@@ -26,7 +24,7 @@ export declare class EmptyContainer implements IContainer {
|
|
|
26
24
|
resolve<T>(key: constructor<T> | DependencyKey, options?: ResolveOneOptions): T;
|
|
27
25
|
resolveByAlias<T>(alias: DependencyKey, options?: ResolveManyOptions): T[];
|
|
28
26
|
resolveOneByAlias<T>(alias: DependencyKey, options?: ResolveOneOptions): T;
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
27
|
+
onInstanceDisposed(...hooks: OnDisposeHook[]): this;
|
|
28
|
+
onConstruct(...hooks: InstanceHook[]): this;
|
|
29
|
+
onScopeCreated(...hooks: ScopeHook[]): this;
|
|
32
30
|
}
|
|
@@ -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 { OnConstructHook } from '../hooks/onConstruct.js';
|
|
4
3
|
import { OnDisposeHook } from '../hooks/onContainerDisposed.js';
|
|
5
4
|
import { type WithArgs } from '../injector/IInjector.js';
|
|
6
5
|
import { type constructor, Instance } from '../utils/basic.js';
|
|
@@ -30,15 +29,17 @@ export interface IContainerModule {
|
|
|
30
29
|
}
|
|
31
30
|
export type CreateScopeOptions = Partial<WithTags>;
|
|
32
31
|
export type AutoResolveOptions = Partial<WithArgs>;
|
|
33
|
-
export type OnScopeCreatedHook = (scope: IContainer) => void;
|
|
34
32
|
export type RegisterOptions = {
|
|
35
33
|
aliases?: DependencyKey[];
|
|
36
34
|
};
|
|
35
|
+
export type ScopeHook = (scope: IContainer) => void;
|
|
36
|
+
export type InstanceHook = (instance: Instance, scope: IContainer) => void;
|
|
37
|
+
export type DependencyHook = (dependency: unknown, scope: IContainer) => void;
|
|
37
38
|
export interface IContainer extends Tagged {
|
|
38
39
|
readonly isDisposed: boolean;
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
40
|
+
onConstruct(...hooks: InstanceHook[]): this;
|
|
41
|
+
onInstanceDisposed(...hooks: OnDisposeHook[]): this;
|
|
42
|
+
onScopeCreated(...hooks: ScopeHook[]): this;
|
|
42
43
|
register(key: DependencyKey, value: IProvider, options?: RegisterOptions): this;
|
|
43
44
|
addRegistration(registration: IRegistration): this;
|
|
44
45
|
getRegistrations(): IRegistration[];
|
|
@@ -49,7 +50,6 @@ export interface IContainer extends Tagged {
|
|
|
49
50
|
createScope(options?: CreateScopeOptions): IContainer;
|
|
50
51
|
autoResolve(options?: AutoResolveOptions): this;
|
|
51
52
|
getScopes(): IContainer[];
|
|
52
|
-
getScopeByInstanceOrFail(instance: Instance): IContainer;
|
|
53
53
|
removeScope(child: IContainer): void;
|
|
54
54
|
useModule(module: IContainerModule): this;
|
|
55
55
|
getParent(): IContainer | undefined;
|
|
@@ -1,13 +1,11 @@
|
|
|
1
1
|
import { HookType } from './hook.js';
|
|
2
2
|
import type { IContainer, IContainerModule } from '../container/IContainer.js';
|
|
3
|
-
import { Instance } from '../utils/basic.js';
|
|
4
3
|
import { HooksRunner } from './HooksRunner.js';
|
|
5
4
|
import type { ExecutionContext } from '../ExecutionContext.js';
|
|
6
5
|
export declare const onConstructHooksRunner: HooksRunner;
|
|
7
6
|
export declare const onConstruct: (...fns: HookType[]) => (target: object, propertyKey: string | symbol) => void;
|
|
8
|
-
export type OnConstructHook = (instance: Instance, scope: IContainer) => void;
|
|
9
7
|
export type OnExceptionHandler = (ex: unknown, context: ExecutionContext) => void;
|
|
10
|
-
export declare class
|
|
8
|
+
export declare class OnConstructModule implements IContainerModule {
|
|
11
9
|
private readonly onException?;
|
|
12
10
|
constructor(onException?: OnExceptionHandler | undefined);
|
|
13
11
|
applyTo(container: IContainer): void;
|
|
@@ -4,7 +4,7 @@ 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
|
|
7
|
+
export declare class OnConstructAsyncModule implements IContainerModule {
|
|
8
8
|
private readonly onException?;
|
|
9
9
|
constructor(onException?: OnExceptionHandler | undefined);
|
|
10
10
|
applyTo(container: IContainer): void;
|
|
@@ -4,6 +4,6 @@ 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
6
|
export type OnDisposeHook = (scope: IContainer) => void;
|
|
7
|
-
export declare class
|
|
7
|
+
export declare class OnDisposeModule implements IContainerModule {
|
|
8
8
|
applyTo(container: IContainer): void;
|
|
9
9
|
}
|
package/typings/index.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
export { type IContainer, type Resolvable, type IContainerModule, type DependencyKey, type Tag, type Tagged, type ResolveOneOptions, type ResolveManyOptions, type
|
|
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 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';
|
|
@@ -8,7 +8,7 @@ export { SimpleInjector } from './injector/SimpleInjector.js';
|
|
|
8
8
|
export { ProxyInjector } from './injector/ProxyInjector.js';
|
|
9
9
|
export { type ResolveDependency, type IProvider, type DecorateFn, type ArgsFn, type ProviderOptions, type GetCacheKey, type ScopeAccessOptions, type ScopeAccessRule, } from './provider/IProvider.js';
|
|
10
10
|
export { Provider } from './provider/Provider.js';
|
|
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, } from './registration/IRegistration.js';
|
|
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';
|
|
13
13
|
export { ContainerError } from './errors/ContainerError.js';
|
|
14
14
|
export { DependencyNotFoundError } from './errors/DependencyNotFoundError.js';
|
|
@@ -23,9 +23,9 @@ export { UnsupportedTokenTypeError } from './errors/UnsupportedTokenTypeError.js
|
|
|
23
23
|
export { getHooks, hook, hasHooks, appendHooks, prependHooks, append, prepend, type HookFn, type HookClass, type HookType, type MapHooksFn, type InjectFn, type HooksOfClass, } from './hooks/hook.js';
|
|
24
24
|
export { HookContext, createHookContextFactory, createHookContext, type IHookContext } from './hooks/HookContext.js';
|
|
25
25
|
export { injectProp } from './hooks/injectProp.js';
|
|
26
|
-
export { onConstructHooksRunner, onConstruct,
|
|
27
|
-
export { onConstructAsyncHooksRunner, onConstructAsync,
|
|
28
|
-
export { onContainerDisposedHooksRunner, onContainerDisposed,
|
|
26
|
+
export { onConstructHooksRunner, onConstruct, OnConstructModule, type OnExceptionHandler } from './hooks/onConstruct.js';
|
|
27
|
+
export { onConstructAsyncHooksRunner, onConstructAsync, OnConstructAsyncModule } from './hooks/onConstructAsync.js';
|
|
28
|
+
export { onContainerDisposedHooksRunner, onContainerDisposed, OnDisposeModule } from './hooks/onContainerDisposed.js';
|
|
29
29
|
export { HooksRunner, type HooksRunnerContext, type MapHookContext } from './hooks/HooksRunner.js';
|
|
30
30
|
export { InjectionToken } from './token/InjectionToken.js';
|
|
31
31
|
export { type Injectable, toToken, toMappedToken, argToToken } from './token/toToken.js';
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { IContainer, Tagged } from '../container/IContainer.js';
|
|
1
|
+
import { type DependencyHook, IContainer, Tagged } from '../container/IContainer.js';
|
|
2
2
|
import { InjectOptions } from '../injector/IInjector.js';
|
|
3
3
|
export type WithLazy = {
|
|
4
4
|
lazy: boolean;
|
|
@@ -25,4 +25,5 @@ export interface IProvider<T = any> {
|
|
|
25
25
|
isAutoResolvable(): boolean;
|
|
26
26
|
singleton(getCacheKey?: GetCacheKey): this;
|
|
27
27
|
dispose(): void;
|
|
28
|
+
onResolve(...hooks: DependencyHook[]): this;
|
|
28
29
|
}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { type ArgsFn, type DecorateFn, type GetCacheKey, type IProvider, type ProviderOptions, type ResolveDependency, type ScopeAccessOptions, type ScopeAccessRule } from './IProvider.js';
|
|
2
|
-
import type { DependencyKey, IContainer } from '../container/IContainer.js';
|
|
2
|
+
import type { DependencyHook, 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,6 +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
18
|
constructor(resolveDependency: ResolveDependency<T>);
|
|
18
19
|
resolve(scope: IContainer, options: ProviderOptions): T;
|
|
19
20
|
private resolveDep;
|
|
@@ -25,5 +26,6 @@ export declare class Provider<T = any> implements IProvider<T> {
|
|
|
25
26
|
addArgsFn(...fns: ArgsFn[]): this;
|
|
26
27
|
hasAccess(options: ScopeAccessOptions): boolean;
|
|
27
28
|
singleton(getCacheKey?: GetCacheKey): this;
|
|
29
|
+
onResolve(...hooks: DependencyHook[]): this;
|
|
28
30
|
dispose(): void;
|
|
29
31
|
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { type DependencyKey, type IContainer, type IContainerModule } from '../container/IContainer.js';
|
|
1
|
+
import { type DependencyHook, type DependencyKey, type IContainer, type IContainerModule } from '../container/IContainer.js';
|
|
2
2
|
import type { ArgsFn, DecorateFn, GetCacheKey, IProvider, ScopeAccessRule } from '../provider/IProvider.js';
|
|
3
3
|
import { BindToken } from '../token/BindToken.js';
|
|
4
4
|
import { MapFn } from '../utils/fp.js';
|
|
@@ -36,3 +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>;
|