@sipgate/integration-bridge 1.0.36 → 1.0.40

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 (103) hide show
  1. package/dist/cache/contact-cache-storage.js +79 -97
  2. package/dist/cache/contact-cache-storage.js.map +1 -1
  3. package/dist/cache/storage/memory-storage-adapter.js +8 -22
  4. package/dist/cache/storage/memory-storage-adapter.js.map +1 -1
  5. package/dist/cache/storage/redis-storage-adapter.js +16 -30
  6. package/dist/cache/storage/redis-storage-adapter.js.map +1 -1
  7. package/dist/cache/token-cache-storage.js +30 -43
  8. package/dist/cache/token-cache-storage.js.map +1 -1
  9. package/dist/controllers/call-log.controller.js +63 -78
  10. package/dist/controllers/call-log.controller.js.map +1 -1
  11. package/dist/controllers/task.controller.js +60 -75
  12. package/dist/controllers/task.controller.js.map +1 -1
  13. package/dist/index.d.ts +6 -2
  14. package/dist/index.js +38 -21
  15. package/dist/index.js.map +1 -1
  16. package/dist/middlewares/error-handler.middleware.js +1 -2
  17. package/dist/middlewares/error-handler.middleware.js.map +1 -1
  18. package/dist/middlewares/extract-header.middleware.d.ts +0 -1
  19. package/dist/middlewares/extract-header.middleware.js +2 -2
  20. package/dist/middlewares/extract-header.middleware.js.map +1 -1
  21. package/dist/models/cache-item-state.model.js +1 -1
  22. package/dist/models/cache-item-state.model.js.map +1 -1
  23. package/dist/models/call-direction.enum.js +1 -1
  24. package/dist/models/call-direction.enum.js.map +1 -1
  25. package/dist/models/call-event.model.js +2 -2
  26. package/dist/models/call-event.model.js.map +1 -1
  27. package/dist/models/contact.model.js +3 -3
  28. package/dist/models/contact.model.js.map +1 -1
  29. package/dist/models/controller.model.js +579 -622
  30. package/dist/models/controller.model.js.map +1 -1
  31. package/dist/models/integration-entity.model.js +1 -1
  32. package/dist/models/integration-entity.model.js.map +1 -1
  33. package/dist/models/integration-error.model.js +1 -1
  34. package/dist/models/integration-error.model.js.map +1 -1
  35. package/dist/models/integrations-event.model.js +1 -1
  36. package/dist/models/integrations-event.model.js.map +1 -1
  37. package/dist/models/pubsub/pubsub-client.model.js +16 -25
  38. package/dist/models/pubsub/pubsub-client.model.js.map +1 -1
  39. package/dist/models/pubsub/pubsub-contacts-message.model.js +1 -1
  40. package/dist/models/pubsub/pubsub-contacts-message.model.js.map +1 -1
  41. package/dist/models/server-error.model.js +1 -0
  42. package/dist/models/server-error.model.js.map +1 -1
  43. package/dist/swagger/openapi-spec.d.ts +972 -0
  44. package/dist/swagger/openapi-spec.js +787 -0
  45. package/dist/swagger/openapi-spec.js.map +1 -0
  46. package/dist/util/anonymize-key.js +1 -2
  47. package/dist/util/anonymize-key.js.map +1 -1
  48. package/dist/util/call-comment.js +5 -6
  49. package/dist/util/call-comment.js.map +1 -1
  50. package/dist/util/call-event.util.js +1 -2
  51. package/dist/util/call-event.util.js.map +1 -1
  52. package/dist/util/callEventHelper.js +4 -4
  53. package/dist/util/callEventHelper.js.map +1 -1
  54. package/dist/util/contact.util.js +10 -8
  55. package/dist/util/contact.util.js.map +1 -1
  56. package/dist/util/env.js +19 -9
  57. package/dist/util/env.js.map +1 -1
  58. package/dist/util/error/delegate-to-frontend.error.js +1 -0
  59. package/dist/util/error/delegate-to-frontend.error.js.map +1 -1
  60. package/dist/util/error/error.js +11 -8
  61. package/dist/util/error/error.js.map +1 -1
  62. package/dist/util/gdpr/gdprSlackNotification.js +22 -22
  63. package/dist/util/gdpr/gdprSlackNotification.js.map +1 -1
  64. package/dist/util/gdpr/index.js +17 -7
  65. package/dist/util/gdpr/index.js.map +1 -1
  66. package/dist/util/get-contact-cache.js +1 -2
  67. package/dist/util/get-contact-cache.js.map +1 -1
  68. package/dist/util/http/default-axios.js +1 -2
  69. package/dist/util/http/default-axios.js.map +1 -1
  70. package/dist/util/http/index.js +17 -7
  71. package/dist/util/http/index.js.map +1 -1
  72. package/dist/util/http/pagination.js +32 -85
  73. package/dist/util/http/pagination.js.map +1 -1
  74. package/dist/util/http/rate-limited-axios.js +42 -61
  75. package/dist/util/http/rate-limited-axios.js.map +1 -1
  76. package/dist/util/http/retrying-axios.js +11 -23
  77. package/dist/util/http/retrying-axios.js.map +1 -1
  78. package/dist/util/http/url.js +1 -2
  79. package/dist/util/http/url.js.map +1 -1
  80. package/dist/util/index.js +17 -7
  81. package/dist/util/index.js.map +1 -1
  82. package/dist/util/lang/delay.js +1 -2
  83. package/dist/util/lang/delay.js.map +1 -1
  84. package/dist/util/lang/diff.js +19 -10
  85. package/dist/util/lang/diff.js.map +1 -1
  86. package/dist/util/logger.util.js +7 -2
  87. package/dist/util/logger.util.js.map +1 -1
  88. package/dist/util/oauth.js +131 -134
  89. package/dist/util/oauth.js.map +1 -1
  90. package/dist/util/phone-number-utils.js +4 -5
  91. package/dist/util/phone-number-utils.js.map +1 -1
  92. package/dist/util/security/index.js +17 -7
  93. package/dist/util/security/index.js.map +1 -1
  94. package/dist/util/security/nonce.js +5 -6
  95. package/dist/util/security/nonce.js.map +1 -1
  96. package/dist/util/size-of.js +1 -1
  97. package/dist/util/size-of.js.map +1 -1
  98. package/dist/util/token-util.js +46 -62
  99. package/dist/util/token-util.js.map +1 -1
  100. package/dist/util/validate.js +1 -2
  101. package/dist/util/validate.js.map +1 -1
  102. package/package.json +25 -38
  103. package/README.md +0 -117
@@ -1,13 +1,4 @@
1
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
2
  Object.defineProperty(exports, "__esModule", { value: true });
12
3
  exports.Controller = void 0;
13
4
  const lodash_1 = require("lodash");
