@hazeljs/messaging 0.2.0-beta.30

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 (107) hide show
  1. package/LICENSE +192 -0
  2. package/README.md +186 -0
  3. package/dist/adapters/telegram.adapter.d.ts +24 -0
  4. package/dist/adapters/telegram.adapter.d.ts.map +1 -0
  5. package/dist/adapters/telegram.adapter.js +70 -0
  6. package/dist/adapters/telegram.adapter.js.map +1 -0
  7. package/dist/adapters/telegram.adapter.test.d.ts +2 -0
  8. package/dist/adapters/telegram.adapter.test.d.ts.map +1 -0
  9. package/dist/adapters/telegram.adapter.test.js +110 -0
  10. package/dist/adapters/telegram.adapter.test.js.map +1 -0
  11. package/dist/adapters/viber.adapter.d.ts +29 -0
  12. package/dist/adapters/viber.adapter.d.ts.map +1 -0
  13. package/dist/adapters/viber.adapter.js +98 -0
  14. package/dist/adapters/viber.adapter.js.map +1 -0
  15. package/dist/adapters/viber.adapter.test.d.ts +2 -0
  16. package/dist/adapters/viber.adapter.test.d.ts.map +1 -0
  17. package/dist/adapters/viber.adapter.test.js +73 -0
  18. package/dist/adapters/viber.adapter.test.js.map +1 -0
  19. package/dist/adapters/whatsapp.adapter.d.ts +26 -0
  20. package/dist/adapters/whatsapp.adapter.d.ts.map +1 -0
  21. package/dist/adapters/whatsapp.adapter.js +87 -0
  22. package/dist/adapters/whatsapp.adapter.js.map +1 -0
  23. package/dist/adapters/whatsapp.adapter.test.d.ts +2 -0
  24. package/dist/adapters/whatsapp.adapter.test.d.ts.map +1 -0
  25. package/dist/adapters/whatsapp.adapter.test.js +198 -0
  26. package/dist/adapters/whatsapp.adapter.test.js.map +1 -0
  27. package/dist/index.d.ts +24 -0
  28. package/dist/index.d.ts.map +1 -0
  29. package/dist/index.js +27 -0
  30. package/dist/index.js.map +1 -0
  31. package/dist/messaging-kafka.bootstrap.d.ts +14 -0
  32. package/dist/messaging-kafka.bootstrap.d.ts.map +1 -0
  33. package/dist/messaging-kafka.bootstrap.js +42 -0
  34. package/dist/messaging-kafka.bootstrap.js.map +1 -0
  35. package/dist/messaging-kafka.bootstrap.test.d.ts +2 -0
  36. package/dist/messaging-kafka.bootstrap.test.d.ts.map +1 -0
  37. package/dist/messaging-kafka.bootstrap.test.js +34 -0
  38. package/dist/messaging-kafka.bootstrap.test.js.map +1 -0
  39. package/dist/messaging-kafka.consumer.d.ts +10 -0
  40. package/dist/messaging-kafka.consumer.d.ts.map +1 -0
  41. package/dist/messaging-kafka.consumer.js +80 -0
  42. package/dist/messaging-kafka.consumer.js.map +1 -0
  43. package/dist/messaging-kafka.consumer.test.d.ts +2 -0
  44. package/dist/messaging-kafka.consumer.test.d.ts.map +1 -0
  45. package/dist/messaging-kafka.consumer.test.js +129 -0
  46. package/dist/messaging-kafka.consumer.test.js.map +1 -0
  47. package/dist/messaging-kafka.types.d.ts +10 -0
  48. package/dist/messaging-kafka.types.d.ts.map +1 -0
  49. package/dist/messaging-kafka.types.js +5 -0
  50. package/dist/messaging-kafka.types.js.map +1 -0
  51. package/dist/messaging-kafka.types.test.d.ts +2 -0
  52. package/dist/messaging-kafka.types.test.d.ts.map +1 -0
  53. package/dist/messaging-kafka.types.test.js +12 -0
  54. package/dist/messaging-kafka.types.test.js.map +1 -0
  55. package/dist/messaging.controller.d.ts +27 -0
  56. package/dist/messaging.controller.d.ts.map +1 -0
  57. package/dist/messaging.controller.js +151 -0
  58. package/dist/messaging.controller.js.map +1 -0
  59. package/dist/messaging.controller.test.d.ts +2 -0
  60. package/dist/messaging.controller.test.d.ts.map +1 -0
  61. package/dist/messaging.controller.test.js +184 -0
  62. package/dist/messaging.controller.test.js.map +1 -0
  63. package/dist/messaging.module.d.ts +69 -0
  64. package/dist/messaging.module.d.ts.map +1 -0
  65. package/dist/messaging.module.js +152 -0
  66. package/dist/messaging.module.js.map +1 -0
  67. package/dist/messaging.module.test.d.ts +2 -0
  68. package/dist/messaging.module.test.d.ts.map +1 -0
  69. package/dist/messaging.module.test.js +97 -0
  70. package/dist/messaging.module.test.js.map +1 -0
  71. package/dist/messaging.service.d.ts +42 -0
  72. package/dist/messaging.service.d.ts.map +1 -0
  73. package/dist/messaging.service.js +109 -0
  74. package/dist/messaging.service.js.map +1 -0
  75. package/dist/messaging.service.test.d.ts +2 -0
  76. package/dist/messaging.service.test.d.ts.map +1 -0
  77. package/dist/messaging.service.test.js +163 -0
  78. package/dist/messaging.service.test.js.map +1 -0
  79. package/dist/store/conversation-context.interface.d.ts +17 -0
  80. package/dist/store/conversation-context.interface.d.ts.map +1 -0
  81. package/dist/store/conversation-context.interface.js +7 -0
  82. package/dist/store/conversation-context.interface.js.map +1 -0
  83. package/dist/store/memory-conversation-context.d.ts +11 -0
  84. package/dist/store/memory-conversation-context.d.ts.map +1 -0
  85. package/dist/store/memory-conversation-context.js +22 -0
  86. package/dist/store/memory-conversation-context.js.map +1 -0
  87. package/dist/store/memory-conversation-context.test.d.ts +2 -0
  88. package/dist/store/memory-conversation-context.test.d.ts.map +1 -0
  89. package/dist/store/memory-conversation-context.test.js +69 -0
  90. package/dist/store/memory-conversation-context.test.js.map +1 -0
  91. package/dist/store/redis-conversation-context.d.ts +24 -0
  92. package/dist/store/redis-conversation-context.d.ts.map +1 -0
  93. package/dist/store/redis-conversation-context.js +37 -0
  94. package/dist/store/redis-conversation-context.js.map +1 -0
  95. package/dist/store/redis-conversation-context.test.d.ts +2 -0
  96. package/dist/store/redis-conversation-context.test.d.ts.map +1 -0
  97. package/dist/store/redis-conversation-context.test.js +85 -0
  98. package/dist/store/redis-conversation-context.test.js.map +1 -0
  99. package/dist/types/message.types.d.ts +55 -0
  100. package/dist/types/message.types.d.ts.map +1 -0
  101. package/dist/types/message.types.js +7 -0
  102. package/dist/types/message.types.js.map +1 -0
  103. package/dist/types/response-handler.types.d.ts +47 -0
  104. package/dist/types/response-handler.types.d.ts.map +1 -0
  105. package/dist/types/response-handler.types.js +3 -0
  106. package/dist/types/response-handler.types.js.map +1 -0
  107. package/package.json +88 -0
