awilixify 3.0.0 → 3.1.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 +5 -2
- package/dist/index.d.ts +2 -1
- package/dist/lib/devtools/devtools.types.d.ts +63 -0
- package/dist/lib/devtools/devtools.types.js +1 -0
- package/dist/lib/devtools/helpers.d.ts +2 -0
- package/dist/lib/devtools/helpers.js +18 -0
- package/dist/lib/devtools/index.d.ts +4 -0
- package/dist/lib/devtools/index.js +3 -0
- package/dist/lib/di/contexts/container-context-base.d.ts +13 -3
- package/dist/lib/di/contexts/container-context-base.js +45 -7
- package/dist/lib/di/contexts/di-context-async.js +15 -9
- package/dist/lib/di/contexts/di-context-base.js +5 -4
- package/dist/lib/di/contexts/module-graph-ensurer.d.ts +1 -0
- package/dist/lib/di/contexts/module-graph-ensurer.js +5 -0
- package/dist/lib/di/errors.d.ts +3 -0
- package/dist/lib/di/errors.js +6 -0
- package/dist/lib/di/modules/module-factories.js +9 -1
- package/dist/lib/di/modules/runtime-module.types.d.ts +7 -0
- package/dist/lib/di/processors/handler-processor.d.ts +5 -1
- package/dist/lib/di/processors/handler-processor.js +41 -7
- package/dist/lib/di/processors/initializer-processor.d.ts +3 -2
- package/dist/lib/di/processors/initializer-processor.js +33 -29
- package/dist/lib/di/processors/interceptor-processor.d.ts +4 -1
- package/dist/lib/di/processors/interceptor-processor.js +18 -2
- package/dist/lib/di/processors/keyed-feature-registrar.js +1 -1
- package/dist/lib/di/processors/lifecycle-processor.d.ts +0 -1
- package/dist/lib/di/processors/lifecycle-processor.js +1 -4
- package/dist/lib/di/providers/provider-resolver.d.ts +7 -3
- package/dist/lib/di/providers/provider-resolver.js +56 -16
- package/dist/lib/di/providers/types/provider.types.d.ts +5 -5
- package/dist/lib/mediator/mediator.d.ts +4 -1
- package/dist/lib/mediator/mediator.js +13 -2
- package/dist/lib/react/index.d.ts +4 -0
- package/dist/lib/react/index.js +4 -0
- package/dist/lib/react/react-di-context.d.ts +2 -7
- package/dist/lib/react/react-di-context.js +5 -8
- package/dist/lib/react/react-module.types.d.ts +5 -19
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/package.json +7 -3
- package/dist/lib/di/contexts/context-overrides.d.ts +0 -22
- package/dist/lib/di/contexts/context-overrides.js +0 -93
- package/dist/lib/di/contexts/module-overrides.d.ts +0 -70
- package/dist/lib/di/contexts/module-overrides.js +0 -3
- package/dist/lib/di/contexts/override-value.types.d.ts +0 -6
- package/dist/lib/di/contexts/override-value.types.js +0 -1
- package/dist/lib/di/contexts/overrides-processor.d.ts +0 -22
- package/dist/lib/di/contexts/overrides-processor.js +0 -93
- package/dist/lib/di/contexts/provider-overrides.types.d.ts +0 -19
- package/dist/lib/di/contexts/provider-overrides.types.js +0 -1
- package/dist/lib/di/modules/provider-overrides.types.d.ts +0 -19
- package/dist/lib/di/modules/provider-overrides.types.js +0 -1
- package/dist/lib/di/providers/basic-provider-resolver.d.ts +0 -35
- package/dist/lib/di/providers/basic-provider-resolver.js +0 -88
- package/dist/react.d.ts +0 -4
- package/dist/react.js +0 -4
package/README.md
CHANGED
|
@@ -7,8 +7,11 @@ Transport-agnostic, type-safe, modular DI and CQRS framework on top of [Awilix](
|
|
|
7
7
|
[](https://github.com/wildstyles/awilixify/actions)
|
|
8
8
|
[](https://codecov.io/gh/wildstyles/awilixify)
|
|
9
9
|
|
|
10
|
-
> [!
|
|
11
|
-
>
|
|
10
|
+
> [!TIP]
|
|
11
|
+
> 🤔 “Another JS framework?” Here are my attempts to convince you to give Awilixify a try:
|
|
12
|
+
>
|
|
13
|
+
> - [Awilixify: NestJS-Like Modular DI for Legacy Applications](https://medium.com/@r.vanzhula/awilixify-nestjs-like-modular-di-for-legacy-applications-db2a1e29c7de)
|
|
14
|
+
> - [Awilixify: Making Middlewares End-to-End Type-Safe](https://medium.com/@r.vanzhula/awilixify-making-middlewares-end-to-end-type-safe-b3f4dbfb6b42)
|
|
12
15
|
|
|
13
16
|
📚 Documentation: https://wildstyles.github.io/awilixify/
|
|
14
17
|
|
package/dist/index.d.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
export * from "./lib/decorators/decorator-state.js";
|
|
2
|
+
export type { DecoratorToken } from "./lib/decorators/decorator-state.types.js";
|
|
2
3
|
export type { ModuleScope } from "./lib/di/contexts/container-context-base.js";
|
|
3
4
|
export * from "./lib/di/contexts/di-context.js";
|
|
4
5
|
export * from "./lib/di/contexts/di-context-async.js";
|
|
@@ -7,7 +8,7 @@ export * from "./lib/di/modules/module-def.types.js";
|
|
|
7
8
|
export * from "./lib/di/modules/module-factories.js";
|
|
8
9
|
export * from "./lib/di/modules/module-overrides.js";
|
|
9
10
|
export * from "./lib/di/modules/module-ref.types.js";
|
|
10
|
-
export type { Controller, InitializerContext, InterceptContext, Interceptor, ProviderInit, } from "./lib/di/providers/provider.types.js";
|
|
11
|
+
export type { ConstructorController, Controller, InitializerContext, InterceptContext, Interceptor, ProviderInit, } from "./lib/di/providers/provider.types.js";
|
|
11
12
|
export { Initializer } from "./lib/di/providers/provider.types.js";
|
|
12
13
|
export { isResultLike } from "./lib/di/type-guards.js";
|
|
13
14
|
export * from "./lib/mediator/contract.types.js";
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
import type * as Awilix from "awilix";
|
|
2
|
+
import type { InternalModuleLike } from "../di/modules/runtime-module.types.js";
|
|
3
|
+
import type { ConstructorController, Initializer } from "../di/providers/provider.types.js";
|
|
4
|
+
export declare const AWILIXIFY_DEVTOOLS_PROCESSOR = "__awilixifyDevtoolsProcessor";
|
|
5
|
+
export type TraceSpanKind = "http" | "provider" | "handler" | "prehandler" | "interceptor" | "initializer";
|
|
6
|
+
export type RecordSpanInput<T> = {
|
|
7
|
+
kind: TraceSpanKind;
|
|
8
|
+
moduleName: string;
|
|
9
|
+
providerKey: string;
|
|
10
|
+
methodName: string;
|
|
11
|
+
args: unknown[];
|
|
12
|
+
callback: () => T | Promise<T>;
|
|
13
|
+
moduleId?: string;
|
|
14
|
+
};
|
|
15
|
+
export type WrapResolverInput = {
|
|
16
|
+
kind: TraceSpanKind;
|
|
17
|
+
module: InternalModuleLike;
|
|
18
|
+
options: Awilix.BuildResolverOptions<any>;
|
|
19
|
+
providerKey: string;
|
|
20
|
+
resolver: Awilix.Resolver<any>;
|
|
21
|
+
moduleId?: string;
|
|
22
|
+
isFactory?: boolean;
|
|
23
|
+
};
|
|
24
|
+
export type TraceInitializerInput<T = unknown> = {
|
|
25
|
+
args: unknown[];
|
|
26
|
+
callback: () => T | Promise<T>;
|
|
27
|
+
controllerName: string;
|
|
28
|
+
getStatusCode: () => number | undefined;
|
|
29
|
+
methodName: string;
|
|
30
|
+
moduleName: string;
|
|
31
|
+
};
|
|
32
|
+
export interface Tracer {
|
|
33
|
+
recordSpan<T>(input: RecordSpanInput<T>): T | Promise<T>;
|
|
34
|
+
traceInitializer<T>(input: TraceInitializerInput<T>): T | Promise<T>;
|
|
35
|
+
wrapResolver(input: WrapResolverInput): Awilix.Resolver<any>;
|
|
36
|
+
}
|
|
37
|
+
export type ModuleDecoratorMetadata = {
|
|
38
|
+
module: InternalModuleLike;
|
|
39
|
+
controllers: readonly {
|
|
40
|
+
controllerClass: ConstructorController;
|
|
41
|
+
}[];
|
|
42
|
+
initializers: readonly [string, () => Initializer<any, boolean>][];
|
|
43
|
+
};
|
|
44
|
+
export interface GraphCollector {
|
|
45
|
+
registerModule(input: {
|
|
46
|
+
module: InternalModuleLike;
|
|
47
|
+
scope: Awilix.AwilixContainer;
|
|
48
|
+
importedModules: readonly InternalModuleLike[];
|
|
49
|
+
}): string;
|
|
50
|
+
collectModuleRoutes(metadata: ModuleDecoratorMetadata): void;
|
|
51
|
+
}
|
|
52
|
+
export type DevtoolsProcessorContext = {
|
|
53
|
+
rootModule: InternalModuleLike;
|
|
54
|
+
globalModules: readonly InternalModuleLike[];
|
|
55
|
+
};
|
|
56
|
+
export interface DevtoolsProcessor {
|
|
57
|
+
graphCollector: GraphCollector;
|
|
58
|
+
tracer: Tracer;
|
|
59
|
+
initialize(context: DevtoolsProcessorContext): void;
|
|
60
|
+
}
|
|
61
|
+
export type DevtoolsProcessorRef = {
|
|
62
|
+
current?: DevtoolsProcessor;
|
|
63
|
+
};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export const AWILIXIFY_DEVTOOLS_PROCESSOR = "__awilixifyDevtoolsProcessor";
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
export function getControllerMethodNames(controllerClass) {
|
|
2
|
+
const collected = new Set();
|
|
3
|
+
let proto = controllerClass.prototype;
|
|
4
|
+
while (proto && proto !== Object.prototype) {
|
|
5
|
+
Object.getOwnPropertyNames(proto)
|
|
6
|
+
.filter((name) => name !== "constructor" && typeof proto[name] === "function")
|
|
7
|
+
.forEach((name) => {
|
|
8
|
+
collected.add(name);
|
|
9
|
+
});
|
|
10
|
+
Object.getOwnPropertySymbols(proto)
|
|
11
|
+
.filter((symbol) => typeof proto[symbol] === "function")
|
|
12
|
+
.forEach((symbol) => {
|
|
13
|
+
collected.add(symbol);
|
|
14
|
+
});
|
|
15
|
+
proto = Object.getPrototypeOf(proto);
|
|
16
|
+
}
|
|
17
|
+
return [...collected];
|
|
18
|
+
}
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
export type { InternalModuleLike } from "../di/modules/runtime-module.types.js";
|
|
2
|
+
export { hasInitAfter, hasUseClass, isCostructorProvider, isCostructorProvider as isConstructorProvider, isEagerProvider, isPromiseLike, isResultLike, } from "../di/type-guards.js";
|
|
3
|
+
export * from "./devtools.types.js";
|
|
4
|
+
export { getControllerMethodNames } from "./helpers.js";
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
export { hasInitAfter, hasUseClass, isCostructorProvider, isCostructorProvider as isConstructorProvider, isEagerProvider, isPromiseLike, isResultLike, } from "../di/type-guards.js";
|
|
2
|
+
export * from "./devtools.types.js";
|
|
3
|
+
export { getControllerMethodNames } from "./helpers.js";
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import * as Awilix from "awilix";
|
|
2
|
+
import { type DevtoolsProcessorRef } from "../../devtools/devtools.types.js";
|
|
2
3
|
import type { InternalModuleLike as M } from "../modules/runtime-module.types.js";
|
|
3
4
|
import { type LifecycleMethods, LifecycleProcessor } from "../processors/lifecycle-processor.js";
|
|
4
5
|
import { type OverrideOptions, OverridesProcessor } from "../processors/overrides-processor.js";
|
|
@@ -9,9 +10,9 @@ interface ScopeContext {
|
|
|
9
10
|
hasScopeContext: () => boolean;
|
|
10
11
|
resolveFromScope: <T>(scope: Awilix.AwilixContainer, key: string | symbol) => T;
|
|
11
12
|
}
|
|
12
|
-
export interface ContainerContextOptions extends OverrideOptions {
|
|
13
|
+
export interface ContainerContextOptions<Options extends Awilix.BuildResolverOptions<any> = Awilix.BuildResolverOptions<any>> extends OverrideOptions {
|
|
13
14
|
containerOptions?: Awilix.ContainerOptions;
|
|
14
|
-
providerOptions?:
|
|
15
|
+
providerOptions?: Options;
|
|
15
16
|
globalModules?: readonly M[];
|
|
16
17
|
}
|
|
17
18
|
export interface ModuleScope<S extends Awilix.AwilixContainer = Awilix.AwilixContainer> extends LifecycleMethods {
|
|
@@ -27,6 +28,7 @@ export declare abstract class ContainerContextBase<TOptions extends ContainerCon
|
|
|
27
28
|
private readonly scopeContext?;
|
|
28
29
|
protected readonly forwardRefModules: WeakSet<M>;
|
|
29
30
|
protected readonly moduleScopeMap: WeakMap<M, Awilix.AwilixContainer<{}>>;
|
|
31
|
+
protected readonly devtoolsProcessorRef: DevtoolsProcessorRef;
|
|
30
32
|
protected readonly moduleTreeMap: WeakMap<M, ModuleScope<Awilix.AwilixContainer<{}>>>;
|
|
31
33
|
protected readonly options: TOptions;
|
|
32
34
|
protected readonly sorter: ProviderDependencySorter;
|
|
@@ -39,15 +41,23 @@ export declare abstract class ContainerContextBase<TOptions extends ContainerCon
|
|
|
39
41
|
protected bootstrapModule(module: M): ModuleScope;
|
|
40
42
|
protected createContainer(module?: M): Awilix.AwilixContainer;
|
|
41
43
|
protected registerModuleWithScope(m: M, scope: Awilix.AwilixContainer, moduleChain: M[]): ModuleScope;
|
|
42
|
-
protected initializeGlobalModules(): void;
|
|
44
|
+
protected initializeGlobalModules(rootModule: M): void;
|
|
43
45
|
protected registerImportedFeatures(scope: Awilix.AwilixContainer, importedModulesWithScope: RegisteredModuleScope[]): void;
|
|
44
46
|
protected registerExportedProviders(scope: Awilix.AwilixContainer, importedModulesWithScope: RegisteredModuleScope[]): void;
|
|
45
47
|
protected getExportedProviderKeys(module: M): string[];
|
|
46
48
|
protected markModuleIfImportsUseForwardRef(m: M): void;
|
|
47
49
|
protected createModuleScope(name: string, scope: Awilix.AwilixContainer, importedModulesWithScope: RegisteredModuleScope[]): ModuleScope;
|
|
48
50
|
protected resolveImports(m: M): M[];
|
|
51
|
+
protected registerModuleInGraph({ module, scope, importedModules, }: {
|
|
52
|
+
module: M;
|
|
53
|
+
scope: Awilix.AwilixContainer;
|
|
54
|
+
importedModules: readonly M[];
|
|
55
|
+
}): string | undefined;
|
|
49
56
|
protected ensureAdditionalNameConflicts(_module: M, _resolvedImports: M[]): void;
|
|
50
57
|
protected beforeRegisterProviders(_module: M, _scope: Awilix.AwilixContainer, _importedModulesWithScope: RegisteredModuleScope[]): void;
|
|
51
58
|
protected afterRegisterProviders(_module: M, _scope: Awilix.AwilixContainer, _importedModulesWithScope: RegisteredModuleScope[]): void;
|
|
59
|
+
protected hasDevtoolsProcessorProvider(module: M): boolean;
|
|
60
|
+
protected get globalModules(): M[];
|
|
61
|
+
protected attachDevtools(rootModule: M): void;
|
|
52
62
|
}
|
|
53
63
|
export {};
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import * as Awilix from "awilix";
|
|
2
|
+
import { AWILIXIFY_DEVTOOLS_PROCESSOR, } from "../../devtools/devtools.types.js";
|
|
2
3
|
import * as ERRORS from "../errors.js";
|
|
3
4
|
import { LifecycleProcessor, } from "../processors/lifecycle-processor.js";
|
|
4
5
|
import { OverridesProcessor, } from "../processors/overrides-processor.js";
|
|
@@ -9,6 +10,7 @@ export class ContainerContextBase {
|
|
|
9
10
|
scopeContext;
|
|
10
11
|
forwardRefModules = new WeakSet();
|
|
11
12
|
moduleScopeMap = new WeakMap();
|
|
13
|
+
devtoolsProcessorRef = {};
|
|
12
14
|
moduleTreeMap = new WeakMap();
|
|
13
15
|
options;
|
|
14
16
|
sorter = new ProviderDependencySorter();
|
|
@@ -37,7 +39,7 @@ export class ContainerContextBase {
|
|
|
37
39
|
this.lifecycleProcessor = new LifecycleProcessor(this.options.providerOptions || {});
|
|
38
40
|
}
|
|
39
41
|
bootstrapModule(module) {
|
|
40
|
-
this.initializeGlobalModules();
|
|
42
|
+
this.initializeGlobalModules(module);
|
|
41
43
|
const moduleTree = this.registerModuleWithScope(module, this.createContainer(module), []);
|
|
42
44
|
this.overridesProcessor.ensureAllModuleOverridesApplied();
|
|
43
45
|
return moduleTree;
|
|
@@ -57,6 +59,11 @@ export class ContainerContextBase {
|
|
|
57
59
|
}
|
|
58
60
|
const imports = this.resolveImports(m);
|
|
59
61
|
const moduleWithOverrides = this.overridesProcessor.applyModuleOverrides(m);
|
|
62
|
+
const moduleId = this.registerModuleInGraph({
|
|
63
|
+
module: moduleWithOverrides,
|
|
64
|
+
scope,
|
|
65
|
+
importedModules: imports,
|
|
66
|
+
});
|
|
60
67
|
this.moduleGraphEnsurer.ensureImportedModulesUniqueness({
|
|
61
68
|
module: moduleWithOverrides,
|
|
62
69
|
resolvedImports: imports,
|
|
@@ -100,6 +107,7 @@ export class ContainerContextBase {
|
|
|
100
107
|
scope.register({
|
|
101
108
|
[key]: this.providerResolver.resolveProvider({
|
|
102
109
|
key,
|
|
110
|
+
moduleId,
|
|
103
111
|
provider,
|
|
104
112
|
resolutionScope: scope,
|
|
105
113
|
module: moduleWithOverrides,
|
|
@@ -112,21 +120,21 @@ export class ContainerContextBase {
|
|
|
112
120
|
this.moduleTreeMap.set(m, moduleTree);
|
|
113
121
|
return moduleTree;
|
|
114
122
|
}
|
|
115
|
-
initializeGlobalModules() {
|
|
116
|
-
const
|
|
117
|
-
const globalModuleImports = globalModules.flatMap((module) => this.resolveImports(module).map((importedModule) => ({
|
|
123
|
+
initializeGlobalModules(rootModule) {
|
|
124
|
+
const globalModuleImports = this.globalModules.flatMap((module) => this.resolveImports(module).map((importedModule) => ({
|
|
118
125
|
module,
|
|
119
126
|
importedModule,
|
|
120
127
|
})));
|
|
121
128
|
this.moduleGraphEnsurer.ensureGlobalModulesDoNotImportGlobalModules({
|
|
122
|
-
globalModules,
|
|
129
|
+
globalModules: this.globalModules,
|
|
123
130
|
globalModuleImports,
|
|
124
131
|
});
|
|
125
132
|
this.globalModulesWithScope = [];
|
|
126
|
-
|
|
133
|
+
this.attachDevtools(rootModule);
|
|
134
|
+
for (const module of this.globalModules) {
|
|
127
135
|
const moduleTree = this.registerModuleWithScope(module, this.createContainer(module), []);
|
|
128
136
|
this.globalModulesWithScope.push({
|
|
129
|
-
module
|
|
137
|
+
module,
|
|
130
138
|
moduleScope: moduleTree,
|
|
131
139
|
});
|
|
132
140
|
}
|
|
@@ -188,7 +196,37 @@ export class ContainerContextBase {
|
|
|
188
196
|
return resolvedImport;
|
|
189
197
|
});
|
|
190
198
|
}
|
|
199
|
+
registerModuleInGraph({ module, scope, importedModules, }) {
|
|
200
|
+
if (!this.devtoolsProcessorRef.current) {
|
|
201
|
+
return undefined;
|
|
202
|
+
}
|
|
203
|
+
const moduleId = this.devtoolsProcessorRef.current.graphCollector.registerModule({
|
|
204
|
+
module,
|
|
205
|
+
scope,
|
|
206
|
+
importedModules,
|
|
207
|
+
});
|
|
208
|
+
return moduleId;
|
|
209
|
+
}
|
|
191
210
|
ensureAdditionalNameConflicts(_module, _resolvedImports) { }
|
|
192
211
|
beforeRegisterProviders(_module, _scope, _importedModulesWithScope) { }
|
|
193
212
|
afterRegisterProviders(_module, _scope, _importedModulesWithScope) { }
|
|
213
|
+
hasDevtoolsProcessorProvider(module) {
|
|
214
|
+
return Boolean(module.providers?.[AWILIXIFY_DEVTOOLS_PROCESSOR]);
|
|
215
|
+
}
|
|
216
|
+
get globalModules() {
|
|
217
|
+
return (this.options.globalModules || [])
|
|
218
|
+
.filter((module) => !this.hasDevtoolsProcessorProvider(module))
|
|
219
|
+
.map((el) => this.overridesProcessor.getModuleWithOverrides(el));
|
|
220
|
+
}
|
|
221
|
+
attachDevtools(rootModule) {
|
|
222
|
+
const module = this.moduleGraphEnsurer.ensureSingleDevtoolsModule((this.options.globalModules || []).filter((module) => this.hasDevtoolsProcessorProvider(module)));
|
|
223
|
+
if (!module)
|
|
224
|
+
return;
|
|
225
|
+
const moduleTree = this.registerModuleWithScope(module, this.createContainer(module), []);
|
|
226
|
+
this.devtoolsProcessorRef.current = moduleTree.scope.resolve(AWILIXIFY_DEVTOOLS_PROCESSOR);
|
|
227
|
+
this.devtoolsProcessorRef.current.initialize({
|
|
228
|
+
rootModule,
|
|
229
|
+
globalModules: this.globalModules,
|
|
230
|
+
});
|
|
231
|
+
}
|
|
194
232
|
}
|
|
@@ -10,26 +10,26 @@ export class AsyncDIContext extends DIContextBase {
|
|
|
10
10
|
}
|
|
11
11
|
async bootstrap(module) {
|
|
12
12
|
const rootModule = await module;
|
|
13
|
-
await this.initializeGlobalModulesAsync();
|
|
13
|
+
await this.initializeGlobalModulesAsync(rootModule);
|
|
14
14
|
const moduleTree = await this.registerModuleWithScopeAsync(rootModule, this.createContainer(rootModule), []);
|
|
15
15
|
this.overridesProcessor.ensureAllModuleOverridesApplied();
|
|
16
16
|
return moduleTree;
|
|
17
17
|
}
|
|
18
|
-
async initializeGlobalModulesAsync() {
|
|
19
|
-
const
|
|
20
|
-
const globalModuleImports = (await Promise.all(globalModules.map(async (module) => (await this.resolveImportsAsync(module)).map((importedModule) => ({
|
|
18
|
+
async initializeGlobalModulesAsync(rootModule) {
|
|
19
|
+
const globalModuleImports = (await Promise.all(this.globalModules.map(async (module) => (await this.resolveImportsAsync(module)).map((importedModule) => ({
|
|
21
20
|
module,
|
|
22
21
|
importedModule,
|
|
23
22
|
}))))).flat();
|
|
24
23
|
this.moduleGraphEnsurer.ensureGlobalModulesDoNotImportGlobalModules({
|
|
25
|
-
globalModules,
|
|
24
|
+
globalModules: this.globalModules,
|
|
26
25
|
globalModuleImports,
|
|
27
26
|
});
|
|
28
27
|
this.globalModulesWithScope = [];
|
|
29
|
-
|
|
28
|
+
this.attachDevtools(rootModule);
|
|
29
|
+
for (const module of this.globalModules) {
|
|
30
30
|
const moduleTree = await this.registerModuleWithScopeAsync(module, this.createContainer(module), []);
|
|
31
31
|
this.globalModulesWithScope.push({
|
|
32
|
-
module
|
|
32
|
+
module,
|
|
33
33
|
moduleScope: moduleTree,
|
|
34
34
|
});
|
|
35
35
|
}
|
|
@@ -41,6 +41,11 @@ export class AsyncDIContext extends DIContextBase {
|
|
|
41
41
|
}
|
|
42
42
|
const imports = await this.resolveImportsAsync(m);
|
|
43
43
|
const moduleWithOverrides = this.overridesProcessor.applyModuleOverrides(m);
|
|
44
|
+
const moduleId = this.registerModuleInGraph({
|
|
45
|
+
module: moduleWithOverrides,
|
|
46
|
+
scope,
|
|
47
|
+
importedModules: imports,
|
|
48
|
+
});
|
|
44
49
|
this.moduleGraphEnsurer.ensureImportedModulesUniqueness({
|
|
45
50
|
module: moduleWithOverrides,
|
|
46
51
|
resolvedImports: imports,
|
|
@@ -66,11 +71,11 @@ export class AsyncDIContext extends DIContextBase {
|
|
|
66
71
|
if (pendingTree) {
|
|
67
72
|
return pendingTree;
|
|
68
73
|
}
|
|
69
|
-
const moduleTreePromise = this.registerNewModuleWithScopeAsync(m, moduleWithOverrides, scope, imports, moduleChain);
|
|
74
|
+
const moduleTreePromise = this.registerNewModuleWithScopeAsync(m, moduleWithOverrides, moduleId, scope, imports, moduleChain);
|
|
70
75
|
this.moduleTreePromiseMap.set(m, moduleTreePromise);
|
|
71
76
|
return moduleTreePromise;
|
|
72
77
|
}
|
|
73
|
-
async registerNewModuleWithScopeAsync(m, moduleWithOverrides, scope, imports, moduleChain) {
|
|
78
|
+
async registerNewModuleWithScopeAsync(m, moduleWithOverrides, moduleId, scope, imports, moduleChain) {
|
|
74
79
|
this.moduleScopeMap.set(m, scope);
|
|
75
80
|
const importedModulesWithScope = [
|
|
76
81
|
...this.globalModulesWithScope,
|
|
@@ -93,6 +98,7 @@ export class AsyncDIContext extends DIContextBase {
|
|
|
93
98
|
scope.register({
|
|
94
99
|
[key]: await this.providerResolver.resolveProviderAsync({
|
|
95
100
|
key,
|
|
101
|
+
moduleId,
|
|
96
102
|
provider,
|
|
97
103
|
resolutionScope: scope,
|
|
98
104
|
module: moduleWithOverrides,
|
|
@@ -9,16 +9,17 @@ export class DIContextBase extends ContainerContextBase {
|
|
|
9
9
|
controllerProcessor;
|
|
10
10
|
handlerProcessor;
|
|
11
11
|
interceptorProcessor;
|
|
12
|
-
initializerProcessor
|
|
12
|
+
initializerProcessor;
|
|
13
13
|
constructor(options) {
|
|
14
14
|
super(options, {
|
|
15
15
|
hasScopeContext: hasRequestScopeContext,
|
|
16
16
|
resolveFromScope: resolveFromRequestScope,
|
|
17
17
|
});
|
|
18
|
-
this.handlerProcessor = new HandlerProcessor(this.options.providerOptions || {});
|
|
19
|
-
this.interceptorProcessor = new InterceptorProcessor(this.options.providerOptions || {});
|
|
18
|
+
this.handlerProcessor = new HandlerProcessor(this.options.providerOptions || {}, this.devtoolsProcessorRef);
|
|
19
|
+
this.interceptorProcessor = new InterceptorProcessor(this.options.providerOptions || {}, this.devtoolsProcessorRef);
|
|
20
|
+
this.initializerProcessor = new InitializerProcessor(this.devtoolsProcessorRef);
|
|
20
21
|
this.controllerProcessor = new ControllerProcessor(this.interceptorProcessor, this.options.providerOptions || {}, this.options.skipRegisterRoutes === true);
|
|
21
|
-
this.providerResolver = new ProviderResolver(this.interceptorProcessor, this.options.providerOptions || {}, getOrCreateRequestScope);
|
|
22
|
+
this.providerResolver = new ProviderResolver(this.interceptorProcessor, this.options.providerOptions || {}, this.devtoolsProcessorRef, getOrCreateRequestScope);
|
|
22
23
|
}
|
|
23
24
|
beforeRegisterProviders(m, scope, importedModulesWithScope) {
|
|
24
25
|
this.interceptorProcessor.processInterceptors(m, scope, importedModulesWithScope);
|
|
@@ -27,5 +27,6 @@ export declare class ModuleGraphEnsurer {
|
|
|
27
27
|
ensureGlobalModulesDoNotImportGlobalModules({ globalModules, globalModuleImports, }: EnsureGlobalModulesDoNotImportGlobalModulesParams): void;
|
|
28
28
|
ensureNoProviderNameConflicts({ module, resolvedImports, globalModules, getExportedProviderKeys, }: EnsureNoProviderNameConflictsParams): void;
|
|
29
29
|
ensureCircularDependencyHasForwardRef({ module, moduleChain, forwardRefModules, }: EnsureCircularDependencyHasForwardRefParams): void;
|
|
30
|
+
ensureSingleDevtoolsModule(devtoolsModules: M[]): M | undefined;
|
|
30
31
|
}
|
|
31
32
|
export {};
|
|
@@ -42,4 +42,9 @@ export class ModuleGraphEnsurer {
|
|
|
42
42
|
const chainNames = moduleChain.map((chainModule) => chainModule.name);
|
|
43
43
|
throw new ERRORS.CircularModuleDependencyError(module.name, chainNames);
|
|
44
44
|
}
|
|
45
|
+
ensureSingleDevtoolsModule(devtoolsModules) {
|
|
46
|
+
if (devtoolsModules.length <= 1)
|
|
47
|
+
return devtoolsModules[0];
|
|
48
|
+
throw new ERRORS.DuplicateDevtoolsModuleError(devtoolsModules.map((module) => module.name));
|
|
49
|
+
}
|
|
45
50
|
}
|
package/dist/lib/di/errors.d.ts
CHANGED
|
@@ -13,6 +13,9 @@ export declare class CircularDependencyError extends Error {
|
|
|
13
13
|
export declare class DuplicateModuleImportError extends Error {
|
|
14
14
|
constructor(parentModuleName: string, importedModuleName: string);
|
|
15
15
|
}
|
|
16
|
+
export declare class DuplicateDevtoolsModuleError extends Error {
|
|
17
|
+
constructor(moduleNames: string[]);
|
|
18
|
+
}
|
|
16
19
|
export declare class ProviderNameConflictError extends Error {
|
|
17
20
|
constructor(moduleName: string, conflictingKeys: string[]);
|
|
18
21
|
}
|
package/dist/lib/di/errors.js
CHANGED
|
@@ -30,6 +30,12 @@ export class DuplicateModuleImportError extends Error {
|
|
|
30
30
|
this.name = "DuplicateModuleImportError";
|
|
31
31
|
}
|
|
32
32
|
}
|
|
33
|
+
export class DuplicateDevtoolsModuleError extends Error {
|
|
34
|
+
constructor(moduleNames) {
|
|
35
|
+
super(`Only one devtools module can be registered. Found: ${moduleNames.join(", ")}`);
|
|
36
|
+
this.name = "DuplicateDevtoolsModuleError";
|
|
37
|
+
}
|
|
38
|
+
}
|
|
33
39
|
export class ProviderNameConflictError extends Error {
|
|
34
40
|
constructor(moduleName, conflictingKeys) {
|
|
35
41
|
super(`Module "${moduleName}" has provider name conflicts with imported modules: ${conflictingKeys.join(", ")}`);
|
|
@@ -18,13 +18,21 @@ export function createModule(module, options) {
|
|
|
18
18
|
if (options?.hashNameFrom === undefined) {
|
|
19
19
|
return withOptions;
|
|
20
20
|
}
|
|
21
|
+
const hashSource = stableStringify(options.hashNameFrom);
|
|
21
22
|
const hash = createHash("sha256")
|
|
22
|
-
.update(
|
|
23
|
+
.update(hashSource)
|
|
23
24
|
.digest("hex")
|
|
24
25
|
.slice(0, Math.max(4, options.hashLength ?? 8));
|
|
25
26
|
return {
|
|
26
27
|
...withOptions,
|
|
27
28
|
name: `${withOptions.name}_${hash}`,
|
|
29
|
+
__devtools: {
|
|
30
|
+
baseName: withOptions.name,
|
|
31
|
+
dynamic: {
|
|
32
|
+
hash,
|
|
33
|
+
paramsPreview: hashSource,
|
|
34
|
+
},
|
|
35
|
+
},
|
|
28
36
|
};
|
|
29
37
|
}
|
|
30
38
|
function stableStringify(value) {
|
|
@@ -3,6 +3,13 @@ import type { AnyController, AnyInitializer, AnyInterceptor, AnyMiddleware, AnyP
|
|
|
3
3
|
import type { ForwardRef } from "./module-ref.types.js";
|
|
4
4
|
export interface InternalModuleLike {
|
|
5
5
|
name: string;
|
|
6
|
+
__devtools?: {
|
|
7
|
+
baseName?: string;
|
|
8
|
+
dynamic?: {
|
|
9
|
+
hash: string;
|
|
10
|
+
paramsPreview: string;
|
|
11
|
+
};
|
|
12
|
+
};
|
|
6
13
|
imports?: readonly (InternalModuleLike | Promise<InternalModuleLike> | ForwardRef<InternalModuleLike>)[];
|
|
7
14
|
providers?: Record<string, AnyProvider>;
|
|
8
15
|
exports?: readonly string[];
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import * as Awilix from "awilix";
|
|
2
|
+
import type { DevtoolsProcessorRef } from "../../devtools/devtools.types.js";
|
|
2
3
|
import type { RegisteredModuleScope } from "../contexts/container-context-base.js";
|
|
3
4
|
import type { InternalModuleLike as M } from "../modules/runtime-module.types.js";
|
|
4
5
|
export declare const HandlerType: {
|
|
@@ -8,8 +9,11 @@ export declare const HandlerType: {
|
|
|
8
9
|
export type HandlerType = (typeof HandlerType)[keyof typeof HandlerType];
|
|
9
10
|
export declare class HandlerProcessor {
|
|
10
11
|
private readonly providerOptions;
|
|
12
|
+
private readonly devtoolsProcessorRef;
|
|
11
13
|
private readonly keyedFeatureRegistrar;
|
|
12
14
|
private static readonly handlerConfig;
|
|
13
|
-
constructor(providerOptions: Partial<Awilix.BuildResolverOptions<any
|
|
15
|
+
constructor(providerOptions: Partial<Awilix.BuildResolverOptions<any>>, devtoolsProcessorRef: DevtoolsProcessorRef);
|
|
14
16
|
processHandlers(m: M, scope: Awilix.AwilixContainer, importedModulesWithScope: RegisteredModuleScope[], handlerType: HandlerType): void;
|
|
17
|
+
private createTracedHandlerResolver;
|
|
18
|
+
private get devtoolsTracer();
|
|
15
19
|
}
|
|
@@ -11,6 +11,7 @@ export const HandlerType = {
|
|
|
11
11
|
};
|
|
12
12
|
export class HandlerProcessor {
|
|
13
13
|
providerOptions;
|
|
14
|
+
devtoolsProcessorRef;
|
|
14
15
|
keyedFeatureRegistrar;
|
|
15
16
|
static handlerConfig = {
|
|
16
17
|
query: {
|
|
@@ -24,8 +25,9 @@ export class HandlerProcessor {
|
|
|
24
25
|
mediatorKey: "commandMediator",
|
|
25
26
|
},
|
|
26
27
|
};
|
|
27
|
-
constructor(providerOptions) {
|
|
28
|
+
constructor(providerOptions, devtoolsProcessorRef) {
|
|
28
29
|
this.providerOptions = providerOptions;
|
|
30
|
+
this.devtoolsProcessorRef = devtoolsProcessorRef;
|
|
29
31
|
this.keyedFeatureRegistrar = new KeyedFeatureRegistrar(providerOptions);
|
|
30
32
|
}
|
|
31
33
|
processHandlers(m, scope, importedModulesWithScope, handlerType) {
|
|
@@ -39,7 +41,7 @@ export class HandlerProcessor {
|
|
|
39
41
|
const handlers = m[handlersKey];
|
|
40
42
|
if (!handlers?.length)
|
|
41
43
|
return;
|
|
42
|
-
const mediator = new Mediator(middlewareResolvers, m.name);
|
|
44
|
+
const mediator = new Mediator(middlewareResolvers, m.name, handlerType, this.devtoolsProcessorRef);
|
|
43
45
|
for (const h of handlers) {
|
|
44
46
|
const { useClass: HandlerClass, ...handlerOptions } = hasUseClass(h)
|
|
45
47
|
? h
|
|
@@ -50,20 +52,52 @@ export class HandlerProcessor {
|
|
|
50
52
|
}
|
|
51
53
|
const options = ProviderResolver.mergeResolverOptions(m, this.providerOptions, handlerOptions);
|
|
52
54
|
const handlerSymbol = Symbol(`${handlerKey}_${HandlerClass.name}`);
|
|
55
|
+
const handlerResolver = Awilix.asClass(HandlerClass, options);
|
|
53
56
|
scope.register({
|
|
54
|
-
[handlerSymbol]:
|
|
57
|
+
[handlerSymbol]: this.createTracedHandlerResolver({
|
|
58
|
+
handlerClassName: HandlerClass.name,
|
|
59
|
+
module: m,
|
|
60
|
+
options,
|
|
61
|
+
resolver: handlerResolver,
|
|
62
|
+
}),
|
|
55
63
|
});
|
|
56
|
-
mediator.register(handlerKey, (payload, context) => {
|
|
64
|
+
mediator.register(handlerKey, async (payload, context) => {
|
|
57
65
|
const requestScope = options.lifetime === Awilix.Lifetime.SINGLETON
|
|
58
66
|
? scope
|
|
59
67
|
: getOrCreateRequestScope(scope);
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
68
|
+
if (!this.devtoolsTracer) {
|
|
69
|
+
return requestScope
|
|
70
|
+
.resolve(handlerSymbol)
|
|
71
|
+
.executor(payload, context);
|
|
72
|
+
}
|
|
73
|
+
return this.devtoolsTracer.recordSpan({
|
|
74
|
+
kind: "handler",
|
|
75
|
+
moduleName: m.name,
|
|
76
|
+
providerKey: `${handlerType}:${handlerKey}`,
|
|
77
|
+
methodName: "executor",
|
|
78
|
+
args: [payload, context],
|
|
79
|
+
callback: () => requestScope
|
|
80
|
+
.resolve(handlerSymbol)
|
|
81
|
+
.executor(payload, context),
|
|
82
|
+
});
|
|
63
83
|
});
|
|
64
84
|
}
|
|
65
85
|
scope.register({
|
|
66
86
|
[mediatorKey]: Awilix.asValue(mediator),
|
|
67
87
|
});
|
|
68
88
|
}
|
|
89
|
+
createTracedHandlerResolver({ handlerClassName, module, options, resolver, }) {
|
|
90
|
+
if (!this.devtoolsTracer)
|
|
91
|
+
return resolver;
|
|
92
|
+
return this.devtoolsTracer.wrapResolver({
|
|
93
|
+
kind: "handler",
|
|
94
|
+
module,
|
|
95
|
+
options,
|
|
96
|
+
providerKey: handlerClassName,
|
|
97
|
+
resolver,
|
|
98
|
+
});
|
|
99
|
+
}
|
|
100
|
+
get devtoolsTracer() {
|
|
101
|
+
return this.devtoolsProcessorRef.current?.tracer;
|
|
102
|
+
}
|
|
69
103
|
}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import type * as Awilix from "awilix";
|
|
2
|
+
import type { DevtoolsProcessorRef } from "../../devtools/devtools.types.js";
|
|
2
3
|
import type { RegisteredModuleScope } from "../contexts/container-context-base.js";
|
|
3
4
|
import type { InternalModuleLike as M } from "../modules/runtime-module.types.js";
|
|
4
5
|
import type { ConstructorController } from "../providers/provider.types.js";
|
|
@@ -9,11 +10,11 @@ export type ControllerRuntimeEntry = {
|
|
|
9
10
|
};
|
|
10
11
|
export type InitializerTask = (options?: ModuleInitOptions) => Promise<void>;
|
|
11
12
|
export declare class InitializerProcessor {
|
|
13
|
+
private readonly devtoolsProcessorRef;
|
|
12
14
|
private readonly keyedFeatureRegistrar;
|
|
13
15
|
private readonly resolversByModule;
|
|
16
|
+
constructor(devtoolsProcessorRef: DevtoolsProcessorRef);
|
|
14
17
|
collectInitializers(m: M, scope: Awilix.AwilixContainer, importedModulesWithScope: RegisteredModuleScope[], controllers: ControllerRuntimeEntry[]): InitializerTask | null;
|
|
15
18
|
private ensureNoMultiInvokableInitializersPerMethod;
|
|
16
19
|
private filterActiveInitializers;
|
|
17
|
-
private processInitializerResolvers;
|
|
18
|
-
private getControllerMethodNames;
|
|
19
20
|
}
|