awilixify 2.2.1 → 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 +15 -6
- package/dist/index.d.ts +19 -0
- package/dist/index.js +15 -0
- package/dist/lib/decorators/decorator-state.d.ts +15 -0
- package/dist/lib/decorators/decorator-state.js +72 -0
- package/dist/lib/decorators/decorator-state.types.d.ts +35 -0
- package/dist/lib/decorators/decorator-state.types.js +1 -0
- 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/common.types.d.ts +6 -0
- package/dist/lib/di/common.types.js +1 -0
- package/dist/lib/di/contexts/container-context-base.d.ts +63 -0
- package/dist/lib/di/contexts/container-context-base.js +232 -0
- package/dist/lib/di/contexts/di-context-async.d.ts +14 -0
- package/dist/lib/di/contexts/di-context-async.js +118 -0
- package/dist/lib/di/contexts/di-context-base.d.ts +19 -0
- package/dist/lib/di/contexts/di-context-base.js +33 -0
- package/dist/lib/di/contexts/di-context.d.ts +7 -0
- package/dist/lib/di/contexts/di-context.js +9 -0
- package/dist/lib/di/contexts/module-graph-ensurer.d.ts +32 -0
- package/dist/lib/di/contexts/module-graph-ensurer.js +50 -0
- package/dist/lib/di/errors.d.ts +69 -0
- package/dist/lib/di/errors.js +154 -0
- package/dist/lib/di/modules/module-def.types.d.ts +117 -0
- package/dist/lib/di/modules/module-def.types.js +1 -0
- package/dist/lib/di/modules/module-factories.d.ts +16 -0
- package/dist/lib/di/modules/module-factories.js +54 -0
- package/dist/lib/di/modules/module-overrides.d.ts +70 -0
- package/dist/lib/di/modules/module-overrides.js +3 -0
- package/dist/lib/di/modules/module-ref.types.d.ts +13 -0
- package/dist/lib/di/modules/module-ref.types.js +1 -0
- package/dist/lib/di/modules/module.types.d.ts +178 -0
- package/dist/lib/di/modules/module.types.js +1 -0
- package/dist/lib/di/modules/runtime-module.types.d.ts +32 -0
- package/dist/lib/di/modules/runtime-module.types.js +1 -0
- package/dist/lib/di/processors/controller-processor.d.ts +13 -0
- package/dist/lib/di/processors/controller-processor.js +76 -0
- package/dist/lib/di/processors/handler-processor.d.ts +19 -0
- package/dist/lib/di/processors/handler-processor.js +103 -0
- package/dist/lib/di/processors/initializer-processor.d.ts +20 -0
- package/dist/lib/di/processors/initializer-processor.js +95 -0
- package/dist/lib/di/processors/interceptor-processor.d.ts +21 -0
- package/dist/lib/di/processors/interceptor-processor.js +117 -0
- package/dist/lib/di/processors/keyed-feature-registrar.d.ts +19 -0
- package/dist/lib/di/processors/keyed-feature-registrar.js +112 -0
- package/dist/lib/di/processors/lifecycle-processor.d.ts +37 -0
- package/dist/lib/di/processors/lifecycle-processor.js +175 -0
- package/dist/lib/di/processors/overrides-processor.d.ts +24 -0
- package/dist/lib/di/processors/overrides-processor.js +69 -0
- package/dist/lib/di/providers/provider-dependency-sorter.d.ts +9 -0
- package/dist/lib/di/providers/provider-dependency-sorter.js +76 -0
- package/dist/lib/di/providers/provider-resolver.d.ts +35 -0
- package/dist/lib/di/providers/provider-resolver.js +168 -0
- package/dist/lib/di/providers/provider.types.d.ts +1 -0
- package/dist/lib/di/providers/provider.types.js +1 -0
- package/dist/lib/di/providers/types/controller.types.d.ts +9 -0
- package/dist/lib/di/providers/types/controller.types.js +1 -0
- package/dist/lib/di/providers/types/decorator-context.types.d.ts +9 -0
- package/dist/lib/di/providers/types/decorator-context.types.js +1 -0
- package/dist/lib/di/providers/types/handler.types.d.ts +9 -0
- package/dist/lib/di/providers/types/handler.types.js +1 -0
- package/dist/lib/di/providers/types/index.d.ts +7 -0
- package/dist/lib/di/providers/types/index.js +7 -0
- package/dist/lib/di/providers/types/initializer.types.d.ts +16 -0
- package/dist/lib/di/providers/types/initializer.types.js +3 -0
- package/dist/lib/di/providers/types/interceptor.types.d.ts +18 -0
- package/dist/lib/di/providers/types/interceptor.types.js +1 -0
- package/dist/lib/di/providers/types/middleware.types.d.ts +10 -0
- package/dist/lib/di/providers/types/middleware.types.js +1 -0
- package/dist/lib/di/providers/types/provider.types.d.ts +26 -0
- package/dist/lib/di/providers/types/provider.types.js +1 -0
- package/dist/lib/di/request-scope-context.d.ts +5 -0
- package/dist/lib/di/request-scope-context.js +28 -0
- package/dist/lib/di/type-guards.d.ts +35 -0
- package/dist/lib/di/type-guards.js +84 -0
- package/dist/lib/http/decorators.d.ts +33 -0
- package/dist/lib/http/decorators.js +151 -0
- package/dist/lib/http/exceptions.d.ts +58 -0
- package/dist/lib/http/exceptions.js +71 -0
- package/dist/lib/http/http-verbs.d.ts +12 -0
- package/dist/lib/http/http-verbs.js +11 -0
- package/dist/lib/http/index.d.ts +3 -0
- package/dist/lib/http/index.js +3 -0
- package/dist/lib/http/openapi-builder.d.ts +27 -0
- package/dist/lib/http/openapi-builder.js +83 -0
- package/dist/lib/mediator/contract.types.d.ts +159 -0
- package/dist/lib/mediator/contract.types.js +1 -0
- package/dist/lib/mediator/errors.d.ts +15 -0
- package/dist/lib/mediator/errors.js +33 -0
- package/dist/lib/mediator/global-middlewares.types.d.ts +13 -0
- package/dist/lib/mediator/global-middlewares.types.js +1 -0
- package/dist/lib/mediator/handler.types.d.ts +16 -0
- package/dist/lib/mediator/handler.types.js +1 -0
- package/dist/lib/mediator/mediator.d.ts +24 -0
- package/dist/lib/mediator/mediator.js +134 -0
- package/dist/lib/mediator/mediator.types.d.ts +64 -0
- package/dist/lib/mediator/mediator.types.js +1 -0
- package/dist/lib/mediator/middleware.types.d.ts +41 -0
- package/dist/lib/mediator/middleware.types.js +1 -0
- package/dist/lib/mediator/result.d.ts +18 -0
- package/dist/lib/mediator/result.js +24 -0
- package/dist/lib/react/errors.d.ts +12 -0
- package/dist/lib/react/errors.js +24 -0
- package/dist/lib/react/index.d.ts +4 -0
- package/dist/lib/react/index.js +4 -0
- package/dist/lib/react/react-component-processor.d.ts +10 -0
- package/dist/lib/react/react-component-processor.js +62 -0
- package/dist/lib/react/react-di-context.d.ts +16 -0
- package/dist/lib/react/react-di-context.js +52 -0
- package/dist/lib/react/react-module-factories.d.ts +6 -0
- package/dist/lib/react/react-module-factories.js +34 -0
- package/dist/lib/react/react-module.types.d.ts +169 -0
- package/dist/lib/react/react-module.types.js +1 -0
- package/dist/tsconfig.tsbuildinfo +1 -0
- package/package.json +33 -3
package/README.md
CHANGED
|
@@ -1,19 +1,28 @@
|
|
|
1
|
-
|
|
1
|
+
<div align="center">
|
|
2
|
+
<img src="./logo.png" alt="awilixify logo" width="220" />
|
|
3
|
+
</div>
|
|
4
|
+
|
|
5
|
+
Transport-agnostic, type-safe, modular DI and CQRS framework on top of [Awilix](https://github.com/jeffijoe/awilix) that brings module architecture with powerful CQRS capabilities to Node.js applications and React 🚀 frontends.
|
|
2
6
|
|
|
3
7
|
[](https://github.com/wildstyles/awilixify/actions)
|
|
4
8
|
[](https://codecov.io/gh/wildstyles/awilixify)
|
|
5
9
|
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
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)
|
|
9
15
|
|
|
10
|
-
|
|
16
|
+
📚 Documentation: https://wildstyles.github.io/awilixify/
|
|
11
17
|
|
|
12
18
|
## Features
|
|
13
19
|
|
|
14
20
|
- **Type-Safe Module System** - Complete type safety for each provider in module
|
|
15
|
-
- **
|
|
21
|
+
- **Transport Agnostic** - Works with Express, Fastify, Queues, Rabbit or any other tranport
|
|
22
|
+
- **Fullstack Module Model** - Reuse the same DI module mechanism in Node.js and React applications
|
|
16
23
|
- **Powerful CQRS** - Type-safe query/command handlers with middleware pipeline, per-module mediators, and contract-based execution
|
|
24
|
+
- **Type-Level Middleware Composition** - Compose and inherit middleware with end-to-end type safety
|
|
25
|
+
- **No Experimental Decorators Required** - Uses native ES decorators (TC39 Stage 3) for routing without `reflect-metadata`
|
|
17
26
|
- **NestJS-Inspired Architecture** - Familiar module/controller/provider patterns
|
|
18
27
|
- **Less Import Boilerplate For Typing** - Define module dependencies once - reuse in all providers
|
|
19
28
|
- **Lightweight** - Minimal overhead, built on proven Awilix foundation
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
export * from "./lib/decorators/decorator-state.js";
|
|
2
|
+
export type { DecoratorToken } from "./lib/decorators/decorator-state.types.js";
|
|
3
|
+
export type { ModuleScope } from "./lib/di/contexts/container-context-base.js";
|
|
4
|
+
export * from "./lib/di/contexts/di-context.js";
|
|
5
|
+
export * from "./lib/di/contexts/di-context-async.js";
|
|
6
|
+
export * from "./lib/di/modules/module.types.js";
|
|
7
|
+
export * from "./lib/di/modules/module-def.types.js";
|
|
8
|
+
export * from "./lib/di/modules/module-factories.js";
|
|
9
|
+
export * from "./lib/di/modules/module-overrides.js";
|
|
10
|
+
export * from "./lib/di/modules/module-ref.types.js";
|
|
11
|
+
export type { ConstructorController, Controller, InitializerContext, InterceptContext, Interceptor, ProviderInit, } from "./lib/di/providers/provider.types.js";
|
|
12
|
+
export { Initializer } from "./lib/di/providers/provider.types.js";
|
|
13
|
+
export { isResultLike } from "./lib/di/type-guards.js";
|
|
14
|
+
export * from "./lib/mediator/contract.types.js";
|
|
15
|
+
export * from "./lib/mediator/global-middlewares.types.js";
|
|
16
|
+
export * from "./lib/mediator/handler.types.js";
|
|
17
|
+
export type { ExecutionContext, Middleware, MiddlewareContract, } from "./lib/mediator/middleware.types.js";
|
|
18
|
+
export * from "./lib/mediator/middleware.types.js";
|
|
19
|
+
export { Result } from "./lib/mediator/result.js";
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
export * from "./lib/decorators/decorator-state.js";
|
|
2
|
+
export * from "./lib/di/contexts/di-context.js";
|
|
3
|
+
export * from "./lib/di/contexts/di-context-async.js";
|
|
4
|
+
export * from "./lib/di/modules/module.types.js";
|
|
5
|
+
export * from "./lib/di/modules/module-def.types.js";
|
|
6
|
+
export * from "./lib/di/modules/module-factories.js";
|
|
7
|
+
export * from "./lib/di/modules/module-overrides.js";
|
|
8
|
+
export * from "./lib/di/modules/module-ref.types.js";
|
|
9
|
+
export { Initializer } from "./lib/di/providers/provider.types.js";
|
|
10
|
+
export { isResultLike } from "./lib/di/type-guards.js";
|
|
11
|
+
export * from "./lib/mediator/contract.types.js";
|
|
12
|
+
export * from "./lib/mediator/global-middlewares.types.js";
|
|
13
|
+
export * from "./lib/mediator/handler.types.js";
|
|
14
|
+
export * from "./lib/mediator/middleware.types.js";
|
|
15
|
+
export { Result } from "./lib/mediator/result.js";
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import type { DecoratorState, DecoratorToken, MethodStateFrom, MethodUpdate, RootStateFrom, RootUpdate } from "./decorator-state.types.js";
|
|
2
|
+
export declare function createDecoratorStateUpdater<TInitializers extends {
|
|
3
|
+
method: () => unknown;
|
|
4
|
+
root?: () => unknown;
|
|
5
|
+
} = {
|
|
6
|
+
method: () => unknown;
|
|
7
|
+
}>(description: string, initializers: TInitializers): {
|
|
8
|
+
token: DecoratorToken<DecoratorState<MethodStateFrom<TInitializers>, RootStateFrom<TInitializers>>>;
|
|
9
|
+
update: {
|
|
10
|
+
(context: ClassDecoratorContext<any>, updater: RootUpdate<DecoratorState<MethodStateFrom<TInitializers>, RootStateFrom<TInitializers>>>): void;
|
|
11
|
+
(context: ClassMethodDecoratorContext<any, any>, updater: MethodUpdate<DecoratorState<MethodStateFrom<TInitializers>, RootStateFrom<TInitializers>>>): void;
|
|
12
|
+
};
|
|
13
|
+
};
|
|
14
|
+
export declare function resolveDecoratorState<TState extends DecoratorState<any, any>>(target: unknown, token: DecoratorToken<TState>): TState | null;
|
|
15
|
+
export declare function hasDecoratorMethodMetadata(target: unknown): boolean;
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
export function createDecoratorStateUpdater(description, initializers) {
|
|
2
|
+
const token = {
|
|
3
|
+
stateSymbol: Symbol(`DecoratorState:${description}`),
|
|
4
|
+
};
|
|
5
|
+
return {
|
|
6
|
+
token,
|
|
7
|
+
update: createUpdater(token, {
|
|
8
|
+
...initializers,
|
|
9
|
+
root: initializers.root ?? (() => null),
|
|
10
|
+
}),
|
|
11
|
+
};
|
|
12
|
+
}
|
|
13
|
+
export function resolveDecoratorState(target, token) {
|
|
14
|
+
const metadataSymbol = (typeof Symbol !== "undefined" && Symbol.metadata) ||
|
|
15
|
+
Object.getOwnPropertySymbols(target).find((s) => s.toString() === "Symbol(Symbol.metadata)");
|
|
16
|
+
if (!metadataSymbol)
|
|
17
|
+
return null;
|
|
18
|
+
return (target[metadataSymbol]?.[token.stateSymbol] || null);
|
|
19
|
+
}
|
|
20
|
+
export function hasDecoratorMethodMetadata(target) {
|
|
21
|
+
return [target, target?.prototype].some((value) => hasOwnDecoratorMethodMetadata(value));
|
|
22
|
+
}
|
|
23
|
+
function hasOwnDecoratorMethodMetadata(target) {
|
|
24
|
+
if (target === null ||
|
|
25
|
+
(typeof target !== "object" && typeof target !== "function")) {
|
|
26
|
+
return false;
|
|
27
|
+
}
|
|
28
|
+
const metadataSymbol = (typeof Symbol !== "undefined" && Symbol.metadata) ||
|
|
29
|
+
Object.getOwnPropertySymbols(target).find((s) => s.toString() === "Symbol(Symbol.metadata)");
|
|
30
|
+
if (!metadataSymbol)
|
|
31
|
+
return false;
|
|
32
|
+
const metadata = target[metadataSymbol];
|
|
33
|
+
if (!metadata || typeof metadata !== "object")
|
|
34
|
+
return false;
|
|
35
|
+
return [
|
|
36
|
+
...Object.getOwnPropertyNames(metadata).map((key) => metadata[key]),
|
|
37
|
+
...Object.getOwnPropertySymbols(metadata).map((key) => metadata[key]),
|
|
38
|
+
].some((state) => typeof state === "object" &&
|
|
39
|
+
state !== null &&
|
|
40
|
+
"methods" in state &&
|
|
41
|
+
state.methods instanceof Map &&
|
|
42
|
+
state.methods.size > 0);
|
|
43
|
+
}
|
|
44
|
+
function createUpdater(token, initializers) {
|
|
45
|
+
const initializeState = () => ({
|
|
46
|
+
root: initializers.root(),
|
|
47
|
+
methods: new Map(),
|
|
48
|
+
});
|
|
49
|
+
function update(context, updater) {
|
|
50
|
+
if (!context.metadata)
|
|
51
|
+
return;
|
|
52
|
+
const state = context.metadata[token.stateSymbol] || initializeState();
|
|
53
|
+
if (context.kind === "class") {
|
|
54
|
+
if (!("root" in updater))
|
|
55
|
+
return;
|
|
56
|
+
context.metadata[token.stateSymbol] = {
|
|
57
|
+
...state,
|
|
58
|
+
root: updater.root(state.root),
|
|
59
|
+
};
|
|
60
|
+
return;
|
|
61
|
+
}
|
|
62
|
+
if (!("method" in updater))
|
|
63
|
+
return;
|
|
64
|
+
const nextMethods = new Map(state.methods);
|
|
65
|
+
nextMethods.set(context.name, updater.method(nextMethods.get(context.name) ?? initializers.method()));
|
|
66
|
+
context.metadata[token.stateSymbol] = {
|
|
67
|
+
...state,
|
|
68
|
+
methods: nextMethods,
|
|
69
|
+
};
|
|
70
|
+
}
|
|
71
|
+
return update;
|
|
72
|
+
}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
export type MethodName = string | symbol;
|
|
2
|
+
export type DecoratorState<TMethod, TRoot = null> = {
|
|
3
|
+
root: TRoot;
|
|
4
|
+
methods: Map<MethodName, TMethod>;
|
|
5
|
+
};
|
|
6
|
+
export type DecoratorMethodState<TState> = TState extends DecoratorState<infer TMethod, any> ? TMethod : never;
|
|
7
|
+
export type DecoratorRootState<TState> = TState extends DecoratorState<any, infer TRoot> ? TRoot : never;
|
|
8
|
+
export type StateInitializers<TState extends DecoratorState<any, any>> = {
|
|
9
|
+
method: () => DecoratorMethodState<TState>;
|
|
10
|
+
root: () => DecoratorRootState<TState>;
|
|
11
|
+
};
|
|
12
|
+
type StateUpdater<T> = (previous: T) => T;
|
|
13
|
+
export type RootUpdate<TState extends DecoratorState<any, any>> = {
|
|
14
|
+
root: StateUpdater<DecoratorRootState<TState>>;
|
|
15
|
+
};
|
|
16
|
+
export type MethodUpdate<TState extends DecoratorState<any, any>> = {
|
|
17
|
+
method: StateUpdater<DecoratorMethodState<TState>>;
|
|
18
|
+
};
|
|
19
|
+
export type StateUpdate<TState extends DecoratorState<any, any>> = RootUpdate<TState> | MethodUpdate<TState>;
|
|
20
|
+
export type DecoratorToken<TState extends DecoratorState<any, any>> = {
|
|
21
|
+
stateSymbol: symbol;
|
|
22
|
+
readonly state: TState;
|
|
23
|
+
};
|
|
24
|
+
export type MethodStateFrom<TInitializers> = TInitializers extends {
|
|
25
|
+
method: () => infer TMethod;
|
|
26
|
+
} ? TMethod : never;
|
|
27
|
+
export type RootStateFrom<TInitializers> = TInitializers extends {
|
|
28
|
+
root: () => infer TRoot;
|
|
29
|
+
} ? TRoot : null;
|
|
30
|
+
declare global {
|
|
31
|
+
interface SymbolConstructor {
|
|
32
|
+
readonly metadata: unique symbol;
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
export {};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -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";
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
import * as Awilix from "awilix";
|
|
2
|
+
import { type DevtoolsProcessorRef } from "../../devtools/devtools.types.js";
|
|
3
|
+
import type { InternalModuleLike as M } from "../modules/runtime-module.types.js";
|
|
4
|
+
import { type LifecycleMethods, LifecycleProcessor } from "../processors/lifecycle-processor.js";
|
|
5
|
+
import { type OverrideOptions, OverridesProcessor } from "../processors/overrides-processor.js";
|
|
6
|
+
import { ProviderDependencySorter } from "../providers/provider-dependency-sorter.js";
|
|
7
|
+
import type { ProviderResolver } from "../providers/provider-resolver.js";
|
|
8
|
+
import { ModuleGraphEnsurer } from "./module-graph-ensurer.js";
|
|
9
|
+
interface ScopeContext {
|
|
10
|
+
hasScopeContext: () => boolean;
|
|
11
|
+
resolveFromScope: <T>(scope: Awilix.AwilixContainer, key: string | symbol) => T;
|
|
12
|
+
}
|
|
13
|
+
export interface ContainerContextOptions<Options extends Awilix.BuildResolverOptions<any> = Awilix.BuildResolverOptions<any>> extends OverrideOptions {
|
|
14
|
+
containerOptions?: Awilix.ContainerOptions;
|
|
15
|
+
providerOptions?: Options;
|
|
16
|
+
globalModules?: readonly M[];
|
|
17
|
+
}
|
|
18
|
+
export interface ModuleScope<S extends Awilix.AwilixContainer = Awilix.AwilixContainer> extends LifecycleMethods {
|
|
19
|
+
name: string;
|
|
20
|
+
scope: S;
|
|
21
|
+
importedScopes: Map<string, ModuleScope>;
|
|
22
|
+
}
|
|
23
|
+
export type RegisteredModuleScope = {
|
|
24
|
+
module: M;
|
|
25
|
+
moduleScope: ModuleScope;
|
|
26
|
+
};
|
|
27
|
+
export declare abstract class ContainerContextBase<TOptions extends ContainerContextOptions = ContainerContextOptions> {
|
|
28
|
+
private readonly scopeContext?;
|
|
29
|
+
protected readonly forwardRefModules: WeakSet<M>;
|
|
30
|
+
protected readonly moduleScopeMap: WeakMap<M, Awilix.AwilixContainer<{}>>;
|
|
31
|
+
protected readonly devtoolsProcessorRef: DevtoolsProcessorRef;
|
|
32
|
+
protected readonly moduleTreeMap: WeakMap<M, ModuleScope<Awilix.AwilixContainer<{}>>>;
|
|
33
|
+
protected readonly options: TOptions;
|
|
34
|
+
protected readonly sorter: ProviderDependencySorter;
|
|
35
|
+
protected readonly moduleGraphEnsurer: ModuleGraphEnsurer;
|
|
36
|
+
protected readonly lifecycleProcessor: LifecycleProcessor;
|
|
37
|
+
protected readonly overridesProcessor: OverridesProcessor<M>;
|
|
38
|
+
protected providerResolver: ProviderResolver;
|
|
39
|
+
protected globalModulesWithScope: RegisteredModuleScope[];
|
|
40
|
+
protected constructor(options: TOptions, scopeContext?: ScopeContext | undefined);
|
|
41
|
+
protected bootstrapModule(module: M): ModuleScope;
|
|
42
|
+
protected createContainer(module?: M): Awilix.AwilixContainer;
|
|
43
|
+
protected registerModuleWithScope(m: M, scope: Awilix.AwilixContainer, moduleChain: M[]): ModuleScope;
|
|
44
|
+
protected initializeGlobalModules(rootModule: M): void;
|
|
45
|
+
protected registerImportedFeatures(scope: Awilix.AwilixContainer, importedModulesWithScope: RegisteredModuleScope[]): void;
|
|
46
|
+
protected registerExportedProviders(scope: Awilix.AwilixContainer, importedModulesWithScope: RegisteredModuleScope[]): void;
|
|
47
|
+
protected getExportedProviderKeys(module: M): string[];
|
|
48
|
+
protected markModuleIfImportsUseForwardRef(m: M): void;
|
|
49
|
+
protected createModuleScope(name: string, scope: Awilix.AwilixContainer, importedModulesWithScope: RegisteredModuleScope[]): ModuleScope;
|
|
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;
|
|
56
|
+
protected ensureAdditionalNameConflicts(_module: M, _resolvedImports: M[]): void;
|
|
57
|
+
protected beforeRegisterProviders(_module: M, _scope: Awilix.AwilixContainer, _importedModulesWithScope: RegisteredModuleScope[]): void;
|
|
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;
|
|
62
|
+
}
|
|
63
|
+
export {};
|
|
@@ -0,0 +1,232 @@
|
|
|
1
|
+
import * as Awilix from "awilix";
|
|
2
|
+
import { AWILIXIFY_DEVTOOLS_PROCESSOR, } from "../../devtools/devtools.types.js";
|
|
3
|
+
import * as ERRORS from "../errors.js";
|
|
4
|
+
import { LifecycleProcessor, } from "../processors/lifecycle-processor.js";
|
|
5
|
+
import { OverridesProcessor, } from "../processors/overrides-processor.js";
|
|
6
|
+
import { ProviderDependencySorter } from "../providers/provider-dependency-sorter.js";
|
|
7
|
+
import * as GUARGS from "../type-guards.js";
|
|
8
|
+
import { ModuleGraphEnsurer } from "./module-graph-ensurer.js";
|
|
9
|
+
export class ContainerContextBase {
|
|
10
|
+
scopeContext;
|
|
11
|
+
forwardRefModules = new WeakSet();
|
|
12
|
+
moduleScopeMap = new WeakMap();
|
|
13
|
+
devtoolsProcessorRef = {};
|
|
14
|
+
moduleTreeMap = new WeakMap();
|
|
15
|
+
options;
|
|
16
|
+
sorter = new ProviderDependencySorter();
|
|
17
|
+
moduleGraphEnsurer = new ModuleGraphEnsurer();
|
|
18
|
+
lifecycleProcessor;
|
|
19
|
+
overridesProcessor;
|
|
20
|
+
providerResolver;
|
|
21
|
+
globalModulesWithScope = [];
|
|
22
|
+
constructor(options, scopeContext) {
|
|
23
|
+
this.scopeContext = scopeContext;
|
|
24
|
+
this.options = {
|
|
25
|
+
...options,
|
|
26
|
+
containerOptions: {
|
|
27
|
+
strict: true,
|
|
28
|
+
injectionMode: Awilix.InjectionMode.CLASSIC,
|
|
29
|
+
...options.containerOptions,
|
|
30
|
+
},
|
|
31
|
+
providerOptions: {
|
|
32
|
+
lifetime: Awilix.Lifetime.SINGLETON,
|
|
33
|
+
...options.providerOptions,
|
|
34
|
+
},
|
|
35
|
+
};
|
|
36
|
+
this.overridesProcessor = new OverridesProcessor({
|
|
37
|
+
moduleOverrides: this.options.moduleOverrides,
|
|
38
|
+
});
|
|
39
|
+
this.lifecycleProcessor = new LifecycleProcessor(this.options.providerOptions || {});
|
|
40
|
+
}
|
|
41
|
+
bootstrapModule(module) {
|
|
42
|
+
this.initializeGlobalModules(module);
|
|
43
|
+
const moduleTree = this.registerModuleWithScope(module, this.createContainer(module), []);
|
|
44
|
+
this.overridesProcessor.ensureAllModuleOverridesApplied();
|
|
45
|
+
return moduleTree;
|
|
46
|
+
}
|
|
47
|
+
createContainer(module) {
|
|
48
|
+
const scope = Awilix.createContainer({
|
|
49
|
+
...this.options.containerOptions,
|
|
50
|
+
...module?.containerOptions,
|
|
51
|
+
});
|
|
52
|
+
this.lifecycleProcessor.trackScope(scope);
|
|
53
|
+
return scope;
|
|
54
|
+
}
|
|
55
|
+
registerModuleWithScope(m, scope, moduleChain) {
|
|
56
|
+
const existingTree = this.moduleTreeMap.get(m);
|
|
57
|
+
if (existingTree) {
|
|
58
|
+
return existingTree;
|
|
59
|
+
}
|
|
60
|
+
const imports = this.resolveImports(m);
|
|
61
|
+
const moduleWithOverrides = this.overridesProcessor.applyModuleOverrides(m);
|
|
62
|
+
const moduleId = this.registerModuleInGraph({
|
|
63
|
+
module: moduleWithOverrides,
|
|
64
|
+
scope,
|
|
65
|
+
importedModules: imports,
|
|
66
|
+
});
|
|
67
|
+
this.moduleGraphEnsurer.ensureImportedModulesUniqueness({
|
|
68
|
+
module: moduleWithOverrides,
|
|
69
|
+
resolvedImports: imports,
|
|
70
|
+
globalModules: this.globalModulesWithScope.map((el) => el.module),
|
|
71
|
+
});
|
|
72
|
+
this.moduleGraphEnsurer.ensureNoProviderNameConflicts({
|
|
73
|
+
module: moduleWithOverrides,
|
|
74
|
+
resolvedImports: imports,
|
|
75
|
+
globalModules: this.globalModulesWithScope.map((el) => el.module),
|
|
76
|
+
getExportedProviderKeys: (module) => this.getExportedProviderKeys(module),
|
|
77
|
+
});
|
|
78
|
+
this.ensureAdditionalNameConflicts(moduleWithOverrides, imports);
|
|
79
|
+
this.markModuleIfImportsUseForwardRef(moduleWithOverrides);
|
|
80
|
+
const isCircular = moduleChain.includes(m);
|
|
81
|
+
if (isCircular) {
|
|
82
|
+
this.moduleGraphEnsurer.ensureCircularDependencyHasForwardRef({
|
|
83
|
+
module: m,
|
|
84
|
+
moduleChain,
|
|
85
|
+
forwardRefModules: this.forwardRefModules,
|
|
86
|
+
});
|
|
87
|
+
return this.createModuleScope(m.name, this.moduleScopeMap.get(m), []);
|
|
88
|
+
}
|
|
89
|
+
this.moduleScopeMap.set(m, scope);
|
|
90
|
+
const importedModulesWithScope = [
|
|
91
|
+
...this.globalModulesWithScope,
|
|
92
|
+
...imports.map((module) => {
|
|
93
|
+
const moduleTree = this.registerModuleWithScope(module, this.createContainer(module), [...moduleChain, m]);
|
|
94
|
+
return {
|
|
95
|
+
module: this.overridesProcessor.getModuleWithOverrides(module),
|
|
96
|
+
moduleScope: moduleTree,
|
|
97
|
+
};
|
|
98
|
+
}),
|
|
99
|
+
];
|
|
100
|
+
this.registerImportedFeatures(scope, importedModulesWithScope);
|
|
101
|
+
const moduleForSorting = {
|
|
102
|
+
...moduleWithOverrides,
|
|
103
|
+
imports: importedModulesWithScope.map((el) => el.module),
|
|
104
|
+
};
|
|
105
|
+
this.beforeRegisterProviders(moduleWithOverrides, scope, importedModulesWithScope);
|
|
106
|
+
for (const [key, provider] of Object.entries(this.sorter.sortByDependencies(moduleForSorting))) {
|
|
107
|
+
scope.register({
|
|
108
|
+
[key]: this.providerResolver.resolveProvider({
|
|
109
|
+
key,
|
|
110
|
+
moduleId,
|
|
111
|
+
provider,
|
|
112
|
+
resolutionScope: scope,
|
|
113
|
+
module: moduleWithOverrides,
|
|
114
|
+
}),
|
|
115
|
+
});
|
|
116
|
+
}
|
|
117
|
+
this.lifecycleProcessor.collectEagerProviders(moduleWithOverrides, scope);
|
|
118
|
+
this.afterRegisterProviders(moduleWithOverrides, scope, importedModulesWithScope);
|
|
119
|
+
const moduleTree = this.createModuleScope(m.name, scope, importedModulesWithScope);
|
|
120
|
+
this.moduleTreeMap.set(m, moduleTree);
|
|
121
|
+
return moduleTree;
|
|
122
|
+
}
|
|
123
|
+
initializeGlobalModules(rootModule) {
|
|
124
|
+
const globalModuleImports = this.globalModules.flatMap((module) => this.resolveImports(module).map((importedModule) => ({
|
|
125
|
+
module,
|
|
126
|
+
importedModule,
|
|
127
|
+
})));
|
|
128
|
+
this.moduleGraphEnsurer.ensureGlobalModulesDoNotImportGlobalModules({
|
|
129
|
+
globalModules: this.globalModules,
|
|
130
|
+
globalModuleImports,
|
|
131
|
+
});
|
|
132
|
+
this.globalModulesWithScope = [];
|
|
133
|
+
this.attachDevtools(rootModule);
|
|
134
|
+
for (const module of this.globalModules) {
|
|
135
|
+
const moduleTree = this.registerModuleWithScope(module, this.createContainer(module), []);
|
|
136
|
+
this.globalModulesWithScope.push({
|
|
137
|
+
module,
|
|
138
|
+
moduleScope: moduleTree,
|
|
139
|
+
});
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
registerImportedFeatures(scope, importedModulesWithScope) {
|
|
143
|
+
this.registerExportedProviders(scope, importedModulesWithScope);
|
|
144
|
+
}
|
|
145
|
+
registerExportedProviders(scope, importedModulesWithScope) {
|
|
146
|
+
for (const { module: importedModule, moduleScope: importedModuleScope, } of importedModulesWithScope) {
|
|
147
|
+
for (const key of this.getExportedProviderKeys(importedModule)) {
|
|
148
|
+
if (!importedModule.providers?.[key]) {
|
|
149
|
+
throw new ERRORS.InvalidProviderDefinitionError(importedModule.name, key);
|
|
150
|
+
}
|
|
151
|
+
scope.register({
|
|
152
|
+
[key]: Awilix.asFunction(() => {
|
|
153
|
+
const registration = importedModuleScope.scope.registrations[key];
|
|
154
|
+
return registration.lifetime === Awilix.Lifetime.SINGLETON
|
|
155
|
+
? importedModuleScope.scope.resolve(key)
|
|
156
|
+
: this.scopeContext?.hasScopeContext()
|
|
157
|
+
? this.scopeContext.resolveFromScope(importedModuleScope.scope, key)
|
|
158
|
+
: importedModuleScope.scope.resolve(key);
|
|
159
|
+
}, {
|
|
160
|
+
lifetime: Awilix.Lifetime.TRANSIENT,
|
|
161
|
+
isLeakSafe: true,
|
|
162
|
+
}),
|
|
163
|
+
});
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
getExportedProviderKeys(module) {
|
|
168
|
+
return module.exports ? [...module.exports] : [];
|
|
169
|
+
}
|
|
170
|
+
markModuleIfImportsUseForwardRef(m) {
|
|
171
|
+
if ((m.imports || []).some(GUARGS.isForwardRef)) {
|
|
172
|
+
this.forwardRefModules.add(m);
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
createModuleScope(name, scope, importedModulesWithScope) {
|
|
176
|
+
const importedScopes = importedModulesWithScope.reduce((acc, { moduleScope }) => {
|
|
177
|
+
acc.set(moduleScope.name, moduleScope);
|
|
178
|
+
return acc;
|
|
179
|
+
}, new Map());
|
|
180
|
+
return {
|
|
181
|
+
name,
|
|
182
|
+
scope,
|
|
183
|
+
importedScopes,
|
|
184
|
+
init: (options) => this.lifecycleProcessor.init(options),
|
|
185
|
+
dispose: () => this.lifecycleProcessor.dispose(),
|
|
186
|
+
};
|
|
187
|
+
}
|
|
188
|
+
resolveImports(m) {
|
|
189
|
+
return (m.imports || []).map((importItem) => {
|
|
190
|
+
const resolvedImport = GUARGS.isForwardRef(importItem)
|
|
191
|
+
? importItem.resolve()
|
|
192
|
+
: importItem;
|
|
193
|
+
if (GUARGS.isPromiseLike(resolvedImport)) {
|
|
194
|
+
throw new ERRORS.AsyncModuleRequiresAsyncCreateError(m.name);
|
|
195
|
+
}
|
|
196
|
+
return resolvedImport;
|
|
197
|
+
});
|
|
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
|
+
}
|
|
210
|
+
ensureAdditionalNameConflicts(_module, _resolvedImports) { }
|
|
211
|
+
beforeRegisterProviders(_module, _scope, _importedModulesWithScope) { }
|
|
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
|
+
}
|
|
232
|
+
}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import type { InternalModuleLike as M } from "../modules/runtime-module.types.js";
|
|
2
|
+
import type { ModuleScope } from "./container-context-base.js";
|
|
3
|
+
import type { DiContextOptions } from "./di-context-base.js";
|
|
4
|
+
import { DIContextBase } from "./di-context-base.js";
|
|
5
|
+
export declare class AsyncDIContext extends DIContextBase {
|
|
6
|
+
private readonly moduleTreePromiseMap;
|
|
7
|
+
private constructor();
|
|
8
|
+
static create(module: M | Promise<M>, options?: DiContextOptions): Promise<ModuleScope>;
|
|
9
|
+
private bootstrap;
|
|
10
|
+
private initializeGlobalModulesAsync;
|
|
11
|
+
private registerModuleWithScopeAsync;
|
|
12
|
+
private registerNewModuleWithScopeAsync;
|
|
13
|
+
private resolveImportsAsync;
|
|
14
|
+
}
|