@@ -0,0 +1,42 @@
1
+ "use strict";
2
+ var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
3
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
4
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
5
+ else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
6
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
7
+ };
8
+ var __metadata = (this && this.__metadata) || function (k, v) {
9
+ if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
10
+ };
11
+ var __param = (this && this.__param) || function (paramIndex, decorator) {
12
+ return function (target, key) { decorator(target, key, paramIndex); }
13
+ };
14
+ Object.defineProperty(exports, "__esModule", { value: true });
15
+ exports.MessagingKafkaBootstrap = void 0;
16
+ /**
17
+ * Registers MessagingKafkaConsumer with KafkaConsumerService on module init
18
+ */
19
+ const core_1 = require("@hazeljs/core");
20
+ const kafka_1 = require("@hazeljs/kafka");
21
+ const messaging_kafka_consumer_1 = require("./messaging-kafka.consumer");
22
+ const messaging_controller_1 = require("./messaging.controller");
23
+ let MessagingKafkaBootstrap = class MessagingKafkaBootstrap {
24
+ constructor(consumerService, messagingConsumer, useKafka) {
25
+ this.consumerService = consumerService;
26
+ this.messagingConsumer = messagingConsumer;
27
+ this.useKafka = useKafka;
28
+ }
29
+ async onModuleInit() {
30
+ if (!this.useKafka)
31
+ return;
32
+ await this.consumerService.registerFromProvider(this.messagingConsumer);
33
+ }
34
+ };
35
+ exports.MessagingKafkaBootstrap = MessagingKafkaBootstrap;
36
+ exports.MessagingKafkaBootstrap = MessagingKafkaBootstrap = __decorate([
37
+ (0, core_1.Injectable)(),
38
+ __param(2, (0, core_1.Inject)(messaging_controller_1.MESSAGING_USE_KAFKA)),
39
+ __metadata("design:paramtypes", [kafka_1.KafkaConsumerService,
40
+ messaging_kafka_consumer_1.MessagingKafkaConsumer, Boolean])
41
+ ], MessagingKafkaBootstrap);
42
+ //# sourceMappingURL=messaging-kafka.bootstrap.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"messaging-kafka.bootstrap.js","sourceRoot":"","sources":["../src/messaging-kafka.bootstrap.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;AAAA;;GAEG;AACH,wCAAsE;AACtE,0CAAsD;AACtD,yEAAoE;AACpE,iEAA6D;AAGtD,IAAM,uBAAuB,GAA7B,MAAM,uBAAuB;IAClC,YACmB,eAAqC,EACrC,iBAAyC,EACZ,QAAiB;QAF9C,oBAAe,GAAf,eAAe,CAAsB;QACrC,sBAAiB,GAAjB,iBAAiB,CAAwB;QACZ,aAAQ,GAAR,QAAQ,CAAS;IAC9D,CAAC;IAEJ,KAAK,CAAC,YAAY;QAChB,IAAI,CAAC,IAAI,CAAC,QAAQ;YAAE,OAAO;QAC3B,MAAM,IAAI,CAAC,eAAe,CAAC,oBAAoB,CAAC,IAAI,CAAC,iBAAiB,CAAC,CAAC;IAC1E,CAAC;CACF,CAAA;AAXY,0DAAuB;kCAAvB,uBAAuB;IADnC,IAAA,iBAAU,GAAE;IAKR,WAAA,IAAA,aAAM,EAAC,0CAAmB,CAAC,CAAA;qCAFM,4BAAoB;QAClB,iDAAsB;GAHjD,uBAAuB,CAWnC"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=messaging-kafka.bootstrap.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"messaging-kafka.bootstrap.test.d.ts","sourceRoot":"","sources":["../src/messaging-kafka.bootstrap.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,34 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ /**
4
+ * MessagingKafkaBootstrap tests
5
+ */
6
+ const messaging_kafka_bootstrap_1 = require("./messaging-kafka.bootstrap");
7
+ jest.mock('@hazeljs/kafka', () => ({
8
+ KafkaConsumer: () => () => { },
9
+ KafkaSubscribe: () => (_target, _key, descriptor) => descriptor,
10
+ KafkaConsumerService: jest.fn().mockImplementation(() => ({
11
+ registerFromProvider: jest.fn().mockResolvedValue(undefined),
12
+ })),
13
+ }));
14
+ describe('MessagingKafkaBootstrap', () => {
15
+ it('does nothing when useKafka is false', async () => {
16
+ const mockConsumerService = {
17
+ registerFromProvider: jest.fn(),
18
+ };
19
+ const mockConsumer = {};
20
+ const bootstrap = new messaging_kafka_bootstrap_1.MessagingKafkaBootstrap(mockConsumerService, mockConsumer, false);
21
+ await bootstrap.onModuleInit();
22
+ expect(mockConsumerService.registerFromProvider).not.toHaveBeenCalled();
23
+ });
24
+ it('registers consumer when useKafka is true', async () => {
25
+ const mockConsumerService = {
26
+ registerFromProvider: jest.fn().mockResolvedValue(undefined),
27
+ };
28
+ const mockConsumer = {};
29
+ const bootstrap = new messaging_kafka_bootstrap_1.MessagingKafkaBootstrap(mockConsumerService, mockConsumer, true);
30
+ await bootstrap.onModuleInit();
31
+ expect(mockConsumerService.registerFromProvider).toHaveBeenCalledWith(mockConsumer);
32
+ });
33
+ });
34
+ //# sourceMappingURL=messaging-kafka.bootstrap.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"messaging-kafka.bootstrap.test.js","sourceRoot":"","sources":["../src/messaging-kafka.bootstrap.test.ts"],"names":[],"mappings":";;AAAA;;GAEG;AACH,2EAAsE;AAEtE,IAAI,CAAC,IAAI,CAAC,gBAAgB,EAAE,GAAG,EAAE,CAAC,CAAC;IACjC,aAAa,EAAE,GAAG,EAAE,CAAC,GAAG,EAAE,GAAE,CAAC;IAC7B,cAAc,EAAE,GAAG,EAAE,CAAC,CAAC,OAAgB,EAAE,IAAa,EAAE,UAA+B,EAAE,EAAE,CACzF,UAAU;IACZ,oBAAoB,EAAE,IAAI,CAAC,EAAE,EAAE,CAAC,kBAAkB,CAAC,GAAG,EAAE,CAAC,CAAC;QACxD,oBAAoB,EAAE,IAAI,CAAC,EAAE,EAAE,CAAC,iBAAiB,CAAC,SAAS,CAAC;KAC7D,CAAC,CAAC;CACJ,CAAC,CAAC,CAAC;AAEJ,QAAQ,CAAC,yBAAyB,EAAE,GAAG,EAAE;IACvC,EAAE,CAAC,qCAAqC,EAAE,KAAK,IAAI,EAAE;QACnD,MAAM,mBAAmB,GAAG;YAC1B,oBAAoB,EAAE,IAAI,CAAC,EAAE,EAAE;SAChC,CAAC;QACF,MAAM,YAAY,GAAG,EAAE,CAAC;QACxB,MAAM,SAAS,GAAG,IAAI,mDAAuB,CAC3C,mBAA4B,EAC5B,YAAqB,EACrB,KAAK,CACN,CAAC;QAEF,MAAM,SAAS,CAAC,YAAY,EAAE,CAAC;QAE/B,MAAM,CAAC,mBAAmB,CAAC,oBAAoB,CAAC,CAAC,GAAG,CAAC,gBAAgB,EAAE,CAAC;IAC1E,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,0CAA0C,EAAE,KAAK,IAAI,EAAE;QACxD,MAAM,mBAAmB,GAAG;YAC1B,oBAAoB,EAAE,IAAI,CAAC,EAAE,EAAE,CAAC,iBAAiB,CAAC,SAAS,CAAC;SAC7D,CAAC;QACF,MAAM,YAAY,GAAG,EAAE,CAAC;QACxB,MAAM,SAAS,GAAG,IAAI,mDAAuB,CAC3C,mBAA4B,EAC5B,YAAqB,EACrB,IAAI,CACL,CAAC;QAEF,MAAM,SAAS,CAAC,YAAY,EAAE,CAAC;QAE/B,MAAM,CAAC,mBAAmB,CAAC,oBAAoB,CAAC,CAAC,oBAAoB,CAAC,YAAY,CAAC,CAAC;IACtF,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC"}
@@ -0,0 +1,10 @@
1
+ import { KafkaMessagePayload } from '@hazeljs/kafka';
2
+ import { MessagingService } from './messaging.service';
3
+ import type { IChannelAdapter } from './types/message.types';
4
+ export declare class MessagingKafkaConsumer {
5
+ private readonly messagingService;
6
+ private readonly adapters;
7
+ constructor(messagingService: MessagingService, adapters: IChannelAdapter[]);
8
+ handleIncoming(payload: KafkaMessagePayload): Promise<void>;
9
+ }
10
+ //# sourceMappingURL=messaging-kafka.consumer.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"messaging-kafka.consumer.d.ts","sourceRoot":"","sources":["../src/messaging-kafka.consumer.ts"],"names":[],"mappings":"AAKA,OAAO,EAAE,mBAAmB,EAAE,MAAM,gBAAgB,CAAC;AACrD,OAAO,EAAE,gBAAgB,EAAE,MAAM,qBAAqB,CAAC;AACvD,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;AAK7D,qBAEa,sBAAsB;IAE/B,OAAO,CAAC,QAAQ,CAAC,gBAAgB;IACL,OAAO,CAAC,QAAQ,CAAC,QAAQ;gBADpC,gBAAgB,EAAE,gBAAgB,EACN,QAAQ,EAAE,eAAe,EAAE;IAIpE,cAAc,CAAC,OAAO,EAAE,mBAAmB,GAAG,OAAO,CAAC,IAAI,CAAC;CAiClE"}
@@ -0,0 +1,80 @@
1
+ "use strict";
2
+ var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
3
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
4
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
5
+ else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
6
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
7
+ };
8
+ var __metadata = (this && this.__metadata) || function (k, v) {
9
+ if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
10
+ };
11
+ var __param = (this && this.__param) || function (paramIndex, decorator) {
12
+ return function (target, key) { decorator(target, key, paramIndex); }
13
+ };
14
+ var __importDefault = (this && this.__importDefault) || function (mod) {
15
+ return (mod && mod.__esModule) ? mod : { "default": mod };
16
+ };
17
+ Object.defineProperty(exports, "__esModule", { value: true });
18
+ exports.MessagingKafkaConsumer = void 0;
19
+ /**
20
+ * Kafka consumer for async message processing - horizontally scalable
21
+ */
22
+ const core_1 = require("@hazeljs/core");
23
+ const kafka_1 = require("@hazeljs/kafka");
24
+ const messaging_service_1 = require("./messaging.service");
25
+ const core_2 = __importDefault(require("@hazeljs/core"));
26
+ const messaging_controller_1 = require("./messaging.controller");
27
+ const messaging_kafka_types_1 = require("./messaging-kafka.types");
28
+ let MessagingKafkaConsumer = class MessagingKafkaConsumer {
29
+ constructor(messagingService, adapters) {
30
+ this.messagingService = messagingService;
31
+ this.adapters = adapters;
32
+ }
33
+ async handleIncoming(payload) {
34
+ const raw = payload.message.value?.toString();
35
+ if (!raw)
36
+ return;
37
+ let data;
38
+ try {
39
+ data = JSON.parse(raw);
40
+ }
41
+ catch {
42
+ core_2.default.error('MessagingKafkaConsumer: invalid JSON payload');
43
+ return;
44
+ }
45
+ const { message, channel } = data;
46
+ const adapter = this.adapters.find((a) => a.channel === channel);
47
+ if (!adapter) {
48
+ core_2.default.warn(`MessagingKafkaConsumer: no adapter for channel ${channel}`);
49
+ return;
50
+ }
51
+ try {
52
+ const response = await this.messagingService.handleMessage(message);
53
+ if (response) {
54
+ await adapter.send({
55
+ conversationId: message.conversationId,
56
+ text: response,
57
+ replyToMessageId: message.id,
58
+ });
59
+ }
60
+ }
61
+ catch (err) {
62
+ core_2.default.error(`MessagingKafkaConsumer error for ${channel}:`, err);
63
+ throw err; // Let Kafka retry
64
+ }
65
+ }
66
+ };
67
+ exports.MessagingKafkaConsumer = MessagingKafkaConsumer;
68
+ __decorate([
69
+ (0, kafka_1.KafkaSubscribe)(messaging_kafka_types_1.MESSAGING_INCOMING_TOPIC),
70
+ __metadata("design:type", Function),
71
+ __metadata("design:paramtypes", [Object]),
72
+ __metadata("design:returntype", Promise)
73
+ ], MessagingKafkaConsumer.prototype, "handleIncoming", null);
74
+ exports.MessagingKafkaConsumer = MessagingKafkaConsumer = __decorate([
75
+ (0, core_1.Injectable)(),
76
+ (0, kafka_1.KafkaConsumer)({ groupId: 'messaging-bot' }),
77
+ __param(1, (0, core_1.Inject)(messaging_controller_1.MESSAGING_ADAPTERS)),
78
+ __metadata("design:paramtypes", [messaging_service_1.MessagingService, Array])
79
+ ], MessagingKafkaConsumer);
80
+ //# sourceMappingURL=messaging-kafka.consumer.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"messaging-kafka.consumer.js","sourceRoot":"","sources":["../src/messaging-kafka.consumer.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;AAAA;;GAEG;AACH,wCAAmD;AACnD,0CAA+D;AAE/D,2DAAuD;AAEvD,yDAAmC;AACnC,iEAA4D;AAC5D,mEAAkG;AAI3F,IAAM,sBAAsB,GAA5B,MAAM,sBAAsB;IACjC,YACmB,gBAAkC,EACN,QAA2B;QADvD,qBAAgB,GAAhB,gBAAgB,CAAkB;QACN,aAAQ,GAAR,QAAQ,CAAmB;IACvE,CAAC;IAGE,AAAN,KAAK,CAAC,cAAc,CAAC,OAA4B;QAC/C,MAAM,GAAG,GAAG,OAAO,CAAC,OAAO,CAAC,KAAK,EAAE,QAAQ,EAAE,CAAC;QAC9C,IAAI,CAAC,GAAG;YAAE,OAAO;QAEjB,IAAI,IAA8B,CAAC;QACnC,IAAI,CAAC;YACH,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAA6B,CAAC;QACrD,CAAC;QAAC,MAAM,CAAC;YACP,cAAM,CAAC,KAAK,CAAC,8CAA8C,CAAC,CAAC;YAC7D,OAAO;QACT,CAAC;QAED,MAAM,EAAE,OAAO,EAAE,OAAO,EAAE,GAAG,IAAI,CAAC;QAClC,MAAM,OAAO,GAAG,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,OAAO,KAAK,OAAO,CAAC,CAAC;QACjE,IAAI,CAAC,OAAO,EAAE,CAAC;YACb,cAAM,CAAC,IAAI,CAAC,kDAAkD,OAAO,EAAE,CAAC,CAAC;YACzE,OAAO;QACT,CAAC;QAED,IAAI,CAAC;YACH,MAAM,QAAQ,GAAG,MAAM,IAAI,CAAC,gBAAgB,CAAC,aAAa,CAAC,OAAO,CAAC,CAAC;YACpE,IAAI,QAAQ,EAAE,CAAC;gBACb,MAAM,OAAO,CAAC,IAAI,CAAC;oBACjB,cAAc,EAAE,OAAO,CAAC,cAAc;oBACtC,IAAI,EAAE,QAAQ;oBACd,gBAAgB,EAAE,OAAO,CAAC,EAAE;iBAC7B,CAAC,CAAC;YACL,CAAC;QACH,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,cAAM,CAAC,KAAK,CAAC,oCAAoC,OAAO,GAAG,EAAE,GAAG,CAAC,CAAC;YAClE,MAAM,GAAG,CAAC,CAAC,kBAAkB;QAC/B,CAAC;IACH,CAAC;CACF,CAAA;AAxCY,wDAAsB;AAO3B;IADL,IAAA,sBAAc,EAAC,gDAAwB,CAAC;;;;4DAiCxC;iCAvCU,sBAAsB;IAFlC,IAAA,iBAAU,GAAE;IACZ,IAAA,qBAAa,EAAC,EAAE,OAAO,EAAE,eAAe,EAAE,CAAC;IAIvC,WAAA,IAAA,aAAM,EAAC,yCAAkB,CAAC,CAAA;qCADQ,oCAAgB;GAF1C,sBAAsB,CAwClC"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=messaging-kafka.consumer.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"messaging-kafka.consumer.test.d.ts","sourceRoot":"","sources":["../src/messaging-kafka.consumer.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,129 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ /**
4
+ * MessagingKafkaConsumer tests - tests handleIncoming logic without Kafka
5
+ */
6
+ const messaging_kafka_consumer_1 = require("./messaging-kafka.consumer");
7
+ const messaging_service_1 = require("./messaging.service");
8
+ describe('MessagingKafkaConsumer', () => {
9
+ let messagingService;
10
+ let mockAdapter;
11
+ beforeEach(() => {
12
+ messagingService = new messaging_service_1.MessagingService({
13
+ customHandler: jest.fn().mockResolvedValue('Kafka reply'),
14
+ });
15
+ mockAdapter = {
16
+ channel: 'telegram',
17
+ parseIncoming: jest.fn(),
18
+ send: jest.fn().mockResolvedValue(undefined),
19
+ };
20
+ });
21
+ it('processes valid payload and sends reply', async () => {
22
+ const consumer = new messaging_kafka_consumer_1.MessagingKafkaConsumer(messagingService, [mockAdapter]);
23
+ const payload = {
24
+ message: {
25
+ value: Buffer.from(JSON.stringify({
26
+ message: {
27
+ id: '1',
28
+ channel: 'telegram',
29
+ conversationId: 'conv-1',
30
+ userId: 'u1',
31
+ text: 'Hello',
32
+ timestamp: new Date().toISOString(),
33
+ },
34
+ channel: 'telegram',
35
+ })),
36
+ },
37
+ };
38
+ await consumer.handleIncoming(payload);
39
+ expect(mockAdapter.send).toHaveBeenCalledWith({
40
+ conversationId: 'conv-1',
41
+ text: 'Kafka reply',
42
+ replyToMessageId: '1',
43
+ });
44
+ });
45
+ it('does nothing when message value is empty', async () => {
46
+ const consumer = new messaging_kafka_consumer_1.MessagingKafkaConsumer(messagingService, [mockAdapter]);
47
+ const payload = { message: { value: null } };
48
+ await consumer.handleIncoming(payload);
49
+ expect(mockAdapter.send).not.toHaveBeenCalled();
50
+ });
51
+ it('does nothing when message value is undefined', async () => {
52
+ const consumer = new messaging_kafka_consumer_1.MessagingKafkaConsumer(messagingService, [mockAdapter]);
53
+ const payload = { message: {} };
54
+ await consumer.handleIncoming(payload);
55
+ expect(mockAdapter.send).not.toHaveBeenCalled();
56
+ });
57
+ it('handles invalid JSON gracefully', async () => {
58
+ const consumer = new messaging_kafka_consumer_1.MessagingKafkaConsumer(messagingService, [mockAdapter]);
59
+ const payload = { message: { value: Buffer.from('not json') } };
60
+ await expect(consumer.handleIncoming(payload)).resolves.not.toThrow();
61
+ expect(mockAdapter.send).not.toHaveBeenCalled();
62
+ });
63
+ it('does not send when no adapter for channel', async () => {
64
+ const consumer = new messaging_kafka_consumer_1.MessagingKafkaConsumer(messagingService, [mockAdapter]);
65
+ const payload = {
66
+ message: {
67
+ value: Buffer.from(JSON.stringify({
68
+ message: {
69
+ id: '1',
70
+ channel: 'whatsapp',
71
+ conversationId: 'c1',
72
+ userId: 'u1',
73
+ text: 'Hi',
74
+ timestamp: new Date().toISOString(),
75
+ },
76
+ channel: 'whatsapp',
77
+ })),
78
+ },
79
+ };
80
+ await consumer.handleIncoming(payload);
81
+ expect(mockAdapter.send).not.toHaveBeenCalled();
82
+ });
83
+ it('throws when handleMessage fails to allow Kafka retry', async () => {
84
+ const failingService = new messaging_service_1.MessagingService({
85
+ customHandler: jest.fn().mockRejectedValue(new Error('Service error')),
86
+ });
87
+ const consumer = new messaging_kafka_consumer_1.MessagingKafkaConsumer(failingService, [mockAdapter]);
88
+ const payload = {
89
+ message: {
90
+ value: Buffer.from(JSON.stringify({
91
+ message: {
92
+ id: '1',
93
+ channel: 'telegram',
94
+ conversationId: 'c1',
95
+ userId: 'u1',
96
+ text: 'Hi',
97
+ timestamp: new Date().toISOString(),
98
+ },
99
+ channel: 'telegram',
100
+ })),
101
+ },
102
+ };
103
+ await expect(consumer.handleIncoming(payload)).rejects.toThrow('Service error');
104
+ });
105
+ it('does not send when handleMessage returns empty', async () => {
106
+ const emptyService = new messaging_service_1.MessagingService({
107
+ customHandler: jest.fn().mockResolvedValue(''),
108
+ });
109
+ const consumer = new messaging_kafka_consumer_1.MessagingKafkaConsumer(emptyService, [mockAdapter]);
110
+ const payload = {
111
+ message: {
112
+ value: Buffer.from(JSON.stringify({
113
+ message: {
114
+ id: '1',
115
+ channel: 'telegram',
116
+ conversationId: 'c1',
117
+ userId: 'u1',
118
+ text: 'Hi',
119
+ timestamp: new Date().toISOString(),
120
+ },
121
+ channel: 'telegram',
122
+ })),
123
+ },
124
+ };
125
+ await consumer.handleIncoming(payload);
126
+ expect(mockAdapter.send).not.toHaveBeenCalled();
127
+ });
128
+ });
129
+ //# sourceMappingURL=messaging-kafka.consumer.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"messaging-kafka.consumer.test.js","sourceRoot":"","sources":["../src/messaging-kafka.consumer.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,10 @@
1
+ /**
2
+ * Kafka messaging types - shared between producer and consumer
3
+ */
4
+ import type { IncomingMessage } from './types/message.types';
5
+ export declare const MESSAGING_INCOMING_TOPIC = "messaging.incoming";
6
+ export interface MessagingIncomingPayload {
7
+ message: IncomingMessage;
8
+ channel: string;
9
+ }
10
+ //# sourceMappingURL=messaging-kafka.types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"messaging-kafka.types.d.ts","sourceRoot":"","sources":["../src/messaging-kafka.types.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;AAE7D,eAAO,MAAM,wBAAwB,uBAAuB,CAAC;AAE7D,MAAM,WAAW,wBAAwB;IACvC,OAAO,EAAE,eAAe,CAAC;IACzB,OAAO,EAAE,MAAM,CAAC;CACjB"}
@@ -0,0 +1,5 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.MESSAGING_INCOMING_TOPIC = void 0;
4
+ exports.MESSAGING_INCOMING_TOPIC = 'messaging.incoming';
5
+ //# sourceMappingURL=messaging-kafka.types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"messaging-kafka.types.js","sourceRoot":"","sources":["../src/messaging-kafka.types.ts"],"names":[],"mappings":";;;AAKa,QAAA,wBAAwB,GAAG,oBAAoB,CAAC"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=messaging-kafka.types.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"messaging-kafka.types.test.d.ts","sourceRoot":"","sources":["../src/messaging-kafka.types.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,12 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ /**
4
+ * MessagingKafkaTypes - minimal test for exports
5
+ */
6
+ const messaging_kafka_types_1 = require("./messaging-kafka.types");
7
+ describe('messaging-kafka.types', () => {
8
+ it('MESSAGING_INCOMING_TOPIC is messaging.incoming', () => {
9
+ expect(messaging_kafka_types_1.MESSAGING_INCOMING_TOPIC).toBe('messaging.incoming');
10
+ });
11
+ });
12
+ //# sourceMappingURL=messaging-kafka.types.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"messaging-kafka.types.test.js","sourceRoot":"","sources":["../src/messaging-kafka.types.test.ts"],"names":[],"mappings":";;AAAA;;GAEG;AACH,mEAAmE;AAEnE,QAAQ,CAAC,uBAAuB,EAAE,GAAG,EAAE;IACrC,EAAE,CAAC,gDAAgD,EAAE,GAAG,EAAE;QACxD,MAAM,CAAC,gDAAwB,CAAC,CAAC,IAAI,CAAC,oBAAoB,CAAC,CAAC;IAC9D,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC"}
@@ -0,0 +1,27 @@
1
+ import type { Request, HazelResponse } from '@hazeljs/core';
2
+ import { MessagingService } from './messaging.service';
3
+ import type { IChannelAdapter } from './types/message.types';
4
+ export declare const MESSAGING_ADAPTERS: unique symbol;
5
+ export declare const MESSAGING_USE_KAFKA: unique symbol;
6
+ export declare const MESSAGING_KAFKA_PRODUCER: unique symbol;
7
+ export declare class MessagingController {
8
+ private readonly messagingService;
9
+ private adapters;
10
+ private useKafka;
11
+ private producer?;
12
+ constructor(messagingService: MessagingService, adapterList?: IChannelAdapter[], useKafka?: boolean, producer?: {
13
+ send: (topic: string, messages: {
14
+ key?: string;
15
+ value: string;
16
+ } | Array<{
17
+ key?: string;
18
+ value: string;
19
+ }>) => Promise<void>;
20
+ });
21
+ /** GET webhook - WhatsApp verification, etc. */
22
+ webhookGet(channel: string, req: Request, res: HazelResponse): Promise<void>;
23
+ /** Generic webhook - route by path param: POST /api/messaging/webhook/:channel */
24
+ webhookPost(channel: string, req: Request, res: HazelResponse): Promise<void>;
25
+ private normalizeMessages;
26
+ }
27
+ //# sourceMappingURL=messaging.controller.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"messaging.controller.d.ts","sourceRoot":"","sources":["../src/messaging.controller.ts"],"names":[],"mappings":"AAgBA,OAAO,KAAK,EAAE,OAAO,EAAE,aAAa,EAAE,MAAM,eAAe,CAAC;AAC5D,OAAO,EAAE,gBAAgB,EAAE,MAAM,qBAAqB,CAAC;AACvD,OAAO,KAAK,EAAE,eAAe,EAAmB,MAAM,uBAAuB,CAAC;AAG9E,eAAO,MAAM,kBAAkB,eAA+B,CAAC;AAC/D,eAAO,MAAM,mBAAmB,eAAgC,CAAC;AACjE,eAAO,MAAM,wBAAwB,eAAqC,CAAC;AAG3E,qBACa,mBAAmB;IAW5B,OAAO,CAAC,QAAQ,CAAC,gBAAgB;IAVnC,OAAO,CAAC,QAAQ,CAA+B;IAC/C,OAAO,CAAC,QAAQ,CAAU;IAC1B,OAAO,CAAC,QAAQ,CAAC,CAKf;gBAGiB,gBAAgB,EAAE,gBAAgB,EACvB,WAAW,GAAE,eAAe,EAAO,EAClC,QAAQ,UAAQ,EAE7C,QAAQ,CAAC,EAAE;QACT,IAAI,EAAE,CACJ,KAAK,EAAE,MAAM,EACb,QAAQ,EAAE;YAAE,GAAG,CAAC,EAAE,MAAM,CAAC;YAAC,KAAK,EAAE,MAAM,CAAA;SAAE,GAAG,KAAK,CAAC;YAAE,GAAG,CAAC,EAAE,MAAM,CAAC;YAAC,KAAK,EAAE,MAAM,CAAA;SAAE,CAAC,KAC/E,OAAO,CAAC,IAAI,CAAC,CAAC;KACpB;IAOH,gDAAgD;IAE1C,UAAU,CACQ,OAAO,EAAE,MAAM,EAC9B,GAAG,EAAE,OAAO,EACZ,GAAG,EAAE,aAAa,GACxB,OAAO,CAAC,IAAI,CAAC;IA8BhB,kFAAkF;IAE5E,WAAW,CACO,OAAO,EAAE,MAAM,EAC9B,GAAG,EAAE,OAAO,EACZ,GAAG,EAAE,aAAa,GACxB,OAAO,CAAC,IAAI,CAAC;IAwDhB,OAAO,CAAC,iBAAiB;CAI1B"}
@@ -0,0 +1,151 @@
1
+ "use strict";
2
+ var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
3
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
4
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
5
+ else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
6
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
7
+ };
8
+ var __metadata = (this && this.__metadata) || function (k, v) {
9
+ if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
10
+ };
11
+ var __param = (this && this.__param) || function (paramIndex, decorator) {
12
+ return function (target, key) { decorator(target, key, paramIndex); }
13
+ };
14
+ Object.defineProperty(exports, "__esModule", { value: true });
15
+ exports.MessagingController = exports.MESSAGING_KAFKA_PRODUCER = exports.MESSAGING_USE_KAFKA = exports.MESSAGING_ADAPTERS = void 0;
16
+ /**
17
+ * Messaging Controller - Webhook endpoints for each channel
18
+ * In Kafka mode: produces to topic and returns 200 immediately (async processing)
19
+ * In sync mode: processes inline and responds
20
+ */
21
+ const core_1 = require("@hazeljs/core");
22
+ const messaging_service_1 = require("./messaging.service");
23
+ const messaging_kafka_types_1 = require("./messaging-kafka.types");
24
+ exports.MESSAGING_ADAPTERS = Symbol('MESSAGING_ADAPTERS');
25
+ exports.MESSAGING_USE_KAFKA = Symbol('MESSAGING_USE_KAFKA');
26
+ exports.MESSAGING_KAFKA_PRODUCER = Symbol('MESSAGING_KAFKA_PRODUCER');
27
+ const CHANNEL_PARAM = 'channel';
28
+ let MessagingController = class MessagingController {
29
+ constructor(messagingService, adapterList = [], useKafka = false, producer) {
30
+ this.messagingService = messagingService;
31
+ this.adapters = new Map(adapterList.map((a) => [a.channel, a]));
32
+ this.useKafka = useKafka;
33
+ this.producer = producer;
34
+ }
35
+ /** GET webhook - WhatsApp verification, etc. */
36
+ async webhookGet(channel, req, res) {
37
+ if (channel !== 'whatsapp') {
38
+ res.status(404).setHeader('Content-Type', 'text/plain');
39
+ res.write('Not found');
40
+ res.end();
41
+ return;
42
+ }
43
+ const adapter = this.adapters.get('whatsapp');
44
+ if (!adapter?.verifyWebhook) {
45
+ res.status(404).setHeader('Content-Type', 'text/plain');
46
+ res.write('Not found');
47
+ res.end();
48
+ return;
49
+ }
50
+ const q = req.query;
51
+ if (adapter.verifyWebhook(q, req.headers)) {
52
+ const challenge = q['hub.challenge'];
53
+ if (challenge) {
54
+ res.status(200);
55
+ res.setHeader('Content-Type', 'text/plain');
56
+ res.write(challenge);
57
+ res.end();
58
+ return;
59
+ }
60
+ }
61
+ res.status(403).setHeader('Content-Type', 'text/plain');
62
+ res.write('Verification failed');
63
+ res.end();
64
+ }
65
+ /** Generic webhook - route by path param: POST /api/messaging/webhook/:channel */
66
+ async webhookPost(channel, req, res) {
67
+ const adapter = this.adapters.get(channel);
68
+ if (!adapter) {
69
+ throw new core_1.BadRequestException(`Unsupported channel: ${channel}`);
70
+ }
71
+ let payload;
72
+ try {
73
+ const body = req.body;
74
+ payload = typeof body === 'object' && body !== null ? body : {};
75
+ }
76
+ catch {
77
+ payload = {};
78
+ }
79
+ const messages = this.normalizeMessages(adapter.parseIncoming(payload));
80
+ if (messages.length === 0) {
81
+ res.status(200).json({ ok: true });
82
+ return;
83
+ }
84
+ if (this.useKafka && this.producer) {
85
+ // Async: produce to Kafka, return immediately (horizontally scalable)
86
+ for (const msg of messages) {
87
+ try {
88
+ const payload = { message: msg, channel };
89
+ await this.producer.send(messaging_kafka_types_1.MESSAGING_INCOMING_TOPIC, {
90
+ key: msg.sessionId ?? msg.conversationId,
91
+ value: JSON.stringify(payload),
92
+ });
93
+ }
94
+ catch (err) {
95
+ core_1.logger.error(`Messaging Kafka produce error for ${channel}:`, err);
96
+ }
97
+ }
98
+ res.status(200).json({ ok: true });
99
+ return;
100
+ }
101
+ // Sync: process inline
102
+ for (const msg of messages) {
103
+ try {
104
+ const response = await this.messagingService.handleMessage(msg);
105
+ if (response) {
106
+ await adapter.send({
107
+ conversationId: msg.conversationId,
108
+ text: response,
109
+ replyToMessageId: msg.id,
110
+ });
111
+ }
112
+ }
113
+ catch (err) {
114
+ core_1.logger.error(`Messaging webhook error for ${channel}:`, err);
115
+ }
116
+ }
117
+ res.status(200).json({ ok: true });
118
+ }
119
+ normalizeMessages(result) {
120
+ if (!result)
121
+ return [];
122
+ return Array.isArray(result) ? result : [result];
123
+ }
124
+ };
125
+ exports.MessagingController = MessagingController;
126
+ __decorate([
127
+ (0, core_1.Get)(`/webhook/:${CHANNEL_PARAM}`),
128
+ __param(0, (0, core_1.Param)(CHANNEL_PARAM)),
129
+ __param(1, (0, core_1.Req)()),
130
+ __param(2, (0, core_1.Res)()),
131
+ __metadata("design:type", Function),
132
+ __metadata("design:paramtypes", [String, Object, Object]),
133
+ __metadata("design:returntype", Promise)
134
+ ], MessagingController.prototype, "webhookGet", null);
135
+ __decorate([
136
+ (0, core_1.Post)(`/webhook/:${CHANNEL_PARAM}`),
137
+ __param(0, (0, core_1.Param)(CHANNEL_PARAM)),
138
+ __param(1, (0, core_1.Req)()),
139
+ __param(2, (0, core_1.Res)()),
140
+ __metadata("design:type", Function),
141
+ __metadata("design:paramtypes", [String, Object, Object]),
142
+ __metadata("design:returntype", Promise)
143
+ ], MessagingController.prototype, "webhookPost", null);
144
+ exports.MessagingController = MessagingController = __decorate([
145
+ (0, core_1.Controller)('api/messaging'),
146
+ __param(1, (0, core_1.Inject)(exports.MESSAGING_ADAPTERS)),
147
+ __param(2, (0, core_1.Inject)(exports.MESSAGING_USE_KAFKA)),
148
+ __param(3, (0, core_1.Inject)(exports.MESSAGING_KAFKA_PRODUCER)),
149
+ __metadata("design:paramtypes", [messaging_service_1.MessagingService, Array, Object, Object])
150
+ ], MessagingController);
151
+ //# sourceMappingURL=messaging.controller.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"messaging.controller.js","sourceRoot":"","sources":["../src/messaging.controller.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=messaging.controller.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"messaging.controller.test.d.ts","sourceRoot":"","sources":["../src/messaging.controller.test.ts"],"names":[],"mappings":""}