UNPKG

@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.

165 lines 10.1 kB
"use strict"; 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 __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 RecurrenceService_1; Object.defineProperty(exports, "__esModule", { value: true }); exports.RecurrenceService = void 0; const common_1 = require("@nestjs/common"); const calendar_service_1 = require("./calendar.service"); let RecurrenceService = RecurrenceService_1 = class RecurrenceService { constructor(calendarService) { this.calendarService = calendarService; this.logger = new common_1.Logger(RecurrenceService_1.name); } processEvent(event) { var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p, _q, _r, _s, _t, _u, _v, _w; const eventType = (_a = event.type) !== null && _a !== void 0 ? _a : 'singleInstance'; const processed = { externalId: (_b = event.id) !== null && _b !== void 0 ? _b : '', eventType, start: { dateTime: (_d = (_c = event.start) === null || _c === void 0 ? void 0 : _c.dateTime) !== null && _d !== void 0 ? _d : '', timeZone: (_f = (_e = event.start) === null || _e === void 0 ? void 0 : _e.timeZone) !== null && _f !== void 0 ? _f : '', }, end: { dateTime: (_h = (_g = event.end) === null || _g === void 0 ? void 0 : _g.dateTime) !== null && _h !== void 0 ? _h : '', timeZone: (_k = (_j = event.end) === null || _j === void 0 ? void 0 : _j.timeZone) !== null && _k !== void 0 ? _k : '', }, subject: (_l = event.subject) !== null && _l !== void 0 ? _l : '', bodyPreview: (_m = event.bodyPreview) !== null && _m !== void 0 ? _m : '', location: (_p = (_o = event.location) === null || _o === void 0 ? void 0 : _o.displayName) !== null && _p !== void 0 ? _p : undefined, showAs: (_q = event.showAs) !== null && _q !== void 0 ? _q : undefined, changeKey: (_r = event.changeKey) !== null && _r !== void 0 ? _r : undefined, seriesMasterId: (_s = event.seriesMasterId) !== null && _s !== void 0 ? _s : undefined, transactionId: (_t = event.transactionId) !== null && _t !== void 0 ? _t : undefined, }; if (eventType === 'seriesMaster' && event.recurrence) { processed.recurrenceRule = this.extractRecurrenceRule(event.recurrence); } if (eventType === 'exception' && event.originalStart) { processed.originalStart = { dateTime: event.originalStart, timeZone: (_w = (_u = event.originalStartTimeZone) !== null && _u !== void 0 ? _u : (_v = event.start) === null || _v === void 0 ? void 0 : _v.timeZone) !== null && _w !== void 0 ? _w : '', }; } return processed; } async expandRecurringSeries(seriesMasterId, externalUserId, options) { var _a, e_1, _b, _c; this.logger.log(`[expandRecurringSeries] Expanding series ${seriesMasterId} for user ${externalUserId}`); const masterEvents = await this.calendarService.getEventsBatch([seriesMasterId], externalUserId); if (masterEvents.length === 0) { throw new Error(`Series master ${seriesMasterId} not found in Outlook for user ${externalUserId}`); } const seriesMaster = this.processEvent(masterEvents[0]); const expansionWindow = this.calculateExpansionWindow(seriesMaster.recurrenceRule, options === null || options === void 0 ? void 0 : options.existingWindowEnd); this.logger.log(`[expandRecurringSeries] Window: ${expansionWindow.startDate.toISOString()}${expansionWindow.endDate.toISOString()}`); const instances = []; try { for (var _d = true, _e = __asyncValues(this.calendarService.getRecurringEventInstances(seriesMasterId, externalUserId, { startDate: expansionWindow.startDate, endDate: expansionWindow.endDate, batchSize: 100, })), _f; _f = await _e.next(), _a = _f.done, !_a; _d = true) { _c = _f.value; _d = false; const batch = _c; for (const event of batch) { instances.push(this.processEvent(event)); } } } catch (e_1_1) { e_1 = { error: e_1_1 }; } finally { try { if (!_d && !_a && (_b = _e.return)) await _b.call(_e); } finally { if (e_1) throw e_1.error; } } this.logger.log(`[expandRecurringSeries] Fetched ${instances.length} instances for series ${seriesMasterId}`); const staleExternalIds = (options === null || options === void 0 ? void 0 : options.existingExternalIds) ? this.detectStaleOccurrences(instances.map((i) => i.externalId), options.existingExternalIds) : []; if (staleExternalIds.length > 0) { this.logger.log(`[expandRecurringSeries] Detected ${staleExternalIds.length} stale occurrences`); } return { seriesMaster, instances, expansionWindow, staleExternalIds, }; } calculateExpansionWindow(recurrenceRule, existingWindowEnd) { const now = new Date(); const startDate = new Date(now); startDate.setMonth(startDate.getMonth() - 1); let endDate; if ((recurrenceRule === null || recurrenceRule === void 0 ? void 0 : recurrenceRule.range.type) === 'endDate' && recurrenceRule.range.endDate) { const seriesEnd = new Date(recurrenceRule.range.endDate); const maxEnd = new Date(now); maxEnd.setFullYear(maxEnd.getFullYear() + 5); endDate = seriesEnd < maxEnd ? seriesEnd : maxEnd; } else if (existingWindowEnd) { endDate = new Date(existingWindowEnd); endDate.setMonth(endDate.getMonth() + 6); } else { endDate = new Date(now); endDate.setMonth(endDate.getMonth() + 6); } return { startDate, endDate }; } detectStaleOccurrences(fetchedExternalIds, existingExternalIds) { const fetchedSet = new Set(fetchedExternalIds); return existingExternalIds.filter((id) => !fetchedSet.has(id)); } isSeriesMaster(event) { return event.type === 'seriesMaster' || event.recurrence != null; } extractRecurrenceRule(recurrence) { var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m; const pattern = recurrence.pattern; const range = recurrence.range; return { pattern: { type: (_a = pattern === null || pattern === void 0 ? void 0 : pattern.type) !== null && _a !== void 0 ? _a : 'daily', interval: (_b = pattern === null || pattern === void 0 ? void 0 : pattern.interval) !== null && _b !== void 0 ? _b : 1, daysOfWeek: (_c = pattern === null || pattern === void 0 ? void 0 : pattern.daysOfWeek) !== null && _c !== void 0 ? _c : undefined, dayOfMonth: (_d = pattern === null || pattern === void 0 ? void 0 : pattern.dayOfMonth) !== null && _d !== void 0 ? _d : undefined, month: (_e = pattern === null || pattern === void 0 ? void 0 : pattern.month) !== null && _e !== void 0 ? _e : undefined, firstDayOfWeek: (_f = pattern === null || pattern === void 0 ? void 0 : pattern.firstDayOfWeek) !== null && _f !== void 0 ? _f : undefined, index: (_g = pattern === null || pattern === void 0 ? void 0 : pattern.index) !== null && _g !== void 0 ? _g : undefined, }, range: { type: (_h = range === null || range === void 0 ? void 0 : range.type) !== null && _h !== void 0 ? _h : 'noEnd', startDate: (_j = range === null || range === void 0 ? void 0 : range.startDate) !== null && _j !== void 0 ? _j : '', endDate: (_k = range === null || range === void 0 ? void 0 : range.endDate) !== null && _k !== void 0 ? _k : undefined, numberOfOccurrences: (_l = range === null || range === void 0 ? void 0 : range.numberOfOccurrences) !== null && _l !== void 0 ? _l : undefined, recurrenceTimeZone: (_m = range === null || range === void 0 ? void 0 : range.recurrenceTimeZone) !== null && _m !== void 0 ? _m : undefined, }, }; } }; exports.RecurrenceService = RecurrenceService; exports.RecurrenceService = RecurrenceService = RecurrenceService_1 = __decorate([ (0, common_1.Injectable)(), __metadata("design:paramtypes", [calendar_service_1.CalendarService]) ], RecurrenceService); //# sourceMappingURL=recurrence.service.js.map