@asenajs/asena 0.7.0 → 0.8.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 (140) hide show
  1. package/README.md +2 -2
  2. package/dist/lib/adapter/AsenaAdapter.d.ts +5 -3
  3. package/dist/lib/adapter/AsenaAdapter.js.map +1 -1
  4. package/dist/lib/adapter/AsenaContext.d.ts +6 -0
  5. package/dist/lib/adapter/types/ServeOptions.d.ts +16 -0
  6. package/dist/lib/ioc/Container.d.ts +25 -0
  7. package/dist/lib/ioc/Container.js +47 -0
  8. package/dist/lib/ioc/Container.js.map +1 -1
  9. package/dist/lib/ioc/CoreContainer.d.ts +5 -3
  10. package/dist/lib/ioc/CoreContainer.js +9 -3
  11. package/dist/lib/ioc/CoreContainer.js.map +1 -1
  12. package/dist/lib/ioc/IocEngine.js +4 -5
  13. package/dist/lib/ioc/IocEngine.js.map +1 -1
  14. package/dist/lib/ioc/component/decorators/Inject.js +16 -0
  15. package/dist/lib/ioc/component/decorators/Inject.js.map +1 -1
  16. package/dist/lib/ioc/constants/ComponentConstants.d.ts +4 -0
  17. package/dist/lib/ioc/constants/ComponentConstants.js +5 -0
  18. package/dist/lib/ioc/constants/ComponentConstants.js.map +1 -1
  19. package/dist/lib/ioc/types/ICoreServiceNamesType.d.ts +1 -0
  20. package/dist/lib/ioc/types/ICoreServiceNamesType.js +1 -0
  21. package/dist/lib/ioc/types/ICoreServiceNamesType.js.map +1 -1
  22. package/dist/lib/ioc/types/InjectableComponent.d.ts +10 -0
  23. package/dist/lib/ioc/types/decorators/ComponentType.d.ts +2 -1
  24. package/dist/lib/ioc/types/decorators/ComponentType.js +1 -0
  25. package/dist/lib/ioc/types/decorators/ComponentType.js.map +1 -1
  26. package/dist/lib/server/AsenaServer.d.ts +46 -3
  27. package/dist/lib/server/AsenaServer.js +159 -29
  28. package/dist/lib/server/AsenaServer.js.map +1 -1
  29. package/dist/lib/server/AsenaServerFactory.d.ts +38 -3
  30. package/dist/lib/server/AsenaServerFactory.js +21 -2
  31. package/dist/lib/server/AsenaServerFactory.js.map +1 -1
  32. package/dist/lib/server/config/AsenaConfig.d.ts +82 -4
  33. package/dist/lib/server/config/AsenaConfig.js +39 -1
  34. package/dist/lib/server/config/AsenaConfig.js.map +1 -1
  35. package/dist/lib/server/decorators/components/FrontendController.js.map +1 -1
  36. package/dist/lib/server/decorators/components/MessageController.d.ts +49 -0
  37. package/dist/lib/server/decorators/components/MessageController.js +62 -0
  38. package/dist/lib/server/decorators/components/MessageController.js.map +1 -0
  39. package/dist/lib/server/decorators/components/index.d.ts +1 -0
  40. package/dist/lib/server/decorators/components/index.js +1 -0
  41. package/dist/lib/server/decorators/components/index.js.map +1 -1
  42. package/dist/lib/server/event/EventDispatchService.d.ts +3 -7
  43. package/dist/lib/server/event/EventDispatchService.js +9 -40
  44. package/dist/lib/server/event/EventDispatchService.js.map +1 -1
  45. package/dist/lib/server/event/PatternHandlerIndex.d.ts +53 -0
  46. package/dist/lib/server/event/PatternHandlerIndex.js +100 -0
  47. package/dist/lib/server/event/PatternHandlerIndex.js.map +1 -0
  48. package/dist/lib/server/event/decorators/On.d.ts +4 -0
  49. package/dist/lib/server/event/decorators/On.js +6 -0
  50. package/dist/lib/server/event/decorators/On.js.map +1 -1
  51. package/dist/lib/server/event/index.d.ts +1 -0
  52. package/dist/lib/server/event/index.js +2 -0
  53. package/dist/lib/server/event/index.js.map +1 -1
  54. package/dist/lib/server/event/types.d.ts +12 -0
  55. package/dist/lib/server/health/HealthServer.d.ts +26 -0
  56. package/dist/lib/server/health/HealthServer.js +63 -0
  57. package/dist/lib/server/health/HealthServer.js.map +1 -0
  58. package/dist/lib/server/health/index.d.ts +1 -0
  59. package/dist/lib/server/health/index.js +2 -0
  60. package/dist/lib/server/health/index.js.map +1 -0
  61. package/dist/lib/server/messaging/Ulak.d.ts +156 -0
  62. package/dist/lib/server/messaging/Ulak.js +174 -0
  63. package/dist/lib/server/messaging/Ulak.js.map +1 -1
  64. package/dist/lib/server/messaging/types.d.ts +5 -1
  65. package/dist/lib/server/messaging/types.js +5 -0
  66. package/dist/lib/server/messaging/types.js.map +1 -1
  67. package/dist/lib/server/microservice/InMemoryTransport.d.ts +45 -0
  68. package/dist/lib/server/microservice/InMemoryTransport.js +124 -0
  69. package/dist/lib/server/microservice/InMemoryTransport.js.map +1 -0
  70. package/dist/lib/server/microservice/MicroserviceTransport.d.ts +132 -0
  71. package/dist/lib/server/microservice/MicroserviceTransport.js +2 -0
  72. package/dist/lib/server/microservice/MicroserviceTransport.js.map +1 -0
  73. package/dist/lib/server/microservice/decorators/EventPattern.d.ts +38 -0
  74. package/dist/lib/server/microservice/decorators/EventPattern.js +59 -0
  75. package/dist/lib/server/microservice/decorators/EventPattern.js.map +1 -0
  76. package/dist/lib/server/microservice/decorators/MessagePattern.d.ts +31 -0
  77. package/dist/lib/server/microservice/decorators/MessagePattern.js +55 -0
  78. package/dist/lib/server/microservice/decorators/MessagePattern.js.map +1 -0
  79. package/dist/lib/server/microservice/decorators/index.d.ts +2 -0
  80. package/dist/lib/server/microservice/decorators/index.js +3 -0
  81. package/dist/lib/server/microservice/decorators/index.js.map +1 -0
  82. package/dist/lib/server/microservice/index.d.ts +5 -0
  83. package/dist/lib/server/microservice/index.js +11 -0
  84. package/dist/lib/server/microservice/index.js.map +1 -0
  85. package/dist/lib/server/microservice/interceptorChain.d.ts +20 -0
  86. package/dist/lib/server/microservice/interceptorChain.js +39 -0
  87. package/dist/lib/server/microservice/interceptorChain.js.map +1 -0
  88. package/dist/lib/server/microservice/types.d.ts +142 -0
  89. package/dist/lib/server/microservice/types.js +5 -0
  90. package/dist/lib/server/microservice/types.js.map +1 -0
  91. package/dist/lib/server/src/services/PrepareEventService.d.ts +4 -1
  92. package/dist/lib/server/src/services/PrepareEventService.js +10 -3
  93. package/dist/lib/server/src/services/PrepareEventService.js.map +1 -1
  94. package/dist/lib/server/src/services/PrepareFrontendControllerService.d.ts +1 -0
  95. package/dist/lib/server/src/services/PrepareFrontendControllerService.js +1 -1
  96. package/dist/lib/server/src/services/PrepareFrontendControllerService.js.map +1 -1
  97. package/dist/lib/server/src/services/PrepareMicroserviceService.d.ts +66 -0
  98. package/dist/lib/server/src/services/PrepareMicroserviceService.js +193 -0
  99. package/dist/lib/server/src/services/PrepareMicroserviceService.js.map +1 -0
  100. package/dist/lib/server/src/services/PrepareScheduleService.js.map +1 -1
  101. package/dist/lib/server/web/decorators/methods/Connect.js +9 -1
  102. package/dist/lib/server/web/decorators/methods/Connect.js.map +1 -1
  103. package/dist/lib/server/web/decorators/methods/Options.js +9 -1
  104. package/dist/lib/server/web/decorators/methods/Options.js.map +1 -1
  105. package/dist/lib/server/web/websocket/AsenaSocket.js.map +1 -1
  106. package/dist/lib/test/factory/deepMock.d.ts +25 -0
  107. package/dist/lib/test/factory/deepMock.js +105 -0
  108. package/dist/lib/test/factory/deepMock.js.map +1 -0
  109. package/dist/lib/test/factory/ulakStub.d.ts +44 -0
  110. package/dist/lib/test/factory/ulakStub.js +40 -0
  111. package/dist/lib/test/factory/ulakStub.js.map +1 -0
  112. package/dist/lib/test/harness/createTestApp.d.ts +33 -0
  113. package/dist/lib/test/harness/createTestApp.js +105 -0
  114. package/dist/lib/test/harness/createTestApp.js.map +1 -0
  115. package/dist/lib/test/harness/createWebTest.d.ts +28 -0
  116. package/dist/lib/test/harness/createWebTest.js +127 -0
  117. package/dist/lib/test/harness/createWebTest.js.map +1 -0
  118. package/dist/lib/test/harness/silentLogger.d.ts +27 -0
  119. package/dist/lib/test/harness/silentLogger.js +54 -0
  120. package/dist/lib/test/harness/silentLogger.js.map +1 -0
  121. package/dist/lib/test/harness/types.d.ts +147 -0
  122. package/dist/lib/test/harness/types.js +2 -0
  123. package/dist/lib/test/harness/types.js.map +1 -0
  124. package/dist/lib/test/http/TestHttpCall.d.ts +78 -0
  125. package/dist/lib/test/http/TestHttpCall.js +149 -0
  126. package/dist/lib/test/http/TestHttpCall.js.map +1 -0
  127. package/dist/lib/test/http/TestHttpResponse.d.ts +46 -0
  128. package/dist/lib/test/http/TestHttpResponse.js +70 -0
  129. package/dist/lib/test/http/TestHttpResponse.js.map +1 -0
  130. package/dist/lib/test/index.d.ts +9 -0
  131. package/dist/lib/test/index.js +8 -0
  132. package/dist/lib/test/index.js.map +1 -1
  133. package/dist/lib/test/metadata/discovery.d.ts +21 -0
  134. package/dist/lib/test/metadata/discovery.js +37 -8
  135. package/dist/lib/test/metadata/discovery.js.map +1 -1
  136. package/dist/lib/test/mockComponent.d.ts +25 -0
  137. package/dist/lib/test/mockComponent.js +39 -6
  138. package/dist/lib/test/mockComponent.js.map +1 -1
  139. package/dist/lib/test/types.d.ts +13 -0
  140. package/package.json +11 -7
