@bikdotai/bik-shared-backend 20.3.1 → 20.3.2-beta.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 (80) hide show
  1. package/lib/alerts/templates/campaign/campaignMovedToDraftSegmentSyncDelay.d.ts +1 -0
  2. package/lib/alerts/templates/campaign/campaignMovedToDraftSegmentSyncDelay.js +4 -0
  3. package/lib/alerts/templates/campaign/campaignMovedToDraftSegmentSyncFailed.d.ts +1 -0
  4. package/lib/alerts/templates/campaign/campaignMovedToDraftSegmentSyncFailed.js +4 -0
  5. package/lib/alerts/templates/campaign/campaignScheduledTimeExceededDueToSyncDelay.d.ts +1 -0
  6. package/lib/alerts/templates/campaign/campaignScheduledTimeExceededDueToSyncDelay.js +4 -0
  7. package/lib/alertsV2/alertInstances.repo.js +26 -2
  8. package/lib/alertsV2/alertsV2.helper.d.ts +3 -4
  9. package/lib/alertsV2/alertsV2.helper.js +49 -3
  10. package/lib/alertsV2/alertsV2.service.js +14 -5
  11. package/lib/auth/authMiddlewares.js +68 -3
  12. package/lib/auth/firebase-auth.service.js +3 -3
  13. package/lib/auth/implementations/bik-admin-auth-service.d.ts +1 -1
  14. package/lib/auth/implementations/bik-admin-auth-service.js +2 -1
  15. package/lib/auth/index.d.ts +3 -0
  16. package/lib/auth/index.js +3 -0
  17. package/lib/auth/secret-manager/configManager.firestore.d.ts +22 -0
  18. package/lib/auth/secret-manager/configManager.firestore.js +166 -0
  19. package/lib/auth/secret-manager/configManager.helper.d.ts +13 -0
  20. package/lib/auth/secret-manager/configManager.helper.js +32 -0
  21. package/lib/auth/secret-manager/configManager.model.d.ts +38 -0
  22. package/lib/auth/secret-manager/configManager.model.js +2 -0
  23. package/lib/auth/secret-manager/configManager.service.d.ts +17 -0
  24. package/lib/auth/secret-manager/configManager.service.js +138 -0
  25. package/lib/auth/secret-manager/env-variables/variables.list.d.ts +3 -0
  26. package/lib/auth/secret-manager/env-variables/variables.list.js +3 -0
  27. package/lib/chat-handover-protocol/chat-handover-protocol.js +26 -41
  28. package/lib/core/local_runner.js +28 -11
  29. package/lib/core/setup.d.ts +3 -0
  30. package/lib/core/setup.js +24 -2
  31. package/lib/database/database.model.d.ts +95 -0
  32. package/lib/database/database.model.js +5 -0
  33. package/lib/database/database.service.d.ts +90 -0
  34. package/lib/database/database.service.js +382 -0
  35. package/lib/database/index.d.ts +7 -0
  36. package/lib/database/index.js +23 -0
  37. package/lib/elastic/counter/ingestion.js +1 -0
  38. package/lib/elastic/queries/campaign/getBroadcastDetailedStats.d.ts +117 -0
  39. package/lib/elastic/queries/campaign/getBroadcastDetailedStats.js +94 -1
  40. package/lib/elastic/queries/campaign/getUniqueCustomerCnt.d.ts +1 -0
  41. package/lib/elastic/queries/campaign/getUniqueCustomerCnt.js +1 -0
  42. package/lib/elastic/queries/chatbot/getAgentCostForBroadcast.d.ts +117 -0
  43. package/lib/elastic/queries/chatbot/getAgentCostForBroadcast.js +98 -0
  44. package/lib/elastic/queries/chatbot/getAiOperations.d.ts +5 -5
  45. package/lib/elastic/queries/chatbot/getAiOperations.js +3 -3
  46. package/lib/elastic/queries/chatbot/index.d.ts +1 -0
  47. package/lib/elastic/queries/chatbot/index.js +1 -0
  48. package/lib/elastic/queries/crm/getActivityTimelineByAgent.js +1 -1
  49. package/lib/elastic/queries/crm/getBreachedSLACount.d.ts +1 -0
  50. package/lib/elastic/queries/crm/getBreachedSLACount.js +8 -5
  51. package/lib/elastic/queries/crm/getFirstResponseTime.d.ts +1 -0
  52. package/lib/elastic/queries/crm/getFirstResponseTime.js +8 -5
  53. package/lib/elastic/queries/integrations/getOrdersShadowServices.d.ts +76 -0
  54. package/lib/elastic/queries/integrations/getOrdersShadowServices.js +61 -0
  55. package/lib/elastic/queries/integrations/index.d.ts +1 -0
  56. package/lib/elastic/queries/integrations/index.js +1 -0
  57. package/lib/elastic/queries/openAi/addToCartSession.d.ts +1 -0
  58. package/lib/elastic/queries/openAi/addToCartSession.js +11 -3
  59. package/lib/elastic/queries/openAi/checkoutCompletedSession.d.ts +1 -0
  60. package/lib/elastic/queries/openAi/checkoutCompletedSession.js +11 -3
  61. package/lib/elastic/reports/crm/index.d.ts +1 -0
  62. package/lib/elastic/reports/crm/index.js +1 -0
  63. package/lib/elastic/reports/reports.service.js +17 -8
  64. package/lib/events/events.d.ts +8 -0
  65. package/lib/events/events.js +25 -1
  66. package/lib/events/schema/events.helper.d.ts +1 -0
  67. package/lib/events/schema/events.helper.js +12 -6
  68. package/lib/index.d.ts +1 -0
  69. package/lib/index.js +1 -0
  70. package/lib/merchant-events/elastic.search.d.ts +5 -0
  71. package/lib/merchant-events/elastic.search.js +23 -2
  72. package/lib/merchant-events/merchant.service.d.ts +1 -1
  73. package/lib/merchant-events/merchant.service.js +12 -11
  74. package/lib/recordAnalytics/recordAnalytics.service.js +5 -4
  75. package/lib/redis/redisPubSubService.d.ts +4 -6
  76. package/lib/redis/redisPubSubService.js +211 -123
  77. package/lib/redis/redisService.js +14 -8
  78. package/lib/swagger/SwaggerSchemaHelper.js +21 -17
  79. package/lib/user-properties/userProperties.service.js +1 -0
  80. package/package.json +2 -2
