@mcp-monorepo/ics 1.2.0 → 1.3.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (71) hide show
  1. package/dist/ics-parser/errors.d.ts +16 -0
  2. package/dist/ics-parser/errors.d.ts.map +1 -0
  3. package/dist/ics-parser/errors.js +31 -0
  4. package/dist/ics-parser/errors.js.map +1 -0
  5. package/dist/ics-parser/event-expander.d.ts +71 -0
  6. package/dist/ics-parser/event-expander.d.ts.map +1 -0
  7. package/dist/ics-parser/event-expander.js +328 -0
  8. package/dist/ics-parser/event-expander.js.map +1 -0
  9. package/dist/ics-parser/index.d.ts +67 -0
  10. package/dist/ics-parser/index.d.ts.map +1 -0
  11. package/dist/ics-parser/index.js +91 -0
  12. package/dist/ics-parser/index.js.map +1 -0
  13. package/dist/ics-parser/parser.d.ts +26 -0
  14. package/dist/ics-parser/parser.d.ts.map +1 -0
  15. package/dist/ics-parser/parser.js +99 -0
  16. package/dist/ics-parser/parser.js.map +1 -0
  17. package/dist/ics-parser/property-parsers.d.ts +66 -0
  18. package/dist/ics-parser/property-parsers.d.ts.map +1 -0
  19. package/dist/ics-parser/property-parsers.js +226 -0
  20. package/dist/ics-parser/property-parsers.js.map +1 -0
  21. package/dist/ics-parser/rrule-expander.d.ts +10 -0
  22. package/dist/ics-parser/rrule-expander.d.ts.map +1 -0
  23. package/dist/ics-parser/rrule-expander.js +305 -0
  24. package/dist/ics-parser/rrule-expander.js.map +1 -0
  25. package/dist/ics-parser/timezone-processor.d.ts +40 -0
  26. package/dist/ics-parser/timezone-processor.d.ts.map +1 -0
  27. package/dist/ics-parser/timezone-processor.js +219 -0
  28. package/dist/ics-parser/timezone-processor.js.map +1 -0
  29. package/dist/ics-parser/types.d.ts +119 -0
  30. package/dist/ics-parser/types.d.ts.map +1 -0
  31. package/dist/ics-parser/types.js +2 -0
  32. package/dist/ics-parser/types.js.map +1 -0
  33. package/dist/ics-parser/utils.d.ts +16 -0
  34. package/dist/ics-parser/utils.d.ts.map +1 -0
  35. package/dist/ics-parser/utils.js +19 -0
  36. package/dist/ics-parser/utils.js.map +1 -0
  37. package/dist/index.js +5 -3
  38. package/dist/index.js.map +1 -1
  39. package/dist/lib/config.d.ts +10 -0
  40. package/dist/lib/config.d.ts.map +1 -0
  41. package/dist/lib/config.js +39 -0
  42. package/dist/lib/config.js.map +1 -0
  43. package/dist/lib/event-store-2.d.ts +11 -0
  44. package/dist/lib/event-store-2.d.ts.map +1 -0
  45. package/dist/lib/event-store-2.js +90 -0
  46. package/dist/lib/event-store-2.js.map +1 -0
  47. package/dist/lib/format-date.d.ts +7 -1
  48. package/dist/lib/format-date.d.ts.map +1 -1
  49. package/dist/lib/format-date.js +9 -4
  50. package/dist/lib/format-date.js.map +1 -1
  51. package/dist/lib/types.d.ts +0 -42
  52. package/dist/lib/types.d.ts.map +1 -1
  53. package/dist/tools/fetch-events.d.ts.map +1 -1
  54. package/dist/tools/fetch-events.js +31 -26
  55. package/dist/tools/fetch-events.js.map +1 -1
  56. package/dist/tools/search-events.d.ts.map +1 -1
  57. package/dist/tools/search-events.js +50 -17
  58. package/dist/tools/search-events.js.map +1 -1
  59. package/package.json +11 -9
  60. package/dist/lib/event-store.d.ts +0 -20
  61. package/dist/lib/event-store.d.ts.map +0 -1
  62. package/dist/lib/event-store.js +0 -107
  63. package/dist/lib/event-store.js.map +0 -1
  64. package/dist/lib/filter-events.d.ts +0 -3
  65. package/dist/lib/filter-events.d.ts.map +0 -1
  66. package/dist/lib/filter-events.js +0 -10
  67. package/dist/lib/filter-events.js.map +0 -1
  68. package/dist/lib/recurrrence.d.ts +0 -3
  69. package/dist/lib/recurrrence.d.ts.map +0 -1
  70. package/dist/lib/recurrrence.js +0 -70
  71. package/dist/lib/recurrrence.js.map +0 -1