@@ -0,0 +1,124 @@
1
+ import { UlakError, UlakErrorCode } from '../messaging/types';
2
+ import { PatternHandlerIndex } from '../event/PatternHandlerIndex';
3
+ /**
4
+ * @description Zero-dependency in-process microservice transport.
5
+ *
6
+ * Messages never leave the process — send/emit dispatch directly to handlers
7
+ * registered in the same application. Useful as:
8
+ * - a development mode before a broker is available
9
+ * - a test double for @MessageController integration tests
10
+ * - the reference implementation of the MicroserviceTransport SPI
11
+ *
12
+ * Delivery semantics: synchronous at-most-once, attempt is always 1.
13
+ *
14
+ * @example
15
+ * @Config()
16
+ * export class AppConfig extends ConfigService {
17
+ * transport() {
18
+ * return { microservice: new InMemoryTransport() };
19
+ * }
20
+ * }
21
+ */
22
+ export class InMemoryTransport {
23
+ name = 'in-memory';
24
+ /**
25
+ * Exact request pattern -> handler (request/response requires exact routing)
26
+ */
27
+ messageHandlers = new Map();
28
+ /**
29
+ * Event handler index (shared hybrid exact/wildcard implementation)
30
+ */
31
+ eventHandlers = new PatternHandlerIndex();
32
+ /**
33
+ * Monotonic counter used to build message ids
34
+ */
35
+ sequence = 0;
36
+ isConnected = true;
37
+ async init() {
38
+ // Nothing to connect - in-process only
39
+ }
40
+ registerMessageHandler(pattern, handler) {
41
+ // Validate the FINAL pattern: the decorator only sees the raw method
42
+ // pattern, so a wildcard or emptiness introduced by the @MessageController
43
+ // prefix would otherwise slip through
44
+ if (!pattern) {
45
+ throw new Error('Message pattern cannot be empty - check @MessagePattern and the @MessageController prefix');
46
+ }
47
+ if (pattern.includes('*')) {
48
+ throw new Error(`Message pattern "${pattern}" cannot contain wildcards - request/response requires exact routing ` +
49
+ '(a wildcard likely leaked in via the @MessageController prefix - remove it, or set ' +
50
+ 'prefix: false on the @MessagePattern)');
51
+ }
52
+ if (this.messageHandlers.has(pattern)) {
53
+ throw new Error(`Duplicate @MessagePattern('${pattern}') - a message pattern can only have one handler`);
54
+ }
55
+ this.messageHandlers.set(pattern, handler);
56
+ }
57
+ registerEventHandler(pattern, handler) {
58
+ if (!pattern) {
59
+ throw new Error('Event pattern cannot be empty - check @EventPattern and the @MessageController prefix');
60
+ }
61
+ this.eventHandlers.add(pattern, handler);
62
+ }
63
+ async listen() {
64
+ // Nothing to consume - handlers are invoked directly by send/emit
65
+ }
66
+ async send(pattern, data, options) {
67
+ const handler = this.messageHandlers.get(pattern);
68
+ if (!handler) {
69
+ throw new UlakError(`No message handler registered for pattern "${pattern}"`, UlakErrorCode.SEND_FAILED);
70
+ }
71
+ const context = this.createContext(pattern, crypto.randomUUID(), options?.headers);
72
+ const invocation = Promise.resolve().then(() => handler(data, context));
73
+ try {
74
+ const result = options?.timeout ? await this.withTimeout(invocation, options.timeout, pattern) : await invocation;
75
+ return result;
76
+ }
77
+ catch (error) {
78
+ if (error instanceof UlakError) {
79
+ throw error;
80
+ }
81
+ throw new UlakError(`Handler for pattern "${pattern}" failed: ${error.message}`, UlakErrorCode.REMOTE_ERROR, undefined, error);
82
+ }
83
+ }
84
+ async emit(pattern, data, options) {
85
+ const handlers = this.eventHandlers.collect(pattern);
86
+ // One context per emit: every handler of the same event must observe the
87
+ // SAME messageId (as in Redis, where all handlers see the entry id) - the
88
+ // documented messageId-dedup recipe relies on this
89
+ const context = this.createContext(pattern, undefined, options?.headers);
90
+ // Fire-and-forget: handler failures must not reach the emitter
91
+ await Promise.allSettled(handlers.map((handler) => Promise.resolve().then(() => handler(data, context))));
92
+ }
93
+ async destroy() {
94
+ this.messageHandlers.clear();
95
+ this.eventHandlers.clear();
96
+ }
97
+ createContext(pattern, correlationId, headers) {
98
+ return {
99
+ pattern,
100
+ messageId: `mem-${++this.sequence}`,
101
+ correlationId,
102
+ headers: { ...headers },
103
+ timestamp: Date.now(),
104
+ attempt: 1,
105
+ };
106
+ }
107
+ withTimeout(promise, timeout, pattern) {
108
+ return new Promise((resolve, reject) => {
109
+ const timer = setTimeout(() => {
110
+ reject(new UlakError(`Request "${pattern}" timed out after ${timeout}ms`, UlakErrorCode.TIMEOUT));
111
+ }, timeout);
112
+ promise
113
+ .then((value) => {
114
+ clearTimeout(timer);
115
+ resolve(value);
116
+ })
117
+ .catch((error) => {
118
+ clearTimeout(timer);
119
+ reject(error);
120
+ });
121
+ });
122
+ }
123
+ }
124
+ //# sourceMappingURL=InMemoryTransport.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"InMemoryTransport.js","sourceRoot":"","sources":["../../../../lib/server/microservice/InMemoryTransport.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,132 @@
1
+ /**
2
+ * @description Context passed to every microservice message/event handler.
3
+ * Carries transport-level metadata about the incoming message.
4
+ */
5
+ export interface MessageContext {
6
+ /**
7
+ * Concrete pattern of the incoming message (e.g. 'order.create')
8
+ */
9
+ pattern: string;
10
+ /**
11
+ * Transport-assigned unique id of the message (e.g. Redis stream entry id).
12
+ * Useful for idempotency/deduplication in at-least-once transports.
13
+ */
14
+ messageId: string;
15
+ /**
16
+ * Correlation id, present only for request/response messages
17
+ */
18
+ correlationId?: string;
19
+ /**
20
+ * Message headers (trace context, user metadata, ...)
21
+ */
22
+ headers: Record<string, string>;
23
+ /**
24
+ * Producer-side timestamp (epoch millis)
25
+ */
26
+ timestamp: number;
27
+ /**
28
+ * Delivery attempt number, starting at 1.
29
+ * Greater than 1 means the message was redelivered (at-least-once transports).
30
+ */
31
+ attempt: number;
32
+ }
33
+ /**
34
+ * @description Handler for request/response messages (@MessagePattern).
35
+ * The return value is serialized and sent back to the caller as the reply.
36
+ */
37
+ export type MessageHandler = (data: any, context: MessageContext) => any | Promise<any>;
38
+ /**
39
+ * @description Handler for fire-and-forget events (@EventPattern)
40
+ */
41
+ export type EventPatternHandler = (data: any, context: MessageContext) => void | Promise<void>;
42
+ /**
43
+ * @description Options for request/response sends
44
+ */
45
+ export interface SendOptions {
46
+ /**
47
+ * Reply timeout in milliseconds (transport default applies when omitted)
48
+ */
49
+ timeout?: number;
50
+ /**
51
+ * Extra headers attached to the outgoing message
52
+ */
53
+ headers?: Record<string, string>;
54
+ }
55
+ /**
56
+ * @description Options for fire-and-forget emits
57
+ */
58
+ export interface EmitOptions {
59
+ /**
60
+ * Extra headers attached to the outgoing event
61
+ */
62
+ headers?: Record<string, string>;
63
+ }
64
+ /**
65
+ * @description Options for transport shutdown
66
+ */
67
+ export interface DestroyOptions {
68
+ /**
69
+ * Max time in milliseconds to wait for in-flight handlers to finish
70
+ * before closing connections (graceful drain)
71
+ */
72
+ drainTimeout?: number;
73
+ }
74
+ /**
75
+ * @description Broker-agnostic microservice transport SPI.
76
+ *
77
+ * A transport carries two message semantics between Asena services:
78
+ * - request/response (@MessagePattern) — exact patterns, a reply is produced
79
+ * - fire-and-forget events (@EventPattern) — wildcard patterns allowed
80
+ *
81
+ * Lifecycle contract (driven by PrepareMicroserviceService):
82
+ * 1. registerMessageHandler / registerEventHandler — push all handler registrations
83
+ * 2. init() — connect broker resources; after init, send/emit must work (client-only mode)
84
+ * 3. listen() — start consuming. MUST only consume sources that have at least one
85
+ * registered handler; with zero handlers no consumer may be started (client-only mode)
86
+ * 4. destroy() — graceful drain, then release all resources
87
+ */
88
+ export interface MicroserviceTransport {
89
+ /**
90
+ * Human-readable transport name (used in logs and health reporting)
91
+ */
92
+ readonly name: string;
93
+ /**
94
+ * Whether the transport currently holds a live broker connection.
95
+ * Read by the health endpoint.
96
+ */
97
+ readonly isConnected: boolean;
98
+ /**
99
+ * Connect broker resources. Called once before listen().
100
+ * After init() resolves, send()/emit() must be usable (client-only mode).
101
+ */
102
+ init(): Promise<void>;
103
+ /**
104
+ * Register a request/response handler. Patterns must be exact (no wildcards).
105
+ */
106
+ registerMessageHandler(pattern: string, handler: MessageHandler): void;
107
+ /**
108
+ * Register a fire-and-forget event handler. Patterns arrive with the
109
+ * @MessageController prefix already resolved and may contain wildcards
110
+ * (e.g. 'payment.*').
111
+ */
112
+ registerEventHandler(pattern: string, handler: EventPatternHandler): void;
113
+ /**
114
+ * Start consuming registered patterns.
115
+ * Contract: only sources with at least one registered handler are consumed;
116
+ * with zero handlers no consumer loop is started.
117
+ */
118
+ listen(): Promise<void>;
119
+ /**
120
+ * Send a request and await its reply (request/response semantics)
121
+ */
122
+ send<T = unknown>(pattern: string, data?: unknown, options?: SendOptions): Promise<T>;
123
+ /**
124
+ * Emit a fire-and-forget event
125
+ */
126
+ emit(pattern: string, data?: unknown, options?: EmitOptions): Promise<void>;
127
+ /**
128
+ * Gracefully shut down: stop consuming, drain in-flight handlers,
129
+ * reject pending sends, release connections.
130
+ */
131
+ destroy(options?: DestroyOptions): Promise<void>;
132
+ }
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=MicroserviceTransport.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"MicroserviceTransport.js","sourceRoot":"","sources":["../../../../lib/server/microservice/MicroserviceTransport.ts"],"names":[],"mappings":""}
@@ -0,0 +1,38 @@
1
+ import type { EventPatternParams } from '../types';
2
+ /**
3
+ * @description EventPattern decorator - Marks a method as a fire-and-forget event handler
4
+ *
5
+ * Methods decorated with @EventPattern will be automatically registered into the
6
+ * configured microservice transport when the server boots (via PrepareMicroserviceService).
7
+ * No reply is produced; delivery is at-least-once on durable transports, so handlers
8
+ * should be idempotent (use context.messageId for deduplication).
9
+ *
10
+ * The controller prefix is joined onto the pattern ('order' + 'created' →
11
+ * 'order.created'), matching what ulak.messages('order').emit('created') publishes.
12
+ * Pass `prefix: false` when the pattern is absolute — another service's event
13
+ * vocabulary, a Kafka external topic name, or a global catch-all.
14
+ * Wildcards are supported: 'payment.*', '*.completed', 'user.*.created'.
15
+ * Note that under a prefix, '*' becomes 'order.*' and is no longer a global catch-all.
16
+ *
17
+ * @param params - Event pattern or configuration object
18
+ *
19
+ * @example
20
+ * @MessageController('order')
21
+ * export class OrderHandler {
22
+ * @EventPattern('created') // Handles 'order.created'
23
+ * async onCreated(event: OrderEvent, context: MessageContext) { }
24
+ *
25
+ * // Absolute - another service's event vocabulary
26
+ * @EventPattern({ pattern: 'payment.completed', prefix: false })
27
+ * async onPaymentCompleted(event: PaymentEvent, context: MessageContext) {
28
+ * await this.orderService.markPaid(event.orderId);
29
+ * }
30
+ *
31
+ * @EventPattern('*') // Wildcards allowed - handles 'order.*'
32
+ * async onAnyOrderEvent(event: any, context: MessageContext) { }
33
+ *
34
+ * @EventPattern({ pattern: 'stock.depleted', skip: true }) // Temporarily disabled
35
+ * async onStockDepleted(event: any, context: MessageContext) { }
36
+ * }
37
+ */
38
+ export declare function EventPattern(params: EventPatternParams | string): MethodDecorator;
@@ -0,0 +1,59 @@
1
+ import { ComponentConstants } from '../../../ioc';
2
+ import { defineTypedMetadata, getOwnTypedMetadata } from '../../../utils';
3
+ /**
4
+ * @description EventPattern decorator - Marks a method as a fire-and-forget event handler
5
+ *
6
+ * Methods decorated with @EventPattern will be automatically registered into the
7
+ * configured microservice transport when the server boots (via PrepareMicroserviceService).
8
+ * No reply is produced; delivery is at-least-once on durable transports, so handlers
9
+ * should be idempotent (use context.messageId for deduplication).
10
+ *
11
+ * The controller prefix is joined onto the pattern ('order' + 'created' →
12
+ * 'order.created'), matching what ulak.messages('order').emit('created') publishes.
13
+ * Pass `prefix: false` when the pattern is absolute — another service's event
14
+ * vocabulary, a Kafka external topic name, or a global catch-all.
15
+ * Wildcards are supported: 'payment.*', '*.completed', 'user.*.created'.
16
+ * Note that under a prefix, '*' becomes 'order.*' and is no longer a global catch-all.
17
+ *
18
+ * @param params - Event pattern or configuration object
19
+ *
20
+ * @example
21
+ * @MessageController('order')
22
+ * export class OrderHandler {
23
+ * @EventPattern('created') // Handles 'order.created'
24
+ * async onCreated(event: OrderEvent, context: MessageContext) { }
25
+ *
26
+ * // Absolute - another service's event vocabulary
27
+ * @EventPattern({ pattern: 'payment.completed', prefix: false })
28
+ * async onPaymentCompleted(event: PaymentEvent, context: MessageContext) {
29
+ * await this.orderService.markPaid(event.orderId);
30
+ * }
31
+ *
32
+ * @EventPattern('*') // Wildcards allowed - handles 'order.*'
33
+ * async onAnyOrderEvent(event: any, context: MessageContext) { }
34
+ *
35
+ * @EventPattern({ pattern: 'stock.depleted', skip: true }) // Temporarily disabled
36
+ * async onStockDepleted(event: any, context: MessageContext) { }
37
+ * }
38
+ */
39
+ export function EventPattern(params) {
40
+ // Normalize params - support both object and string
41
+ const _params = typeof params === 'string' ? { pattern: params, skip: false } : params;
42
+ return function (target, propertyKey, descriptor) {
43
+ // Get existing handlers metadata (other @MessagePattern/@EventPattern methods)
44
+ const handlers = getOwnTypedMetadata(ComponentConstants.MessageHandlersKey, target.constructor) || {};
45
+ // Add this handler's metadata
46
+ handlers[propertyKey.toString()] = {
47
+ pattern: _params.pattern,
48
+ type: 'event',
49
+ methodName: propertyKey.toString(),
50
+ // `!== false` covers the string shorthand and objects that omit the flag
51
+ prefix: _params.prefix !== false,
52
+ skip: _params.skip || false,
53
+ };
54
+ // Store updated metadata
55
+ defineTypedMetadata(ComponentConstants.MessageHandlersKey, handlers, target.constructor);
56
+ return descriptor;
57
+ };
58
+ }
59
+ //# sourceMappingURL=EventPattern.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"EventPattern.js","sourceRoot":"","sources":["../../../../../lib/server/microservice/decorators/EventPattern.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,kBAAkB,EAAE,MAAM,cAAc,CAAC;AAClD,OAAO,EAAE,mBAAmB,EAAE,mBAAmB,EAAE,MAAM,gBAAgB,CAAC;AAG1E;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAmCG;AACH,MAAM,UAAU,YAAY,CAAC,MAAmC;IAC9D,oDAAoD;IACpD,MAAM,OAAO,GAAG,OAAO,MAAM,KAAK,QAAQ,CAAC,CAAC,CAAC,EAAE,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC,CAAC,CAAC,MAAM,CAAC;IAEvF,OAAO,UAAU,MAAc,EAAE,WAA4B,EAAE,UAA8B;QAC3F,+EAA+E;QAC/E,MAAM,QAAQ,GACZ,mBAAmB,CACjB,kBAAkB,CAAC,kBAAkB,EACrC,MAAM,CAAC,WAAW,CACnB,IAAI,EAAE,CAAC;QAEV,8BAA8B;QAC9B,QAAQ,CAAC,WAAW,CAAC,QAAQ,EAAE,CAAC,GAAG;YACjC,OAAO,EAAE,OAAO,CAAC,OAAO;YACxB,IAAI,EAAE,OAAO;YACb,UAAU,EAAE,WAAW,CAAC,QAAQ,EAAE;YAClC,yEAAyE;YACzE,MAAM,EAAE,OAAO,CAAC,MAAM,KAAK,KAAK;YAChC,IAAI,EAAE,OAAO,CAAC,IAAI,IAAI,KAAK;SAC5B,CAAC;QAEF,yBAAyB;QACzB,mBAAmB,CAAC,kBAAkB,CAAC,kBAAkB,EAAE,QAAQ,EAAE,MAAM,CAAC,WAAW,CAAC,CAAC;QAEzF,OAAO,UAAU,CAAC;IACpB,CAAC,CAAC;AACJ,CAAC"}
@@ -0,0 +1,31 @@
1
+ import type { MessagePatternParams } from '../types';
2
+ /**
3
+ * @description MessagePattern decorator - Marks a method as a request/response handler
4
+ *
5
+ * Methods decorated with @MessagePattern will be automatically registered into the
6
+ * configured microservice transport when the server boots (via PrepareMicroserviceService).
7
+ * The method's return value is sent back to the caller as the reply.
8
+ *
9
+ * The controller prefix is joined onto the pattern ('order' + 'create' → 'order.create').
10
+ * Pass `prefix: false` to register the pattern verbatim.
11
+ * Wildcards are NOT allowed — request/response requires exact routing — and
12
+ * `prefix: false` does not relax that.
13
+ *
14
+ * @param params - Request pattern or configuration object
15
+ *
16
+ * @example
17
+ * @MessageController('order')
18
+ * export class OrderHandler {
19
+ * @MessagePattern('create') // Handles 'order.create'
20
+ * async create(data: CreateOrderDto, context: MessageContext) {
21
+ * return this.orderService.create(data); // reply sent to caller
22
+ * }
23
+ *
24
+ * @MessagePattern({ pattern: 'ping', prefix: false }) // Handles 'ping'
25
+ * async ping(data: any, context: MessageContext) { }
26
+ *
27
+ * @MessagePattern({ pattern: 'delete', skip: true }) // Temporarily disabled
28
+ * async delete(data: any, context: MessageContext) { }
29
+ * }
30
+ */
31
+ export declare function MessagePattern(params: MessagePatternParams | string): MethodDecorator;
@@ -0,0 +1,55 @@
1
+ import { ComponentConstants } from '../../../ioc';
2
+ import { defineTypedMetadata, getOwnTypedMetadata } from '../../../utils';
3
+ /**
4
+ * @description MessagePattern decorator - Marks a method as a request/response handler
5
+ *
6
+ * Methods decorated with @MessagePattern will be automatically registered into the
7
+ * configured microservice transport when the server boots (via PrepareMicroserviceService).
8
+ * The method's return value is sent back to the caller as the reply.
9
+ *
10
+ * The controller prefix is joined onto the pattern ('order' + 'create' → 'order.create').
11
+ * Pass `prefix: false` to register the pattern verbatim.
12
+ * Wildcards are NOT allowed — request/response requires exact routing — and
13
+ * `prefix: false` does not relax that.
14
+ *
15
+ * @param params - Request pattern or configuration object
16
+ *
17
+ * @example
18
+ * @MessageController('order')
19
+ * export class OrderHandler {
20
+ * @MessagePattern('create') // Handles 'order.create'
21
+ * async create(data: CreateOrderDto, context: MessageContext) {
22
+ * return this.orderService.create(data); // reply sent to caller
23
+ * }
24
+ *
25
+ * @MessagePattern({ pattern: 'ping', prefix: false }) // Handles 'ping'
26
+ * async ping(data: any, context: MessageContext) { }
27
+ *
28
+ * @MessagePattern({ pattern: 'delete', skip: true }) // Temporarily disabled
29
+ * async delete(data: any, context: MessageContext) { }
30
+ * }
31
+ */
32
+ export function MessagePattern(params) {
33
+ // Normalize params - support both object and string
34
+ const _params = typeof params === 'string' ? { pattern: params, skip: false } : params;
35
+ if (_params.pattern.includes('*')) {
36
+ throw new Error(`@MessagePattern('${_params.pattern}') cannot contain wildcards - request/response requires exact patterns. Use @EventPattern for wildcard subscriptions.`);
37
+ }
38
+ return function (target, propertyKey, descriptor) {
39
+ // Get existing handlers metadata (other @MessagePattern/@EventPattern methods)
40
+ const handlers = getOwnTypedMetadata(ComponentConstants.MessageHandlersKey, target.constructor) || {};
41
+ // Add this handler's metadata
42
+ handlers[propertyKey.toString()] = {
43
+ pattern: _params.pattern,
44
+ type: 'message',
45
+ methodName: propertyKey.toString(),
46
+ // `!== false` covers the string shorthand and objects that omit the flag
47
+ prefix: _params.prefix !== false,
48
+ skip: _params.skip || false,
49
+ };
50
+ // Store updated metadata
51
+ defineTypedMetadata(ComponentConstants.MessageHandlersKey, handlers, target.constructor);
52
+ return descriptor;
53
+ };
54
+ }
55
+ //# sourceMappingURL=MessagePattern.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"MessagePattern.js","sourceRoot":"","sources":["../../../../../lib/server/microservice/decorators/MessagePattern.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,kBAAkB,EAAE,MAAM,cAAc,CAAC;AAClD,OAAO,EAAE,mBAAmB,EAAE,mBAAmB,EAAE,MAAM,gBAAgB,CAAC;AAG1E;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AACH,MAAM,UAAU,cAAc,CAAC,MAAqC;IAClE,oDAAoD;IACpD,MAAM,OAAO,GAAG,OAAO,MAAM,KAAK,QAAQ,CAAC,CAAC,CAAC,EAAE,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC,CAAC,CAAC,MAAM,CAAC;IAEvF,IAAI,OAAO,CAAC,OAAO,CAAC,QAAQ,CAAC,GAAG,CAAC,EAAE,CAAC;QAClC,MAAM,IAAI,KAAK,CACb,oBAAoB,OAAO,CAAC,OAAO,uHAAuH,CAC3J,CAAC;IACJ,CAAC;IAED,OAAO,UAAU,MAAc,EAAE,WAA4B,EAAE,UAA8B;QAC3F,+EAA+E;QAC/E,MAAM,QAAQ,GACZ,mBAAmB,CACjB,kBAAkB,CAAC,kBAAkB,EACrC,MAAM,CAAC,WAAW,CACnB,IAAI,EAAE,CAAC;QAEV,8BAA8B;QAC9B,QAAQ,CAAC,WAAW,CAAC,QAAQ,EAAE,CAAC,GAAG;YACjC,OAAO,EAAE,OAAO,CAAC,OAAO;YACxB,IAAI,EAAE,SAAS;YACf,UAAU,EAAE,WAAW,CAAC,QAAQ,EAAE;YAClC,yEAAyE;YACzE,MAAM,EAAE,OAAO,CAAC,MAAM,KAAK,KAAK;YAChC,IAAI,EAAE,OAAO,CAAC,IAAI,IAAI,KAAK;SAC5B,CAAC;QAEF,yBAAyB;QACzB,mBAAmB,CAAC,kBAAkB,CAAC,kBAAkB,EAAE,QAAQ,EAAE,MAAM,CAAC,WAAW,CAAC,CAAC;QAEzF,OAAO,UAAU,CAAC;IACpB,CAAC,CAAC;AACJ,CAAC"}
@@ -0,0 +1,2 @@
1
+ export * from './MessagePattern';
2
+ export * from './EventPattern';
@@ -0,0 +1,3 @@
1
+ export * from './MessagePattern';
2
+ export * from './EventPattern';
3
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../../lib/server/microservice/decorators/index.ts"],"names":[],"mappings":"AAAA,cAAc,kBAAkB,CAAC;AACjC,cAAc,gBAAgB,CAAC"}
@@ -0,0 +1,5 @@
1
+ export * from './MicroserviceTransport';
2
+ export * from './types';
3
+ export * from './InMemoryTransport';
4
+ export * from './interceptorChain';
5
+ export * from './decorators';
@@ -0,0 +1,11 @@
1
+ // Transport SPI
2
+ export * from './MicroserviceTransport';
3
+ // Types (params, metadata, interceptor SPI)
4
+ export * from './types';
5
+ // In-process reference transport
6
+ export * from './InMemoryTransport';
7
+ // Interceptor composition (used by Ulak and PrepareMicroserviceService)
8
+ export * from './interceptorChain';
9
+ // Decorators
10
+ export * from './decorators';
11
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../lib/server/microservice/index.ts"],"names":[],"mappings":"AAAA,gBAAgB;AAChB,cAAc,yBAAyB,CAAC;AAExC,4CAA4C;AAC5C,cAAc,SAAS,CAAC;AAExB,iCAAiC;AACjC,cAAc,qBAAqB,CAAC;AAEpC,wEAAwE;AACxE,cAAc,oBAAoB,CAAC;AAEnC,aAAa;AACb,cAAc,cAAc,CAAC"}
@@ -0,0 +1,20 @@
1
+ import type { MessageContext } from './MicroserviceTransport';
2
+ import type { MessagingInterceptor, OutboundContext } from './types';
3
+ /**
4
+ * @description Composes interceptor onSend hooks around an outgoing operation.
5
+ * Interceptors run in registration order (first interceptor is outermost).
6
+ *
7
+ * @param interceptors - Registered messaging interceptors
8
+ * @param ctx - Outbound context (interceptors may mutate ctx.headers)
9
+ * @param operation - The actual transport send/emit call
10
+ */
11
+ export declare function composeOnSend(interceptors: MessagingInterceptor[], ctx: OutboundContext, operation: () => Promise<any>): Promise<any>;
12
+ /**
13
+ * @description Composes interceptor onReceive hooks around a handler invocation.
14
+ * Interceptors run in registration order (first interceptor is outermost).
15
+ *
16
+ * @param interceptors - Registered messaging interceptors
17
+ * @param ctx - Incoming message context
18
+ * @param operation - The actual handler invocation
19
+ */
20
+ export declare function composeOnReceive(interceptors: MessagingInterceptor[], ctx: MessageContext, operation: () => Promise<any>): Promise<any>;
@@ -0,0 +1,39 @@
1
+ /**
2
+ * @description Composes interceptor onSend hooks around an outgoing operation.
3
+ * Interceptors run in registration order (first interceptor is outermost).
4
+ *
5
+ * @param interceptors - Registered messaging interceptors
6
+ * @param ctx - Outbound context (interceptors may mutate ctx.headers)
7
+ * @param operation - The actual transport send/emit call
8
+ */
9
+ export function composeOnSend(interceptors, ctx, operation) {
10
+ let next = operation;
11
+ for (let i = interceptors.length - 1; i >= 0; i--) {
12
+ const interceptor = interceptors[i];
13
+ if (interceptor.onSend) {
14
+ const inner = next;
15
+ next = () => interceptor.onSend(ctx, inner);
16
+ }
17
+ }
18
+ return next();
19
+ }
20
+ /**
21
+ * @description Composes interceptor onReceive hooks around a handler invocation.
22
+ * Interceptors run in registration order (first interceptor is outermost).
23
+ *
24
+ * @param interceptors - Registered messaging interceptors
25
+ * @param ctx - Incoming message context
26
+ * @param operation - The actual handler invocation
27
+ */
28
+ export function composeOnReceive(interceptors, ctx, operation) {
29
+ let next = operation;
30
+ for (let i = interceptors.length - 1; i >= 0; i--) {
31
+ const interceptor = interceptors[i];
32
+ if (interceptor.onReceive) {
33
+ const inner = next;
34
+ next = () => interceptor.onReceive(ctx, inner);
35
+ }
36
+ }
37
+ return next();
38
+ }
39
+ //# sourceMappingURL=interceptorChain.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"interceptorChain.js","sourceRoot":"","sources":["../../../../lib/server/microservice/interceptorChain.ts"],"names":[],"mappings":"AAGA;;;;;;;GAOG;AACH,MAAM,UAAU,aAAa,CAC3B,YAAoC,EACpC,GAAoB,EACpB,SAA6B;IAE7B,IAAI,IAAI,GAAG,SAAS,CAAC;IAErB,KAAK,IAAI,CAAC,GAAG,YAAY,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC,IAAI,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC;QAClD,MAAM,WAAW,GAAG,YAAY,CAAC,CAAC,CAAC,CAAC;QAEpC,IAAI,WAAW,CAAC,MAAM,EAAE,CAAC;YACvB,MAAM,KAAK,GAAG,IAAI,CAAC;YAEnB,IAAI,GAAG,GAAG,EAAE,CAAC,WAAW,CAAC,MAAM,CAAC,GAAG,EAAE,KAAK,CAAC,CAAC;QAC9C,CAAC;IACH,CAAC;IAED,OAAO,IAAI,EAAE,CAAC;AAChB,CAAC;AAED;;;;;;;GAOG;AACH,MAAM,UAAU,gBAAgB,CAC9B,YAAoC,EACpC,GAAmB,EACnB,SAA6B;IAE7B,IAAI,IAAI,GAAG,SAAS,CAAC;IAErB,KAAK,IAAI,CAAC,GAAG,YAAY,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC,IAAI,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC;QAClD,MAAM,WAAW,GAAG,YAAY,CAAC,CAAC,CAAC,CAAC;QAEpC,IAAI,WAAW,CAAC,SAAS,EAAE,CAAC;YAC1B,MAAM,KAAK,GAAG,IAAI,CAAC;YAEnB,IAAI,GAAG,GAAG,EAAE,CAAC,WAAW,CAAC,SAAS,CAAC,GAAG,EAAE,KAAK,CAAC,CAAC;QACjD,CAAC;IACH,CAAC;IAED,OAAO,IAAI,EAAE,CAAC;AAChB,CAAC"}