@@ -23,13 +14,15 @@ const pubsub_contacts_message_model_1 = require("./pubsub/pubsub-contacts-messag
23
14
  const anonymize_key_1 = require("../util/anonymize-key");
24
15
  const CONTACT_FETCH_TIMEOUT = 5000;
25
16
  class Controller {
17
+ adapter;
18
+ contactCache;
19
+ pubSubContactStreamingClient = null;
20
+ pubSubIntegrationEventsClient = null;
21
+ additionalPubSubContactStreamingClient = null;
22
+ integrationName = 'UNKNOWN';
23
+ // used for garbage collection reasons, to prevent long running promises from getting canceled
24
+ streamingPromises = new Map();
26
25
  constructor(adapter, contactCache) {
27
- this.pubSubContactStreamingClient = null;
28
- this.pubSubIntegrationEventsClient = null;
29
- this.additionalPubSubContactStreamingClient = null;
30
- this.integrationName = 'UNKNOWN';
31
- // used for garbage collection reasons, to prevent long running promises from getting canceled
32
- this.streamingPromises = new Map();
33
26
  this.adapter = adapter;
34
27
  this.contactCache = contactCache;
35
28
  if (this.adapter.streamContacts) {
@@ -48,7 +41,7 @@ class Controller {
48
41
  }
49
42
  initContactStreaming() {
50
43
  const { PUBSUB_TOPIC_NAME: topicNameLegacy, PUBSUB_TOPIC_NAME_CONTACT_STREAMING: topicName, PUBSUB_ADDITIONAL_TOPIC_NAME: additionalTopicName, } = process.env;
51
- const topicNameProvided = topicName !== null && topicName !== void 0 ? topicName : topicNameLegacy;
44
+ const topicNameProvided = topicName ?? topicNameLegacy;
52
45
  if (!topicNameProvided) {
53
46
  throw new Error('No PUBSUB_TOPIC_NAME_CONTACT_STREAMING provided.');
54
47
  }
@@ -67,388 +60,371 @@ class Controller {
67
60
  this.pubSubIntegrationEventsClient = new _1.PubSubClient(topicName);
68
61
  (0, logger_util_1.infoLogger)('Controller', `Initialized PubSub client for topic ${topicName}`);
69
62
  }
70
- isValidToken(req, res, next) {
71
- return __awaiter(this, void 0, void 0, function* () {
72
- const { providerConfig } = req;
73
- if (!providerConfig) {
74
- throw new _1.ServerError(400, 'Missing parameters');
63
+ async isValidToken(req, res, next) {
64
+ const { providerConfig } = req;
65
+ if (!providerConfig) {
66
+ throw new _1.ServerError(400, 'Missing parameters');
67
+ }
68
+ try {
69
+ (0, logger_util_1.infoLogger)('isValidToken', 'START', providerConfig.apiKey);
70
+ if (!this.adapter.isValidToken) {
71
+ throw new _1.ServerError(501, 'Token validation function is not implemented');
75
72
  }
76
- try {
77
- (0, logger_util_1.infoLogger)('isValidToken', 'START', providerConfig.apiKey);
78
- if (!this.adapter.isValidToken) {
79
- throw new _1.ServerError(501, 'Token validation function is not implemented');
80
- }
81
- const isTokenValid = yield this.adapter.isValidToken(providerConfig);
82
- if (!isTokenValid) {
83
- throw new _1.ServerError(401, 'Token is not valid');
73
+ const isTokenValid = await this.adapter.isValidToken(providerConfig);
74
+ if (!isTokenValid) {
75
+ throw new _1.ServerError(401, 'Token is not valid');
76
+ }
77
+ (0, logger_util_1.infoLogger)('isValidToken', 'END', providerConfig.apiKey);
78
+ res.status(200).send('OK');
79
+ }
80
+ catch (error) {
81
+ // prevent logging of refresh errors
82
+ if (error instanceof _1.ServerError &&
83
+ error.message === integration_error_model_1.IntegrationErrorType.INTEGRATION_REFRESH_ERROR) {
84
+ next(error);
85
+ return;
86
+ }
87
+ (0, logger_util_1.errorLogger)('isValidToken', 'Could not validate token:', providerConfig.apiKey, error);
88
+ next(error);
89
+ }
90
+ }
91
+ async getContacts(req, res, next) {
92
+ const { providerConfig } = req;
93
+ if (!providerConfig) {
94
+ throw new _1.ServerError(400, 'Missing parameters');
95
+ }
96
+ try {
97
+ (0, logger_util_1.infoLogger)('getContacts', 'START', providerConfig.apiKey);
98
+ const fetchContacts = async () => {
99
+ if (!this.adapter.getContacts) {
100
+ throw new _1.ServerError(501, 'Fetching contacts is not implemented');
101
+ }
102
+ (0, logger_util_1.infoLogger)('getContacts', `Fetching contacts…`, providerConfig.apiKey);
103
+ const fetchedContacts = await this.adapter.getContacts(providerConfig);
104
+ const { error: parsingError, data: parsedContacts } = schemas_1.contactsGetSchema.safeParse(fetchedContacts);
105
+ if (parsingError)
106
+ throw new _1.ServerError(500, `Invalid contacts received: ${parsingError.message}`);
107
+ return parsedContacts.map((contact) => (0, contact_util_1.sanitizeContact)(contact, providerConfig.locale));
108
+ };
109
+ const fetcherPromise = this.contactCache
110
+ ? this.contactCache.get(providerConfig.apiKey, fetchContacts)
111
+ : fetchContacts();
112
+ const timeoutPromise = new Promise((resolve) => setTimeout(() => resolve('TIMEOUT'), CONTACT_FETCH_TIMEOUT));
113
+ const raceResult = await Promise.race([fetcherPromise, timeoutPromise]);
114
+ if (raceResult === 'TIMEOUT') {
115
+ (0, logger_util_1.infoLogger)('getContacts', `Fetching too slow, returning empty array.`, providerConfig.apiKey);
116
+ }
117
+ const responseContacts = Array.isArray(raceResult)
118
+ ? raceResult
119
+ : [];
120
+ const contactsCount = responseContacts.length;
121
+ (0, logger_util_1.infoLogger)('getContacts', `Found ${contactsCount} cached contacts`, providerConfig.apiKey);
122
+ if (!Array.isArray(raceResult) &&
123
+ (raceResult === 'TIMEOUT' ||
124
+ raceResult.state === cache_item_state_model_1.CacheItemStateType.FETCHING)) {
125
+ res.header('X-Fetching-State', 'pending');
126
+ }
127
+ if (this.adapter.getToken && req.providerConfig) {
128
+ try {
129
+ const { apiKey } = await this.adapter.getToken(req.providerConfig);
130
+ res.header('X-Provider-Key', apiKey);
84
131
  }
85
- (0, logger_util_1.infoLogger)('isValidToken', 'END', providerConfig.apiKey);
86
- res.status(200).send('OK');
87
- }
88
- catch (error) {
89
- // prevent logging of refresh errors
90
- if (error instanceof _1.ServerError &&
91
- error.message === integration_error_model_1.IntegrationErrorType.INTEGRATION_REFRESH_ERROR) {
92
- next(error);
93
- return;
132
+ catch (error) {
133
+ (0, logger_util_1.errorLogger)('getContacts', 'Could not get and refresh token', providerConfig.apiKey, error);
94
134
  }
95
- (0, logger_util_1.errorLogger)('isValidToken', 'Could not validate token:', providerConfig.apiKey, error);
135
+ }
136
+ (0, logger_util_1.infoLogger)('getContacts', 'END', providerConfig.apiKey);
137
+ res.status(200).send(responseContacts);
138
+ }
139
+ catch (error) {
140
+ // prevent logging of refresh errors
141
+ if (error instanceof _1.ServerError &&
142
+ error.message === integration_error_model_1.IntegrationErrorType.INTEGRATION_REFRESH_ERROR) {
96
143
  next(error);
144
+ return;
97
145
  }
98
- });
146
+ (0, logger_util_1.errorLogger)('getContacts', 'Could not get contacts:', providerConfig.apiKey, error);
147
+ next(error);
148
+ }
99
149
  }
100
- getContacts(req, res, next) {
101
- return __awaiter(this, void 0, void 0, function* () {
102
- const { providerConfig } = req;
150
+ async streamContacts(req, res, next) {
151
+ const { providerConfig } = req;
152
+ try {
103
153
  if (!providerConfig) {
104
154
  throw new _1.ServerError(400, 'Missing parameters');
105
155
  }
106
- try {
107
- (0, logger_util_1.infoLogger)('getContacts', 'START', providerConfig.apiKey);
108
- const fetchContacts = () => __awaiter(this, void 0, void 0, function* () {
109
- if (!this.adapter.getContacts) {
110
- throw new _1.ServerError(501, 'Fetching contacts is not implemented');
111
- }
112
- (0, logger_util_1.infoLogger)('getContacts', `Fetching contacts…`, providerConfig.apiKey);
113
- const fetchedContacts = yield this.adapter.getContacts(providerConfig);
114
- const { error: parsingError, data: parsedContacts } = schemas_1.contactsGetSchema.safeParse(fetchedContacts);
115
- if (parsingError)
156
+ const { userId } = providerConfig;
157
+ if (!userId) {
158
+ throw new _1.ServerError(400, 'Missing user ID');
159
+ }
160
+ const timestamp = Date.now();
161
+ const orderingKey = `${userId}:${timestamp}`;
162
+ (0, logger_util_1.infoLogger)('streamContacts', `[${orderingKey}] Starting contact streaming`, providerConfig.apiKey);
163
+ const publishContacts = async (contacts) => {
164
+ try {
165
+ const { error: parsingError, data: parsedContacts } = schemas_1.contactsGetSchema.safeParse(contacts);
166
+ if (parsingError) {
116
167
  throw new _1.ServerError(500, `Invalid contacts received: ${parsingError.message}`);
117
- return parsedContacts.map((contact) => (0, contact_util_1.sanitizeContact)(contact, providerConfig.locale));
118
- });
119
- const fetcherPromise = this.contactCache
120
- ? this.contactCache.get(providerConfig.apiKey, fetchContacts)
121
- : fetchContacts();
122
- const timeoutPromise = new Promise((resolve) => setTimeout(() => resolve('TIMEOUT'), CONTACT_FETCH_TIMEOUT));
123
- const raceResult = yield Promise.race([fetcherPromise, timeoutPromise]);
124
- if (raceResult === 'TIMEOUT') {
125
- (0, logger_util_1.infoLogger)('getContacts', `Fetching too slow, returning empty array.`, providerConfig.apiKey);
126
- }
127
- const responseContacts = Array.isArray(raceResult)
128
- ? raceResult
129
- : [];
130
- const contactsCount = responseContacts.length;
131
- (0, logger_util_1.infoLogger)('getContacts', `Found ${contactsCount} cached contacts`, providerConfig.apiKey);
132
- if (!Array.isArray(raceResult) &&
133
- (raceResult === 'TIMEOUT' ||
134
- raceResult.state === cache_item_state_model_1.CacheItemStateType.FETCHING)) {
135
- res.header('X-Fetching-State', 'pending');
136
- }
137
- if (this.adapter.getToken && req.providerConfig) {
138
- try {
139
- const { apiKey } = yield this.adapter.getToken(req.providerConfig);
140
- res.header('X-Provider-Key', apiKey);
141
- }
142
- catch (error) {
143
- (0, logger_util_1.errorLogger)('getContacts', 'Could not get and refresh token', providerConfig.apiKey, error);
144
168
  }
145
- }
146
- (0, logger_util_1.infoLogger)('getContacts', 'END', providerConfig.apiKey);
147
- res.status(200).send(responseContacts);
148
- }
149
- catch (error) {
150
- // prevent logging of refresh errors
151
- if (error instanceof _1.ServerError &&
152
- error.message === integration_error_model_1.IntegrationErrorType.INTEGRATION_REFRESH_ERROR) {
153
- next(error);
154
- return;
155
- }
156
- (0, logger_util_1.errorLogger)('getContacts', 'Could not get contacts:', providerConfig.apiKey, error);
157
- next(error);
158
- }
159
- });
160
- }
161
- streamContacts(req, res, next) {
162
- return __awaiter(this, void 0, void 0, function* () {
163
- const { providerConfig } = req;
164
- try {
165
- if (!providerConfig) {
166
- throw new _1.ServerError(400, 'Missing parameters');
167
- }
168
- const { userId } = providerConfig;
169
- if (!userId) {
170
- throw new _1.ServerError(400, 'Missing user ID');
171
- }
172
- const timestamp = Date.now();
173
- const orderingKey = `${userId}:${timestamp}`;
174
- (0, logger_util_1.infoLogger)('streamContacts', `[${orderingKey}] Starting contact streaming`, providerConfig.apiKey);
175
- const publishContacts = (contacts) => __awaiter(this, void 0, void 0, function* () {
176
- var _a, _b;
177
- try {
178
- const { error: parsingError, data: parsedContacts } = schemas_1.contactsGetSchema.safeParse(contacts);
179
- if (parsingError) {
180
- throw new _1.ServerError(500, `Invalid contacts received: ${parsingError.message}`);
181
- }
182
- yield ((_a = this.pubSubContactStreamingClient) === null || _a === void 0 ? void 0 : _a.publishMessage({
183
- userId,
184
- timestamp,
185
- contacts: parsedContacts.map((contact) => (0, contact_util_1.sanitizeContact)(contact, providerConfig.locale)),
186
- state: pubsub_contacts_message_model_1.PubSubContactsState.IN_PROGRESS,
187
- integrationName: this.integrationName,
188
- }, orderingKey));
189
- // todo: remove as soon as platypus goes live
190
- yield ((_b = this.additionalPubSubContactStreamingClient) === null || _b === void 0 ? void 0 : _b.publishMessage({
191
- userId,
192
- timestamp,
193
- contacts: contacts.map((contact) => (0, contact_util_1.sanitizeContact)(contact, providerConfig.locale)),
194
- state: pubsub_contacts_message_model_1.PubSubContactsState.IN_PROGRESS,
195
- integrationName: this.integrationName,
196
- }, orderingKey));
197
- }
198
- catch (error) {
199
- if (error instanceof _1.ServerError) {
200
- (0, logger_util_1.errorLogger)('streamContacts', `[${orderingKey}] Could not publish contacts`, providerConfig.apiKey, { message: error.message, status: error.status });
201
- return;
202
- }
203
- (0, logger_util_1.errorLogger)('streamContacts', `[${orderingKey}] Could not publish contacts (${error})`, providerConfig.apiKey);
204
- }
205
- });
206
- const streamContacts = () => __awaiter(this, void 0, void 0, function* () {
207
- if (!this.adapter.streamContacts) {
208
- throw new _1.ServerError(501, 'Streaming contacts is not implemented');
209
- }
210
- const iterator = this.adapter.streamContacts(providerConfig);
211
- let result;
212
- do {
213
- result = yield iterator.next();
214
- const { value: contacts } = result;
215
- if (contacts && contacts.length > 0)
216
- yield publishContacts(contacts);
217
- } while (!result.done);
218
- });
219
- const streamingPromise = streamContacts()
220
- .then(() => {
221
- var _a, _b;
222
- (_a = this.additionalPubSubContactStreamingClient) === null || _a === void 0 ? void 0 : _a.publishMessage({
223
- userId: providerConfig.userId,
169
+ await this.pubSubContactStreamingClient?.publishMessage({
170
+ userId,
224
171
  timestamp,
225
- contacts: [],
226
- state: pubsub_contacts_message_model_1.PubSubContactsState.COMPLETE,
172
+ contacts: parsedContacts.map((contact) => (0, contact_util_1.sanitizeContact)(contact, providerConfig.locale)),
173
+ state: pubsub_contacts_message_model_1.PubSubContactsState.IN_PROGRESS,
227
174
  integrationName: this.integrationName,
228
175
  }, orderingKey);
229
- return (_b = this.pubSubContactStreamingClient) === null || _b === void 0 ? void 0 : _b.publishMessage({
230
- userId: providerConfig.userId,
176
+ // todo: remove as soon as platypus goes live
177
+ await this.additionalPubSubContactStreamingClient?.publishMessage({
178
+ userId,
231
179
  timestamp,
232
- contacts: [],
233
- state: pubsub_contacts_message_model_1.PubSubContactsState.COMPLETE,
180
+ contacts: contacts.map((contact) => (0, contact_util_1.sanitizeContact)(contact, providerConfig.locale)),
181
+ state: pubsub_contacts_message_model_1.PubSubContactsState.IN_PROGRESS,
234
182
  integrationName: this.integrationName,
235
183
  }, orderingKey);
236
- })
237
- .catch((error) => __awaiter(this, void 0, void 0, function* () {
238
- var _c, _d;
239
- (0, logger_util_1.errorLogger)('streamContacts', `[${orderingKey}] Could not stream contacts`, providerConfig.apiKey, error);
240
- (_c = this.additionalPubSubContactStreamingClient) === null || _c === void 0 ? void 0 : _c.publishMessage({
241
- userId: providerConfig.userId,
242
- timestamp,
243
- contacts: [],
244
- state: pubsub_contacts_message_model_1.PubSubContactsState.FAILED,
245
- integrationName: this.integrationName,
246
- }, orderingKey);
247
- return (_d = this.pubSubContactStreamingClient) === null || _d === void 0 ? void 0 : _d.publishMessage({
248
- userId: providerConfig.userId,
249
- timestamp,
250
- contacts: [],
251
- state: pubsub_contacts_message_model_1.PubSubContactsState.FAILED,
252
- integrationName: this.integrationName,
253
- }, orderingKey);
254
- }))
255
- .catch((error) => {
256
- (0, logger_util_1.errorLogger)('streamContacts', `[${orderingKey}] Could not publish failed message`, providerConfig.apiKey, error);
257
- })
258
- .finally(() => this.streamingPromises.delete(`${userId}:${timestamp}`));
259
- this.streamingPromises.set(`${userId}:${timestamp}`, streamingPromise);
260
- if (this.adapter.getToken && req.providerConfig) {
261
- try {
262
- const { apiKey } = yield this.adapter.getToken(req.providerConfig);
263
- res.header('X-Provider-Key', apiKey);
264
- }
265
- catch (error) {
266
- (0, logger_util_1.errorLogger)('streamContacts', `[${orderingKey}] Could not get and refresh token`, providerConfig.apiKey, error);
184
+ }
185
+ catch (error) {
186
+ if (error instanceof _1.ServerError) {
187
+ (0, logger_util_1.errorLogger)('streamContacts', `[${orderingKey}] Could not publish contacts`, providerConfig.apiKey, { message: error.message, status: error.status });
188
+ return;
267
189
  }
190
+ (0, logger_util_1.errorLogger)('streamContacts', `[${orderingKey}] Could not publish contacts (${error})`, providerConfig.apiKey);
191
+ }
192
+ };
193
+ const streamContacts = async () => {
194
+ if (!this.adapter.streamContacts) {
195
+ throw new _1.ServerError(501, 'Streaming contacts is not implemented');
196
+ }
197
+ const iterator = this.adapter.streamContacts(providerConfig);
198
+ let result;
199
+ do {
200
+ result = await iterator.next();
201
+ const { value: contacts } = result;
202
+ if (contacts && contacts.length > 0)
203
+ await publishContacts(contacts);
204
+ } while (!result.done);
205
+ };
206
+ const streamingPromise = streamContacts()
207
+ .then(() => {
208
+ this.additionalPubSubContactStreamingClient?.publishMessage({
209
+ userId: providerConfig.userId,
210
+ timestamp,
211
+ contacts: [],
212
+ state: pubsub_contacts_message_model_1.PubSubContactsState.COMPLETE,
213
+ integrationName: this.integrationName,
214
+ }, orderingKey);
215
+ return this.pubSubContactStreamingClient?.publishMessage({
216
+ userId: providerConfig.userId,
217
+ timestamp,
218
+ contacts: [],
219
+ state: pubsub_contacts_message_model_1.PubSubContactsState.COMPLETE,
220
+ integrationName: this.integrationName,
221
+ }, orderingKey);
222
+ })
223
+ .catch(async (error) => {
224
+ (0, logger_util_1.errorLogger)('streamContacts', `[${orderingKey}] Could not stream contacts`, providerConfig.apiKey, error);
225
+ this.additionalPubSubContactStreamingClient?.publishMessage({
226
+ userId: providerConfig.userId,
227
+ timestamp,
228
+ contacts: [],
229
+ state: pubsub_contacts_message_model_1.PubSubContactsState.FAILED,
230
+ integrationName: this.integrationName,
231
+ }, orderingKey);
232
+ return this.pubSubContactStreamingClient?.publishMessage({
233
+ userId: providerConfig.userId,
234
+ timestamp,
235
+ contacts: [],
236
+ state: pubsub_contacts_message_model_1.PubSubContactsState.FAILED,
237
+ integrationName: this.integrationName,
238
+ }, orderingKey);
239
+ })
240
+ .catch((error) => {
241
+ (0, logger_util_1.errorLogger)('streamContacts', `[${orderingKey}] Could not publish failed message`, providerConfig.apiKey, error);
242
+ })
243
+ .finally(() => this.streamingPromises.delete(`${userId}:${timestamp}`));
244
+ this.streamingPromises.set(`${userId}:${timestamp}`, streamingPromise);
245
+ if (this.adapter.getToken && req.providerConfig) {
246
+ try {
247
+ const { apiKey } = await this.adapter.getToken(req.providerConfig);
248
+ res.header('X-Provider-Key', apiKey);
268
249
  }
269
- (0, logger_util_1.infoLogger)(`streamContacts`, `[${orderingKey}] END`, providerConfig.apiKey);
270
- res.status(200).send({ timestamp });
271
- yield streamingPromise;
272
- }
273
- catch (error) {
274
- // prevent logging of refresh errors
275
- if (error instanceof _1.ServerError &&
276
- error.message === integration_error_model_1.IntegrationErrorType.INTEGRATION_REFRESH_ERROR) {
277
- next(error);
278
- return;
250
+ catch (error) {
251
+ (0, logger_util_1.errorLogger)('streamContacts', `[${orderingKey}] Could not get and refresh token`, providerConfig.apiKey, error);
279
252
  }
280
- (0, logger_util_1.errorLogger)('streamContacts', `Could not stream contacts`, providerConfig === null || providerConfig === void 0 ? void 0 : providerConfig.apiKey, error);
253
+ }
254
+ (0, logger_util_1.infoLogger)(`streamContacts`, `[${orderingKey}] END`, providerConfig.apiKey);
255
+ res.status(200).send({ timestamp });
256
+ await streamingPromise;
257
+ }
258
+ catch (error) {
259
+ // prevent logging of refresh errors
260
+ if (error instanceof _1.ServerError &&
261
+ error.message === integration_error_model_1.IntegrationErrorType.INTEGRATION_REFRESH_ERROR) {
281
262
  next(error);
263
+ return;
282
264
  }
283
- });
265
+ (0, logger_util_1.errorLogger)('streamContacts', `Could not stream contacts`, providerConfig?.apiKey, error);
266
+ next(error);
267
+ }
284
268
  }
285
- getContact(req, res, next) {
286
- return __awaiter(this, void 0, void 0, function* () {
287
- const { providerConfig } = req;
288
- try {
289
- if (!providerConfig) {
290
- throw new _1.ServerError(400, 'Missing parameters');
291
- }
292
- if (!this.adapter.getContact) {
293
- throw new _1.ServerError(501, 'Getting single contact is not implemented');
294
- }
295
- (0, logger_util_1.infoLogger)('getContact', 'START', providerConfig.apiKey);
296
- const contactType = Object.values(_1.IntegrationEntityType).find((value) => { var _a; return value === ((_a = req.query.type) === null || _a === void 0 ? void 0 : _a.toString()); });
297
- if (!contactType) {
298
- throw new _1.ServerError(400, 'Missing contact type query parameter');
299
- }
300
- const contactId = req.params.id;
301
- (0, logger_util_1.infoLogger)('getContact', `Fetching contact ${contactId} of type ${contactType}`, providerConfig.apiKey);
302
- const contact = yield this.adapter.getContact(providerConfig, contactId, contactType);
303
- (0, logger_util_1.infoLogger)('getContact', 'END', providerConfig.apiKey);
304
- res.status(200).send((0, contact_util_1.sanitizeContact)(contact, providerConfig.locale));
305
- }
306
- catch (error) {
307
- // prevent logging of refresh errors
308
- if (error instanceof _1.ServerError &&
309
- error.message === integration_error_model_1.IntegrationErrorType.INTEGRATION_REFRESH_ERROR) {
310
- next(error);
311
- return;
312
- }
313
- (0, logger_util_1.errorLogger)('getContact', 'Could not get contact:', providerConfig === null || providerConfig === void 0 ? void 0 : providerConfig.apiKey, error);
269
+ async getContact(req, res, next) {
270
+ const { providerConfig } = req;
271
+ try {
272
+ if (!providerConfig) {
273
+ throw new _1.ServerError(400, 'Missing parameters');
274
+ }
275
+ if (!this.adapter.getContact) {
276
+ throw new _1.ServerError(501, 'Getting single contact is not implemented');
277
+ }
278
+ (0, logger_util_1.infoLogger)('getContact', 'START', providerConfig.apiKey);
279
+ const contactType = Object.values(_1.IntegrationEntityType).find((value) => value === req.query.type?.toString());
280
+ if (!contactType) {
281
+ throw new _1.ServerError(400, 'Missing contact type query parameter');
282
+ }
283
+ const contactId = req.params.id;
284
+ (0, logger_util_1.infoLogger)('getContact', `Fetching contact ${contactId} of type ${contactType}`, providerConfig.apiKey);
285
+ const contact = await this.adapter.getContact(providerConfig, contactId, contactType);
286
+ (0, logger_util_1.infoLogger)('getContact', 'END', providerConfig.apiKey);
287
+ res.status(200).send((0, contact_util_1.sanitizeContact)(contact, providerConfig.locale));
288
+ }
289
+ catch (error) {
290
+ // prevent logging of refresh errors
291
+ if (error instanceof _1.ServerError &&
292
+ error.message === integration_error_model_1.IntegrationErrorType.INTEGRATION_REFRESH_ERROR) {
314
293
  next(error);
294
+ return;
315
295
  }
316
- });
296
+ (0, logger_util_1.errorLogger)('getContact', 'Could not get contact:', providerConfig?.apiKey, error);
297
+ next(error);
298
+ }
317
299
  }
318
- createContact(req, res, next) {
319
- return __awaiter(this, void 0, void 0, function* () {
320
- const { providerConfig: { apiKey = '', locale = '' } = {} } = req;
321
- try {
322
- (0, logger_util_1.infoLogger)('createContact', 'START', apiKey);
323
- if (!this.adapter.createContact) {
324
- throw new _1.ServerError(501, 'Creating contacts is not implemented');
325
- }
326
- if (!req.providerConfig) {
327
- throw new _1.ServerError(400, 'Missing config parameters');
328
- }
329
- const parseResultContactCreate = schemas_1.contactCreateSchema.safeParse(req.body);
330
- if (parseResultContactCreate.error)
331
- throw new _1.ServerError(400, `Invalid contactCreate received: ${parseResultContactCreate.error.message}`);
332
- (0, logger_util_1.infoLogger)('createContact', 'Creating contact', apiKey);
333
- const contact = yield this.adapter.createContact(req.providerConfig, parseResultContactCreate.data);
334
- const parseResultReturnContact = schemas_1.contactSchema.safeParse(contact);
335
- if (parseResultReturnContact.error)
336
- throw new _1.ServerError(500, `Invalid contact returned from bridge: ${parseResultReturnContact.error.message}`);
337
- (0, logger_util_1.infoLogger)('createContact', `Contact with id ${parseResultReturnContact.data.id} created`, apiKey);
338
- const sanitizedContact = (0, contact_util_1.sanitizeContact)(parseResultReturnContact.data, locale);
339
- if (this.adapter.getToken && req.providerConfig) {
340
- const { apiKey } = yield this.adapter.getToken(req.providerConfig);
341
- res.header('X-Provider-Key', apiKey);
342
- }
343
- res.status(200).send(sanitizedContact);
344
- if (this.contactCache) {
345
- const contacts = yield this.contactCache.get(apiKey);
346
- if (Array.isArray(contacts)) {
347
- yield this.contactCache.set(apiKey, [...contacts, sanitizedContact]);
348
- }
349
- }
350
- (0, logger_util_1.infoLogger)('createContact', 'END', apiKey);
351
- }
352
- catch (error) {
353
- // prevent logging of refresh errors
354
- if (error instanceof _1.ServerError &&
355
- error.message === integration_error_model_1.IntegrationErrorType.INTEGRATION_REFRESH_ERROR) {
356
- next(error);
357
- return;
358
- }
359
- (0, logger_util_1.errorLogger)('createContact', 'Could not create contact:', apiKey, error || 'Unknown');
360
- (0, logger_util_1.errorLogger)('createContact', 'Entity', apiKey, req.body);
300
+ async createContact(req, res, next) {
301
+ const { providerConfig: { apiKey = '', locale = '' } = {} } = req;
302
+ try {
303
+ (0, logger_util_1.infoLogger)('createContact', 'START', apiKey);
304
+ if (!this.adapter.createContact) {
305
+ throw new _1.ServerError(501, 'Creating contacts is not implemented');
306
+ }
307
+ if (!req.providerConfig) {
308
+ throw new _1.ServerError(400, 'Missing config parameters');
309
+ }
310
+ const parseResultContactCreate = schemas_1.contactCreateSchema.safeParse(req.body);
311
+ if (parseResultContactCreate.error)
312
+ throw new _1.ServerError(400, `Invalid contactCreate received: ${parseResultContactCreate.error.message}`);
313
+ (0, logger_util_1.infoLogger)('createContact', 'Creating contact', apiKey);
314
+ const contact = await this.adapter.createContact(req.providerConfig, parseResultContactCreate.data);
315
+ const parseResultReturnContact = schemas_1.contactSchema.safeParse(contact);
316
+ if (parseResultReturnContact.error)
317
+ throw new _1.ServerError(500, `Invalid contact returned from bridge: ${parseResultReturnContact.error.message}`);
318
+ (0, logger_util_1.infoLogger)('createContact', `Contact with id ${parseResultReturnContact.data.id} created`, apiKey);
319
+ const sanitizedContact = (0, contact_util_1.sanitizeContact)(parseResultReturnContact.data, locale);
320
+ if (this.adapter.getToken && req.providerConfig) {
321
+ const { apiKey } = await this.adapter.getToken(req.providerConfig);
322
+ res.header('X-Provider-Key', apiKey);
323
+ }
324
+ res.status(200).send(sanitizedContact);
325
+ if (this.contactCache) {
326
+ const contacts = await this.contactCache.get(apiKey);
327
+ if (Array.isArray(contacts)) {
328
+ await this.contactCache.set(apiKey, [...contacts, sanitizedContact]);
329
+ }
330
+ }
331
+ (0, logger_util_1.infoLogger)('createContact', 'END', apiKey);
332
+ }
333
+ catch (error) {
334
+ // prevent logging of refresh errors
335
+ if (error instanceof _1.ServerError &&
336
+ error.message === integration_error_model_1.IntegrationErrorType.INTEGRATION_REFRESH_ERROR) {
361
337
  next(error);
338
+ return;
362
339
  }
363
- });
340
+ (0, logger_util_1.errorLogger)('createContact', 'Could not create contact:', apiKey, error || 'Unknown');
341
+ (0, logger_util_1.errorLogger)('createContact', 'Entity', apiKey, req.body);
342
+ next(error);
343
+ }
364
344
  }
365
- updateContact(req, res, next) {
366
- return __awaiter(this, void 0, void 0, function* () {
367
- const { providerConfig: { apiKey = '', locale = '' } = {} } = req;
368
- try {
369
- if (!this.adapter.updateContact) {
370
- throw new _1.ServerError(501, 'Updating contacts is not implemented');
371
- }
372
- if (!req.providerConfig) {
373
- throw new _1.ServerError(400, 'Missing config parameters');
374
- }
375
- const parseResultContactUpdate = schemas_1.contactCreateSchema.safeParse(req.body);
376
- if (parseResultContactUpdate.error)
377
- throw new _1.ServerError(400, `Invalid contactUpdate received: ${parseResultContactUpdate.error.message}`);
378
- (0, logger_util_1.infoLogger)('updateContact', 'Updating contact', apiKey);
379
- const contact = yield this.adapter.updateContact(req.providerConfig, req.params.id, Object.assign(Object.assign({}, parseResultContactUpdate.data), { id: req.params.id }));
380
- const parseResultReturnContact = schemas_1.contactSchema.safeParse(contact);
381
- if (parseResultReturnContact.error)
382
- throw new _1.ServerError(500, `Invalid contact returned from bridge: ${parseResultReturnContact.error.message}`);
383
- (0, logger_util_1.infoLogger)('updateContact', `Contact with id ${parseResultReturnContact.data.id} updated`, apiKey);
384
- const sanitizedContact = (0, contact_util_1.sanitizeContact)(parseResultReturnContact.data, locale);
385
- if (this.adapter.getToken && req.providerConfig) {
386
- const { apiKey } = yield this.adapter.getToken(req.providerConfig);
387
- res.header('X-Provider-Key', apiKey);
388
- }
389
- res.status(200).send(sanitizedContact);
390
- if (this.contactCache) {
391
- const contacts = yield this.contactCache.get(apiKey);
392
- if (Array.isArray(contacts)) {
393
- const updatedCache = contacts.map((entry) => entry.id === sanitizedContact.id ? sanitizedContact : entry);
394
- yield this.contactCache.set(apiKey, updatedCache);
395
- }
396
- }
397
- (0, logger_util_1.infoLogger)('updateContact', 'END', apiKey);
398
- }
399
- catch (error) {
400
- // prevent logging of refresh errors
401
- if (error instanceof _1.ServerError &&
402
- error.message === integration_error_model_1.IntegrationErrorType.INTEGRATION_REFRESH_ERROR) {
403
- next(error);
404
- return;
405
- }
406
- (0, logger_util_1.errorLogger)('updateContact', 'Could not update contact:', apiKey, error || 'Unknown');
407
- (0, logger_util_1.errorLogger)('updateContact', 'Entity', apiKey, req.body);
345
+ async updateContact(req, res, next) {
346
+ const { providerConfig: { apiKey = '', locale = '' } = {} } = req;
347
+ try {
348
+ if (!this.adapter.updateContact) {
349
+ throw new _1.ServerError(501, 'Updating contacts is not implemented');
350
+ }
351
+ if (!req.providerConfig) {
352
+ throw new _1.ServerError(400, 'Missing config parameters');
353
+ }
354
+ const parseResultContactUpdate = schemas_1.contactCreateSchema.safeParse(req.body);
355
+ if (parseResultContactUpdate.error)
356
+ throw new _1.ServerError(400, `Invalid contactUpdate received: ${parseResultContactUpdate.error.message}`);
357
+ (0, logger_util_1.infoLogger)('updateContact', 'Updating contact', apiKey);
358
+ const contact = await this.adapter.updateContact(req.providerConfig, req.params.id, { ...parseResultContactUpdate.data, id: req.params.id });
359
+ const parseResultReturnContact = schemas_1.contactSchema.safeParse(contact);
360
+ if (parseResultReturnContact.error)
361
+ throw new _1.ServerError(500, `Invalid contact returned from bridge: ${parseResultReturnContact.error.message}`);
362
+ (0, logger_util_1.infoLogger)('updateContact', `Contact with id ${parseResultReturnContact.data.id} updated`, apiKey);
363
+ const sanitizedContact = (0, contact_util_1.sanitizeContact)(parseResultReturnContact.data, locale);
364
+ if (this.adapter.getToken && req.providerConfig) {
365
+ const { apiKey } = await this.adapter.getToken(req.providerConfig);
366
+ res.header('X-Provider-Key', apiKey);
367
+ }
368
+ res.status(200).send(sanitizedContact);
369
+ if (this.contactCache) {
370
+ const contacts = await this.contactCache.get(apiKey);
371
+ if (Array.isArray(contacts)) {
372
+ const updatedCache = contacts.map((entry) => entry.id === sanitizedContact.id ? sanitizedContact : entry);
373
+ await this.contactCache.set(apiKey, updatedCache);
374
+ }
375
+ }
376
+ (0, logger_util_1.infoLogger)('updateContact', 'END', apiKey);
377
+ }
378
+ catch (error) {
379
+ // prevent logging of refresh errors
380
+ if (error instanceof _1.ServerError &&
381
+ error.message === integration_error_model_1.IntegrationErrorType.INTEGRATION_REFRESH_ERROR) {
408
382
  next(error);
383
+ return;
409
384
  }
410
- });
385
+ (0, logger_util_1.errorLogger)('updateContact', 'Could not update contact:', apiKey, error || 'Unknown');
386
+ (0, logger_util_1.errorLogger)('updateContact', 'Entity', apiKey, req.body);
387
+ next(error);
388
+ }
411
389
  }
412
- deleteContact(req, res, next) {
413
- return __awaiter(this, void 0, void 0, function* () {
414
- const { providerConfig: { apiKey = '' } = {} } = req;
415
- try {
416
- (0, logger_util_1.infoLogger)('deleteContact', 'START', apiKey);
417
- if (!this.adapter.deleteContact) {
418
- throw new _1.ServerError(501, 'Deleting contacts is not implemented');
419
- }
420
- if (!req.providerConfig) {
421
- throw new _1.ServerError(400, 'Missing config parameters');
422
- }
423
- (0, logger_util_1.infoLogger)('deleteContact', 'Deleting contact', apiKey);
424
- const contactId = req.params.id;
425
- yield this.adapter.deleteContact(req.providerConfig, contactId);
426
- if (this.adapter.getToken && req.providerConfig) {
427
- const { apiKey } = yield this.adapter.getToken(req.providerConfig);
428
- res.header('X-Provider-Key', apiKey);
429
- }
430
- res.status(200).send();
431
- (0, logger_util_1.infoLogger)('deleteContact', `Contact with id ${contactId} deleted`, apiKey);
432
- if (this.contactCache) {
433
- const contacts = yield this.contactCache.get(apiKey);
434
- if (Array.isArray(contacts)) {
435
- const updatedCache = contacts.filter((entry) => entry.id !== contactId);
436
- yield this.contactCache.set(apiKey, updatedCache);
437
- }
438
- }
439
- (0, logger_util_1.infoLogger)('deleteContact', 'END', apiKey);
440
- }
441
- catch (error) {
442
- // prevent logging of refresh errors
443
- if (error instanceof _1.ServerError &&
444
- error.message === integration_error_model_1.IntegrationErrorType.INTEGRATION_REFRESH_ERROR) {
445
- next(error);
446
- return;
447
- }
448
- (0, logger_util_1.errorLogger)('deleteContact', 'Could not delete contact:', apiKey, error || 'Unknown');
390
+ async deleteContact(req, res, next) {
391
+ const { providerConfig: { apiKey = '' } = {} } = req;
392
+ try {
393
+ (0, logger_util_1.infoLogger)('deleteContact', 'START', apiKey);
394
+ if (!this.adapter.deleteContact) {
395
+ throw new _1.ServerError(501, 'Deleting contacts is not implemented');
396
+ }
397
+ if (!req.providerConfig) {
398
+ throw new _1.ServerError(400, 'Missing config parameters');
399
+ }
400
+ (0, logger_util_1.infoLogger)('deleteContact', 'Deleting contact', apiKey);
401
+ const contactId = req.params.id;
402
+ await this.adapter.deleteContact(req.providerConfig, contactId);
403
+ if (this.adapter.getToken && req.providerConfig) {
404
+ const { apiKey } = await this.adapter.getToken(req.providerConfig);
405
+ res.header('X-Provider-Key', apiKey);
406
+ }
407
+ res.status(200).send();
408
+ (0, logger_util_1.infoLogger)('deleteContact', `Contact with id ${contactId} deleted`, apiKey);
409
+ if (this.contactCache) {
410
+ const contacts = await this.contactCache.get(apiKey);
411
+ if (Array.isArray(contacts)) {
412
+ const updatedCache = contacts.filter((entry) => entry.id !== contactId);
413
+ await this.contactCache.set(apiKey, updatedCache);
414
+ }
415
+ }
416
+ (0, logger_util_1.infoLogger)('deleteContact', 'END', apiKey);
417
+ }
418
+ catch (error) {
419
+ // prevent logging of refresh errors
420
+ if (error instanceof _1.ServerError &&
421
+ error.message === integration_error_model_1.IntegrationErrorType.INTEGRATION_REFRESH_ERROR) {
449
422
  next(error);
423
+ return;
450
424
  }
451
- });
425
+ (0, logger_util_1.errorLogger)('deleteContact', 'Could not delete contact:', apiKey, error || 'Unknown');
426
+ next(error);
427
+ }
452
428
  }
453
429
  /**
454
430
  * @deprecated Use createOrUpdateCallLogForEntities instead
@@ -456,82 +432,76 @@ class Controller {
456
432
  * @param res
457
433
  * @param next
458
434
  */
459
- handleCallEvent(req, res, next) {
460
- return __awaiter(this, void 0, void 0, function* () {
461
- const { providerConfig } = req;
462
- try {
463
- (0, logger_util_1.infoLogger)('handleCallEvent', `START`, providerConfig === null || providerConfig === void 0 ? void 0 : providerConfig.apiKey);
464
- if (!providerConfig) {
465
- throw new _1.ServerError(400, 'Missing config parameters');
466
- }
467
- if (!this.adapter.handleCallEvent) {
468
- throw new _1.ServerError(501, 'Handling call event is not implemented');
469
- }
470
- if ((0, call_event_util_1.shouldSkipCallEvent)(req.body)) {
471
- (0, logger_util_1.infoLogger)('handleCallEvent', `Skipping call event for call id ${req.body.id}`, providerConfig.apiKey);
472
- res.status(200).send('Skipping call event');
473
- return;
474
- }
475
- (0, logger_util_1.infoLogger)('handleCallEvent', `Handling call event`, providerConfig.apiKey);
476
- const integrationCallEventRef = yield this.adapter.handleCallEvent(providerConfig, req.body);
477
- if (integrationCallEventRef != '')
478
- (0, logger_util_1.infoLogger)('handleCallEvent', `CallEvent with refId ${integrationCallEventRef} created!`, providerConfig.apiKey);
479
- else
480
- (0, logger_util_1.infoLogger)('handleCallEvent', `Did not create callEvent`, providerConfig.apiKey);
481
- (0, logger_util_1.infoLogger)('handleCallEvent', `END`, providerConfig.apiKey);
482
- res.status(200).send(integrationCallEventRef);
483
- }
484
- catch (error) {
485
- (0, logger_util_1.errorLogger)('handleCallEvent', 'Could not handle call event:', providerConfig === null || providerConfig === void 0 ? void 0 : providerConfig.apiKey, [error || 'Unknown', req.body]);
486
- next(error);
435
+ async handleCallEvent(req, res, next) {
436
+ const { providerConfig } = req;
437
+ try {
438
+ (0, logger_util_1.infoLogger)('handleCallEvent', `START`, providerConfig?.apiKey);
439
+ if (!providerConfig) {
440
+ throw new _1.ServerError(400, 'Missing config parameters');
487
441
  }
488
- });
489
- }
490
- handleConnectedEvent(req, res, next) {
491
- return __awaiter(this, void 0, void 0, function* () {
492
- const { providerConfig: { apiKey = '' } = {} } = req;
493
- try {
494
- (0, logger_util_1.infoLogger)('handleConnectedEvent', `START`, apiKey);
495
- if (!this.adapter.handleConnectedEvent) {
496
- throw new _1.ServerError(501, 'Handling connected event is not implemented');
497
- }
498
- if (!req.providerConfig) {
499
- throw new _1.ServerError(400, 'Missing config parameters');
500
- }
501
- (0, logger_util_1.infoLogger)('handleConnectedEvent', `Handling connected event`, apiKey);
502
- yield this.adapter.handleConnectedEvent(req.providerConfig);
503
- (0, logger_util_1.infoLogger)('handleConnectedEvent', `END`, apiKey);
504
- res.status(200).send();
505
- }
506
- catch (error) {
507
- (0, logger_util_1.errorLogger)('handleConnectedEvent', `Could not handle connected event:`, apiKey, error || 'Unknown');
508
- (0, logger_util_1.errorLogger)('handleConnectedEvent', 'Entity', apiKey, req.body);
509
- next(error);
442
+ if (!this.adapter.handleCallEvent) {
443
+ throw new _1.ServerError(501, 'Handling call event is not implemented');
510
444
  }
511
- });
512
- }
513
- handleDisconnectedEvent(req, res, next) {
514
- return __awaiter(this, void 0, void 0, function* () {
515
- const { providerConfig: { apiKey = '' } = {} } = req;
516
- try {
517
- (0, logger_util_1.infoLogger)('handleDisconnectedEvent', `START`, apiKey);
518
- if (!this.adapter.handleDisconnectedEvent) {
519
- throw new _1.ServerError(501, 'Handling disconnected event is not implemented');
520
- }
521
- if (!req.providerConfig) {
522
- throw new _1.ServerError(400, 'Missing config parameters');
523
- }
524
- (0, logger_util_1.infoLogger)('handleDisconnectedEvent', `Handling disconnected event`, apiKey);
525
- yield this.adapter.handleDisconnectedEvent(req.providerConfig);
526
- (0, logger_util_1.infoLogger)('handleDisconnectedEvent', `END`, apiKey);
527
- res.status(200).send();
528
- }
529
- catch (error) {
530
- (0, logger_util_1.errorLogger)('handleDisconnectedEvent', `Could not handle connected event:`, apiKey, error || 'Unknown');
531
- (0, logger_util_1.errorLogger)('handleDisconnectedEvent', 'Entity', apiKey, req.body);
532
- next(error);
445
+ if ((0, call_event_util_1.shouldSkipCallEvent)(req.body)) {
446
+ (0, logger_util_1.infoLogger)('handleCallEvent', `Skipping call event for call id ${req.body.id}`, providerConfig.apiKey);
447
+ res.status(200).send('Skipping call event');
448
+ return;
533
449
  }
534
- });
450
+ (0, logger_util_1.infoLogger)('handleCallEvent', `Handling call event`, providerConfig.apiKey);
451
+ const integrationCallEventRef = await this.adapter.handleCallEvent(providerConfig, req.body);
452
+ if (integrationCallEventRef != '')
453
+ (0, logger_util_1.infoLogger)('handleCallEvent', `CallEvent with refId ${integrationCallEventRef} created!`, providerConfig.apiKey);
454
+ else
455
+ (0, logger_util_1.infoLogger)('handleCallEvent', `Did not create callEvent`, providerConfig.apiKey);
456
+ (0, logger_util_1.infoLogger)('handleCallEvent', `END`, providerConfig.apiKey);
457
+ res.status(200).send(integrationCallEventRef);
458
+ }
459
+ catch (error) {
460
+ (0, logger_util_1.errorLogger)('handleCallEvent', 'Could not handle call event:', providerConfig?.apiKey, [error || 'Unknown', req.body]);
461
+ next(error);
462
+ }
463
+ }
464
+ async handleConnectedEvent(req, res, next) {
465
+ const { providerConfig: { apiKey = '' } = {} } = req;
466
+ try {
467
+ (0, logger_util_1.infoLogger)('handleConnectedEvent', `START`, apiKey);
468
+ if (!this.adapter.handleConnectedEvent) {
469
+ throw new _1.ServerError(501, 'Handling connected event is not implemented');
470
+ }
471
+ if (!req.providerConfig) {
472
+ throw new _1.ServerError(400, 'Missing config parameters');
473
+ }
474
+ (0, logger_util_1.infoLogger)('handleConnectedEvent', `Handling connected event`, apiKey);
475
+ await this.adapter.handleConnectedEvent(req.providerConfig);
476
+ (0, logger_util_1.infoLogger)('handleConnectedEvent', `END`, apiKey);
477
+ res.status(200).send();
478
+ }
479
+ catch (error) {
480
+ (0, logger_util_1.errorLogger)('handleConnectedEvent', `Could not handle connected event:`, apiKey, error || 'Unknown');
481
+ (0, logger_util_1.errorLogger)('handleConnectedEvent', 'Entity', apiKey, req.body);
482
+ next(error);
483
+ }
484
+ }
485
+ async handleDisconnectedEvent(req, res, next) {
486
+ const { providerConfig: { apiKey = '' } = {} } = req;
487
+ try {
488
+ (0, logger_util_1.infoLogger)('handleDisconnectedEvent', `START`, apiKey);
489
+ if (!this.adapter.handleDisconnectedEvent) {
490
+ throw new _1.ServerError(501, 'Handling disconnected event is not implemented');
491
+ }
492
+ if (!req.providerConfig) {
493
+ throw new _1.ServerError(400, 'Missing config parameters');
494
+ }
495
+ (0, logger_util_1.infoLogger)('handleDisconnectedEvent', `Handling disconnected event`, apiKey);
496
+ await this.adapter.handleDisconnectedEvent(req.providerConfig);
497
+ (0, logger_util_1.infoLogger)('handleDisconnectedEvent', `END`, apiKey);
498
+ res.status(200).send();
499
+ }
500
+ catch (error) {
501
+ (0, logger_util_1.errorLogger)('handleDisconnectedEvent', `Could not handle connected event:`, apiKey, error || 'Unknown');
502
+ (0, logger_util_1.errorLogger)('handleDisconnectedEvent', 'Entity', apiKey, req.body);
503
+ next(error);
504
+ }
535
505
  }
536
506
  /**
537
507
  * @deprecated Use createOrUpdateCallLogForEntities instead
@@ -539,207 +509,194 @@ class Controller {
539
509
  * @param res
540
510
  * @param next
541
511
  */
542
- updateCallEvent(req, res, next) {
543
- return __awaiter(this, void 0, void 0, function* () {
544
- const { providerConfig: { apiKey = '' } = {}, body, params } = req;
545
- try {
546
- (0, logger_util_1.infoLogger)('updateCallEvent', `START`, apiKey);
547
- if (!this.adapter.updateCallEvent) {
548
- throw new _1.ServerError(501, 'Updating call events is not implemented');
549
- }
550
- if (!req.providerConfig) {
551
- throw new _1.ServerError(400, 'Missing config parameters');
552
- }
553
- (0, logger_util_1.infoLogger)('updateCallEvent', `Updating call event`, apiKey);
554
- yield this.adapter.updateCallEvent(req.providerConfig, params.id, body);
555
- (0, logger_util_1.infoLogger)('updateCallEvent', `END`, apiKey);
556
- res.status(200).send();
557
- }
558
- catch (error) {
559
- (0, logger_util_1.errorLogger)('updateCallEvent', `Could not update call event:`, apiKey, error || 'Unknown');
560
- (0, logger_util_1.errorLogger)('updateCallEvent', 'Entity', apiKey, req.body);
561
- next(error);
562
- }
563
- });
512
+ async updateCallEvent(req, res, next) {
513
+ const { providerConfig: { apiKey = '' } = {}, body, params } = req;
514
+ try {
515
+ (0, logger_util_1.infoLogger)('updateCallEvent', `START`, apiKey);
516
+ if (!this.adapter.updateCallEvent) {
517
+ throw new _1.ServerError(501, 'Updating call events is not implemented');
518
+ }
519
+ if (!req.providerConfig) {
520
+ throw new _1.ServerError(400, 'Missing config parameters');
521
+ }
522
+ (0, logger_util_1.infoLogger)('updateCallEvent', `Updating call event`, apiKey);
523
+ await this.adapter.updateCallEvent(req.providerConfig, params.id, body);
524
+ (0, logger_util_1.infoLogger)('updateCallEvent', `END`, apiKey);
525
+ res.status(200).send();
526
+ }
527
+ catch (error) {
528
+ (0, logger_util_1.errorLogger)('updateCallEvent', `Could not update call event:`, apiKey, error || 'Unknown');
529
+ (0, logger_util_1.errorLogger)('updateCallEvent', 'Entity', apiKey, req.body);
530
+ next(error);
531
+ }
564
532
  }
565
- getEntity(req, res, next) {
566
- return __awaiter(this, void 0, void 0, function* () {
567
- const { providerConfig } = req;
568
- try {
569
- (0, logger_util_1.infoLogger)('getEntity', `START`, providerConfig === null || providerConfig === void 0 ? void 0 : providerConfig.apiKey);
570
- if (!providerConfig) {
571
- throw new _1.ServerError(400, 'Missing parameters');
572
- }
573
- if (!this.adapter.getEntity) {
574
- throw new _1.ServerError(501, 'Fetching Entity is not implemented');
575
- }
576
- const fetchedEntity = yield this.adapter.getEntity(providerConfig, req.params.id, req.params.type);
577
- (0, logger_util_1.infoLogger)('getEntity', `successfully got entity`, providerConfig.apiKey, Object.assign(Object.assign({}, fetchedEntity), { label: (0, anonymize_key_1.anonymizeKey)(fetchedEntity === null || fetchedEntity === void 0 ? void 0 : fetchedEntity.label) }));
578
- (0, logger_util_1.infoLogger)('getEntity', `END`, providerConfig.apiKey);
579
- res.status(200).send(fetchedEntity);
580
- }
581
- catch (error) {
582
- (0, logger_util_1.errorLogger)('getEntity', 'Could not get entity:', providerConfig === null || providerConfig === void 0 ? void 0 : providerConfig.apiKey, error);
583
- next(error);
533
+ async getEntity(req, res, next) {
534
+ const { providerConfig } = req;
535
+ try {
536
+ (0, logger_util_1.infoLogger)('getEntity', `START`, providerConfig?.apiKey);
537
+ if (!providerConfig) {
538
+ throw new _1.ServerError(400, 'Missing parameters');
584
539
  }
585
- });
586
- }
587
- getEntitiesForContact(req, res, next) {
588
- return __awaiter(this, void 0, void 0, function* () {
589
- const { providerConfig } = req;
590
- try {
591
- (0, logger_util_1.infoLogger)('getEntitiesForContact', `START`, providerConfig === null || providerConfig === void 0 ? void 0 : providerConfig.apiKey);
592
- if (!providerConfig) {
593
- throw new _1.ServerError(400, 'Missing parameters');
594
- }
595
- if (!this.adapter.getEntitiesForContact) {
596
- throw new _1.ServerError(501, 'Fetching Entities for contact is not implemented');
597
- }
598
- const fetchedEntities = yield this.adapter.getEntitiesForContact(providerConfig, req.params.id);
599
- (0, logger_util_1.infoLogger)('getEntitiesForContact', `successfully fetched ${fetchedEntities.length} entities`, providerConfig.apiKey, {
600
- count: fetchedEntities.length,
601
- });
602
- (0, logger_util_1.infoLogger)('getEntitiesForContact', `END`, providerConfig === null || providerConfig === void 0 ? void 0 : providerConfig.apiKey);
603
- res.status(200).send(fetchedEntities);
604
- }
605
- catch (error) {
606
- (0, logger_util_1.errorLogger)('getEntitiesForContact', 'Could not get entities for contact', providerConfig === null || providerConfig === void 0 ? void 0 : providerConfig.apiKey, error);
607
- next(error);
540
+ if (!this.adapter.getEntity) {
541
+ throw new _1.ServerError(501, 'Fetching Entity is not implemented');
608
542
  }
609
- });
543
+ const fetchedEntity = await this.adapter.getEntity(providerConfig, req.params.id, req.params.type);
544
+ (0, logger_util_1.infoLogger)('getEntity', `successfully got entity`, providerConfig.apiKey, {
545
+ ...fetchedEntity,
546
+ label: (0, anonymize_key_1.anonymizeKey)(fetchedEntity?.label),
547
+ });
548
+ (0, logger_util_1.infoLogger)('getEntity', `END`, providerConfig.apiKey);
549
+ res.status(200).send(fetchedEntity);
550
+ }
551
+ catch (error) {
552
+ (0, logger_util_1.errorLogger)('getEntity', 'Could not get entity:', providerConfig?.apiKey, error);
553
+ next(error);
554
+ }
610
555
  }
611
- getHealth(req, res, next) {
612
- return __awaiter(this, void 0, void 0, function* () {
613
- try {
614
- if (this.adapter.getHealth) {
615
- yield this.adapter.getHealth();
616
- }
617
- res.sendStatus(200);
556
+ async getEntitiesForContact(req, res, next) {
557
+ const { providerConfig } = req;
558
+ try {
559
+ (0, logger_util_1.infoLogger)('getEntitiesForContact', `START`, providerConfig?.apiKey);
560
+ if (!providerConfig) {
561
+ throw new _1.ServerError(400, 'Missing parameters');
618
562
  }
619
- catch (error) {
620
- (0, logger_util_1.errorLogger)('getHealth', 'Health check failed:', '', error || 'Unknown');
621
- next(error || 'Internal Server Error');
563
+ if (!this.adapter.getEntitiesForContact) {
564
+ throw new _1.ServerError(501, 'Fetching Entities for contact is not implemented');
622
565
  }
623
- });
566
+ const fetchedEntities = await this.adapter.getEntitiesForContact(providerConfig, req.params.id);
567
+ (0, logger_util_1.infoLogger)('getEntitiesForContact', `successfully fetched ${fetchedEntities.length} entities`, providerConfig.apiKey, {
568
+ count: fetchedEntities.length,
569
+ });
570
+ (0, logger_util_1.infoLogger)('getEntitiesForContact', `END`, providerConfig?.apiKey);
571
+ res.status(200).send(fetchedEntities);
572
+ }
573
+ catch (error) {
574
+ (0, logger_util_1.errorLogger)('getEntitiesForContact', 'Could not get entities for contact', providerConfig?.apiKey, error);
575
+ next(error);
576
+ }
624
577
  }
625
- oAuth2Redirect(req, res, next) {
626
- return __awaiter(this, void 0, void 0, function* () {
627
- try {
628
- if (!this.adapter.getOAuth2RedirectUrl) {
629
- throw new _1.ServerError(501, 'OAuth2 flow not implemented');
630
- }
631
- const redirectUrl = yield this.adapter.getOAuth2RedirectUrl(req, res);
632
- res.status(200).send({ redirectUrl });
633
- }
634
- catch (error) {
635
- (0, logger_util_1.errorLogger)('oAuth2Redirect', 'Could not get OAuth2 redirect URL:', '', error || 'Unknown');
636
- next(error);
578
+ async getHealth(req, res, next) {
579
+ try {
580
+ if (this.adapter.getHealth) {
581
+ await this.adapter.getHealth();
637
582
  }
638
- });
583
+ res.sendStatus(200);
584
+ }
585
+ catch (error) {
586
+ (0, logger_util_1.errorLogger)('getHealth', 'Health check failed:', '', error || 'Unknown');
587
+ next(error || 'Internal Server Error');
588
+ }
639
589
  }
640
- oAuth2Callback(req, res) {
641
- return __awaiter(this, void 0, void 0, function* () {
642
- const { OAUTH2_REDIRECT_URL: redirectUrl, OAUTH2_IDENTIFIER: oAuth2Identifier = 'UNKNOWN', } = process.env;
643
- if (!redirectUrl) {
644
- (0, logger_util_1.errorLogger)('oAuth2Callback', 'OAuth2 Redirect URL not configured!', '');
645
- res.status(500).send('OAuth2 Redirect URL not configured!');
646
- return;
590
+ async oAuth2Redirect(req, res, next) {
591
+ try {
592
+ if (!this.adapter.getOAuth2RedirectUrl) {
593
+ throw new _1.ServerError(501, 'OAuth2 flow not implemented');
647
594
  }
648
- try {
649
- if (!this.adapter.handleOAuth2Callback) {
650
- throw new _1.ServerError(501, 'OAuth2 flow not implemented');
651
- }
652
- const { apiKey, apiUrl } = yield this.adapter.handleOAuth2Callback(req, res);
653
- const params = (0, querystring_1.stringify)({
654
- name: oAuth2Identifier,
655
- key: apiKey,
656
- url: apiUrl,
657
- });
658
- res.redirect(`${redirectUrl}?${params}`);
659
- }
660
- catch (error) {
661
- (0, logger_util_1.errorLogger)('oAuth2Callback', 'Unable to save OAuth2 token:', '', error || 'Unknown');
662
- res.redirect(redirectUrl);
663
- }
664
- });
595
+ const redirectUrl = await this.adapter.getOAuth2RedirectUrl(req, res);
596
+ res.status(200).send({ redirectUrl });
597
+ }
598
+ catch (error) {
599
+ (0, logger_util_1.errorLogger)('oAuth2Redirect', 'Could not get OAuth2 redirect URL:', '', error || 'Unknown');
600
+ next(error);
601
+ }
665
602
  }
666
- oAuth2Token(req, res) {
667
- return __awaiter(this, void 0, void 0, function* () {
668
- try {
669
- if (!this.adapter.handleOAuth2Callback) {
670
- throw new _1.ServerError(501, 'OAuth2 flow not implemented');
671
- }
672
- const credentials = yield this.adapter.handleOAuth2Callback(req, res);
673
- res.json(credentials);
674
- }
675
- catch (error) {
676
- (0, logger_util_1.errorLogger)('oAuth2Callback', 'Unable to save OAuth2 token:', '', error || 'Unknown');
677
- throw error;
678
- }
679
- });
603
+ async oAuth2Callback(req, res) {
604
+ const { OAUTH2_REDIRECT_URL: redirectUrl, OAUTH2_IDENTIFIER: oAuth2Identifier = 'UNKNOWN', } = process.env;
605
+ if (!redirectUrl) {
606
+ (0, logger_util_1.errorLogger)('oAuth2Callback', 'OAuth2 Redirect URL not configured!', '');
607
+ res.status(500).send('OAuth2 Redirect URL not configured!');
608
+ return;
609
+ }
610
+ try {
611
+ if (!this.adapter.handleOAuth2Callback) {
612
+ throw new _1.ServerError(501, 'OAuth2 flow not implemented');
613
+ }
614
+ const { apiKey, apiUrl } = await this.adapter.handleOAuth2Callback(req, res);
615
+ const params = (0, querystring_1.stringify)({
616
+ name: oAuth2Identifier,
617
+ key: apiKey,
618
+ url: apiUrl,
619
+ });
620
+ res.redirect(`${redirectUrl}?${params}`);
621
+ }
622
+ catch (error) {
623
+ (0, logger_util_1.errorLogger)('oAuth2Callback', 'Unable to save OAuth2 token:', '', error || 'Unknown');
624
+ res.redirect(redirectUrl);
625
+ }
680
626
  }
681
- getAccountId(req, res, next) {
682
- return __awaiter(this, void 0, void 0, function* () {
683
- const { providerConfig } = req;
684
- try {
685
- if (!providerConfig) {
686
- throw new _1.ServerError(400, 'Missing parameters');
687
- }
688
- if (!this.adapter.getAccountId) {
689
- throw new _1.ServerError(501, 'Fetching account id is not implemented');
690
- }
691
- (0, logger_util_1.infoLogger)('getAccountId', 'START', providerConfig.apiKey);
692
- const accountId = yield this.adapter.getAccountId(providerConfig);
693
- if (!accountId) {
694
- throw new _1.ServerError(500, 'AccountID not found');
695
- }
696
- (0, logger_util_1.infoLogger)('getAccountId', 'END', providerConfig.apiKey);
697
- res.status(200).json(accountId.toString());
698
- }
699
- catch (error) {
700
- (0, logger_util_1.errorLogger)('getAccountId', 'Could not get AccountId', providerConfig === null || providerConfig === void 0 ? void 0 : providerConfig.apiKey, error);
701
- next(error);
627
+ async oAuth2Token(req, res) {
628
+ try {
629
+ if (!this.adapter.handleOAuth2Callback) {
630
+ throw new _1.ServerError(501, 'OAuth2 flow not implemented');
702
631
  }
703
- });
632
+ const credentials = await this.adapter.handleOAuth2Callback(req, res);
633
+ res.json(credentials);
634
+ }
635
+ catch (error) {
636
+ (0, logger_util_1.errorLogger)('oAuth2Callback', 'Unable to save OAuth2 token:', '', error || 'Unknown');
637
+ throw error;
638
+ }
704
639
  }
705
- handleWebhook(req, res, next) {
706
- return __awaiter(this, void 0, void 0, function* () {
707
- try {
708
- if (!this.adapter.handleWebhook) {
709
- throw new _1.ServerError(501, 'Webhook handling not implemented');
710
- }
711
- if (!this.adapter.verifyWebhookRequest) {
712
- throw new _1.ServerError(501, 'Webhook verification not implemented');
713
- }
714
- const verified = yield this.adapter.verifyWebhookRequest(req);
715
- if (!verified) {
716
- (0, logger_util_1.errorLogger)('handleWebhook', 'Webhook verification failed');
717
- throw new _1.ServerError(403, 'Webhook verification failed');
718
- }
719
- (0, logger_util_1.infoLogger)('handleWebhook', 'START');
720
- const events = yield this.adapter.handleWebhook(req);
721
- (0, logger_util_1.infoLogger)('handleWebhook', `Got ${events.length} events`);
722
- const deduplicatedEvents = (0, lodash_1.uniqWith)(events, lodash_1.isEqual);
723
- const publishResults = yield Promise.allSettled(deduplicatedEvents
724
- .map((event) => (Object.assign({ integrationName: this.integrationName }, event)))
725
- .map((message) => {
726
- var _a;
727
- (0, logger_util_1.infoLogger)('handleWebhook', `Publishing event ${message.type} with accountId ${message.accountId}`);
728
- return (_a = this.pubSubIntegrationEventsClient) === null || _a === void 0 ? void 0 : _a.publishMessage(message);
729
- }));
730
- publishResults.forEach((result) => {
731
- if (result.status === 'rejected') {
732
- (0, logger_util_1.errorLogger)('handleWebhook', `Could not publish event ${result.reason.type} with accountId ${result.reason.accountId}`, '', result.reason);
733
- }
734
- });
735
- (0, logger_util_1.infoLogger)('handleWebhook', 'END', '');
736
- res.sendStatus(200);
640
+ async getAccountId(req, res, next) {
641
+ const { providerConfig } = req;
642
+ try {
643
+ if (!providerConfig) {
644
+ throw new _1.ServerError(400, 'Missing parameters');
737
645
  }
738
- catch (error) {
739
- (0, logger_util_1.errorLogger)('handleWebhook', 'Could not handle webhook:', '', error || 'Unknown');
740
- next(error);
646
+ if (!this.adapter.getAccountId) {
647
+ throw new _1.ServerError(501, 'Fetching account id is not implemented');
648
+ }
649
+ (0, logger_util_1.infoLogger)('getAccountId', 'START', providerConfig.apiKey);
650
+ const accountId = await this.adapter.getAccountId(providerConfig);
651
+ if (!accountId) {
652
+ throw new _1.ServerError(500, 'AccountID not found');
741
653
  }
742
- });
654
+ (0, logger_util_1.infoLogger)('getAccountId', 'END', providerConfig.apiKey);
655
+ res.status(200).json(accountId.toString());
656
+ }
657
+ catch (error) {
658
+ (0, logger_util_1.errorLogger)('getAccountId', 'Could not get AccountId', providerConfig?.apiKey, error);
659
+ next(error);
660
+ }
661
+ }
662
+ async handleWebhook(req, res, next) {
663
+ try {
664
+ if (!this.adapter.handleWebhook) {
665
+ throw new _1.ServerError(501, 'Webhook handling not implemented');
666
+ }
667
+ if (!this.adapter.verifyWebhookRequest) {
668
+ throw new _1.ServerError(501, 'Webhook verification not implemented');
669
+ }
670
+ const verified = await this.adapter.verifyWebhookRequest(req);
671
+ if (!verified) {
672
+ (0, logger_util_1.errorLogger)('handleWebhook', 'Webhook verification failed');
673
+ throw new _1.ServerError(403, 'Webhook verification failed');
674
+ }
675
+ (0, logger_util_1.infoLogger)('handleWebhook', 'START');
676
+ const events = await this.adapter.handleWebhook(req);
677
+ (0, logger_util_1.infoLogger)('handleWebhook', `Got ${events.length} events`);
678
+ const deduplicatedEvents = (0, lodash_1.uniqWith)(events, lodash_1.isEqual);
679
+ const publishResults = await Promise.allSettled(deduplicatedEvents
680
+ .map((event) => ({
681
+ integrationName: this.integrationName,
682
+ ...event,
683
+ }))
684
+ .map((message) => {
685
+ (0, logger_util_1.infoLogger)('handleWebhook', `Publishing event ${message.type} with accountId ${message.accountId}`);
686
+ return this.pubSubIntegrationEventsClient?.publishMessage(message);
687
+ }));
688
+ publishResults.forEach((result) => {
689
+ if (result.status === 'rejected') {
690
+ (0, logger_util_1.errorLogger)('handleWebhook', `Could not publish event ${result.reason.type} with accountId ${result.reason.accountId}`, '', result.reason);
691
+ }
692
+ });
693
+ (0, logger_util_1.infoLogger)('handleWebhook', 'END', '');
694
+ res.sendStatus(200);
695
+ }
696
+ catch (error) {
697
+ (0, logger_util_1.errorLogger)('handleWebhook', 'Could not handle webhook:', '', error || 'Unknown');
698
+ next(error);
699
+ }
743
700
  }
744
701
  }
745
702
  exports.Controller = Controller;