@checkfirst/nestjs-outlook
Version:
An opinionated NestJS module for Microsoft Outlook integration that provides easy access to Microsoft Graph API for emails, calendars, and more.
550 lines • 30.2 kB
JavaScript
;
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
return c > 3 && r && Object.defineProperty(target, key, r), r;
};
var __metadata = (this && this.__metadata) || function (k, v) {
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
};
var __param = (this && this.__param) || function (paramIndex, decorator) {
return function (target, key) { decorator(target, key, paramIndex); }
};
var __await = (this && this.__await) || function (v) { return this instanceof __await ? (this.v = v, this) : new __await(v); }
var __asyncValues = (this && this.__asyncValues) || function (o) {
if (!Symbol.asyncIterator) throw new TypeError("Symbol.asyncIterator is not defined.");
var m = o[Symbol.asyncIterator], i;
return m ? m.call(o) : (o = typeof __values === "function" ? __values(o) : o[Symbol.iterator](), i = {}, verb("next"), verb("throw"), verb("return"), i[Symbol.asyncIterator] = function () { return this; }, i);
function verb(n) { i[n] = o[n] && function (v) { return new Promise(function (resolve, reject) { v = o[n](v), settle(resolve, reject, v.done, v.value); }); }; }
function settle(resolve, reject, d, v) { Promise.resolve(v).then(function(v) { resolve({ value: v, done: d }); }, reject); }
};
var __asyncGenerator = (this && this.__asyncGenerator) || function (thisArg, _arguments, generator) {
if (!Symbol.asyncIterator) throw new TypeError("Symbol.asyncIterator is not defined.");
var g = generator.apply(thisArg, _arguments || []), i, q = [];
return i = Object.create((typeof AsyncIterator === "function" ? AsyncIterator : Object).prototype), verb("next"), verb("throw"), verb("return", awaitReturn), i[Symbol.asyncIterator] = function () { return this; }, i;
function awaitReturn(f) { return function (v) { return Promise.resolve(v).then(f, reject); }; }
function verb(n, f) { if (g[n]) { i[n] = function (v) { return new Promise(function (a, b) { q.push([n, v, a, b]) > 1 || resume(n, v); }); }; if (f) i[n] = f(i[n]); } }
function resume(n, v) { try { step(g[n](v)); } catch (e) { settle(q[0][3], e); } }
function step(r) { r.value instanceof __await ? Promise.resolve(r.value.v).then(fulfill, reject) : settle(q[0][2], r); }
function fulfill(value) { resume("next", value); }
function reject(value) { resume("throw", value); }
function settle(f, v) { if (f(v), q.shift(), q.length) resume(q[0][0], q[0][1]); }
};
var CalendarService_1;
Object.defineProperty(exports, "__esModule", { value: true });
exports.CalendarService = void 0;
const common_1 = require("@nestjs/common");
const event_emitter_1 = require("@nestjs/event-emitter");
const microsoft_graph_client_1 = require("@microsoft/microsoft-graph-client");
const axios_1 = require("axios");
const microsoft_auth_service_1 = require("../auth/microsoft-auth.service");
const schedule_1 = require("@nestjs/schedule");
const outlook_webhook_subscription_repository_1 = require("../../repositories/outlook-webhook-subscription.repository");
const outlook_delta_link_repository_1 = require("../../repositories/outlook-delta-link.repository");
const constants_1 = require("../../constants");
const event_types_enum_1 = require("../../enums/event-types.enum");
const typeorm_1 = require("@nestjs/typeorm");
const microsoft_user_entity_1 = require("../../entities/microsoft-user.entity");
const typeorm_2 = require("typeorm");
const delta_sync_service_1 = require("../shared/delta-sync.service");
const resource_type_enum_1 = require("../../enums/resource-type.enum");
const retry_util_1 = require("../../utils/retry.util");
const OUTLOOK_EVENT_CREATED = event_types_enum_1.OutlookEventTypes.EVENT_CREATED;
const OUTLOOK_EVENT_UPDATED = event_types_enum_1.OutlookEventTypes.EVENT_UPDATED;
const OUTLOOK_EVENT_DELETED = event_types_enum_1.OutlookEventTypes.EVENT_DELETED;
const EVENT_TYPE_TO_CHANGE_TYPE = {
[OUTLOOK_EVENT_CREATED]: "created",
[OUTLOOK_EVENT_UPDATED]: "updated",
[OUTLOOK_EVENT_DELETED]: "deleted",
};
function isNewEvent(change) {
var _a;
if (!change.createdDateTime) {
return true;
}
const lastModified = new Date((_a = change.lastModifiedDateTime) !== null && _a !== void 0 ? _a : change.createdDateTime).getTime();
const created = new Date(change.createdDateTime).getTime();
return lastModified - created <= 1000;
}
function detectEventType(change) {
if (change["@removed"]) {
return OUTLOOK_EVENT_DELETED;
}
return isNewEvent(change) ? OUTLOOK_EVENT_CREATED : OUTLOOK_EVENT_UPDATED;
}
let CalendarService = CalendarService_1 = class CalendarService {
constructor(microsoftAuthService, webhookSubscriptionRepository, eventEmitter, microsoftConfig, deltaLinkRepository, microsoftUserRepository, deltaSyncService) {
this.microsoftAuthService = microsoftAuthService;
this.webhookSubscriptionRepository = webhookSubscriptionRepository;
this.eventEmitter = eventEmitter;
this.microsoftConfig = microsoftConfig;
this.deltaLinkRepository = deltaLinkRepository;
this.microsoftUserRepository = microsoftUserRepository;
this.deltaSyncService = deltaSyncService;
this.logger = new common_1.Logger(CalendarService_1.name);
this.syncLocks = new Map();
}
async getDefaultCalendarId(externalUserId) {
try {
const accessToken = await this.microsoftAuthService.getUserAccessTokenByExternalUserId(externalUserId);
const response = await axios_1.default.get("https://graph.microsoft.com/v1.0/me/calendar", {
headers: {
Authorization: `Bearer ${accessToken}`,
"Content-Type": "application/json",
},
});
if (!response.data.id) {
throw new Error("Failed to retrieve calendar ID");
}
return response.data.id;
}
catch (error) {
this.logger.error("Error getting default calendar ID:", error);
throw new Error("Failed to get calendar ID from Microsoft");
}
}
async createEvent(event, externalUserId, calendarId) {
try {
const accessToken = await this.microsoftAuthService.getUserAccessTokenByExternalUserId(externalUserId);
const client = microsoft_graph_client_1.Client.init({
authProvider: (done) => {
done(null, accessToken);
},
});
const createdEvent = (await client
.api(`/me/calendars/${calendarId}/events`)
.post(event));
return {
event: createdEvent,
};
}
catch (error) {
const errorMessage = error instanceof Error ? error.message : "Unknown error";
this.logger.error(`Failed to create Outlook calendar event: ${errorMessage}`);
throw new Error(`Failed to create Outlook calendar event: ${errorMessage}`);
}
}
async deleteEvent(event, externalUserId, calendarId) {
try {
const accessToken = await this.microsoftAuthService.getUserAccessTokenByExternalUserId(externalUserId);
const client = microsoft_graph_client_1.Client.init({
authProvider: (done) => {
done(null, accessToken);
},
});
this.logger.log(`Deleting event ${event.id} from calendar ${calendarId} for user ${externalUserId}`);
(await client
.api(`/me/calendars/${calendarId}/events/${event.id}`)
.delete());
}
catch (error) {
const errorMessage = error instanceof Error ? error.message : "Unknown error";
this.logger.error(`Failed to delete Outlook calendar event: ${errorMessage}`);
throw new Error(`Failed to delete Outlook calendar event: ${errorMessage}`);
}
}
async createWebhookSubscription(externalUserId) {
try {
const accessToken = await this.microsoftAuthService.getUserAccessTokenByExternalUserId(externalUserId);
const expirationDateTime = new Date();
expirationDateTime.setHours(expirationDateTime.getHours() + 72);
const appUrl = this.microsoftConfig.backendBaseUrl || "http://localhost:3000";
const basePath = this.microsoftConfig.basePath;
const basePathUrl = basePath ? `${appUrl}/${basePath}` : appUrl;
const notificationUrl = `${basePathUrl}/calendar/webhook`;
const subscriptionData = {
changeType: "created,updated,deleted",
notificationUrl,
lifecycleNotificationUrl: notificationUrl,
resource: "/me/events",
expirationDateTime: expirationDateTime.toISOString(),
clientState: `user_${externalUserId}_${Math.random().toString(36).substring(2, 15)}`,
};
this.logger.debug(`Creating webhook subscription with notificationUrl: ${notificationUrl}`);
this.logger.debug(`Subscription data: ${JSON.stringify(subscriptionData)}`);
const response = await axios_1.default.post("https://graph.microsoft.com/v1.0/subscriptions", subscriptionData, {
headers: {
Authorization: `Bearer ${accessToken}`,
"Content-Type": "application/json",
},
});
this.logger.log(`Created webhook subscription ${response.data.id || "unknown"} for user ${externalUserId}`);
const internalUserId = parseInt(externalUserId, 10);
await this.webhookSubscriptionRepository.saveSubscription({
subscriptionId: response.data.id,
userId: internalUserId,
resource: response.data.resource,
changeType: response.data.changeType,
clientState: response.data.clientState || "",
notificationUrl: response.data.notificationUrl,
expirationDateTime: response.data.expirationDateTime
? new Date(response.data.expirationDateTime)
: new Date(),
});
this.logger.debug(`Stored subscription`);
return response.data;
}
catch (error) {
this.logger.error("Failed to create webhook subscription:", error);
throw new Error("Failed to create webhook subscription");
}
}
async renewWebhookSubscription(subscriptionId, externalUserId) {
try {
const accessToken = await this.microsoftAuthService.getUserAccessTokenByExternalUserId(externalUserId);
const expirationDateTime = new Date();
expirationDateTime.setHours(expirationDateTime.getHours() + 72);
const renewalData = {
expirationDateTime: expirationDateTime.toISOString(),
};
const response = await axios_1.default.patch(`https://graph.microsoft.com/v1.0/subscriptions/${subscriptionId}`, renewalData, {
headers: {
Authorization: `Bearer ${accessToken}`,
"Content-Type": "application/json",
},
});
if (response.data.expirationDateTime) {
await this.webhookSubscriptionRepository.updateSubscriptionExpiration(subscriptionId, new Date(response.data.expirationDateTime));
}
this.logger.log(`Renewed webhook subscription: ${subscriptionId}`);
return response.data;
}
catch (error) {
const errorMessage = error instanceof Error ? error.message : "Unknown error";
this.logger.error(`Failed to renew webhook subscription: ${errorMessage}`);
throw new Error(`Failed to renew webhook subscription: ${errorMessage}`);
}
}
async renewWebhookSubscriptionByUserId(subscriptionId, internalUserId) {
try {
const accessToken = await this.microsoftAuthService.getUserAccessTokenByUserId(internalUserId);
const expirationDateTime = new Date();
expirationDateTime.setHours(expirationDateTime.getHours() + 72);
const renewalData = {
expirationDateTime: expirationDateTime.toISOString(),
};
const response = await axios_1.default.patch(`https://graph.microsoft.com/v1.0/subscriptions/${subscriptionId}`, renewalData, {
headers: {
Authorization: `Bearer ${accessToken}`,
"Content-Type": "application/json",
},
});
if (response.data.expirationDateTime) {
await this.webhookSubscriptionRepository.updateSubscriptionExpiration(subscriptionId, new Date(response.data.expirationDateTime));
}
this.logger.log(`Renewed webhook subscription: ${subscriptionId}`);
return response.data;
}
catch (error) {
const errorMessage = error instanceof Error ? error.message : "Unknown error";
this.logger.error(`Failed to renew webhook subscription: ${errorMessage}`);
throw new Error(`Failed to renew webhook subscription: ${errorMessage}`);
}
}
async deleteWebhookSubscription(subscriptionId, externalUserId) {
var _a;
try {
const accessToken = await this.microsoftAuthService.getUserAccessTokenByExternalUserId(externalUserId);
await axios_1.default.delete(`https://graph.microsoft.com/v1.0/subscriptions/${subscriptionId}`, {
headers: {
Authorization: `Bearer ${accessToken}`,
"Content-Type": "application/json",
},
});
await this.webhookSubscriptionRepository.deactivateSubscription(subscriptionId);
await this.microsoftUserRepository.update({ externalUserId }, {
isActive: false
});
this.logger.log(`Deleted webhook subscription: ${subscriptionId}`);
return true;
}
catch (error) {
const errorMessage = error instanceof Error ? error.message : "Unknown error";
this.logger.error(`Failed to delete webhook subscription: ${errorMessage}`);
if (axios_1.default.isAxiosError(error) && ((_a = error.response) === null || _a === void 0 ? void 0 : _a.status) === 404) {
await this.webhookSubscriptionRepository.deactivateSubscription(subscriptionId);
this.logger.log(`Subscription not found, removed from database: ${subscriptionId}`);
return true;
}
throw new Error(`Failed to delete webhook subscription: ${errorMessage}`);
}
}
async renewSubscriptions() {
try {
const expiringSubscriptions = await this.webhookSubscriptionRepository.findSubscriptionsNeedingRenewal(24);
if (expiringSubscriptions.length === 0) {
this.logger.debug("No subscriptions need renewal");
return;
}
this.logger.log(`Found ${String(expiringSubscriptions.length)} subscriptions that need renewal`);
for (const subscription of expiringSubscriptions) {
try {
await this.renewWebhookSubscriptionByUserId(subscription.subscriptionId, subscription.userId);
}
catch (error) {
this.logger.error(`Failed to renew subscription ${subscription.subscriptionId}:`, error);
}
}
}
catch (error) {
this.logger.error("Error in subscription renewal job:", error);
}
}
async handleOutlookWebhook(notificationItem, useStreaming = false) {
try {
const { subscriptionId, clientState, resource, changeType } = notificationItem;
this.logger.debug(`Received webhook notification for subscription: ${subscriptionId || "unknown"}`);
this.logger.debug(`Resource: ${resource || "unknown"}, ChangeType: ${String(changeType || "unknown")}`);
const { success, externalUserId, message } = await this.validateWebhookSubscription(subscriptionId, clientState);
if (!success || !externalUserId) {
this.logger.error('validateWebhookSubscription failed', message || 'Unknown error');
return { success: false, message: message || 'Unknown error' };
}
const totalProcessed = useStreaming
? await this.processChangesStreaming(String(externalUserId), String(subscriptionId || ''), resource || '')
: await this.processChangesBuffering(String(externalUserId), String(subscriptionId || ''), resource || '');
return { success: true, message: `Processed ${totalProcessed} events` };
}
catch (error) {
const errorMessage = error instanceof Error ? error.message : "Unknown error";
this.logger.error(`Error processing webhook notification: ${errorMessage}`);
return { success: false, message: errorMessage };
}
}
async fetchAndSortChanges(externalUserId, forceReset = false, dateRange) {
const client = await this.getAuthenticatedClient(externalUserId);
const requestUrl = "/me/events/delta";
try {
const items = await this.deltaSyncService.fetchAndSortChanges(client, requestUrl, externalUserId, forceReset, dateRange);
return items;
}
catch (error) {
this.logger.error("Error fetching delta changes:", error);
throw error;
}
}
streamCalendarChanges(externalUserId_1) {
return __asyncGenerator(this, arguments, function* streamCalendarChanges_1(externalUserId, forceReset = false, dateRange, saveDeltaLink = true) {
var _a, e_1, _b, _c;
const client = yield __await(this.getAuthenticatedClient(externalUserId));
const requestUrl = "/me/events/delta";
try {
this.logger.log(`[streamCalendarChanges] Starting stream for user ${externalUserId} (saveDeltaLink: ${saveDeltaLink})`);
try {
for (var _d = true, _e = __asyncValues(this.deltaSyncService.streamDeltaChanges(client, requestUrl, externalUserId, forceReset, dateRange, saveDeltaLink)), _f; _f = yield __await(_e.next()), _a = _f.done, !_a; _d = true) {
_c = _f.value;
_d = false;
const batch = _c;
this.logger.debug(`[streamCalendarChanges] Yielding batch of ${batch.length} events for user ${externalUserId}`);
yield yield __await(batch);
}
}
catch (e_1_1) { e_1 = { error: e_1_1 }; }
finally {
try {
if (!_d && !_a && (_b = _e.return)) yield __await(_b.call(_e));
}
finally { if (e_1) throw e_1.error; }
}
this.logger.log(`[streamCalendarChanges] Completed streaming for user ${externalUserId}`);
}
catch (error) {
this.logger.error(`[streamCalendarChanges] Error streaming delta changes:`, error);
throw error;
}
});
}
async getAuthenticatedClient(externalUserId) {
const accessToken = await this.microsoftAuthService.getUserAccessTokenByExternalUserId(externalUserId);
return microsoft_graph_client_1.Client.init({
authProvider: (done) => {
done(null, accessToken);
},
});
}
async getEventDetails(resource, externalUserId) {
try {
const accessToken = await this.microsoftAuthService.getUserAccessTokenByExternalUserId(externalUserId);
const response = await axios_1.default.get(`https://graph.microsoft.com/v1.0/${resource}`, {
headers: {
Authorization: `Bearer ${accessToken}`,
},
});
return response.data;
}
catch (error) {
this.logger.error("Error fetching event details:", error);
throw error;
}
}
importEventsStream(externalUserId, options) {
return __asyncGenerator(this, arguments, function* importEventsStream_1() {
var _a;
const batchSize = (_a = options === null || options === void 0 ? void 0 : options.batchSize) !== null && _a !== void 0 ? _a : 100;
try {
this.logger.log(`Starting event stream for user ${externalUserId} (batchSize: ${batchSize})`);
const client = yield __await(this.getAuthenticatedClient(externalUserId));
const requestUrl = this.buildRequestUrl(options, batchSize);
let nextLink = requestUrl;
const buffer = [];
let totalFetched = 0;
while (nextLink) {
this.logger.debug(`Fetching page: ${nextLink}`);
const response = (yield __await((0, retry_util_1.retryWithBackoff)(() => client.api(nextLink).get())));
const items = response.value;
buffer.push(...items);
totalFetched += items.length;
while (buffer.length >= batchSize) {
const chunk = buffer.splice(0, batchSize);
this.logger.debug(`Yielding chunk of ${chunk.length} items (total fetched: ${totalFetched})`);
yield yield __await(chunk);
}
nextLink = response["@odata.nextLink"];
if (nextLink) {
yield __await((0, retry_util_1.delay)(200));
}
}
if (buffer.length > 0) {
this.logger.debug(`Yielding final chunk of ${buffer.length} items`);
yield yield __await(buffer);
}
this.logger.log(`Completed streaming ${totalFetched} events for user ${externalUserId}`);
this.eventEmitter.emit(event_types_enum_1.OutlookEventTypes.IMPORT_COMPLETED, {
userId: externalUserId,
totalEvents: totalFetched,
});
}
catch (error) {
const errorMessage = error instanceof Error ? error.message : "Unknown error";
this.logger.error(`Error streaming events for user ${externalUserId}: ${errorMessage}`);
throw error;
}
});
}
async initializeDeltaSync(externalUserId) {
this.logger.log(`Initializing delta sync tracking for user ${externalUserId}`);
try {
const client = await this.getAuthenticatedClient(externalUserId);
await this.deltaSyncService.initializeDeltaLink(client, "/me/events/delta", Number(externalUserId), resource_type_enum_1.ResourceType.CALENDAR);
this.logger.log(`Delta tracking enabled for user ${externalUserId} (all events)`);
}
catch (error) {
this.logger.error(`Failed to initialize delta sync for user ${externalUserId}: ${error instanceof Error ? error.message : "Unknown error"}`);
throw error;
}
}
async processChangesStreaming(externalUserId, subscriptionId, resource) {
var _a, e_2, _b, _c;
let totalProcessed = 0;
let batchCount = 0;
this.logger.log(`[processChangesStreaming] Using STREAMING mode for user ${externalUserId}`);
try {
for (var _d = true, _e = __asyncValues(this.streamCalendarChanges(externalUserId)), _f; _f = await _e.next(), _a = _f.done, !_a; _d = true) {
_c = _f.value;
_d = false;
const changeBatch = _c;
batchCount++;
this.logger.log(`[processChangesStreaming] Processing batch ${batchCount} with ${changeBatch.length} changes`);
if (changeBatch.length === 0) {
this.logger.warn(`[processChangesStreaming] Received empty batch ${batchCount}`);
continue;
}
for (const change of changeBatch) {
this.processDeltaEventChange(change, externalUserId, subscriptionId, resource);
totalProcessed++;
}
this.logger.log(`[processChangesStreaming] Batch ${batchCount} processed: ${changeBatch.length} events (total: ${totalProcessed})`);
}
}
catch (e_2_1) { e_2 = { error: e_2_1 }; }
finally {
try {
if (!_d && !_a && (_b = _e.return)) await _b.call(_e);
}
finally { if (e_2) throw e_2.error; }
}
this.logger.log(`[processChangesStreaming] Completed: ${totalProcessed} events across ${batchCount} batches`);
return totalProcessed;
}
async processChangesBuffering(externalUserId, subscriptionId, resource) {
this.logger.log(`[processChangesBuffering] Using BUFFERING mode for user ${externalUserId}`);
const allChanges = await this.fetchAndSortChanges(externalUserId);
if (allChanges.length === 0) {
this.logger.warn(`[processChangesBuffering] No changes found`);
return 0;
}
this.logger.log(`[processChangesBuffering] Fetched ${allChanges.length} changes, processing batch`);
let totalProcessed = 0;
for (const change of allChanges) {
this.processDeltaEventChange(change, externalUserId, subscriptionId, resource);
totalProcessed++;
}
this.logger.log(`[processChangesBuffering] Completed: ${totalProcessed} events processed`);
return totalProcessed;
}
processDeltaEventChange(change, externalUserId, subscriptionId, resource) {
const eventType = detectEventType(change);
this.logger.debug(`[processDeltaEventChange] Event ${change.id || "unknown"}: created=${change.createdDateTime}, modified=${change.lastModifiedDateTime}, type=${eventType}`);
const resourceData = {
id: change.id || "",
userId: Number(externalUserId),
subscriptionId,
resource,
changeType: EVENT_TYPE_TO_CHANGE_TYPE[eventType],
data: change,
};
this.eventEmitter.emit(eventType, resourceData);
this.logger.log(`[processDeltaEventChange] Emitted ${eventType} for event ID: ${change.id || "unknown"}`);
}
async validateWebhookSubscription(subscriptionId, clientState) {
const subscription = await this.webhookSubscriptionRepository.findBySubscriptionId(subscriptionId || "");
if (!subscription) {
this.logger.warn(`Unknown subscription ID: ${subscriptionId || "unknown"}`);
return { success: false, message: "Unknown subscription" };
}
if (subscription.clientState &&
clientState !== subscription.clientState) {
this.logger.warn("Client state mismatch");
return { success: false, message: "Client state mismatch" };
}
const externalUserId = subscription.userId;
if (!externalUserId) {
this.logger.warn("Could not determine external user ID from client state");
return { success: false, message: "Invalid client state format" };
}
return { success: true, externalUserId };
}
buildRequestUrl(options, batchSize) {
var _a, _b;
const dateinterval = 5 * 365 * 24 * 60 * 60 * 1000;
const defaultStartDate = new Date();
const defaultEndDate = new Date(Date.now() + dateinterval);
const startDate = (_a = options === null || options === void 0 ? void 0 : options.startDate) !== null && _a !== void 0 ? _a : defaultStartDate;
const endDate = (_b = options === null || options === void 0 ? void 0 : options.endDate) !== null && _b !== void 0 ? _b : defaultEndDate;
const startDateStr = startDate.toISOString();
const endDateStr = endDate.toISOString();
let url = `/me/calendarView?startDateTime=${startDateStr}&endDateTime=${endDateStr}`;
url += `&$orderby=start/dateTime&$top=${batchSize !== null && batchSize !== void 0 ? batchSize : 100}`;
return url;
}
};
exports.CalendarService = CalendarService;
__decorate([
(0, schedule_1.Cron)(schedule_1.CronExpression.EVERY_HOUR),
__metadata("design:type", Function),
__metadata("design:paramtypes", []),
__metadata("design:returntype", Promise)
], CalendarService.prototype, "renewSubscriptions", null);
exports.CalendarService = CalendarService = CalendarService_1 = __decorate([
(0, common_1.Injectable)(),
__param(0, (0, common_1.Inject)((0, common_1.forwardRef)(() => microsoft_auth_service_1.MicrosoftAuthService))),
__param(3, (0, common_1.Inject)(constants_1.MICROSOFT_CONFIG)),
__param(5, (0, typeorm_1.InjectRepository)(microsoft_user_entity_1.MicrosoftUser)),
__metadata("design:paramtypes", [microsoft_auth_service_1.MicrosoftAuthService,
outlook_webhook_subscription_repository_1.OutlookWebhookSubscriptionRepository,
event_emitter_1.EventEmitter2, Object, outlook_delta_link_repository_1.OutlookDeltaLinkRepository,
typeorm_2.Repository,
delta_sync_service_1.DeltaSyncService])
], CalendarService);
//# sourceMappingURL=calendar.service.js.map