@asenajs/asena 0.7.1 → 0.8.1

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 (148) 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/adapter/types/ValidationError.d.ts +53 -0
  6. package/dist/lib/adapter/types/ValidationError.js +24 -0
  7. package/dist/lib/adapter/types/ValidationError.js.map +1 -0
  8. package/dist/lib/adapter/types/index.d.ts +1 -0
  9. package/dist/lib/adapter/types/index.js +1 -0
  10. package/dist/lib/adapter/types/index.js.map +1 -1
  11. package/dist/lib/ioc/Container.d.ts +25 -0
  12. package/dist/lib/ioc/Container.js +47 -0
  13. package/dist/lib/ioc/Container.js.map +1 -1
  14. package/dist/lib/ioc/CoreContainer.d.ts +5 -3
  15. package/dist/lib/ioc/CoreContainer.js +9 -3
  16. package/dist/lib/ioc/CoreContainer.js.map +1 -1
  17. package/dist/lib/ioc/IocEngine.d.ts +50 -4
  18. package/dist/lib/ioc/IocEngine.js +138 -12
  19. package/dist/lib/ioc/IocEngine.js.map +1 -1
  20. package/dist/lib/ioc/component/componentRegistry.d.ts +22 -0
  21. package/dist/lib/ioc/component/componentRegistry.js +119 -0
  22. package/dist/lib/ioc/component/componentRegistry.js.map +1 -0
  23. package/dist/lib/ioc/component/componentUtils.js +4 -0
  24. package/dist/lib/ioc/component/componentUtils.js.map +1 -1
  25. package/dist/lib/ioc/component/decorators/Inject.js +16 -0
  26. package/dist/lib/ioc/component/decorators/Inject.js.map +1 -1
  27. package/dist/lib/ioc/component/index.d.ts +1 -0
  28. package/dist/lib/ioc/component/index.js +1 -0
  29. package/dist/lib/ioc/component/index.js.map +1 -1
  30. package/dist/lib/ioc/constants/ComponentConstants.d.ts +4 -0
  31. package/dist/lib/ioc/constants/ComponentConstants.js +5 -0
  32. package/dist/lib/ioc/constants/ComponentConstants.js.map +1 -1
  33. package/dist/lib/ioc/helper/fileHelper.d.ts +9 -0
  34. package/dist/lib/ioc/helper/fileHelper.js +41 -11
  35. package/dist/lib/ioc/helper/fileHelper.js.map +1 -1
  36. package/dist/lib/ioc/types/ICoreServiceNamesType.d.ts +1 -0
  37. package/dist/lib/ioc/types/ICoreServiceNamesType.js +1 -0
  38. package/dist/lib/ioc/types/ICoreServiceNamesType.js.map +1 -1
  39. package/dist/lib/ioc/types/InjectableComponent.d.ts +10 -0
  40. package/dist/lib/ioc/types/IocConfig.d.ts +7 -0
  41. package/dist/lib/ioc/types/decorators/ComponentType.d.ts +2 -1
  42. package/dist/lib/ioc/types/decorators/ComponentType.js +1 -0
  43. package/dist/lib/ioc/types/decorators/ComponentType.js.map +1 -1
  44. package/dist/lib/server/AsenaServer.d.ts +47 -3
  45. package/dist/lib/server/AsenaServer.js +167 -28
  46. package/dist/lib/server/AsenaServer.js.map +1 -1
  47. package/dist/lib/server/AsenaServerFactory.d.ts +38 -3
  48. package/dist/lib/server/AsenaServerFactory.js +21 -2
  49. package/dist/lib/server/AsenaServerFactory.js.map +1 -1
  50. package/dist/lib/server/config/AsenaConfig.d.ts +82 -4
  51. package/dist/lib/server/config/AsenaConfig.js +39 -1
  52. package/dist/lib/server/config/AsenaConfig.js.map +1 -1
  53. package/dist/lib/server/decorators/components/MessageController.d.ts +49 -0
  54. package/dist/lib/server/decorators/components/MessageController.js +62 -0
  55. package/dist/lib/server/decorators/components/MessageController.js.map +1 -0
  56. package/dist/lib/server/decorators/components/index.d.ts +1 -0
  57. package/dist/lib/server/decorators/components/index.js +1 -0
  58. package/dist/lib/server/decorators/components/index.js.map +1 -1
  59. package/dist/lib/server/event/EventDispatchService.d.ts +3 -7
  60. package/dist/lib/server/event/EventDispatchService.js +9 -40
  61. package/dist/lib/server/event/EventDispatchService.js.map +1 -1
  62. package/dist/lib/server/event/PatternHandlerIndex.d.ts +53 -0
  63. package/dist/lib/server/event/PatternHandlerIndex.js +100 -0
  64. package/dist/lib/server/event/PatternHandlerIndex.js.map +1 -0
  65. package/dist/lib/server/event/decorators/On.d.ts +4 -0
  66. package/dist/lib/server/event/decorators/On.js +6 -0
  67. package/dist/lib/server/event/decorators/On.js.map +1 -1
  68. package/dist/lib/server/event/index.d.ts +1 -0
  69. package/dist/lib/server/event/index.js +2 -0
  70. package/dist/lib/server/event/index.js.map +1 -1
  71. package/dist/lib/server/event/types.d.ts +12 -0
  72. package/dist/lib/server/health/HealthServer.d.ts +26 -0
  73. package/dist/lib/server/health/HealthServer.js +63 -0
  74. package/dist/lib/server/health/HealthServer.js.map +1 -0
  75. package/dist/lib/server/health/index.d.ts +1 -0
  76. package/dist/lib/server/health/index.js +2 -0
  77. package/dist/lib/server/health/index.js.map +1 -0
  78. package/dist/lib/server/messaging/Ulak.d.ts +156 -0
  79. package/dist/lib/server/messaging/Ulak.js +174 -0
  80. package/dist/lib/server/messaging/Ulak.js.map +1 -1
  81. package/dist/lib/server/messaging/types.d.ts +5 -1
  82. package/dist/lib/server/messaging/types.js +5 -0
  83. package/dist/lib/server/messaging/types.js.map +1 -1
  84. package/dist/lib/server/microservice/InMemoryTransport.d.ts +45 -0
  85. package/dist/lib/server/microservice/InMemoryTransport.js +124 -0
  86. package/dist/lib/server/microservice/InMemoryTransport.js.map +1 -0
  87. package/dist/lib/server/microservice/MicroserviceTransport.d.ts +132 -0
  88. package/dist/lib/server/microservice/MicroserviceTransport.js +2 -0
  89. package/dist/lib/server/microservice/MicroserviceTransport.js.map +1 -0
  90. package/dist/lib/server/microservice/decorators/EventPattern.d.ts +38 -0
  91. package/dist/lib/server/microservice/decorators/EventPattern.js +59 -0
  92. package/dist/lib/server/microservice/decorators/EventPattern.js.map +1 -0
  93. package/dist/lib/server/microservice/decorators/MessagePattern.d.ts +31 -0
  94. package/dist/lib/server/microservice/decorators/MessagePattern.js +55 -0
  95. package/dist/lib/server/microservice/decorators/MessagePattern.js.map +1 -0
  96. package/dist/lib/server/microservice/decorators/index.d.ts +2 -0
  97. package/dist/lib/server/microservice/decorators/index.js +3 -0
  98. package/dist/lib/server/microservice/decorators/index.js.map +1 -0
  99. package/dist/lib/server/microservice/index.d.ts +5 -0
  100. package/dist/lib/server/microservice/index.js +11 -0
  101. package/dist/lib/server/microservice/index.js.map +1 -0
  102. package/dist/lib/server/microservice/interceptorChain.d.ts +20 -0
  103. package/dist/lib/server/microservice/interceptorChain.js +39 -0
  104. package/dist/lib/server/microservice/interceptorChain.js.map +1 -0
  105. package/dist/lib/server/microservice/types.d.ts +142 -0
  106. package/dist/lib/server/microservice/types.js +5 -0
  107. package/dist/lib/server/microservice/types.js.map +1 -0
  108. package/dist/lib/server/src/services/PrepareEventService.d.ts +4 -1
  109. package/dist/lib/server/src/services/PrepareEventService.js +10 -3
  110. package/dist/lib/server/src/services/PrepareEventService.js.map +1 -1
  111. package/dist/lib/server/src/services/PrepareMicroserviceService.d.ts +66 -0
  112. package/dist/lib/server/src/services/PrepareMicroserviceService.js +193 -0
  113. package/dist/lib/server/src/services/PrepareMicroserviceService.js.map +1 -0
  114. package/dist/lib/test/factory/deepMock.d.ts +25 -0
  115. package/dist/lib/test/factory/deepMock.js +105 -0
  116. package/dist/lib/test/factory/deepMock.js.map +1 -0
  117. package/dist/lib/test/factory/ulakStub.d.ts +44 -0
  118. package/dist/lib/test/factory/ulakStub.js +40 -0
  119. package/dist/lib/test/factory/ulakStub.js.map +1 -0
  120. package/dist/lib/test/harness/createTestApp.d.ts +33 -0
  121. package/dist/lib/test/harness/createTestApp.js +105 -0
  122. package/dist/lib/test/harness/createTestApp.js.map +1 -0
  123. package/dist/lib/test/harness/createWebTest.d.ts +28 -0
  124. package/dist/lib/test/harness/createWebTest.js +127 -0
  125. package/dist/lib/test/harness/createWebTest.js.map +1 -0
  126. package/dist/lib/test/harness/silentLogger.d.ts +27 -0
  127. package/dist/lib/test/harness/silentLogger.js +54 -0
  128. package/dist/lib/test/harness/silentLogger.js.map +1 -0
  129. package/dist/lib/test/harness/types.d.ts +147 -0
  130. package/dist/lib/test/harness/types.js +2 -0
  131. package/dist/lib/test/harness/types.js.map +1 -0
  132. package/dist/lib/test/http/TestHttpCall.d.ts +78 -0
  133. package/dist/lib/test/http/TestHttpCall.js +149 -0
  134. package/dist/lib/test/http/TestHttpCall.js.map +1 -0
  135. package/dist/lib/test/http/TestHttpResponse.d.ts +46 -0
  136. package/dist/lib/test/http/TestHttpResponse.js +70 -0
  137. package/dist/lib/test/http/TestHttpResponse.js.map +1 -0
  138. package/dist/lib/test/index.d.ts +9 -0
  139. package/dist/lib/test/index.js +8 -0
  140. package/dist/lib/test/index.js.map +1 -1
  141. package/dist/lib/test/metadata/discovery.d.ts +21 -0
  142. package/dist/lib/test/metadata/discovery.js +37 -8
  143. package/dist/lib/test/metadata/discovery.js.map +1 -1
  144. package/dist/lib/test/mockComponent.d.ts +25 -0
  145. package/dist/lib/test/mockComponent.js +39 -6
  146. package/dist/lib/test/mockComponent.js.map +1 -1
  147. package/dist/lib/test/types.d.ts +13 -0
  148. package/package.json +11 -7
