ts-ioc-container 55.5.0 → 55.6.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 +31 -8
- package/cjm/container/AliasMap.js +0 -1
- package/cjm/container/Container.js +0 -5
- package/cjm/hooks/HookContext.js +0 -3
- package/cjm/hooks/hook.js +0 -5
- package/cjm/hooks/onContainerDisposed.js +18 -0
- package/cjm/index.js +5 -13
- package/cjm/injector/IInjector.js +0 -1
- package/cjm/utils/fp.js +0 -3
- package/cjm/utils/proxy.js +0 -1
- package/esm/container/AliasMap.js +0 -1
- package/esm/container/Container.js +7 -12
- package/esm/container/EmptyContainer.js +3 -3
- package/esm/errors/CannonSingletonApplyTwiceError.js +1 -1
- package/esm/errors/ContainerDisposedError.js +1 -1
- package/esm/errors/ContainerNotFoundError.js +1 -1
- package/esm/errors/DependencyMissingKeyError.js +1 -1
- package/esm/errors/DependencyNotFoundError.js +1 -1
- package/esm/errors/MethodNotImplementedError.js +1 -1
- package/esm/errors/ProviderDisposedError.js +1 -1
- package/esm/errors/UnexpectedHookResultError.js +1 -1
- package/esm/errors/UnsupportedTokenTypeError.js +1 -1
- package/esm/hooks/HookContext.js +2 -5
- package/esm/hooks/HooksRunner.js +4 -4
- package/esm/hooks/hook.js +2 -7
- package/esm/hooks/injectProp.js +1 -1
- package/esm/hooks/onConstruct.js +2 -2
- package/esm/hooks/onContainerDisposed.js +13 -0
- package/esm/index.js +43 -51
- package/esm/injector/IInjector.js +1 -2
- package/esm/injector/MetadataInjector.js +4 -4
- package/esm/injector/ProxyInjector.js +1 -1
- package/esm/injector/SimpleInjector.js +1 -1
- package/esm/metadata/class.js +1 -1
- package/esm/metadata/method.js +1 -1
- package/esm/metadata/parameter.js +1 -1
- package/esm/package.json +3 -0
- package/esm/provider/Provider.js +2 -2
- package/esm/registration/IRegistration.js +3 -3
- package/esm/registration/Registration.js +8 -8
- package/esm/select.js +4 -4
- package/esm/token/BindToken.js +1 -1
- package/esm/token/ClassToken.js +1 -1
- package/esm/token/ConstantToken.js +2 -2
- package/esm/token/FunctionToken.js +1 -1
- package/esm/token/GroupAliasToken.js +1 -1
- package/esm/token/GroupInstanceToken.js +2 -2
- package/esm/token/InjectionToken.js +1 -1
- package/esm/token/SingleAliasToken.js +1 -1
- package/esm/token/SingleToken.js +1 -1
- package/esm/token/toToken.js +8 -8
- package/esm/utils/fp.js +0 -3
- package/esm/utils/proxy.js +0 -1
- package/package.json +25 -11
- package/typings/ExecutionContext.d.ts +1 -1
- package/typings/container/AliasMap.d.ts +1 -1
- package/typings/container/Container.d.ts +7 -7
- package/typings/container/EmptyContainer.d.ts +6 -6
- package/typings/container/IContainer.d.ts +5 -5
- package/typings/errors/CannonSingletonApplyTwiceError.d.ts +1 -1
- package/typings/errors/ContainerDisposedError.d.ts +1 -1
- package/typings/errors/ContainerNotFoundError.d.ts +1 -1
- package/typings/errors/DependencyMissingKeyError.d.ts +1 -1
- package/typings/errors/DependencyNotFoundError.d.ts +1 -1
- package/typings/errors/MethodNotImplementedError.d.ts +1 -1
- package/typings/errors/ProviderDisposedError.d.ts +1 -1
- package/typings/errors/UnexpectedHookResultError.d.ts +1 -1
- package/typings/errors/UnsupportedTokenTypeError.d.ts +1 -1
- package/typings/hooks/HookContext.d.ts +2 -2
- package/typings/hooks/HooksRunner.d.ts +2 -2
- package/typings/hooks/hook.d.ts +4 -4
- package/typings/hooks/injectProp.d.ts +4 -4
- package/typings/hooks/onConstruct.d.ts +5 -5
- package/typings/hooks/onContainerDisposed.d.ts +10 -0
- package/typings/index.d.ts +45 -45
- package/typings/injector/IInjector.d.ts +3 -3
- package/typings/injector/MetadataInjector.d.ts +6 -6
- package/typings/injector/ProxyInjector.d.ts +3 -3
- package/typings/injector/SimpleInjector.d.ts +3 -3
- package/typings/provider/IProvider.d.ts +2 -2
- package/typings/provider/Provider.d.ts +3 -3
- package/typings/registration/IRegistration.d.ts +5 -5
- package/typings/registration/Registration.d.ts +6 -6
- package/typings/select.d.ts +5 -5
- package/typings/token/BindToken.d.ts +1 -1
- package/typings/token/ClassToken.d.ts +4 -4
- package/typings/token/ConstantToken.d.ts +2 -2
- package/typings/token/FunctionToken.d.ts +4 -4
- package/typings/token/GroupAliasToken.d.ts +5 -5
- package/typings/token/GroupInstanceToken.d.ts +3 -3
- package/typings/token/InjectionToken.d.ts +2 -2
- package/typings/token/SingleAliasToken.d.ts +5 -5
- package/typings/token/SingleToken.d.ts +4 -4
- package/typings/token/toToken.d.ts +4 -4
- package/cjm/hooks/onDispose.js +0 -18
- package/esm/hooks/onDispose.js +0 -13
- package/typings/hooks/onDispose.d.ts +0 -10
package/README.md
CHANGED
|
@@ -19,7 +19,7 @@ provider pipelines, aliases, and custom injector strategies.
|
|
|
19
19
|
- clean API for classes, keys, tokens, aliases, and scopes
|
|
20
20
|
- no global container object; pass containers and scopes explicitly
|
|
21
21
|
- supports tagged application, request, transaction, page, and widget scopes
|
|
22
|
-
- decorator support with `@register`, `@inject`, `@onConstruct`, and `@
|
|
22
|
+
- decorator support with `@register`, `@inject`, `@onConstruct`, and `@onContainerDisposed`
|
|
23
23
|
- can [inject properties](#inject-property)
|
|
24
24
|
- can inject [lazy dependencies](#lazy)
|
|
25
25
|
- composable provider and registration pipelines
|
|
@@ -27,6 +27,7 @@ provider pipelines, aliases, and custom injector strategies.
|
|
|
27
27
|
## Content
|
|
28
28
|
|
|
29
29
|
- [Setup](#setup)
|
|
30
|
+
- [Environment support](#environment-support)
|
|
30
31
|
- [Quickstart](#quickstart)
|
|
31
32
|
- [Cheatsheet](#cheatsheet)
|
|
32
33
|
- [Container](#container)
|
|
@@ -52,7 +53,7 @@ provider pipelines, aliases, and custom injector strategies.
|
|
|
52
53
|
- [Module](#module)
|
|
53
54
|
- [Hook](#hook) `@hook`
|
|
54
55
|
- [OnConstruct](#onconstruct) `@onConstruct`
|
|
55
|
-
- [
|
|
56
|
+
- [OnContainerDisposed](#oncontainerdisposed) `@onContainerDisposed`
|
|
56
57
|
- [Inject Property](#inject-property)
|
|
57
58
|
- [Inject Method](#inject-method)
|
|
58
59
|
- [Mock](#mock)
|
|
@@ -85,6 +86,28 @@ And `tsconfig.json` should have next options:
|
|
|
85
86
|
}
|
|
86
87
|
```
|
|
87
88
|
|
|
89
|
+
## Environment support
|
|
90
|
+
|
|
91
|
+
`ts-ioc-container` ships both CommonJS and ES module builds (selected
|
|
92
|
+
automatically via the package `exports` map) plus TypeScript declarations, so it
|
|
93
|
+
runs anywhere modern JavaScript does. The package is `sideEffects`-free, so
|
|
94
|
+
bundlers tree-shake unused exports.
|
|
95
|
+
|
|
96
|
+
| Environment | Supported | Module format | Notes |
|
|
97
|
+
| --- | :---: | --- | --- |
|
|
98
|
+
| Node.js (ESM, `import`) | ✅ | ESM | Node.js 18+; resolved via the `import` condition. |
|
|
99
|
+
| Node.js (CommonJS, `require`) | ✅ | CJS | Node.js 18+; resolved via the `require` condition. |
|
|
100
|
+
| Browser / Web (via bundlers) | ✅ | ESM | webpack, Vite, Rollup, esbuild, Parcel; tree-shakeable. |
|
|
101
|
+
| TypeScript | ✅ | CJS + ESM | Types shipped for both; needs `experimentalDecorators` for the metadata injector. |
|
|
102
|
+
| Deno | ✅ | ESM | Use the `npm:ts-ioc-container` specifier. |
|
|
103
|
+
| Bun | ✅ | CJS + ESM | Runs the native ESM/CJS builds directly. |
|
|
104
|
+
|
|
105
|
+
> [!NOTE]
|
|
106
|
+
> The default `MetadataInjector` (and the `@inject` / `@onConstruct` /
|
|
107
|
+
> `@onContainerDisposed` decorators) rely on `reflect-metadata`. It is declared as an
|
|
108
|
+
> optional peer dependency — install it and import it once at your entrypoint.
|
|
109
|
+
> `SimpleInjector` and `ProxyInjector` do not need it.
|
|
110
|
+
|
|
88
111
|
## Quickstart
|
|
89
112
|
|
|
90
113
|
```typescript
|
|
@@ -426,7 +449,7 @@ describe('Instances', function () {
|
|
|
426
449
|
Sometimes you want to dispose a container or scope. For example, when a request, page, widget, or other local lifecycle ends.
|
|
427
450
|
|
|
428
451
|
- container can be disposed
|
|
429
|
-
- when container is disposed then it runs its `
|
|
452
|
+
- when container is disposed then it runs its `onContainerDisposed` hooks, unregisters its providers, removes its local instances, and detaches from its parent
|
|
430
453
|
|
|
431
454
|
> [!IMPORTANT]
|
|
432
455
|
> Dispose is local to the container being disposed. Child scopes are not disposed automatically; dispose them explicitly when their own lifecycle ends.
|
|
@@ -445,7 +468,7 @@ import { bindTo, Container, ContainerDisposedError, register, Registration as R,
|
|
|
445
468
|
* - Cache entries cleared
|
|
446
469
|
*
|
|
447
470
|
* The container.dispose() method:
|
|
448
|
-
* 1. Executes all
|
|
471
|
+
* 1. Executes all onContainerDisposed hooks
|
|
449
472
|
* 2. Clears all instances and registrations
|
|
450
473
|
* 3. Detaches from parent scope
|
|
451
474
|
* 4. Prevents further resolution
|
|
@@ -2561,7 +2584,7 @@ describe('onConstruct', function () {
|
|
|
2561
2584
|
|
|
2562
2585
|
```
|
|
2563
2586
|
|
|
2564
|
-
###
|
|
2587
|
+
### OnContainerDisposed
|
|
2565
2588
|
|
|
2566
2589
|
```typescript
|
|
2567
2590
|
import 'reflect-metadata';
|
|
@@ -2571,7 +2594,7 @@ import {
|
|
|
2571
2594
|
Container,
|
|
2572
2595
|
type HookFn,
|
|
2573
2596
|
inject,
|
|
2574
|
-
|
|
2597
|
+
onContainerDisposed,
|
|
2575
2598
|
register,
|
|
2576
2599
|
Registration as R,
|
|
2577
2600
|
singleton,
|
|
@@ -2600,13 +2623,13 @@ class Logger {
|
|
|
2600
2623
|
this.messages.push(message);
|
|
2601
2624
|
}
|
|
2602
2625
|
|
|
2603
|
-
@
|
|
2626
|
+
@onContainerDisposed(execute)
|
|
2604
2627
|
save() {
|
|
2605
2628
|
this.logsRepo.saveLogs(this.messages);
|
|
2606
2629
|
}
|
|
2607
2630
|
}
|
|
2608
2631
|
|
|
2609
|
-
describe('
|
|
2632
|
+
describe('onContainerDisposed', function () {
|
|
2610
2633
|
it('should invoke hooks on all instances when container is disposed', function () {
|
|
2611
2634
|
const container = new Container()
|
|
2612
2635
|
.useModule(new AddOnDisposeHookModule())
|
|
@@ -83,15 +83,12 @@ class Container {
|
|
|
83
83
|
dispose() {
|
|
84
84
|
this.validateContainer();
|
|
85
85
|
this.isDisposed = true;
|
|
86
|
-
// Execute onDispose hooks
|
|
87
86
|
while (this.onDisposeHookList.length) {
|
|
88
87
|
const onDispose = this.onDisposeHookList.shift();
|
|
89
88
|
onDispose(this);
|
|
90
89
|
}
|
|
91
|
-
// Detach from parent
|
|
92
90
|
this.parent.removeScope(this);
|
|
93
91
|
this.parent = new EmptyContainer_1.EmptyContainer();
|
|
94
|
-
// Reset the state
|
|
95
92
|
for (const [_, provider] of this.providers) {
|
|
96
93
|
provider.dispose();
|
|
97
94
|
}
|
|
@@ -99,7 +96,6 @@ class Container {
|
|
|
99
96
|
this.aliases.destroy();
|
|
100
97
|
this.instances = [];
|
|
101
98
|
this.registrations = [];
|
|
102
|
-
// Clear hooks
|
|
103
99
|
this.onConstructHookList.splice(0, this.onConstructHookList.length);
|
|
104
100
|
}
|
|
105
101
|
addRegistration(registration) {
|
|
@@ -123,7 +119,6 @@ class Container {
|
|
|
123
119
|
}
|
|
124
120
|
addInstance(instance) {
|
|
125
121
|
this.instances.push(instance);
|
|
126
|
-
// Execute onConstruct hooks
|
|
127
122
|
for (const onConstruct of this.onConstructHookList) {
|
|
128
123
|
onConstruct(instance, this);
|
|
129
124
|
}
|
package/cjm/hooks/HookContext.js
CHANGED
|
@@ -19,15 +19,12 @@ class HookContext {
|
|
|
19
19
|
});
|
|
20
20
|
}
|
|
21
21
|
invokeMethod({ args = this.resolveArgs() } = {}) {
|
|
22
|
-
// @ts-ignore
|
|
23
22
|
return this.instance[this.methodName](...args);
|
|
24
23
|
}
|
|
25
24
|
setProperty(fn) {
|
|
26
|
-
// @ts-ignore
|
|
27
25
|
this.instance[this.methodName] = fn.resolve(this.scope);
|
|
28
26
|
}
|
|
29
27
|
getProperty() {
|
|
30
|
-
// @ts-ignore
|
|
31
28
|
return this.instance[this.methodName];
|
|
32
29
|
}
|
|
33
30
|
setInitialArgs(...args) {
|
package/cjm/hooks/hook.js
CHANGED
|
@@ -13,7 +13,6 @@ exports.toHookFn = toHookFn;
|
|
|
13
13
|
const getReflectionTarget = (target) => {
|
|
14
14
|
return (0, proxy_1.isProxy)(target) ? (0, proxy_1.getProxyTarget)(target) : target;
|
|
15
15
|
};
|
|
16
|
-
// Walk the constructor's prototype chain (most-derived first) collecting each class.
|
|
17
16
|
const getConstructorChain = (ctor) => {
|
|
18
17
|
const chain = [];
|
|
19
18
|
let current = ctor;
|
|
@@ -23,9 +22,6 @@ const getConstructorChain = (ctor) => {
|
|
|
23
22
|
}
|
|
24
23
|
return chain;
|
|
25
24
|
};
|
|
26
|
-
// Get hooks metadata, merging hooks declared on parent (extended-from) classes.
|
|
27
|
-
// Hooks are collected from base to derived so a derived class's hooks for the same
|
|
28
|
-
// method name take precedence over (replace) the parent's.
|
|
29
25
|
function getHooks(target, key) {
|
|
30
26
|
const reflectionTarget = getReflectionTarget(target);
|
|
31
27
|
const merged = new Map();
|
|
@@ -43,7 +39,6 @@ function hasHooks(target, key) {
|
|
|
43
39
|
const reflectionTarget = getReflectionTarget(target);
|
|
44
40
|
return getConstructorChain(reflectionTarget.constructor).some((ctor) => Reflect.hasOwnMetadata(key, ctor));
|
|
45
41
|
}
|
|
46
|
-
// Hook decorator
|
|
47
42
|
const hook = (key, ...fns) => (target, propertyKey) => {
|
|
48
43
|
const hooks = Reflect.hasOwnMetadata(key, target.constructor)
|
|
49
44
|
? Reflect.getOwnMetadata(key, target.constructor)
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.AddOnDisposeHookModule = exports.onContainerDisposed = exports.onContainerDisposedHooksRunner = void 0;
|
|
4
|
+
const hook_1 = require("./hook");
|
|
5
|
+
const HooksRunner_1 = require("./HooksRunner");
|
|
6
|
+
exports.onContainerDisposedHooksRunner = new HooksRunner_1.HooksRunner('onContainerDisposed');
|
|
7
|
+
const onContainerDisposed = (...fns) => (0, hook_1.hook)('onContainerDisposed', ...fns);
|
|
8
|
+
exports.onContainerDisposed = onContainerDisposed;
|
|
9
|
+
class AddOnDisposeHookModule {
|
|
10
|
+
applyTo(container) {
|
|
11
|
+
container.addOnDisposeHook((scope) => {
|
|
12
|
+
for (const instance of scope.getInstances()) {
|
|
13
|
+
exports.onContainerDisposedHooksRunner.execute(instance, { scope });
|
|
14
|
+
}
|
|
15
|
+
});
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
exports.AddOnDisposeHookModule = AddOnDisposeHookModule;
|
package/cjm/index.js
CHANGED
|
@@ -1,15 +1,13 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.ClassToken = exports.toSingleAlias = exports.SingleAliasToken = exports.toGroupAlias = exports.GroupAliasToken = exports.InjectionToken = exports.HooksRunner = exports.AddOnDisposeHookModule = exports.
|
|
3
|
+
exports.ClassToken = exports.toSingleAlias = exports.SingleAliasToken = exports.toGroupAlias = exports.GroupAliasToken = exports.InjectionToken = exports.HooksRunner = exports.AddOnDisposeHookModule = exports.onContainerDisposed = exports.onContainerDisposedHooksRunner = exports.AddOnConstructHookModule = exports.onConstruct = exports.onConstructHooksRunner = exports.injectProp = exports.createHookContext = exports.createHookContextFactory = exports.HookContext = exports.hasHooks = exports.hook = exports.getHooks = exports.CannonSingletonApplyTwiceError = exports.UnexpectedHookResultError = exports.ProviderDisposedError = exports.ContainerDisposedError = exports.MethodNotImplementedError = exports.DependencyMissingKeyError = exports.ContainerNotFoundError = exports.DependencyNotFoundError = exports.Registration = exports.appendArgsFn = exports.appendArgs = exports.decorate = exports.singleton = exports.lazy = exports.scopeAccess = exports.scope = exports.bindTo = exports.register = exports.Provider = exports.ProxyInjector = exports.SimpleInjector = exports.resolveArgs = exports.argsFn = exports.args = exports.inject = exports.MetadataInjector = exports.Injector = exports.EmptyContainer = exports.Container = exports.isDependencyKey = void 0;
|
|
4
4
|
exports.resolveConstructor = exports.Is = 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 = 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 = void 0;
|
|
5
|
-
// Containers
|
|
6
5
|
var IContainer_1 = require("./container/IContainer");
|
|
7
6
|
Object.defineProperty(exports, "isDependencyKey", { enumerable: true, get: function () { return IContainer_1.isDependencyKey; } });
|
|
8
7
|
var Container_1 = require("./container/Container");
|
|
9
8
|
Object.defineProperty(exports, "Container", { enumerable: true, get: function () { return Container_1.Container; } });
|
|
10
9
|
var EmptyContainer_1 = require("./container/EmptyContainer");
|
|
11
10
|
Object.defineProperty(exports, "EmptyContainer", { enumerable: true, get: function () { return EmptyContainer_1.EmptyContainer; } });
|
|
12
|
-
// Injectors
|
|
13
11
|
var IInjector_1 = require("./injector/IInjector");
|
|
14
12
|
Object.defineProperty(exports, "Injector", { enumerable: true, get: function () { return IInjector_1.Injector; } });
|
|
15
13
|
var MetadataInjector_1 = require("./injector/MetadataInjector");
|
|
@@ -24,7 +22,6 @@ var ProxyInjector_1 = require("./injector/ProxyInjector");
|
|
|
24
22
|
Object.defineProperty(exports, "ProxyInjector", { enumerable: true, get: function () { return ProxyInjector_1.ProxyInjector; } });
|
|
25
23
|
var Provider_1 = require("./provider/Provider");
|
|
26
24
|
Object.defineProperty(exports, "Provider", { enumerable: true, get: function () { return Provider_1.Provider; } });
|
|
27
|
-
// Registrations
|
|
28
25
|
var IRegistration_1 = require("./registration/IRegistration");
|
|
29
26
|
Object.defineProperty(exports, "register", { enumerable: true, get: function () { return IRegistration_1.register; } });
|
|
30
27
|
Object.defineProperty(exports, "bindTo", { enumerable: true, get: function () { return IRegistration_1.bindTo; } });
|
|
@@ -37,7 +34,6 @@ Object.defineProperty(exports, "appendArgs", { enumerable: true, get: function (
|
|
|
37
34
|
Object.defineProperty(exports, "appendArgsFn", { enumerable: true, get: function () { return IRegistration_1.appendArgsFn; } });
|
|
38
35
|
var Registration_1 = require("./registration/Registration");
|
|
39
36
|
Object.defineProperty(exports, "Registration", { enumerable: true, get: function () { return Registration_1.Registration; } });
|
|
40
|
-
// Errors
|
|
41
37
|
var DependencyNotFoundError_1 = require("./errors/DependencyNotFoundError");
|
|
42
38
|
Object.defineProperty(exports, "DependencyNotFoundError", { enumerable: true, get: function () { return DependencyNotFoundError_1.DependencyNotFoundError; } });
|
|
43
39
|
var ContainerNotFoundError_1 = require("./errors/ContainerNotFoundError");
|
|
@@ -54,7 +50,6 @@ var UnexpectedHookResultError_1 = require("./errors/UnexpectedHookResultError");
|
|
|
54
50
|
Object.defineProperty(exports, "UnexpectedHookResultError", { enumerable: true, get: function () { return UnexpectedHookResultError_1.UnexpectedHookResultError; } });
|
|
55
51
|
var CannonSingletonApplyTwiceError_1 = require("./errors/CannonSingletonApplyTwiceError");
|
|
56
52
|
Object.defineProperty(exports, "CannonSingletonApplyTwiceError", { enumerable: true, get: function () { return CannonSingletonApplyTwiceError_1.CannonSingletonApplyTwiceError; } });
|
|
57
|
-
// Hooks
|
|
58
53
|
var hook_1 = require("./hooks/hook");
|
|
59
54
|
Object.defineProperty(exports, "getHooks", { enumerable: true, get: function () { return hook_1.getHooks; } });
|
|
60
55
|
Object.defineProperty(exports, "hook", { enumerable: true, get: function () { return hook_1.hook; } });
|
|
@@ -69,13 +64,12 @@ var onConstruct_1 = require("./hooks/onConstruct");
|
|
|
69
64
|
Object.defineProperty(exports, "onConstructHooksRunner", { enumerable: true, get: function () { return onConstruct_1.onConstructHooksRunner; } });
|
|
70
65
|
Object.defineProperty(exports, "onConstruct", { enumerable: true, get: function () { return onConstruct_1.onConstruct; } });
|
|
71
66
|
Object.defineProperty(exports, "AddOnConstructHookModule", { enumerable: true, get: function () { return onConstruct_1.AddOnConstructHookModule; } });
|
|
72
|
-
var
|
|
73
|
-
Object.defineProperty(exports, "
|
|
74
|
-
Object.defineProperty(exports, "
|
|
75
|
-
Object.defineProperty(exports, "AddOnDisposeHookModule", { enumerable: true, get: function () { return
|
|
67
|
+
var onContainerDisposed_1 = require("./hooks/onContainerDisposed");
|
|
68
|
+
Object.defineProperty(exports, "onContainerDisposedHooksRunner", { enumerable: true, get: function () { return onContainerDisposed_1.onContainerDisposedHooksRunner; } });
|
|
69
|
+
Object.defineProperty(exports, "onContainerDisposed", { enumerable: true, get: function () { return onContainerDisposed_1.onContainerDisposed; } });
|
|
70
|
+
Object.defineProperty(exports, "AddOnDisposeHookModule", { enumerable: true, get: function () { return onContainerDisposed_1.AddOnDisposeHookModule; } });
|
|
76
71
|
var HooksRunner_1 = require("./hooks/HooksRunner");
|
|
77
72
|
Object.defineProperty(exports, "HooksRunner", { enumerable: true, get: function () { return HooksRunner_1.HooksRunner; } });
|
|
78
|
-
// Tokens
|
|
79
73
|
var InjectionToken_1 = require("./token/InjectionToken");
|
|
80
74
|
Object.defineProperty(exports, "InjectionToken", { enumerable: true, get: function () { return InjectionToken_1.InjectionToken; } });
|
|
81
75
|
var GroupAliasToken_1 = require("./token/GroupAliasToken");
|
|
@@ -94,7 +88,6 @@ var ConstantToken_1 = require("./token/ConstantToken");
|
|
|
94
88
|
Object.defineProperty(exports, "ConstantToken", { enumerable: true, get: function () { return ConstantToken_1.ConstantToken; } });
|
|
95
89
|
var GroupInstanceToken_1 = require("./token/GroupInstanceToken");
|
|
96
90
|
Object.defineProperty(exports, "GroupInstanceToken", { enumerable: true, get: function () { return GroupInstanceToken_1.GroupInstanceToken; } });
|
|
97
|
-
// Metadata
|
|
98
91
|
var class_1 = require("./metadata/class");
|
|
99
92
|
Object.defineProperty(exports, "addClassMeta", { enumerable: true, get: function () { return class_1.addClassMeta; } });
|
|
100
93
|
Object.defineProperty(exports, "getClassMeta", { enumerable: true, get: function () { return class_1.getClassMeta; } });
|
|
@@ -127,7 +120,6 @@ var shallowCache_1 = require("./utils/shallowCache");
|
|
|
127
120
|
Object.defineProperty(exports, "shallowCache", { enumerable: true, get: function () { return shallowCache_1.shallowCache; } });
|
|
128
121
|
var once_1 = require("./utils/once");
|
|
129
122
|
Object.defineProperty(exports, "once", { enumerable: true, get: function () { return once_1.once; } });
|
|
130
|
-
// Utils
|
|
131
123
|
var select_1 = require("./select");
|
|
132
124
|
Object.defineProperty(exports, "select", { enumerable: true, get: function () { return select_1.select; } });
|
|
133
125
|
var fp_1 = require("./utils/fp");
|
|
@@ -4,7 +4,6 @@ exports.Injector = void 0;
|
|
|
4
4
|
const proxy_1 = require("../utils/proxy");
|
|
5
5
|
class Injector {
|
|
6
6
|
resolve(scope, Target, { args, lazy } = {}) {
|
|
7
|
-
// @ts-ignore
|
|
8
7
|
return (0, proxy_1.toLazyIf)(() => {
|
|
9
8
|
const instance = this.createInstance(scope, Target, { args });
|
|
10
9
|
scope.addInstance(instance);
|
package/cjm/utils/fp.js
CHANGED
|
@@ -1,9 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.pipe = pipe;
|
|
4
|
-
// Implementation
|
|
5
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
6
4
|
function pipe(...mappers) {
|
|
7
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
8
5
|
return (value) => mappers.reduce((acc, current) => current(acc), value);
|
|
9
6
|
}
|
package/cjm/utils/proxy.js
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
import { EmptyContainer } from './EmptyContainer';
|
|
2
|
-
import { ContainerDisposedError } from '../errors/ContainerDisposedError';
|
|
3
|
-
import { MetadataInjector } from '../injector/MetadataInjector';
|
|
4
|
-
import { AliasMap } from './AliasMap';
|
|
5
|
-
import { DependencyNotFoundError } from '../errors/DependencyNotFoundError';
|
|
6
|
-
import { Is } from '../utils/basic';
|
|
7
|
-
import { Filter as F } from '../utils/array';
|
|
1
|
+
import { EmptyContainer } from './EmptyContainer.js';
|
|
2
|
+
import { ContainerDisposedError } from '../errors/ContainerDisposedError.js';
|
|
3
|
+
import { MetadataInjector } from '../injector/MetadataInjector.js';
|
|
4
|
+
import { AliasMap } from './AliasMap.js';
|
|
5
|
+
import { DependencyNotFoundError } from '../errors/DependencyNotFoundError.js';
|
|
6
|
+
import { Is } from '../utils/basic.js';
|
|
7
|
+
import { Filter as F } from '../utils/array.js';
|
|
8
8
|
export class Container {
|
|
9
9
|
isDisposed = false;
|
|
10
10
|
parent;
|
|
@@ -80,15 +80,12 @@ export class Container {
|
|
|
80
80
|
dispose() {
|
|
81
81
|
this.validateContainer();
|
|
82
82
|
this.isDisposed = true;
|
|
83
|
-
// Execute onDispose hooks
|
|
84
83
|
while (this.onDisposeHookList.length) {
|
|
85
84
|
const onDispose = this.onDisposeHookList.shift();
|
|
86
85
|
onDispose(this);
|
|
87
86
|
}
|
|
88
|
-
// Detach from parent
|
|
89
87
|
this.parent.removeScope(this);
|
|
90
88
|
this.parent = new EmptyContainer();
|
|
91
|
-
// Reset the state
|
|
92
89
|
for (const [_, provider] of this.providers) {
|
|
93
90
|
provider.dispose();
|
|
94
91
|
}
|
|
@@ -96,7 +93,6 @@ export class Container {
|
|
|
96
93
|
this.aliases.destroy();
|
|
97
94
|
this.instances = [];
|
|
98
95
|
this.registrations = [];
|
|
99
|
-
// Clear hooks
|
|
100
96
|
this.onConstructHookList.splice(0, this.onConstructHookList.length);
|
|
101
97
|
}
|
|
102
98
|
addRegistration(registration) {
|
|
@@ -120,7 +116,6 @@ export class Container {
|
|
|
120
116
|
}
|
|
121
117
|
addInstance(instance) {
|
|
122
118
|
this.instances.push(instance);
|
|
123
|
-
// Execute onConstruct hooks
|
|
124
119
|
for (const onConstruct of this.onConstructHookList) {
|
|
125
120
|
onConstruct(instance, this);
|
|
126
121
|
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { MethodNotImplementedError } from '../errors/MethodNotImplementedError';
|
|
2
|
-
import { DependencyNotFoundError } from '../errors/DependencyNotFoundError';
|
|
3
|
-
import { ContainerNotFoundError } from '../errors/ContainerNotFoundError';
|
|
1
|
+
import { MethodNotImplementedError } from '../errors/MethodNotImplementedError.js';
|
|
2
|
+
import { DependencyNotFoundError } from '../errors/DependencyNotFoundError.js';
|
|
3
|
+
import { ContainerNotFoundError } from '../errors/ContainerNotFoundError.js';
|
|
4
4
|
export class EmptyContainer {
|
|
5
5
|
get isDisposed() {
|
|
6
6
|
throw new MethodNotImplementedError();
|
package/esm/hooks/HookContext.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { getProxyTarget, isProxy } from '../utils/proxy';
|
|
2
|
-
import { resolveArgs } from '../injector/MetadataInjector';
|
|
1
|
+
import { getProxyTarget, isProxy } from '../utils/proxy.js';
|
|
2
|
+
import { resolveArgs } from '../injector/MetadataInjector.js';
|
|
3
3
|
export class HookContext {
|
|
4
4
|
scope;
|
|
5
5
|
methodName;
|
|
@@ -16,15 +16,12 @@ export class HookContext {
|
|
|
16
16
|
});
|
|
17
17
|
}
|
|
18
18
|
invokeMethod({ args = this.resolveArgs() } = {}) {
|
|
19
|
-
// @ts-ignore
|
|
20
19
|
return this.instance[this.methodName](...args);
|
|
21
20
|
}
|
|
22
21
|
setProperty(fn) {
|
|
23
|
-
// @ts-ignore
|
|
24
22
|
this.instance[this.methodName] = fn.resolve(this.scope);
|
|
25
23
|
}
|
|
26
24
|
getProperty() {
|
|
27
|
-
// @ts-ignore
|
|
28
25
|
return this.instance[this.methodName];
|
|
29
26
|
}
|
|
30
27
|
setInitialArgs(...args) {
|
package/esm/hooks/HooksRunner.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import { createHookContext } from './HookContext';
|
|
2
|
-
import { getHooks, hasHooks, toHookFn } from './hook';
|
|
3
|
-
import { UnexpectedHookResultError } from '../errors/UnexpectedHookResultError';
|
|
4
|
-
import { promisify } from '../utils/promise';
|
|
1
|
+
import { createHookContext } from './HookContext.js';
|
|
2
|
+
import { getHooks, hasHooks, toHookFn } from './hook.js';
|
|
3
|
+
import { UnexpectedHookResultError } from '../errors/UnexpectedHookResultError.js';
|
|
4
|
+
import { promisify } from '../utils/promise.js';
|
|
5
5
|
export class HooksRunner {
|
|
6
6
|
key;
|
|
7
7
|
constructor(key) {
|
package/esm/hooks/hook.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { Is } from '../utils/basic';
|
|
2
|
-
import { getProxyTarget, isProxy } from '../utils/proxy';
|
|
1
|
+
import { Is } from '../utils/basic.js';
|
|
2
|
+
import { getProxyTarget, isProxy } from '../utils/proxy.js';
|
|
3
3
|
const isHookClassConstructor = (execute) => {
|
|
4
4
|
return Is.constructor(execute) && execute.prototype.execute;
|
|
5
5
|
};
|
|
@@ -7,7 +7,6 @@ export const toHookFn = (execute) => isHookClassConstructor(execute) ? (context)
|
|
|
7
7
|
const getReflectionTarget = (target) => {
|
|
8
8
|
return isProxy(target) ? getProxyTarget(target) : target;
|
|
9
9
|
};
|
|
10
|
-
// Walk the constructor's prototype chain (most-derived first) collecting each class.
|
|
11
10
|
const getConstructorChain = (ctor) => {
|
|
12
11
|
const chain = [];
|
|
13
12
|
let current = ctor;
|
|
@@ -17,9 +16,6 @@ const getConstructorChain = (ctor) => {
|
|
|
17
16
|
}
|
|
18
17
|
return chain;
|
|
19
18
|
};
|
|
20
|
-
// Get hooks metadata, merging hooks declared on parent (extended-from) classes.
|
|
21
|
-
// Hooks are collected from base to derived so a derived class's hooks for the same
|
|
22
|
-
// method name take precedence over (replace) the parent's.
|
|
23
19
|
export function getHooks(target, key) {
|
|
24
20
|
const reflectionTarget = getReflectionTarget(target);
|
|
25
21
|
const merged = new Map();
|
|
@@ -37,7 +33,6 @@ export function hasHooks(target, key) {
|
|
|
37
33
|
const reflectionTarget = getReflectionTarget(target);
|
|
38
34
|
return getConstructorChain(reflectionTarget.constructor).some((ctor) => Reflect.hasOwnMetadata(key, ctor));
|
|
39
35
|
}
|
|
40
|
-
// Hook decorator
|
|
41
36
|
export const hook = (key, ...fns) => (target, propertyKey) => {
|
|
42
37
|
const hooks = Reflect.hasOwnMetadata(key, target.constructor)
|
|
43
38
|
? Reflect.getOwnMetadata(key, target.constructor)
|
package/esm/hooks/injectProp.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { toToken } from '../token/toToken';
|
|
1
|
+
import { toToken } from '../token/toToken.js';
|
|
2
2
|
export const injectProp = (fn) => (context) => context.setProperty(toToken(fn));
|
package/esm/hooks/onConstruct.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { hook } from './hook';
|
|
2
|
-
import { HooksRunner } from './HooksRunner';
|
|
1
|
+
import { hook } from './hook.js';
|
|
2
|
+
import { HooksRunner } from './HooksRunner.js';
|
|
3
3
|
export const onConstructHooksRunner = new HooksRunner('onConstruct');
|
|
4
4
|
export const onConstruct = (...fns) => hook('onConstruct', ...fns);
|
|
5
5
|
export class AddOnConstructHookModule {
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { hook } from './hook.js';
|
|
2
|
+
import { HooksRunner } from './HooksRunner.js';
|
|
3
|
+
export const onContainerDisposedHooksRunner = new HooksRunner('onContainerDisposed');
|
|
4
|
+
export const onContainerDisposed = (...fns) => hook('onContainerDisposed', ...fns);
|
|
5
|
+
export class AddOnDisposeHookModule {
|
|
6
|
+
applyTo(container) {
|
|
7
|
+
container.addOnDisposeHook((scope) => {
|
|
8
|
+
for (const instance of scope.getInstances()) {
|
|
9
|
+
onContainerDisposedHooksRunner.execute(instance, { scope });
|
|
10
|
+
}
|
|
11
|
+
});
|
|
12
|
+
}
|
|
13
|
+
}
|