awilixify 2.2.1 → 3.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.
Files changed (127) hide show
  1. package/README.md +12 -6
  2. package/dist/index.d.ts +18 -0
  3. package/dist/index.js +15 -0
  4. package/dist/lib/decorators/decorator-state.d.ts +15 -0
  5. package/dist/lib/decorators/decorator-state.js +72 -0
  6. package/dist/lib/decorators/decorator-state.types.d.ts +35 -0
  7. package/dist/lib/decorators/decorator-state.types.js +1 -0
  8. package/dist/lib/di/common.types.d.ts +6 -0
  9. package/dist/lib/di/common.types.js +1 -0
  10. package/dist/lib/di/contexts/container-context-base.d.ts +53 -0
  11. package/dist/lib/di/contexts/container-context-base.js +194 -0
  12. package/dist/lib/di/contexts/context-overrides.d.ts +22 -0
  13. package/dist/lib/di/contexts/context-overrides.js +93 -0
  14. package/dist/lib/di/contexts/di-context-async.d.ts +14 -0
  15. package/dist/lib/di/contexts/di-context-async.js +112 -0
  16. package/dist/lib/di/contexts/di-context-base.d.ts +19 -0
  17. package/dist/lib/di/contexts/di-context-base.js +32 -0
  18. package/dist/lib/di/contexts/di-context.d.ts +7 -0
  19. package/dist/lib/di/contexts/di-context.js +9 -0
  20. package/dist/lib/di/contexts/module-graph-ensurer.d.ts +31 -0
  21. package/dist/lib/di/contexts/module-graph-ensurer.js +45 -0
  22. package/dist/lib/di/contexts/module-overrides.d.ts +70 -0
  23. package/dist/lib/di/contexts/module-overrides.js +3 -0
  24. package/dist/lib/di/contexts/override-value.types.d.ts +6 -0
  25. package/dist/lib/di/contexts/override-value.types.js +1 -0
  26. package/dist/lib/di/contexts/overrides-processor.d.ts +22 -0
  27. package/dist/lib/di/contexts/overrides-processor.js +93 -0
  28. package/dist/lib/di/contexts/provider-overrides.types.d.ts +19 -0
  29. package/dist/lib/di/contexts/provider-overrides.types.js +1 -0
  30. package/dist/lib/di/errors.d.ts +66 -0
  31. package/dist/lib/di/errors.js +148 -0
  32. package/dist/lib/di/modules/module-def.types.d.ts +117 -0
  33. package/dist/lib/di/modules/module-def.types.js +1 -0
  34. package/dist/lib/di/modules/module-factories.d.ts +16 -0
  35. package/dist/lib/di/modules/module-factories.js +46 -0
  36. package/dist/lib/di/modules/module-overrides.d.ts +70 -0
  37. package/dist/lib/di/modules/module-overrides.js +3 -0
  38. package/dist/lib/di/modules/module-ref.types.d.ts +13 -0
  39. package/dist/lib/di/modules/module-ref.types.js +1 -0
  40. package/dist/lib/di/modules/module.types.d.ts +178 -0
  41. package/dist/lib/di/modules/module.types.js +1 -0
  42. package/dist/lib/di/modules/provider-overrides.types.d.ts +19 -0
  43. package/dist/lib/di/modules/provider-overrides.types.js +1 -0
  44. package/dist/lib/di/modules/runtime-module.types.d.ts +25 -0
  45. package/dist/lib/di/modules/runtime-module.types.js +1 -0
  46. package/dist/lib/di/processors/controller-processor.d.ts +13 -0
  47. package/dist/lib/di/processors/controller-processor.js +76 -0
  48. package/dist/lib/di/processors/handler-processor.d.ts +15 -0
  49. package/dist/lib/di/processors/handler-processor.js +69 -0
  50. package/dist/lib/di/processors/initializer-processor.d.ts +19 -0
  51. package/dist/lib/di/processors/initializer-processor.js +91 -0
  52. package/dist/lib/di/processors/interceptor-processor.d.ts +18 -0
  53. package/dist/lib/di/processors/interceptor-processor.js +101 -0
  54. package/dist/lib/di/processors/keyed-feature-registrar.d.ts +19 -0
  55. package/dist/lib/di/processors/keyed-feature-registrar.js +112 -0
  56. package/dist/lib/di/processors/lifecycle-processor.d.ts +38 -0
  57. package/dist/lib/di/processors/lifecycle-processor.js +178 -0
  58. package/dist/lib/di/processors/overrides-processor.d.ts +24 -0
  59. package/dist/lib/di/processors/overrides-processor.js +69 -0
  60. package/dist/lib/di/providers/basic-provider-resolver.d.ts +35 -0
  61. package/dist/lib/di/providers/basic-provider-resolver.js +88 -0
  62. package/dist/lib/di/providers/provider-dependency-sorter.d.ts +9 -0
  63. package/dist/lib/di/providers/provider-dependency-sorter.js +76 -0
  64. package/dist/lib/di/providers/provider-resolver.d.ts +31 -0
  65. package/dist/lib/di/providers/provider-resolver.js +128 -0
  66. package/dist/lib/di/providers/provider.types.d.ts +1 -0
  67. package/dist/lib/di/providers/provider.types.js +1 -0
  68. package/dist/lib/di/providers/types/controller.types.d.ts +9 -0
  69. package/dist/lib/di/providers/types/controller.types.js +1 -0
  70. package/dist/lib/di/providers/types/decorator-context.types.d.ts +9 -0
  71. package/dist/lib/di/providers/types/decorator-context.types.js +1 -0
  72. package/dist/lib/di/providers/types/handler.types.d.ts +9 -0
  73. package/dist/lib/di/providers/types/handler.types.js +1 -0
  74. package/dist/lib/di/providers/types/index.d.ts +7 -0
  75. package/dist/lib/di/providers/types/index.js +7 -0
  76. package/dist/lib/di/providers/types/initializer.types.d.ts +16 -0
  77. package/dist/lib/di/providers/types/initializer.types.js +3 -0
  78. package/dist/lib/di/providers/types/interceptor.types.d.ts +18 -0
  79. package/dist/lib/di/providers/types/interceptor.types.js +1 -0
  80. package/dist/lib/di/providers/types/middleware.types.d.ts +10 -0
  81. package/dist/lib/di/providers/types/middleware.types.js +1 -0
  82. package/dist/lib/di/providers/types/provider.types.d.ts +26 -0
  83. package/dist/lib/di/providers/types/provider.types.js +1 -0
  84. package/dist/lib/di/request-scope-context.d.ts +5 -0
  85. package/dist/lib/di/request-scope-context.js +28 -0
  86. package/dist/lib/di/type-guards.d.ts +35 -0
  87. package/dist/lib/di/type-guards.js +84 -0
  88. package/dist/lib/http/decorators.d.ts +33 -0
  89. package/dist/lib/http/decorators.js +151 -0
  90. package/dist/lib/http/exceptions.d.ts +58 -0
  91. package/dist/lib/http/exceptions.js +71 -0
  92. package/dist/lib/http/http-verbs.d.ts +12 -0
  93. package/dist/lib/http/http-verbs.js +11 -0
  94. package/dist/lib/http/index.d.ts +3 -0
  95. package/dist/lib/http/index.js +3 -0
  96. package/dist/lib/http/openapi-builder.d.ts +27 -0
  97. package/dist/lib/http/openapi-builder.js +83 -0
  98. package/dist/lib/mediator/contract.types.d.ts +159 -0
  99. package/dist/lib/mediator/contract.types.js +1 -0
  100. package/dist/lib/mediator/errors.d.ts +15 -0
  101. package/dist/lib/mediator/errors.js +33 -0
  102. package/dist/lib/mediator/global-middlewares.types.d.ts +13 -0
  103. package/dist/lib/mediator/global-middlewares.types.js +1 -0
  104. package/dist/lib/mediator/handler.types.d.ts +16 -0
  105. package/dist/lib/mediator/handler.types.js +1 -0
  106. package/dist/lib/mediator/mediator.d.ts +21 -0
  107. package/dist/lib/mediator/mediator.js +123 -0
  108. package/dist/lib/mediator/mediator.types.d.ts +64 -0
  109. package/dist/lib/mediator/mediator.types.js +1 -0
  110. package/dist/lib/mediator/middleware.types.d.ts +41 -0
  111. package/dist/lib/mediator/middleware.types.js +1 -0
  112. package/dist/lib/mediator/result.d.ts +18 -0
  113. package/dist/lib/mediator/result.js +24 -0
  114. package/dist/lib/react/errors.d.ts +12 -0
  115. package/dist/lib/react/errors.js +24 -0
  116. package/dist/lib/react/react-component-processor.d.ts +10 -0
  117. package/dist/lib/react/react-component-processor.js +62 -0
  118. package/dist/lib/react/react-di-context.d.ts +21 -0
  119. package/dist/lib/react/react-di-context.js +55 -0
  120. package/dist/lib/react/react-module-factories.d.ts +6 -0
  121. package/dist/lib/react/react-module-factories.js +34 -0
  122. package/dist/lib/react/react-module.types.d.ts +183 -0
  123. package/dist/lib/react/react-module.types.js +1 -0
  124. package/dist/react.d.ts +4 -0
  125. package/dist/react.js +4 -0
  126. package/dist/tsconfig.tsbuildinfo +1 -0
  127. package/package.json +29 -3