@@ -1,12 +1,13 @@
1
1
  import { registerTool } from '@mcp-monorepo/shared';
2
2
  import { performKeywordSearch } from '@mcp-monorepo/shared';
3
3
  import { z } from 'zod';
4
- import { getRawEvents } from '../lib/event-store.js';
4
+ import { getUnexpandedEvents } from '../ics-parser/index.js';
5
+ import { getPreparedIcs } from '../lib/event-store-2.js';
5
6
  import { formatDate } from '../lib/format-date.js';
6
7
  export const registerSearchEventsTool = (server) => registerTool(server, {
7
8
  name: 'search-events',
8
9
  title: 'Search Calendar Events',
9
- description: 'Search through all calendar events using keywords. Searches in title and description, sorts by number of matching words.',
10
+ description: 'Search through all calendar events using keywords. Searches in title, description, location, attendees, and categories. Sorts by number of matching words.',
10
11
  inputSchema: {
11
12
  query: z
12
13
  .string()
@@ -24,6 +25,13 @@ export const registerSearchEventsTool = (server) => registerTool(server, {
24
25
  source: z.string(),
25
26
  matchCount: z.number(),
26
27
  matchedWords: z.array(z.string()),
28
+ organizer: z.any().optional(),
29
+ attendees: z.array(z.any()).optional(),
30
+ categories: z.array(z.string()).optional(),
31
+ url: z.string().optional(),
32
+ rrule: z.any().optional(),
33
+ rdates: z.array(z.string()).optional(),
34
+ exdates: z.array(z.string()).optional(),
27
35
  })),
28
36
  errors: z.array(z.string()),
29
37
  total: z.number(),
@@ -34,34 +42,59 @@ export const registerSearchEventsTool = (server) => registerTool(server, {
34
42
  if (!query.trim()) {
35
43
  throw new Error('Search query cannot be empty');
36
44
  }
37
- const events = await getRawEvents();
38
- const results = performKeywordSearch(query, events.events, (event) => [event.summary, event.description, event.location, event.source], (a, b) => new Date(a.dtstart).getTime() - new Date(b.dtstart).getTime());
39
- // Limit results based on the specified `limit`
45
+ const { prepared, errors } = await getPreparedIcs();
46
+ const unexpandedEvents = getUnexpandedEvents(prepared);
47
+ const results = performKeywordSearch(query, unexpandedEvents, (event) => {
48
+ const source = event.customProperties?.['X-MCP-SOURCE']?.value ?? 'Unknown';
49
+ const customPropValues = event.customProperties
50
+ ? Object.values(event.customProperties).map((p) => p.value)
51
+ : [];
52
+ const attendeeNames = event.attendees
53
+ ? event.attendees.flatMap((a) => [a.email, a.commonName]).filter((x) => x !== undefined)
54
+ : [];
55
+ return [
56
+ event.summary,
57
+ event.description,
58
+ event.location,
59
+ source,
60
+ ...(event.categories || []),
61
+ event.organizer?.commonName,
62
+ ...attendeeNames,
63
+ event.url,
64
+ ...customPropValues,
65
+ ].filter((v) => !!v);
66
+ }, (a, b) => new Date(a.start).getTime() - new Date(b.start).getTime());
40
67
  const limitedResults = results.slice(0, limit);
41
68
  return {
42
69
  results: limitedResults,
43
70
  total: results.length,
44
71
  searchQuery: query,
45
- errors: events.errors,
72
+ errors: errors,
46
73
  };
47
74
  },
48
75
  formatter({ results, total, searchQuery, errors }) {
49
76
  const formattedEvents = results.map((result) => {
50
- const { description, dtend, dtstart, location, source, summary, uid } = result.match;
77
+ const event = result.match;
78
+ const source = event.customProperties?.['X-MCP-SOURCE']?.value ?? 'Unknown';
51
79
  return {
52
- summary: summary,
53
- start: formatDate(dtstart, true),
54
- ...(dtend ? { end: formatDate(dtend, true) } : {}),
55
- description: description
56
- ? description.length > 400
57
- ? description.substring(0, 400) + '...'
58
- : description
59
- : undefined,
60
- location: location,
61
- uid: uid,
80
+ summary: event.summary,
81
+ start: formatDate(new Date(event.start), event.allDay),
82
+ ...(event.end ? { end: formatDate(new Date(event.end), event.allDay) } : {}),
83
+ description: event.description && event.description.length > 400
84
+ ? event.description.substring(0, 400) + '...'
85
+ : event.description,
86
+ location: event.location,
87
+ uid: event.uid,
62
88
  source: source,
63
89
  matchCount: result.matchCount,
64
90
  matchedWords: result.matchedWords,
91
+ organizer: event.organizer,
92
+ attendees: event.attendees,
93
+ categories: event.categories,
94
+ url: event.url,
95
+ rrule: event.rrule,
96
+ rdates: event.rdates,
97
+ exdates: event.exdates,
65
98
  };
66
99
  });
67
100
  return {
@@ -1 +1 @@
1
- {"version":3,"file":"search-events.js","sourceRoot":"","sources":["../../src/tools/search-events.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"search-events.js","sourceRoot":"","sources":["../../src/tools/search-events.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,13 +1,11 @@
1
1
  {
2
2
  "name": "@mcp-monorepo/ics",
3
- "version": "1.2.0",
3
+ "version": "1.3.1",
4
4
  "type": "module",
5
5
  "description": "MCP server for calendar tools using ICS/ical feeds",
6
6
  "main": "dist/index.js",
7
7
  "types": "dist/index.d.ts",
8
- "bin": {
9
- "@mcp-monorepo/ics": "./dist/index.js"
10
- },
8
+ "bin": "./dist/index.js",
11
9
  "files": [
12
10
  "dist"
13
11
  ],
@@ -18,6 +16,7 @@
18
16
  "build": "tsc -b",
19
17
  "dev": "tsc --watch",
20
18
  "start": "node dist/index.js",
19
+ "demo": "node --inspect dist/demo.js",
21
20
  "test": "vitest run --passWithNoTests",
22
21
  "test:watch": "vitest",
23
22
  "test:coverage": "vitest run --coverage",
@@ -25,16 +24,19 @@
25
24
  "clean": "rimraf dist tsconfig.tsbuildinfo"
26
25
  },
27
26
  "dependencies": {
27
+ "@mcp-monorepo/shared": "workspace:*",
28
28
  "@modelcontextprotocol/sdk": "^1.23.1",
29
- "zod": "^3.25.76",
30
29
  "date-fns-tz": "^3.2.0",
31
- "node-ical": "^0.20.1",
32
- "@mcp-monorepo/shared": "*"
30
+ "luxon": "^3.7.2",
31
+ "node-ical": "^0.22.1",
32
+ "rrule": "^2.8.1",
33
+ "zod": "^3.25.76"
33
34
  },
34
35
  "devDependencies": {
36
+ "@types/luxon": "^3.7.1",
35
37
  "@types/node": "^22.14.1",
38
+ "rimraf": "^6.0.1",
36
39
  "typescript": "^5.8.3",
37
- "vitest": "^3.2.4",
38
- "rimraf": "^6.0.1"
40
+ "vitest": "^3.2.4"
39
41
  }
40
42
  }
@@ -1,20 +0,0 @@
1
- import { RefreshablePromise } from '@mcp-monorepo/shared';
2
- import { type VEvent } from 'node-ical';
3
- import { type CalendarSource, type RawIcalEvent } from './types.js';
4
- export declare const throwForNoIcsUrls: () => never;
5
- export declare const getIcsUrls: () => CalendarSource[];
6
- export declare const parseIcsContent: (icsContent: string, source: string) => Promise<RawIcalEvent[]>;
7
- export declare const convertEvent: (event: VEvent, source: string) => RawIcalEvent;
8
- export declare function refreshEvents(): Promise<{
9
- events: RawIcalEvent[];
10
- errors: string[];
11
- }>;
12
- /**
13
- * Gets the singleton instance of the RefreshablePromise for raw ICAL events.
14
- * The instance is created on the first call.
15
- */
16
- export declare function getRawEvents(): RefreshablePromise<{
17
- events: RawIcalEvent[];
18
- errors: string[];
19
- }>;
20
- //# sourceMappingURL=event-store.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"event-store.d.ts","sourceRoot":"","sources":["../../src/lib/event-store.ts"],"names":[],"mappings":"AAGA,OAAO,EAAmB,kBAAkB,EAAE,MAAM,sBAAsB,CAAA;AAE1E,OAAa,EAAE,KAAK,MAAM,EAAE,MAAM,WAAW,CAAA;AAE7C,OAAO,EAAE,KAAK,cAAc,EAAE,KAAK,YAAY,EAAkB,MAAM,YAAY,CAAA;AAEnF,eAAO,MAAM,iBAAiB,QAAO,KAEpC,CAAA;AAED,eAAO,MAAM,UAAU,QAAO,cAAc,EAsB3C,CAAA;AAED,eAAO,MAAM,eAAe,GAAU,YAAY,MAAM,EAAE,QAAQ,MAAM,KAAG,OAAO,CAAC,YAAY,EAAE,CAGhG,CAAA;AAED,eAAO,MAAM,YAAY,GAAI,OAAO,MAAM,EAAE,QAAQ,MAAM,KAAG,YAsB5D,CAAA;AAED,wBAAsB,aAAa,IAAI,OAAO,CAAC;IAC7C,MAAM,EAAE,YAAY,EAAE,CAAA;IACtB,MAAM,EAAE,MAAM,EAAE,CAAA;CACjB,CAAC,CAgDD;AAID;;;GAGG;AACH,wBAAgB,YAAY;YANwB,YAAY,EAAE;YAAU,MAAM,EAAE;GAWnF"}
@@ -1,107 +0,0 @@
1
- import { mkdir, readFile, writeFile } from 'fs/promises';
2
- import { dirname, join } from 'path';
3
- import { findProjectRoot, RefreshablePromise } from '@mcp-monorepo/shared';
4
- import { logger } from '@mcp-monorepo/shared';
5
- import ical from 'node-ical';
6
- export const throwForNoIcsUrls = () => {
7
- throw new Error('No valid ICS URLs provided in environment variables.');
8
- };
9
- export const getIcsUrls = () => {
10
- const envVars = process.env;
11
- const calendarSources = [];
12
- Object.keys(envVars).forEach((key) => {
13
- const ENV_PREFIX = 'CALENDAR_';
14
- if (key.startsWith(ENV_PREFIX)) {
15
- const url = envVars[key];
16
- if (url && (url.startsWith('http://') || url.startsWith('https://'))) {
17
- const name = key.substring(ENV_PREFIX.length);
18
- calendarSources.push({ name, url });
19
- }
20
- else {
21
- throw new Error(`Invalid URL for environment variable ${key}: ${url}`);
22
- }
23
- }
24
- });
25
- if (calendarSources.length === 0) {
26
- throwForNoIcsUrls();
27
- }
28
- return calendarSources;
29
- };
30
- export const parseIcsContent = async (icsContent, source) => {
31
- const entries = Object.values(await ical.async.parseICS(icsContent));
32
- return entries.filter((e) => e.type === 'VEVENT').map((event) => convertEvent(event, source));
33
- };
34
- export const convertEvent = (event, source) => {
35
- let recurrences = undefined;
36
- if (event.recurrences) {
37
- recurrences = Object.fromEntries(Object.entries(event.recurrences).map(([key, rec]) => [key, convertEvent(rec, source)]));
38
- }
39
- return {
40
- uid: event.uid,
41
- summary: event.summary,
42
- description: event.description,
43
- location: event.location,
44
- dtstart: event.start,
45
- dtend: event.end,
46
- allDay: event.datetype === 'date',
47
- source,
48
- rrule: event.rrule,
49
- rruleOptions: event.rrule ? event.rrule.origOptions : undefined,
50
- exdate: event.exdate,
51
- recurrences,
52
- status: event.status,
53
- };
54
- };
55
- export async function refreshEvents() {
56
- const sources = getIcsUrls();
57
- logger.info('Refreshing events from: ', sources);
58
- const events = [];
59
- const errors = [];
60
- for (const source of sources) {
61
- const dataFile = join(await findProjectRoot(import.meta.dirname), 'data', 'ics', source.url.replace(/[^a-zA-Z0-9]/g, '_') + '.json');
62
- try {
63
- logger.info(`[${source.name}] Attempting to fetch fresh data...`);
64
- const icsContent = await fetch(source.url);
65
- if (!icsContent.ok) {
66
- throw new Error(`Fetch failed with status ${icsContent.status}`);
67
- }
68
- const text = await icsContent.text();
69
- const parsed = await parseIcsContent(text, source.name);
70
- events.push(...parsed);
71
- await mkdir(dirname(dataFile), { recursive: true });
72
- await writeFile(dataFile, JSON.stringify(parsed));
73
- logger.info(`[${source.name}] Successfully fetched and cached new data.`);
74
- }
75
- catch (e) {
76
- logger.warn(`[${source.name}] Fetch failed: ${e.message}. Attempting to use cache.`);
77
- try {
78
- const data = await readFile(dataFile, 'utf-8');
79
- const parsed = JSON.parse(data);
80
- events.push(...parsed);
81
- logger.info(`[${source.name}] Successfully loaded data from cache.`);
82
- }
83
- catch {
84
- const finalErrorMsg = `[${source.name}] Fetch failed and cache is unavailable or corrupt.`;
85
- logger.error(finalErrorMsg);
86
- errors.push(finalErrorMsg);
87
- }
88
- }
89
- }
90
- errors.forEach((e) => logger.error(e));
91
- return {
92
- events,
93
- errors,
94
- };
95
- }
96
- let rawEventsInstance;
97
- /**
98
- * Gets the singleton instance of the RefreshablePromise for raw ICAL events.
99
- * The instance is created on the first call.
100
- */
101
- export function getRawEvents() {
102
- if (!rawEventsInstance) {
103
- rawEventsInstance = new RefreshablePromise(refreshEvents);
104
- }
105
- return rawEventsInstance;
106
- }
107
- //# sourceMappingURL=event-store.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"event-store.js","sourceRoot":"","sources":["../../src/lib/event-store.ts"],"names":[],"mappings":"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"}
@@ -1,3 +0,0 @@
1
- import { type CalendarEvent } from './types.js';
2
- export declare function filterEvents(events: CalendarEvent[], start: Date, end: Date): CalendarEvent[];
3
- //# sourceMappingURL=filter-events.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"filter-events.d.ts","sourceRoot":"","sources":["../../src/lib/filter-events.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,aAAa,EAAE,MAAM,YAAY,CAAA;AAE/C,wBAAgB,YAAY,CAAC,MAAM,EAAE,aAAa,EAAE,EAAE,KAAK,EAAE,IAAI,EAAE,GAAG,EAAE,IAAI,mBAQ3E"}
@@ -1,10 +0,0 @@
1
- export function filterEvents(events, start, end) {
2
- return events
3
- .filter((evt) => {
4
- const st = evt.dtstart;
5
- const en = evt.dtend || evt.dtstart;
6
- return st <= end && en >= start;
7
- })
8
- .sort((a, b) => a.dtstart.getTime() - b.dtstart.getTime());
9
- }
10
- //# sourceMappingURL=filter-events.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"filter-events.js","sourceRoot":"","sources":["../../src/lib/filter-events.ts"],"names":[],"mappings":"AAEA,MAAM,UAAU,YAAY,CAAC,MAAuB,EAAE,KAAW,EAAE,GAAS;IAC1E,OAAO,MAAM;SACV,MAAM,CAAC,CAAC,GAAG,EAAE,EAAE;QACd,MAAM,EAAE,GAAG,GAAG,CAAC,OAAO,CAAA;QACtB,MAAM,EAAE,GAAG,GAAG,CAAC,KAAK,IAAI,GAAG,CAAC,OAAO,CAAA;QACnC,OAAO,EAAE,IAAI,GAAG,IAAI,EAAE,IAAI,KAAK,CAAA;IACjC,CAAC,CAAC;SACD,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,OAAO,CAAC,OAAO,EAAE,GAAG,CAAC,CAAC,OAAO,CAAC,OAAO,EAAE,CAAC,CAAA;AAC9D,CAAC"}
@@ -1,3 +0,0 @@
1
- import type { CalendarEvent, RawIcalEvent } from './types.js';
2
- export declare function resolveRecurrence(events: RawIcalEvent[], startDate: Date, endDate: Date): CalendarEvent[];
3
- //# sourceMappingURL=recurrrence.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"recurrrence.d.ts","sourceRoot":"","sources":["../../src/lib/recurrrence.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,YAAY,EAAE,MAAM,YAAY,CAAA;AAqB7D,wBAAgB,iBAAiB,CAAC,MAAM,EAAE,YAAY,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,OAAO,EAAE,IAAI,GAAG,aAAa,EAAE,CAkEzG"}
@@ -1,70 +0,0 @@
1
- function getAdjustedRecurrenceDate(rruleOrigOptions, eventStart, recurrence) {
2
- if (rruleOrigOptions && rruleOrigOptions.tzid) {
3
- try {
4
- const utc = recurrence.getTime() + eventStart.getTimezoneOffset() * 60000;
5
- return new Date(utc);
6
- }
7
- catch {
8
- return recurrence;
9
- }
10
- }
11
- const origOffset = eventStart.getTimezoneOffset();
12
- const recOffset = recurrence.getTimezoneOffset();
13
- const offsetDiff = origOffset - recOffset;
14
- return new Date(recurrence.getTime() + offsetDiff * 60000);
15
- }
16
- export function resolveRecurrence(events, startDate, endDate) {
17
- const createCalendarEvent = (event, dtstart, dtend, uidSuffix) => ({
18
- uid: uidSuffix ? `${event.uid}_${uidSuffix}` : event.uid,
19
- summary: event.summary,
20
- description: event.description,
21
- location: event.location,
22
- dtstart: dtstart ?? event.dtstart,
23
- dtend: dtend ?? event.dtend,
24
- allDay: event.allDay,
25
- source: event.source,
26
- });
27
- const getExceptionTimestamps = (event) => {
28
- const exdateTimes = event.exdate ? Object.values(event.exdate).map((d) => d.getTime()) : [];
29
- const cancelledRecurrenceTimes = event.recurrences
30
- ? Object.values(event.recurrences)
31
- .filter((r) => r.status === 'CANCELLED')
32
- .map((r) => r.dtstart.getTime())
33
- : [];
34
- return [...exdateTimes, ...cancelledRecurrenceTimes];
35
- };
36
- const expandSingleEvent = (event) => {
37
- if (!event.rrule) {
38
- if (event.dtstart >= startDate && event.dtstart <= endDate) {
39
- return [createCalendarEvent(event)];
40
- }
41
- return [];
42
- }
43
- try {
44
- const recurrences = event.rrule.between(startDate, endDate);
45
- if (recurrences.length === 0) {
46
- return event.dtstart >= startDate && event.dtstart <= endDate ? [createCalendarEvent(event)] : [];
47
- }
48
- const exceptionTimes = getExceptionTimestamps(event);
49
- const duration = event.dtend && event.dtstart ? event.dtend.getTime() - event.dtstart.getTime() : 0;
50
- return recurrences
51
- .map((recurrenceDate) => {
52
- const adjustedStart = getAdjustedRecurrenceDate(event.rruleOptions, event.dtstart, recurrenceDate);
53
- if (exceptionTimes.includes(adjustedStart.getTime())) {
54
- return undefined;
55
- }
56
- const adjustedEnd = duration ? new Date(adjustedStart.getTime() + duration) : undefined;
57
- return createCalendarEvent(event, adjustedStart, adjustedEnd, adjustedStart.getTime().toString());
58
- })
59
- .filter((e) => e !== undefined);
60
- }
61
- catch {
62
- if (event.dtstart >= startDate && event.dtstart <= endDate) {
63
- return [createCalendarEvent(event)];
64
- }
65
- return [];
66
- }
67
- };
68
- return events.flatMap(expandSingleEvent);
69
- }
70
- //# sourceMappingURL=recurrrence.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"recurrrence.js","sourceRoot":"","sources":["../../src/lib/recurrrence.ts"],"names":[],"mappings":"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"}