@asenajs/asena 0.7.1 → 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 (129) hide show
  1. package/README.md +2 -2
  2. package/dist/lib/adapter/AsenaAdapter.d.ts +2 -2
  3. package/dist/lib/adapter/AsenaAdapter.js.map +1 -1
  4. package/dist/lib/adapter/types/ServeOptions.d.ts +16 -0
  5. package/dist/lib/ioc/Container.d.ts +25 -0
  6. package/dist/lib/ioc/Container.js +47 -0
  7. package/dist/lib/ioc/Container.js.map +1 -1
  8. package/dist/lib/ioc/CoreContainer.d.ts +5 -3
  9. package/dist/lib/ioc/CoreContainer.js +9 -3
  10. package/dist/lib/ioc/CoreContainer.js.map +1 -1
  11. package/dist/lib/ioc/IocEngine.js +3 -1
  12. package/dist/lib/ioc/IocEngine.js.map +1 -1
  13. package/dist/lib/ioc/component/decorators/Inject.js +16 -0
  14. package/dist/lib/ioc/component/decorators/Inject.js.map +1 -1
  15. package/dist/lib/ioc/constants/ComponentConstants.d.ts +4 -0
  16. package/dist/lib/ioc/constants/ComponentConstants.js +5 -0
  17. package/dist/lib/ioc/constants/ComponentConstants.js.map +1 -1
  18. package/dist/lib/ioc/types/ICoreServiceNamesType.d.ts +1 -0
  19. package/dist/lib/ioc/types/ICoreServiceNamesType.js +1 -0
  20. package/dist/lib/ioc/types/ICoreServiceNamesType.js.map +1 -1
  21. package/dist/lib/ioc/types/InjectableComponent.d.ts +10 -0
  22. package/dist/lib/ioc/types/decorators/ComponentType.d.ts +2 -1
  23. package/dist/lib/ioc/types/decorators/ComponentType.js +1 -0
  24. package/dist/lib/ioc/types/decorators/ComponentType.js.map +1 -1
  25. package/dist/lib/server/AsenaServer.d.ts +46 -3
  26. package/dist/lib/server/AsenaServer.js +158 -28
  27. package/dist/lib/server/AsenaServer.js.map +1 -1
  28. package/dist/lib/server/AsenaServerFactory.d.ts +38 -3
  29. package/dist/lib/server/AsenaServerFactory.js +21 -2
  30. package/dist/lib/server/AsenaServerFactory.js.map +1 -1
  31. package/dist/lib/server/config/AsenaConfig.d.ts +82 -4
  32. package/dist/lib/server/config/AsenaConfig.js +39 -1
  33. package/dist/lib/server/config/AsenaConfig.js.map +1 -1
  34. package/dist/lib/server/decorators/components/MessageController.d.ts +49 -0
  35. package/dist/lib/server/decorators/components/MessageController.js +62 -0
  36. package/dist/lib/server/decorators/components/MessageController.js.map +1 -0
  37. package/dist/lib/server/decorators/components/index.d.ts +1 -0
  38. package/dist/lib/server/decorators/components/index.js +1 -0
  39. package/dist/lib/server/decorators/components/index.js.map +1 -1
  40. package/dist/lib/server/event/EventDispatchService.d.ts +3 -7
  41. package/dist/lib/server/event/EventDispatchService.js +9 -40
  42. package/dist/lib/server/event/EventDispatchService.js.map +1 -1
  43. package/dist/lib/server/event/PatternHandlerIndex.d.ts +53 -0
  44. package/dist/lib/server/event/PatternHandlerIndex.js +100 -0
  45. package/dist/lib/server/event/PatternHandlerIndex.js.map +1 -0
  46. package/dist/lib/server/event/decorators/On.d.ts +4 -0
  47. package/dist/lib/server/event/decorators/On.js +6 -0
  48. package/dist/lib/server/event/decorators/On.js.map +1 -1
  49. package/dist/lib/server/event/index.d.ts +1 -0
  50. package/dist/lib/server/event/index.js +2 -0
  51. package/dist/lib/server/event/index.js.map +1 -1
  52. package/dist/lib/server/event/types.d.ts +12 -0
  53. package/dist/lib/server/health/HealthServer.d.ts +26 -0
  54. package/dist/lib/server/health/HealthServer.js +63 -0
  55. package/dist/lib/server/health/HealthServer.js.map +1 -0
  56. package/dist/lib/server/health/index.d.ts +1 -0
  57. package/dist/lib/server/health/index.js +2 -0
  58. package/dist/lib/server/health/index.js.map +1 -0
  59. package/dist/lib/server/messaging/Ulak.d.ts +156 -0
  60. package/dist/lib/server/messaging/Ulak.js +174 -0
  61. package/dist/lib/server/messaging/Ulak.js.map +1 -1
  62. package/dist/lib/server/messaging/types.d.ts +5 -1
  63. package/dist/lib/server/messaging/types.js +5 -0
  64. package/dist/lib/server/messaging/types.js.map +1 -1
  65. package/dist/lib/server/microservice/InMemoryTransport.d.ts +45 -0
  66. package/dist/lib/server/microservice/InMemoryTransport.js +124 -0
  67. package/dist/lib/server/microservice/InMemoryTransport.js.map +1 -0
  68. package/dist/lib/server/microservice/MicroserviceTransport.d.ts +132 -0
  69. package/dist/lib/server/microservice/MicroserviceTransport.js +2 -0
  70. package/dist/lib/server/microservice/MicroserviceTransport.js.map +1 -0
  71. package/dist/lib/server/microservice/decorators/EventPattern.d.ts +38 -0
  72. package/dist/lib/server/microservice/decorators/EventPattern.js +59 -0
  73. package/dist/lib/server/microservice/decorators/EventPattern.js.map +1 -0
  74. package/dist/lib/server/microservice/decorators/MessagePattern.d.ts +31 -0
  75. package/dist/lib/server/microservice/decorators/MessagePattern.js +55 -0
  76. package/dist/lib/server/microservice/decorators/MessagePattern.js.map +1 -0
  77. package/dist/lib/server/microservice/decorators/index.d.ts +2 -0
  78. package/dist/lib/server/microservice/decorators/index.js +3 -0
  79. package/dist/lib/server/microservice/decorators/index.js.map +1 -0
  80. package/dist/lib/server/microservice/index.d.ts +5 -0
  81. package/dist/lib/server/microservice/index.js +11 -0
  82. package/dist/lib/server/microservice/index.js.map +1 -0
  83. package/dist/lib/server/microservice/interceptorChain.d.ts +20 -0
  84. package/dist/lib/server/microservice/interceptorChain.js +39 -0
  85. package/dist/lib/server/microservice/interceptorChain.js.map +1 -0
  86. package/dist/lib/server/microservice/types.d.ts +142 -0
  87. package/dist/lib/server/microservice/types.js +5 -0
  88. package/dist/lib/server/microservice/types.js.map +1 -0
  89. package/dist/lib/server/src/services/PrepareEventService.d.ts +4 -1
  90. package/dist/lib/server/src/services/PrepareEventService.js +10 -3
  91. package/dist/lib/server/src/services/PrepareEventService.js.map +1 -1
  92. package/dist/lib/server/src/services/PrepareMicroserviceService.d.ts +66 -0
  93. package/dist/lib/server/src/services/PrepareMicroserviceService.js +193 -0
  94. package/dist/lib/server/src/services/PrepareMicroserviceService.js.map +1 -0
  95. package/dist/lib/test/factory/deepMock.d.ts +25 -0
  96. package/dist/lib/test/factory/deepMock.js +105 -0
  97. package/dist/lib/test/factory/deepMock.js.map +1 -0
  98. package/dist/lib/test/factory/ulakStub.d.ts +44 -0
  99. package/dist/lib/test/factory/ulakStub.js +40 -0
  100. package/dist/lib/test/factory/ulakStub.js.map +1 -0
  101. package/dist/lib/test/harness/createTestApp.d.ts +33 -0
  102. package/dist/lib/test/harness/createTestApp.js +105 -0
  103. package/dist/lib/test/harness/createTestApp.js.map +1 -0
  104. package/dist/lib/test/harness/createWebTest.d.ts +28 -0
  105. package/dist/lib/test/harness/createWebTest.js +127 -0
  106. package/dist/lib/test/harness/createWebTest.js.map +1 -0
  107. package/dist/lib/test/harness/silentLogger.d.ts +27 -0
  108. package/dist/lib/test/harness/silentLogger.js +54 -0
  109. package/dist/lib/test/harness/silentLogger.js.map +1 -0
  110. package/dist/lib/test/harness/types.d.ts +147 -0
  111. package/dist/lib/test/harness/types.js +2 -0
  112. package/dist/lib/test/harness/types.js.map +1 -0
  113. package/dist/lib/test/http/TestHttpCall.d.ts +78 -0
  114. package/dist/lib/test/http/TestHttpCall.js +149 -0
  115. package/dist/lib/test/http/TestHttpCall.js.map +1 -0
  116. package/dist/lib/test/http/TestHttpResponse.d.ts +46 -0
  117. package/dist/lib/test/http/TestHttpResponse.js +70 -0
  118. package/dist/lib/test/http/TestHttpResponse.js.map +1 -0
  119. package/dist/lib/test/index.d.ts +9 -0
  120. package/dist/lib/test/index.js +8 -0
  121. package/dist/lib/test/index.js.map +1 -1
  122. package/dist/lib/test/metadata/discovery.d.ts +21 -0
  123. package/dist/lib/test/metadata/discovery.js +37 -8
  124. package/dist/lib/test/metadata/discovery.js.map +1 -1
  125. package/dist/lib/test/mockComponent.d.ts +25 -0
  126. package/dist/lib/test/mockComponent.js +39 -6
  127. package/dist/lib/test/mockComponent.js.map +1 -1
  128. package/dist/lib/test/types.d.ts +13 -0
  129. package/package.json +11 -7