@@ -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
@@ -0,0 +1 @@
1
+ {"version":3,"file":"HealthServer.js","sourceRoot":"","sources":["../../../../lib/server/health/HealthServer.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,GAAG,MAAM,KAAK,CAAC;AAC3B,OAAO,EAAE,IAAI,EAAqB,MAAM,cAAc,CAAC;AAIvD;;;;;;;;;;;GAWG;AACH,MAAM,OAAO,YAAY;IAMJ;IACA;IACA;IAPX,MAAM,CAAmB;IAEzB,SAAS,GAAG,CAAC,CAAC;IAEtB,YACmB,OAAsB,EACtB,IAAU,EACV,MAAoB;QAFpB,YAAO,GAAP,OAAO,CAAe;QACtB,SAAI,GAAJ,IAAI,CAAM;QACV,WAAM,GAAN,MAAM,CAAc;IACpC,CAAC;IAEG,KAAK;QACV,MAAM,IAAI,GAAG,IAAI,CAAC,OAAO,CAAC,IAAI,IAAI,UAAU,CAAC;QAE7C,IAAI,CAAC,SAAS,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;QAE5B,IAAI,CAAC,MAAM,GAAG,GAAG,CAAC,KAAK,CAAC;YACtB,IAAI,EAAE,IAAI,CAAC,OAAO,CAAC,IAAI;YACvB,KAAK,EAAE,CAAC,OAAgB,EAAE,EAAE;gBAC1B,MAAM,GAAG,GAAG,IAAI,GAAG,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC;gBAEjC,IAAI,GAAG,CAAC,QAAQ,KAAK,IAAI,EAAE,CAAC;oBAC1B,OAAO,IAAI,QAAQ,CAAC,WAAW,EAAE,EAAE,MAAM,EAAE,GAAG,EAAE,CAAC,CAAC;gBACpD,CAAC;gBAED,OAAO,IAAI,CAAC,mBAAmB,EAAE,CAAC;YACpC,CAAC;SACF,CAAC,CAAC;QAEH,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC,UAAU,CAAC,8BAA8B,IAAI,CAAC,OAAO,CAAC,IAAI,GAAG,IAAI,EAAE,CAAC,CAAC;IAChG,CAAC;IAEM,IAAI;QACT,KAAK,IAAI,CAAC,MAAM,EAAE,IAAI,CAAC,IAAI,CAAC,CAAC;QAC7B,IAAI,CAAC,MAAM,GAAG,SAAS,CAAC;IAC1B,CAAC;IAEO,mBAAmB;QACzB,MAAM,UAAU,GAAG,IAAI,CAAC,IAAI,CAAC,yBAAyB,EAAE,CAAC;QAEzD,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,IAAI,CAAC,GAAG,EAAE,GAAG,IAAI,CAAC,SAAS,CAAC,GAAG,IAAI,CAAC,CAAC;QAEhE,IAAI,UAAU,CAAC,IAAI,KAAK,CAAC,EAAE,CAAC;YAC1B,OAAO,QAAQ,CAAC,IAAI,CAAC,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC,CAAC;QACjD,CAAC;QAED,MAAM,MAAM,GAAiD,EAAE,CAAC;QAChE,IAAI,QAAQ,GAAG,KAAK,CAAC;QAErB,KAAK,MAAM,CAAC,IAAI,EAAE,SAAS,CAAC,IAAI,UAAU,EAAE,CAAC;YAC3C,MAAM,SAAS,GAAG,SAAS,CAAC,WAAW,CAAC;YAExC,MAAM,CAAC,IAAI,CAAC,GAAG,SAAS,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC,CAAC,cAAc,CAAC;YAExD,IAAI,CAAC,SAAS,EAAE,CAAC;gBACf,QAAQ,GAAG,IAAI,CAAC;YAClB,CAAC;QACH,CAAC;QAED,OAAO,QAAQ,CAAC,IAAI,CAClB,EAAE,MAAM,EAAE,QAAQ,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,IAAI,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,EAAE,EACpE,EAAE,MAAM,EAAE,QAAQ,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,EAAE,CACjC,CAAC;IACJ,CAAC;CACF"}
@@ -0,0 +1 @@
1
+ export * from './HealthServer';
@@ -0,0 +1,2 @@
1
+ export * from './HealthServer';
2
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../lib/server/health/index.ts"],"names":[],"mappings":"AAAA,cAAc,gBAAgB,CAAC"}
@@ -1,6 +1,28 @@
1
1
  import type { AsenaWebSocketService } from '../web/websocket';
2
2
  import { type ICoreService, ICoreServiceNames } from '../../ioc';
3
3
  import { type BulkOperation, type BulkResult } from './types';
4
+ import type { MessagingInterceptor } from '../microservice/types';
5
+ import type { EmitOptions, MicroserviceTransport, SendOptions } from '../microservice/MicroserviceTransport';
6
+ /**
7
+ * @description Options for Ulak microservice sends - adds named transport selection
8
+ */
9
+ export interface UlakSendOptions extends SendOptions {
10
+ /**
11
+ * Named microservice transport to use (multi-broker projects)
12
+ * @default 'default'
13
+ */
14
+ transport?: string;
15
+ }
16
+ /**
17
+ * @description Options for Ulak microservice emits - adds named transport selection
18
+ */
19
+ export interface UlakEmitOptions extends EmitOptions {
20
+ /**
21
+ * Named microservice transport to use (multi-broker projects)
22
+ * @default 'default'
23
+ */
24
+ transport?: string;
25
+ }
4
26
  /**
5
27
  * Central WebSocket message broker for Asena.js
6
28
  *
@@ -32,6 +54,14 @@ export declare class Ulak implements ICoreService {
32
54
  * Map of namespace path to WebSocket service instance
33
55
  */
34
56
  private namespaces;
57
+ /**
58
+ * Named microservice transports (set during bootstrap by PrepareMicroserviceService)
59
+ */
60
+ private microserviceTransports;
61
+ /**
62
+ * Messaging interceptors applied to all outgoing send/emit calls
63
+ */
64
+ private microserviceInterceptors;
35
65
  /**
36
66
  * Initialize Ulak messaging system
37
67
  * Called after dependency injection is complete
@@ -133,6 +163,62 @@ export declare class Ulak implements ICoreService {
133
163
  * @returns Number of active sockets
134
164
  */
135
165
  getSocketCount(namespace: string): number;
166
+ /**
167
+ * Wire the microservice transports into Ulak
168
+ * Called during bootstrap by PrepareMicroserviceService - not intended for user code
169
+ *
170
+ * @param transports - Named transports ('default' for the single-transport form)
171
+ * @param interceptors - Interceptors applied to all outgoing send/emit calls
172
+ */
173
+ setMicroserviceTransports(transports: Map<string, MicroserviceTransport>, interceptors?: MessagingInterceptor[]): void;
174
+ /**
175
+ * Check if a microservice transport is configured and connected
176
+ *
177
+ * @param transport - Named transport to check
178
+ * @returns True when the transport exists and reports a live connection
179
+ */
180
+ isMicroserviceConnected(transport?: string): boolean;
181
+ /**
182
+ * Get all configured microservice transports (read-only)
183
+ * Used by the health endpoint to report per-transport status
184
+ */
185
+ getMicroserviceTransports(): ReadonlyMap<string, MicroserviceTransport>;
186
+ /**
187
+ * Send a request to another service and await its reply (request/response)
188
+ *
189
+ * @param pattern - Full request pattern (e.g. 'order.create')
190
+ * @param data - Request payload
191
+ * @param options - Timeout, headers and named transport selection
192
+ * @returns The reply produced by the remote @MessagePattern handler
193
+ * @throws {UlakError} NO_TRANSPORT / TRANSPORT_NOT_FOUND / TIMEOUT / REMOTE_ERROR
194
+ */
195
+ send<T = unknown>(pattern: string, data?: unknown, options?: UlakSendOptions): Promise<T>;
196
+ /**
197
+ * Emit a fire-and-forget event to other services
198
+ *
199
+ * @param pattern - Full event pattern (e.g. 'order.created')
200
+ * @param data - Event payload
201
+ * @param options - Headers and named transport selection
202
+ * @throws {UlakError} NO_TRANSPORT / TRANSPORT_NOT_FOUND
203
+ */
204
+ emit(pattern: string, data?: unknown, options?: UlakEmitOptions): Promise<void>;
205
+ /**
206
+ * Select a pattern-scoped microservice messaging view
207
+ * Patterns passed to the returned view are joined with the prefix ('order' + 'create' → 'order.create')
208
+ *
209
+ * @param prefix - Pattern prefix (empty for absolute patterns)
210
+ * @param options - Named transport selection
211
+ * @returns Scoped messages instance
212
+ *
213
+ * @example
214
+ * ```typescript
215
+ * const orders = ulak.messages('order');
216
+ * const res = await orders.send('create', dto); // sends 'order.create'
217
+ * ```
218
+ */
219
+ messages<T extends string = ''>(prefix?: T, options?: {
220
+ transport?: string;
221
+ }): Ulak.Messages<T>;
136
222
  /**
137
223
  * Dispose of all resources and stop background tasks
138
224
  * Should be called during application shutdown
@@ -146,6 +232,13 @@ export declare class Ulak implements ICoreService {
146
232
  * @throws {UlakError} If namespace not found
147
233
  */
148
234
  private getNamespaceService;
235
+ /**
236
+ * Get a named microservice transport or throw
237
+ *
238
+ * @param name - Named transport (defaults to 'default')
239
+ * @throws {UlakError} NO_TRANSPORT when none configured, TRANSPORT_NOT_FOUND for unknown names
240
+ */
241
+ private getMicroserviceTransport;
149
242
  }
