@cosmneo/onion-lasagna 0.2.1 → 0.3.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/dist/chunk-36IO4BM7.js +113 -0
- package/dist/chunk-36IO4BM7.js.map +1 -0
- package/dist/chunk-4BVOLXDJ.js +54 -0
- package/dist/chunk-4BVOLXDJ.js.map +1 -0
- package/dist/chunk-CBTICRSM.js +34 -0
- package/dist/chunk-CBTICRSM.js.map +1 -0
- package/dist/chunk-KJ4JGZOE.js +96 -0
- package/dist/chunk-KJ4JGZOE.js.map +1 -0
- package/dist/chunk-RVSBIYY4.js +1 -0
- package/dist/chunk-RVSBIYY4.js.map +1 -0
- package/dist/chunk-XWKHOLIP.js +191 -0
- package/dist/chunk-XWKHOLIP.js.map +1 -0
- package/dist/event-router-definition.type-CP9uTlux.d.cts +150 -0
- package/dist/event-router-definition.type-D8CG-kjZ.d.ts +150 -0
- package/dist/events/asyncapi/index.cjs +143 -0
- package/dist/events/asyncapi/index.cjs.map +1 -0
- package/dist/events/asyncapi/index.d.cts +184 -0
- package/dist/events/asyncapi/index.d.ts +184 -0
- package/dist/events/asyncapi/index.js +8 -0
- package/dist/events/asyncapi/index.js.map +1 -0
- package/dist/events/handler/index.cjs +171 -0
- package/dist/events/handler/index.cjs.map +1 -0
- package/dist/events/handler/index.d.cts +153 -0
- package/dist/events/handler/index.d.ts +153 -0
- package/dist/events/handler/index.js +21 -0
- package/dist/events/handler/index.js.map +1 -0
- package/dist/events/index.cjs +497 -0
- package/dist/events/index.cjs.map +1 -0
- package/dist/events/index.d.cts +9 -0
- package/dist/events/index.d.ts +9 -0
- package/dist/events/index.js +41 -0
- package/dist/events/index.js.map +1 -0
- package/dist/events/server/index.cjs +291 -0
- package/dist/events/server/index.cjs.map +1 -0
- package/dist/events/server/index.d.cts +281 -0
- package/dist/events/server/index.d.ts +281 -0
- package/dist/events/server/index.js +16 -0
- package/dist/events/server/index.js.map +1 -0
- package/dist/events/shared/index.cjs +85 -0
- package/dist/events/shared/index.cjs.map +1 -0
- package/dist/events/shared/index.d.cts +35 -0
- package/dist/events/shared/index.d.ts +35 -0
- package/dist/events/shared/index.js +13 -0
- package/dist/events/shared/index.js.map +1 -0
- package/dist/http/index.d.cts +2 -1
- package/dist/http/index.d.ts +2 -1
- package/dist/http/index.js +3 -3
- package/dist/http/server/index.d.cts +4 -261
- package/dist/http/server/index.d.ts +4 -261
- package/dist/types-B6Q1iCgf.d.ts +262 -0
- package/dist/types-afYpL7Ap.d.cts +262 -0
- package/dist/types-cke61juH.d.cts +42 -0
- package/dist/types-cke61juH.d.ts +42 -0
- package/package.json +35 -2
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
import {
|
|
2
|
+
isEventHandlerDefinition,
|
|
3
|
+
isEventRouterDefinition
|
|
4
|
+
} from "./chunk-CBTICRSM.js";
|
|
5
|
+
|
|
6
|
+
// src/presentation/events/handler/define-event-handler.ts
|
|
7
|
+
function defineEventHandler(input) {
|
|
8
|
+
const definition = {
|
|
9
|
+
eventType: input.eventType,
|
|
10
|
+
payload: input.payload ?? void 0,
|
|
11
|
+
context: input.context ?? void 0,
|
|
12
|
+
docs: {
|
|
13
|
+
summary: input.docs?.summary,
|
|
14
|
+
description: input.docs?.description,
|
|
15
|
+
tags: input.docs?.tags,
|
|
16
|
+
deprecated: input.docs?.deprecated ?? false
|
|
17
|
+
},
|
|
18
|
+
_types: void 0
|
|
19
|
+
};
|
|
20
|
+
return Object.freeze(definition);
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
// src/presentation/events/handler/define-event-router.ts
|
|
24
|
+
function defineEventRouter(handlers, options) {
|
|
25
|
+
const defaults = options?.defaults;
|
|
26
|
+
const processedHandlers = defaults?.context || defaults?.tags ? applyEventRouterDefaults(handlers, defaults) : handlers;
|
|
27
|
+
const definition = {
|
|
28
|
+
handlers: processedHandlers,
|
|
29
|
+
defaults,
|
|
30
|
+
_isEventRouter: true
|
|
31
|
+
};
|
|
32
|
+
return deepFreeze(definition);
|
|
33
|
+
}
|
|
34
|
+
function applyEventRouterDefaults(handlers, defaults) {
|
|
35
|
+
const result = {};
|
|
36
|
+
for (const [key, value] of Object.entries(handlers)) {
|
|
37
|
+
if (isEventHandlerDefinition(value)) {
|
|
38
|
+
result[key] = applyDefaultsToEventHandler(value, defaults);
|
|
39
|
+
} else if (isEventRouterDefinition(value)) {
|
|
40
|
+
result[key] = {
|
|
41
|
+
...value,
|
|
42
|
+
handlers: applyEventRouterDefaults(value.handlers, defaults)
|
|
43
|
+
};
|
|
44
|
+
} else if (typeof value === "object" && value !== null) {
|
|
45
|
+
result[key] = applyEventRouterDefaults(value, defaults);
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
return result;
|
|
49
|
+
}
|
|
50
|
+
function applyDefaultsToEventHandler(handler, defaults) {
|
|
51
|
+
const needsContext = defaults.context && !handler.context;
|
|
52
|
+
const needsTags = defaults.tags && defaults.tags.length > 0;
|
|
53
|
+
if (!needsContext && !needsTags) return handler;
|
|
54
|
+
return Object.freeze({
|
|
55
|
+
...handler,
|
|
56
|
+
context: handler.context ?? defaults.context ?? void 0,
|
|
57
|
+
docs: {
|
|
58
|
+
...handler.docs,
|
|
59
|
+
tags: mergeTags(defaults.tags, handler.docs.tags)
|
|
60
|
+
}
|
|
61
|
+
});
|
|
62
|
+
}
|
|
63
|
+
function mergeTags(routerTags, handlerTags) {
|
|
64
|
+
if (!routerTags || routerTags.length === 0) return handlerTags;
|
|
65
|
+
if (!handlerTags || handlerTags.length === 0) return routerTags;
|
|
66
|
+
const merged = [...routerTags];
|
|
67
|
+
for (const tag of handlerTags) {
|
|
68
|
+
if (!merged.includes(tag)) {
|
|
69
|
+
merged.push(tag);
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
return merged;
|
|
73
|
+
}
|
|
74
|
+
function deepFreeze(obj) {
|
|
75
|
+
const propNames = Object.getOwnPropertyNames(obj);
|
|
76
|
+
for (const name of propNames) {
|
|
77
|
+
const value = obj[name];
|
|
78
|
+
if (value && typeof value === "object" && !Object.isFrozen(value)) {
|
|
79
|
+
deepFreeze(value);
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
return Object.freeze(obj);
|
|
83
|
+
}
|
|
84
|
+
function extractHandlers(input) {
|
|
85
|
+
return isEventRouterDefinition(input) ? input.handlers : input;
|
|
86
|
+
}
|
|
87
|
+
function isSubRouter(value) {
|
|
88
|
+
return typeof value === "object" && value !== null && !isEventHandlerDefinition(value) && !isEventRouterDefinition(value);
|
|
89
|
+
}
|
|
90
|
+
function deepMergeConfigs(a, b) {
|
|
91
|
+
const result = { ...a };
|
|
92
|
+
for (const key of Object.keys(b)) {
|
|
93
|
+
const aVal = result[key];
|
|
94
|
+
const bVal = b[key];
|
|
95
|
+
if (isSubRouter(aVal) && isSubRouter(bVal)) {
|
|
96
|
+
result[key] = deepMergeConfigs(aVal, bVal);
|
|
97
|
+
} else {
|
|
98
|
+
result[key] = bVal;
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
return result;
|
|
102
|
+
}
|
|
103
|
+
function mergeEventRouters(...routers) {
|
|
104
|
+
const merged = routers.map(extractHandlers).reduce(deepMergeConfigs);
|
|
105
|
+
return defineEventRouter(merged);
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
export {
|
|
109
|
+
defineEventHandler,
|
|
110
|
+
defineEventRouter,
|
|
111
|
+
mergeEventRouters
|
|
112
|
+
};
|
|
113
|
+
//# sourceMappingURL=chunk-36IO4BM7.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/presentation/events/handler/define-event-handler.ts","../src/presentation/events/handler/define-event-router.ts"],"sourcesContent":["/**\n * @fileoverview Factory function for creating event handler definitions.\n *\n * The `defineEventHandler` function is the main entry point for defining\n * event handlers. It mirrors `defineRoute` from the HTTP layer but is\n * tailored for asynchronous event processing.\n *\n * @module events/handler/define-event-handler\n */\n\nimport type { SchemaAdapter, InferOutput } from '../../http/schema/types';\nimport type { EventHandlerDefinition } from './types';\n\n// ============================================================================\n// Input Types\n// ============================================================================\n\n/**\n * Input for defineEventHandler.\n *\n * @example Basic handler with payload schema\n * ```typescript\n * defineEventHandler({\n * eventType: 'ticket.created',\n * payload: zodSchema(z.object({ ticketId: z.string() })),\n * docs: { summary: 'Handle ticket creation', tags: ['ticket'] },\n * })\n * ```\n *\n * @example With context schema\n * ```typescript\n * defineEventHandler({\n * eventType: 'order.shipped',\n * payload: zodSchema(orderShippedSchema),\n * context: zodSchema(eventMetadataSchema),\n * })\n * ```\n */\ninterface DefineEventHandlerInput<\n TEventType extends string,\n TPayload extends SchemaAdapter | undefined = undefined,\n TContext extends SchemaAdapter | undefined = undefined,\n> {\n /** Event type string used for routing (e.g., 'ticket.created'). */\n readonly eventType: TEventType;\n\n /** Payload validation schema. */\n readonly payload?: TPayload;\n\n /** Context validation schema (validates event metadata). */\n readonly context?: TContext;\n\n /** Handler documentation. */\n readonly docs?: {\n readonly summary?: string;\n readonly description?: string;\n readonly tags?: readonly string[];\n readonly deprecated?: boolean;\n };\n}\n\n// ============================================================================\n// Return type helpers\n// ============================================================================\n\ntype ResolvePayload<T> = T extends SchemaAdapter ? InferOutput<T> : undefined;\ntype ResolveContext<T> = T extends SchemaAdapter ? InferOutput<T> : undefined;\n\n// ============================================================================\n// Factory Function\n// ============================================================================\n\n/**\n * Creates an event handler definition from the provided configuration.\n *\n * This is the main entry point for defining event handlers. The resulting\n * definition can be used for type-safe handler registration, payload\n * validation, and documentation generation.\n *\n * @param input - Event handler configuration with optional schemas\n * @returns A frozen EventHandlerDefinition object with full type information\n */\nexport function defineEventHandler<\n TEventType extends string,\n TPayload extends SchemaAdapter | undefined = undefined,\n TContext extends SchemaAdapter | undefined = undefined,\n>(\n input: DefineEventHandlerInput<TEventType, TPayload, TContext>,\n): EventHandlerDefinition<TEventType, ResolvePayload<TPayload>, ResolveContext<TContext>> {\n const definition = {\n eventType: input.eventType,\n payload: input.payload ?? undefined,\n context: input.context ?? undefined,\n docs: {\n summary: input.docs?.summary,\n description: input.docs?.description,\n tags: input.docs?.tags,\n deprecated: input.docs?.deprecated ?? false,\n },\n _types: undefined as unknown,\n };\n\n return Object.freeze(definition) as EventHandlerDefinition<\n TEventType,\n ResolvePayload<TPayload>,\n ResolveContext<TContext>\n >;\n}\n","/**\n * @fileoverview Factory function for creating event router definitions.\n *\n * The `defineEventRouter` function groups event handlers into a hierarchical\n * structure with optional router-level defaults for context and tags.\n *\n * @module events/handler/define-event-router\n */\n\nimport type {\n EventRouterConfig,\n EventRouterDefaults,\n EventRouterDefinition,\n EventHandlerDefinition,\n DeepMergeTwo,\n DeepMergeAll,\n} from './types';\nimport { isEventHandlerDefinition, isEventRouterDefinition } from './types';\n\n/**\n * Options for event router definition.\n */\nexport interface DefineEventRouterOptions {\n /**\n * Default values applied to all child handlers.\n *\n * @example\n * ```typescript\n * defineEventRouter({\n * created: onTicketCreated,\n * assigned: onTicketAssigned,\n * }, {\n * defaults: {\n * context: zodSchema(eventMetadataSchema),\n * tags: ['ticket'],\n * },\n * })\n * ```\n */\n readonly defaults?: EventRouterDefaults;\n}\n\n/**\n * Creates an event router definition from a configuration object.\n *\n * @param handlers - Object containing event handlers and nested routers\n * @param options - Optional router configuration\n * @returns A frozen EventRouterDefinition object\n *\n * @example Basic router\n * ```typescript\n * const ticketEvents = defineEventRouter({\n * created: onTicketCreated,\n * assigned: onTicketAssigned,\n * transferred: onTicketTransferred,\n * });\n * ```\n *\n * @example Nested router\n * ```typescript\n * const events = defineEventRouter({\n * ticket: {\n * created: onTicketCreated,\n * assigned: onTicketAssigned,\n * },\n * ecosystem: {\n * memberAdded: onMemberAdded,\n * },\n * });\n * ```\n */\nexport function defineEventRouter<T extends EventRouterConfig>(\n handlers: T,\n options?: DefineEventRouterOptions,\n): EventRouterDefinition<T> {\n const defaults = options?.defaults;\n\n const processedHandlers =\n defaults?.context || defaults?.tags\n ? (applyEventRouterDefaults(handlers, defaults) as T)\n : handlers;\n\n const definition: EventRouterDefinition<T> = {\n handlers: processedHandlers,\n defaults,\n _isEventRouter: true,\n };\n\n return deepFreeze(definition);\n}\n\n/**\n * Recursively applies router-level defaults to all handlers in the tree.\n */\nfunction applyEventRouterDefaults(\n handlers: EventRouterConfig,\n defaults: EventRouterDefaults,\n): EventRouterConfig {\n const result: Record<string, unknown> = {};\n\n for (const [key, value] of Object.entries(handlers)) {\n if (isEventHandlerDefinition(value)) {\n result[key] = applyDefaultsToEventHandler(value, defaults);\n } else if (isEventRouterDefinition(value)) {\n result[key] = {\n ...value,\n handlers: applyEventRouterDefaults(value.handlers, defaults),\n };\n } else if (typeof value === 'object' && value !== null) {\n result[key] = applyEventRouterDefaults(value as EventRouterConfig, defaults);\n }\n }\n\n return result as EventRouterConfig;\n}\n\n/**\n * Applies router-level defaults to a single event handler definition.\n */\nfunction applyDefaultsToEventHandler(\n handler: EventHandlerDefinition,\n defaults: EventRouterDefaults,\n): EventHandlerDefinition {\n const needsContext = defaults.context && !handler.context;\n const needsTags = defaults.tags && defaults.tags.length > 0;\n\n if (!needsContext && !needsTags) return handler;\n\n return Object.freeze({\n ...handler,\n context: handler.context ?? defaults.context ?? undefined,\n docs: {\n ...handler.docs,\n tags: mergeTags(defaults.tags, handler.docs.tags),\n },\n }) as EventHandlerDefinition;\n}\n\n/**\n * Merges router-level tags with handler-level tags, avoiding duplicates.\n */\nfunction mergeTags(\n routerTags?: readonly string[],\n handlerTags?: readonly string[],\n): readonly string[] | undefined {\n if (!routerTags || routerTags.length === 0) return handlerTags;\n if (!handlerTags || handlerTags.length === 0) return routerTags;\n\n const merged = [...routerTags];\n for (const tag of handlerTags) {\n if (!merged.includes(tag)) {\n merged.push(tag);\n }\n }\n return merged;\n}\n\n/**\n * Deep freezes an object and all its nested objects.\n */\nfunction deepFreeze<T extends object>(obj: T): T {\n const propNames = Object.getOwnPropertyNames(obj) as (keyof T)[];\n\n for (const name of propNames) {\n const value = obj[name];\n if (value && typeof value === 'object' && !Object.isFrozen(value)) {\n deepFreeze(value);\n }\n }\n\n return Object.freeze(obj);\n}\n\n// ============================================================================\n// mergeEventRouters — variadic deep merge\n// ============================================================================\n\ntype EventRouterInput<T extends EventRouterConfig> = T | EventRouterDefinition<T>;\n\n/** Extracts the raw EventRouterConfig from either a plain config or an EventRouterDefinition. */\nfunction extractHandlers<T extends EventRouterConfig>(input: EventRouterInput<T>): T {\n return isEventRouterDefinition(input) ? input.handlers : input;\n}\n\n/** Returns true if `value` is a plain sub-router object. */\nfunction isSubRouter(value: unknown): value is EventRouterConfig {\n return (\n typeof value === 'object' &&\n value !== null &&\n !isEventHandlerDefinition(value) &&\n !isEventRouterDefinition(value)\n );\n}\n\n/** Recursively deep-merges two router configs. Sub-routers are merged; leaves are overwritten. */\nfunction deepMergeConfigs(a: EventRouterConfig, b: EventRouterConfig): EventRouterConfig {\n const result: Record<string, unknown> = { ...a };\n\n for (const key of Object.keys(b)) {\n const aVal = result[key];\n const bVal = b[key];\n\n if (isSubRouter(aVal) && isSubRouter(bVal)) {\n result[key] = deepMergeConfigs(aVal, bVal);\n } else {\n result[key] = bVal;\n }\n }\n\n return result as EventRouterConfig;\n}\n\n// Overloads for 2–8 routers\nexport function mergeEventRouters<T1 extends EventRouterConfig, T2 extends EventRouterConfig>(\n r1: EventRouterInput<T1>,\n r2: EventRouterInput<T2>,\n): EventRouterDefinition<DeepMergeTwo<T1, T2>>;\nexport function mergeEventRouters<\n T1 extends EventRouterConfig,\n T2 extends EventRouterConfig,\n T3 extends EventRouterConfig,\n>(\n r1: EventRouterInput<T1>,\n r2: EventRouterInput<T2>,\n r3: EventRouterInput<T3>,\n): EventRouterDefinition<DeepMergeAll<[T1, T2, T3]>>;\nexport function mergeEventRouters<\n T1 extends EventRouterConfig,\n T2 extends EventRouterConfig,\n T3 extends EventRouterConfig,\n T4 extends EventRouterConfig,\n>(\n r1: EventRouterInput<T1>,\n r2: EventRouterInput<T2>,\n r3: EventRouterInput<T3>,\n r4: EventRouterInput<T4>,\n): EventRouterDefinition<DeepMergeAll<[T1, T2, T3, T4]>>;\nexport function mergeEventRouters<\n T1 extends EventRouterConfig,\n T2 extends EventRouterConfig,\n T3 extends EventRouterConfig,\n T4 extends EventRouterConfig,\n T5 extends EventRouterConfig,\n>(\n r1: EventRouterInput<T1>,\n r2: EventRouterInput<T2>,\n r3: EventRouterInput<T3>,\n r4: EventRouterInput<T4>,\n r5: EventRouterInput<T5>,\n): EventRouterDefinition<DeepMergeAll<[T1, T2, T3, T4, T5]>>;\nexport function mergeEventRouters<\n T1 extends EventRouterConfig,\n T2 extends EventRouterConfig,\n T3 extends EventRouterConfig,\n T4 extends EventRouterConfig,\n T5 extends EventRouterConfig,\n T6 extends EventRouterConfig,\n>(\n r1: EventRouterInput<T1>,\n r2: EventRouterInput<T2>,\n r3: EventRouterInput<T3>,\n r4: EventRouterInput<T4>,\n r5: EventRouterInput<T5>,\n r6: EventRouterInput<T6>,\n): EventRouterDefinition<DeepMergeAll<[T1, T2, T3, T4, T5, T6]>>;\nexport function mergeEventRouters<\n T1 extends EventRouterConfig,\n T2 extends EventRouterConfig,\n T3 extends EventRouterConfig,\n T4 extends EventRouterConfig,\n T5 extends EventRouterConfig,\n T6 extends EventRouterConfig,\n T7 extends EventRouterConfig,\n>(\n r1: EventRouterInput<T1>,\n r2: EventRouterInput<T2>,\n r3: EventRouterInput<T3>,\n r4: EventRouterInput<T4>,\n r5: EventRouterInput<T5>,\n r6: EventRouterInput<T6>,\n r7: EventRouterInput<T7>,\n): EventRouterDefinition<DeepMergeAll<[T1, T2, T3, T4, T5, T6, T7]>>;\nexport function mergeEventRouters<\n T1 extends EventRouterConfig,\n T2 extends EventRouterConfig,\n T3 extends EventRouterConfig,\n T4 extends EventRouterConfig,\n T5 extends EventRouterConfig,\n T6 extends EventRouterConfig,\n T7 extends EventRouterConfig,\n T8 extends EventRouterConfig,\n>(\n r1: EventRouterInput<T1>,\n r2: EventRouterInput<T2>,\n r3: EventRouterInput<T3>,\n r4: EventRouterInput<T4>,\n r5: EventRouterInput<T5>,\n r6: EventRouterInput<T6>,\n r7: EventRouterInput<T7>,\n r8: EventRouterInput<T8>,\n): EventRouterDefinition<DeepMergeAll<[T1, T2, T3, T4, T5, T6, T7, T8]>>;\n\n// Variadic fallback for 9+\nexport function mergeEventRouters(\n ...routers: EventRouterInput<EventRouterConfig>[]\n): EventRouterDefinition<EventRouterConfig>;\n\n// Implementation\nexport function mergeEventRouters(\n ...routers: EventRouterInput<EventRouterConfig>[]\n): EventRouterDefinition<EventRouterConfig> {\n const merged = routers.map(extractHandlers).reduce(deepMergeConfigs);\n return defineEventRouter(merged);\n}\n"],"mappings":"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","names":[]}
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
import {
|
|
2
|
+
isErrorType
|
|
3
|
+
} from "./chunk-H5TNDC5U.js";
|
|
4
|
+
|
|
5
|
+
// src/presentation/events/shared/error-mapping.ts
|
|
6
|
+
var DLQ_ERROR_TYPES = [
|
|
7
|
+
"ObjectValidationError",
|
|
8
|
+
"InvalidRequestError",
|
|
9
|
+
"UseCaseError",
|
|
10
|
+
"DomainError",
|
|
11
|
+
"UnprocessableError",
|
|
12
|
+
"AccessDeniedError",
|
|
13
|
+
"ForbiddenError",
|
|
14
|
+
"UnauthorizedError",
|
|
15
|
+
"InvariantViolationError"
|
|
16
|
+
];
|
|
17
|
+
var RETRY_ERROR_TYPES = [
|
|
18
|
+
"NotFoundError",
|
|
19
|
+
"ConflictError",
|
|
20
|
+
"InfraError",
|
|
21
|
+
"DbError",
|
|
22
|
+
"NetworkError",
|
|
23
|
+
"TimeoutError",
|
|
24
|
+
"ExternalServiceError",
|
|
25
|
+
"PersistenceError"
|
|
26
|
+
];
|
|
27
|
+
function mapErrorToEventResult(error) {
|
|
28
|
+
for (const typeName of DLQ_ERROR_TYPES) {
|
|
29
|
+
if (isErrorType(error, typeName)) {
|
|
30
|
+
return {
|
|
31
|
+
outcome: "dlq",
|
|
32
|
+
reason: error.message
|
|
33
|
+
};
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
for (const typeName of RETRY_ERROR_TYPES) {
|
|
37
|
+
if (isErrorType(error, typeName)) {
|
|
38
|
+
return {
|
|
39
|
+
outcome: "retry",
|
|
40
|
+
reason: error.message
|
|
41
|
+
};
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
const message = error instanceof Error ? error.message : "Unknown error occurred during event processing";
|
|
45
|
+
return {
|
|
46
|
+
outcome: "retry",
|
|
47
|
+
reason: message
|
|
48
|
+
};
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
export {
|
|
52
|
+
mapErrorToEventResult
|
|
53
|
+
};
|
|
54
|
+
//# sourceMappingURL=chunk-4BVOLXDJ.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/presentation/events/shared/error-mapping.ts"],"sourcesContent":["/**\n * @fileoverview Error-to-EventResult mapping for event handlers.\n *\n * Maps caught errors to event processing outcomes (ack/retry/dlq).\n * Uses the same name-based type checking as the HTTP error mapper\n * for compatibility with bundled/minified code.\n *\n * @module events/shared/error-mapping\n */\n\nimport { isErrorType } from '../../http/shared/error-mapping';\nimport type { EventResult } from './types';\n\n// ============================================================================\n// Error Type Classifications\n// ============================================================================\n\n/**\n * Error types that indicate permanent failures (send to DLQ).\n * These errors will not resolve on retry.\n */\nconst DLQ_ERROR_TYPES = [\n 'ObjectValidationError',\n 'InvalidRequestError',\n 'UseCaseError',\n 'DomainError',\n 'UnprocessableError',\n 'AccessDeniedError',\n 'ForbiddenError',\n 'UnauthorizedError',\n 'InvariantViolationError',\n];\n\n/**\n * Error types that indicate transient failures (retry).\n * These errors may resolve on subsequent attempts.\n */\nconst RETRY_ERROR_TYPES = [\n 'NotFoundError',\n 'ConflictError',\n 'InfraError',\n 'DbError',\n 'NetworkError',\n 'TimeoutError',\n 'ExternalServiceError',\n 'PersistenceError',\n];\n\n// ============================================================================\n// Mapping Function\n// ============================================================================\n\n/**\n * Maps a caught error to an EventResult.\n *\n * Default mapping strategy:\n *\n * | Error Type | Outcome | Rationale |\n * |------------------------------------------------|---------|----------------------------------------|\n * | ObjectValidationError, InvalidRequestError | dlq | Bad payload — retrying won't help |\n * | UseCaseError | dlq | Business rule rejection — permanent |\n * | DomainError, InvariantViolationError | dlq | Domain invariant — permanent |\n * | UnprocessableError | dlq | Valid but not processable — permanent |\n * | AccessDeniedError, ForbiddenError, Unauthorized | dlq | Permission — permanent |\n * | NotFoundError | retry | Entity might not exist yet |\n * | ConflictError | retry | Concurrent write — may resolve |\n * | InfraError, DbError, NetworkError, TimeoutError | retry | Infrastructure/transient |\n * | Unknown | retry | Conservative — don't lose messages |\n *\n * @param error - The caught error\n * @returns An EventResult indicating how the message should be handled\n */\nexport function mapErrorToEventResult(error: unknown): EventResult {\n // Check DLQ errors first (permanent failures)\n for (const typeName of DLQ_ERROR_TYPES) {\n if (isErrorType(error, typeName)) {\n return {\n outcome: 'dlq',\n reason: (error as { message: string }).message,\n };\n }\n }\n\n // Check retry errors (transient failures)\n for (const typeName of RETRY_ERROR_TYPES) {\n if (isErrorType(error, typeName)) {\n return {\n outcome: 'retry',\n reason: (error as { message: string }).message,\n };\n }\n }\n\n // Unknown errors — retry conservatively to avoid losing messages\n const message =\n error instanceof Error ? error.message : 'Unknown error occurred during event processing';\n\n return {\n outcome: 'retry',\n reason: message,\n };\n}\n"],"mappings":";;;;;AAqBA,IAAM,kBAAkB;AAAA,EACtB;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF;AAMA,IAAM,oBAAoB;AAAA,EACxB;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF;AA0BO,SAAS,sBAAsB,OAA6B;AAEjE,aAAW,YAAY,iBAAiB;AACtC,QAAI,YAAY,OAAO,QAAQ,GAAG;AAChC,aAAO;AAAA,QACL,SAAS;AAAA,QACT,QAAS,MAA8B;AAAA,MACzC;AAAA,IACF;AAAA,EACF;AAGA,aAAW,YAAY,mBAAmB;AACxC,QAAI,YAAY,OAAO,QAAQ,GAAG;AAChC,aAAO;AAAA,QACL,SAAS;AAAA,QACT,QAAS,MAA8B;AAAA,MACzC;AAAA,IACF;AAAA,EACF;AAGA,QAAM,UACJ,iBAAiB,QAAQ,MAAM,UAAU;AAE3C,SAAO;AAAA,IACL,SAAS;AAAA,IACT,QAAQ;AAAA,EACV;AACF;","names":[]}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
// src/presentation/events/handler/types/event-router-definition.type.ts
|
|
2
|
+
function isEventHandlerDefinition(value) {
|
|
3
|
+
return typeof value === "object" && value !== null && "eventType" in value && "_types" in value;
|
|
4
|
+
}
|
|
5
|
+
function isEventRouterDefinition(value) {
|
|
6
|
+
return typeof value === "object" && value !== null && "_isEventRouter" in value && value._isEventRouter === true;
|
|
7
|
+
}
|
|
8
|
+
function collectEventHandlers(config, basePath = "") {
|
|
9
|
+
const handlers = [];
|
|
10
|
+
for (const [key, value] of Object.entries(config)) {
|
|
11
|
+
const fullKey = basePath ? `${basePath}.${key}` : key;
|
|
12
|
+
if (isEventHandlerDefinition(value)) {
|
|
13
|
+
handlers.push({ key: fullKey, handler: value });
|
|
14
|
+
} else if (isEventRouterDefinition(value)) {
|
|
15
|
+
handlers.push(...collectEventHandlers(value.handlers, fullKey));
|
|
16
|
+
} else if (typeof value === "object" && value !== null) {
|
|
17
|
+
handlers.push(...collectEventHandlers(value, fullKey));
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
return handlers;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
// src/presentation/events/handler/utils.ts
|
|
24
|
+
function generateHandlerId(key) {
|
|
25
|
+
return key.replace(/\.(\w)/g, (_, char) => char.toUpperCase());
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
export {
|
|
29
|
+
isEventHandlerDefinition,
|
|
30
|
+
isEventRouterDefinition,
|
|
31
|
+
collectEventHandlers,
|
|
32
|
+
generateHandlerId
|
|
33
|
+
};
|
|
34
|
+
//# sourceMappingURL=chunk-CBTICRSM.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/presentation/events/handler/types/event-router-definition.type.ts","../src/presentation/events/handler/utils.ts"],"sourcesContent":["/**\n * @fileoverview Event router definition types for grouping event handlers.\n *\n * Mirrors the HTTP router definition pattern with hierarchical grouping,\n * dotted-key access, and deep merge support.\n *\n * @module events/handler/types/event-router-definition\n */\n\nimport type { EventHandlerDefinition } from './event-handler-definition.type';\nimport type { SchemaAdapter } from '../../../http/schema/types';\n\n// ============================================================================\n// Router Types\n// ============================================================================\n\n/**\n * A router entry can be an event handler definition, a nested config, or a router definition.\n */\nexport type EventRouterEntry =\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n EventHandlerDefinition<string, any, any> | EventRouterConfig | EventRouterDefinition;\n\n/**\n * Configuration for an event router (group of event handlers).\n */\nexport interface EventRouterConfig {\n readonly [key: string]: EventRouterEntry;\n}\n\n/**\n * Router-level defaults applied to all child event handlers.\n */\nexport interface EventRouterDefaults {\n /** Default tags for all handlers. Merged with handler-specific tags. */\n readonly tags?: readonly string[];\n\n /** Default context schema. Applied to handlers that don't define their own. */\n readonly context?: SchemaAdapter;\n}\n\n/**\n * A fully defined event router.\n */\nexport interface EventRouterDefinition<T extends EventRouterConfig = EventRouterConfig> {\n /** The handlers and nested routers in this router. */\n readonly handlers: T;\n\n /** Default values applied to all child handlers. */\n readonly defaults?: EventRouterDefaults;\n\n /**\n * Marker to identify this as an event router.\n * @internal\n */\n readonly _isEventRouter: true;\n}\n\n// ============================================================================\n// Type Guards\n// ============================================================================\n\n/**\n * Checks if a value is an EventHandlerDefinition.\n */\nexport function isEventHandlerDefinition(value: unknown): value is EventHandlerDefinition {\n return typeof value === 'object' && value !== null && 'eventType' in value && '_types' in value;\n}\n\n/**\n * Checks if a value is an EventRouterDefinition.\n */\nexport function isEventRouterDefinition(value: unknown): value is EventRouterDefinition {\n return (\n typeof value === 'object' &&\n value !== null &&\n '_isEventRouter' in value &&\n (value as EventRouterDefinition)._isEventRouter === true\n );\n}\n\n// ============================================================================\n// Utility Types\n// ============================================================================\n\n/**\n * Flattens an event router into a map of dotted keys to handler definitions.\n */\nexport type FlattenEventRouter<\n T extends EventRouterConfig,\n Prefix extends string = '',\n> = T extends EventRouterConfig\n ? {\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n [K in keyof T]: T[K] extends EventHandlerDefinition<any, any, any>\n ? { [P in `${Prefix}${K & string}`]: T[K] }\n : T[K] extends EventRouterConfig\n ? FlattenEventRouter<T[K], `${Prefix}${K & string}.`>\n : never;\n }[keyof T] extends infer U\n ? // eslint-disable-next-line @typescript-eslint/no-explicit-any\n U extends Record<string, EventHandlerDefinition<any, any, any>>\n ? U\n : never\n : never\n : never;\n\n/**\n * Gets all handler keys from an event router.\n */\nexport type EventRouterKeys<\n T extends EventRouterConfig,\n Prefix extends string = '',\n> = T extends EventRouterConfig\n ? {\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n [K in keyof T]: T[K] extends EventHandlerDefinition<any, any, any>\n ? `${Prefix}${K & string}`\n : T[K] extends EventRouterConfig\n ? EventRouterKeys<T[K], `${Prefix}${K & string}.`>\n : never;\n }[keyof T]\n : never;\n\n/**\n * Gets an event handler by its dotted key path.\n */\nexport type GetEventHandler<\n T extends EventRouterConfig,\n K extends string,\n> = K extends `${infer Head}.${infer Tail}`\n ? Head extends keyof T\n ? T[Head] extends EventRouterConfig\n ? GetEventHandler<T[Head], Tail>\n : never\n : never\n : K extends keyof T\n ? // eslint-disable-next-line @typescript-eslint/no-explicit-any\n T[K] extends EventHandlerDefinition<any, any, any>\n ? T[K]\n : never\n : never;\n\n// ============================================================================\n// Deep Merge Types\n// ============================================================================\n\n/**\n * Deep-merges two event router configs at the type level.\n */\nexport type DeepMergeTwo<A extends EventRouterConfig, B extends EventRouterConfig> = {\n readonly [K in keyof A | keyof B]: K extends keyof A\n ? K extends keyof B\n ? A[K] extends EventRouterConfig\n ? B[K] extends EventRouterConfig\n ? DeepMergeTwo<A[K], B[K]>\n : B[K]\n : B[K]\n : A[K]\n : K extends keyof B\n ? B[K]\n : never;\n};\n\n/**\n * Recursively deep-merges N event router configs left-to-right.\n */\nexport type DeepMergeAll<T extends readonly EventRouterConfig[]> = T extends readonly [\n infer Only extends EventRouterConfig,\n]\n ? Only\n : T extends readonly [\n infer First extends EventRouterConfig,\n infer Second extends EventRouterConfig,\n ...infer Rest extends readonly EventRouterConfig[],\n ]\n ? DeepMergeAll<[DeepMergeTwo<First, Second>, ...Rest]>\n : EventRouterConfig;\n\n// ============================================================================\n// Runtime Utilities\n// ============================================================================\n\n/**\n * Collects all event handlers from a router into a flat array.\n */\nexport function collectEventHandlers(\n config: EventRouterConfig,\n basePath = '',\n): { key: string; handler: EventHandlerDefinition }[] {\n const handlers: { key: string; handler: EventHandlerDefinition }[] = [];\n\n for (const [key, value] of Object.entries(config)) {\n const fullKey = basePath ? `${basePath}.${key}` : key;\n\n if (isEventHandlerDefinition(value)) {\n handlers.push({ key: fullKey, handler: value });\n } else if (isEventRouterDefinition(value)) {\n handlers.push(...collectEventHandlers(value.handlers, fullKey));\n } else if (typeof value === 'object' && value !== null) {\n handlers.push(...collectEventHandlers(value as EventRouterConfig, fullKey));\n }\n }\n\n return handlers;\n}\n","/**\n * @fileoverview Utility functions for event handler routing.\n *\n * @module events/handler/utils\n */\n\n/**\n * Generates a handler ID from a dotted key path.\n *\n * Converts dot-separated keys to camelCase:\n * - `\"ticket.created\"` → `\"ticketCreated\"`\n * - `\"ecosystem.member.added\"` → `\"ecosystemMemberAdded\"`\n *\n * @param key - The dotted key path\n * @returns A camelCase handler ID\n */\nexport function generateHandlerId(key: string): string {\n return key.replace(/\\.(\\w)/g, (_, char: string) => char.toUpperCase());\n}\n"],"mappings":";AAiEO,SAAS,yBAAyB,OAAiD;AACxF,SAAO,OAAO,UAAU,YAAY,UAAU,QAAQ,eAAe,SAAS,YAAY;AAC5F;AAKO,SAAS,wBAAwB,OAAgD;AACtF,SACE,OAAO,UAAU,YACjB,UAAU,QACV,oBAAoB,SACnB,MAAgC,mBAAmB;AAExD;AA2GO,SAAS,qBACd,QACA,WAAW,IACyC;AACpD,QAAM,WAA+D,CAAC;AAEtE,aAAW,CAAC,KAAK,KAAK,KAAK,OAAO,QAAQ,MAAM,GAAG;AACjD,UAAM,UAAU,WAAW,GAAG,QAAQ,IAAI,GAAG,KAAK;AAElD,QAAI,yBAAyB,KAAK,GAAG;AACnC,eAAS,KAAK,EAAE,KAAK,SAAS,SAAS,MAAM,CAAC;AAAA,IAChD,WAAW,wBAAwB,KAAK,GAAG;AACzC,eAAS,KAAK,GAAG,qBAAqB,MAAM,UAAU,OAAO,CAAC;AAAA,IAChE,WAAW,OAAO,UAAU,YAAY,UAAU,MAAM;AACtD,eAAS,KAAK,GAAG,qBAAqB,OAA4B,OAAO,CAAC;AAAA,IAC5E;AAAA,EACF;AAEA,SAAO;AACT;;;AC7LO,SAAS,kBAAkB,KAAqB;AACrD,SAAO,IAAI,QAAQ,WAAW,CAAC,GAAG,SAAiB,KAAK,YAAY,CAAC;AACvE;","names":[]}
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
import {
|
|
2
|
+
collectEventHandlers,
|
|
3
|
+
generateHandlerId,
|
|
4
|
+
isEventRouterDefinition
|
|
5
|
+
} from "./chunk-CBTICRSM.js";
|
|
6
|
+
|
|
7
|
+
// src/presentation/events/asyncapi/generate.ts
|
|
8
|
+
function generateAsyncAPI(router, config) {
|
|
9
|
+
const routerConfig = isEventRouterDefinition(router) ? router.handlers : router;
|
|
10
|
+
const handlers = collectEventHandlers(routerConfig);
|
|
11
|
+
const channels = {};
|
|
12
|
+
const operations = {};
|
|
13
|
+
const allTags = /* @__PURE__ */ new Set();
|
|
14
|
+
for (const { key, handler } of handlers) {
|
|
15
|
+
const handlerId = generateHandlerId(key);
|
|
16
|
+
const channelId = handler.eventType;
|
|
17
|
+
const message = buildMessage(handler.eventType, handler.payload, handler.docs);
|
|
18
|
+
if (!channels[channelId]) {
|
|
19
|
+
channels[channelId] = {
|
|
20
|
+
address: handler.eventType,
|
|
21
|
+
messages: {}
|
|
22
|
+
};
|
|
23
|
+
}
|
|
24
|
+
const channelMessages = { ...channels[channelId].messages ?? {} };
|
|
25
|
+
channelMessages[handlerId] = message;
|
|
26
|
+
channels[channelId] = { ...channels[channelId], messages: channelMessages };
|
|
27
|
+
const operation = {
|
|
28
|
+
action: "receive",
|
|
29
|
+
channel: { $ref: `#/channels/${channelId}` },
|
|
30
|
+
messages: [{ $ref: `#/channels/${channelId}/messages/${handlerId}` }]
|
|
31
|
+
};
|
|
32
|
+
if (handler.docs.summary) {
|
|
33
|
+
operation.summary = handler.docs.summary;
|
|
34
|
+
}
|
|
35
|
+
if (handler.docs.description) {
|
|
36
|
+
operation.description = handler.docs.description;
|
|
37
|
+
}
|
|
38
|
+
if (handler.docs.deprecated) {
|
|
39
|
+
operation.deprecated = true;
|
|
40
|
+
}
|
|
41
|
+
if (handler.docs.tags && handler.docs.tags.length > 0) {
|
|
42
|
+
operation.tags = handler.docs.tags.map((t) => ({
|
|
43
|
+
name: t
|
|
44
|
+
}));
|
|
45
|
+
for (const tag of handler.docs.tags) {
|
|
46
|
+
allTags.add(tag);
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
operations[handlerId] = operation;
|
|
50
|
+
}
|
|
51
|
+
const tags = config.tags ? [...config.tags] : [];
|
|
52
|
+
for (const tagName of allTags) {
|
|
53
|
+
if (!tags.some((t) => t.name === tagName)) {
|
|
54
|
+
tags.push({ name: tagName });
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
const info = tags.length > 0 ? { ...config.info, tags } : config.info;
|
|
58
|
+
const spec = {
|
|
59
|
+
asyncapi: config.asyncapi ?? "3.0.0",
|
|
60
|
+
info,
|
|
61
|
+
defaultContentType: config.defaultContentType ?? "application/json",
|
|
62
|
+
channels,
|
|
63
|
+
operations
|
|
64
|
+
};
|
|
65
|
+
if (config.servers && Object.keys(config.servers).length > 0) {
|
|
66
|
+
spec.servers = config.servers;
|
|
67
|
+
}
|
|
68
|
+
if (config.externalDocs) {
|
|
69
|
+
spec.externalDocs = config.externalDocs;
|
|
70
|
+
}
|
|
71
|
+
return spec;
|
|
72
|
+
}
|
|
73
|
+
function buildMessage(eventType, payload, docs) {
|
|
74
|
+
const message = {
|
|
75
|
+
name: eventType
|
|
76
|
+
};
|
|
77
|
+
if (docs.summary) {
|
|
78
|
+
message.summary = docs.summary;
|
|
79
|
+
}
|
|
80
|
+
if (docs.description) {
|
|
81
|
+
message.description = docs.description;
|
|
82
|
+
}
|
|
83
|
+
if (docs.deprecated) {
|
|
84
|
+
message.deprecated = true;
|
|
85
|
+
}
|
|
86
|
+
if (payload) {
|
|
87
|
+
const schema = payload.toJsonSchema();
|
|
88
|
+
message.payload = schema;
|
|
89
|
+
}
|
|
90
|
+
return message;
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
export {
|
|
94
|
+
generateAsyncAPI
|
|
95
|
+
};
|
|
96
|
+
//# sourceMappingURL=chunk-KJ4JGZOE.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/presentation/events/asyncapi/generate.ts"],"sourcesContent":["/**\n * @fileoverview AsyncAPI specification generation from event router definitions.\n *\n * The `generateAsyncAPI` function creates a complete AsyncAPI 3.0 specification\n * from an event router definition. All handler payload schemas are converted to\n * JSON Schema and included in the specification.\n *\n * @module events/asyncapi/generate\n */\n\nimport type { SchemaAdapter } from '../../http/schema/types';\nimport type { EventRouterConfig, EventRouterDefinition } from '../handler/types';\nimport { isEventRouterDefinition, collectEventHandlers } from '../handler/types';\nimport { generateHandlerId } from '../handler/utils';\nimport type {\n AsyncAPIConfig,\n AsyncAPISpec,\n AsyncAPIChannel,\n AsyncAPIOperation,\n AsyncAPIMessage,\n AsyncAPITag,\n} from './types';\n\n/**\n * Generates an AsyncAPI 3.0 specification from an event router definition.\n *\n * This function walks the event router structure, extracts JSON schemas from\n * all handler payload definitions, and builds a complete AsyncAPI 3.0 specification.\n *\n * @param router - Event router definition or raw config\n * @param config - AsyncAPI configuration (info, servers, tags, etc.)\n * @returns Complete AsyncAPI specification\n *\n * @example\n * ```typescript\n * import { generateAsyncAPI } from '@cosmneo/onion-lasagna/events/asyncapi';\n * import { notificationEventRouter } from './events/router';\n *\n * const spec = generateAsyncAPI(notificationEventRouter, {\n * info: {\n * title: 'My Event API',\n * version: '1.0.0',\n * description: 'Domain events for the application',\n * },\n * });\n *\n * app.get('/asyncapi.json', (c) => c.json(spec));\n * ```\n */\nexport function generateAsyncAPI<T extends EventRouterConfig>(\n router: T | EventRouterDefinition<T>,\n config: AsyncAPIConfig,\n): AsyncAPISpec {\n const routerConfig = isEventRouterDefinition(router) ? router.handlers : router;\n const handlers = collectEventHandlers(routerConfig);\n\n const channels: Record<string, AsyncAPIChannel> = {};\n const operations: Record<string, AsyncAPIOperation> = {};\n const allTags = new Set<string>();\n\n for (const { key, handler } of handlers) {\n const handlerId = generateHandlerId(key);\n const channelId = handler.eventType;\n\n // Build message\n const message = buildMessage(handler.eventType, handler.payload, handler.docs);\n\n // Build channel (group by eventType — multiple handlers may share a channel)\n if (!channels[channelId]) {\n channels[channelId] = {\n address: handler.eventType,\n messages: {},\n };\n }\n const channelMessages = { ...(channels[channelId]!.messages ?? {}) };\n channelMessages[handlerId] = message;\n channels[channelId] = { ...channels[channelId]!, messages: channelMessages };\n\n // Build operation (one per handler)\n const operation: AsyncAPIOperation = {\n action: 'receive',\n channel: { $ref: `#/channels/${channelId}` },\n messages: [{ $ref: `#/channels/${channelId}/messages/${handlerId}` }],\n };\n\n if (handler.docs.summary) {\n (operation as { summary: string }).summary = handler.docs.summary;\n }\n if (handler.docs.description) {\n (operation as { description: string }).description = handler.docs.description;\n }\n if (handler.docs.deprecated) {\n (operation as { deprecated: boolean }).deprecated = true;\n }\n if (handler.docs.tags && handler.docs.tags.length > 0) {\n (operation as { tags: readonly AsyncAPITag[] }).tags = handler.docs.tags.map((t) => ({\n name: t,\n }));\n for (const tag of handler.docs.tags) {\n allTags.add(tag);\n }\n }\n\n operations[handlerId] = operation;\n }\n\n // Merge custom tags with collected tags (AsyncAPI 3.0: tags live inside info)\n const tags: AsyncAPITag[] = config.tags ? [...config.tags] : [];\n for (const tagName of allTags) {\n if (!tags.some((t) => t.name === tagName)) {\n tags.push({ name: tagName });\n }\n }\n\n const info = tags.length > 0 ? { ...config.info, tags } : config.info;\n\n // Build the specification\n const spec: AsyncAPISpec = {\n asyncapi: config.asyncapi ?? '3.0.0',\n info,\n defaultContentType: config.defaultContentType ?? 'application/json',\n channels,\n operations,\n };\n\n if (config.servers && Object.keys(config.servers).length > 0) {\n (spec as { servers: typeof config.servers }).servers = config.servers;\n }\n\n if (config.externalDocs) {\n (spec as { externalDocs: typeof config.externalDocs }).externalDocs = config.externalDocs;\n }\n\n return spec;\n}\n\n/**\n * Builds an AsyncAPI message from a handler definition.\n */\nfunction buildMessage(\n eventType: string,\n payload: unknown,\n docs: {\n readonly summary?: string;\n readonly description?: string;\n readonly tags?: readonly string[];\n readonly deprecated?: boolean;\n },\n): AsyncAPIMessage {\n const message: AsyncAPIMessage = {\n name: eventType,\n };\n\n if (docs.summary) {\n (message as { summary: string }).summary = docs.summary;\n }\n if (docs.description) {\n (message as { description: string }).description = docs.description;\n }\n if (docs.deprecated) {\n (message as { deprecated: boolean }).deprecated = true;\n }\n\n if (payload) {\n const schema = (payload as SchemaAdapter).toJsonSchema();\n (message as { payload: typeof schema }).payload = schema;\n }\n\n return message;\n}\n"],"mappings":"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","names":[]}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
//# sourceMappingURL=chunk-RVSBIYY4.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":[],"sourcesContent":[],"mappings":"","names":[]}
|
|
@@ -0,0 +1,191 @@
|
|
|
1
|
+
import {
|
|
2
|
+
mapErrorToEventResult
|
|
3
|
+
} from "./chunk-4BVOLXDJ.js";
|
|
4
|
+
import {
|
|
5
|
+
collectEventHandlers,
|
|
6
|
+
generateHandlerId,
|
|
7
|
+
isEventRouterDefinition
|
|
8
|
+
} from "./chunk-CBTICRSM.js";
|
|
9
|
+
|
|
10
|
+
// src/presentation/events/server/types.ts
|
|
11
|
+
function isSimpleEventHandlerConfig(config) {
|
|
12
|
+
return "handler" in config && typeof config.handler === "function";
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
// src/presentation/events/server/create-event-routes.ts
|
|
16
|
+
function createEventRoutesInternal(router, handlers, options) {
|
|
17
|
+
const config = isEventRouterDefinition(router) ? router.handlers : router;
|
|
18
|
+
const collectedHandlers = collectEventHandlers(config);
|
|
19
|
+
const result = [];
|
|
20
|
+
const resolvedOptions = {
|
|
21
|
+
...options,
|
|
22
|
+
validatePayload: options?.validatePayload ?? true,
|
|
23
|
+
allowPartial: options?.allowPartial ?? false
|
|
24
|
+
};
|
|
25
|
+
for (const { key, handler: handlerDef } of collectedHandlers) {
|
|
26
|
+
const handlerConfig = handlers[key];
|
|
27
|
+
if (!handlerConfig) {
|
|
28
|
+
if (resolvedOptions.allowPartial) {
|
|
29
|
+
continue;
|
|
30
|
+
}
|
|
31
|
+
throw new Error(
|
|
32
|
+
`Missing handler for event "${key}". All event handlers must have a handler configuration.`
|
|
33
|
+
);
|
|
34
|
+
}
|
|
35
|
+
result.push(createEventHandler(key, handlerDef, handlerConfig, resolvedOptions));
|
|
36
|
+
}
|
|
37
|
+
return result;
|
|
38
|
+
}
|
|
39
|
+
function createEventHandler(key, handlerDef, config, options) {
|
|
40
|
+
const middleware = config.middleware ?? [];
|
|
41
|
+
const globalMiddleware = options?.middleware ?? [];
|
|
42
|
+
const allMiddleware = [...globalMiddleware, ...middleware];
|
|
43
|
+
const shouldValidatePayload = options.validatePayload ?? true;
|
|
44
|
+
const errorMapper = options.errorMapper ?? mapErrorToEventResult;
|
|
45
|
+
return {
|
|
46
|
+
eventType: handlerDef.eventType,
|
|
47
|
+
metadata: {
|
|
48
|
+
handlerId: generateHandlerId(key),
|
|
49
|
+
summary: handlerDef.docs.summary,
|
|
50
|
+
description: handlerDef.docs.description,
|
|
51
|
+
tags: handlerDef.docs.tags,
|
|
52
|
+
deprecated: handlerDef.docs.deprecated
|
|
53
|
+
},
|
|
54
|
+
handler: async (rawEvent) => {
|
|
55
|
+
try {
|
|
56
|
+
let validatedContext = rawEvent.metadata;
|
|
57
|
+
if (handlerDef.context) {
|
|
58
|
+
const contextResult = validateContextData(handlerDef, rawEvent.metadata);
|
|
59
|
+
if (!contextResult.success) {
|
|
60
|
+
const errors = contextResult.errors ?? [];
|
|
61
|
+
return {
|
|
62
|
+
outcome: "dlq",
|
|
63
|
+
reason: `Context validation failed: ${errors.map((e) => `${e.path.join(".")}: ${e.message}`).join("; ")}`
|
|
64
|
+
};
|
|
65
|
+
}
|
|
66
|
+
validatedContext = contextResult.data;
|
|
67
|
+
}
|
|
68
|
+
let validatedPayload = rawEvent.payload;
|
|
69
|
+
if (shouldValidatePayload && handlerDef.payload) {
|
|
70
|
+
const payloadResult = validatePayloadData(handlerDef, rawEvent.payload);
|
|
71
|
+
if (!payloadResult.success) {
|
|
72
|
+
const errors = payloadResult.errors ?? [];
|
|
73
|
+
return {
|
|
74
|
+
outcome: "dlq",
|
|
75
|
+
reason: `Payload validation failed: ${errors.map((e) => `${e.path.join(".")}: ${e.message}`).join("; ")}`
|
|
76
|
+
};
|
|
77
|
+
}
|
|
78
|
+
validatedPayload = payloadResult.data;
|
|
79
|
+
}
|
|
80
|
+
const validatedEvent = {
|
|
81
|
+
payload: validatedPayload,
|
|
82
|
+
raw: rawEvent
|
|
83
|
+
};
|
|
84
|
+
const executePipeline = async () => {
|
|
85
|
+
if (isSimpleEventHandlerConfig(config)) {
|
|
86
|
+
return config.handler(
|
|
87
|
+
validatedEvent,
|
|
88
|
+
validatedContext
|
|
89
|
+
);
|
|
90
|
+
} else {
|
|
91
|
+
const { payloadMapper, useCase, resultMapper } = config;
|
|
92
|
+
const input = payloadMapper(
|
|
93
|
+
validatedEvent,
|
|
94
|
+
validatedContext
|
|
95
|
+
);
|
|
96
|
+
const output = await useCase.execute(input);
|
|
97
|
+
return resultMapper ? resultMapper(output) : { outcome: "ack" };
|
|
98
|
+
}
|
|
99
|
+
};
|
|
100
|
+
if (allMiddleware.length === 0) {
|
|
101
|
+
return await executePipeline();
|
|
102
|
+
}
|
|
103
|
+
let index = 0;
|
|
104
|
+
const next = async () => {
|
|
105
|
+
if (index >= allMiddleware.length) {
|
|
106
|
+
return executePipeline();
|
|
107
|
+
}
|
|
108
|
+
const mw = allMiddleware[index++];
|
|
109
|
+
return mw(rawEvent, next);
|
|
110
|
+
};
|
|
111
|
+
return await next();
|
|
112
|
+
} catch (error) {
|
|
113
|
+
return errorMapper(error);
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
};
|
|
117
|
+
}
|
|
118
|
+
function validatePayloadData(handler, payload) {
|
|
119
|
+
const schema = handler.payload;
|
|
120
|
+
if (!schema) return { success: true, data: payload };
|
|
121
|
+
const result = schema.validate(payload);
|
|
122
|
+
if (result.success) {
|
|
123
|
+
return { success: true, data: result.data };
|
|
124
|
+
}
|
|
125
|
+
const errors = result.issues.map((issue) => ({
|
|
126
|
+
...issue,
|
|
127
|
+
path: ["payload", ...issue.path]
|
|
128
|
+
}));
|
|
129
|
+
return { success: false, errors };
|
|
130
|
+
}
|
|
131
|
+
function validateContextData(handler, metadata) {
|
|
132
|
+
const schema = handler.context;
|
|
133
|
+
if (!schema) return { success: true, data: metadata };
|
|
134
|
+
const result = schema.validate(metadata);
|
|
135
|
+
if (result.success) {
|
|
136
|
+
return { success: true, data: result.data };
|
|
137
|
+
}
|
|
138
|
+
const errors = result.issues.map((issue) => ({
|
|
139
|
+
...issue,
|
|
140
|
+
path: ["context", ...issue.path]
|
|
141
|
+
}));
|
|
142
|
+
return { success: false, errors };
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
// src/presentation/events/server/event-routes-builder.ts
|
|
146
|
+
var EventRoutesBuilderImpl = class _EventRoutesBuilderImpl {
|
|
147
|
+
router;
|
|
148
|
+
handlers;
|
|
149
|
+
constructor(router, handlers) {
|
|
150
|
+
this.router = router;
|
|
151
|
+
this.handlers = handlers ?? /* @__PURE__ */ new Map();
|
|
152
|
+
}
|
|
153
|
+
handle(key, handlerOrConfig) {
|
|
154
|
+
const config = typeof handlerOrConfig === "function" ? { handler: handlerOrConfig } : handlerOrConfig;
|
|
155
|
+
const newHandlers = new Map(this.handlers);
|
|
156
|
+
newHandlers.set(key, config);
|
|
157
|
+
return new _EventRoutesBuilderImpl(
|
|
158
|
+
this.router,
|
|
159
|
+
newHandlers
|
|
160
|
+
);
|
|
161
|
+
}
|
|
162
|
+
handleWithUseCase(key, config) {
|
|
163
|
+
const newHandlers = new Map(this.handlers);
|
|
164
|
+
newHandlers.set(
|
|
165
|
+
key,
|
|
166
|
+
config
|
|
167
|
+
);
|
|
168
|
+
return new _EventRoutesBuilderImpl(
|
|
169
|
+
this.router,
|
|
170
|
+
newHandlers
|
|
171
|
+
);
|
|
172
|
+
}
|
|
173
|
+
build(options) {
|
|
174
|
+
return createEventRoutesInternal(this.router, Object.fromEntries(this.handlers), options);
|
|
175
|
+
}
|
|
176
|
+
buildPartial(options) {
|
|
177
|
+
return createEventRoutesInternal(this.router, Object.fromEntries(this.handlers), {
|
|
178
|
+
...options,
|
|
179
|
+
allowPartial: true
|
|
180
|
+
});
|
|
181
|
+
}
|
|
182
|
+
};
|
|
183
|
+
function eventRoutes(router) {
|
|
184
|
+
return new EventRoutesBuilderImpl(router);
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
export {
|
|
188
|
+
isSimpleEventHandlerConfig,
|
|
189
|
+
eventRoutes
|
|
190
|
+
};
|
|
191
|
+
//# sourceMappingURL=chunk-XWKHOLIP.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/presentation/events/server/types.ts","../src/presentation/events/server/create-event-routes.ts","../src/presentation/events/server/event-routes-builder.ts"],"sourcesContent":["/**\n * @fileoverview Server types for the event handler system.\n *\n * @module events/server/types\n */\n\nimport type { EventHandlerDefinition, EventRouterConfig, EventRouterKeys } from '../handler/types';\nimport type { EventResult } from '../shared/types';\n\n// Re-export UseCasePort from HTTP — same interface, no duplication\nexport type { UseCasePort } from '../../http/server/types';\n\n// ============================================================================\n// Raw Event (from messaging system)\n// ============================================================================\n\n/**\n * Event metadata provided by the messaging system.\n */\nexport interface EventMetadata {\n /** Unique event identifier for idempotency checks. */\n readonly eventId: string;\n\n /** ISO 8601 timestamp of when the event occurred. */\n readonly timestamp: string;\n\n /** Correlation ID for distributed tracing. */\n readonly correlationId?: string;\n\n /** Source system or bounded context that emitted the event. */\n readonly source?: string;\n\n /** Number of delivery attempts (1-based). */\n readonly attemptCount?: number;\n\n /** Additional metadata from the messaging system. */\n readonly [key: string]: unknown;\n}\n\n/**\n * Raw event from the messaging system.\n * This is the input to event handlers before validation.\n */\nexport interface RawEvent {\n /** Event type string for routing. */\n readonly type: string;\n\n /** Event payload (unvalidated). */\n readonly payload: unknown;\n\n /** Event metadata from the messaging system. */\n readonly metadata: EventMetadata;\n}\n\n// ============================================================================\n// Validated Event\n// ============================================================================\n\n/**\n * A validated event with typed payload.\n * This is what handlers receive after validation passes.\n */\nexport interface ValidatedEvent<THandler extends EventHandlerDefinition> {\n /** Validated event payload. */\n readonly payload: THandler['_types']['payload'];\n\n /** Raw event object for advanced use cases. */\n readonly raw: RawEvent;\n}\n\n/**\n * Typed event context based on handler definition.\n * If the handler defines a context schema, this will be the validated type.\n * Otherwise, it falls back to the generic EventMetadata.\n */\nexport type TypedEventContext<THandler extends EventHandlerDefinition> =\n THandler['_types']['context'] extends undefined ? EventMetadata : THandler['_types']['context'];\n\n// ============================================================================\n// Handler Types\n// ============================================================================\n\n/**\n * Handler configuration using the use case pattern.\n *\n * @typeParam THandler - The event handler definition type\n * @typeParam TInput - Use case input type\n * @typeParam TOutput - Use case output type\n */\nexport interface EventHandlerConfig<\n THandler extends EventHandlerDefinition,\n TInput = void,\n TOutput = void,\n> {\n /**\n * Maps the validated event payload to use case input.\n * Both `event` and `ctx` are fully typed based on handler schemas.\n */\n readonly payloadMapper: (\n event: ValidatedEvent<THandler>,\n ctx: TypedEventContext<THandler>,\n ) => TInput;\n\n /** The use case to execute. */\n readonly useCase: { execute(input?: TInput): Promise<TOutput> };\n\n /**\n * Maps the use case output to an EventResult.\n * If omitted, defaults to `{ outcome: 'ack' }`.\n */\n readonly resultMapper?: (output: TOutput) => EventResult;\n\n /** Middleware to run before the handler. */\n readonly middleware?: readonly EventMiddlewareFunction[];\n}\n\n/**\n * Simple handler function that directly returns an EventResult.\n */\nexport type SimpleEventHandlerFn<THandler extends EventHandlerDefinition> = (\n event: ValidatedEvent<THandler>,\n ctx: TypedEventContext<THandler>,\n) => Promise<EventResult> | EventResult;\n\n/**\n * Configuration for a simple handler (no use case).\n */\nexport interface SimpleEventHandlerConfig<THandler extends EventHandlerDefinition> {\n readonly handler: SimpleEventHandlerFn<THandler>;\n readonly middleware?: readonly EventMiddlewareFunction[];\n}\n\n/**\n * Union of all event handler config types.\n * Used internally to store handlers in the builder.\n */\nexport type AnyEventHandlerConfig<\n THandler extends EventHandlerDefinition,\n TInput = unknown,\n TOutput = unknown,\n> = EventHandlerConfig<THandler, TInput, TOutput> | SimpleEventHandlerConfig<THandler>;\n\n/**\n * Type guard to check if config is a simple event handler.\n */\nexport function isSimpleEventHandlerConfig(\n config: AnyEventHandlerConfig<EventHandlerDefinition, unknown, unknown>,\n): config is SimpleEventHandlerConfig<EventHandlerDefinition> {\n return 'handler' in config && typeof config.handler === 'function';\n}\n\n/**\n * Event middleware function type.\n */\nexport type EventMiddlewareFunction = (\n event: RawEvent,\n next: () => Promise<EventResult>,\n) => Promise<EventResult>;\n\n// ============================================================================\n// Server Configuration\n// ============================================================================\n\n/**\n * Configuration mapping handler keys to handler configs.\n */\n// TInput/TOutput are user-defined per handler - any is required for heterogeneous configs\nexport type EventRoutesConfig<T extends EventRouterConfig> = Record<\n EventRouterKeys<T>,\n EventHandlerConfig<any, any, any>\n>;\n\n/**\n * Options for creating event routes.\n */\nexport interface CreateEventRoutesOptions {\n /** Global middleware to run before all handlers. */\n readonly middleware?: readonly EventMiddlewareFunction[];\n\n /**\n * Whether to validate incoming event payloads against handler schemas.\n * When enabled, invalid payloads result in a `dlq` outcome.\n * @default true\n */\n readonly validatePayload?: boolean;\n\n /**\n * Custom error mapper to override default error-to-EventResult mapping.\n * If not provided, uses the built-in `mapErrorToEventResult`.\n */\n readonly errorMapper?: (error: unknown) => EventResult;\n\n /**\n * Allow partial handler configuration (not all handlers need to be wired).\n * @default false\n * @internal Used by builder pattern's buildPartial()\n */\n readonly allowPartial?: boolean;\n}\n\n// ============================================================================\n// Unified Event Input (for messaging adapters)\n// ============================================================================\n\n/**\n * Event input compatible with messaging adapters.\n * This is the output of eventRoutes().build().\n */\nexport interface UnifiedEventInput {\n /** Event type string for routing. */\n readonly eventType: string;\n\n /** Handler function. */\n readonly handler: (rawEvent: RawEvent) => Promise<EventResult>;\n\n /** Handler metadata for documentation. */\n readonly metadata: {\n readonly handlerId?: string;\n readonly summary?: string;\n readonly description?: string;\n readonly tags?: readonly string[];\n readonly deprecated?: boolean;\n };\n}\n","/**\n * @fileoverview Internal implementation for creating event routes with auto-validation.\n *\n * Generates event handlers from an event router definition.\n * Each handler automatically validates incoming event payloads and context\n * against the handler's schemas.\n *\n * @module events/server/create-event-routes\n * @internal\n */\n\nimport type { SchemaAdapter, ValidationIssue } from '../../http/schema/types';\nimport type {\n EventRouterConfig,\n EventRouterDefinition,\n EventHandlerDefinition,\n} from '../handler/types';\nimport { isEventRouterDefinition, collectEventHandlers } from '../handler/types';\nimport { generateHandlerId } from '../handler/utils';\nimport { mapErrorToEventResult } from '../shared/error-mapping';\nimport type { EventResult } from '../shared/types';\nimport type {\n AnyEventHandlerConfig,\n CreateEventRoutesOptions,\n EventMetadata,\n RawEvent,\n UnifiedEventInput,\n ValidatedEvent,\n} from './types';\nimport { isSimpleEventHandlerConfig } from './types';\n\n/**\n * Internal implementation for creating event routes.\n * Used by the builder pattern (eventRoutes).\n *\n * @internal\n */\nexport function createEventRoutesInternal<T extends EventRouterConfig>(\n router: T | EventRouterDefinition<T>,\n handlers: Record<string, AnyEventHandlerConfig<EventHandlerDefinition, unknown, unknown>>,\n options?: CreateEventRoutesOptions,\n): UnifiedEventInput[] {\n const config = isEventRouterDefinition(router) ? router.handlers : router;\n const collectedHandlers = collectEventHandlers(config);\n\n const result: UnifiedEventInput[] = [];\n\n const resolvedOptions: CreateEventRoutesOptions = {\n ...options,\n validatePayload: options?.validatePayload ?? true,\n allowPartial: options?.allowPartial ?? false,\n };\n\n for (const { key, handler: handlerDef } of collectedHandlers) {\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n const handlerConfig = handlers[key] as\n | AnyEventHandlerConfig<EventHandlerDefinition, any, any>\n | undefined;\n\n if (!handlerConfig) {\n if (resolvedOptions.allowPartial) {\n continue;\n }\n throw new Error(\n `Missing handler for event \"${key}\". All event handlers must have a handler configuration.`,\n );\n }\n\n result.push(createEventHandler(key, handlerDef, handlerConfig, resolvedOptions));\n }\n\n return result;\n}\n\n/**\n * Creates a single event handler with validation and error mapping.\n */\nfunction createEventHandler(\n key: string,\n handlerDef: EventHandlerDefinition,\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n config: AnyEventHandlerConfig<EventHandlerDefinition, any, any>,\n options: CreateEventRoutesOptions,\n): UnifiedEventInput {\n const middleware = config.middleware ?? [];\n const globalMiddleware = options?.middleware ?? [];\n const allMiddleware = [...globalMiddleware, ...middleware];\n const shouldValidatePayload = options.validatePayload ?? true;\n const errorMapper = options.errorMapper ?? mapErrorToEventResult;\n\n return {\n eventType: handlerDef.eventType,\n metadata: {\n handlerId: generateHandlerId(key),\n summary: handlerDef.docs.summary,\n description: handlerDef.docs.description,\n tags: handlerDef.docs.tags as string[],\n deprecated: handlerDef.docs.deprecated,\n },\n handler: async (rawEvent: RawEvent): Promise<EventResult> => {\n try {\n // Validate context (if schema defined)\n let validatedContext: unknown = rawEvent.metadata;\n if (handlerDef.context) {\n const contextResult = validateContextData(handlerDef, rawEvent.metadata);\n if (!contextResult.success) {\n const errors = contextResult.errors ?? [];\n return {\n outcome: 'dlq',\n reason: `Context validation failed: ${errors.map((e) => `${e.path.join('.')}: ${e.message}`).join('; ')}`,\n };\n }\n validatedContext = contextResult.data;\n }\n\n // Validate payload (if enabled and schema defined)\n let validatedPayload: unknown = rawEvent.payload;\n if (shouldValidatePayload && handlerDef.payload) {\n const payloadResult = validatePayloadData(handlerDef, rawEvent.payload);\n if (!payloadResult.success) {\n const errors = payloadResult.errors ?? [];\n return {\n outcome: 'dlq',\n reason: `Payload validation failed: ${errors.map((e) => `${e.path.join('.')}: ${e.message}`).join('; ')}`,\n };\n }\n validatedPayload = payloadResult.data;\n }\n\n const validatedEvent: ValidatedEventInternal = {\n payload: validatedPayload,\n raw: rawEvent,\n };\n\n // Execute the pipeline\n const executePipeline = async (): Promise<EventResult> => {\n if (isSimpleEventHandlerConfig(config)) {\n return config.handler(\n validatedEvent as unknown as ValidatedEvent<EventHandlerDefinition>,\n validatedContext as EventMetadata,\n );\n } else {\n const { payloadMapper, useCase, resultMapper } = config;\n\n const input = payloadMapper(\n validatedEvent as unknown as ValidatedEvent<EventHandlerDefinition>,\n validatedContext as EventMetadata,\n );\n\n const output = await useCase.execute(input);\n\n return resultMapper ? resultMapper(output) : { outcome: 'ack' };\n }\n };\n\n if (allMiddleware.length === 0) {\n return await executePipeline();\n }\n\n // Build middleware chain\n let index = 0;\n const next = async (): Promise<EventResult> => {\n if (index >= allMiddleware.length) {\n return executePipeline();\n }\n // eslint-disable-next-line @typescript-eslint/no-non-null-assertion -- index bounds checked above\n const mw = allMiddleware[index++]!;\n return mw(rawEvent, next);\n };\n\n return await next();\n } catch (error) {\n return errorMapper(error);\n }\n },\n };\n}\n\n// ============================================================================\n// Validation Helpers\n// ============================================================================\n\ninterface ValidationResultInternal {\n success: boolean;\n errors?: ValidationIssue[];\n data?: unknown;\n}\n\n/**\n * Validates event payload against the handler's payload schema.\n */\nfunction validatePayloadData(\n handler: EventHandlerDefinition,\n payload: unknown,\n): ValidationResultInternal {\n const schema = handler.payload as SchemaAdapter | undefined;\n if (!schema) return { success: true, data: payload };\n\n const result = schema.validate(payload);\n if (result.success) {\n return { success: true, data: result.data };\n }\n\n const errors = result.issues.map((issue) => ({\n ...issue,\n path: ['payload', ...issue.path],\n }));\n\n return { success: false, errors };\n}\n\n/**\n * Validates event metadata against the handler's context schema.\n */\nfunction validateContextData(\n handler: EventHandlerDefinition,\n metadata: EventMetadata,\n): ValidationResultInternal {\n const schema = handler.context as SchemaAdapter | undefined;\n if (!schema) return { success: true, data: metadata };\n\n const result = schema.validate(metadata);\n if (result.success) {\n return { success: true, data: result.data };\n }\n\n const errors = result.issues.map((issue) => ({\n ...issue,\n path: ['context', ...issue.path],\n }));\n\n return { success: false, errors };\n}\n\n/**\n * Internal validated event type with unknown fields.\n * Used inside createEventHandler where specific types are erased.\n */\ninterface ValidatedEventInternal {\n readonly payload: unknown;\n readonly raw: RawEvent;\n}\n","/**\n * @fileoverview Builder pattern for creating type-safe event routes.\n *\n * The `eventRoutes` function returns a builder that provides 100% type inference\n * for all handler parameters — no manual type annotations required.\n *\n * @module events/server/event-routes-builder\n */\n\nimport type {\n EventRouterConfig,\n EventRouterDefinition,\n GetEventHandler,\n EventRouterKeys,\n EventHandlerDefinition,\n} from '../handler/types';\nimport type { EventResult } from '../shared/types';\nimport type {\n AnyEventHandlerConfig,\n CreateEventRoutesOptions,\n EventHandlerConfig,\n EventMiddlewareFunction,\n SimpleEventHandlerConfig,\n SimpleEventHandlerFn,\n TypedEventContext,\n UnifiedEventInput,\n ValidatedEvent,\n} from './types';\nimport { createEventRoutesInternal } from './create-event-routes';\n\n// ============================================================================\n// Builder Types\n// ============================================================================\n\n/**\n * Error type displayed when attempting to build() with missing handlers.\n * The `___missingHandlers` property shows which handlers are missing.\n */\nexport interface MissingHandlersError<TMissing extends string> {\n /**\n * This error indicates that not all event handlers have been wired.\n * Use buildPartial() to build with only the defined handlers,\n * or add handlers for the missing events.\n */\n (options?: never): never;\n /** Event handlers that are missing. */\n readonly ___missingHandlers: TMissing;\n}\n\n/**\n * Handler configuration for the builder pattern.\n */\nexport interface BuilderEventHandlerConfig<\n THandler extends EventHandlerDefinition,\n TInput,\n TOutput,\n> {\n /**\n * Maps the validated event payload to use case input.\n * Both `event` and `ctx` are fully typed based on handler schemas.\n */\n readonly payloadMapper: (\n event: ValidatedEvent<THandler>,\n ctx: TypedEventContext<THandler>,\n ) => TInput;\n\n /** The use case to execute. */\n readonly useCase: { execute(input?: TInput): Promise<TOutput> };\n\n /**\n * Maps the use case output to an EventResult.\n * If omitted, defaults to `{ outcome: 'ack' }`.\n */\n readonly resultMapper?: (output: TOutput) => EventResult;\n\n /** Middleware to run before the handler. */\n readonly middleware?: readonly EventMiddlewareFunction[];\n}\n\n/**\n * Builder interface for creating type-safe event routes.\n *\n * Each `.handle()` call captures the specific handler type and provides\n * full type inference for payloadMapper and useCase.\n *\n * @typeParam T - The event router configuration type\n * @typeParam THandled - Union of handler keys that have been wired (accumulates)\n *\n * @example\n * ```typescript\n * const routes = eventRoutes(ticketEvents)\n * .handleWithUseCase('created', {\n * payloadMapper: (event, ctx) => ({\n * ticketId: event.payload.ticketId, // Fully typed!\n * correlationId: ctx.correlationId, // Fully typed!\n * }),\n * useCase: sendNotificationUseCase,\n * })\n * .handle('assigned', async (event) => {\n * await notifyAssignee(event.payload);\n * return { outcome: 'ack' as const };\n * })\n * .build();\n * ```\n */\nexport interface EventRoutesBuilder<T extends EventRouterConfig, THandled extends string = never> {\n /**\n * Register a simple handler for an event.\n * The handler receives validated event and context, returns EventResult directly.\n */\n handle<K extends Exclude<EventRouterKeys<T>, THandled>>(\n key: K,\n handlerOrConfig:\n | SimpleEventHandlerFn<GetEventHandler<T, K>>\n | SimpleEventHandlerConfig<GetEventHandler<T, K>>,\n ): EventRoutesBuilder<T, THandled | K>;\n\n /**\n * Register a handler using the use case pattern.\n * Follows: payloadMapper → useCase.execute() → resultMapper (or ack)\n */\n handleWithUseCase<K extends Exclude<EventRouterKeys<T>, THandled>, TInput, TOutput>(\n key: K,\n config: BuilderEventHandlerConfig<GetEventHandler<T, K>, TInput, TOutput>,\n ): EventRoutesBuilder<T, THandled | K>;\n\n /**\n * Build the event routes array for messaging adapter registration.\n *\n * This method is only available when ALL handlers have been wired.\n * If some handlers are missing, use `buildPartial()` instead.\n */\n build: [Exclude<EventRouterKeys<T>, THandled>] extends [never]\n ? (options?: CreateEventRoutesOptions) => UnifiedEventInput[]\n : MissingHandlersError<Exclude<EventRouterKeys<T>, THandled>>;\n\n /**\n * Build event routes for only the defined handlers.\n * No compile-time enforcement of completeness.\n */\n buildPartial(options?: CreateEventRoutesOptions): UnifiedEventInput[];\n}\n\n// ============================================================================\n// Builder Implementation\n// ============================================================================\n\n/**\n * Internal builder implementation.\n *\n * Uses an immutable pattern where each handle() call returns a new\n * builder instance with the updated handlers map.\n */\nclass EventRoutesBuilderImpl<T extends EventRouterConfig, THandled extends string = never> {\n private readonly router: T | EventRouterDefinition<T>;\n private readonly handlers: Map<\n string,\n AnyEventHandlerConfig<EventHandlerDefinition, unknown, unknown>\n >;\n\n constructor(\n router: T | EventRouterDefinition<T>,\n handlers?: Map<string, AnyEventHandlerConfig<EventHandlerDefinition, unknown, unknown>>,\n ) {\n this.router = router;\n this.handlers = handlers ?? new Map();\n }\n\n handle<K extends Exclude<EventRouterKeys<T>, THandled>>(\n key: K,\n handlerOrConfig:\n | SimpleEventHandlerFn<GetEventHandler<T, K>>\n | SimpleEventHandlerConfig<GetEventHandler<T, K>>,\n ): EventRoutesBuilder<T, THandled | K> {\n const config: SimpleEventHandlerConfig<EventHandlerDefinition> =\n typeof handlerOrConfig === 'function'\n ? { handler: handlerOrConfig as SimpleEventHandlerFn<EventHandlerDefinition> }\n : (handlerOrConfig as SimpleEventHandlerConfig<EventHandlerDefinition>);\n\n const newHandlers = new Map(this.handlers);\n newHandlers.set(key as string, config);\n\n return new EventRoutesBuilderImpl<T, THandled | K>(\n this.router,\n newHandlers,\n ) as unknown as EventRoutesBuilder<T, THandled | K>;\n }\n\n handleWithUseCase<K extends Exclude<EventRouterKeys<T>, THandled>, TInput, TOutput>(\n key: K,\n config: BuilderEventHandlerConfig<GetEventHandler<T, K>, TInput, TOutput>,\n ): EventRoutesBuilder<T, THandled | K> {\n const newHandlers = new Map(this.handlers);\n newHandlers.set(\n key as string,\n config as EventHandlerConfig<EventHandlerDefinition, unknown, unknown>,\n );\n\n return new EventRoutesBuilderImpl<T, THandled | K>(\n this.router,\n newHandlers,\n ) as unknown as EventRoutesBuilder<T, THandled | K>;\n }\n\n build(options?: CreateEventRoutesOptions): UnifiedEventInput[] {\n return createEventRoutesInternal(this.router, Object.fromEntries(this.handlers), options);\n }\n\n buildPartial(options?: CreateEventRoutesOptions): UnifiedEventInput[] {\n return createEventRoutesInternal(this.router, Object.fromEntries(this.handlers), {\n ...options,\n allowPartial: true,\n });\n }\n}\n\n// ============================================================================\n// Public API\n// ============================================================================\n\n/**\n * Creates a type-safe event routes builder for an event router.\n *\n * The builder pattern provides 100% type inference for all handler parameters:\n * - `event.payload` is typed from the handler's payload schema\n * - `ctx` is typed from the handler's context schema (or EventMetadata)\n * - `output` in resultMapper is typed from the use case\n *\n * @param router - Event router definition or event router config\n * @returns Builder for registering handlers\n *\n * @example Basic usage\n * ```typescript\n * import { eventRoutes } from '@cosmneo/onion-lasagna/events/server';\n * import { ticketEvents } from './router';\n *\n * const routes = eventRoutes(ticketEvents)\n * .handleWithUseCase('created', {\n * payloadMapper: (event, ctx) => ({\n * ticketId: event.payload.ticketId,\n * correlationId: ctx.correlationId,\n * }),\n * useCase: sendNotificationUseCase,\n * })\n * .handle('assigned', async (event) => {\n * await notifyAssignee(event.payload);\n * return { outcome: 'ack' as const };\n * })\n * .build();\n * ```\n */\nexport function eventRoutes<T extends EventRouterConfig>(\n router: T | EventRouterDefinition<T>,\n): EventRoutesBuilder<T, never> {\n return new EventRoutesBuilderImpl(router) as unknown as EventRoutesBuilder<T, never>;\n}\n"],"mappings":"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","names":[]}
|