@@ -1,2 +1,40 @@
1
- export {};
1
+ import { DEFAULT_TRANSPORT_NAME } from '../microservice/types';
2
+ /**
3
+ * Normalize the transport() hook result into a single shape.
4
+ *
5
+ * - A bare WebSocketTransport (has a publish function) is the legacy form → { websocket }
6
+ * - An object form is discriminated per field; a single MicroserviceTransport
7
+ * (has a send function) becomes the 'default' named transport
8
+ * - An object with none of the known fields throws (catches accidentally
9
+ * returning a bare MicroserviceTransport, which would otherwise be a silent no-op)
10
+ *
11
+ * CAVEAT: the legacy detection is duck-typed on `publish`. A custom
12
+ * MicroserviceTransport that also defines a `publish` method would be
13
+ * mistaken for a bare WebSocketTransport when returned bare - such
14
+ * transports must use the explicit `{ microservice: ... }` object form.
15
+ */
16
+ export async function normalizeTransportConfig(result) {
17
+ // Legacy form: bare WebSocketTransport (publish is its only required member)
18
+ if (typeof result.publish === 'function') {
19
+ return { websocket: result, microservices: new Map(), interceptors: [] };
20
+ }
21
+ const config = result;
22
+ if (config.websocket === undefined && config.microservice === undefined && config.interceptors === undefined) {
23
+ throw new Error('transport() returned an object without websocket/microservice/interceptors fields - return a WebSocketTransport or an AsenaTransportConfig object');
24
+ }
25
+ const websocket = config.websocket ? await config.websocket : undefined;
26
+ const microservices = new Map();
27
+ if (config.microservice) {
28
+ const resolved = await config.microservice;
29
+ if (typeof resolved.send === 'function') {
30
+ microservices.set(DEFAULT_TRANSPORT_NAME, resolved);
31
+ }
32
+ else {
33
+ for (const [name, transport] of Object.entries(resolved)) {
34
+ microservices.set(name, transport);
35
+ }
36
+ }
37
+ }
38
+ return { websocket, microservices, interceptors: config.interceptors || [] };
39
+ }
2
40
  //# sourceMappingURL=AsenaConfig.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"AsenaConfig.js","sourceRoot":"","sources":["../../../../lib/server/config/AsenaConfig.ts"],"names":[],"mappings":""}