@@ -0,0 +1,27 @@
1
+ export interface RouteRegistration {
2
+ method: string;
3
+ path: string;
4
+ schema: RouteSchema;
5
+ }
6
+ export interface RouteSchema {
7
+ body?: unknown;
8
+ querystring?: unknown;
9
+ params?: unknown;
10
+ headers?: unknown;
11
+ response?: unknown;
12
+ description?: string;
13
+ summary?: string;
14
+ tags?: string[];
15
+ operationId?: string;
16
+ deprecated?: boolean;
17
+ }
18
+ export declare function hasValidationSchema(schema: RouteSchema): boolean;
19
+ export declare class OpenAPIBuilder {
20
+ private routes;
21
+ registerRoute(method: string, path: string, schema: RouteSchema): void;
22
+ buildPaths(): Record<string, any>;
23
+ private buildOperation;
24
+ private buildParameters;
25
+ private buildRequestBody;
26
+ private buildResponses;
27
+ }
@@ -0,0 +1,83 @@
1
+ export function hasValidationSchema(schema) {
2
+ return !!(schema?.body ||
3
+ schema?.querystring ||
4
+ schema?.params ||
5
+ schema?.headers);
6
+ }
7
+ export class OpenAPIBuilder {
8
+ routes = [];
9
+ registerRoute(method, path, schema) {
10
+ this.routes.push({ method: method.toLowerCase(), path, schema });
11
+ }
12
+ buildPaths() {
13
+ return this.routes.reduce((paths, route) => {
14
+ paths[route.path] ??= {};
15
+ paths[route.path][route.method] = this.buildOperation(route.schema);
16
+ return paths;
17
+ }, {});
18
+ }
19
+ buildOperation(schema) {
20
+ const parameters = this.buildParameters(schema);
21
+ const requestBody = this.buildRequestBody(schema);
22
+ const responses = this.buildResponses(schema);
23
+ return {
24
+ ...(schema.summary && { summary: schema.summary }),
25
+ ...(schema.description && { description: schema.description }),
26
+ ...(schema.tags && { tags: schema.tags }),
27
+ ...(schema.operationId && { operationId: schema.operationId }),
28
+ ...(schema.deprecated && { deprecated: schema.deprecated }),
29
+ ...(parameters.length > 0 && { parameters }),
30
+ ...(requestBody && { requestBody }),
31
+ responses,
32
+ };
33
+ }
34
+ buildParameters(schema) {
35
+ const parameters = [];
36
+ const querySchema = schema.querystring;
37
+ if (querySchema?.properties) {
38
+ parameters.push(...Object.entries(querySchema.properties).map(([name, propSchema]) => ({
39
+ name,
40
+ in: "query",
41
+ required: querySchema.required?.includes(name) ?? false,
42
+ schema: propSchema,
43
+ })));
44
+ }
45
+ const paramsSchema = schema.params;
46
+ if (paramsSchema?.properties) {
47
+ parameters.push(...Object.entries(paramsSchema.properties).map(([name, propSchema]) => ({
48
+ name,
49
+ in: "path",
50
+ required: true,
51
+ schema: propSchema,
52
+ })));
53
+ }
54
+ return parameters;
55
+ }
56
+ buildRequestBody(schema) {
57
+ return schema.body
58
+ ? {
59
+ required: true,
60
+ content: {
61
+ "application/json": {
62
+ schema: schema.body,
63
+ },
64
+ },
65
+ }
66
+ : undefined;
67
+ }
68
+ buildResponses(schema) {
69
+ if (!schema.response)
70
+ return {};
71
+ return Object.entries(schema.response).reduce((acc, [statusCode, responseSchema]) => {
72
+ acc[statusCode] = {
73
+ description: statusCode === "200" ? "Successful response" : "Response",
74
+ content: {
75
+ "application/json": {
76
+ schema: responseSchema,
77
+ },
78
+ },
79
+ };
80
+ return acc;
81
+ }, {});
82
+ }
83
+ }
@@ -0,0 +1,159 @@
1
+ import type { EmptyObject } from "../di/common.types.js";
2
+ import type { Module, ModuleDefinition, ModuleImport } from "../di/modules/module.types.js";
3
+ import type { DefPreHandlerMap } from "../di/providers/provider.types.js";
4
+ import type { GlobalCommandPreHandlers, GlobalQueryPreHandlers, NormalizeGlobalPreHandlerMap } from "./global-middlewares.types.js";
5
+ import type { EmptyContext } from "./middleware.types.js";
6
+ type QueryContractModuleDef = {
7
+ queryPreHandlers?: DefPreHandlerMap;
8
+ imports?: readonly ModuleImport[];
9
+ };
10
+ type EmptyModuleDef = Record<never, never>;
11
+ type CommandContractModuleDef = {
12
+ commandPreHandlers?: DefPreHandlerMap;
13
+ imports?: readonly ModuleImport[];
14
+ };
15
+ type ContractScenario<TPreHandlerKey extends string> = {
16
+ name: string;
17
+ includePreHandlerKeys?: readonly TPreHandlerKey[];
18
+ excludePreHandlerKeys?: readonly TPreHandlerKey[];
19
+ };
20
+ type PreHandlerExportKey = "queryPreHandlerExports" | "commandPreHandlerExports";
21
+ type ExtractModuleDef<T> = T extends Module<infer TDef extends ModuleDefinition> ? TDef : T extends Record<string, unknown> ? T : never;
22
+ type ExtractExportedPreHandlerMap<TModuleDef, TExportKey extends PreHandlerExportKey> = TModuleDef extends {
23
+ [K in TExportKey]?: infer E;
24
+ } ? [NonNullable<E>] extends [DefPreHandlerMap] ? NonNullable<E> : EmptyObject : EmptyObject;
25
+ type ExtractPreHandlerMapFromImports<TImports extends readonly ModuleImport[] | undefined, TExportKey extends PreHandlerExportKey> = TImports extends readonly [
26
+ infer First,
27
+ ...infer Rest extends readonly ModuleImport[]
28
+ ] ? ExtractExportedPreHandlerMap<ExtractModuleDef<First>, TExportKey> & ExtractPreHandlerMapFromImports<Rest, TExportKey> : EmptyObject;
29
+ type ExtractMiddlewareContract<M> = M extends {
30
+ readonly contract: infer C;
31
+ } ? C : M extends new (...args: any[]) => infer I ? I extends {
32
+ readonly contract: infer C;
33
+ } ? C : never : M extends {
34
+ useClass: infer U;
35
+ } ? ExtractMiddlewareContract<U> : never;
36
+ type ExtractContextData<T> = T extends Result<infer Data, any> ? Data extends Record<string, unknown> ? Data : never : T extends Record<string, unknown> ? T : never;
37
+ type ExtractContextFromMiddleware<M> = ExtractMiddlewareContract<M> extends {
38
+ returnType: infer R;
39
+ } ? ExtractContextData<R> : never;
40
+ type ExtractErrorFromMiddleware<M> = ExtractMiddlewareContract<M> extends {
41
+ returnType: infer R;
42
+ } ? ExtractResultError<R> : never;
43
+ export type AnyContract = {
44
+ key: string;
45
+ payload: unknown;
46
+ response: unknown;
47
+ returnType?: unknown;
48
+ context?: Record<string, unknown>;
49
+ scenarios?: Record<string, unknown>;
50
+ };
51
+ export type QueryContract<K extends string, P, R, Scenarios extends ContractScenario<QueryPreHandlerKeys<M>> | never = never, M extends QueryContractModuleDef = EmptyModuleDef> = Contract<K, P, R> & WithScenario<QueryContractPreHandlerMap<M>, QueryPreHandlerKeys<M>, R, Scenarios> & {
52
+ returnType: QueryContractReturnType<M, R>;
53
+ context: ResolveQueryContractContext<M, Scenarios>;
54
+ };
55
+ export type CommandContract<K extends string, P, R, Scenarios extends ContractScenario<CommandPreHandlerKeys<M>> | never = never, M extends CommandContractModuleDef = EmptyModuleDef> = Contract<K, P, R> & {
56
+ returnType: CommandContractReturnType<M, R>;
57
+ context: ResolveCommandContractContext<M, Scenarios>;
58
+ } & WithScenario<CommandContractPreHandlerMap<M>, CommandPreHandlerKeys<M>, R, Scenarios>;
59
+ type QueryContractPreHandlerMap<M extends QueryContractModuleDef> = [
60
+ M
61
+ ] extends [never] ? NormalizeGlobalPreHandlerMap<GlobalQueryPreHandlers> : NonNullable<M["queryPreHandlers"]> & NormalizeGlobalPreHandlerMap<GlobalQueryPreHandlers> & ExtractPreHandlerMapFromImports<M["imports"], "queryPreHandlerExports">;
62
+ type CommandContractPreHandlerMap<M extends CommandContractModuleDef> = [
63
+ M
64
+ ] extends [never] ? NormalizeGlobalPreHandlerMap<GlobalCommandPreHandlers> : NonNullable<M["commandPreHandlers"]> & NormalizeGlobalPreHandlerMap<GlobalCommandPreHandlers> & ExtractPreHandlerMapFromImports<M["imports"], "commandPreHandlerExports">;
65
+ type QueryContractReturnType<M extends QueryContractModuleDef, R> = ResolveContractReturnTypeByModule<M, NormalizeGlobalPreHandlerMap<GlobalQueryPreHandlers>, QueryContractPreHandlerMap<M>, R>;
66
+ type CommandContractReturnType<M extends CommandContractModuleDef, R> = ResolveContractReturnTypeByModule<M, NormalizeGlobalPreHandlerMap<GlobalCommandPreHandlers>, CommandContractPreHandlerMap<M>, R>;
67
+ type QueryPreHandlerKeys<M extends QueryContractModuleDef> = [M] extends [never] ? Extract<keyof NormalizeGlobalPreHandlerMap<GlobalQueryPreHandlers>, string> : Extract<keyof NonNullable<M["queryPreHandlers"]>, string> | Extract<keyof NormalizeGlobalPreHandlerMap<GlobalQueryPreHandlers>, string> | Extract<keyof ExtractPreHandlerMapFromImports<M["imports"], "queryPreHandlerExports">, string>;
68
+ type CommandPreHandlerKeys<M extends CommandContractModuleDef> = [M] extends [
69
+ never
70
+ ] ? Extract<keyof NormalizeGlobalPreHandlerMap<GlobalCommandPreHandlers>, string> : Extract<keyof NonNullable<M["commandPreHandlers"]>, string> | Extract<keyof NormalizeGlobalPreHandlerMap<GlobalCommandPreHandlers>, string> | Extract<keyof ExtractPreHandlerMapFromImports<M["imports"], "commandPreHandlerExports">, string>;
71
+ type WithScenario<TPreHandlerMap, TPreHandlerKey extends string, R, Scenarios extends ContractScenario<TPreHandlerKey> | never> = [Scenarios] extends [never] ? Record<never, never> : {
72
+ scenarios: ResolveScenarioResponseMap<TPreHandlerMap, TPreHandlerKey, R, Scenarios>;
73
+ };
74
+ type ExtractIncludedPreHandlerMap<TMap, TAllKeys extends string, TScenario> = NormalizeScenarioWithDefaultInclude<TScenario, TAllKeys> extends {
75
+ includePreHandlerKeys: infer Include extends readonly any[];
76
+ } ? Pick<TMap, Extract<Include[number], TAllKeys>> : TMap;
77
+ type NormalizeScenarioWithDefaultInclude<TScenario, TAllKeys extends string> = TScenario extends {
78
+ includePreHandlerKeys: readonly any[];
79
+ } ? TScenario : TScenario & {
80
+ includePreHandlerKeys: readonly TAllKeys[];
81
+ };
82
+ type ExtractScenarioPreHandlerMap<TMap, TAllKeys extends string, TScenario> = ExtractIncludedPreHandlerMap<TMap, TAllKeys, TScenario> extends infer TIncluded ? TScenario extends {
83
+ excludePreHandlerKeys: infer Exclude extends readonly any[];
84
+ } ? Omit<TIncluded, Extract<Exclude[number], keyof TIncluded>> : TIncluded : EmptyContext;
85
+ type ResolveScenarioContext<TPreHandlerMap, TPreHandlerKey extends string, Scenarios extends ContractScenario<TPreHandlerKey>> = Scenarios extends ContractScenario<TPreHandlerKey> ? ResolveContextOrEmpty<ContextFromPreHandlerMap<ExtractScenarioPreHandlerMap<TPreHandlerMap, TPreHandlerKey, Scenarios>>> : never;
86
+ type ExtractPreHandlerErrorsFromMap<TMap> = [
87
+ Extract<keyof TMap, string>
88
+ ] extends [never] ? never : {
89
+ [K in Extract<keyof TMap, string>]: ExtractErrorFromMiddleware<TMap[K]>;
90
+ }[Extract<keyof TMap, string>];
91
+ type ResolveScenarioResponse<TPreHandlerMap, TPreHandlerKey extends string, R, Scenario extends ContractScenario<TPreHandlerKey>> = ResponseWithErrors<R, ExtractPreHandlerErrorsFromMap<ExtractScenarioPreHandlerMap<TPreHandlerMap, TPreHandlerKey, Scenario>>>;
92
+ type ResolveContractReturnType<TPreHandlerErrors, R> = MergeResponseWithPreHandlerErrors<R, TPreHandlerErrors>;
93
+ type ResolveContractReturnTypeByModule<M, TGlobalPreHandlerMap, TContractPreHandlerMap, R> = [keyof M] extends [never] ? ResolveContractReturnType<ExtractPreHandlerErrorsFromMap<TGlobalPreHandlerMap>, R> : ResolveContractReturnType<ExtractPreHandlerErrorsFromMap<TContractPreHandlerMap>, R>;
94
+ type ResolveScenarioResponseMap<TPreHandlerMap, TPreHandlerKey extends string, R, Scenarios extends ContractScenario<TPreHandlerKey>> = {
95
+ [Scenario in Scenarios as Scenario["name"]]: {
96
+ config: Omit<Scenario, "name">;
97
+ returnType: ResolveScenarioResponse<TPreHandlerMap, TPreHandlerKey, R, Scenario>;
98
+ };
99
+ };
100
+ type ContextFromMiddlewareOrEmpty<TMiddleware> = [
101
+ ExtractContextFromMiddleware<TMiddleware>
102
+ ] extends [never] ? EmptyContext : ExtractContextFromMiddleware<TMiddleware>;
103
+ type ResolveContextOrEmpty<TContext> = [TContext] extends [
104
+ Record<string, unknown>
105
+ ] ? TContext : EmptyContext;
106
+ type ContextFromPreHandlerMap<TMap> = Extract<keyof TMap, string> extends never ? EmptyContext : UnionToIntersection<{
107
+ [K in Extract<keyof TMap, string>]: ContextFromMiddlewareOrEmpty<TMap[K]>;
108
+ }[Extract<keyof TMap, string>]>;
109
+ type Contract<K extends string, P, R> = {
110
+ key: K;
111
+ payload: P;
112
+ response: R;
113
+ };
114
+ type ResolveQueryContractContext<M extends QueryContractModuleDef, Scenarios extends ContractScenario<QueryPreHandlerKeys<M>>> = [Scenarios] extends [never] ? ResolveContextOrEmpty<ContextFromPreHandlerMap<QueryContractPreHandlerMap<M>>> : ResolveScenarioContext<QueryContractPreHandlerMap<M>, QueryPreHandlerKeys<M>, Scenarios>;
115
+ type ResolveCommandContractContext<M extends CommandContractModuleDef, Scenarios extends ContractScenario<CommandPreHandlerKeys<M>>> = [Scenarios] extends [never] ? ResolveContextOrEmpty<ContextFromPreHandlerMap<CommandContractPreHandlerMap<M>>> : ResolveScenarioContext<CommandContractPreHandlerMap<M>, CommandPreHandlerKeys<M>, Scenarios>;
116
+ type ExtractResultSuccess<R> = R extends {
117
+ readonly ok: true;
118
+ readonly value: infer T;
119
+ } ? T : never;
120
+ type ExtractResultError<R> = R extends {
121
+ readonly ok: false;
122
+ readonly error: infer E;
123
+ } ? E : never;
124
+ type IsResult<R> = R extends {
125
+ readonly ok: true;
126
+ readonly value: any;
127
+ } | {
128
+ readonly ok: false;
129
+ readonly error: any;
130
+ } ? true : false;
131
+ type ResponseWithErrors<Response, Errors> = [Errors] extends [never] ? Response : IsResult<Response> extends true ? Result<ExtractResultSuccess<Response>, ExtractResultError<Response> | Errors> : Result<Response, Errors>;
132
+ type Result<Value, Err> = {
133
+ readonly ok: true;
134
+ readonly value: Value;
135
+ readonly error: undefined;
136
+ } | {
137
+ readonly ok: false;
138
+ readonly value: undefined;
139
+ readonly error: Err;
140
+ };
141
+ type MergeResponseWithPreHandlerErrors<TResponse, TPreHandlerError> = [
142
+ TPreHandlerError
143
+ ] extends [never] ? TResponse : [TResponse] extends [{
144
+ readonly ok: true;
145
+ readonly value: infer V;
146
+ }] ? Result<V, TPreHandlerError> : [TResponse] extends [{
147
+ readonly ok: false;
148
+ readonly error: infer E;
149
+ }] ? Result<never, E | TPreHandlerError> : [TResponse] extends [
150
+ {
151
+ readonly ok: true;
152
+ readonly value: infer V;
153
+ } | {
154
+ readonly ok: false;
155
+ readonly error: infer E;
156
+ }
157
+ ] ? Result<V, E | TPreHandlerError> : Result<TResponse, TPreHandlerError>;
158
+ type UnionToIntersection<U> = (U extends any ? (k: U) => void : never) extends (k: infer I) => void ? I : never;
159
+ export {};
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,15 @@
1
+ export declare class HandlerAlreadyRegisteredError extends Error {
2
+ constructor(handlerKey: string);
3
+ }
4
+ export declare class HandlerNotRegisteredError extends Error {
5
+ constructor(handlerKey: string, moduleName: string);
6
+ }
7
+ export declare class InvalidMiddlewareReturnValueError extends Error {
8
+ constructor(middlewareKey: string, returnedType: string);
9
+ }
10
+ export declare class ContextKeyConflictError extends Error {
11
+ constructor(middlewareKey: string, conflictingKeys: string[]);
12
+ }
13
+ export declare class MiddlewareRequiredError extends Error {
14
+ constructor(middlewareKey: string, requiredKey: string);
15
+ }
@@ -0,0 +1,33 @@
1
+ export class HandlerAlreadyRegisteredError extends Error {
2
+ constructor(handlerKey) {
3
+ super(`Handler "${handlerKey}" already registered!`);
4
+ this.name = "HandlerAlreadyRegisteredError";
5
+ }
6
+ }
7
+ export class HandlerNotRegisteredError extends Error {
8
+ constructor(handlerKey, moduleName) {
9
+ super(`Handler key of ${handlerKey} is not registered in module: "${moduleName}"`);
10
+ this.name = "HandlerNotRegisteredError";
11
+ }
12
+ }
13
+ export class InvalidMiddlewareReturnValueError extends Error {
14
+ constructor(middlewareKey, returnedType) {
15
+ super(`Middleware "${middlewareKey}" returned invalid value of type "${returnedType}". ` +
16
+ `Middlewares must return a Result type or a plain object for context merging.`);
17
+ this.name = "InvalidMiddlewareReturnValueError";
18
+ }
19
+ }
20
+ export class ContextKeyConflictError extends Error {
21
+ constructor(middlewareKey, conflictingKeys) {
22
+ super(`Middleware "${middlewareKey}" tried to add context keys that already exist: ${conflictingKeys.join(", ")}. ` +
23
+ `Each middleware must add unique keys to the context.`);
24
+ this.name = "ContextKeyConflictError";
25
+ }
26
+ }
27
+ export class MiddlewareRequiredError extends Error {
28
+ constructor(middlewareKey, requiredKey) {
29
+ super(`Middleware "${middlewareKey}" requires "${requiredKey}" to run before it. ` +
30
+ `Ensure "${requiredKey}" is included and appears before "${middlewareKey}" in the execution order.`);
31
+ this.name = "MiddlewareRequiredError";
32
+ }
33
+ }
@@ -0,0 +1,13 @@
1
+ import type { EmptyObject } from "../di/common.types.js";
2
+ import type { DefPreHandlerMap } from "../di/providers/provider.types.js";
3
+ export interface GlobalQueryPreHandlers {
4
+ }
5
+ export interface GlobalCommandPreHandlers {
6
+ }
7
+ export type NormalizeGlobalPreHandlerMap<T> = [T] extends [DefPreHandlerMap] ? T : EmptyObject;
8
+ export type InferGlobalQueryPreHandlers<TModuleDef> = TModuleDef extends {
9
+ queryPreHandlerExports: infer TPreHandlers;
10
+ } ? NormalizeGlobalPreHandlerMap<TPreHandlers> : EmptyObject;
11
+ export type InferGlobalCommandPreHandlers<TModuleDef> = TModuleDef extends {
12
+ commandPreHandlerExports: infer TPreHandlers;
13
+ } ? NormalizeGlobalPreHandlerMap<TPreHandlers> : EmptyObject;
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,16 @@
1
+ import type { AnyContract } from "./contract.types.js";
2
+ import type { EmptyContext } from "./middleware.types.js";
3
+ export interface Handler<C extends AnyContract, K extends C["key"] = C["key"]> {
4
+ readonly contract: C;
5
+ executor: Executor<ExtractPayload<C, K>, ExtractResponse<C, K>, ExtractContractContext<C>>;
6
+ }
7
+ export type Executor<P = unknown, R = unknown, Ctx extends EmptyContext = EmptyContext> = (payload: P, context: Ctx) => Promise<R>;
8
+ type ExtractContractContext<C extends AnyContract> = C extends {
9
+ context: infer TContext extends Record<string, unknown>;
10
+ } ? TContext : EmptyContext;
11
+ type ExtractContractByKey<C extends AnyContract, K extends C["key"]> = Extract<C, {
12
+ key: K;
13
+ }>;
14
+ export type ExtractPayload<C extends AnyContract, K extends C["key"]> = ExtractContractByKey<C, K>["payload"];
15
+ export type ExtractResponse<C extends AnyContract, K extends C["key"]> = ExtractContractByKey<C, K>["response"];
16
+ export {};
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,21 @@
1
+ import type { AnyContract } from "./contract.types.js";
2
+ import type { Executor, ExtractPayload } from "./handler.types.js";
3
+ import type { ExecuteArgs, ExecuteResponse, ExecuteResponseByScenario, ExecuteRuntimeOptions, ExtractScenarioName } from "./mediator.types.js";
4
+ import type { MiddlewareResolverMap } from "./middleware.types.js";
5
+ export declare class Mediator<C extends AnyContract> {
6
+ private handlers;
7
+ private middlewareResolvers;
8
+ private moduleName;
9
+ constructor(middlewareResolvers: MiddlewareResolverMap, moduleName: string);
10
+ register(key: string, executor: Executor): void;
11
+ execute<K extends C["key"], Name extends ExtractScenarioName<C, K>>(key: K, payload: ExtractPayload<C, K>, options: ExecuteRuntimeOptions<C, K> & {
12
+ scenario: Name;
13
+ }): Promise<ExecuteResponseByScenario<C, K, Name>>;
14
+ execute<K extends C["key"], TOptions extends ExecuteRuntimeOptions<C, K> = ExecuteRuntimeOptions<C, K>>(key: K, payload: ExtractPayload<C, K>, ...args: ExecuteArgs<C, K, TOptions>): Promise<ExecuteResponse<C, K>>;
15
+ private executeMiddlewares;
16
+ private processMiddlewareResult;
17
+ private resolveApplicableMiddlewares;
18
+ private ensureMiddlewareDependencies;
19
+ private mergeContext;
20
+ private isResult;
21
+ }
@@ -0,0 +1,123 @@
1
+ import { runInRequestScopeContext } from "../di/request-scope-context.js";
2
+ import * as errors from "./errors.js";
3
+ import { Result } from "./result.js";
4
+ export class Mediator {
5
+ handlers = new Map();
6
+ middlewareResolvers;
7
+ moduleName;
8
+ constructor(middlewareResolvers, moduleName) {
9
+ this.moduleName = moduleName;
10
+ this.middlewareResolvers = middlewareResolvers;
11
+ }
12
+ register(key, executor) {
13
+ const keyStr = String(key);
14
+ if (this.handlers.has(keyStr)) {
15
+ throw new errors.HandlerAlreadyRegisteredError(keyStr);
16
+ }
17
+ this.handlers.set(keyStr, executor);
18
+ }
19
+ async execute(key, payload, options) {
20
+ return runInRequestScopeContext(async () => {
21
+ const keyStr = String(key);
22
+ const executor = this.handlers.get(keyStr);
23
+ if (!executor) {
24
+ throw new errors.HandlerNotRegisteredError(keyStr, this.moduleName);
25
+ }
26
+ const { executionContext, includePreHandlerKeys, excludePreHandlerKeys } = options ?? {};
27
+ const applicableMiddlewares = this.resolveApplicableMiddlewares({
28
+ excludePreHandlerKeys,
29
+ includePreHandlerKeys,
30
+ });
31
+ const middlewareResult = await this.executeMiddlewares(applicableMiddlewares, payload, executionContext ?? {});
32
+ if (middlewareResult.type === "error") {
33
+ return middlewareResult.error;
34
+ }
35
+ const handlerResult = await executor(payload, middlewareResult.context);
36
+ if (middlewareResult.hasResultMiddleware) {
37
+ return (this.isResult(handlerResult)
38
+ ? handlerResult
39
+ : Result.ok(handlerResult));
40
+ }
41
+ return handlerResult;
42
+ });
43
+ }
44
+ async executeMiddlewares(middlewares, payload, executionContext) {
45
+ let context = {};
46
+ let hasResultMiddleware = false;
47
+ for (const [middlewareKey, middleware] of middlewares) {
48
+ const result = await middleware.execute(payload, context, executionContext);
49
+ if (this.isResult(result)) {
50
+ hasResultMiddleware = true;
51
+ }
52
+ const processed = this.processMiddlewareResult(result, context, middlewareKey);
53
+ if (processed.shouldShortCircuit) {
54
+ return { type: "error", error: processed.result };
55
+ }
56
+ context = processed.context;
57
+ }
58
+ return { type: "success", context, hasResultMiddleware };
59
+ }
60
+ processMiddlewareResult(result, currentContext, middlewareKey) {
61
+ if (this.isResult(result)) {
62
+ return result.ok
63
+ ? {
64
+ shouldShortCircuit: false,
65
+ context: this.mergeContext(currentContext, result.value, middlewareKey),
66
+ }
67
+ : { shouldShortCircuit: true, result };
68
+ }
69
+ return {
70
+ shouldShortCircuit: false,
71
+ context: this.mergeContext(currentContext, result, middlewareKey),
72
+ };
73
+ }
74
+ resolveApplicableMiddlewares(options) {
75
+ const { includePreHandlerKeys = [], excludePreHandlerKeys = [] } = options ?? {};
76
+ const filtered = Array.from(this.middlewareResolvers.entries()).filter(([key]) => {
77
+ if (excludePreHandlerKeys.includes(key)) {
78
+ return false;
79
+ }
80
+ if (includePreHandlerKeys.length > 0) {
81
+ return includePreHandlerKeys.includes(key);
82
+ }
83
+ return true;
84
+ });
85
+ const resolvedMiddlewares = filtered.map(([key, resolver]) => [key, resolver()]);
86
+ this.ensureMiddlewareDependencies(resolvedMiddlewares);
87
+ return resolvedMiddlewares;
88
+ }
89
+ ensureMiddlewareDependencies(middlewares) {
90
+ const processedKeys = [];
91
+ for (const [key, middleware] of middlewares) {
92
+ const requires = middleware.requires || [];
93
+ for (const requiredKey of requires) {
94
+ if (!processedKeys.includes(requiredKey)) {
95
+ throw new errors.MiddlewareRequiredError(key, requiredKey);
96
+ }
97
+ }
98
+ processedKeys.push(key);
99
+ }
100
+ }
101
+ mergeContext(currentContext, data, middlewareKey) {
102
+ if (data === undefined) {
103
+ return currentContext;
104
+ }
105
+ if (typeof data !== "object" || data === null) {
106
+ const returnedType = data === null ? "null" : typeof data;
107
+ throw new errors.InvalidMiddlewareReturnValueError(middlewareKey, returnedType);
108
+ }
109
+ const currentKeys = Object.keys(currentContext);
110
+ const newKeys = Object.keys(data);
111
+ const conflictingKeys = newKeys.filter((key) => currentKeys.includes(key));
112
+ if (conflictingKeys.length > 0) {
113
+ throw new errors.ContextKeyConflictError(middlewareKey, conflictingKeys);
114
+ }
115
+ return { ...currentContext, ...data };
116
+ }
117
+ isResult(value) {
118
+ return (typeof value === "object" &&
119
+ value !== null &&
120
+ "ok" in value &&
121
+ typeof value.ok === "boolean");
122
+ }
123
+ }
@@ -0,0 +1,64 @@
1
+ import type { AnyContract } from "./contract.types.js";
2
+ import type { ExecutionContext } from "./middleware.types.js";
3
+ export type ExtractScenarioName<C extends AnyContract, K extends C["key"]> = Extract<keyof ExtractContractScenarios<C, K>, string>;
4
+ export type ExecuteResponseByScenario<C extends AnyContract, K extends C["key"], Name extends ExtractScenarioName<C, K>> = ExtractScenarioReturnType<C, K, Name>;
5
+ export type ExecuteRuntimeOptions<C extends AnyContract, K extends C["key"]> = ExecutionContextOption & ExecuteOptions<C, K>;
6
+ export type ExecuteArgs<C extends AnyContract, K extends C["key"], TOptions extends ExecuteRuntimeOptions<C, K> = ExecuteRuntimeOptions<C, K>> = IsExecuteOptionsRequired<C, K> extends true ? [options: TOptions] : [options?: never];
7
+ export type ExecuteResponse<C extends AnyContract, K extends C["key"]> = ExtractContractReturnType<C, K>;
8
+ type ExtractContractScenarios<C extends AnyContract, K extends C["key"]> = Extract<C, {
9
+ key: K;
10
+ }> extends {
11
+ scenarios: infer S extends Record<string, unknown>;
12
+ } ? S : never;
13
+ type ExtractScenarioByName<C extends AnyContract, K extends C["key"], Name extends string> = Name extends keyof ExtractContractScenarios<C, K> ? ExtractContractScenarios<C, K>[Name] : never;
14
+ type ExtractScenarioConfig<C extends AnyContract, K extends C["key"], Name extends string> = ExtractScenarioByName<C, K, Name> extends {
15
+ config: infer Config;
16
+ } ? Config : never;
17
+ type ExtractScenarioReturnType<C extends AnyContract, K extends C["key"], Name extends string> = ExtractScenarioByName<C, K, Name> extends {
18
+ returnType: infer ReturnType;
19
+ } ? ReturnType : ExtractContractReturnType<C, K>;
20
+ type ExecuteNoScenarioOptions = {
21
+ scenario?: never;
22
+ includePreHandlerKeys?: never;
23
+ excludePreHandlerKeys?: never;
24
+ };
25
+ type ExecuteOptions<C extends AnyContract, K extends C["key"]> = [
26
+ ExtractContractScenarios<C, K>
27
+ ] extends [never] ? ExecuteNoScenarioOptions : ExecuteScenarioOptions<C, K>;
28
+ type ScenarioIncludeOption<C extends AnyContract, K extends C["key"], Name extends string> = ExtractScenarioConfig<C, K, Name> extends {
29
+ includePreHandlerKeys: infer Include extends readonly any[];
30
+ } ? {
31
+ includePreHandlerKeys: Include;
32
+ } : {
33
+ includePreHandlerKeys?: never;
34
+ };
35
+ type ScenarioExcludeOption<C extends AnyContract, K extends C["key"], Name extends string> = ExtractScenarioConfig<C, K, Name> extends {
36
+ excludePreHandlerKeys: infer Exclude extends readonly any[];
37
+ } ? {
38
+ excludePreHandlerKeys: Exclude;
39
+ } : {
40
+ excludePreHandlerKeys?: never;
41
+ };
42
+ type ExecuteScenarioOptions<C extends AnyContract, K extends C["key"]> = {
43
+ [Name in ExtractScenarioName<C, K>]: {
44
+ scenario: Name;
45
+ } & ScenarioIncludeOption<C, K, Name> & ScenarioExcludeOption<C, K, Name>;
46
+ }[ExtractScenarioName<C, K>];
47
+ type ExecutionContextOption = [keyof ExecutionContext] extends [never] ? {
48
+ executionContext?: never;
49
+ } : {
50
+ executionContext: ExecutionContext;
51
+ };
52
+ type HasScenarios<C extends AnyContract, K extends C["key"]> = [
53
+ ExtractContractScenarios<C, K>
54
+ ] extends [never] ? false : true;
55
+ type IsExecutionContextRequired = [keyof ExecutionContext] extends [never] ? false : true;
56
+ type IsExecuteOptionsRequired<C extends AnyContract, K extends C["key"]> = HasScenarios<C, K> extends true ? true : IsExecutionContextRequired;
57
+ type ExtractContractReturnType<C extends AnyContract, K extends C["key"]> = Extract<C, {
58
+ key: K;
59
+ }> extends {
60
+ returnType: infer ReturnType;
61
+ } ? ReturnType : Extract<C, {
62
+ key: K;
63
+ }>["response"];
64
+ export {};
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,41 @@
1
+ import type { Result } from "./result.js";
2
+ type EmptyObject = Record<never, never>;
3
+ export interface ExecutionContext {
4
+ }
5
+ export type EmptyContext = EmptyObject;
6
+ export type AnyMiddlewareContract = MiddlewareContract<string, unknown, any>;
7
+ export type AnyContext = Record<string, unknown>;
8
+ export type MiddlewareResolver = () => Middleware;
9
+ export type MiddlewareResolverMap = Map<string, () => Middleware>;
10
+ export type Middleware<C extends AnyMiddlewareContract = AnyMiddlewareContract> = MiddlewareRequires<C> & {
11
+ readonly contract: C;
12
+ execute: MiddlewareFn<ExtractContractContext<C>, ExtractMiddlewareReturnType<C>>;
13
+ };
14
+ export type ExtractMiddlewareContext<T> = [T] extends [Result<infer Data, any>] ? Data extends Record<string, unknown> ? Data : EmptyObject : T extends Record<string, unknown> ? T : EmptyObject;
15
+ export type MiddlewareContract<K extends string, ReturnType, RequiredContracts extends readonly AnyMiddlewareContract[] = readonly []> = {
16
+ key: K;
17
+ returnType: ReturnType;
18
+ requires: ExtractRequiredKeysTupleFromContracts<RequiredContracts>;
19
+ context: MergeContextFromContracts<RequiredContracts>;
20
+ executionContext: ExecutionContext;
21
+ };
22
+ type ExtractRequiredKeysTupleFromContracts<Contracts extends readonly AnyMiddlewareContract[]> = number extends Contracts["length"] ? readonly string[] : Contracts extends readonly [] ? readonly [] : Contracts extends readonly [infer First, ...infer Rest] ? First extends AnyMiddlewareContract ? Rest extends readonly AnyMiddlewareContract[] ? readonly [
23
+ First["key"],
24
+ ...ExtractRequiredKeysTupleFromContracts<Rest>
25
+ ] : readonly [First["key"]] : readonly [] : readonly [];
26
+ type MergeContextFromContracts<Contracts extends readonly AnyMiddlewareContract[]> = number extends Contracts["length"] ? AnyContext : Contracts extends readonly [] ? EmptyObject : Contracts extends readonly [infer First, ...infer Rest] ? First extends AnyMiddlewareContract ? Rest extends readonly AnyMiddlewareContract[] ? ExtractMiddlewareContext<First["returnType"]> & MergeContextFromContracts<Rest> : ExtractMiddlewareContext<First["returnType"]> : EmptyObject : EmptyObject;
27
+ type ExtractMiddlewareReturnType<C extends AnyMiddlewareContract> = C["returnType"];
28
+ type ExtractRequiredKeys<C extends AnyMiddlewareContract> = C["requires"][number];
29
+ type ExtractRequiredList<C extends AnyMiddlewareContract> = C["requires"];
30
+ type ExtractContractContext<C extends AnyMiddlewareContract> = C["context"];
31
+ type MiddlewareFn<RequiredContext extends AnyContext = EmptyContext, ReturnType = unknown> = (payload: unknown, context: RequiredContext, executionContext: ExecutionContext) => Promise<ReturnType>;
32
+ type MiddlewareRequires<C extends AnyMiddlewareContract> = [
33
+ ExtractRequiredKeys<C>
34
+ ] extends [never] ? {
35
+ readonly requires?: readonly [];
36
+ } : string extends ExtractRequiredKeys<C> ? {
37
+ readonly requires?: readonly string[];
38
+ } : {
39
+ readonly requires: ExtractRequiredList<C>;
40
+ };
41
+ export {};
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,18 @@
1
+ export type Result<T, E> = Ok<T> | Err<E>;
2
+ declare class Ok<T> {
3
+ readonly value: T;
4
+ readonly ok: true;
5
+ readonly error: undefined;
6
+ constructor(value: T);
7
+ }
8
+ declare class Err<E> {
9
+ readonly error: E;
10
+ readonly ok: false;
11
+ readonly value: undefined;
12
+ constructor(error: E);
13
+ }
14
+ export declare const Result: {
15
+ ok<T>(value: T): Result<T, never>;
16
+ error<E>(error: E): Result<never, E>;
17
+ };
18
+ export {};