150
243
  /**
151
244
  * Scoped namespace interface
@@ -191,6 +284,34 @@ export declare namespace Ulak {
191
284
  */
192
285
  getSocketCount(): number;
193
286
  }
287
+ /**
288
+ * Pattern-scoped microservice messaging view
289
+ * Provides ergonomic API without repeating the pattern prefix
290
+ */
291
+ interface Messages<P extends string = string> {
292
+ /**
293
+ * The pattern prefix ('' for absolute patterns)
294
+ */
295
+ readonly prefix: P;
296
+ /**
297
+ * Send a request and await its reply (request/response)
298
+ * The pattern is joined with the prefix ('create' → 'order.create')
299
+ *
300
+ * @param pattern - Request pattern relative to the prefix
301
+ * @param data - Request payload
302
+ * @param options - Timeout and headers
303
+ */
304
+ send<T = unknown>(pattern: string, data?: unknown, options?: SendOptions): Promise<T>;
305
+ /**
306
+ * Emit a fire-and-forget event
307
+ * The pattern is joined with the prefix ('created' → 'order.created')
308
+ *
309
+ * @param pattern - Event pattern relative to the prefix
310
+ * @param data - Event payload
311
+ * @param options - Headers
312
+ */
313
+ emit(pattern: string, data?: unknown, options?: EmitOptions): Promise<void>;
314
+ }
194
315
  }
