ts-ioc-container 63.0.0 → 65.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 +110 -94
- package/cjm/container/AutoResolveModule.js +1 -1
- package/cjm/container/Container.js +20 -31
- package/cjm/container/EmptyContainer.js +6 -3
- package/cjm/errors/TypedEventDisposedError.js +17 -0
- package/cjm/hooks/AsyncHookExecutionStrategy.js +15 -0
- package/cjm/hooks/HookContext.js +4 -4
- package/cjm/hooks/HookExecutionStrategy.js +68 -0
- package/cjm/hooks/ParallelAsync.js +17 -0
- package/cjm/hooks/SequentialAsync.js +15 -0
- package/cjm/hooks/SequentialSync.js +14 -0
- package/cjm/hooks/onConstruct.js +7 -9
- package/cjm/hooks/onResolved.js +14 -10
- package/cjm/hooks/onScopeDisposed.js +6 -8
- package/cjm/hooks/resolveHooks.js +1 -18
- package/cjm/index.js +18 -11
- package/cjm/utils/TypedEvent.js +35 -0
- package/esm/container/AutoResolveModule.js +1 -1
- package/esm/container/Container.js +20 -31
- package/esm/container/EmptyContainer.js +6 -3
- package/esm/errors/TypedEventDisposedError.js +13 -0
- package/esm/hooks/AsyncHookExecutionStrategy.js +11 -0
- package/esm/hooks/HookContext.js +2 -2
- package/esm/hooks/HookExecutionStrategy.js +62 -0
- package/esm/hooks/ParallelAsync.js +13 -0
- package/esm/hooks/SequentialAsync.js +11 -0
- package/esm/hooks/SequentialSync.js +10 -0
- package/esm/hooks/onConstruct.js +6 -8
- package/esm/hooks/onResolved.js +12 -9
- package/esm/hooks/onScopeDisposed.js +5 -7
- package/esm/hooks/resolveHooks.js +1 -14
- package/esm/index.js +12 -6
- package/esm/utils/TypedEvent.js +31 -0
- package/package.json +1 -1
- package/typings/container/Container.d.ts +9 -7
- package/typings/container/EmptyContainer.d.ts +7 -4
- package/typings/container/IContainer.d.ts +6 -4
- package/typings/errors/TypedEventDisposedError.d.ts +6 -0
- package/typings/hooks/AsyncHookExecutionStrategy.d.ts +10 -0
- package/typings/hooks/HookContext.d.ts +3 -3
- package/typings/hooks/HookExecutionStrategy.d.ts +35 -0
- package/typings/hooks/ParallelAsync.d.ts +5 -0
- package/typings/hooks/SequentialAsync.d.ts +5 -0
- package/typings/hooks/SequentialSync.d.ts +4 -0
- package/typings/hooks/onConstruct.d.ts +7 -8
- package/typings/hooks/onResolved.d.ts +5 -5
- package/typings/hooks/onScopeDisposed.d.ts +4 -5
- package/typings/hooks/resolveHooks.d.ts +0 -6
- package/typings/index.d.ts +12 -6
- package/typings/utils/TypedEvent.d.ts +17 -0
- package/cjm/hooks/HooksRunner.js +0 -50
- package/esm/hooks/HooksRunner.js +0 -45
- package/typings/hooks/HooksRunner.d.ts +0 -19
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.SequentialSync = void 0;
|
|
4
|
+
const HookExecutionStrategy_1 = require("./HookExecutionStrategy");
|
|
5
|
+
class SequentialSync extends HookExecutionStrategy_1.HookExecutionStrategy {
|
|
6
|
+
processHooks(members) {
|
|
7
|
+
for (const { hooks, context } of members) {
|
|
8
|
+
for (const hook of hooks) {
|
|
9
|
+
hook(context);
|
|
10
|
+
}
|
|
11
|
+
}
|
|
12
|
+
}
|
|
13
|
+
}
|
|
14
|
+
exports.SequentialSync = SequentialSync;
|
package/cjm/hooks/onConstruct.js
CHANGED
|
@@ -1,19 +1,17 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.OnConstructModule = exports.onConstruct =
|
|
3
|
+
exports.OnConstructModule = exports.onConstruct = void 0;
|
|
4
4
|
const hook_1 = require("./hook");
|
|
5
|
-
const HooksRunner_1 = require("./HooksRunner");
|
|
6
|
-
exports.onConstructHooksRunner = new HooksRunner_1.HooksRunner('onConstruct');
|
|
7
5
|
const onConstruct = (...fns) => (0, hook_1.hook)('onConstruct', (0, hook_1.prependHooks)(...fns));
|
|
8
6
|
exports.onConstruct = onConstruct;
|
|
9
7
|
class OnConstructModule {
|
|
10
|
-
|
|
11
|
-
constructor(
|
|
12
|
-
this.
|
|
8
|
+
strategy;
|
|
9
|
+
constructor(strategy) {
|
|
10
|
+
this.strategy = strategy;
|
|
13
11
|
}
|
|
14
|
-
applyTo(
|
|
15
|
-
|
|
16
|
-
|
|
12
|
+
applyTo(container) {
|
|
13
|
+
container.getInjector().onConstructed((instance, scope) => {
|
|
14
|
+
this.strategy.execute(instance, { scope });
|
|
17
15
|
});
|
|
18
16
|
}
|
|
19
17
|
}
|
package/cjm/hooks/onResolved.js
CHANGED
|
@@ -1,23 +1,27 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.resolved = exports.OnResolvedModule = exports.onResolved =
|
|
4
|
-
const HooksRunner_1 = require("./HooksRunner");
|
|
3
|
+
exports.resolved = exports.OnResolvedModule = exports.onResolved = void 0;
|
|
5
4
|
const IRegistration_1 = require("../registration/IRegistration");
|
|
6
|
-
const
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
5
|
+
const basic_1 = require("../utils/basic");
|
|
6
|
+
const hook_1 = require("./hook");
|
|
7
|
+
const onResolved = (...hooks) => (0, hook_1.hook)('onResolved', (0, hook_1.prependHooks)(...hooks));
|
|
8
|
+
exports.onResolved = onResolved;
|
|
9
|
+
const runHooks = (strategy) => (dependency, scope) => {
|
|
10
|
+
if (basic_1.Is.object(dependency)) {
|
|
11
|
+
strategy.execute(dependency, { scope });
|
|
12
|
+
}
|
|
13
|
+
};
|
|
10
14
|
class OnResolvedModule {
|
|
11
15
|
runHooks;
|
|
12
|
-
constructor(
|
|
13
|
-
this.runHooks = runHooks(
|
|
16
|
+
constructor(strategy) {
|
|
17
|
+
this.runHooks = runHooks(strategy);
|
|
14
18
|
}
|
|
15
19
|
applyTo(container) {
|
|
16
|
-
container.
|
|
20
|
+
container.registered.subscribe((provider) => {
|
|
17
21
|
provider.onResolved(this.runHooks);
|
|
18
22
|
});
|
|
19
23
|
}
|
|
20
24
|
}
|
|
21
25
|
exports.OnResolvedModule = OnResolvedModule;
|
|
22
|
-
const resolved = (
|
|
26
|
+
const resolved = (strategy) => (0, IRegistration_1.registerPipe)((p) => p.onResolved(runHooks(strategy)));
|
|
23
27
|
exports.resolved = resolved;
|
|
@@ -1,20 +1,18 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.OnDisposeModule = exports.onScopeDisposed =
|
|
3
|
+
exports.OnDisposeModule = exports.onScopeDisposed = void 0;
|
|
4
4
|
const hook_1 = require("./hook");
|
|
5
|
-
const HooksRunner_1 = require("./HooksRunner");
|
|
6
|
-
exports.onScopeDisposedHooksRunner = new HooksRunner_1.HooksRunner('onScopeDisposed');
|
|
7
5
|
const onScopeDisposed = (...fns) => (0, hook_1.hook)('onScopeDisposed', (0, hook_1.prependHooks)(...fns));
|
|
8
6
|
exports.onScopeDisposed = onScopeDisposed;
|
|
9
7
|
class OnDisposeModule {
|
|
10
|
-
|
|
11
|
-
constructor(
|
|
12
|
-
this.
|
|
8
|
+
strategy;
|
|
9
|
+
constructor(strategy) {
|
|
10
|
+
this.strategy = strategy;
|
|
13
11
|
}
|
|
14
12
|
applyTo(container) {
|
|
15
|
-
container.
|
|
13
|
+
container.scopeDisposed.subscribe((scope) => {
|
|
16
14
|
for (const instance of scope.getInstances()) {
|
|
17
|
-
|
|
15
|
+
this.strategy.execute(instance, { scope });
|
|
18
16
|
}
|
|
19
17
|
});
|
|
20
18
|
}
|
|
@@ -1,14 +1,7 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.
|
|
4
|
-
const HooksRunner_1 = require("./HooksRunner");
|
|
3
|
+
exports.oncePerInstance = void 0;
|
|
5
4
|
const hook_1 = require("./hook");
|
|
6
|
-
const basic_1 = require("../utils/basic");
|
|
7
|
-
const invokeMethod = (context) => {
|
|
8
|
-
context.invokeMethod();
|
|
9
|
-
};
|
|
10
|
-
exports.invokeMethod = invokeMethod;
|
|
11
|
-
const toHooks = (hooks) => (hooks.length > 0 ? hooks : [exports.invokeMethod]);
|
|
12
5
|
const oncePerInstance = (execute) => {
|
|
13
6
|
const invokedInstances = new WeakSet();
|
|
14
7
|
return (context) => {
|
|
@@ -20,13 +13,3 @@ const oncePerInstance = (execute) => {
|
|
|
20
13
|
};
|
|
21
14
|
};
|
|
22
15
|
exports.oncePerInstance = oncePerInstance;
|
|
23
|
-
const resolvedHook = (key) => (...hooks) => (0, hook_1.hook)(key, (0, hook_1.prependHooks)(...toHooks(hooks)));
|
|
24
|
-
exports.resolvedHook = resolvedHook;
|
|
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, onException) => (dependency, scope) => (0, HooksRunner_1.runHooks)(runner, dependency, scope, onException);
|
|
32
|
-
exports.executeHooks = executeHooks;
|
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.throttle = exports.handleAsyncError = exports.handleError = exports.getMethodTags = exports.addMethodTag = exports.getMethodLabels = exports.addMethodLabel = exports.getMethodMeta = exports.addMethodMeta = exports.getParamTags = exports.addParamTag = exports.getParamLabels = exports.addParamLabel = exports.getParamMeta = exports.addParamMeta = exports.getClassTags = exports.addClassTag = exports.getClassLabels = exports.addClassLabel = exports.getClassMeta = exports.addClassMeta = exports.resolveConstructor = exports.GroupInstanceToken = exports.ConstantToken = exports.FunctionToken = exports.SingleToken = exports.ClassToken = exports.toSingleAlias = exports.SingleAliasToken = exports.toGroupAlias = exports.GroupAliasToken = exports.argToToken = exports.toMappedToken = exports.toToken = exports.InjectionToken = exports.
|
|
5
|
-
exports.Is = exports.unwrapProxy = exports.ProxyRegistry = exports.pipe = exports.select = exports.once = exports.shallowCache = exports.debounce = void 0;
|
|
3
|
+
exports.createHookContextFactory = exports.HookContext = exports.prepend = exports.append = exports.prependHooks = exports.appendHooks = exports.hasHooks = exports.hook = exports.getHooks = exports.TypedEventDisposedError = exports.UnsupportedTokenTypeError = exports.CannonSingletonApplyTwiceError = exports.ProviderDisposedError = exports.ContainerDisposedError = exports.MethodNotImplementedError = exports.DependencyMissingKeyError = exports.ContainerNotFoundError = exports.DependencyNotFoundError = exports.ContainerError = exports.Registration = exports.onResolve = exports.appendArgsFn = exports.appendArgs = exports.decorate = exports.singleton = exports.autoResolve = exports.lazy = exports.scopeAccess = exports.scope = exports.bindTo = exports.register = exports.toRegistrationFn = exports.toProviderFn = exports.toBindToken = exports.registerPipe = exports.isProviderPipe = exports.Provider = exports.ProxyInjector = exports.SimpleInjector = exports.resolveArgs = exports.argsFn = exports.args = exports.arg = exports.inject = exports.MetadataInjector = exports.Injector = exports.EmptyContainer = exports.AutoResolveModule = exports.Container = exports.isDependencyKey = void 0;
|
|
4
|
+
exports.throttle = exports.handleAsyncError = exports.handleError = exports.getMethodTags = exports.addMethodTag = exports.getMethodLabels = exports.addMethodLabel = exports.getMethodMeta = exports.addMethodMeta = exports.getParamTags = exports.addParamTag = exports.getParamLabels = exports.addParamLabel = exports.getParamMeta = exports.addParamMeta = exports.getClassTags = exports.addClassTag = exports.getClassLabels = exports.addClassLabel = exports.getClassMeta = exports.addClassMeta = exports.resolveConstructor = exports.GroupInstanceToken = exports.ConstantToken = exports.FunctionToken = exports.SingleToken = exports.ClassToken = exports.toSingleAlias = exports.SingleAliasToken = exports.toGroupAlias = exports.GroupAliasToken = exports.argToToken = exports.toMappedToken = exports.toToken = exports.InjectionToken = exports.ParallelAsync = exports.SequentialAsync = exports.SequentialSync = exports.AsyncHookExecutionStrategy = exports.HookExecutionStrategy = exports.oncePerInstance = exports.resolved = exports.OnResolvedModule = exports.onResolved = exports.OnDisposeModule = exports.onScopeDisposed = exports.OnConstructModule = exports.onConstruct = exports.injectProp = exports.createHookExecutionContext = void 0;
|
|
5
|
+
exports.Is = exports.unwrapProxy = exports.ProxyRegistry = exports.pipe = exports.select = exports.TypedEvent = exports.once = exports.shallowCache = exports.debounce = 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");
|
|
@@ -63,6 +63,8 @@ var CannonSingletonApplyTwiceError_1 = require("./errors/CannonSingletonApplyTwi
|
|
|
63
63
|
Object.defineProperty(exports, "CannonSingletonApplyTwiceError", { enumerable: true, get: function () { return CannonSingletonApplyTwiceError_1.CannonSingletonApplyTwiceError; } });
|
|
64
64
|
var UnsupportedTokenTypeError_1 = require("./errors/UnsupportedTokenTypeError");
|
|
65
65
|
Object.defineProperty(exports, "UnsupportedTokenTypeError", { enumerable: true, get: function () { return UnsupportedTokenTypeError_1.UnsupportedTokenTypeError; } });
|
|
66
|
+
var TypedEventDisposedError_1 = require("./errors/TypedEventDisposedError");
|
|
67
|
+
Object.defineProperty(exports, "TypedEventDisposedError", { enumerable: true, get: function () { return TypedEventDisposedError_1.TypedEventDisposedError; } });
|
|
66
68
|
var hook_1 = require("./hooks/hook");
|
|
67
69
|
Object.defineProperty(exports, "getHooks", { enumerable: true, get: function () { return hook_1.getHooks; } });
|
|
68
70
|
Object.defineProperty(exports, "hook", { enumerable: true, get: function () { return hook_1.hook; } });
|
|
@@ -74,28 +76,31 @@ Object.defineProperty(exports, "prepend", { enumerable: true, get: function () {
|
|
|
74
76
|
var HookContext_1 = require("./hooks/HookContext");
|
|
75
77
|
Object.defineProperty(exports, "HookContext", { enumerable: true, get: function () { return HookContext_1.HookContext; } });
|
|
76
78
|
Object.defineProperty(exports, "createHookContextFactory", { enumerable: true, get: function () { return HookContext_1.createHookContextFactory; } });
|
|
77
|
-
Object.defineProperty(exports, "
|
|
79
|
+
Object.defineProperty(exports, "createHookExecutionContext", { enumerable: true, get: function () { return HookContext_1.createHookExecutionContext; } });
|
|
78
80
|
var injectProp_1 = require("./hooks/injectProp");
|
|
79
81
|
Object.defineProperty(exports, "injectProp", { enumerable: true, get: function () { return injectProp_1.injectProp; } });
|
|
80
82
|
var onConstruct_1 = require("./hooks/onConstruct");
|
|
81
|
-
Object.defineProperty(exports, "onConstructHooksRunner", { enumerable: true, get: function () { return onConstruct_1.onConstructHooksRunner; } });
|
|
82
83
|
Object.defineProperty(exports, "onConstruct", { enumerable: true, get: function () { return onConstruct_1.onConstruct; } });
|
|
83
84
|
Object.defineProperty(exports, "OnConstructModule", { enumerable: true, get: function () { return onConstruct_1.OnConstructModule; } });
|
|
84
85
|
var onScopeDisposed_1 = require("./hooks/onScopeDisposed");
|
|
85
|
-
Object.defineProperty(exports, "onScopeDisposedHooksRunner", { enumerable: true, get: function () { return onScopeDisposed_1.onScopeDisposedHooksRunner; } });
|
|
86
86
|
Object.defineProperty(exports, "onScopeDisposed", { enumerable: true, get: function () { return onScopeDisposed_1.onScopeDisposed; } });
|
|
87
87
|
Object.defineProperty(exports, "OnDisposeModule", { enumerable: true, get: function () { return onScopeDisposed_1.OnDisposeModule; } });
|
|
88
88
|
var onResolved_1 = require("./hooks/onResolved");
|
|
89
|
-
Object.defineProperty(exports, "onResolvedHooksRunner", { enumerable: true, get: function () { return onResolved_1.onResolvedHooksRunner; } });
|
|
90
89
|
Object.defineProperty(exports, "onResolved", { enumerable: true, get: function () { return onResolved_1.onResolved; } });
|
|
91
90
|
Object.defineProperty(exports, "OnResolvedModule", { enumerable: true, get: function () { return onResolved_1.OnResolvedModule; } });
|
|
92
91
|
Object.defineProperty(exports, "resolved", { enumerable: true, get: function () { return onResolved_1.resolved; } });
|
|
93
92
|
var resolveHooks_1 = require("./hooks/resolveHooks");
|
|
94
|
-
Object.defineProperty(exports, "invokeMethod", { enumerable: true, get: function () { return resolveHooks_1.invokeMethod; } });
|
|
95
93
|
Object.defineProperty(exports, "oncePerInstance", { enumerable: true, get: function () { return resolveHooks_1.oncePerInstance; } });
|
|
96
|
-
var
|
|
97
|
-
Object.defineProperty(exports, "
|
|
98
|
-
|
|
94
|
+
var HookExecutionStrategy_1 = require("./hooks/HookExecutionStrategy");
|
|
95
|
+
Object.defineProperty(exports, "HookExecutionStrategy", { enumerable: true, get: function () { return HookExecutionStrategy_1.HookExecutionStrategy; } });
|
|
96
|
+
var AsyncHookExecutionStrategy_1 = require("./hooks/AsyncHookExecutionStrategy");
|
|
97
|
+
Object.defineProperty(exports, "AsyncHookExecutionStrategy", { enumerable: true, get: function () { return AsyncHookExecutionStrategy_1.AsyncHookExecutionStrategy; } });
|
|
98
|
+
var SequentialSync_1 = require("./hooks/SequentialSync");
|
|
99
|
+
Object.defineProperty(exports, "SequentialSync", { enumerable: true, get: function () { return SequentialSync_1.SequentialSync; } });
|
|
100
|
+
var SequentialAsync_1 = require("./hooks/SequentialAsync");
|
|
101
|
+
Object.defineProperty(exports, "SequentialAsync", { enumerable: true, get: function () { return SequentialAsync_1.SequentialAsync; } });
|
|
102
|
+
var ParallelAsync_1 = require("./hooks/ParallelAsync");
|
|
103
|
+
Object.defineProperty(exports, "ParallelAsync", { enumerable: true, get: function () { return ParallelAsync_1.ParallelAsync; } });
|
|
99
104
|
var InjectionToken_1 = require("./token/InjectionToken");
|
|
100
105
|
Object.defineProperty(exports, "InjectionToken", { enumerable: true, get: function () { return InjectionToken_1.InjectionToken; } });
|
|
101
106
|
var toToken_1 = require("./token/toToken");
|
|
@@ -152,6 +157,8 @@ var shallowCache_1 = require("./utils/shallowCache");
|
|
|
152
157
|
Object.defineProperty(exports, "shallowCache", { enumerable: true, get: function () { return shallowCache_1.shallowCache; } });
|
|
153
158
|
var once_1 = require("./utils/once");
|
|
154
159
|
Object.defineProperty(exports, "once", { enumerable: true, get: function () { return once_1.once; } });
|
|
160
|
+
var TypedEvent_1 = require("./utils/TypedEvent");
|
|
161
|
+
Object.defineProperty(exports, "TypedEvent", { enumerable: true, get: function () { return TypedEvent_1.TypedEvent; } });
|
|
155
162
|
var select_1 = require("./select");
|
|
156
163
|
Object.defineProperty(exports, "select", { enumerable: true, get: function () { return select_1.select; } });
|
|
157
164
|
var fp_1 = require("./utils/fp");
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.TypedEvent = void 0;
|
|
4
|
+
const TypedEventDisposedError_1 = require("../errors/TypedEventDisposedError");
|
|
5
|
+
class TypedEvent {
|
|
6
|
+
listeners = new Set();
|
|
7
|
+
isDisposed = false;
|
|
8
|
+
subscribe(listener) {
|
|
9
|
+
this.validate();
|
|
10
|
+
this.listeners.add(listener);
|
|
11
|
+
return () => this.unsubscribe(listener);
|
|
12
|
+
}
|
|
13
|
+
unsubscribe(listener) {
|
|
14
|
+
this.listeners.delete(listener);
|
|
15
|
+
}
|
|
16
|
+
emit(...args) {
|
|
17
|
+
this.validate();
|
|
18
|
+
for (const listener of [...this.listeners]) {
|
|
19
|
+
if (this.listeners.has(listener)) {
|
|
20
|
+
listener(...args);
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
getListeners() {
|
|
25
|
+
return [...this.listeners];
|
|
26
|
+
}
|
|
27
|
+
dispose() {
|
|
28
|
+
this.listeners.clear();
|
|
29
|
+
this.isDisposed = true;
|
|
30
|
+
}
|
|
31
|
+
validate() {
|
|
32
|
+
TypedEventDisposedError_1.TypedEventDisposedError.assert(!this.isDisposed, 'TypedEvent is already disposed');
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
exports.TypedEvent = TypedEvent;
|
|
@@ -6,6 +6,7 @@ import { unwrapProxy } from '../utils/ProxyRegistry.js';
|
|
|
6
6
|
import { DependencyNotFoundError } from '../errors/DependencyNotFoundError.js';
|
|
7
7
|
import { Is } from '../utils/basic.js';
|
|
8
8
|
import { Filter as F } from '../utils/array.js';
|
|
9
|
+
import { TypedEvent } from '../utils/TypedEvent.js';
|
|
9
10
|
export class Container {
|
|
10
11
|
isDisposed = false;
|
|
11
12
|
parent;
|
|
@@ -16,9 +17,12 @@ export class Container {
|
|
|
16
17
|
providers = new Map();
|
|
17
18
|
aliases = new AliasMap();
|
|
18
19
|
injector;
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
20
|
+
scopeCreatedEvent = new TypedEvent();
|
|
21
|
+
scopeDisposedEvent = new TypedEvent();
|
|
22
|
+
registeredEvent = new TypedEvent();
|
|
23
|
+
scopeCreated = this.scopeCreatedEvent;
|
|
24
|
+
scopeDisposed = this.scopeDisposedEvent;
|
|
25
|
+
registered = this.registeredEvent;
|
|
22
26
|
constructor(options = {}) {
|
|
23
27
|
this.injector = options.injector ?? new MetadataInjector();
|
|
24
28
|
this.parent = options.parent ?? new EmptyContainer();
|
|
@@ -28,9 +32,7 @@ export class Container {
|
|
|
28
32
|
this.validateContainer();
|
|
29
33
|
this.providers.set(key, provider);
|
|
30
34
|
this.aliases.setAliasesByKey(key, aliases);
|
|
31
|
-
|
|
32
|
-
onRegistered(provider, key, this);
|
|
33
|
-
}
|
|
35
|
+
this.registeredEvent.emit(provider, key, this);
|
|
34
36
|
return this;
|
|
35
37
|
}
|
|
36
38
|
resolve(target, { args = [], child = this, lazy } = {}) {
|
|
@@ -73,17 +75,15 @@ export class Container {
|
|
|
73
75
|
}
|
|
74
76
|
createScope({ tags } = {}) {
|
|
75
77
|
this.validateContainer();
|
|
76
|
-
const scope = new Container({ injector: this.injector, parent: this, tags })
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
78
|
+
const scope = new Container({ injector: this.injector, parent: this, tags });
|
|
79
|
+
this.scopeCreatedEvent.getListeners().forEach((hook) => scope.scopeCreatedEvent.subscribe(hook));
|
|
80
|
+
this.scopeDisposedEvent.getListeners().forEach((hook) => scope.scopeDisposedEvent.subscribe(hook));
|
|
81
|
+
this.registeredEvent.getListeners().forEach((hook) => scope.registeredEvent.subscribe(hook));
|
|
80
82
|
for (const registration of this.getRegistrations()) {
|
|
81
83
|
registration.applyTo(scope);
|
|
82
84
|
}
|
|
83
85
|
this.scopes.push(scope);
|
|
84
|
-
|
|
85
|
-
onScopeCreated(scope);
|
|
86
|
-
}
|
|
86
|
+
this.scopeCreatedEvent.emit(scope);
|
|
87
87
|
return scope;
|
|
88
88
|
}
|
|
89
89
|
autoResolve({ args = [] } = {}) {
|
|
@@ -98,9 +98,7 @@ export class Container {
|
|
|
98
98
|
dispose() {
|
|
99
99
|
this.validateContainer();
|
|
100
100
|
this.isDisposed = true;
|
|
101
|
-
|
|
102
|
-
onScopeDisposed(this);
|
|
103
|
-
}
|
|
101
|
+
this.scopeDisposedEvent.emit(this);
|
|
104
102
|
this.parent.removeScope(this);
|
|
105
103
|
this.parent = new EmptyContainer();
|
|
106
104
|
for (const provider of this.providers.values()) {
|
|
@@ -110,9 +108,9 @@ export class Container {
|
|
|
110
108
|
this.aliases.destroy();
|
|
111
109
|
this.instances.clear();
|
|
112
110
|
this.registrations = [];
|
|
113
|
-
this.
|
|
114
|
-
this.
|
|
115
|
-
this.
|
|
111
|
+
this.scopeCreatedEvent.dispose();
|
|
112
|
+
this.scopeDisposedEvent.dispose();
|
|
113
|
+
this.registeredEvent.dispose();
|
|
116
114
|
}
|
|
117
115
|
addRegistration(registration) {
|
|
118
116
|
this.registrations.push(registration);
|
|
@@ -122,21 +120,12 @@ export class Container {
|
|
|
122
120
|
getRegistrations() {
|
|
123
121
|
return [...this.parent.getRegistrations(), ...this.registrations];
|
|
124
122
|
}
|
|
123
|
+
getInjector() {
|
|
124
|
+
return this.injector;
|
|
125
|
+
}
|
|
125
126
|
hasRegistration(key) {
|
|
126
127
|
return this.registrations.some((r) => r.getKeyOrFail() === key) || this.parent.hasRegistration(key);
|
|
127
128
|
}
|
|
128
|
-
onScopeCreated(...hooks) {
|
|
129
|
-
this.onScopeCreatedHookList.push(...hooks);
|
|
130
|
-
return this;
|
|
131
|
-
}
|
|
132
|
-
onScopeDisposed(...hooks) {
|
|
133
|
-
this.onScopeDisposedHookList.push(...hooks);
|
|
134
|
-
return this;
|
|
135
|
-
}
|
|
136
|
-
onRegistered(...hooks) {
|
|
137
|
-
this.onRegisteredHookList.push(...hooks);
|
|
138
|
-
return this;
|
|
139
|
-
}
|
|
140
129
|
addInstance(instance) {
|
|
141
130
|
this.instances.add(instance);
|
|
142
131
|
}
|
|
@@ -20,6 +20,9 @@ export class EmptyContainer {
|
|
|
20
20
|
createScope() {
|
|
21
21
|
throw new MethodNotImplementedError();
|
|
22
22
|
}
|
|
23
|
+
getInjector() {
|
|
24
|
+
throw new MethodNotImplementedError();
|
|
25
|
+
}
|
|
23
26
|
autoResolve(options) {
|
|
24
27
|
throw new MethodNotImplementedError();
|
|
25
28
|
}
|
|
@@ -57,13 +60,13 @@ export class EmptyContainer {
|
|
|
57
60
|
resolveOneByAlias(alias, options) {
|
|
58
61
|
throw new DependencyNotFoundError(`Cannot find alias ${alias.toString()}`);
|
|
59
62
|
}
|
|
60
|
-
|
|
63
|
+
get scopeCreated() {
|
|
61
64
|
throw new MethodNotImplementedError();
|
|
62
65
|
}
|
|
63
|
-
|
|
66
|
+
get scopeDisposed() {
|
|
64
67
|
throw new MethodNotImplementedError();
|
|
65
68
|
}
|
|
66
|
-
|
|
69
|
+
get registered() {
|
|
67
70
|
throw new MethodNotImplementedError();
|
|
68
71
|
}
|
|
69
72
|
}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { ContainerError } from './ContainerError.js';
|
|
2
|
+
export class TypedEventDisposedError extends ContainerError {
|
|
3
|
+
name = 'TypedEventDisposedError';
|
|
4
|
+
static assert(isTrue, failMessage) {
|
|
5
|
+
if (!isTrue) {
|
|
6
|
+
throw new TypedEventDisposedError(failMessage);
|
|
7
|
+
}
|
|
8
|
+
}
|
|
9
|
+
constructor(message) {
|
|
10
|
+
super(message);
|
|
11
|
+
Object.setPrototypeOf(this, TypedEventDisposedError.prototype);
|
|
12
|
+
}
|
|
13
|
+
}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { HookExecutionStrategy, runAtOnce, runInOrder, } from './HookExecutionStrategy.js';
|
|
2
|
+
export class AsyncHookExecutionStrategy extends HookExecutionStrategy {
|
|
3
|
+
methodStrategy;
|
|
4
|
+
constructor({ methodStrategy = 'sequential', ...props }) {
|
|
5
|
+
super(props);
|
|
6
|
+
this.methodStrategy = methodStrategy;
|
|
7
|
+
}
|
|
8
|
+
runMember({ hooks, context }) {
|
|
9
|
+
return this.methodStrategy === 'parallel' ? runAtOnce(hooks, context) : runInOrder(hooks, context);
|
|
10
|
+
}
|
|
11
|
+
}
|
package/esm/hooks/HookContext.js
CHANGED
|
@@ -31,5 +31,5 @@ export class HookContext {
|
|
|
31
31
|
return this.initialArgs;
|
|
32
32
|
}
|
|
33
33
|
}
|
|
34
|
-
export const
|
|
35
|
-
export const createHookContextFactory = ({ args = [] } = {}) => (Target, scope, methodName) =>
|
|
34
|
+
export const createHookExecutionContext = (Target, scope, methodName = 'constructor') => new HookContext(Target, scope, methodName);
|
|
35
|
+
export const createHookContextFactory = ({ args = [] } = {}) => (Target, scope, methodName) => createHookExecutionContext(Target, scope, methodName).setInitialArgs(...args);
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
import { resolveConstructor } from '../metadata/target.js';
|
|
2
|
+
import { getHooks, hasHooks, toHookFn } from './hook.js';
|
|
3
|
+
import { createHookExecutionContext } from './HookContext.js';
|
|
4
|
+
export const runInOrder = (hooks, context, from = 0) => {
|
|
5
|
+
for (let i = from; i < hooks.length; i++) {
|
|
6
|
+
const result = hooks[i](context);
|
|
7
|
+
if (result instanceof Promise) {
|
|
8
|
+
return result.then(() => runInOrder(hooks, context, i + 1));
|
|
9
|
+
}
|
|
10
|
+
}
|
|
11
|
+
};
|
|
12
|
+
export const runAtOnce = (hooks, context) => {
|
|
13
|
+
const pending = [];
|
|
14
|
+
for (const hook of hooks) {
|
|
15
|
+
const result = hook(context);
|
|
16
|
+
if (result instanceof Promise) {
|
|
17
|
+
pending.push(result);
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
return pending.length > 0 ? Promise.all(pending).then(() => undefined) : undefined;
|
|
21
|
+
};
|
|
22
|
+
export class HookExecutionStrategy {
|
|
23
|
+
key;
|
|
24
|
+
onError;
|
|
25
|
+
options;
|
|
26
|
+
hooksByClass = new WeakMap();
|
|
27
|
+
constructor({ key, onError, createExecutionContext = createHookExecutionContext, mapExecutionContext = (context) => context, predicate = () => true, }) {
|
|
28
|
+
this.key = key;
|
|
29
|
+
this.onError = onError;
|
|
30
|
+
this.options = { createExecutionContext, mapExecutionContext, predicate };
|
|
31
|
+
}
|
|
32
|
+
hasHooks(target) {
|
|
33
|
+
return hasHooks(target, this.key);
|
|
34
|
+
}
|
|
35
|
+
execute(target, { scope, ...overrides }) {
|
|
36
|
+
const report = (ex) => this.onError?.(scope)(ex);
|
|
37
|
+
try {
|
|
38
|
+
this.processHooks(this.collect(target, scope, overrides))?.catch(report);
|
|
39
|
+
}
|
|
40
|
+
catch (ex) {
|
|
41
|
+
report(ex);
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
collect(target, scope, { createExecutionContext = this.options.createExecutionContext, mapExecutionContext = this.options.mapExecutionContext, predicate = this.options.predicate, }) {
|
|
45
|
+
const members = [];
|
|
46
|
+
for (const { methodName, hooks } of this.hooksOf(target)) {
|
|
47
|
+
if (predicate(methodName)) {
|
|
48
|
+
members.push({ hooks, context: mapExecutionContext(createExecutionContext(target, scope, methodName)) });
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
return members;
|
|
52
|
+
}
|
|
53
|
+
hooksOf(target) {
|
|
54
|
+
const Target = resolveConstructor(target);
|
|
55
|
+
let hooks = this.hooksByClass.get(Target);
|
|
56
|
+
if (!hooks) {
|
|
57
|
+
hooks = Array.from(getHooks(Target, this.key), ([methodName, fns]) => ({ methodName, hooks: fns.map(toHookFn) }));
|
|
58
|
+
this.hooksByClass.set(Target, hooks);
|
|
59
|
+
}
|
|
60
|
+
return hooks;
|
|
61
|
+
}
|
|
62
|
+
}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { AsyncHookExecutionStrategy } from './AsyncHookExecutionStrategy.js';
|
|
2
|
+
export class ParallelAsync extends AsyncHookExecutionStrategy {
|
|
3
|
+
processHooks(members) {
|
|
4
|
+
const pending = [];
|
|
5
|
+
for (const member of members) {
|
|
6
|
+
const result = this.runMember(member);
|
|
7
|
+
if (result) {
|
|
8
|
+
pending.push(result);
|
|
9
|
+
}
|
|
10
|
+
}
|
|
11
|
+
return pending.length > 0 ? Promise.all(pending).then(() => undefined) : undefined;
|
|
12
|
+
}
|
|
13
|
+
}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { AsyncHookExecutionStrategy } from './AsyncHookExecutionStrategy.js';
|
|
2
|
+
export class SequentialAsync extends AsyncHookExecutionStrategy {
|
|
3
|
+
processHooks(members, from = 0) {
|
|
4
|
+
for (let i = from; i < members.length; i++) {
|
|
5
|
+
const result = this.runMember(members[i]);
|
|
6
|
+
if (result) {
|
|
7
|
+
return result.then(() => this.processHooks(members, i + 1));
|
|
8
|
+
}
|
|
9
|
+
}
|
|
10
|
+
}
|
|
11
|
+
}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { HookExecutionStrategy } from './HookExecutionStrategy.js';
|
|
2
|
+
export class SequentialSync extends HookExecutionStrategy {
|
|
3
|
+
processHooks(members) {
|
|
4
|
+
for (const { hooks, context } of members) {
|
|
5
|
+
for (const hook of hooks) {
|
|
6
|
+
hook(context);
|
|
7
|
+
}
|
|
8
|
+
}
|
|
9
|
+
}
|
|
10
|
+
}
|
package/esm/hooks/onConstruct.js
CHANGED
|
@@ -1,15 +1,13 @@
|
|
|
1
1
|
import { hook, prependHooks } from './hook.js';
|
|
2
|
-
import { HooksRunner, runHooks } from './HooksRunner.js';
|
|
3
|
-
export const onConstructHooksRunner = new HooksRunner('onConstruct');
|
|
4
2
|
export const onConstruct = (...fns) => hook('onConstruct', prependHooks(...fns));
|
|
5
3
|
export class OnConstructModule {
|
|
6
|
-
|
|
7
|
-
constructor(
|
|
8
|
-
this.
|
|
4
|
+
strategy;
|
|
5
|
+
constructor(strategy) {
|
|
6
|
+
this.strategy = strategy;
|
|
9
7
|
}
|
|
10
|
-
applyTo(
|
|
11
|
-
|
|
12
|
-
|
|
8
|
+
applyTo(container) {
|
|
9
|
+
container.getInjector().onConstructed((instance, scope) => {
|
|
10
|
+
this.strategy.execute(instance, { scope });
|
|
13
11
|
});
|
|
14
12
|
}
|
|
15
13
|
}
|
package/esm/hooks/onResolved.js
CHANGED
|
@@ -1,18 +1,21 @@
|
|
|
1
|
-
import { HooksRunner } from './HooksRunner.js';
|
|
2
1
|
import { registerPipe } from '../registration/IRegistration.js';
|
|
3
|
-
import {
|
|
4
|
-
|
|
5
|
-
export const onResolved =
|
|
6
|
-
const runHooks = (
|
|
2
|
+
import { Is } from '../utils/basic.js';
|
|
3
|
+
import { hook, prependHooks } from './hook.js';
|
|
4
|
+
export const onResolved = (...hooks) => hook('onResolved', prependHooks(...hooks));
|
|
5
|
+
const runHooks = (strategy) => (dependency, scope) => {
|
|
6
|
+
if (Is.object(dependency)) {
|
|
7
|
+
strategy.execute(dependency, { scope });
|
|
8
|
+
}
|
|
9
|
+
};
|
|
7
10
|
export class OnResolvedModule {
|
|
8
11
|
runHooks;
|
|
9
|
-
constructor(
|
|
10
|
-
this.runHooks = runHooks(
|
|
12
|
+
constructor(strategy) {
|
|
13
|
+
this.runHooks = runHooks(strategy);
|
|
11
14
|
}
|
|
12
15
|
applyTo(container) {
|
|
13
|
-
container.
|
|
16
|
+
container.registered.subscribe((provider) => {
|
|
14
17
|
provider.onResolved(this.runHooks);
|
|
15
18
|
});
|
|
16
19
|
}
|
|
17
20
|
}
|
|
18
|
-
export const resolved = (
|
|
21
|
+
export const resolved = (strategy) => registerPipe((p) => p.onResolved(runHooks(strategy)));
|
|
@@ -1,16 +1,14 @@
|
|
|
1
1
|
import { hook, prependHooks } from './hook.js';
|
|
2
|
-
import { HooksRunner, runHooks } from './HooksRunner.js';
|
|
3
|
-
export const onScopeDisposedHooksRunner = new HooksRunner('onScopeDisposed');
|
|
4
2
|
export const onScopeDisposed = (...fns) => hook('onScopeDisposed', prependHooks(...fns));
|
|
5
3
|
export class OnDisposeModule {
|
|
6
|
-
|
|
7
|
-
constructor(
|
|
8
|
-
this.
|
|
4
|
+
strategy;
|
|
5
|
+
constructor(strategy) {
|
|
6
|
+
this.strategy = strategy;
|
|
9
7
|
}
|
|
10
8
|
applyTo(container) {
|
|
11
|
-
container.
|
|
9
|
+
container.scopeDisposed.subscribe((scope) => {
|
|
12
10
|
for (const instance of scope.getInstances()) {
|
|
13
|
-
|
|
11
|
+
this.strategy.execute(instance, { scope });
|
|
14
12
|
}
|
|
15
13
|
});
|
|
16
14
|
}
|
|
@@ -1,10 +1,4 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { hook, prependHooks, toHookFn } from './hook.js';
|
|
3
|
-
import { Is } from '../utils/basic.js';
|
|
4
|
-
export const invokeMethod = (context) => {
|
|
5
|
-
context.invokeMethod();
|
|
6
|
-
};
|
|
7
|
-
const toHooks = (hooks) => (hooks.length > 0 ? hooks : [invokeMethod]);
|
|
1
|
+
import { toHookFn } from './hook.js';
|
|
8
2
|
export const oncePerInstance = (execute) => {
|
|
9
3
|
const invokedInstances = new WeakSet();
|
|
10
4
|
return (context) => {
|
|
@@ -15,10 +9,3 @@ export const oncePerInstance = (execute) => {
|
|
|
15
9
|
return toHookFn(execute)(context);
|
|
16
10
|
};
|
|
17
11
|
};
|
|
18
|
-
export const resolvedHook = (key) => (...hooks) => hook(key, prependHooks(...toHooks(hooks)));
|
|
19
|
-
export const forEachResolvedObject = (run) => (dependency, scope) => {
|
|
20
|
-
if (Is.object(dependency)) {
|
|
21
|
-
run(dependency, scope);
|
|
22
|
-
}
|
|
23
|
-
};
|
|
24
|
-
export const executeHooks = (runner, onException) => (dependency, scope) => runHooks(runner, dependency, scope, onException);
|