@bolt.tech/kafka-utils 1.0.12 → 2.0.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 (40) hide show
  1. package/build/dependencies/paramstore/paramstore.d.ts +6 -0
  2. package/build/dependencies/paramstore/paramstore.js +27 -0
  3. package/build/index.d.ts +9 -0
  4. package/build/index.js +144 -0
  5. package/build/kafkaServer.d.ts +11 -0
  6. package/build/kafkaServer.js +80 -0
  7. package/build/store/interfaces/assestTriggerNotification.interface.d.ts +27 -0
  8. package/build/store/interfaces/assestTriggerNotification.interface.js +2 -0
  9. package/build/store/interfaces/authEmailNotification.interface.d.ts +11 -0
  10. package/build/store/interfaces/authEmailNotification.interface.js +2 -0
  11. package/build/store/interfaces/boltChargerNotificationV2.interface.d.ts +20 -0
  12. package/build/store/interfaces/boltChargerNotificationV2.interface.js +2 -0
  13. package/build/store/interfaces/kafkaSecret.interface.d.ts +5 -0
  14. package/build/store/interfaces/kafkaSecret.interface.js +2 -0
  15. package/build/store/interfaces/notification.interface.d.ts +35 -0
  16. package/build/store/interfaces/notification.interface.js +2 -0
  17. package/build/store/interfaces/whatsappPayload.interface.d.ts +6 -0
  18. package/build/store/interfaces/whatsappPayload.interface.js +2 -0
  19. package/build/store/schemas/proto/assetTriggersNotification.proto +36 -0
  20. package/build/store/schemas/proto/boltNotification.proto +23 -0
  21. package/build/store/schemas/proto/commonNotification.proto +36 -0
  22. package/build/store/types/notification.type.d.ts +2 -0
  23. package/build/store/types/notification.type.js +2 -0
  24. package/build/utils/kafka/brokers.kafka.d.ts +3 -0
  25. package/build/utils/kafka/brokers.kafka.js +23 -0
  26. package/build/utils/kafka/config.kafka.d.ts +7 -0
  27. package/build/utils/kafka/config.kafka.js +29 -0
  28. package/build/utils/kafka/producer.kafka.d.ts +8 -0
  29. package/build/utils/kafka/producer.kafka.js +52 -0
  30. package/build/utils/kafka/publisher.kafka.d.ts +6 -0
  31. package/build/utils/kafka/publisher.kafka.js +27 -0
  32. package/build/utils/kafka/topicMap.kafka.d.ts +3 -0
  33. package/build/utils/kafka/topicMap.kafka.js +10 -0
  34. package/build/utils/schemaRegistry/notificationSchema.registry.d.ts +16 -0
  35. package/build/utils/schemaRegistry/notificationSchema.registry.js +68 -0
  36. package/build/utils/schemaRegistry/pickSchema.d.ts +7 -0
  37. package/build/utils/schemaRegistry/pickSchema.js +37 -0
  38. package/build/utils/schemaRegistry/registry.util.d.ts +9 -0
  39. package/build/utils/schemaRegistry/registry.util.js +24 -0
  40. package/package.json +1 -1
