@checkfirst/nestjs-outlook 6.1.2 → 6.1.3

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.
@@ -6,6 +6,7 @@ export declare class MicrosoftUser {
6
6
  tokenExpiry: Date;
7
7
  scopes: string;
8
8
  isActive: boolean;
9
+ defaultCalendarId: string | null;
9
10
  createdAt: Date;
10
11
  updatedAt: Date;
11
12
  }
@@ -19,6 +19,7 @@ let MicrosoftUser = class MicrosoftUser {
19
19
  this.tokenExpiry = new Date();
20
20
  this.scopes = '';
21
21
  this.isActive = true;
22
+ this.defaultCalendarId = null;
22
23
  this.createdAt = new Date();
23
24
  this.updatedAt = new Date();
24
25
  }
@@ -53,6 +54,10 @@ __decorate([
53
54
  (0, typeorm_1.Column)({ name: 'is_active', default: true }),
54
55
  __metadata("design:type", Boolean)
55
56
  ], MicrosoftUser.prototype, "isActive", void 0);
57
+ __decorate([
58
+ (0, typeorm_1.Column)({ name: 'default_calendar_id', type: 'varchar', length: 255, nullable: true }),
59
+ __metadata("design:type", Object)
60
+ ], MicrosoftUser.prototype, "defaultCalendarId", void 0);
56
61
  __decorate([
57
62
  (0, typeorm_1.CreateDateColumn)({ name: 'created_at' }),
58
63
  __metadata("design:type", Date)
@@ -1 +1 @@
1
- {"version":3,"file":"microsoft-user.entity.js","sourceRoot":"","sources":["../../src/entities/microsoft-user.entity.ts"],"names":[],"mappings":";;;;;;;;;;;;AAAA,qCAOiB;AAQV,IAAM,aAAa,GAAnB,MAAM,aAAa;IAAnB;QAML,mBAAc,GAAW,EAAE,CAAC;QAG5B,gBAAW,GAAW,EAAE,CAAC;QAGzB,iBAAY,GAAW,EAAE,CAAC;QAG1B,gBAAW,GAAS,IAAI,IAAI,EAAE,CAAC;QAG/B,WAAM,GAAW,EAAE,CAAC;QAGpB,aAAQ,GAAY,IAAI,CAAC;QAGzB,cAAS,GAAS,IAAI,IAAI,EAAE,CAAC;QAG7B,cAAS,GAAS,IAAI,IAAI,EAAE,CAAC;IAC/B,CAAC;CAAA,CAAA;AA5BY,sCAAa;AAExB;IADC,IAAA,gCAAsB,EAAC,WAAW,CAAC;;yCACxB;AAIZ;IAFC,IAAA,gBAAM,EAAC,EAAE,IAAI,EAAE,kBAAkB,EAAE,CAAC;IACpC,IAAA,eAAK,GAAE;;qDACoB;AAG5B;IADC,IAAA,gBAAM,EAAC,EAAE,IAAI,EAAE,cAAc,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC;;kDACtB;AAGzB;IADC,IAAA,gBAAM,EAAC,EAAE,IAAI,EAAE,eAAe,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC;;mDACtB;AAG1B;IADC,IAAA,gBAAM,EAAC,EAAE,IAAI,EAAE,cAAc,EAAE,IAAI,EAAE,UAAU,EAAE,CAAC;8BACtC,IAAI;kDAAc;AAG/B;IADC,IAAA,gBAAM,EAAC,EAAE,IAAI,EAAE,QAAQ,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC;;6CACrB;AAGpB;IADC,IAAA,gBAAM,EAAC,EAAE,IAAI,EAAE,WAAW,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC;;+CACpB;AAGzB;IADC,IAAA,0BAAgB,EAAC,EAAE,IAAI,EAAE,YAAY,EAAE,CAAC;8BAC9B,IAAI;gDAAc;AAG7B;IADC,IAAA,0BAAgB,EAAC,EAAE,IAAI,EAAE,YAAY,EAAE,CAAC;8BAC9B,IAAI;gDAAc;wBA3BlB,aAAa;IADzB,IAAA,gBAAM,EAAC,iBAAiB,CAAC;GACb,aAAa,CA4BzB"}
1
+ {"version":3,"file":"microsoft-user.entity.js","sourceRoot":"","sources":["../../src/entities/microsoft-user.entity.ts"],"names":[],"mappings":";;;;;;;;;;;;AAAA,qCAOiB;AAQV,IAAM,aAAa,GAAnB,MAAM,aAAa;IAAnB;QAML,mBAAc,GAAW,EAAE,CAAC;QAG5B,gBAAW,GAAW,EAAE,CAAC;QAGzB,iBAAY,GAAW,EAAE,CAAC;QAG1B,gBAAW,GAAS,IAAI,IAAI,EAAE,CAAC;QAG/B,WAAM,GAAW,EAAE,CAAC;QAGpB,aAAQ,GAAY,IAAI,CAAC;QAGzB,sBAAiB,GAAkB,IAAI,CAAC;QAGxC,cAAS,GAAS,IAAI,IAAI,EAAE,CAAC;QAG7B,cAAS,GAAS,IAAI,IAAI,EAAE,CAAC;IAC/B,CAAC;CAAA,CAAA;AA/BY,sCAAa;AAExB;IADC,IAAA,gCAAsB,EAAC,WAAW,CAAC;;yCACxB;AAIZ;IAFC,IAAA,gBAAM,EAAC,EAAE,IAAI,EAAE,kBAAkB,EAAE,CAAC;IACpC,IAAA,eAAK,GAAE;;qDACoB;AAG5B;IADC,IAAA,gBAAM,EAAC,EAAE,IAAI,EAAE,cAAc,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC;;kDACtB;AAGzB;IADC,IAAA,gBAAM,EAAC,EAAE,IAAI,EAAE,eAAe,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC;;mDACtB;AAG1B;IADC,IAAA,gBAAM,EAAC,EAAE,IAAI,EAAE,cAAc,EAAE,IAAI,EAAE,UAAU,EAAE,CAAC;8BACtC,IAAI;kDAAc;AAG/B;IADC,IAAA,gBAAM,EAAC,EAAE,IAAI,EAAE,QAAQ,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC;;6CACrB;AAGpB;IADC,IAAA,gBAAM,EAAC,EAAE,IAAI,EAAE,WAAW,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC;;+CACpB;AAGzB;IADC,IAAA,gBAAM,EAAC,EAAE,IAAI,EAAE,qBAAqB,EAAE,IAAI,EAAE,SAAS,EAAE,MAAM,EAAE,GAAG,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC;;wDAC9C;AAGxC;IADC,IAAA,0BAAgB,EAAC,EAAE,IAAI,EAAE,YAAY,EAAE,CAAC;8BAC9B,IAAI;gDAAc;AAG7B;IADC,IAAA,0BAAgB,EAAC,EAAE,IAAI,EAAE,YAAY,EAAE,CAAC;8BAC9B,IAAI;gDAAc;wBA9BlB,aAAa;IADzB,IAAA,gBAAM,EAAC,iBAAiB,CAAC;GACb,aAAa,CA+BzB"}
@@ -0,0 +1,5 @@
1
+ import { MigrationInterface, QueryRunner } from 'typeorm';
2
+ export declare class AddDefaultCalendarIdColumn1740400000000 implements MigrationInterface {
3
+ up(queryRunner: QueryRunner): Promise<void>;
4
+ down(queryRunner: QueryRunner): Promise<void>;
5
+ }
@@ -0,0 +1,19 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.AddDefaultCalendarIdColumn1740400000000 = void 0;
4
+ const typeorm_1 = require("typeorm");
5
+ class AddDefaultCalendarIdColumn1740400000000 {
6
+ async up(queryRunner) {
7
+ await queryRunner.addColumn('microsoft_users', new typeorm_1.TableColumn({
8
+ name: 'default_calendar_id',
9
+ type: 'varchar',
10
+ length: '255',
11
+ isNullable: true,
12
+ }));
13
+ }
14
+ async down(queryRunner) {
15
+ await queryRunner.dropColumn('microsoft_users', 'default_calendar_id');
16
+ }
17
+ }
18
+ exports.AddDefaultCalendarIdColumn1740400000000 = AddDefaultCalendarIdColumn1740400000000;
19
+ //# sourceMappingURL=1740400000000-AddDefaultCalendarIdColumn.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"1740400000000-AddDefaultCalendarIdColumn.js","sourceRoot":"","sources":["../../src/migrations/1740400000000-AddDefaultCalendarIdColumn.ts"],"names":[],"mappings":";;;AAAA,qCAAuE;AAEvE,MAAa,uCAAuC;IAC3C,KAAK,CAAC,EAAE,CAAC,WAAwB;QACtC,MAAM,WAAW,CAAC,SAAS,CACzB,iBAAiB,EACjB,IAAI,qBAAW,CAAC;YACd,IAAI,EAAE,qBAAqB;YAC3B,IAAI,EAAE,SAAS;YACf,MAAM,EAAE,KAAK;YACb,UAAU,EAAE,IAAI;SACjB,CAAC,CACH,CAAC;IACJ,CAAC;IAEM,KAAK,CAAC,IAAI,CAAC,WAAwB;QACxC,MAAM,WAAW,CAAC,UAAU,CAAC,iBAAiB,EAAE,qBAAqB,CAAC,CAAC;IACzE,CAAC;CACF;AAhBD,0FAgBC"}
@@ -77,7 +77,7 @@ let OutlookWebhookSubscriptionRepository = class OutlookWebhookSubscriptionRepos
77
77
  });