1
+ {"version":3,"file":"AsenaConfig.js","sourceRoot":"","sources":["../../../../lib/server/config/AsenaConfig.ts"],"names":[],"mappings":"AAMA,OAAO,EAAE,sBAAsB,EAAE,MAAM,uBAAuB,CAAC;AA2C/D;;;;;;;;;;;;;GAaG;AACH,MAAM,CAAC,KAAK,UAAU,wBAAwB,CAC5C,MAAiD;IAEjD,6EAA6E;IAC7E,IAAI,OAAQ,MAA6B,CAAC,OAAO,KAAK,UAAU,EAAE,CAAC;QACjE,OAAO,EAAE,SAAS,EAAE,MAA4B,EAAE,aAAa,EAAE,IAAI,GAAG,EAAE,EAAE,YAAY,EAAE,EAAE,EAAE,CAAC;IACjG,CAAC;IAED,MAAM,MAAM,GAAG,MAA8B,CAAC;IAE9C,IAAI,MAAM,CAAC,SAAS,KAAK,SAAS,IAAI,MAAM,CAAC,YAAY,KAAK,SAAS,IAAI,MAAM,CAAC,YAAY,KAAK,SAAS,EAAE,CAAC;QAC7G,MAAM,IAAI,KAAK,CACb,mJAAmJ,CACpJ,CAAC;IACJ,CAAC;IAED,MAAM,SAAS,GAAG,MAAM,CAAC,SAAS,CAAC,CAAC,CAAC,MAAM,MAAM,CAAC,SAAS,CAAC,CAAC,CAAC,SAAS,CAAC;IAExE,MAAM,aAAa,GAAG,IAAI,GAAG,EAAiC,CAAC;IAE/D,IAAI,MAAM,CAAC,YAAY,EAAE,CAAC;QACxB,MAAM,QAAQ,GAAG,MAAM,MAAM,CAAC,YAAY,CAAC;QAE3C,IAAI,OAAQ,QAAkC,CAAC,IAAI,KAAK,UAAU,EAAE,CAAC;YACnE,aAAa,CAAC,GAAG,CAAC,sBAAsB,EAAE,QAAiC,CAAC,CAAC;QAC/E,CAAC;aAAM,CAAC;YACN,KAAK,MAAM,CAAC,IAAI,EAAE,SAAS,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,QAAiD,CAAC,EAAE,CAAC;gBAClG,aAAa,CAAC,GAAG,CAAC,IAAI,EAAE,SAAS,CAAC,CAAC;YACrC,CAAC;QACH,CAAC;IACH,CAAC;IAED,OAAO,EAAE,SAAS,EAAE,aAAa,EAAE,YAAY,EAAE,MAAM,CAAC,YAAY,IAAI,EAAE,EAAE,CAAC;AAC/E,CAAC"}
@@ -0,0 +1,49 @@
1
+ import type { MessageControllerParams } from '../../microservice';
2
+ /**
3
+ * @description MessageController decorator - Marks a class as a microservice message controller
4
+ *
5
+ * Message controllers contain @MessagePattern (request/response) and
6
+ * @EventPattern (fire-and-forget) decorated methods. They are registered into the
7
+ * microservice transport configured via the @Config transport() hook.
8
+ *
9
+ * The prefix is joined (with a dot) onto every @MessagePattern AND @EventPattern
10
+ * in the class. A single handler opts out with `prefix: false`.
11
+ *
12
+ * @param params - Optional configuration or prefix string
13
+ *
14
+ * @example
15
+ * // With prefix
16
+ * @MessageController('order')
17
+ * export class OrderHandler {
18
+ * @MessagePattern('create') // Handles 'order.create'
19
+ * async create(data: CreateOrderDto, context: MessageContext) {
20
+ * return this.orderService.create(data);
21
+ * }
22
+ *
23
+ * @EventPattern('created') // Handles 'order.created'
24
+ * async onCreated(event: OrderEvent) { }
25
+ *
26
+ * // Absolute - another service's event vocabulary
27
+ * @EventPattern({ pattern: 'payment.completed', prefix: false })
28
+ * async onPaymentCompleted(event: PaymentEvent) { }
29
+ * }
30
+ *
31
+ * @example
32
+ * // Without prefix
33
+ * @MessageController()
34
+ * export class GlobalHandler {
35
+ * @MessagePattern('ping') // Handles 'ping'
36
+ * async ping() {
37
+ * return 'pong';
38
+ * }
39
+ * }
40
+ *
41
+ * @example
42
+ * // Bound to a named transport (multi-broker projects)
43
+ * @MessageController({ prefix: 'metrics', transport: 'analytics' })
44
+ * export class AnalyticsHandler {
45
+ * @EventPattern('page.viewed') // Handles 'metrics.page.viewed'
46
+ * async onPageViewed(event: PageViewedEvent) { }
47
+ * }
48
+ */
49
+ export declare const MessageController: (params?: MessageControllerParams | string) => ClassDecorator;
@@ -0,0 +1,62 @@
1
+ import { ComponentConstants, ComponentType } from '../../../ioc';
2
+ import { defineComponent } from '../../../ioc/component';
3
+ import { defineTypedMetadata } from '../../../utils';
4
+ import { DEFAULT_TRANSPORT_NAME } from '../../microservice';
5
+ /**
6
+ * @description MessageController decorator - Marks a class as a microservice message controller
7
+ *
8
+ * Message controllers contain @MessagePattern (request/response) and
9
+ * @EventPattern (fire-and-forget) decorated methods. They are registered into the
10
+ * microservice transport configured via the @Config transport() hook.
11
+ *
12
+ * The prefix is joined (with a dot) onto every @MessagePattern AND @EventPattern
13
+ * in the class. A single handler opts out with `prefix: false`.
14
+ *
15
+ * @param params - Optional configuration or prefix string
16
+ *
17
+ * @example
18
+ * // With prefix
19
+ * @MessageController('order')
20
+ * export class OrderHandler {
21
+ * @MessagePattern('create') // Handles 'order.create'
22
+ * async create(data: CreateOrderDto, context: MessageContext) {
23
+ * return this.orderService.create(data);
24
+ * }
25
+ *
26
+ * @EventPattern('created') // Handles 'order.created'
27
+ * async onCreated(event: OrderEvent) { }
28
+ *
29
+ * // Absolute - another service's event vocabulary
30
+ * @EventPattern({ pattern: 'payment.completed', prefix: false })
31
+ * async onPaymentCompleted(event: PaymentEvent) { }
32
+ * }
33
+ *
34
+ * @example
35
+ * // Without prefix
36
+ * @MessageController()
37
+ * export class GlobalHandler {
38
+ * @MessagePattern('ping') // Handles 'ping'
39
+ * async ping() {
40
+ * return 'pong';
41
+ * }
42
+ * }
43
+ *
44
+ * @example
45
+ * // Bound to a named transport (multi-broker projects)
46
+ * @MessageController({ prefix: 'metrics', transport: 'analytics' })
47
+ * export class AnalyticsHandler {
48
+ * @EventPattern('page.viewed') // Handles 'metrics.page.viewed'
49
+ * async onPageViewed(event: PageViewedEvent) { }
50
+ * }
51
+ */
52
+ export const MessageController = (params) => {
53
+ // Normalize params BEFORE defineComponent - a bare string must become a prefix,
54
+ // otherwise paramsGenerator would treat it as the component name
55
+ const _params = typeof params === 'string' ? { prefix: params, name: undefined } : params || { prefix: undefined, name: undefined };
56
+ return defineComponent(ComponentType.MESSAGE_CONTROLLER, _params, (target) => {
57
+ // Store prefix + transport binding metadata for PrepareMicroserviceService
58
+ defineTypedMetadata(ComponentConstants.MessagePrefixKey, _params.prefix || '', target);
59
+ defineTypedMetadata(ComponentConstants.MessageTransportKey, _params.transport || DEFAULT_TRANSPORT_NAME, target);
60
+ });
61
+ };
62
+ //# sourceMappingURL=MessageController.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"MessageController.js","sourceRoot":"","sources":["../../../../../lib/server/decorators/components/MessageController.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,kBAAkB,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC;AACjE,OAAO,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAC;AACzD,OAAO,EAAE,mBAAmB,EAAE,MAAM,gBAAgB,CAAC;AACrD,OAAO,EAAE,sBAAsB,EAAE,MAAM,oBAAoB,CAAC;AAG5D;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8CG;AACH,MAAM,CAAC,MAAM,iBAAiB,GAAG,CAAC,MAAyC,EAAkB,EAAE;IAC7F,gFAAgF;IAChF,iEAAiE;IACjE,MAAM,OAAO,GACX,OAAO,MAAM,KAAK,QAAQ,CAAC,CAAC,CAAC,EAAE,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,SAAS,EAAE,CAAC,CAAC,CAAC,MAAM,IAAI,EAAE,MAAM,EAAE,SAAS,EAAE,IAAI,EAAE,SAAS,EAAE,CAAC;IAEtH,OAAO,eAAe,CAAC,aAAa,CAAC,kBAAkB,EAAE,OAAO,EAAE,CAAC,MAAM,EAAE,EAAE;QAC3E,2EAA2E;QAC3E,mBAAmB,CAAS,kBAAkB,CAAC,gBAAgB,EAAE,OAAO,CAAC,MAAM,IAAI,EAAE,EAAE,MAAM,CAAC,CAAC;QAE/F,mBAAmB,CACjB,kBAAkB,CAAC,mBAAmB,EACtC,OAAO,CAAC,SAAS,IAAI,sBAAsB,EAC3C,MAAM,CACP,CAAC;IACJ,CAAC,CAAC,CAAC;AACL,CAAC,CAAC"}
@@ -8,3 +8,4 @@ export * from './WebSocket';
8
8
  export * from './StaticServe';