@@ -0,0 +1,6 @@
1
+ export declare class ParamStore {
2
+ private PARAMSTORE_PATH;
3
+ private NODE_ENV_LOCAL;
4
+ constructor(PARAMSTORE_PATH: string, NODE_ENV_LOCAL: string);
5
+ getParams(): Promise<void>;
6
+ }
@@ -0,0 +1,27 @@
1
+ "use strict";
2
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
3
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
4
+ return new (P || (P = Promise))(function (resolve, reject) {
5
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
6
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
7
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
8
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
9
+ });
10
+ };
11
+ Object.defineProperty(exports, "__esModule", { value: true });
12
+ exports.ParamStore = void 0;
13
+ const bolt_paramstore_1 = require("bolt-paramstore");
14
+ class ParamStore {
15
+ constructor(PARAMSTORE_PATH, NODE_ENV_LOCAL) {
16
+ this.PARAMSTORE_PATH = PARAMSTORE_PATH;
17
+ this.NODE_ENV_LOCAL = NODE_ENV_LOCAL;
18
+ }
19
+ getParams() {
20
+ return __awaiter(this, void 0, void 0, function* () {
21
+ yield (0, bolt_paramstore_1.getParameters)(`/${this.PARAMSTORE_PATH}/common/`);
22
+ if (this.NODE_ENV_LOCAL === "TRUE")
23
+ yield (0, bolt_paramstore_1.getParameters)(`/local/${this.PARAMSTORE_PATH}/`);
24
+ });
25
+ }
26
+ }
27
+ exports.ParamStore = ParamStore;
@@ -0,0 +1,9 @@
1
+ import { notificationType } from './store/types/notification.type';
2
+ import { IUser, IMessage, ISmsObj, IOneSignalPayload, IAttachment } from './store/interfaces/notification.interface';
3
+ import { IWhatsappPayload } from './store/interfaces/whatsappPayload.interface';
4
+ export declare function initialiseNotification(paramStorePath: string, nodeEnvLocal: string, serviceName: string, notificationType: notificationType): Promise<void>;
5
+ export declare function sendEmailNotifications(user: IUser, message: IMessage, attachment?: IAttachment): Promise<void>;
6
+ export declare function sendSmsNotifications(user: IUser, message: IMessage, smsObj: ISmsObj): Promise<void>;
7
+ export declare function sendPushNotification(user: IUser, message: IMessage, appId: string, oneSignalPayload: IOneSignalPayload): Promise<void>;
8
+ export declare function sendInAppNotification(user: IUser, message: IMessage, appId: string): Promise<void>;
9
+ export declare function sendWhatsappNotification(whatsappPayload: IWhatsappPayload): Promise<void>;
package/build/index.js ADDED
@@ -0,0 +1,144 @@
1
+ "use strict";
2
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
3
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
4
+ return new (P || (P = Promise))(function (resolve, reject) {
5
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
6
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
7
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
8
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
9
+ });
10
+ };
11
+ Object.defineProperty(exports, "__esModule", { value: true });
12
+ exports.initialiseNotification = initialiseNotification;
13
+ exports.sendEmailNotifications = sendEmailNotifications;
14
+ exports.sendSmsNotifications = sendSmsNotifications;
15
+ exports.sendPushNotification = sendPushNotification;
16
+ exports.sendInAppNotification = sendInAppNotification;
17
+ exports.sendWhatsappNotification = sendWhatsappNotification;
18
+ const notificationSchema_registry_1 = require("./utils/schemaRegistry/notificationSchema.registry");
19
+ const getTopic = require('./utils/kafka/topicMap.kafka');
20
+ const publishToKafka = require('./utils/kafka/publisher.kafka');
21
+ let currentNotificationType;
22
+ function initialiseNotification(paramStorePath, nodeEnvLocal, serviceName, notificationType) {
23
+ return __awaiter(this, void 0, void 0, function* () {
24
+ try {
25
+ currentNotificationType = notificationType;
26
+ const KafkaServer = require('./kafkaServer');
27
+ const kafkaInstance = new KafkaServer();
28
+ yield kafkaInstance.setupKafka(paramStorePath, nodeEnvLocal, serviceName, notificationType);
29
+ yield kafkaInstance.setupShutdownHandlers();
30
+ console.log("---------------------------------------------");
31
+ console.log("Notification utility is ready.");
32
+ console.log("---------------------------------------------");
33
+ }
34
+ catch (e) {
35
+ console.log("🔴 kafka-utils: initialiseNotification", e);
36
+ }
37
+ });
38
+ }
39
+ /* publish notifications to kafka */
40
+ function sendNotificationToKafka(userId, payload) {
41
+ return __awaiter(this, void 0, void 0, function* () {
42
+ try {
43
+ const instance = notificationSchema_registry_1.NotificationSchema.getInstance();
44
+ if (!instance) {
45
+ throw new Error("Notification schema is not initialised or Schema Registry is not connected.");
46
+ }
47
+ if (!notificationSchema_registry_1.NotificationSchema) {
48
+ throw new Error("Notification schema is not initialised");
49
+ }
50
+ const topic = getTopic(currentNotificationType);
51
+ const schemaId = yield instance.getSchemaId();
52
+ yield publishToKafka(topic, schemaId, { key: userId, value: payload });
53
+ console.log(`✅ Notification sent to user: ${userId}`);
54
+ }
55
+ catch (error) {
56
+ console.log("🔴 kafka-utils: sendNotificationToKafka", error);
57
+ }
58
+ });
59
+ }
60
+ /* send email notifications to users */
61
+ function sendEmailNotifications(user, message, attachment) {
62
+ return __awaiter(this, void 0, void 0, function* () {
63
+ if (user.emailIds.length === 0) {
64
+ console.log("No email addresses provided");
65
+ return;
66
+ }
67
+ const basePayload = {
68
+ user: Object.assign(Object.assign({}, user), { emailIds: user.emailIds }),
69
+ message,
70
+ Attachment: attachment || {}
71
+ };
72
+ for (const emailId of user.emailIds) {
73
+ const payload = Object.assign(Object.assign({}, basePayload), { user: Object.assign(Object.assign({}, basePayload.user), { emailIds: [emailId] }) });
74
+ yield sendNotificationToKafka(emailId, payload);
75
+ }
76
+ });
77
+ }
78
+ /* send sms notifications to users */
79
+ function sendSmsNotifications(user, message, smsObj) {
80
+ return __awaiter(this, void 0, void 0, function* () {
81
+ if (user.phoneNumbers.length === 0) {
82
+ console.log("No phone numbers provided");
83
+ return;
84
+ }
85
+ const basePayload = {
86
+ user: Object.assign(Object.assign({}, user), { phoneNumbers: user.phoneNumbers }),
87
+ message,
88
+ smsObj,
89
+ };
90
+ for (const phoneNumber of user.phoneNumbers) {
91
+ const payload = Object.assign(Object.assign({}, basePayload), { user: Object.assign(Object.assign({}, basePayload.user), { phoneNumbers: [phoneNumber] }) });
92
+ yield sendNotificationToKafka(phoneNumber, payload);
93
+ }
94
+ });
95
+ }
96
+ /* send push notifications to users */
97
+ function sendPushNotification(user, message, appId, oneSignalPayload) {
98
+ return __awaiter(this, void 0, void 0, function* () {
99
+ if (!user.pushNotificationUserId) {
100
+ console.log("No push notification user ID provided");
101
+ return;
102
+ }
103
+ const payload = {
104
+ user: Object.assign(Object.assign({}, user), { pushNotificationUserId: user.pushNotificationUserId }),
105
+ message,
106
+ appId,
107
+ smsObj: {},
108
+ oneSignalPayload,
109
+ };
110
+ yield sendNotificationToKafka(user.pushNotificationUserId, payload);
111
+ });
112
+ }
113
+ /* send in-app notifications to users */
114
+ function sendInAppNotification(user, message, appId) {
115
+ return __awaiter(this, void 0, void 0, function* () {
116
+ if (!user.inAppNotificationUserId) {
117
+ console.log("No in-app notification user ID provided");
118
+ return;
119
+ }
120
+ const payload = {
121
+ user: Object.assign(Object.assign({}, user), { inAppNotificationUserId: user.inAppNotificationUserId }),
122
+ message,
123
+ appId,
124
+ smsObj: {},
125
+ oneSignalPayload: {},
126
+ };
127
+ yield sendNotificationToKafka(user.inAppNotificationUserId, payload);
128
+ });
129
+ }
130
+ /* send whatsapp notifications to users */
131
+ function sendWhatsappNotification(whatsappPayload) {
132
+ return __awaiter(this, void 0, void 0, function* () {
133
+ var _a;
134
+ if (!((_a = whatsappPayload === null || whatsappPayload === void 0 ? void 0 : whatsappPayload.phone) === null || _a === void 0 ? void 0 : _a.length)) {
135
+ console.log("No phone number provided");
136
+ return;
137
+ }
138
+ const payload = {
139
+ user: { phoneNumbers: [whatsappPayload.phone] },
140
+ whatsappPayload,
141
+ };
142
+ yield sendNotificationToKafka(whatsappPayload.phone, payload);
143
+ });
144
+ }
@@ -0,0 +1,11 @@
1
+ import { notificationType } from './store/types/notification.type';
2
+ declare class KafkaServer {
3
+ private paramStore;
4
+ private schemaRegistry;
5
+ private notificationSchema;
6
+ constructor();
7
+ setupKafka(paramStorePath: string, nodeEnvLocal: string, serviceName: string, notificationType: notificationType): Promise<void>;
8
+ setupShutdownHandlers(): void;
9
+ private handleShutdown;
10
+ }
11
+ export = KafkaServer;
@@ -0,0 +1,80 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || function (mod) {
19
+ if (mod && mod.__esModule) return mod;
20
+ var result = {};
21
+ if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
22
+ __setModuleDefault(result, mod);
23
+ return result;
24
+ };
25
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
26
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
27
+ return new (P || (P = Promise))(function (resolve, reject) {
28
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
29
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
30
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
31
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
32
+ });
33
+ };
34
+ const producer_kafka_1 = require("./utils/kafka/producer.kafka");
35
+ const config_kafka_1 = require("./utils/kafka/config.kafka");
36
+ const dotenv = __importStar(require("dotenv"));
37
+ const paramstore_1 = require("./dependencies/paramstore/paramstore");
38
+ const notificationSchema_registry_1 = require("./utils/schemaRegistry/notificationSchema.registry");
39
+ const registry_util_1 = require("./utils/schemaRegistry/registry.util");
40
+ const getKafkaBrokers = require('./utils/kafka/brokers.kafka');
41
+ class KafkaServer {
42
+ constructor() {
43
+ this.paramStore = null;
44
+ this.schemaRegistry = null;
45
+ this.notificationSchema = null;
46
+ this.handleShutdown = () => __awaiter(this, void 0, void 0, function* () {
47
+ console.log('Shutting down Kafka Server...');
48
+ if (producer_kafka_1.KafkaProducer) {
49
+ yield producer_kafka_1.KafkaProducer.shutdown();
50
+ }
51
+ process.exit(0);
52
+ });
53
+ dotenv.config();
54
+ }
55
+ setupKafka(paramStorePath, nodeEnvLocal, serviceName, notificationType) {
56
+ return __awaiter(this, void 0, void 0, function* () {
57
+ // Retrieve values from paramstore
58
+ this.paramStore = new paramstore_1.ParamStore(paramStorePath, nodeEnvLocal);
59
+ yield this.paramStore.getParams();
60
+ // Get Kafka brokers
61
+ const kafkaConnectionDetails = yield getKafkaBrokers();
62
+ const kafka = config_kafka_1.KafkaConfig.getConfig(kafkaConnectionDetails, serviceName);
63
+ // Connect to Kafka
64
+ yield producer_kafka_1.KafkaProducer.connect(kafka);
65
+ // Connect to Schema Registry and wait for completion
66
+ console.log('🔵 Connecting to Schema Registry...');
67
+ yield registry_util_1.SchemaRegistryS.connect(process.env.SCHEMA_REGISTRY_URL);
68
+ this.schemaRegistry = registry_util_1.SchemaRegistryS.getInstance();
69
+ console.log('✅ Schema Registry connected.');
70
+ // Register Notification schema
71
+ this.notificationSchema = notificationSchema_registry_1.NotificationSchema.getInstance();
72
+ yield this.notificationSchema.register(notificationType);
73
+ });
74
+ }
75
+ setupShutdownHandlers() {
76
+ process.on('SIGINT', this.handleShutdown);
77
+ process.on('SIGTERM', this.handleShutdown);
78
+ }
79
+ }
80
+ module.exports = KafkaServer;
@@ -0,0 +1,27 @@
1
+ export interface IAssetsTriggerNotification {
2
+ user?: IUser;
3
+ message?: IMessage;
4
+ appId?: string;
5
+ smsObj?: ISmsObj;
6
+ oneSignalPayload?: IOneSignalPayload;
7
+ }
8
+ export interface IUser {
9
+ inAppNotificationUserId?: string;
10
+ pushNotificationUserId?: string;
11
+ emailIds?: string[];
12
+ phoneNumbers?: string[];
13
+ }
14
+ export interface IMessage {
15
+ body?: string;
16
+ subject?: string;
17
+ priority?: number;
18
+ }
19
+ export interface ISmsObj {
20
+ smsType?: string;
21
+ templateId?: string;
22
+ }
23
+ export interface IOneSignalPayload {
24
+ alert?: string;
25
+ sos?: boolean;
26
+ vin?: string;
27
+ }
@@ -0,0 +1,2 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
@@ -0,0 +1,11 @@
1
+ export interface IAuthNotificationSchema {
2
+ user?: IUser;
3
+ message?: IMessage;
4
+ }
5
+ export interface IUser {
6
+ emailIds: string[];
7
+ }
8
+ export interface IMessage {
9
+ body?: string;
10
+ subject?: string;
11
+ }
@@ -0,0 +1,2 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
@@ -0,0 +1,20 @@
1
+ export interface IBoltChargerNotificationV2 {
2
+ user?: IUser;
3
+ message?: IMessage;
4
+ appId?: string;
5
+ smsObj?: ISmsObj;
6
+ }
7
+ export interface IUser {
8
+ pushNotificationUserId?: string;
9
+ inAppNotificationUserId?: string;
10
+ phoneNumbers: string[];
11
+ emailIds: string[];
12
+ }
13
+ export interface IMessage {
14
+ body?: string;
15
+ subject?: string;
16
+ }
17
+ export interface ISmsObj {
18
+ smsType?: string;
19
+ templateId?: string;
20
+ }
@@ -0,0 +1,2 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
@@ -0,0 +1,5 @@
1
+ export interface IKafkaSecret {
2
+ username: string;
3
+ password: string;
4
+ brokers: string[];
5
+ }
@@ -0,0 +1,2 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
@@ -0,0 +1,35 @@
1
+ export interface IUser {
2
+ inAppNotificationUserId?: string;
3
+ pushNotificationUserId?: string;
4
+ emailIds?: string[];
5
+ phoneNumbers?: string[];
6
+ }
7
+ export interface IMessage {
8
+ body?: string;
9
+ subject?: string;
10
+ priority?: number;
11
+ attachments?: Uint8Array[];
12
+ html?: string;
13
+ }
14
+ export interface ISmsObj {
15
+ smsType?: string;
16
+ templateId?: string;
17
+ }
18
+ export interface IOneSignalPayload {
19
+ alert?: string;
20
+ sos?: boolean;
21
+ vin?: string;
22
+ }
23
+ export interface IAttachment {
24
+ filename?: string;
25
+ filetype?: string;
26
+ content?: Uint8Array;
27
+ }
28
+ export interface INotification {
29
+ user?: IUser;
30
+ message?: IMessage;
31
+ appId?: string;
32
+ smsObj?: ISmsObj;
33
+ oneSignalPayload?: IOneSignalPayload;
34
+ Attachment?: IAttachment;
35
+ }
@@ -0,0 +1,2 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
@@ -0,0 +1,6 @@
1
+ export interface IWhatsappPayload {
2
+ name: string;
3
+ phone: string;
4
+ template_name: string;
5
+ template_params: Record<string, string>;
6
+ }
@@ -0,0 +1,2 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
@@ -0,0 +1,36 @@
1
+ syntax = "proto3";
2
+
3
+ message Notification {
4
+ message User {
5
+ string inAppNotificationUserId = 1;
6
+ string pushNotificationUserId = 2;
7
+ repeated string emailIds = 3;
8
+ repeated string phoneNumbers = 4;
9
+ }
10
+ message Message {
11
+ string body = 1;
12
+ string subject = 2;
13
+ int32 priority = 3;
14
+ repeated bytes attachments = 4;
15
+ string html = 5;
16
+ }
17
+ message SmsObj {
18
+ string smsType = 1;
19
+ string templateId = 2;
20
+ }
21
+ message OneSignalPayload {
22
+ string alert = 1;
23
+ bool sos = 2;
24
+ string vin = 3;
25
+ }
26
+ message Attachment {
27
+ string filename = 1;
28
+ string filetype = 2;
29
+ bytes content = 3;
30
+ }
31
+ User user = 1;
32
+ Message message = 2;
33
+ string appId = 3;
34
+ SmsObj smsObj = 4;
35
+ OneSignalPayload oneSignalPayload = 6;
36
+ }
@@ -0,0 +1,23 @@
1
+ syntax = "proto3";
2
+
3
+ message BoltNotification {
4
+ optional User user = 1;
5
+ optional Message message = 2;
6
+ optional string appId = 4;
7
+ optional SmsObj smsObj = 5;
8
+
9
+ message User {
10
+ optional string pushNotificationUserId = 3;
11
+ optional string inAppNotificationUserId = 4;
12
+ repeated string phoneNumbers = 5;
13
+ repeated string emailIds = 6;
14
+ }
15
+ message Message {
16
+ optional string body = 1;
17
+ optional string subject = 2;
18
+ }
19
+ message SmsObj {
20
+ optional string smsType = 1;
21
+ optional string templateId = 2;
22
+ }
23
+ }
@@ -0,0 +1,36 @@
1
+ syntax = "proto3";
2
+
3
+ message AssetsTriggerNotification {
4
+ optional User user = 1;
5
+ optional Message message = 2;
6
+ optional string appId = 3;
7
+ optional SmsObj smsObj = 4;
8
+ optional OneSignalPayload oneSignalPayload = 6;
9
+
10
+ message User {
11
+ optional string inAppNotificationUserId = 1;
12
+ optional string pushNotificationUserId = 2;
13
+ repeated string emailIds = 3;
14
+ repeated string phoneNumbers = 4;
15
+ }
16
+ message Message {
17
+ optional string body = 1;
18
+ optional string subject = 2;
19
+ optional int32 priority = 3;
20
+ }
21
+ message SmsObj {
22
+ optional string smsType = 1;
23
+ optional string templateId = 2;
24
+ }
25
+ message OneSignalPayload {
26
+ optional string alert = 1;
27
+ optional bool sos = 2;
28
+ optional string vin = 3;
29
+ }
30
+ message WhatsappPayload {
31
+ optional string name = 1;
32
+ optional string phone = 2;
33
+ optional string template_name = 3;
34
+ map<string, string> template_params = 4;
35
+ }
36
+ }
@@ -0,0 +1,2 @@
1
+ /** For three different topics and corresponding schemas */
2
+ export type notificationType = "bolt" | "asset-triggers" | "common";
@@ -0,0 +1,2 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
@@ -0,0 +1,3 @@
1
+ import { IKafkaSecret } from '../../store/interfaces/kafkaSecret.interface';
2
+ declare function getKafkaBrokers(): Promise<IKafkaSecret>;
3
+ export = getKafkaBrokers;
@@ -0,0 +1,23 @@
1
+ "use strict";
2
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
3
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
4
+ return new (P || (P = Promise))(function (resolve, reject) {
5
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
6
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
7
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
8
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
9
+ });
10
+ };
11
+ const bolt_paramstore_1 = require("bolt-paramstore");
12
+ function getKafkaBrokers() {
13
+ return __awaiter(this, void 0, void 0, function* () {
14
+ const slug = process.env.NODE_ENV_LOCAL === "TRUE" ? "KAFKA_CREDENTIALS_EXTERNAL" : "KAFKA_CREDENTIALS";
15
+ const config = yield (0, bolt_paramstore_1.getSecret)(`${process.env.PARAMSTORE_PATH}/common/${slug}`);
16
+ if (!config.brokers) {
17
+ throw new Error('Kafka brokers configuration not found.');
18
+ }
19
+ config.brokers = JSON.parse(config.brokers);
20
+ return config;
21
+ });
22
+ }
23
+ module.exports = getKafkaBrokers;
@@ -0,0 +1,7 @@
1
+ import { Kafka } from 'kafkajs';
2
+ import { IKafkaSecret } from '../../store/interfaces/kafkaSecret.interface';
3
+ export declare class KafkaConfig {
4
+ private static config;
5
+ private constructor();
6
+ static getConfig(config: IKafkaSecret, clientId: string): Kafka;
7
+ }
@@ -0,0 +1,29 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.KafkaConfig = void 0;
7
+ const dotenv_1 = __importDefault(require("dotenv"));
8
+ const kafkajs_1 = require("kafkajs");
9
+ dotenv_1.default.config();
10
+ class KafkaConfig {
11
+ constructor() { }
12
+ static getConfig(config, clientId) {
13
+ if (!this.config) {
14
+ const isExternal = process.env.NODE_ENV_LOCAL === "TRUE"; // ← Add this line
15
+ this.config = new kafkajs_1.Kafka({
16
+ clientId: clientId,
17
+ brokers: config.brokers,
18
+ sasl: {
19
+ mechanism: "scram-sha-512",
20
+ username: config.username,
21
+ password: config.password
22
+ },
23
+ ssl: isExternal ? { rejectUnauthorized: false } : false
24
+ });
25
+ }
26
+ return this.config;
27
+ }
28
+ }
29
+ exports.KafkaConfig = KafkaConfig;
@@ -0,0 +1,8 @@
1
+ import { Kafka, Producer } from 'kafkajs';
2
+ export declare class KafkaProducer {
3
+ private static producer;
4
+ private constructor();
5
+ static connect(kafka: Kafka): Promise<void>;
6
+ static getProducer(): Promise<Producer>;
7
+ static shutdown(): Promise<void>;
8
+ }
@@ -0,0 +1,52 @@
1
+ "use strict";
2
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
3
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
4
+ return new (P || (P = Promise))(function (resolve, reject) {
5
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
6
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
7
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
8
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
9
+ });
10
+ };
11
+ Object.defineProperty(exports, "__esModule", { value: true });
12
+ exports.KafkaProducer = void 0;
13
+ class KafkaProducer {
14
+ constructor() { }
15
+ static connect(kafka) {
16
+ return __awaiter(this, void 0, void 0, function* () {
17
+ try {
18
+ if (this.producer)
19
+ return;
20
+ this.producer = kafka.producer();
21
+ yield this.producer.connect();
22
+ }
23
+ catch (error) {
24
+ console.log(error);
25
+ }
26
+ });
27
+ }
28
+ static getProducer() {
29
+ return __awaiter(this, void 0, void 0, function* () {
30
+ try {
31
+ if (!this.producer)
32
+ throw new Error("Producer not connected");
33
+ return this.producer;
34
+ }
35
+ catch (error) {
36
+ console.log('KafkaProducer: error while connecting', error);
37
+ throw error;
38
+ }
39
+ });
40
+ }
41
+ static shutdown() {
42
+ return __awaiter(this, void 0, void 0, function* () {
43
+ try {
44
+ yield this.producer.disconnect();
45
+ }
46
+ catch (error) {
47
+ console.log('KafkaProducer: error while disconnecting', error);
48
+ }
49
+ });
50
+ }
51
+ }
52
+ exports.KafkaProducer = KafkaProducer;
@@ -0,0 +1,6 @@
1
+ interface KafkaMessage {
2
+ key: string;
3
+ value: any;
4
+ }
5
+ declare function publishToKafka(topic: string, schemaId: number, message: KafkaMessage): Promise<void>;
6
+ export = publishToKafka;
@@ -0,0 +1,27 @@
1
+ "use strict";
2
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
3
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
4
+ return new (P || (P = Promise))(function (resolve, reject) {
5
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
6
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
7
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
8
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
9
+ });
10
+ };
11
+ const registry_util_1 = require("./../schemaRegistry/registry.util");
12
+ const producer_kafka_1 = require("./producer.kafka");
13
+ function publishToKafka(topic, schemaId, message) {
14
+ return __awaiter(this, void 0, void 0, function* () {
15
+ try {
16
+ const encodedMessage = yield registry_util_1.SchemaRegistryS.getInstance().encode(schemaId, message.value);
17
+ const payload = { topic, messages: [{ key: message.key, value: encodedMessage }] };
18
+ const producer = yield producer_kafka_1.KafkaProducer.getProducer();
19
+ yield producer.send(payload);
20
+ console.log(`✅ Published to kafka for key: ${message.key}`);
21
+ }
22
+ catch (e) {
23
+ console.log(`🔴 publishToKafka Error: ${message}`, e);
24
+ }
25
+ });
26
+ }
27
+ module.exports = publishToKafka;
@@ -0,0 +1,3 @@
1
+ import { notificationType } from '../../store/types/notification.type';
2
+ declare function getTopic(type: notificationType): string;
3
+ export = getTopic;
@@ -0,0 +1,10 @@
1
+ "use strict";
2
+ const typeTopicMap = {
3
+ "common": "COMMON_NOTIFICATIONS",
4
+ "asset-triggers": "ASSET_TRIGGER_NOTIFICATIONS",
5
+ "bolt": "BOLT_CHARGERS_NOTIFICATIONS"
6
+ };
7
+ function getTopic(type) {
8
+ return typeTopicMap[type];
9
+ }
10
+ module.exports = getTopic;
@@ -0,0 +1,16 @@
1
+ import { notificationType } from '../../store/types/notification.type';
2
+ export declare class NotificationSchema {
3
+ private static instance;
4
+ private registry;
5
+ private registeredSchemaId;
6
+ private notificationType;
7
+ private constructor();
8
+ static getInstance(): NotificationSchema;
9
+ register(notificationType: notificationType): Promise<void>;
10
+ getSchemaId(): Promise<number>;
11
+ /**
12
+ * Reads schema from protobuf file and stringifies it. Will throw an error in case proto file has multiple message
13
+ * @returns Stringified schema
14
+ */
15
+ private getSchema;
16
+ }
@@ -0,0 +1,68 @@
1
+ "use strict";
2
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
3
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
4
+ return new (P || (P = Promise))(function (resolve, reject) {
5
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
6
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
7
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
8
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
9
+ });
10
+ };
11
+ Object.defineProperty(exports, "__esModule", { value: true });
12
+ exports.NotificationSchema = void 0;
13
+ const confluent_schema_registry_1 = require("@kafkajs/confluent-schema-registry");
14
+ const registry_util_1 = require("./registry.util");
15
+ const fs = require('fs');
16
+ const protoSchemaBuffer = require('protocol-buffers-schema');
17
+ const pickSchema = require('./pickSchema');
18
+ class NotificationSchema {
19
+ constructor() {
20
+ this.registry = registry_util_1.SchemaRegistryS.getInstance();
21
+ }
22
+ static getInstance() {
23
+ if (!this.instance)
24
+ this.instance = new NotificationSchema();
25
+ return this.instance;
26
+ }
27
+ register(notificationType) {
28
+ return __awaiter(this, void 0, void 0, function* () {
29
+ try {
30
+ const { path, subject } = pickSchema(notificationType);
31
+ if (!path) {
32
+ throw new Error(`Schema ${path} not found`);
33
+ }
34
+ const schema = this.getSchema(path);
35
+ const protoSchema = {
36
+ schema,
37
+ type: confluent_schema_registry_1.SchemaType.PROTOBUF
38
+ };
39
+ const { id } = yield this.registry.register(protoSchema, { subject, compatibility: confluent_schema_registry_1.COMPATIBILITY.FULL });
40
+ this.registeredSchemaId = id;
41
+ }
42
+ catch (e) {
43
+ console.log(e);
44
+ throw e;
45
+ }
46
+ });
47
+ }
48
+ getSchemaId() {
49
+ return __awaiter(this, void 0, void 0, function* () {
50
+ if (!this.registeredSchemaId)
51
+ yield this.register(this.notificationType);
52
+ return this.registeredSchemaId;
53
+ });
54
+ }
55
+ /**
56
+ * Reads schema from protobuf file and stringifies it. Will throw an error in case proto file has multiple message
57
+ * @returns Stringified schema
58
+ */
59
+ getSchema(path) {
60
+ var _a;
61
+ const dataRead = fs.readFileSync(path);
62
+ const notificationMessage = protoSchemaBuffer.parse(dataRead);
63
+ if (((_a = notificationMessage === null || notificationMessage === void 0 ? void 0 : notificationMessage.messages) === null || _a === void 0 ? void 0 : _a.length) > 1)
64
+ throw new Error(`One schema file cannot have multiple schemas`);
65
+ return protoSchemaBuffer.stringify(notificationMessage);
66
+ }
67
+ }
68
+ exports.NotificationSchema = NotificationSchema;
@@ -0,0 +1,7 @@
1
+ import { notificationType } from '../../store/types/notification.type';
2
+ interface SchemaInfo {
3
+ path: string;
4
+ subject: string;
5
+ }
6
+ declare function pickSchema(notificationType: notificationType): SchemaInfo;
7
+ export = pickSchema;
@@ -0,0 +1,37 @@
1
+ "use strict";
2
+ const path = require('path');
3
+ const schemaMap = {
4
+ 'common': {
5
+ path: path.join(__dirname, '..', '..', 'store', 'schemas', 'proto', 'commonNotification.proto'),
6
+ subject: "common_notification"
7
+ },
8
+ 'asset-triggers': {
9
+ path: path.join(__dirname, '..', '..', 'store', 'schemas', 'proto', 'assetTriggersNotification.proto'),
10
+ subject: "asset_trigger_notification_details"
11
+ },
12
+ 'bolt': {
13
+ path: path.join(__dirname, '..', '..', 'store', 'schemas', 'proto', 'boltNotification.proto'),
14
+ subject: "bolt_charger_notification_v2"
15
+ }
16
+ };
17
+ function pickSchema(notificationType) {
18
+ let schemaPath;
19
+ switch (notificationType) {
20
+ case 'common':
21
+ schemaPath = schemaMap["common"];
22
+ break;
23
+ case 'asset-triggers':
24
+ schemaPath = schemaMap["asset-triggers"];
25
+ break;
26
+ case 'bolt':
27
+ schemaPath = schemaMap["bolt"];
28
+ break;
29
+ default:
30
+ throw new Error(`Schema ${notificationType} not found`);
31
+ }
32
+ if (!schemaPath) {
33
+ throw new Error(`Schema ${notificationType} not saved`);
34
+ }
35
+ return schemaPath;
36
+ }
37
+ module.exports = pickSchema;
@@ -0,0 +1,9 @@
1
+ import { SchemaRegistry } from '@kafkajs/confluent-schema-registry';
2
+ export declare class SchemaRegistryS extends SchemaRegistry {
3
+ private static instance;
4
+ constructor(url: string);
5
+ static connect(url: string): void;
6
+ static getInstance(): SchemaRegistryS;
7
+ getRegistry(url: string): SchemaRegistryS;
8
+ static isConnected(): boolean;
9
+ }
@@ -0,0 +1,24 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.SchemaRegistryS = void 0;
4
+ const confluent_schema_registry_1 = require("@kafkajs/confluent-schema-registry");
5
+ class SchemaRegistryS extends confluent_schema_registry_1.SchemaRegistry {
6
+ constructor(url) {
7
+ super({ host: `${url}` });
8
+ }
9
+ static connect(url) {
10
+ this.instance = new SchemaRegistryS(url);
11
+ }
12
+ static getInstance() {
13
+ if (!this.instance)
14
+ throw new Error('Schema Registry is not connected yet. First connect to schema registry');
15
+ return this.instance;
16
+ }
17
+ getRegistry(url) {
18
+ return SchemaRegistryS.instance;
19
+ }
20
+ static isConnected() {
21
+ return !!this.instance;
22
+ }
23
+ }
24
+ exports.SchemaRegistryS = SchemaRegistryS;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@bolt.tech/kafka-utils",
3
- "version": "1.0.12",
3
+ "version": "2.0.0",
4
4
  "description": "",
5
5
  "main": "build/index.js",
6
6
  "types": "build/index.d.ts",