195
316
  /**
196
317
  * Helper function for injecting scoped Ulak namespace
@@ -222,3 +343,38 @@ export declare namespace Ulak {
222
343
  * ```
223
344
  */
224
345
  export declare function ulak<T extends string>(namespace: T): readonly [ICoreServiceNames.__ULAK__, (ulak: Ulak) => Ulak.NameSpace<T>];
346
+ /**
347
+ * Helper functions for injecting microservice messaging views from Ulak
348
+ * Declaration merging keeps the single `ulak` entry point:
349
+ * `ulak('/chat')` → WebSocket namespace, `ulak.messages('order')` → microservice messaging
350
+ */
351
+ export declare namespace ulak {
352
+ /**
353
+ * Inject a pattern-scoped microservice messaging view
354
+ *
355
+ * @param prefix - Pattern prefix joined to every send/emit ('' for absolute patterns)
356
+ * @param options - Named transport selection (multi-broker projects)
357
+ * @returns A tuple of [serviceName, expression] for @Inject decorator
358
+ *
359
+ * @example
360
+ * ```typescript
361
+ * @Service('CheckoutService')
362
+ * export class CheckoutService {
363
+ * @Inject(ulak.messages('order'))
364
+ * private orders: Ulak.Messages<'order'>;
365
+ *
366
+ * async checkout(dto: CheckoutDto) {
367
+ * const res = await this.orders.send('create', dto); // sends 'order.create'
368
+ * await this.orders.emit('created', { id: res.id }); // emits 'order.created'
369
+ * }
370
+ * }
371
+ *
372
+ * // Named transport (multi-broker projects)
373
+ * @Inject(ulak.messages('metrics', { transport: 'analytics' }))
374
+ * private metrics: Ulak.Messages<'metrics'>;
375
+ * ```
376
+ */
377
+ function messages<P extends string = ''>(prefix?: P, options?: {
378
+ transport?: string;
379
+ }): readonly [ICoreServiceNames.__ULAK__, (u: Ulak) => Ulak.Messages<P>];
380
+ }