9
9
  export * from './EventService';
10
10
  export * from './FrontendController';
11
+ export * from './MessageController';
@@ -8,4 +8,5 @@ export * from './WebSocket';
8
8
  export * from './StaticServe';
9
9
  export * from './EventService';
10
10
  export * from './FrontendController';
11
+ export * from './MessageController';
11
12
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../../lib/server/decorators/components/index.ts"],"names":[],"mappings":"AAAA,cAAc,6CAA6C,CAAC;AAC5D,cAAc,cAAc,CAAC;AAC7B,cAAc,cAAc,CAAC;AAC7B,cAAc,iBAAiB,CAAC;AAChC,cAAc,YAAY,CAAC;AAC3B,cAAc,WAAW,CAAC;AAC1B,cAAc,aAAa,CAAC;AAC5B,cAAc,eAAe,CAAC;AAC9B,cAAc,gBAAgB,CAAC;AAC/B,cAAc,sBAAsB,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../../lib/server/decorators/components/index.ts"],"names":[],"mappings":"AAAA,cAAc,6CAA6C,CAAC;AAC5D,cAAc,cAAc,CAAC;AAC7B,cAAc,cAAc,CAAC;AAC7B,cAAc,iBAAiB,CAAC;AAChC,cAAc,YAAY,CAAC;AAC3B,cAAc,WAAW,CAAC;AAC1B,cAAc,aAAa,CAAC;AAC5B,cAAc,eAAe,CAAC;AAC9B,cAAc,gBAAgB,CAAC;AAC/B,cAAc,sBAAsB,CAAC;AACrC,cAAc,qBAAqB,CAAC"}
@@ -26,14 +26,10 @@ export declare class EventDispatchService implements ICoreService {
26
26
  */
27
27
  private warmedUp;
28
28
  /**
29
- * Exact pattern cache for O(1) lookup
30
- * Key: exact event pattern, Value: handlers for that pattern
29
+ * Hybrid lookup index (exact Map + wildcard array), shared implementation
30
+ * with the microservice transports
31
31
  */
32
- private exactMatches;
33
- /**
34
- * Wildcard patterns that need O(n) matching
35
- */
36
- private wildcardPatterns;
32
+ private index;
37
33
  /**
38
34
  * Register a handler for an event pattern
39
35
  *
@@ -6,7 +6,7 @@ var __decorate = (this && this.__decorate) || function (decorators, target, key,
6
6
  };
7
7
  import { CoreService } from '../../ioc';
8
8
  import { ICoreServiceNames } from '../../ioc';
9
- import { matchesEventPattern } from './eventPatternMatcher';
9
+ import { PatternHandlerIndex } from './PatternHandlerIndex';
10
10
  /**
11
11
  * @description Internal event dispatch service
12
12
  * Handles pattern matching, storage, and dispatching of events
@@ -33,14 +33,10 @@ let EventDispatchService = class EventDispatchService {
33
33
  */
34
34
  warmedUp = false;
35
35
  /**
36
- * Exact pattern cache for O(1) lookup
37
- * Key: exact event pattern, Value: handlers for that pattern
36
+ * Hybrid lookup index (exact Map + wildcard array), shared implementation
37
+ * with the microservice transports
38
38
  */
39
- exactMatches = new Map();
40
- /**
41
- * Wildcard patterns that need O(n) matching
42
- */
43
- wildcardPatterns = [];
39
+ index = new PatternHandlerIndex();
44
40
  /**
45
41
  * Register a handler for an event pattern
46
42
  *
@@ -94,24 +90,8 @@ let EventDispatchService = class EventDispatchService {
94
90
  if (!this.warmedUp) {
95
91
  this.warmup();
96
92
  }
97
- const handlersToCall = [];
98
- // 1. Check exact match cache - O(1)
99
- const exactHandlers = this.exactMatches.get(eventName);
100
- if (exactHandlers) {
101
- for (const handler of exactHandlers) {
102
- // Find full subscription info (for 'once' support)
103
- const sub = this.handlers.find((s) => s.handler === handler && s.pattern === eventName);
104
- if (sub) {
105
- handlersToCall.push(sub);
106
- }
107
- }
108
- }
109
- // 2. Check wildcard patterns - O(n) but smaller n
110
- for (const sub of this.wildcardPatterns) {
111
- if (matchesEventPattern(eventName, sub.pattern)) {
112
- handlersToCall.push(sub);
113
- }
114
- }
93
+ // 1-2. Collect matching subscriptions: exact matches O(1), then wildcards O(n)
94
+ const handlersToCall = this.index.collect(eventName);
115
95
  // 3. No handlers matched
116
96
  if (handlersToCall.length === 0) {
117
97
  return false;
@@ -159,19 +139,9 @@ let EventDispatchService = class EventDispatchService {
159
139
  * @private
160
140
  */
161
141
  warmup() {
162
- this.exactMatches.clear();
163
- this.wildcardPatterns = [];
142
+ this.index.clear();
164
143
  for (const sub of this.handlers) {
165
- if (sub.pattern.includes('*')) {
166
- // Wildcard pattern - needs O(n) matching on dispatch
167
- this.wildcardPatterns.push(sub);
168
- }
169
- else {
170
- // Exact pattern - O(1) lookup on dispatch
171
- const handlers = this.exactMatches.get(sub.pattern) || [];
172
- handlers.push(sub.handler);
173
- this.exactMatches.set(sub.pattern, handlers);
174
- }
144
+ this.index.add(sub.pattern, sub);
175
145
  }
176
146
  this.warmedUp = true;
177
147
  }
@@ -191,8 +161,7 @@ let EventDispatchService = class EventDispatchService {
191
161
  */
192
162
  clearHandlers() {
193
163
  this.handlers = [];
194
- this.exactMatches.clear();
195
- this.wildcardPatterns = [];
164
+ this.index.clear();
196
165
  this.warmedUp = false;
197
166
  }
198
167
  };
@@ -1 +1 @@
1
- {"version":3,"file":"EventDispatchService.js","sourceRoot":"","sources":["../../../../lib/server/event/EventDispatchService.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"EventDispatchService.js","sourceRoot":"","sources":["../../../../lib/server/event/EventDispatchService.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,53 @@
1
+ /**
2
+ * @description Shared pattern → handler index with the hybrid lookup strategy
3
+ * used across Asena's event and messaging systems:
4
+ *
5
+ * - Exact patterns → Map (O(1) lookup on collect)
6
+ * - Wildcard patterns → Array (O(n) matchesEventPattern check, smaller n)
7
+ *
8
+ * Consumers: EventDispatchService (in-process events), InMemoryTransport and
9
+ * RedisMicroserviceTransport (microservice event handlers). The generic type T
10
+ * lets each consumer store what it needs (a bare handler or a subscription object).
11
+ *
12
+ * Collection order: exact matches first (registration order), then wildcard
13
+ * matches (registration order).
14
+ */
15
+ export declare class PatternHandlerIndex<T> {
16
+ /**
17
+ * Exact pattern → entries (O(1) fast path)
18
+ */
19
+ private exact;
20
+ /**
21
+ * Wildcard patterns, matched with matchesEventPattern on collect
22
+ */
23
+ private wildcard;
24
+ /**
25
+ * Register an entry under a pattern
26
+ */
27
+ add(pattern: string, entry: T): void;
28
+ /**
29
+ * Remove a specific entry registered under a pattern (identity comparison)
30
+ *
31
+ * @returns true if the entry was found and removed
32
+ */
33
+ remove(pattern: string, entry: T): boolean;
34
+ /**
35
+ * Collect all entries whose pattern matches the given event name
36
+ */
37
+ collect(eventName: string): T[];
38
+ /**
39
+ * All registered patterns - exact first (registration order), then wildcard
40
+ *
41
+ * Diagnostics only: consumers use it to explain why an expected source
42
+ * matched no handler (e.g. the Kafka transport's external-topic hint).
43
+ */
44
+ patterns(): string[];
45
+ /**
46
+ * Whether the index holds no entries at all
47
+ */
48
+ get isEmpty(): boolean;
49
+ /**
50
+ * Remove all entries
51
+ */
52
+ clear(): void;
53
+ }
@@ -0,0 +1,100 @@
1
+ import { matchesEventPattern } from './eventPatternMatcher';
2
+ /**
3
+ * @description Shared pattern → handler index with the hybrid lookup strategy
4
+ * used across Asena's event and messaging systems:
5
+ *
6
+ * - Exact patterns → Map (O(1) lookup on collect)
7
+ * - Wildcard patterns → Array (O(n) matchesEventPattern check, smaller n)
8
+ *
9
+ * Consumers: EventDispatchService (in-process events), InMemoryTransport and
10
+ * RedisMicroserviceTransport (microservice event handlers). The generic type T
11
+ * lets each consumer store what it needs (a bare handler or a subscription object).
12
+ *
13
+ * Collection order: exact matches first (registration order), then wildcard
14
+ * matches (registration order).
15
+ */
16
+ export class PatternHandlerIndex {
17
+ /**
18
+ * Exact pattern → entries (O(1) fast path)
19
+ */
20
+ exact = new Map();
21
+ /**
22
+ * Wildcard patterns, matched with matchesEventPattern on collect
23
+ */
24
+ wildcard = [];
25
+ /**
26
+ * Register an entry under a pattern
27
+ */
28
+ add(pattern, entry) {
29
+ if (pattern.includes('*')) {
30
+ this.wildcard.push({ pattern, entry });
31
+ return;
32
+ }
33
+ const entries = this.exact.get(pattern) || [];
34
+ entries.push(entry);
35
+ this.exact.set(pattern, entries);
36
+ }
37
+ /**
38
+ * Remove a specific entry registered under a pattern (identity comparison)
39
+ *
40
+ * @returns true if the entry was found and removed
41
+ */
42
+ remove(pattern, entry) {
43
+ if (pattern.includes('*')) {
44
+ const index = this.wildcard.findIndex((item) => item.pattern === pattern && item.entry === entry);
45
+ if (index !== -1) {
46
+ this.wildcard.splice(index, 1);
47
+ return true;
48
+ }
49
+ return false;
50
+ }
51
+ const entries = this.exact.get(pattern);
52
+ if (!entries) {
53
+ return false;
54
+ }
55
+ const index = entries.indexOf(entry);
56
+ if (index === -1) {
57
+ return false;
58
+ }
59
+ entries.splice(index, 1);
60
+ if (!entries.length) {
61
+ this.exact.delete(pattern);
62
+ }
63
+ return true;
64
+ }
65
+ /**
66
+ * Collect all entries whose pattern matches the given event name
67
+ */
68
+ collect(eventName) {
69
+ const result = [...(this.exact.get(eventName) || [])];
70
+ for (const item of this.wildcard) {
71
+ if (matchesEventPattern(eventName, item.pattern)) {
72
+ result.push(item.entry);
73
+ }
74
+ }
75
+ return result;
76
+ }
77
+ /**
78
+ * All registered patterns - exact first (registration order), then wildcard
79
+ *
80
+ * Diagnostics only: consumers use it to explain why an expected source
81
+ * matched no handler (e.g. the Kafka transport's external-topic hint).
82
+ */
83
+ patterns() {
84
+ return [...this.exact.keys(), ...this.wildcard.map((item) => item.pattern)];
85
+ }
86
+ /**
87
+ * Whether the index holds no entries at all
88
+ */
89
+ get isEmpty() {
90
+ return this.exact.size === 0 && this.wildcard.length === 0;
91
+ }
92
+ /**
93
+ * Remove all entries
94
+ */
95
+ clear() {
96
+ this.exact.clear();
97
+ this.wildcard = [];
98
+ }
99
+ }
100
+ //# sourceMappingURL=PatternHandlerIndex.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"PatternHandlerIndex.js","sourceRoot":"","sources":["../../../../lib/server/event/PatternHandlerIndex.ts"],"names":[],"mappings":"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"}
@@ -20,6 +20,10 @@ import type { OnParams } from '../types';
20
20
  *
21
21
  * @On({ event: 'deleted', skip: true }) // Temporarily disabled
22
22
  * handleDeleted(eventName: string, data: any) { }
23
+ *
24
+ * // Absolute - opts out of the 'user' prefix
25
+ * @On({ event: 'payment.completed', prefix: false })
26
+ * handlePayment(eventName: string, data: any) { }
23
27
  * }
24
28
  *
25
29
  * @example
@@ -21,6 +21,10 @@ import { defineTypedMetadata, getOwnTypedMetadata } from '../../../utils';
21
21
  *
22
22
  * @On({ event: 'deleted', skip: true }) // Temporarily disabled
23
23
  * handleDeleted(eventName: string, data: any) { }
24
+ *
25
+ * // Absolute - opts out of the 'user' prefix
26
+ * @On({ event: 'payment.completed', prefix: false })
27
+ * handlePayment(eventName: string, data: any) { }
24
28
  * }
25
29
  *
26
30
  * @example
@@ -46,6 +50,8 @@ export function On(params) {
46
50
  handlers[propertyKey.toString()] = {
47
51
  pattern: _params.event,
48
52
  methodName: propertyKey.toString(),
53
+ // `!== false` covers the string shorthand and objects that omit the flag
54
+ prefix: _params.prefix !== false,
49
55
  skip: _params.skip || false,
50
56
  };
51
57
  // Store updated metadata
@@ -1 +1 @@
1
- {"version":3,"file":"On.js","sourceRoot":"","sources":["../../../../../lib/server/event/decorators/On.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,EAAE,CAAC,MAAyB;IAC1C,oDAAoD;IACpD,MAAM,OAAO,GAAG,OAAO,MAAM,KAAK,QAAQ,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC,CAAC,CAAC,MAAM,CAAC;IAErF,OAAO,UAAU,MAAc,EAAE,WAA4B,EAAE,UAA8B;QAC3F,qDAAqD;QACrD,MAAM,QAAQ,GACZ,mBAAmB,CACjB,kBAAkB,CAAC,gBAAgB,EACnC,MAAM,CAAC,WAAW,CACnB,IAAI,EAAE,CAAC;QAEV,8BAA8B;QAC9B,QAAQ,CAAC,WAAW,CAAC,QAAQ,EAAE,CAAC,GAAG;YACjC,OAAO,EAAE,OAAO,CAAC,KAAK;YACtB,UAAU,EAAE,WAAW,CAAC,QAAQ,EAAE;YAClC,IAAI,EAAE,OAAO,CAAC,IAAI,IAAI,KAAK;SAC5B,CAAC;QAEF,yBAAyB;QACzB,mBAAmB,CAAC,kBAAkB,CAAC,gBAAgB,EAAE,QAAQ,EAAE,MAAM,CAAC,WAAW,CAAC,CAAC;QAEvF,OAAO,UAAU,CAAC;IACpB,CAAC,CAAC;AACJ,CAAC"}
1
+ {"version":3,"file":"On.js","sourceRoot":"","sources":["../../../../../lib/server/event/decorators/On.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,kBAAkB,EAAE,MAAM,cAAc,CAAC;AAClD,OAAO,EAAE,mBAAmB,EAAE,mBAAmB,EAAE,MAAM,gBAAgB,CAAC;AAG1E;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAuCG;AACH,MAAM,UAAU,EAAE,CAAC,MAAyB;IAC1C,oDAAoD;IACpD,MAAM,OAAO,GAAG,OAAO,MAAM,KAAK,QAAQ,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC,CAAC,CAAC,MAAM,CAAC;IAErF,OAAO,UAAU,MAAc,EAAE,WAA4B,EAAE,UAA8B;QAC3F,qDAAqD;QACrD,MAAM,QAAQ,GACZ,mBAAmB,CACjB,kBAAkB,CAAC,gBAAgB,EACnC,MAAM,CAAC,WAAW,CACnB,IAAI,EAAE,CAAC;QAEV,8BAA8B;QAC9B,QAAQ,CAAC,WAAW,CAAC,QAAQ,EAAE,CAAC,GAAG;YACjC,OAAO,EAAE,OAAO,CAAC,KAAK;YACtB,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,gBAAgB,EAAE,QAAQ,EAAE,MAAM,CAAC,WAAW,CAAC,CAAC;QAEvF,OAAO,UAAU,CAAC;IACpB,CAAC,CAAC;AACJ,CAAC"}
@@ -1,6 +1,7 @@
1
1
  export { EventEmitter } from './EventEmitter';
2
2
  export { EventDispatchService } from './EventDispatchService';
3
3
  export { matchesEventPattern } from './eventPatternMatcher';
4
+ export { PatternHandlerIndex } from './PatternHandlerIndex';
4
5
  export { emitter } from './emitter';
5
6
  export * from './types';
6
7
  export * from './decorators';
@@ -3,6 +3,8 @@ export { EventEmitter } from './EventEmitter';
3
3
  export { EventDispatchService } from './EventDispatchService';
4
4
  // Pattern matcher (utility)
5
5
  export { matchesEventPattern } from './eventPatternMatcher';
6
+ // Shared pattern → handler index (hybrid exact/wildcard lookup)
7
+ export { PatternHandlerIndex } from './PatternHandlerIndex';
6
8
  // Injection utility
7
9
  export { emitter } from './emitter';
8
10
  // Types
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../lib/server/event/index.ts"],"names":[],"mappings":"AAAA,oBAAoB;AACpB,OAAO,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAC9C,OAAO,EAAE,oBAAoB,EAAE,MAAM,wBAAwB,CAAC;AAE9D,4BAA4B;AAC5B,OAAO,EAAE,mBAAmB,EAAE,MAAM,uBAAuB,CAAC;AAE5D,oBAAoB;AACpB,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAEpC,QAAQ;AACR,cAAc,SAAS,CAAC;AAExB,aAAa;AACb,cAAc,cAAc,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../lib/server/event/index.ts"],"names":[],"mappings":"AAAA,oBAAoB;AACpB,OAAO,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAC9C,OAAO,EAAE,oBAAoB,EAAE,MAAM,wBAAwB,CAAC;AAE9D,4BAA4B;AAC5B,OAAO,EAAE,mBAAmB,EAAE,MAAM,uBAAuB,CAAC;AAE5D,gEAAgE;AAChE,OAAO,EAAE,mBAAmB,EAAE,MAAM,uBAAuB,CAAC;AAE5D,oBAAoB;AACpB,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAEpC,QAAQ;AACR,cAAc,SAAS,CAAC;AAExB,aAAa;AACb,cAAc,cAAc,CAAC"}
@@ -21,6 +21,13 @@ export interface OnParams {
21
21
  * @example 'download.complete' or 'download.*'
22
22
  */
23
23
  event: string;
24
+ /**
25
+ * Join the @EventService prefix onto `event`.
26
+ * Set false to listen on an absolute pattern — another domain's event
27
+ * vocabulary, or a global catch-all ('*').
28
+ * @default true
29
+ */
30
+ prefix?: boolean;
24
31
  /**
25
32
  * Skip this handler (useful for temporarily disabling handlers)
26
33
  * @default false
@@ -40,6 +47,11 @@ export interface EventHandlerMetadata {
40
47
  * Method name to call when event is emitted
41
48
  */
42
49
  methodName: string;
50
+ /**
51
+ * Whether the @EventService prefix is joined onto `pattern`.
52
+ * Normalized at decoration time (`prefix: false` opt-out → false).
53
+ */
54
+ prefix: boolean;
43
55
  /**
44
56
  * Whether this handler should be skipped
45
57
  */
@@ -0,0 +1,26 @@
1
+ import { type ServerLogger } from '../../logger';
2
+ import type { HealthOptions } from '../AsenaServerFactory';
3
+ import type { Ulak } from '../messaging/Ulak';
4
+ /**
5
+ * @description Minimal zero-dependency health endpoint for headless/hybrid deployments.
6
+ *
7
+ * Serves a single endpoint (default GET /healthz) reporting process liveness and
8
+ * per-microservice-transport connection state - built for Kubernetes probes on
9
+ * headless services that have no HTTP adapter.
10
+ *
11
+ * Responses:
12
+ * - No microservice transports configured → 200 { status: 'up', uptime }
13
+ * - All transports connected → 200 { status: 'up', uptime, transports: { name: 'connected' } }
14
+ * - Any transport disconnected → 503 { status: 'degraded', ... }
15
+ */
16
+ export declare class HealthServer {
17
+ private readonly options;
18
+ private readonly ulak;
19
+ private readonly logger;
20
+ private server?;
21
+ private startedAt;
22
+ constructor(options: HealthOptions, ulak: Ulak, logger: ServerLogger);
23
+ start(): void;
24
+ stop(): void;
25
+ private buildHealthResponse;
26
+ }
@@ -0,0 +1,63 @@
1
+ import * as bun from 'bun';
2
+ import { blue } from '../../logger';
3
+ /**
4
+ * @description Minimal zero-dependency health endpoint for headless/hybrid deployments.
5
+ *
6
+ * Serves a single endpoint (default GET /healthz) reporting process liveness and
7
+ * per-microservice-transport connection state - built for Kubernetes probes on
8
+ * headless services that have no HTTP adapter.
9
+ *
10
+ * Responses:
11
+ * - No microservice transports configured → 200 { status: 'up', uptime }
12
+ * - All transports connected → 200 { status: 'up', uptime, transports: { name: 'connected' } }
13
+ * - Any transport disconnected → 503 { status: 'degraded', ... }
14
+ */
15
+ export class HealthServer {
16
+ options;
17
+ ulak;
18
+ logger;
19
+ server;
20
+ startedAt = 0;
21
+ constructor(options, ulak, logger) {
22
+ this.options = options;
23
+ this.ulak = ulak;
24
+ this.logger = logger;
25
+ }
26
+ start() {
27
+ const path = this.options.path || '/healthz';
28
+ this.startedAt = Date.now();
29
+ this.server = bun.serve({
30
+ port: this.options.port,
31
+ fetch: (request) => {
32
+ const url = new URL(request.url);
33
+ if (url.pathname !== path) {
34
+ return new Response('Not Found', { status: 404 });
35
+ }
36
+ return this.buildHealthResponse();
37
+ },
38
+ });
39
+ this.logger.info(`${blue('[Health]')} Health endpoint ready at :${this.options.port}${path}`);
40
+ }
41
+ stop() {
42
+ void this.server?.stop(true);
43
+ this.server = undefined;
44
+ }
45
+ buildHealthResponse() {
46
+ const transports = this.ulak.getMicroserviceTransports();
47
+ const uptime = Math.round((Date.now() - this.startedAt) / 1000);
48
+ if (transports.size === 0) {
49
+ return Response.json({ status: 'up', uptime });
50
+ }
51
+ const states = {};
52
+ let degraded = false;
53
+ for (const [name, transport] of transports) {
54
+ const connected = transport.isConnected;
55
+ states[name] = connected ? 'connected' : 'disconnected';
56
+ if (!connected) {
57
+ degraded = true;
58
+ }
59
+ }
60
+ return Response.json({ status: degraded ? 'degraded' : 'up', uptime, transports: states }, { status: degraded ? 503 : 200 });
61
+ }
62
+ }
63
+ //# sourceMappingURL=HealthServer.js.map