@@ -15,10 +15,99 @@ Object.defineProperty(exports, "__esModule", { value: true });
15
15
  exports.RedisPubSubService = void 0;
16
16
  const ioredis_1 = __importDefault(require("ioredis"));
17
17
  const auth_1 = require("../auth");
18
+ // One publisher + one subscriber shared across ALL RedisPubSubService instances.
19
+ // This ensures the entire process uses exactly 2 pub/sub connections regardless
20
+ // of how many channels are subscribed to.
21
+ let sharedPublisher = null;
22
+ let sharedSubscriber = null;
23
+ let shutdownRegistered = false;
24
+ // Stored so closeAll() can remove the handlers and avoid accumulation across
25
+ // closeAll() + reinit cycles (e.g. in tests).
26
+ let signalHandler = null;
27
+ // Registry mapping channel name → message callback for all active subscriptions.
28
+ // A single 'message' listener on sharedSubscriber dispatches via this map,
29
+ // avoiding MaxListenersExceededWarning when many channels are subscribed.
30
+ const channelCallbacks = new Map();
31
+ // Guards registration of the shared 'ready' and 'message' listeners so they
32
+ // are added to sharedSubscriber exactly once regardless of how many instances
33
+ // call subscribe().
34
+ let sharedListenersRegistered = false;
35
+ const MAX_RETRIES = 3;
36
+ const BASE_DELAY_MS = 200;
37
+ // Single authoritative predicate for transient Redis errors, used by both the
38
+ // client error handler and retryWithBackoff — no duplicate classification logic.
39
+ function isTransientError(err) {
40
+ const code = err === null || err === void 0 ? void 0 : err.code;
41
+ const name = err === null || err === void 0 ? void 0 : err.name;
42
+ const message = err === null || err === void 0 ? void 0 : err.message;
43
+ const transientCodes = new Set([
44
+ 'ECONNRESET',
45
+ 'ETIMEDOUT',
46
+ 'EHOSTUNREACH',
47
+ 'ENETUNREACH',
48
+ 'ECONNREFUSED',
49
+ 'NR_CLOSED',
50
+ 'EPIPE',
51
+ ]);
52
+ if (name === 'TimeoutError')
53
+ return true;
54
+ if (code && transientCodes.has(code))
55
+ return true;
56
+ if (message) {
57
+ return [
58
+ /connection is closed/i,
59
+ /socket closed/i,
60
+ /not yet established/i,
61
+ /still connecting/i,
62
+ /Ready check failed/i,
63
+ ].some((r) => r.test(message));
64
+ }
65
+ return false;
66
+ }
67
+ function createRedisClient(opts) {
68
+ var _a, _b, _c;
69
+ const client = new ioredis_1.default({
70
+ host: opts.host,
71
+ password: opts.password,
72
+ port: opts.port,
73
+ keepAlive: 30000,
74
+ lazyConnect: (_a = opts.lazyConnect) !== null && _a !== void 0 ? _a : false,
75
+ autoResubscribe: (_b = opts.autoResubscribe) !== null && _b !== void 0 ? _b : true,
76
+ enableReadyCheck: (_c = opts.enableReadyCheck) !== null && _c !== void 0 ? _c : true,
77
+ });
78
+ client.on('error', (err) => {
79
+ if (isTransientError(err))
80
+ return;
81
+ console.error('RedisPubSubService client error:', err);
82
+ });
83
+ return client;
84
+ }
85
+ // Module-level so the shared 'ready' listener (registered once) can call it
86
+ // without requiring a class instance reference.
87
+ function retryWithBackoff(fn) {
88
+ return __awaiter(this, void 0, void 0, function* () {
89
+ let attempt = 0;
90
+ let lastError;
91
+ while (attempt <= MAX_RETRIES) {
92
+ try {
93
+ return yield fn();
94
+ }
95
+ catch (err) {
96
+ lastError = err;
97
+ if (!isTransientError(err) || attempt === MAX_RETRIES) {
98
+ throw err;
99
+ }
100
+ const delay = Math.min(BASE_DELAY_MS * Math.pow(2, attempt), 2000);
101
+ yield new Promise((res) => setTimeout(res, delay));
102
+ attempt++;
103
+ }
104
+ }
105
+ throw lastError;
106
+ });
107
+ }
18
108
  class RedisPubSubService {
19
109
  constructor(config) {
20
- this.maxRetries = 3;
21
- this.baseDelayMs = 200;
110
+ this.subscribed = false;
22
111
  const host = auth_1.EnvVariableHelper.access(auth_1.ServiceName.REDIS, auth_1.RedisKeys.HOST, 'REDIS_HOST') || 'localhost';
23
112
  const portStr = auth_1.EnvVariableHelper.access(auth_1.ServiceName.REDIS, auth_1.RedisKeys.PORT, 'REDIS_PORT');
24
113
  const port = portStr ? parseInt(portStr) : 6379;
@@ -27,114 +116,60 @@ class RedisPubSubService {
27
116
  if (!host || !password) {
28
117
  throw new Error('Missing environment variables for Redis Cloud from bik-shared-backend');
29
118
  }
30
- this.publisher = new ioredis_1.default({ host, password, port });
31
- // autoResubscribe: false — we re-subscribe manually in the 'ready' handler,
32
- // so ioredis's built-in re-subscribe doesn't double-up and cause the
33
- // "Connection in subscriber mode" error on reconnect.
34
- // enableReadyCheck: false avoids the INFO ready-check command racing with
35
- // our SUBSCRIBE and producing the same "subscriber mode" error.
36
- this.subscriber = new ioredis_1.default({
37
- host,
38
- password,
39
- port,
40
- autoResubscribe: false,
41
- enableReadyCheck: false,
42
- });
43
- const isTransient = (err) => {
44
- const code = err === null || err === void 0 ? void 0 : err.code;
45
- const name = err === null || err === void 0 ? void 0 : err.name;
46
- const message = err === null || err === void 0 ? void 0 : err.message;
47
- const transientCodes = new Set([
48
- 'ECONNRESET',
49
- 'ETIMEDOUT',
50
- 'EHOSTUNREACH',
51
- 'ENETUNREACH',
52
- 'ECONNREFUSED',
53
- 'NR_CLOSED',
54
- 'EPIPE',
55
- ]);
56
- if (name === 'TimeoutError')
57
- return true;
58
- if (code && transientCodes.has(code))
59
- return true;
60
- if (message) {
61
- return [
62
- /connection is closed/i,
63
- /socket closed/i,
64
- /not yet established/i,
65
- /still connecting/i,
66
- /Ready check failed/i,
67
- ].some((r) => r.test(message));
68
- }
69
- return false;
70
- };
71
- this.publisher.on('error', (err) => {
72
- if (isTransient(err))
73
- return; // suppress transient errors
74
- console.error('Redis publisher error:', err);
75
- });
76
- this.subscriber.on('error', (err) => {
77
- if (isTransient(err))
78
- return; // suppress transient errors
79
- console.error('Redis subscriber error:', err);
80
- });
81
- }
82
- isRetriableRedisError(error) {
83
- const code = error === null || error === void 0 ? void 0 : error.code;
84
- const name = error === null || error === void 0 ? void 0 : error.name;
85
- const message = error === null || error === void 0 ? void 0 : error.message;
86
- const transientCodes = new Set([
87
- 'ECONNRESET',
88
- 'ETIMEDOUT',
89
- 'EHOSTUNREACH',
90
- 'ENETUNREACH',
91
- 'ECONNREFUSED',
92
- 'NR_CLOSED',
93
- 'EPIPE',
94
- ]);
95
- if (name === 'TimeoutError')
96
- return true;
97
- if (code && transientCodes.has(code))
98
- return true;
99
- if (message) {
100
- const patterns = [
101
- /connection is closed/i,
102
- /socket closed/i,
103
- /The connection is not yet established/i,
104
- /ioredis is still connecting/i,
105
- /Ready check failed/i,
106
- ];
107
- if (patterns.some((re) => re.test(message)))
108
- return true;
119
+ // Initialise shared clients once per process.
120
+ if (!sharedPublisher) {
121
+ // lazyConnect: true publisher only opens a connection when publish() is
122
+ // first called, saving a connection on pods that only subscribe.
123
+ sharedPublisher = createRedisClient({ host, password, port, lazyConnect: true });
109
124
  }
110
- return false;
111
- }
112
- retryWithBackoff(fn) {
113
- return __awaiter(this, void 0, void 0, function* () {
114
- let attempt = 0;
115
- let lastError;
116
- while (attempt <= this.maxRetries) {
125
+ if (!sharedSubscriber) {
126
+ // autoResubscribe: false — we re-subscribe manually in the 'ready' handler
127
+ // so ioredis's built-in re-subscribe doesn't double-up and cause the
128
+ // "Connection in subscriber mode" error on reconnect.
129
+ // enableReadyCheck: false — avoids the INFO ready-check command racing with
130
+ // SUBSCRIBE on reconnect.
131
+ sharedSubscriber = createRedisClient({
132
+ host,
133
+ password,
134
+ port,
135
+ autoResubscribe: false,
136
+ enableReadyCheck: false,
137
+ });
138
+ }
139
+ // Register SIGTERM/SIGINT cleanup once per process. This handler closes the
140
+ // shared Redis connections gracefully. process.exit() is intentionally NOT
141
+ // called here — that responsibility belongs to the host service (e.g. via
142
+ // Fastify server.close() in main.ts) so it can drain HTTP and perform its
143
+ // own cleanup before exiting.
144
+ // signalHandler is stored so closeAll() can remove it via process.off(),
145
+ // preventing handler accumulation across closeAll() + reinit cycles.
146
+ if (!shutdownRegistered) {
147
+ shutdownRegistered = true;
148
+ signalHandler = () => __awaiter(this, void 0, void 0, function* () {
149
+ console.log('[RedisPubSubService] Signal received — closing shared Redis pub/sub connections');
117
150
  try {
118
- return yield fn();
151
+ yield Promise.all([sharedPublisher === null || sharedPublisher === void 0 ? void 0 : sharedPublisher.quit(), sharedSubscriber === null || sharedSubscriber === void 0 ? void 0 : sharedSubscriber.quit()]);
152
+ console.log('[RedisPubSubService] Redis pub/sub connections closed successfully');
119
153
  }
120
154
  catch (err) {
121
- lastError = err;
122
- if (!this.isRetriableRedisError(err) || attempt === this.maxRetries) {
123
- throw err;
124
- }
125
- const delay = Math.min(this.baseDelayMs * Math.pow(2, attempt), 2000);
126
- yield new Promise((res) => setTimeout(res, delay));
127
- attempt++;
155
+ console.warn('[RedisPubSubService] Error closing pub/sub connections:', err);
128
156
  }
129
- }
130
- throw lastError;
131
- });
157
+ });
158
+ process.on('SIGTERM', signalHandler);
159
+ process.on('SIGINT', signalHandler);
160
+ }
161
+ }
162
+ get publisher() {
163
+ return sharedPublisher;
164
+ }
165
+ get subscriber() {
166
+ return sharedSubscriber;
132
167
  }
133
168
  publish(data) {
134
169
  return __awaiter(this, void 0, void 0, function* () {
135
170
  try {
136
171
  const payload = JSON.stringify(data);
137
- yield this.retryWithBackoff(() => this.publisher.publish(this.channel, payload));
172
+ yield retryWithBackoff(() => this.publisher.publish(this.channel, payload));
138
173
  console.log(`Published to ${this.channel}:`, data);
139
174
  }
140
175
  catch (error) {
@@ -143,39 +178,92 @@ class RedisPubSubService {
143
178
  });
144
179
  }
145
180
  subscribe(callback) {
146
- const doSubscribe = () => {
147
- this.retryWithBackoff(() => this.subscriber.subscribe(this.channel))
148
- .then(() => console.log(`Subscribed to channel: ${this.channel}`))
149
- .catch((err) => console.error('Redis subscription failed:', err));
150
- };
151
- // 'ready' fires after AUTH + SELECT (and INFO if enableReadyCheck is on),
152
- // so it's safe to send SUBSCRIBE here without conflicting with ioredis internals.
153
- // It also fires on every reconnect, handling re-subscription since
154
- // autoResubscribe is disabled.
155
- this.subscriber.on('ready', () => {
156
- console.log(`Redis Subscriber ready on channel "${this.channel}"`);
157
- doSubscribe();
158
- });
181
+ if (this.subscribed) {
182
+ console.warn(`RedisPubSubService: already subscribed to channel "${this.channel}", ignoring duplicate call.`);
183
+ return;
184
+ }
185
+ this.subscribed = true;
186
+ // Register the callback before attaching listeners so the 'ready' handler
187
+ // sees this channel immediately on the first connect.
188
+ channelCallbacks.set(this.channel, callback);
189
+ if (!sharedListenersRegistered) {
190
+ sharedListenersRegistered = true;
191
+ // Single 'ready' listener re-subscribes ALL registered channels on every
192
+ // connect/reconnect. autoResubscribe is disabled so we own this entirely.
193
+ // 'ready' fires after AUTH + SELECT, safe to send SUBSCRIBE here.
194
+ sharedSubscriber.on('ready', () => {
195
+ const channels = Array.from(channelCallbacks.keys());
196
+ if (channels.length === 0)
197
+ return;
198
+ console.log(`[RedisPubSubService] Subscriber ready — resubscribing to: ${channels.join(', ')}`);
199
+ retryWithBackoff(() => sharedSubscriber.subscribe(...channels))
200
+ .then(() => console.log(`[RedisPubSubService] Subscribed to: ${channels.join(', ')}`))
201
+ .catch((err) => console.error('[RedisPubSubService] Subscription failed:', err));
202
+ });
203
+ // Single 'message' listener dispatches to the correct per-channel callback
204
+ // via the registry. This replaces per-instance listeners and prevents
205
+ // MaxListenersExceededWarning regardless of how many channels are active.
206
+ sharedSubscriber.on('message', (incomingChannel, message) => {
207
+ const cb = channelCallbacks.get(incomingChannel);
208
+ if (!cb)
209
+ return;
210
+ try {
211
+ const parsed = JSON.parse(message);
212
+ console.log(`Message received on ${incomingChannel}:`, parsed);
213
+ cb(parsed);
214
+ }
215
+ catch (e) {
216
+ console.error(`[RedisPubSubService] Error parsing message on ${incomingChannel}:`, e);
217
+ }
218
+ });
219
+ }
159
220
  // Handle the case where the connection is already established before
160
221
  // subscribe() is called (e.g. delayed initialization).
161
222
  if (this.subscriber.status === 'ready') {
162
- doSubscribe();
223
+ retryWithBackoff(() => this.subscriber.subscribe(this.channel))
224
+ .then(() => console.log(`[RedisPubSubService] Subscribed to channel: ${this.channel}`))
225
+ .catch((err) => console.error('[RedisPubSubService] Subscription failed:', err));
163
226
  }
164
- this.subscriber.on('message', (_channel, message) => {
227
+ }
228
+ // Unsubscribes this instance's channel and removes its callback from the
229
+ // shared registry. The shared publisher/subscriber remain open for other
230
+ // active channels and are closed on SIGTERM or via closeAll().
231
+ close() {
232
+ return __awaiter(this, void 0, void 0, function* () {
233
+ if (!this.subscribed)
234
+ return;
235
+ this.subscribed = false;
236
+ channelCallbacks.delete(this.channel);
165
237
  try {
166
- const parsed = JSON.parse(message);
167
- console.log(`Message received on ${this.channel}:`, parsed);
168
- callback(parsed);
238
+ yield (sharedSubscriber === null || sharedSubscriber === void 0 ? void 0 : sharedSubscriber.unsubscribe(this.channel));
169
239
  }
170
- catch (e) {
171
- console.error('Error parsing message:', e);
240
+ catch (err) {
241
+ console.warn(`[RedisPubSubService] Error unsubscribing from ${this.channel}:`, err);
172
242
  }
173
243
  });
174
244
  }
175
- close() {
245
+ // Closes both shared connections and resets all module-level state including
246
+ // signal handler registration. Intended for tests and explicit full teardown;
247
+ // in production the SIGTERM handler handles shutdown automatically.
248
+ static closeAll() {
176
249
  return __awaiter(this, void 0, void 0, function* () {
177
- yield Promise.all([this.publisher.quit(), this.subscriber.quit()]);
178
- console.log('Redis connections closed.');
250
+ try {
251
+ yield Promise.all([sharedPublisher === null || sharedPublisher === void 0 ? void 0 : sharedPublisher.quit(), sharedSubscriber === null || sharedSubscriber === void 0 ? void 0 : sharedSubscriber.quit()]);
252
+ sharedPublisher = null;
253
+ sharedSubscriber = null;
254
+ channelCallbacks.clear();
255
+ sharedListenersRegistered = false;
256
+ if (signalHandler) {
257
+ process.off('SIGTERM', signalHandler);
258
+ process.off('SIGINT', signalHandler);
259
+ signalHandler = null;
260
+ }
261
+ shutdownRegistered = false;
262
+ console.log('[RedisPubSubService] All Redis pub/sub connections closed.');
263
+ }
264
+ catch (err) {
265
+ console.warn('[RedisPubSubService] Error closing Redis pub/sub connections:', err);
266
+ }
179
267
  });
180
268
  }
181
269
  }
@@ -46,12 +46,13 @@ class RedisAppService {
46
46
  host: redisHost,
47
47
  password: redisKey,
48
48
  port: redisPort ? Number(redisPort) : 6379,
49
- keepAlive: 1,
49
+ keepAlive: 30000,
50
50
  maxRetriesPerRequest: null,
51
51
  enableReadyCheck: false,
52
52
  connectionName: logger_1.LOGGING_CONFIGURATION.serviceName,
53
53
  connectTimeout: 5000,
54
54
  commandTimeout: 5000,
55
+ disconnectTimeout: 10000,
55
56
  reconnectOnError: (err) => {
56
57
  if (err.code === 'ECONNREFUSED') {
57
58
  console.error('REDIS QUOTA LIKELY EXCEEDED - Check Redis Labs dashboard', err);
@@ -138,7 +139,7 @@ class RedisAppService {
138
139
  return __awaiter(this, void 0, void 0, function* () {
139
140
  let attempt = 0;
140
141
  let lastError;
141
- while (attempt < this.maxRetries) {
142
+ while (attempt <= this.maxRetries) {
142
143
  try {
143
144
  return yield fn();
144
145
  }
@@ -565,15 +566,20 @@ class RedisAppService {
565
566
  exports.RedisAppService = RedisAppService;
566
567
  // Dangerous - this will impact any service that bik shared is injected with.
567
568
  const cleanup = () => __awaiter(void 0, void 0, void 0, function* () {
569
+ console.log('[RedisAppService] SIGTERM received — closing Redis connection');
568
570
  if (!RedisAppService.getInstance().getClient()) {
571
+ console.log('[RedisAppService] No client found, skipping');
569
572
  return;
570
573
  }
571
- // console.log(
572
- // '@bik-shared (redisService.ts) Received SIGTERM - closing Redis connection and shutting down gracefully.'
573
- // );
574
- // Close the Redis connection
575
- yield RedisAppService.getInstance().gracefulShutdown();
574
+ try {
575
+ yield RedisAppService.getInstance().gracefulShutdown();
576
+ console.log('[RedisAppService] Redis connection closed successfully');
577
+ }
578
+ catch (err) {
579
+ console.warn('[RedisAppService] Error closing Redis connection:', err);
580
+ }
576
581
  });
577
582
  // Register the cleanup function for SIGTERM signal
578
583
  process.on('SIGTERM', cleanup);
579
- process.on('exit', cleanup);
584
+ // Also handle SIGINT (Ctrl+C / local dev)
585
+ process.on('SIGINT', cleanup);
@@ -52,7 +52,11 @@ class SwaggerSchemaHelper {
52
52
  }
53
53
  });
54
54
  // Convert camelCase or kebab-case to human-readable format
55
- return prefix.charAt(0).toUpperCase() + prefix.slice(1).replace(/([A-Z])/g, ' $1').trim();
55
+ return (prefix.charAt(0).toUpperCase() +
56
+ prefix
57
+ .slice(1)
58
+ .replace(/([A-Z])/g, ' $1')
59
+ .trim());
56
60
  }
57
61
  static loadSwaggerConfig(apiPath) {
58
62
  try {
@@ -90,10 +94,10 @@ class SwaggerSchemaHelper {
90
94
  security: [
91
95
  {
92
96
  Authorization: [],
93
- bikReferer: []
94
- }
97
+ bikReferer: [],
98
+ },
95
99
  ],
96
- 'x-timeout': existingSchema === null || existingSchema === void 0 ? void 0 : existingSchema['x-timeout']
100
+ 'x-timeout': existingSchema === null || existingSchema === void 0 ? void 0 : existingSchema['x-timeout'],
97
101
  };
98
102
  if (swaggerConfig['x-timeout']) {
99
103
  swaggerConfig.description += `\n\n**Timeout:** ${swaggerConfig['x-timeout']} seconds`;
@@ -103,23 +107,23 @@ class SwaggerSchemaHelper {
103
107
  acc[example.summary] = { value: example.value };
104
108
  return acc;
105
109
  }, {});
106
- swaggerConfig["responses"] = {
107
- "200": {
108
- "description": "Default Response"
110
+ swaggerConfig['responses'] = {
111
+ '200': {
112
+ description: 'Default Response',
109
113
  },
110
- "503": {
111
- "description": `Request Timeout - Operation exceeded ${swaggerConfig['x-timeout'] || 'configured'} seconds`
114
+ '408': {
115
+ description: `Request Timeout - Operation exceeded ${swaggerConfig['x-timeout'] || 'configured'} seconds`,
112
116
  },
113
117
  };
114
- swaggerConfig["requestBody"] = {
115
- "content": {
116
- "application/json": {
117
- "schema": {
118
- "type": "object"
118
+ swaggerConfig['requestBody'] = {
119
+ content: {
120
+ 'application/json': {
121
+ schema: {
122
+ type: 'object',
119
123
  },
120
- "examples": flattenedExamples
121
- }
122
- }
124
+ examples: flattenedExamples,
125
+ },
126
+ },
123
127
  };
124
128
  return swaggerConfig;
125
129
  }
@@ -111,6 +111,7 @@ class BikUserPropertiesService {
111
111
  return;
112
112
  }
113
113
  const userPropertiesPayload = userPropertiesHelper.constructUserProperties(currObj, (customerTagsMap === null || customerTagsMap === void 0 ? void 0 : customerTagsMap[currObj.customerId.toString()]) || [], undefined, currObj.tagsToRemove);
114
+ console.log('Final userPropertiesPayload:', JSON.stringify(userPropertiesPayload === null || userPropertiesPayload === void 0 ? void 0 : userPropertiesPayload.data, null, 2));
114
115
  const isUatStore = (0, events_1.getUatStoreIds)().includes(currObj.storeId || storeId || '');
115
116
  const upTopic = isUatStore ? 'trackUserProperty-uat' : 'trackUserProperty';
116
117
  return (0, pubsub_listener_1.publishMessageToTopic)(upTopic, userPropertiesPayload === null || userPropertiesPayload === void 0 ? void 0 : userPropertiesPayload.data);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@bikdotai/bik-shared-backend",
3
- "version": "20.3.1",
3
+ "version": "20.3.2-beta.1",
4
4
  "description": "",
5
5
  "main": "lib/index.js",
6
6
  "types": "lib/index.d.ts",
@@ -35,7 +35,7 @@
35
35
  "dependencies": {
36
36
  "@amplitude/identify": "^1.10.0",
37
37
  "@amplitude/node": "^1.10.0",
38
- "@bikdotai/bik-models": "^11.6.1",
38
+ "@bikdotai/bik-models": "11.6.2-beta.0",
39
39
  "@elastic/elasticsearch": "^8.7.0",
40
40
  "@fastify/cookie": "^9.4.0",
41
41
  "@fastify/cors": "^9.0.1",