78
78
  }
79
79
  async count(options) {
80
- return this.repository.count(options);
80
+ return await this.repository.count(options);
81
81
  }
82
82
  };
83
83
  exports.OutlookWebhookSubscriptionRepository = OutlookWebhookSubscriptionRepository;
@@ -1 +1 @@
1
- {"version":3,"file":"outlook-webhook-subscription.repository.js","sourceRoot":"","sources":["../../src/repositories/outlook-webhook-subscription.repository.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"outlook-webhook-subscription.repository.js","sourceRoot":"","sources":["../../src/repositories/outlook-webhook-subscription.repository.ts"],"names":[],"mappings":"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"}
@@ -53,7 +53,6 @@ const typeorm_1 = require("@nestjs/typeorm");
53
53
  const microsoft_user_entity_1 = require("../../entities/microsoft-user.entity");
54
54
  const typeorm_2 = require("typeorm");
55
55
  const delta_sync_service_1 = require("../shared/delta-sync.service");
56
- const retry_util_1 = require("../../utils/retry.util");
57
56
  const user_id_converter_service_1 = require("../shared/user-id-converter.service");
58
57
  const resource_type_enum_1 = require("../../enums/resource-type.enum");
59
58
  const microsoft_subscription_service_1 = require("../subscription/microsoft-subscription.service");
@@ -99,25 +98,45 @@ let CalendarService = CalendarService_1 = class CalendarService {
99
98
  }
100
99
  async getDefaultCalendarId(externalUserId) {
101
100
  try {
102
- const accessToken = await this.microsoftAuthService.getUserAccessToken({ externalUserId });
103
- const response = await axios_1.default.get("https://graph.microsoft.com/v1.0/me/calendar", {
101
+ const user = await this.microsoftUserRepository.findOne({
102
+ where: { externalUserId, isActive: true },
103
+ cache: true,
104
+ });
105
+ if (!user) {
106
+ throw new Error(`No Microsoft user found for external user ID ${externalUserId}`);
107
+ }
108
+ if (user.defaultCalendarId) {
109
+ this.logger.debug(`Using cached calendar ID for user ${externalUserId}`);
110
+ return user.defaultCalendarId;
111
+ }
112
+ this.logger.debug(`Fetching calendar ID from Microsoft for user ${externalUserId}`);
113
+ const accessToken = await this.microsoftAuthService.getUserAccessToken({ externalUserId, cache: true });
114
+ await this.rateLimiter.acquirePermit(externalUserId);
115
+ const response = await (0, outlook_api_executor_util_1.executeGraphApiCall)(() => axios_1.default.get("https://graph.microsoft.com/v1.0/me/calendar", {
104
116
  headers: {
105
117
  Authorization: `Bearer ${accessToken}`,
106
118
  "Content-Type": "application/json",
107
119
  },
120
+ }), {
121
+ logger: this.logger,
122
+ resourceName: `me/calendar for user ${externalUserId}`,
123
+ maxRetries: 3,
108
124
  });
109
- if (!response.data.id) {
125
+ if (!(response === null || response === void 0 ? void 0 : response.data.id)) {
110
126
  throw new Error("Failed to retrieve calendar ID");
111
127
  }
112
- return response.data.id;
128
+ const calendarId = response.data.id;
129
+ user.defaultCalendarId = calendarId;
130
+ await this.microsoftUserRepository.save(user);
131
+ this.logger.log(`Cached calendar ID for user ${externalUserId}`);
132
+ return calendarId;
113
133
  }
114
134
  catch (error) {
115
- this.logger.error("Error getting default calendar ID:", error);
135
+ this.logger.error(`Error getting default calendar ID for user ${externalUserId}:`, error);
116
136
  throw new Error("Failed to get calendar ID from Microsoft");
117
137
  }
118
138
  }
119
139
  async createEvent(event, externalUserId, calendarId) {
120
- await this.rateLimiter.acquirePermit(externalUserId);
121
140
  try {
122
141
  const accessToken = await this.microsoftAuthService.getUserAccessToken({ externalUserId });
123
142
  const client = microsoft_graph_client_1.Client.init({
@@ -125,9 +144,13 @@ let CalendarService = CalendarService_1 = class CalendarService {
125
144
  done(null, accessToken);
126
145
  },
127
146
  });
128
- const createdEvent = (await client
129
- .api(`/me/calendars/${calendarId}/events`)
130
- .post(event));
147
+ const createdEvent = (await (0, outlook_api_executor_util_1.executeGraphApiCall)(() => client.api(`/me/calendars/${calendarId}/events`).post(event), {
148
+ logger: this.logger,
149
+ resourceName: `create event in calendar ${calendarId} for user ${externalUserId}`,
150
+ maxRetries: 3,
151
+ rateLimiter: this.rateLimiter,
152
+ userId: externalUserId,
153
+ }));
131
154
  return {
132
155
  event: createdEvent,
133
156
  };
@@ -137,12 +160,8 @@ let CalendarService = CalendarService_1 = class CalendarService {
137
160
  this.logger.error(`Failed to create Outlook calendar event: ${errorMessage}`);
138
161
  throw new Error(`Failed to create Outlook calendar event: ${errorMessage}`);
139
162
  }
140
- finally {
141
- this.rateLimiter.releasePermit(externalUserId);
142
- }
143
163
  }
144
164
  async updateEvent(eventId, updates, externalUserId, calendarId) {
145
- await this.rateLimiter.acquirePermit(externalUserId);
146
165
  try {
147
166
  const accessToken = await this.microsoftAuthService.getUserAccessToken({ externalUserId });
148
167
  const client = microsoft_graph_client_1.Client.init({
@@ -151,9 +170,13 @@ let CalendarService = CalendarService_1 = class CalendarService {
151
170
  },
152
171
  });
153
172
  this.logger.log(`Updating event ${eventId} in calendar ${calendarId} for user ${externalUserId}`);
154
- const updatedEvent = (await client
155
- .api(`/me/calendars/${calendarId}/events/${eventId}`)
156
- .patch(updates));
173
+ const updatedEvent = (await (0, outlook_api_executor_util_1.executeGraphApiCall)(() => client.api(`/me/calendars/${calendarId}/events/${eventId}`).patch(updates), {
174
+ logger: this.logger,
175
+ resourceName: `update event ${eventId} in calendar ${calendarId} for user ${externalUserId}`,
176
+ maxRetries: 3,
177
+ rateLimiter: this.rateLimiter,
178
+ userId: externalUserId,
179
+ }));
157
180
  return {
158
181
  event: updatedEvent,
159
182
  };
@@ -163,12 +186,8 @@ let CalendarService = CalendarService_1 = class CalendarService {
163
186
  this.logger.error(`Failed to update Outlook calendar event: ${errorMessage}`);
164
187
  throw new Error(`Failed to update Outlook calendar event: ${errorMessage}`);
165
188
  }
166
- finally {
167
- this.rateLimiter.releasePermit(externalUserId);
168
- }
169
189
  }
170
190
  async deleteEvent(event, externalUserId, calendarId) {
171
- await this.rateLimiter.acquirePermit(externalUserId);
172
191
  try {
173
192
  const internalUserId = await this.userIdConverter.toInternalUserId(externalUserId);
174
193
  const accessToken = await this.microsoftAuthService.getUserAccessToken({ internalUserId });
@@ -178,24 +197,20 @@ let CalendarService = CalendarService_1 = class CalendarService {
178
197
  },
179
198
  });
180
199
  this.logger.log(`Deleting event ${event.id} from calendar ${calendarId} for user ${externalUserId}`);
181
- await (0, retry_util_1.retryWithBackoff)(async () => {
182
- await client
183
- .api(`/me/calendars/${calendarId}/events/${event.id}`)
184
- .delete();
185
- }, { maxRetries: 3, retryDelayMs: 1000 });
200
+ await (0, outlook_api_executor_util_1.executeGraphApiCall)(() => client.api(`/me/calendars/${calendarId}/events/${event.id}`).delete(), {
201
+ logger: this.logger,
202
+ resourceName: `delete event ${event.id} from calendar ${calendarId} for user ${externalUserId}`,
203
+ maxRetries: 3,
204
+ rateLimiter: this.rateLimiter,
205
+ userId: externalUserId,
206
+ return404AsNull: true,
207
+ });
186
208
  }
187
209
  catch (error) {
188
- if ((0, retry_util_1.is404Error)(error)) {
189
- this.logger.warn(`Outlook calendar event ${event.id} not found (already deleted), treating as successful deletion`);
190
- return;
191
- }
192
210
  const errorMessage = error instanceof Error ? error.message : "Unknown error";
193
211
  this.logger.error(`Failed to delete Outlook calendar event after retries: ${errorMessage}`);
194
212
  throw new Error(`Failed to delete Outlook calendar event: ${errorMessage}`);
195
213
  }
196
- finally {
197
- this.rateLimiter.releasePermit(externalUserId);
198
- }
199
214
  }
200
215
  async createBatchEvents(events, externalUserId, calendarId) {
201
216
  if (events.length === 0) {
@@ -222,15 +237,20 @@ let CalendarService = CalendarService_1 = class CalendarService {
222
237
  })),
223
238
  };
224
239
  this.logger.log(`Creating batch of ${batchEvents.length} events in calendar ${calendarId} for user ${externalUserId}`);
225
- const batchResponse = await (0, retry_util_1.retryWithBackoff)(async () => {
226
- const response = await axios_1.default.post('https://graph.microsoft.com/v1.0/$batch', batchPayload, {
227
- headers: {
228
- Authorization: `Bearer ${accessToken}`,
229
- 'Content-Type': 'application/json',
230
- },
231
- });
232
- return response.data;
233
- }, { maxRetries: 3, retryDelayMs: 1000 });
240
+ const response = await (0, outlook_api_executor_util_1.executeGraphApiCall)(() => axios_1.default.post('https://graph.microsoft.com/v1.0/$batch', batchPayload, {
241
+ headers: {
242
+ Authorization: `Bearer ${accessToken}`,
243
+ 'Content-Type': 'application/json',
244
+ },
245
+ }), {
246
+ logger: this.logger,
247
+ resourceName: `batch create ${batchEvents.length} events for user ${externalUserId}`,
248
+ maxRetries: 3,
249
+ });
250
+ const batchResponse = response === null || response === void 0 ? void 0 : response.data;
251
+ if (!batchResponse) {
252
+ throw new Error('Batch request returned null response');
253
+ }
234
254
  batchResponse.responses.forEach((response, batchIndex) => {
235
255
  const globalIndex = i + batchIndex;
236
256
  if (response.status === 201) {
@@ -307,15 +327,20 @@ let CalendarService = CalendarService_1 = class CalendarService {
307
327
  };
308
328
  this.logger.log(`Updating batch of ${batchUpdates.length} events in calendar ${calendarId} for user ${externalUserId}`);
309
329
  try {
310
- const batchResponse = await (0, retry_util_1.retryWithBackoff)(async () => {
311
- const response = await axios_1.default.post('https://graph.microsoft.com/v1.0/$batch', batchPayload, {
312
- headers: {
313
- Authorization: `Bearer ${accessToken}`,
314
- 'Content-Type': 'application/json',
315
- },
316
- });
317
- return response.data;
318
- }, { maxRetries: 3, retryDelayMs: 1000 });
330
+ const response = await (0, outlook_api_executor_util_1.executeGraphApiCall)(() => axios_1.default.post('https://graph.microsoft.com/v1.0/$batch', batchPayload, {
331
+ headers: {
332
+ Authorization: `Bearer ${accessToken}`,
333
+ 'Content-Type': 'application/json',
334
+ },
335
+ }), {
336
+ logger: this.logger,
337
+ resourceName: `batch update ${batchUpdates.length} events for user ${externalUserId}`,
338
+ maxRetries: 3,
339
+ });
340
+ const batchResponse = response === null || response === void 0 ? void 0 : response.data;
341
+ if (!batchResponse) {
342
+ throw new Error('Batch request returned null response');
343
+ }
319
344
  batchResponse.responses.forEach((response, batchIndex) => {
320
345
  const globalIndex = i + batchIndex;
321
346
  if (response.status === 200) {
@@ -385,15 +410,20 @@ let CalendarService = CalendarService_1 = class CalendarService {
385
410
  };
386
411
  this.logger.log(`Deleting batch of ${batchEventIds.length} events from calendar ${calendarId} for user ${externalUserId}`);
387
412
  try {
388
- const batchResponse = await (0, retry_util_1.retryWithBackoff)(async () => {
389
- const response = await axios_1.default.post('https://graph.microsoft.com/v1.0/$batch', batchPayload, {
390
- headers: {
391
- Authorization: `Bearer ${accessToken}`,
392
- 'Content-Type': 'application/json',
393
- },
394
- });
395
- return response.data;
396
- }, { maxRetries: 3, retryDelayMs: 1000 });
413
+ const response = await (0, outlook_api_executor_util_1.executeGraphApiCall)(() => axios_1.default.post('https://graph.microsoft.com/v1.0/$batch', batchPayload, {
414
+ headers: {
415
+ Authorization: `Bearer ${accessToken}`,
416
+ 'Content-Type': 'application/json',
417
+ },
418
+ }), {
419
+ logger: this.logger,
420
+ resourceName: `batch delete ${batchEventIds.length} events for user ${externalUserId}`,
421
+ maxRetries: 3,
422
+ });
423
+ const batchResponse = response === null || response === void 0 ? void 0 : response.data;
424
+ if (!batchResponse) {
425
+ throw new Error('Batch request returned null response');
426
+ }
397
427
  batchResponse.responses.forEach((response, index) => {
398
428
  const eventId = batchEventIds[index];
399
429
  if (response.status === 204 || response.status === 404) {
@@ -467,12 +497,19 @@ let CalendarService = CalendarService_1 = class CalendarService {
467
497
  this.logger.log(`[${correlationId}] Creating webhook subscription with notificationUrl: ${notificationUrl}`);
468
498
  this.logger.debug(`[${correlationId}] Subscription data: ${JSON.stringify(subscriptionData)}`);
469
499
  this.logger.log(`[${correlationId}] Sending POST request to Microsoft Graph API`);
470
- const response = await axios_1.default.post("https://graph.microsoft.com/v1.0/subscriptions", subscriptionData, {
500
+ const response = await (0, outlook_api_executor_util_1.executeGraphApiCall)(() => axios_1.default.post("https://graph.microsoft.com/v1.0/subscriptions", subscriptionData, {
471
501
  headers: {
472
502
  Authorization: `Bearer ${accessToken}`,
473
503
  "Content-Type": "application/json",
474
504
  },
505
+ }), {
506
+ logger: this.logger,
507
+ resourceName: `create webhook subscription for user ${internalUserId}`,
508
+ maxRetries: 3,
475
509
  });
510
+ if (!(response === null || response === void 0 ? void 0 : response.data)) {
511
+ throw new Error('Subscription creation returned null response');
512
+ }
476
513
  this.logger.log(`[${correlationId}] Created webhook subscription ${response.data.id || "unknown"} for user ${internalUserId}`);
477
514
  this.logger.log(`[${correlationId}] Saving subscription to database (internalUserId: ${internalUserId}, externalUserId: ${externalUserId})`);
478
515
  await this.webhookSubscriptionRepository.saveSubscription({
@@ -528,12 +565,19 @@ let CalendarService = CalendarService_1 = class CalendarService {
528
565
  expirationDateTime: expirationDateTime.toISOString(),
529
566
  };
530
567
  this.logger.debug(`[${correlationId}] Calling Microsoft Graph API to renew subscription`);
531
- const response = await axios_1.default.patch(`https://graph.microsoft.com/v1.0/subscriptions/${subscriptionId}`, renewalData, {
568
+ const response = await (0, outlook_api_executor_util_1.executeGraphApiCall)(() => axios_1.default.patch(`https://graph.microsoft.com/v1.0/subscriptions/${subscriptionId}`, renewalData, {
532
569
  headers: {
533
570
  Authorization: `Bearer ${accessToken}`,
534
571
  "Content-Type": "application/json",
535
572
  },
573
+ }), {
574
+ logger: this.logger,
575
+ resourceName: `renew webhook subscription ${subscriptionId} for user ${internalUserId}`,
576
+ maxRetries: 3,
536
577
  });
578
+ if (!(response === null || response === void 0 ? void 0 : response.data)) {
579
+ throw new Error('Subscription renewal returned null response');
580
+ }
537
581
  this.logger.debug(`[${correlationId}] Microsoft Graph API returned status: ${response.status}`);
538
582
  if (response.data.expirationDateTime) {
539
583
  await this.webhookSubscriptionRepository.updateSubscriptionExpiration(subscriptionId, new Date(response.data.expirationDateTime));
@@ -788,21 +832,21 @@ let CalendarService = CalendarService_1 = class CalendarService {
788
832
  this.logger.log(`[saveDeltaLink] Saved delta link for user ${externalUserId} (internal: ${internalUserId})`);
789
833
  }
790
834
  async getEventDetails(resource, externalUserId) {
791
- var _a;
792
835
  try {
793
836
  const accessToken = await this.microsoftAuthService.getUserAccessToken({ externalUserId });
794
- const response = await axios_1.default.get(`https://graph.microsoft.com/v1.0/${resource}`, {
837
+ const response = await (0, outlook_api_executor_util_1.executeGraphApiCall)(() => axios_1.default.get(`https://graph.microsoft.com/v1.0/${resource}`, {
795
838
  headers: {
796
839
  Authorization: `Bearer ${accessToken}`,
797
840
  },
841
+ }), {
842
+ logger: this.logger,
843
+ resourceName: `event details for ${resource}`,
844
+ maxRetries: 3,
845
+ return404AsNull: true,
798
846
  });
799
- return response.data;
847
+ return response === null || response === void 0 ? void 0 : response.data;
800
848
  }
801
849
  catch (error) {
802
- if (axios_1.default.isAxiosError(error) && ((_a = error.response) === null || _a === void 0 ? void 0 : _a.status) === 404) {
803
- this.logger.debug(`Event not found (404) for resource ${resource}, likely deleted - returning null`);
804
- return null;
805
- }
806
850
  this.logger.error("Error fetching event details:", error);
807
851
  throw error;
808
852
  }
@@ -932,7 +976,12 @@ let CalendarService = CalendarService_1 = class CalendarService {
932
976
  let totalFetched = 0;
933
977
  while (nextLink) {
934
978
  this.logger.debug(`Fetching page: ${nextLink}`);
935
- const response = (yield __await((0, retry_util_1.retryWithBackoff)(() => client.api(nextLink).get())));
979
+ const response = (yield __await((0, outlook_api_executor_util_1.executeGraphApiCall)(() => client.api(nextLink).get(), {
980
+ logger: this.logger,
981
+ resourceName: `calendarView for user ${externalUserId}`,
982
+ rateLimiter: this.rateLimiter,
983
+ userId: externalUserId,
984
+ })));
936
985
  const items = response.value;
937
986
  buffer.push(...items);
938
987
  totalFetched += items.length;
@@ -942,9 +991,6 @@ let CalendarService = CalendarService_1 = class CalendarService {
942
991
  yield yield __await(chunk);
943
992
  }
944
993
  nextLink = response["@odata.nextLink"];
945
- if (nextLink) {
946
- yield __await((0, retry_util_1.delay)(200));
947
- }
948
994
  }
949
995
  if (buffer.length > 0) {
950
996
  this.logger.debug(`Yielding final chunk of ${buffer.length} items`);
@@ -1005,7 +1051,12 @@ let CalendarService = CalendarService_1 = class CalendarService {
1005
1051
  const buffer = [];
1006
1052
  let totalFetched = 0;
1007
1053
  while (nextLink) {
1008
- const response = (yield __await((0, retry_util_1.retryWithBackoff)(() => client.api(nextLink).get())));
1054
+ const response = (yield __await((0, outlook_api_executor_util_1.executeGraphApiCall)(() => client.api(nextLink).get(), {
1055
+ logger: this.logger,
1056
+ resourceName: `recurring event instances for series ${seriesMasterId}`,
1057
+ rateLimiter: this.rateLimiter,
1058
+ userId: externalUserId,
1059
+ })));
1009
1060
  const items = response.value;
1010
1061
  buffer.push(...items);
1011
1062
  totalFetched += items.length;
@@ -1014,9 +1065,6 @@ let CalendarService = CalendarService_1 = class CalendarService {
1014
1065
  yield yield __await(chunk);
1015
1066
  }
1016
1067
  nextLink = response['@odata.nextLink'];
1017
- if (nextLink) {
1018
- yield __await((0, retry_util_1.delay)(200));
1019
- }
1020
1068
  }
1021
1069
  if (buffer.length > 0) {
1022
1070
  yield yield __await(buffer);