@miguelarios/pim-core 0.5.0 → 0.6.0

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 (45) hide show
  1. package/dist/ics/_shared.d.ts +11 -0
  2. package/dist/ics/_shared.d.ts.map +1 -0
  3. package/dist/ics/_shared.js +150 -0
  4. package/dist/ics/_shared.js.map +1 -0
  5. package/dist/ics/_tz-init.d.ts +2 -0
  6. package/dist/ics/_tz-init.d.ts.map +1 -0
  7. package/dist/ics/_tz-init.js +29 -0
  8. package/dist/ics/_tz-init.js.map +1 -0
  9. package/dist/ics/components.d.ts +26 -0
  10. package/dist/ics/components.d.ts.map +1 -0
  11. package/dist/ics/components.js +178 -0
  12. package/dist/ics/components.js.map +1 -0
  13. package/dist/ics/errors.d.ts +7 -0
  14. package/dist/ics/errors.d.ts.map +1 -0
  15. package/dist/ics/errors.js +13 -0
  16. package/dist/ics/errors.js.map +1 -0
  17. package/dist/ics/generate.d.ts +4 -0
  18. package/dist/ics/generate.d.ts.map +1 -0
  19. package/dist/ics/generate.js +101 -0
  20. package/dist/ics/generate.js.map +1 -0
  21. package/dist/ics/index.d.ts +11 -0
  22. package/dist/ics/index.d.ts.map +1 -0
  23. package/dist/ics/index.js +12 -0
  24. package/dist/ics/index.js.map +1 -0
  25. package/dist/ics/parse-events.d.ts +4 -0
  26. package/dist/ics/parse-events.d.ts.map +1 -0
  27. package/dist/ics/parse-events.js +223 -0
  28. package/dist/ics/parse-events.js.map +1 -0
  29. package/dist/ics/parse-journals.d.ts +4 -0
  30. package/dist/ics/parse-journals.d.ts.map +1 -0
  31. package/dist/ics/parse-journals.js +54 -0
  32. package/dist/ics/parse-journals.js.map +1 -0
  33. package/dist/ics/parse-todos.d.ts +4 -0
  34. package/dist/ics/parse-todos.d.ts.map +1 -0
  35. package/dist/ics/parse-todos.js +55 -0
  36. package/dist/ics/parse-todos.js.map +1 -0
  37. package/dist/ics/rrule.d.ts +2 -0
  38. package/dist/ics/rrule.d.ts.map +1 -0
  39. package/dist/ics/rrule.js +23 -0
  40. package/dist/ics/rrule.js.map +1 -0
  41. package/dist/ics/types.d.ts +100 -0
  42. package/dist/ics/types.d.ts.map +1 -0
  43. package/dist/ics/types.js +3 -0
  44. package/dist/ics/types.js.map +1 -0
  45. package/package.json +7 -1
@@ -0,0 +1,11 @@
1
+ import ICAL from "ical.js";
2
+ import type { ParsedAlarm, ParsedAttendee, ParsedGeo, ParsedOrganizer } from "./types.js";
3
+ export declare function parseAttendees(component: ICAL.Component): ParsedAttendee[];
4
+ export declare function parseOrganizer(component: ICAL.Component): ParsedOrganizer | null;
5
+ export declare function parseCategories(component: ICAL.Component): string[];
6
+ export declare function parseGeo(component: ICAL.Component): ParsedGeo | null;
7
+ export declare function parseDurationToSeconds(duration: string): number;
8
+ export declare function formatTriggerHuman(seconds: number): string;
9
+ export declare function parseAlarms(component: ICAL.Component): ParsedAlarm[];
10
+ export declare function timeToIso(time: ICAL.Time): string;
11
+ //# sourceMappingURL=_shared.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"_shared.d.ts","sourceRoot":"","sources":["../../src/ics/_shared.ts"],"names":[],"mappings":"AAAA,OAAO,IAAI,MAAM,SAAS,CAAC;AAC3B,OAAO,KAAK,EAAE,WAAW,EAAE,cAAc,EAAE,SAAS,EAAE,eAAe,EAAE,MAAM,YAAY,CAAC;AAa1F,wBAAgB,cAAc,CAAC,SAAS,EAAE,IAAI,CAAC,SAAS,GAAG,cAAc,EAAE,CAsB1E;AAED,wBAAgB,cAAc,CAAC,SAAS,EAAE,IAAI,CAAC,SAAS,GAAG,eAAe,GAAG,IAAI,CAShF;AAED,wBAAgB,eAAe,CAAC,SAAS,EAAE,IAAI,CAAC,SAAS,GAAG,MAAM,EAAE,CAUnE;AAED,wBAAgB,QAAQ,CAAC,SAAS,EAAE,IAAI,CAAC,SAAS,GAAG,SAAS,GAAG,IAAI,CAepE;AAED,wBAAgB,sBAAsB,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,CAgB/D;AAED,wBAAgB,kBAAkB,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAe1D;AAED,wBAAgB,WAAW,CAAC,SAAS,EAAE,IAAI,CAAC,SAAS,GAAG,WAAW,EAAE,CAwBpE;AAED,wBAAgB,SAAS,CAAC,IAAI,EAAE,IAAI,CAAC,IAAI,GAAG,MAAM,CAKjD"}
@@ -0,0 +1,150 @@
1
+ import ICAL from "ical.js";
2
+ const CUTYPE_MAP = {
3
+ INDIVIDUAL: "person",
4
+ ROOM: "room",
5
+ RESOURCE: "resource",
6
+ GROUP: "group",
7
+ };
8
+ function stripMailto(value) {
9
+ return value.replace(/^mailto:/i, "");
10
+ }
11
+ export function parseAttendees(component) {
12
+ const properties = component.getAllProperties("attendee");
13
+ return properties.map((prop) => {
14
+ const value = prop.getFirstValue();
15
+ const email = typeof value === "string" ? stripMailto(value) : "";
16
+ const cnRaw = prop.getParameter("cn");
17
+ const cn = typeof cnRaw === "string" ? cnRaw : null;
18
+ const partstatRaw = prop.getParameter("partstat");
19
+ const partstat = typeof partstatRaw === "string" ? partstatRaw : undefined;
20
+ const roleRaw = prop.getParameter("role");
21
+ const role = typeof roleRaw === "string" ? roleRaw : undefined;
22
+ const cutypeRaw = prop.getParameter("cutype");
23
+ // RFC 5545 §3.2.3: CUTYPE defaults to INDIVIDUAL when absent.
24
+ const cutype = typeof cutypeRaw === "string" && cutypeRaw.length > 0 ? cutypeRaw : "INDIVIDUAL";
25
+ return {
26
+ email,
27
+ name: cn,
28
+ status: partstat ? partstat.toLowerCase() : null,
29
+ role: role ? role.toLowerCase() : null,
30
+ type: CUTYPE_MAP[cutype] ?? "unknown",
31
+ };
32
+ });
33
+ }
34
+ export function parseOrganizer(component) {
35
+ const prop = component.getFirstProperty("organizer");
36
+ if (!prop)
37
+ return null;
38
+ const value = prop.getFirstValue();
39
+ const email = typeof value === "string" ? stripMailto(value) : "";
40
+ if (!email)
41
+ return null;
42
+ const cnRaw = prop.getParameter("cn");
43
+ const name = typeof cnRaw === "string" ? cnRaw : null;
44
+ return { email, name };
45
+ }
46
+ export function parseCategories(component) {
47
+ const properties = component.getAllProperties("categories");
48
+ const out = [];
49
+ for (const prop of properties) {
50
+ const values = prop.getValues();
51
+ for (const v of values) {
52
+ if (typeof v === "string" && v.length > 0)
53
+ out.push(v);
54
+ }
55
+ }
56
+ return out;
57
+ }
58
+ export function parseGeo(component) {
59
+ const prop = component.getFirstProperty("geo");
60
+ if (!prop)
61
+ return null;
62
+ const value = prop.getFirstValue();
63
+ if (!Array.isArray(value) || value.length !== 2)
64
+ return null;
65
+ const [lat, lon] = value;
66
+ if (typeof lat !== "number" || typeof lon !== "number")
67
+ return null;
68
+ if (Number.isNaN(lat) || Number.isNaN(lon))
69
+ return null;
70
+ // Reject GEO:; sentinel: ical.js parses `GEO:;` (empty value) as [0, 0]
71
+ // (verified). The 0,0 false-rejection at Gulf-of-Guinea (0°N 0°E) is a known
72
+ // edge case — preferred over surfacing corrupted-GEO data as a real location.
73
+ // If you genuinely need 0,0, a future change can disambiguate by inspecting
74
+ // the raw property string for "GEO:;" vs "GEO:0;0".
75
+ if (lat === 0 && lon === 0)
76
+ return null;
77
+ return { latitude: lat, longitude: lon };
78
+ }
79
+ export function parseDurationToSeconds(duration) {
80
+ const negative = duration.startsWith("-");
81
+ // RFC 5545 §3.3.6: PnW (weeks-only) is mutually exclusive with the date/time form.
82
+ const weekMatch = duration.match(/P(\d+)W$/);
83
+ if (weekMatch) {
84
+ const weeks = Number.parseInt(weekMatch[1], 10);
85
+ return (negative ? -1 : 1) * weeks * 604800;
86
+ }
87
+ const match = duration.match(/P(?:(\d+)D)?(?:T(?:(\d+)H)?(?:(\d+)M)?(?:(\d+)S)?)?/);
88
+ if (!match)
89
+ return 0;
90
+ const days = Number.parseInt(match[1] || "0", 10);
91
+ const hours = Number.parseInt(match[2] || "0", 10);
92
+ const minutes = Number.parseInt(match[3] || "0", 10);
93
+ const seconds = Number.parseInt(match[4] || "0", 10);
94
+ const total = days * 86400 + hours * 3600 + minutes * 60 + seconds;
95
+ return negative ? -total : total;
96
+ }
97
+ export function formatTriggerHuman(seconds) {
98
+ if (seconds === 0)
99
+ return "At time of event";
100
+ const abs = Math.abs(seconds);
101
+ const suffix = seconds < 0 ? "before" : "after";
102
+ const parts = [];
103
+ const days = Math.floor(abs / 86400);
104
+ const hours = Math.floor((abs % 86400) / 3600);
105
+ const minutes = Math.floor((abs % 3600) / 60);
106
+ if (days > 0)
107
+ parts.push(`${days} ${days === 1 ? "day" : "days"}`);
108
+ if (hours > 0)
109
+ parts.push(`${hours} ${hours === 1 ? "hour" : "hours"}`);
110
+ if (minutes > 0)
111
+ parts.push(`${minutes} ${minutes === 1 ? "minute" : "minutes"}`);
112
+ if (parts.length === 0) {
113
+ parts.push(`${abs} ${abs === 1 ? "second" : "seconds"}`);
114
+ }
115
+ return `${parts.join(", ")} ${suffix}`;
116
+ }
117
+ export function parseAlarms(component) {
118
+ const valarms = component.getAllSubcomponents("valarm");
119
+ const out = [];
120
+ for (const valarm of valarms) {
121
+ const triggerProp = valarm.getFirstProperty("trigger");
122
+ if (!triggerProp)
123
+ continue;
124
+ const value = triggerProp.getFirstValue();
125
+ if (value instanceof ICAL.Time) {
126
+ const date = value.toJSDate();
127
+ out.push({
128
+ type: "absolute",
129
+ trigger: date.toISOString(),
130
+ trigger_human: date.toISOString(),
131
+ });
132
+ }
133
+ else if (value instanceof ICAL.Duration) {
134
+ const seconds = value.toSeconds();
135
+ out.push({
136
+ type: "relative",
137
+ trigger: seconds,
138
+ trigger_human: formatTriggerHuman(seconds),
139
+ });
140
+ }
141
+ }
142
+ return out;
143
+ }
144
+ export function timeToIso(time) {
145
+ // Convert to UTC then to JS Date then to ISO. Floating times resolve as-if-UTC
146
+ // unless the caller is providing context via a viewer timezone (handled at the
147
+ // parse-events layer where the timezone param is known).
148
+ return time.toJSDate().toISOString();
149
+ }
150
+ //# sourceMappingURL=_shared.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"_shared.js","sourceRoot":"","sources":["../../src/ics/_shared.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export declare function initializeTimezones(): void;
2
+ //# sourceMappingURL=_tz-init.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"_tz-init.d.ts","sourceRoot":"","sources":["../../src/ics/_tz-init.ts"],"names":[],"mappings":"AAMA,wBAAgB,mBAAmB,IAAI,IAAI,CAqB1C"}
@@ -0,0 +1,29 @@
1
+ import { getVtimezone } from "@touch4it/ical-timezones";
2
+ import zones from "@touch4it/ical-timezones/zones.js";
3
+ import ICAL from "ical.js";
4
+ let initialized = false;
5
+ export function initializeTimezones() {
6
+ if (initialized)
7
+ return;
8
+ initialized = true;
9
+ for (const tzid of Object.keys(zones)) {
10
+ if (ICAL.TimezoneService.has(tzid))
11
+ continue;
12
+ const vtimezoneBlock = getVtimezone(tzid);
13
+ if (!vtimezoneBlock || typeof vtimezoneBlock !== "string")
14
+ continue;
15
+ try {
16
+ const root = ICAL.Component.fromString(vtimezoneBlock);
17
+ const vtz = root.getFirstSubcomponent("vtimezone");
18
+ if (vtz) {
19
+ const tz = new ICAL.Timezone({ component: vtz });
20
+ ICAL.TimezoneService.register(tz, tzid);
21
+ }
22
+ }
23
+ catch {
24
+ // Skip any malformed entries silently — vendor data, not user input.
25
+ }
26
+ }
27
+ }
28
+ initializeTimezones();
29
+ //# sourceMappingURL=_tz-init.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"_tz-init.js","sourceRoot":"","sources":["../../src/ics/_tz-init.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,0BAA0B,CAAC;AACxD,OAAO,KAAK,MAAM,mCAAmC,CAAC;AACtD,OAAO,IAAI,MAAM,SAAS,CAAC;AAE3B,IAAI,WAAW,GAAG,KAAK,CAAC;AAExB,MAAM,UAAU,mBAAmB;IACjC,IAAI,WAAW;QAAE,OAAO;IACxB,WAAW,GAAG,IAAI,CAAC;IAEnB,KAAK,MAAM,IAAI,IAAI,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC;QACtC,IAAI,IAAI,CAAC,eAAe,CAAC,GAAG,CAAC,IAAI,CAAC;YAAE,SAAS;QAE7C,MAAM,cAAc,GAAG,YAAY,CAAC,IAAI,CAAC,CAAC;QAC1C,IAAI,CAAC,cAAc,IAAI,OAAO,cAAc,KAAK,QAAQ;YAAE,SAAS;QAEpE,IAAI,CAAC;YACH,MAAM,IAAI,GAAG,IAAI,CAAC,SAAS,CAAC,UAAU,CAAC,cAAc,CAAC,CAAC;YACvD,MAAM,GAAG,GAAG,IAAI,CAAC,oBAAoB,CAAC,WAAW,CAAC,CAAC;YACnD,IAAI,GAAG,EAAE,CAAC;gBACR,MAAM,EAAE,GAAG,IAAI,IAAI,CAAC,QAAQ,CAAC,EAAE,SAAS,EAAE,GAAG,EAAE,CAAC,CAAC;gBACjD,IAAI,CAAC,eAAe,CAAC,QAAQ,CAAC,EAAE,EAAE,IAAI,CAAC,CAAC;YAC1C,CAAC;QACH,CAAC;QAAC,MAAM,CAAC;YACP,qEAAqE;QACvE,CAAC;IACH,CAAC;AACH,CAAC;AAED,mBAAmB,EAAE,CAAC"}
@@ -0,0 +1,26 @@
1
+ import "./_tz-init.js";
2
+ export interface ExceptionOverrides {
3
+ title?: string;
4
+ start?: string;
5
+ end?: string;
6
+ all_day?: boolean;
7
+ location?: string;
8
+ description?: string;
9
+ attendees?: Array<{
10
+ email: string;
11
+ }>;
12
+ alarms?: Array<{
13
+ type: "relative" | "absolute";
14
+ trigger: number | string;
15
+ }>;
16
+ categories?: string[];
17
+ organizer?: {
18
+ email: string;
19
+ name?: string | null;
20
+ };
21
+ availability?: "busy" | "free";
22
+ }
23
+ export declare function createExceptionComponent(masterIcs: string, componentType: "vevent" | "vtodo", occurrenceDate: string, overrides: ExceptionOverrides, allDay: boolean): string;
24
+ export declare function combineIcsComponents(masterIcs: string, exceptionComponent: string): string;
25
+ export declare function addExdateToIcs(icsContent: string, occurrenceDate: string, allDay: boolean): string;
26
+ //# sourceMappingURL=components.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"components.d.ts","sourceRoot":"","sources":["../../src/ics/components.ts"],"names":[],"mappings":"AACA,OAAO,eAAe,CAAC;AAIvB,MAAM,WAAW,kBAAkB;IACjC,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,SAAS,CAAC,EAAE,KAAK,CAAC;QAAE,KAAK,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IACrC,MAAM,CAAC,EAAE,KAAK,CAAC;QAAE,IAAI,EAAE,UAAU,GAAG,UAAU,CAAC;QAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAAA;KAAE,CAAC,CAAC;IAC5E,UAAU,CAAC,EAAE,MAAM,EAAE,CAAC;IACtB,SAAS,CAAC,EAAE;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,IAAI,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;KAAE,CAAC;IACpD,YAAY,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;CAChC;AAUD,wBAAgB,wBAAwB,CACtC,SAAS,EAAE,MAAM,EACjB,aAAa,EAAE,QAAQ,GAAG,OAAO,EACjC,cAAc,EAAE,MAAM,EACtB,SAAS,EAAE,kBAAkB,EAC7B,MAAM,EAAE,OAAO,GACd,MAAM,CAoGR;AAED,wBAAgB,oBAAoB,CAAC,SAAS,EAAE,MAAM,EAAE,kBAAkB,EAAE,MAAM,GAAG,MAAM,CAyC1F;AAED,wBAAgB,cAAc,CAC5B,UAAU,EAAE,MAAM,EAClB,cAAc,EAAE,MAAM,EACtB,MAAM,EAAE,OAAO,GACd,MAAM,CAiCR"}
@@ -0,0 +1,178 @@
1
+ import ICAL from "ical.js";
2
+ import "./_tz-init.js";
3
+ import { parseAttendees, parseCategories, parseOrganizer } from "./_shared.js";
4
+ import { IcsParseError } from "./errors.js";
5
+ function parseRoot(ics) {
6
+ try {
7
+ return ICAL.Component.fromString(ics);
8
+ }
9
+ catch (e) {
10
+ throw new IcsParseError("Invalid ICS content", e);
11
+ }
12
+ }
13
+ export function createExceptionComponent(masterIcs, componentType, occurrenceDate, overrides, allDay) {
14
+ const masterRoot = parseRoot(masterIcs);
15
+ const masterComp = masterRoot.getFirstSubcomponent(componentType);
16
+ if (!masterComp)
17
+ throw new IcsParseError(`No ${componentType} found in master ICS`, null);
18
+ // Read fields directly from the already-parsed component instead of running a
19
+ // second full pass through parseIcsEvents.
20
+ const rawUid = masterComp.getFirstPropertyValue("uid");
21
+ const uid = typeof rawUid === "string" ? rawUid : "";
22
+ const masterDtstart = masterComp.getFirstPropertyValue("dtstart");
23
+ const masterDtend = masterComp.getFirstPropertyValue("dtend");
24
+ const masterStartMs = masterDtstart instanceof ICAL.Time ? masterDtstart.toJSDate().getTime() : 0;
25
+ const masterEndMs = masterDtend instanceof ICAL.Time ? masterDtend.toJSDate().getTime() : 0;
26
+ const duration = masterEndMs - masterStartMs;
27
+ const occMs = new Date(occurrenceDate).getTime();
28
+ const defaultStart = new Date(occMs).toISOString();
29
+ const defaultEnd = new Date(occMs + duration).toISOString();
30
+ const rawSummary = masterComp.getFirstPropertyValue("summary");
31
+ const masterTitle = typeof rawSummary === "string" ? rawSummary : "";
32
+ const rawLocation = masterComp.getFirstPropertyValue("location");
33
+ const masterLocation = typeof rawLocation === "string" && rawLocation.length > 0 ? rawLocation : null;
34
+ const rawDescription = masterComp.getFirstPropertyValue("description");
35
+ const masterDescription = typeof rawDescription === "string" && rawDescription.length > 0 ? rawDescription : null;
36
+ const masterOrganizer = parseOrganizer(masterComp);
37
+ const masterAttendees = parseAttendees(masterComp);
38
+ const masterCategories = parseCategories(masterComp);
39
+ const masterTransp = masterComp.getFirstPropertyValue("transp");
40
+ let masterAvailability = null;
41
+ if (typeof masterTransp === "string") {
42
+ if (masterTransp.toUpperCase() === "OPAQUE")
43
+ masterAvailability = "busy";
44
+ else if (masterTransp.toUpperCase() === "TRANSPARENT")
45
+ masterAvailability = "free";
46
+ }
47
+ const ex = new ICAL.Component(componentType);
48
+ ex.updatePropertyWithValue("uid", uid);
49
+ const recurId = ICAL.Time.fromJSDate(new Date(occurrenceDate), true);
50
+ if (allDay)
51
+ recurId.isDate = true;
52
+ const recurProp = ex.updatePropertyWithValue("recurrence-id", recurId);
53
+ if (allDay)
54
+ recurProp.setParameter("value", "DATE");
55
+ const startIso = overrides.start ?? defaultStart;
56
+ const endIso = overrides.end ?? defaultEnd;
57
+ const isAllDay = overrides.all_day ?? allDay;
58
+ const dtstart = ICAL.Time.fromJSDate(new Date(startIso), true);
59
+ if (isAllDay)
60
+ dtstart.isDate = true;
61
+ const dtstartProp = ex.updatePropertyWithValue("dtstart", dtstart);
62
+ if (isAllDay)
63
+ dtstartProp.setParameter("value", "DATE");
64
+ const dtend = ICAL.Time.fromJSDate(new Date(endIso), true);
65
+ if (isAllDay)
66
+ dtend.isDate = true;
67
+ const dtendProp = ex.updatePropertyWithValue("dtend", dtend);
68
+ if (isAllDay)
69
+ dtendProp.setParameter("value", "DATE");
70
+ // SEQUENCE: bump master's
71
+ const masterSeq = masterComp.getFirstPropertyValue("sequence");
72
+ const seq = (typeof masterSeq === "number" ? masterSeq : 0) + 1;
73
+ ex.updatePropertyWithValue("sequence", seq);
74
+ ex.updatePropertyWithValue("summary", overrides.title ?? masterTitle);
75
+ if (overrides.location ?? masterLocation) {
76
+ ex.updatePropertyWithValue("location", overrides.location ?? masterLocation ?? "");
77
+ }
78
+ if (overrides.description ?? masterDescription) {
79
+ ex.updatePropertyWithValue("description", overrides.description ?? masterDescription ?? "");
80
+ }
81
+ const organizer = overrides.organizer ?? masterOrganizer;
82
+ if (organizer) {
83
+ const name = organizer.name && organizer.name.trim().length > 0
84
+ ? organizer.name
85
+ : organizer.email.split("@")[0];
86
+ const orgProp = ex.updatePropertyWithValue("organizer", `mailto:${organizer.email}`);
87
+ orgProp.setParameter("cn", name);
88
+ }
89
+ const attendees = overrides.attendees ?? masterAttendees;
90
+ if (attendees) {
91
+ for (const att of attendees) {
92
+ ex.addPropertyWithValue("attendee", `mailto:${att.email}`);
93
+ }
94
+ }
95
+ const categories = overrides.categories ?? masterCategories;
96
+ if (categories && categories.length > 0) {
97
+ ex.addPropertyWithValue("categories", categories.join(","));
98
+ }
99
+ const availability = overrides.availability ?? masterAvailability;
100
+ if (availability === "free")
101
+ ex.updatePropertyWithValue("transp", "TRANSPARENT");
102
+ else if (availability === "busy")
103
+ ex.updatePropertyWithValue("transp", "OPAQUE");
104
+ ex.updatePropertyWithValue("status", "CONFIRMED");
105
+ return ex.toString();
106
+ }
107
+ export function combineIcsComponents(masterIcs, exceptionComponent) {
108
+ const masterRoot = parseRoot(masterIcs);
109
+ // Guard against double-wrap: callers should pass a bare BEGIN:VEVENT…END:VEVENT
110
+ // block (the output of createExceptionComponent), not a full VCALENDAR.
111
+ if (/BEGIN:VCALENDAR/i.test(exceptionComponent)) {
112
+ throw new IcsParseError("exceptionComponent must be a bare VEVENT/VTODO block, not a full VCALENDAR", null);
113
+ }
114
+ // Wrap the bare exception VEVENT/VTODO in a synthetic VCALENDAR so it can be parsed.
115
+ const wrapped = `BEGIN:VCALENDAR\r\nVERSION:2.0\r\nPRODID:-//pim-core//combine//EN\r\n${exceptionComponent}\r\nEND:VCALENDAR`;
116
+ const exRoot = parseRoot(wrapped);
117
+ const exComp = exRoot.getFirstSubcomponent("vevent") ?? exRoot.getFirstSubcomponent("vtodo");
118
+ if (!exComp)
119
+ throw new IcsParseError("Exception component is not a VEVENT or VTODO", null);
120
+ const exUid = exComp.getFirstPropertyValue("uid");
121
+ const exRecurId = exComp.getFirstPropertyValue("recurrence-id");
122
+ if (!(exRecurId instanceof ICAL.Time)) {
123
+ throw new IcsParseError("Exception component must have a RECURRENCE-ID", null);
124
+ }
125
+ const exRecurMs = exRecurId.toJSDate().getTime();
126
+ const componentName = exComp.name;
127
+ // Find and remove any existing matching subcomponent.
128
+ const existing = masterRoot.getAllSubcomponents(componentName);
129
+ for (const sub of existing) {
130
+ const subUid = sub.getFirstPropertyValue("uid");
131
+ const subRecur = sub.getFirstPropertyValue("recurrence-id");
132
+ if (subUid === exUid &&
133
+ subRecur instanceof ICAL.Time &&
134
+ subRecur.toJSDate().getTime() === exRecurMs) {
135
+ masterRoot.removeSubcomponent(sub);
136
+ }
137
+ }
138
+ masterRoot.addSubcomponent(exComp);
139
+ return masterRoot.toString();
140
+ }
141
+ export function addExdateToIcs(icsContent, occurrenceDate, allDay) {
142
+ const root = parseRoot(icsContent);
143
+ // EXDATE goes on the master event (first VEVENT without a RECURRENCE-ID).
144
+ const masters = root
145
+ .getAllSubcomponents("vevent")
146
+ .filter((c) => !c.getFirstProperty("recurrence-id"));
147
+ const master = masters[0];
148
+ if (!master)
149
+ return icsContent;
150
+ const newDate = ICAL.Time.fromJSDate(new Date(occurrenceDate), true);
151
+ if (allDay)
152
+ newDate.isDate = true;
153
+ const newMs = newDate.toJSDate().getTime();
154
+ const newYmd = `${newDate.year}-${String(newDate.month).padStart(2, "0")}-${String(newDate.day).padStart(2, "0")}`;
155
+ // Idempotency check: scan existing EXDATE values. For all-day (DATE-typed)
156
+ // EXDATEs compare YYYY-MM-DD strings — toJSDate() on a date-only value uses
157
+ // local-midnight which can drift across DST boundaries vs. the new value's
158
+ // UTC-midnight epoch ms. For date-time EXDATEs the epoch comparison works.
159
+ for (const exProp of master.getAllProperties("exdate")) {
160
+ for (const v of exProp.getValues()) {
161
+ if (!(v instanceof ICAL.Time))
162
+ continue;
163
+ if (allDay && v.isDate) {
164
+ const vYmd = `${v.year}-${String(v.month).padStart(2, "0")}-${String(v.day).padStart(2, "0")}`;
165
+ if (vYmd === newYmd)
166
+ return icsContent;
167
+ }
168
+ else if (!allDay && !v.isDate && v.toJSDate().getTime() === newMs) {
169
+ return icsContent;
170
+ }
171
+ }
172
+ }
173
+ const exProp = master.addPropertyWithValue("exdate", newDate);
174
+ if (allDay)
175
+ exProp.setParameter("value", "DATE");
176
+ return root.toString();
177
+ }
178
+ //# sourceMappingURL=components.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"components.js","sourceRoot":"","sources":["../../src/ics/components.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,7 @@
1
+ export declare class IcsParseError extends Error {
2
+ constructor(message: string, cause: unknown);
3
+ }
4
+ export declare class IcsGenerateError extends Error {
5
+ constructor(message: string, cause: unknown);
6
+ }
7
+ //# sourceMappingURL=errors.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"errors.d.ts","sourceRoot":"","sources":["../../src/ics/errors.ts"],"names":[],"mappings":"AAAA,qBAAa,aAAc,SAAQ,KAAK;gBAC1B,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,OAAO;CAI5C;AAED,qBAAa,gBAAiB,SAAQ,KAAK;gBAC7B,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,OAAO;CAI5C"}
@@ -0,0 +1,13 @@
1
+ export class IcsParseError extends Error {
2
+ constructor(message, cause) {
3
+ super(message, { cause });
4
+ this.name = "IcsParseError";
5
+ }
6
+ }
7
+ export class IcsGenerateError extends Error {
8
+ constructor(message, cause) {
9
+ super(message, { cause });
10
+ this.name = "IcsGenerateError";
11
+ }
12
+ }
13
+ //# sourceMappingURL=errors.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"errors.js","sourceRoot":"","sources":["../../src/ics/errors.ts"],"names":[],"mappings":"AAAA,MAAM,OAAO,aAAc,SAAQ,KAAK;IACtC,YAAY,OAAe,EAAE,KAAc;QACzC,KAAK,CAAC,OAAO,EAAE,EAAE,KAAK,EAAE,CAAC,CAAC;QAC1B,IAAI,CAAC,IAAI,GAAG,eAAe,CAAC;IAC9B,CAAC;CACF;AAED,MAAM,OAAO,gBAAiB,SAAQ,KAAK;IACzC,YAAY,OAAe,EAAE,KAAc;QACzC,KAAK,CAAC,OAAO,EAAE,EAAE,KAAK,EAAE,CAAC,CAAC;QAC1B,IAAI,CAAC,IAAI,GAAG,kBAAkB,CAAC;IACjC,CAAC;CACF"}
@@ -0,0 +1,4 @@
1
+ import "./_tz-init.js";
2
+ import type { EventCreateProps } from "./types.js";
3
+ export declare function generateEventIcs(props: EventCreateProps): string;
4
+ //# sourceMappingURL=generate.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"generate.d.ts","sourceRoot":"","sources":["../../src/ics/generate.ts"],"names":[],"mappings":"AAGA,OAAO,eAAe,CAAC;AAGvB,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAC;AAoBnD,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,gBAAgB,GAAG,MAAM,CAqFhE"}
@@ -0,0 +1,101 @@
1
+ // packages/core/src/ics/generate.ts
2
+ import { randomUUID } from "node:crypto";
3
+ import ICAL from "ical.js";
4
+ import "./_tz-init.js";
5
+ import { IcsGenerateError } from "./errors.js";
6
+ import { normalizeRecurrenceRule } from "./rrule.js";
7
+ function toIcalTime(iso, allDay, tzid) {
8
+ const date = new Date(iso);
9
+ if (Number.isNaN(date.getTime())) {
10
+ throw new IcsGenerateError(`Invalid ISO date: ${iso}`, null);
11
+ }
12
+ if (allDay) {
13
+ return ICAL.Time.fromDateString(date.toISOString().slice(0, 10));
14
+ }
15
+ if (tzid) {
16
+ const zone = ICAL.TimezoneService.get(tzid);
17
+ if (zone) {
18
+ const utc = ICAL.Time.fromJSDate(date, true);
19
+ return utc.convertToZone(zone);
20
+ }
21
+ }
22
+ return ICAL.Time.fromJSDate(date, true);
23
+ }
24
+ export function generateEventIcs(props) {
25
+ if (props.attendees && props.attendees.length > 0 && !props.organizer) {
26
+ throw new IcsGenerateError("ORGANIZER is required when ATTENDEE is present (RFC 6638)", null);
27
+ }
28
+ const calendar = new ICAL.Component(["vcalendar", [], []]);
29
+ calendar.updatePropertyWithValue("prodid", "-//pim-core//cal-mcp//EN");
30
+ calendar.updatePropertyWithValue("version", "2.0");
31
+ if (props.timezone) {
32
+ const zone = ICAL.TimezoneService.get(props.timezone);
33
+ if (zone?.component) {
34
+ calendar.addSubcomponent(zone.component);
35
+ }
36
+ }
37
+ const vevent = new ICAL.Component("vevent");
38
+ const uid = props.uid ?? `${randomUUID()}@pim-core`;
39
+ vevent.updatePropertyWithValue("uid", uid);
40
+ vevent.updatePropertyWithValue("dtstamp", ICAL.Time.now());
41
+ vevent.updatePropertyWithValue("summary", props.title);
42
+ vevent.updatePropertyWithValue("status", "CONFIRMED");
43
+ const allDay = props.all_day === true;
44
+ const dtstart = toIcalTime(props.start, allDay, props.timezone);
45
+ const dtend = toIcalTime(props.end, allDay, props.timezone);
46
+ const dtstartProp = vevent.updatePropertyWithValue("dtstart", dtstart);
47
+ const dtendProp = vevent.updatePropertyWithValue("dtend", dtend);
48
+ if (props.timezone && !allDay) {
49
+ dtstartProp.setParameter("tzid", props.timezone);
50
+ dtendProp.setParameter("tzid", props.timezone);
51
+ }
52
+ if (props.location)
53
+ vevent.updatePropertyWithValue("location", props.location);
54
+ if (props.description)
55
+ vevent.updatePropertyWithValue("description", props.description);
56
+ if (props.availability === "free")
57
+ vevent.updatePropertyWithValue("transp", "TRANSPARENT");
58
+ else if (props.availability === "busy")
59
+ vevent.updatePropertyWithValue("transp", "OPAQUE");
60
+ if (props.organizer) {
61
+ const name = props.organizer.name && props.organizer.name.trim().length > 0
62
+ ? props.organizer.name
63
+ : props.organizer.email.split("@")[0];
64
+ const orgProp = vevent.updatePropertyWithValue("organizer", `mailto:${props.organizer.email}`);
65
+ orgProp.setParameter("cn", name);
66
+ }
67
+ if (props.attendees) {
68
+ for (const att of props.attendees) {
69
+ vevent.addPropertyWithValue("attendee", `mailto:${att.email}`);
70
+ }
71
+ }
72
+ if (props.categories && props.categories.length > 0) {
73
+ vevent.addPropertyWithValue("categories", props.categories.join(","));
74
+ }
75
+ if (props.recurrence_rule) {
76
+ const normalized = normalizeRecurrenceRule(props.recurrence_rule);
77
+ if (!normalized) {
78
+ throw new IcsGenerateError(`Invalid recurrence_rule: ${props.recurrence_rule}`, null);
79
+ }
80
+ vevent.addProperty(ICAL.Property.fromString(`RRULE:${normalized}`));
81
+ }
82
+ if (props.alarms) {
83
+ for (const alarm of props.alarms) {
84
+ const valarm = new ICAL.Component("valarm");
85
+ valarm.updatePropertyWithValue("action", "DISPLAY");
86
+ valarm.updatePropertyWithValue("description", props.title);
87
+ if (alarm.type === "relative" && typeof alarm.trigger === "number") {
88
+ const dur = ICAL.Duration.fromSeconds(alarm.trigger);
89
+ valarm.updatePropertyWithValue("trigger", dur);
90
+ }
91
+ else if (alarm.type === "absolute" && typeof alarm.trigger === "string") {
92
+ const t = ICAL.Time.fromJSDate(new Date(alarm.trigger), true);
93
+ valarm.updatePropertyWithValue("trigger", t);
94
+ }
95
+ vevent.addSubcomponent(valarm);
96
+ }
97
+ }
98
+ calendar.addSubcomponent(vevent);
99
+ return calendar.toString();
100
+ }
101
+ //# sourceMappingURL=generate.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"generate.js","sourceRoot":"","sources":["../../src/ics/generate.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,11 @@
1
+ import "./_tz-init.js";
2
+ export { IcsParseError, IcsGenerateError } from "./errors.js";
3
+ export type { ParsedAlarm, ParsedAttendee, ParsedOrganizer, ParsedGeo, ParsedEvent, ParsedTodo, ParsedJournal, TimeRange, EventCreateProps, } from "./types.js";
4
+ export { normalizeRecurrenceRule } from "./rrule.js";
5
+ export { parseIcsEvents } from "./parse-events.js";
6
+ export { parseIcsTodos } from "./parse-todos.js";
7
+ export { parseIcsJournals } from "./parse-journals.js";
8
+ export { generateEventIcs } from "./generate.js";
9
+ export { createExceptionComponent, combineIcsComponents, addExdateToIcs, } from "./components.js";
10
+ export type { ExceptionOverrides } from "./components.js";
11
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/ics/index.ts"],"names":[],"mappings":"AAGA,OAAO,eAAe,CAAC;AAEvB,OAAO,EAAE,aAAa,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAC;AAC9D,YAAY,EACV,WAAW,EACX,cAAc,EACd,eAAe,EACf,SAAS,EACT,WAAW,EACX,UAAU,EACV,aAAa,EACb,SAAS,EACT,gBAAgB,GACjB,MAAM,YAAY,CAAC;AACpB,OAAO,EAAE,uBAAuB,EAAE,MAAM,YAAY,CAAC;AACrD,OAAO,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAC;AACnD,OAAO,EAAE,aAAa,EAAE,MAAM,kBAAkB,CAAC;AACjD,OAAO,EAAE,gBAAgB,EAAE,MAAM,qBAAqB,CAAC;AACvD,OAAO,EAAE,gBAAgB,EAAE,MAAM,eAAe,CAAC;AACjD,OAAO,EACL,wBAAwB,EACxB,oBAAoB,EACpB,cAAc,GACf,MAAM,iBAAiB,CAAC;AACzB,YAAY,EAAE,kBAAkB,EAAE,MAAM,iBAAiB,CAAC"}
@@ -0,0 +1,12 @@
1
+ // Side-effect import: registers the IANA timezone set with ICAL.TimezoneService
2
+ // at module load. Consumers of @miguelarios/pim-core/ics get tz resolution wired
3
+ // up by virtue of importing from this barrel.
4
+ import "./_tz-init.js";
5
+ export { IcsParseError, IcsGenerateError } from "./errors.js";
6
+ export { normalizeRecurrenceRule } from "./rrule.js";
7
+ export { parseIcsEvents } from "./parse-events.js";
8
+ export { parseIcsTodos } from "./parse-todos.js";
9
+ export { parseIcsJournals } from "./parse-journals.js";
10
+ export { generateEventIcs } from "./generate.js";
11
+ export { createExceptionComponent, combineIcsComponents, addExdateToIcs, } from "./components.js";
12
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/ics/index.ts"],"names":[],"mappings":"AAAA,gFAAgF;AAChF,iFAAiF;AACjF,8CAA8C;AAC9C,OAAO,eAAe,CAAC;AAEvB,OAAO,EAAE,aAAa,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAC;AAY9D,OAAO,EAAE,uBAAuB,EAAE,MAAM,YAAY,CAAC;AACrD,OAAO,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAC;AACnD,OAAO,EAAE,aAAa,EAAE,MAAM,kBAAkB,CAAC;AACjD,OAAO,EAAE,gBAAgB,EAAE,MAAM,qBAAqB,CAAC;AACvD,OAAO,EAAE,gBAAgB,EAAE,MAAM,eAAe,CAAC;AACjD,OAAO,EACL,wBAAwB,EACxB,oBAAoB,EACpB,cAAc,GACf,MAAM,iBAAiB,CAAC"}
@@ -0,0 +1,4 @@
1
+ import "./_tz-init.js";
2
+ import type { ParsedEvent, TimeRange } from "./types.js";
3
+ export declare function parseIcsEvents(icsContent: string, range?: TimeRange, timezone?: string): ParsedEvent[];
4
+ //# sourceMappingURL=parse-events.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"parse-events.d.ts","sourceRoot":"","sources":["../../src/ics/parse-events.ts"],"names":[],"mappings":"AACA,OAAO,eAAe,CAAC;AAUvB,OAAO,KAAK,EAAE,WAAW,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AAoKzD,wBAAgB,cAAc,CAC5B,UAAU,EAAE,MAAM,EAClB,KAAK,CAAC,EAAE,SAAS,EACjB,QAAQ,CAAC,EAAE,MAAM,GAChB,WAAW,EAAE,CAiEf"}
@@ -0,0 +1,223 @@
1
+ import ICAL from "ical.js";
2
+ import "./_tz-init.js";
3
+ import { parseAlarms, parseAttendees, parseCategories, parseGeo, parseOrganizer, timeToIso, } from "./_shared.js";
4
+ import { IcsParseError } from "./errors.js";
5
+ function nullIfEmpty(value) {
6
+ if (typeof value !== "string")
7
+ return null;
8
+ return value.length > 0 ? value : null;
9
+ }
10
+ function buildBaseEvent(component) {
11
+ const url = component.getFirstPropertyValue("url");
12
+ const status = component.getFirstPropertyValue("status");
13
+ const transp = component.getFirstPropertyValue("transp");
14
+ const rrule = component.getFirstPropertyValue("rrule");
15
+ const created = component.getFirstPropertyValue("created");
16
+ const lastModified = component.getFirstPropertyValue("last-modified");
17
+ const rdateProps = component.getAllProperties("rdate");
18
+ const rdates = [];
19
+ for (const prop of rdateProps) {
20
+ for (const v of prop.getValues()) {
21
+ if (v instanceof ICAL.Time)
22
+ rdates.push(timeToIso(v));
23
+ }
24
+ }
25
+ let availability = null;
26
+ if (typeof transp === "string") {
27
+ if (transp.toUpperCase() === "OPAQUE")
28
+ availability = "busy";
29
+ else if (transp.toUpperCase() === "TRANSPARENT")
30
+ availability = "free";
31
+ }
32
+ const summary = component.getFirstPropertyValue("summary");
33
+ const uid = component.getFirstPropertyValue("uid");
34
+ const location = component.getFirstPropertyValue("location");
35
+ const description = component.getFirstPropertyValue("description");
36
+ return {
37
+ uid: typeof uid === "string" ? uid : "",
38
+ title: typeof summary === "string" ? summary : "",
39
+ all_day: false, // overwritten below per-instance
40
+ location: nullIfEmpty(location),
41
+ description: nullIfEmpty(description),
42
+ status: typeof status === "string" ? status.toLowerCase() : null,
43
+ availability,
44
+ url: typeof url === "string" && url.length > 0 ? url : null,
45
+ attendees: parseAttendees(component),
46
+ categories: parseCategories(component),
47
+ geo: parseGeo(component),
48
+ organizer: parseOrganizer(component),
49
+ recurrence_rule: rrule ? rrule.toString() : null,
50
+ rdates: rdates.length > 0 ? rdates : null,
51
+ created: created instanceof ICAL.Time ? created.toJSDate().toISOString() : null,
52
+ last_modified: lastModified instanceof ICAL.Time ? lastModified.toJSDate().toISOString() : null,
53
+ is_recurring: !!rrule,
54
+ alarms: parseAlarms(component),
55
+ occurrence_date: null,
56
+ };
57
+ }
58
+ function dateOnlyToIso(time) {
59
+ // For VALUE=DATE values, treat as UTC midnight rather than local-midnight.
60
+ // ICAL.Time.toJSDate() for date-only values uses the local Date constructor
61
+ // which makes the result depend on the test machine's tz; we want a
62
+ // deterministic ISO string anchored at UTC midnight.
63
+ const yyyy = time.year.toString().padStart(4, "0");
64
+ const mm = time.month.toString().padStart(2, "0");
65
+ const dd = time.day.toString().padStart(2, "0");
66
+ return `${yyyy}-${mm}-${dd}T00:00:00.000Z`;
67
+ }
68
+ function timeToEventIso(time) {
69
+ return time.isDate ? dateOnlyToIso(time) : time.toJSDate().toISOString();
70
+ }
71
+ // A floating time has no TZID and is not UTC ("Z"). In ical.js v2 the parser
72
+ // assigns ICAL.Timezone.localTimezone to such values, which makes
73
+ // toJSDate() interpret the wall-clock components in the host process tz.
74
+ // That makes parser output non-deterministic across machines. When the caller
75
+ // passes a `timezone` argument, treat it as the viewer's preferred zone and
76
+ // re-anchor the wall-clock there before converting to UTC.
77
+ function isFloating(time) {
78
+ if (time.isDate)
79
+ return false;
80
+ const zone = time.zone;
81
+ return zone === ICAL.Timezone.localTimezone || zone == null;
82
+ }
83
+ function timeToEventIsoWithTz(time, timezone) {
84
+ if (time.isDate)
85
+ return dateOnlyToIso(time);
86
+ if (timezone && isFloating(time)) {
87
+ const tz = ICAL.TimezoneService.get(timezone);
88
+ if (tz) {
89
+ // Build a fresh ICAL.Time with the same wall-clock components anchored
90
+ // in the requested zone. Mutating `time.zone` directly also works in
91
+ // ical.js v2 but constructing a new value avoids touching the caller's
92
+ // component tree.
93
+ const rebound = new ICAL.Time({
94
+ year: time.year,
95
+ month: time.month,
96
+ day: time.day,
97
+ hour: time.hour,
98
+ minute: time.minute,
99
+ second: time.second,
100
+ isDate: false,
101
+ }, tz);
102
+ return rebound.toJSDate().toISOString();
103
+ }
104
+ }
105
+ return time.toJSDate().toISOString();
106
+ }
107
+ function emitNonExpanded(component, isException, timezone) {
108
+ const base = buildBaseEvent(component);
109
+ const dtstart = component.getFirstPropertyValue("dtstart");
110
+ const dtend = component.getFirstPropertyValue("dtend");
111
+ if (!(dtstart instanceof ICAL.Time))
112
+ return [];
113
+ const allDay = dtstart.isDate;
114
+ const startIso = timeToEventIsoWithTz(dtstart, timezone);
115
+ const endIso = dtend instanceof ICAL.Time ? timeToEventIsoWithTz(dtend, timezone) : startIso;
116
+ let occDate = null;
117
+ if (isException) {
118
+ const recurId = component.getFirstPropertyValue("recurrence-id");
119
+ if (recurId instanceof ICAL.Time)
120
+ occDate = recurId.toJSDate().toISOString();
121
+ }
122
+ return [{ ...base, all_day: allDay, start: startIso, end: endIso, occurrence_date: occDate }];
123
+ }
124
+ function emitOccurrences(event, range, timezone) {
125
+ const out = [];
126
+ const rangeStart = ICAL.Time.fromJSDate(new Date(range.start), true);
127
+ const rangeEnd = ICAL.Time.fromJSDate(new Date(range.end), true);
128
+ const it = event.iterator();
129
+ // event.iterator().next() returns null/undefined when the series is exhausted
130
+ // (finite RRULEs with COUNT or UNTIL hit this branch). Range is half-open
131
+ // [start, end) per RFC 4791 §9.9 — an occurrence whose DTSTART equals
132
+ // range.end is excluded.
133
+ while (true) {
134
+ const next = it.next();
135
+ if (!next)
136
+ break;
137
+ if (next.compare(rangeEnd) >= 0)
138
+ break;
139
+ if (next.compare(rangeStart) < 0)
140
+ continue;
141
+ const details = event.getOccurrenceDetails(next);
142
+ const effective = details.item; // master or exception override
143
+ const base = buildBaseEvent(effective.component);
144
+ const allDay = details.startDate.isDate;
145
+ out.push({
146
+ ...base,
147
+ all_day: allDay,
148
+ start: timeToEventIsoWithTz(details.startDate, timezone),
149
+ end: timeToEventIsoWithTz(details.endDate, timezone),
150
+ // occurrence_date is the original RRULE-generated slot (RECURRENCE-ID).
151
+ // For ordinary occurrences this equals startDate; for exception overrides
152
+ // it is the original time the occurrence was supposed to fire, which is
153
+ // what consumers need to reconcile overrides back to the master series.
154
+ occurrence_date: timeToEventIsoWithTz(details.recurrenceId, timezone),
155
+ });
156
+ }
157
+ return out;
158
+ }
159
+ export function parseIcsEvents(icsContent, range, timezone) {
160
+ if (!icsContent.trim())
161
+ return [];
162
+ let root;
163
+ try {
164
+ root = ICAL.Component.fromString(icsContent);
165
+ }
166
+ catch (e) {
167
+ throw new IcsParseError("Invalid ICS content", e);
168
+ }
169
+ const veventComponents = root.getAllSubcomponents("vevent");
170
+ // Group by UID. Master events have no RECURRENCE-ID; exception VEVENTs do.
171
+ const groups = new Map();
172
+ for (const comp of veventComponents) {
173
+ // UID is REQUIRED by RFC 5545 §3.8.4.7 but real-world fixtures sometimes
174
+ // omit it (e.g. ical.js sample timezone_from_file.ics). Bucket UID-less
175
+ // VEVENTs under the empty string so they still surface to consumers
176
+ // rather than being silently dropped.
177
+ const rawUid = comp.getFirstPropertyValue("uid");
178
+ const uid = typeof rawUid === "string" ? rawUid : "";
179
+ let group = groups.get(uid);
180
+ if (!group) {
181
+ group = { master: null, exceptions: [] };
182
+ groups.set(uid, group);
183
+ }
184
+ if (comp.getFirstProperty("recurrence-id")) {
185
+ group.exceptions.push(comp);
186
+ }
187
+ else {
188
+ group.master = comp;
189
+ }
190
+ }
191
+ const out = [];
192
+ for (const [, group] of groups) {
193
+ if (!group.master) {
194
+ // Orphan exception VEVENTs (master not in this ICS) — emit each as standalone.
195
+ for (const ex of group.exceptions) {
196
+ out.push(...emitNonExpanded(ex, true, timezone));
197
+ }
198
+ continue;
199
+ }
200
+ let event;
201
+ try {
202
+ event = new ICAL.Event(group.master);
203
+ for (const ex of group.exceptions) {
204
+ event.relateException(new ICAL.Event(ex));
205
+ }
206
+ }
207
+ catch {
208
+ // If ICAL.Event construction fails for this group, skip it but don't fail the batch.
209
+ continue;
210
+ }
211
+ if (event.isRecurring() && range) {
212
+ out.push(...emitOccurrences(event, range, timezone));
213
+ }
214
+ else {
215
+ out.push(...emitNonExpanded(group.master, false, timezone));
216
+ for (const ex of group.exceptions) {
217
+ out.push(...emitNonExpanded(ex, true, timezone));
218
+ }
219
+ }
220
+ }
221
+ return out;
222
+ }
223
+ //# sourceMappingURL=parse-events.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"parse-events.js","sourceRoot":"","sources":["../../src/ics/parse-events.ts"],"names":[],"mappings":"AAAA,OAAO,IAAI,MAAM,SAAS,CAAC;AAC3B,OAAO,eAAe,CAAC;AACvB,OAAO,EACL,WAAW,EACX,cAAc,EACd,eAAe,EACf,QAAQ,EACR,cAAc,EACd,SAAS,GACV,MAAM,cAAc,CAAC;AACtB,OAAO,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAG5C,SAAS,WAAW,CAAC,KAAc;IACjC,IAAI,OAAO,KAAK,KAAK,QAAQ;QAAE,OAAO,IAAI,CAAC;IAC3C,OAAO,KAAK,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,CAAC;AACzC,CAAC;AAED,SAAS,cAAc,CAAC,SAAyB;IAC/C,MAAM,GAAG,GAAG,SAAS,CAAC,qBAAqB,CAAC,KAAK,CAAC,CAAC;IACnD,MAAM,MAAM,GAAG,SAAS,CAAC,qBAAqB,CAAC,QAAQ,CAAC,CAAC;IACzD,MAAM,MAAM,GAAG,SAAS,CAAC,qBAAqB,CAAC,QAAQ,CAAC,CAAC;IACzD,MAAM,KAAK,GAAG,SAAS,CAAC,qBAAqB,CAAC,OAAO,CAAC,CAAC;IACvD,MAAM,OAAO,GAAG,SAAS,CAAC,qBAAqB,CAAC,SAAS,CAAC,CAAC;IAC3D,MAAM,YAAY,GAAG,SAAS,CAAC,qBAAqB,CAAC,eAAe,CAAC,CAAC;IAEtE,MAAM,UAAU,GAAG,SAAS,CAAC,gBAAgB,CAAC,OAAO,CAAC,CAAC;IACvD,MAAM,MAAM,GAAa,EAAE,CAAC;IAC5B,KAAK,MAAM,IAAI,IAAI,UAAU,EAAE,CAAC;QAC9B,KAAK,MAAM,CAAC,IAAI,IAAI,CAAC,SAAS,EAAE,EAAE,CAAC;YACjC,IAAI,CAAC,YAAY,IAAI,CAAC,IAAI;gBAAE,MAAM,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,CAAC;QACxD,CAAC;IACH,CAAC;IAED,IAAI,YAAY,GAAkB,IAAI,CAAC;IACvC,IAAI,OAAO,MAAM,KAAK,QAAQ,EAAE,CAAC;QAC/B,IAAI,MAAM,CAAC,WAAW,EAAE,KAAK,QAAQ;YAAE,YAAY,GAAG,MAAM,CAAC;aACxD,IAAI,MAAM,CAAC,WAAW,EAAE,KAAK,aAAa;YAAE,YAAY,GAAG,MAAM,CAAC;IACzE,CAAC;IAED,MAAM,OAAO,GAAG,SAAS,CAAC,qBAAqB,CAAC,SAAS,CAAC,CAAC;IAC3D,MAAM,GAAG,GAAG,SAAS,CAAC,qBAAqB,CAAC,KAAK,CAAC,CAAC;IACnD,MAAM,QAAQ,GAAG,SAAS,CAAC,qBAAqB,CAAC,UAAU,CAAC,CAAC;IAC7D,MAAM,WAAW,GAAG,SAAS,CAAC,qBAAqB,CAAC,aAAa,CAAC,CAAC;IAEnE,OAAO;QACL,GAAG,EAAE,OAAO,GAAG,KAAK,QAAQ,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE;QACvC,KAAK,EAAE,OAAO,OAAO,KAAK,QAAQ,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE;QACjD,OAAO,EAAE,KAAK,EAAE,iCAAiC;QACjD,QAAQ,EAAE,WAAW,CAAC,QAAQ,CAAC;QAC/B,WAAW,EAAE,WAAW,CAAC,WAAW,CAAC;QACrC,MAAM,EAAE,OAAO,MAAM,KAAK,QAAQ,CAAC,CAAC,CAAC,MAAM,CAAC,WAAW,EAAE,CAAC,CAAC,CAAC,IAAI;QAChE,YAAY;QACZ,GAAG,EAAE,OAAO,GAAG,KAAK,QAAQ,IAAI,GAAG,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI;QAC3D,SAAS,EAAE,cAAc,CAAC,SAAS,CAAC;QACpC,UAAU,EAAE,eAAe,CAAC,SAAS,CAAC;QACtC,GAAG,EAAE,QAAQ,CAAC,SAAS,CAAC;QACxB,SAAS,EAAE,cAAc,CAAC,SAAS,CAAC;QACpC,eAAe,EAAE,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,QAAQ,EAAE,CAAC,CAAC,CAAC,IAAI;QAChD,MAAM,EAAE,MAAM,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,IAAI;QACzC,OAAO,EAAE,OAAO,YAAY,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,OAAO,CAAC,QAAQ,EAAE,CAAC,WAAW,EAAE,CAAC,CAAC,CAAC,IAAI;QAC/E,aAAa,EAAE,YAAY,YAAY,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,YAAY,CAAC,QAAQ,EAAE,CAAC,WAAW,EAAE,CAAC,CAAC,CAAC,IAAI;QAC/F,YAAY,EAAE,CAAC,CAAC,KAAK;QACrB,MAAM,EAAE,WAAW,CAAC,SAAS,CAAC;QAC9B,eAAe,EAAE,IAAI;KACtB,CAAC;AACJ,CAAC;AAED,SAAS,aAAa,CAAC,IAAe;IACpC,2EAA2E;IAC3E,4EAA4E;IAC5E,oEAAoE;IACpE,qDAAqD;IACrD,MAAM,IAAI,GAAG,IAAI,CAAC,IAAI,CAAC,QAAQ,EAAE,CAAC,QAAQ,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC;IACnD,MAAM,EAAE,GAAG,IAAI,CAAC,KAAK,CAAC,QAAQ,EAAE,CAAC,QAAQ,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC;IAClD,MAAM,EAAE,GAAG,IAAI,CAAC,GAAG,CAAC,QAAQ,EAAE,CAAC,QAAQ,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC;IAChD,OAAO,GAAG,IAAI,IAAI,EAAE,IAAI,EAAE,gBAAgB,CAAC;AAC7C,CAAC;AAED,SAAS,cAAc,CAAC,IAAe;IACrC,OAAO,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,aAAa,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,QAAQ,EAAE,CAAC,WAAW,EAAE,CAAC;AAC3E,CAAC;AAED,6EAA6E;AAC7E,kEAAkE;AAClE,yEAAyE;AACzE,8EAA8E;AAC9E,4EAA4E;AAC5E,2DAA2D;AAC3D,SAAS,UAAU,CAAC,IAAe;IACjC,IAAI,IAAI,CAAC,MAAM;QAAE,OAAO,KAAK,CAAC;IAC9B,MAAM,IAAI,GAAG,IAAI,CAAC,IAAI,CAAC;IACvB,OAAO,IAAI,KAAK,IAAI,CAAC,QAAQ,CAAC,aAAa,IAAI,IAAI,IAAI,IAAI,CAAC;AAC9D,CAAC;AAED,SAAS,oBAAoB,CAAC,IAAe,EAAE,QAAiB;IAC9D,IAAI,IAAI,CAAC,MAAM;QAAE,OAAO,aAAa,CAAC,IAAI,CAAC,CAAC;IAC5C,IAAI,QAAQ,IAAI,UAAU,CAAC,IAAI,CAAC,EAAE,CAAC;QACjC,MAAM,EAAE,GAAG,IAAI,CAAC,eAAe,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;QAC9C,IAAI,EAAE,EAAE,CAAC;YACP,uEAAuE;YACvE,qEAAqE;YACrE,uEAAuE;YACvE,kBAAkB;YAClB,MAAM,OAAO,GAAG,IAAI,IAAI,CAAC,IAAI,CAC3B;gBACE,IAAI,EAAE,IAAI,CAAC,IAAI;gBACf,KAAK,EAAE,IAAI,CAAC,KAAK;gBACjB,GAAG,EAAE,IAAI,CAAC,GAAG;gBACb,IAAI,EAAE,IAAI,CAAC,IAAI;gBACf,MAAM,EAAE,IAAI,CAAC,MAAM;gBACnB,MAAM,EAAE,IAAI,CAAC,MAAM;gBACnB,MAAM,EAAE,KAAK;aACd,EACD,EAAE,CACH,CAAC;YACF,OAAO,OAAO,CAAC,QAAQ,EAAE,CAAC,WAAW,EAAE,CAAC;QAC1C,CAAC;IACH,CAAC;IACD,OAAO,IAAI,CAAC,QAAQ,EAAE,CAAC,WAAW,EAAE,CAAC;AACvC,CAAC;AAED,SAAS,eAAe,CACtB,SAAyB,EACzB,WAAoB,EACpB,QAAiB;IAEjB,MAAM,IAAI,GAAG,cAAc,CAAC,SAAS,CAAC,CAAC;IACvC,MAAM,OAAO,GAAG,SAAS,CAAC,qBAAqB,CAAC,SAAS,CAAC,CAAC;IAC3D,MAAM,KAAK,GAAG,SAAS,CAAC,qBAAqB,CAAC,OAAO,CAAC,CAAC;IACvD,IAAI,CAAC,CAAC,OAAO,YAAY,IAAI,CAAC,IAAI,CAAC;QAAE,OAAO,EAAE,CAAC;IAC/C,MAAM,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;IAC9B,MAAM,QAAQ,GAAG,oBAAoB,CAAC,OAAO,EAAE,QAAQ,CAAC,CAAC;IACzD,MAAM,MAAM,GAAG,KAAK,YAAY,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,oBAAoB,CAAC,KAAK,EAAE,QAAQ,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC;IAC7F,IAAI,OAAO,GAAkB,IAAI,CAAC;IAClC,IAAI,WAAW,EAAE,CAAC;QAChB,MAAM,OAAO,GAAG,SAAS,CAAC,qBAAqB,CAAC,eAAe,CAAC,CAAC;QACjE,IAAI,OAAO,YAAY,IAAI,CAAC,IAAI;YAAE,OAAO,GAAG,OAAO,CAAC,QAAQ,EAAE,CAAC,WAAW,EAAE,CAAC;IAC/E,CAAC;IACD,OAAO,CAAC,EAAE,GAAG,IAAI,EAAE,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,QAAQ,EAAE,GAAG,EAAE,MAAM,EAAE,eAAe,EAAE,OAAO,EAAE,CAAC,CAAC;AAChG,CAAC;AAED,SAAS,eAAe,CAAC,KAAiB,EAAE,KAAgB,EAAE,QAAiB;IAC7E,MAAM,GAAG,GAAkB,EAAE,CAAC;IAC9B,MAAM,UAAU,GAAG,IAAI,CAAC,IAAI,CAAC,UAAU,CAAC,IAAI,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,EAAE,IAAI,CAAC,CAAC;IACrE,MAAM,QAAQ,GAAG,IAAI,CAAC,IAAI,CAAC,UAAU,CAAC,IAAI,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,EAAE,IAAI,CAAC,CAAC;IACjE,MAAM,EAAE,GAAG,KAAK,CAAC,QAAQ,EAAE,CAAC;IAC5B,8EAA8E;IAC9E,0EAA0E;IAC1E,sEAAsE;IACtE,yBAAyB;IACzB,OAAO,IAAI,EAAE,CAAC;QACZ,MAAM,IAAI,GAAiC,EAAE,CAAC,IAAI,EAAE,CAAC;QACrD,IAAI,CAAC,IAAI;YAAE,MAAM;QACjB,IAAI,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAC;YAAE,MAAM;QACvC,IAAI,IAAI,CAAC,OAAO,CAAC,UAAU,CAAC,GAAG,CAAC;YAAE,SAAS;QAC3C,MAAM,OAAO,GAAG,KAAK,CAAC,oBAAoB,CAAC,IAAI,CAAC,CAAC;QACjD,MAAM,SAAS,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC,+BAA+B;QAC/D,MAAM,IAAI,GAAG,cAAc,CAAC,SAAS,CAAC,SAAS,CAAC,CAAC;QACjD,MAAM,MAAM,GAAG,OAAO,CAAC,SAAS,CAAC,MAAM,CAAC;QACxC,GAAG,CAAC,IAAI,CAAC;YACP,GAAG,IAAI;YACP,OAAO,EAAE,MAAM;YACf,KAAK,EAAE,oBAAoB,CAAC,OAAO,CAAC,SAAS,EAAE,QAAQ,CAAC;YACxD,GAAG,EAAE,oBAAoB,CAAC,OAAO,CAAC,OAAO,EAAE,QAAQ,CAAC;YACpD,wEAAwE;YACxE,0EAA0E;YAC1E,wEAAwE;YACxE,wEAAwE;YACxE,eAAe,EAAE,oBAAoB,CAAC,OAAO,CAAC,YAAY,EAAE,QAAQ,CAAC;SACtE,CAAC,CAAC;IACL,CAAC;IACD,OAAO,GAAG,CAAC;AACb,CAAC;AAED,MAAM,UAAU,cAAc,CAC5B,UAAkB,EAClB,KAAiB,EACjB,QAAiB;IAEjB,IAAI,CAAC,UAAU,CAAC,IAAI,EAAE;QAAE,OAAO,EAAE,CAAC;IAElC,IAAI,IAAoB,CAAC;IACzB,IAAI,CAAC;QACH,IAAI,GAAG,IAAI,CAAC,SAAS,CAAC,UAAU,CAAC,UAAU,CAAC,CAAC;IAC/C,CAAC;IAAC,OAAO,CAAC,EAAE,CAAC;QACX,MAAM,IAAI,aAAa,CAAC,qBAAqB,EAAE,CAAC,CAAC,CAAC;IACpD,CAAC;IAED,MAAM,gBAAgB,GAAG,IAAI,CAAC,mBAAmB,CAAC,QAAQ,CAAC,CAAC;IAC5D,2EAA2E;IAC3E,MAAM,MAAM,GAAG,IAAI,GAAG,EAA2E,CAAC;IAClG,KAAK,MAAM,IAAI,IAAI,gBAAgB,EAAE,CAAC;QACpC,yEAAyE;QACzE,wEAAwE;QACxE,oEAAoE;QACpE,sCAAsC;QACtC,MAAM,MAAM,GAAG,IAAI,CAAC,qBAAqB,CAAC,KAAK,CAAC,CAAC;QACjD,MAAM,GAAG,GAAG,OAAO,MAAM,KAAK,QAAQ,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC;QACrD,IAAI,KAAK,GAAG,MAAM,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;QAC5B,IAAI,CAAC,KAAK,EAAE,CAAC;YACX,KAAK,GAAG,EAAE,MAAM,EAAE,IAAI,EAAE,UAAU,EAAE,EAAE,EAAE,CAAC;YACzC,MAAM,CAAC,GAAG,CAAC,GAAG,EAAE,KAAK,CAAC,CAAC;QACzB,CAAC;QACD,IAAI,IAAI,CAAC,gBAAgB,CAAC,eAAe,CAAC,EAAE,CAAC;YAC3C,KAAK,CAAC,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QAC9B,CAAC;aAAM,CAAC;YACN,KAAK,CAAC,MAAM,GAAG,IAAI,CAAC;QACtB,CAAC;IACH,CAAC;IAED,MAAM,GAAG,GAAkB,EAAE,CAAC;IAE9B,KAAK,MAAM,CAAC,EAAE,KAAK,CAAC,IAAI,MAAM,EAAE,CAAC;QAC/B,IAAI,CAAC,KAAK,CAAC,MAAM,EAAE,CAAC;YAClB,+EAA+E;YAC/E,KAAK,MAAM,EAAE,IAAI,KAAK,CAAC,UAAU,EAAE,CAAC;gBAClC,GAAG,CAAC,IAAI,CAAC,GAAG,eAAe,CAAC,EAAE,EAAE,IAAI,EAAE,QAAQ,CAAC,CAAC,CAAC;YACnD,CAAC;YACD,SAAS;QACX,CAAC;QAED,IAAI,KAAiB,CAAC;QACtB,IAAI,CAAC;YACH,KAAK,GAAG,IAAI,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC;YACrC,KAAK,MAAM,EAAE,IAAI,KAAK,CAAC,UAAU,EAAE,CAAC;gBAClC,KAAK,CAAC,eAAe,CAAC,IAAI,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC,CAAC;YAC5C,CAAC;QACH,CAAC;QAAC,MAAM,CAAC;YACP,qFAAqF;YACrF,SAAS;QACX,CAAC;QAED,IAAI,KAAK,CAAC,WAAW,EAAE,IAAI,KAAK,EAAE,CAAC;YACjC,GAAG,CAAC,IAAI,CAAC,GAAG,eAAe,CAAC,KAAK,EAAE,KAAK,EAAE,QAAQ,CAAC,CAAC,CAAC;QACvD,CAAC;aAAM,CAAC;YACN,GAAG,CAAC,IAAI,CAAC,GAAG,eAAe,CAAC,KAAK,CAAC,MAAM,EAAE,KAAK,EAAE,QAAQ,CAAC,CAAC,CAAC;YAC5D,KAAK,MAAM,EAAE,IAAI,KAAK,CAAC,UAAU,EAAE,CAAC;gBAClC,GAAG,CAAC,IAAI,CAAC,GAAG,eAAe,CAAC,EAAE,EAAE,IAAI,EAAE,QAAQ,CAAC,CAAC,CAAC;YACnD,CAAC;QACH,CAAC;IACH,CAAC;IAED,OAAO,GAAG,CAAC;AACb,CAAC"}
@@ -0,0 +1,4 @@
1
+ import "./_tz-init.js";
2
+ import type { ParsedJournal } from "./types.js";
3
+ export declare function parseIcsJournals(icsContent: string): ParsedJournal[];
4
+ //# sourceMappingURL=parse-journals.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"parse-journals.d.ts","sourceRoot":"","sources":["../../src/ics/parse-journals.ts"],"names":[],"mappings":"AACA,OAAO,eAAe,CAAC;AAGvB,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAWhD,wBAAgB,gBAAgB,CAAC,UAAU,EAAE,MAAM,GAAG,aAAa,EAAE,CA2CpE"}
@@ -0,0 +1,54 @@
1
+ import ICAL from "ical.js";
2
+ import "./_tz-init.js";
3
+ import { parseCategories } from "./_shared.js";
4
+ import { IcsParseError } from "./errors.js";
5
+ function dateOnlyToString(t) {
6
+ // For VALUE=DATE properties, ical.js sets isDate=true and the JS Date is at midnight UTC.
7
+ // Emit YYYY-MM-DD without timezone interpretation.
8
+ const yr = t.year.toString().padStart(4, "0");
9
+ const mo = t.month.toString().padStart(2, "0");
10
+ const da = t.day.toString().padStart(2, "0");
11
+ return `${yr}-${mo}-${da}`;
12
+ }
13
+ export function parseIcsJournals(icsContent) {
14
+ if (!icsContent.trim())
15
+ return [];
16
+ let root;
17
+ try {
18
+ root = ICAL.Component.fromString(icsContent);
19
+ }
20
+ catch (e) {
21
+ throw new IcsParseError("Invalid ICS content", e);
22
+ }
23
+ const out = [];
24
+ for (const vjournal of root.getAllSubcomponents("vjournal")) {
25
+ try {
26
+ const dtstart = vjournal.getFirstPropertyValue("dtstart");
27
+ const status = vjournal.getFirstPropertyValue("status");
28
+ const created = vjournal.getFirstPropertyValue("created");
29
+ const lastModified = vjournal.getFirstPropertyValue("last-modified");
30
+ let dateStr = "";
31
+ if (dtstart instanceof ICAL.Time) {
32
+ dateStr = dtstart.isDate ? dateOnlyToString(dtstart) : dtstart.toJSDate().toISOString();
33
+ }
34
+ const rawUid = vjournal.getFirstPropertyValue("uid");
35
+ const rawSummary = vjournal.getFirstPropertyValue("summary");
36
+ const rawDescription = vjournal.getFirstPropertyValue("description");
37
+ out.push({
38
+ uid: typeof rawUid === "string" ? rawUid : "",
39
+ title: typeof rawSummary === "string" ? rawSummary : "",
40
+ date: dateStr,
41
+ description: typeof rawDescription === "string" ? rawDescription : null,
42
+ categories: parseCategories(vjournal),
43
+ status: typeof status === "string" ? status.toLowerCase() : null,
44
+ created: created instanceof ICAL.Time ? created.toJSDate().toISOString() : null,
45
+ last_modified: lastModified instanceof ICAL.Time ? lastModified.toJSDate().toISOString() : null,
46
+ });
47
+ }
48
+ catch {
49
+ // Skip malformed VJOURNAL, don't fail whole batch.
50
+ }
51
+ }
52
+ return out;
53
+ }
54
+ //# sourceMappingURL=parse-journals.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"parse-journals.js","sourceRoot":"","sources":["../../src/ics/parse-journals.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,4 @@
1
+ import "./_tz-init.js";
2
+ import type { ParsedTodo } from "./types.js";
3
+ export declare function parseIcsTodos(icsContent: string): ParsedTodo[];
4
+ //# sourceMappingURL=parse-todos.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"parse-todos.d.ts","sourceRoot":"","sources":["../../src/ics/parse-todos.ts"],"names":[],"mappings":"AACA,OAAO,eAAe,CAAC;AAGvB,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AAE7C,wBAAgB,aAAa,CAAC,UAAU,EAAE,MAAM,GAAG,UAAU,EAAE,CAkD9D"}
@@ -0,0 +1,55 @@
1
+ import ICAL from "ical.js";
2
+ import "./_tz-init.js";
3
+ import { parseAlarms, parseAttendees, parseCategories, parseOrganizer } from "./_shared.js";
4
+ import { IcsParseError } from "./errors.js";
5
+ export function parseIcsTodos(icsContent) {
6
+ if (!icsContent.trim())
7
+ return [];
8
+ let root;
9
+ try {
10
+ root = ICAL.Component.fromString(icsContent);
11
+ }
12
+ catch (e) {
13
+ throw new IcsParseError("Invalid ICS content", e);
14
+ }
15
+ const out = [];
16
+ for (const vtodo of root.getAllSubcomponents("vtodo")) {
17
+ try {
18
+ const due = vtodo.getFirstPropertyValue("due");
19
+ const completed = vtodo.getFirstPropertyValue("completed");
20
+ const percent = vtodo.getFirstPropertyValue("percent-complete");
21
+ const priority = vtodo.getFirstPropertyValue("priority");
22
+ const status = vtodo.getFirstPropertyValue("status");
23
+ const created = vtodo.getFirstPropertyValue("created");
24
+ const lastModified = vtodo.getFirstPropertyValue("last-modified");
25
+ const rrule = vtodo.getFirstPropertyValue("rrule");
26
+ const recurId = vtodo.getFirstPropertyValue("recurrence-id");
27
+ const rawUid = vtodo.getFirstPropertyValue("uid");
28
+ const rawSummary = vtodo.getFirstPropertyValue("summary");
29
+ const rawDescription = vtodo.getFirstPropertyValue("description");
30
+ out.push({
31
+ uid: typeof rawUid === "string" ? rawUid : "",
32
+ title: typeof rawSummary === "string" ? rawSummary : "",
33
+ due: due instanceof ICAL.Time ? due.toJSDate().toISOString() : null,
34
+ completed: completed instanceof ICAL.Time ? completed.toJSDate().toISOString() : null,
35
+ percent_complete: typeof percent === "number" ? percent : null,
36
+ priority: typeof priority === "number" ? priority : null,
37
+ status: typeof status === "string" ? status.toLowerCase() : null,
38
+ description: typeof rawDescription === "string" ? rawDescription : null,
39
+ categories: parseCategories(vtodo),
40
+ attendees: parseAttendees(vtodo),
41
+ organizer: parseOrganizer(vtodo),
42
+ alarms: parseAlarms(vtodo),
43
+ recurrence_rule: rrule ? rrule.toString() : null,
44
+ created: created instanceof ICAL.Time ? created.toJSDate().toISOString() : null,
45
+ last_modified: lastModified instanceof ICAL.Time ? lastModified.toJSDate().toISOString() : null,
46
+ occurrence_date: recurId instanceof ICAL.Time ? recurId.toJSDate().toISOString() : null,
47
+ });
48
+ }
49
+ catch {
50
+ // Skip malformed VTODO, don't fail whole batch.
51
+ }
52
+ }
53
+ return out;
54
+ }
55
+ //# sourceMappingURL=parse-todos.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"parse-todos.js","sourceRoot":"","sources":["../../src/ics/parse-todos.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export declare function normalizeRecurrenceRule(rule: string): string | null;
2
+ //# sourceMappingURL=rrule.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"rrule.d.ts","sourceRoot":"","sources":["../../src/ics/rrule.ts"],"names":[],"mappings":"AAEA,wBAAgB,uBAAuB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAcnE"}
@@ -0,0 +1,23 @@
1
+ import ICAL from "ical.js";
2
+ export function normalizeRecurrenceRule(rule) {
3
+ if (typeof rule !== "string")
4
+ return null;
5
+ let trimmed = rule.trim();
6
+ if (!trimmed)
7
+ return null;
8
+ if (/^RRULE:/i.test(trimmed))
9
+ trimmed = trimmed.slice(6).trim();
10
+ if (/[\r\n]/.test(trimmed))
11
+ return null;
12
+ try {
13
+ const recur = ICAL.Recur.fromString(trimmed);
14
+ // Ensure it has a FREQ property to be valid
15
+ if (!recur.freq)
16
+ return null;
17
+ }
18
+ catch {
19
+ return null;
20
+ }
21
+ return trimmed;
22
+ }
23
+ //# sourceMappingURL=rrule.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"rrule.js","sourceRoot":"","sources":["../../src/ics/rrule.ts"],"names":[],"mappings":"AAAA,OAAO,IAAI,MAAM,SAAS,CAAC;AAE3B,MAAM,UAAU,uBAAuB,CAAC,IAAY;IAClD,IAAI,OAAO,IAAI,KAAK,QAAQ;QAAE,OAAO,IAAI,CAAC;IAC1C,IAAI,OAAO,GAAG,IAAI,CAAC,IAAI,EAAE,CAAC;IAC1B,IAAI,CAAC,OAAO;QAAE,OAAO,IAAI,CAAC;IAC1B,IAAI,UAAU,CAAC,IAAI,CAAC,OAAO,CAAC;QAAE,OAAO,GAAG,OAAO,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC;IAChE,IAAI,QAAQ,CAAC,IAAI,CAAC,OAAO,CAAC;QAAE,OAAO,IAAI,CAAC;IACxC,IAAI,CAAC;QACH,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,UAAU,CAAC,OAAO,CAAC,CAAC;QAC7C,4CAA4C;QAC5C,IAAI,CAAC,KAAK,CAAC,IAAI;YAAE,OAAO,IAAI,CAAC;IAC/B,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,IAAI,CAAC;IACd,CAAC;IACD,OAAO,OAAO,CAAC;AACjB,CAAC"}
@@ -0,0 +1,100 @@
1
+ export interface ParsedAlarm {
2
+ type: "relative" | "absolute";
3
+ trigger: number | string;
4
+ trigger_human: string;
5
+ }
6
+ export interface ParsedAttendee {
7
+ name: string | null;
8
+ email: string;
9
+ status: string | null;
10
+ role: string | null;
11
+ type: string;
12
+ }
13
+ export interface ParsedOrganizer {
14
+ name: string | null;
15
+ email: string;
16
+ }
17
+ export interface ParsedGeo {
18
+ latitude: number;
19
+ longitude: number;
20
+ }
21
+ export interface ParsedEvent {
22
+ uid: string;
23
+ title: string;
24
+ start: string;
25
+ end: string;
26
+ all_day: boolean;
27
+ location: string | null;
28
+ description: string | null;
29
+ status: string | null;
30
+ availability: string | null;
31
+ url: string | null;
32
+ attendees: ParsedAttendee[];
33
+ categories: string[];
34
+ geo: ParsedGeo | null;
35
+ organizer: ParsedOrganizer | null;
36
+ recurrence_rule: string | null;
37
+ rdates: string[] | null;
38
+ created: string | null;
39
+ last_modified: string | null;
40
+ is_recurring: boolean;
41
+ alarms: ParsedAlarm[];
42
+ occurrence_date: string | null;
43
+ }
44
+ export interface ParsedTodo {
45
+ uid: string;
46
+ title: string;
47
+ due: string | null;
48
+ completed: string | null;
49
+ percent_complete: number | null;
50
+ priority: number | null;
51
+ status: string | null;
52
+ description: string | null;
53
+ categories: string[];
54
+ attendees: ParsedAttendee[];
55
+ organizer: ParsedOrganizer | null;
56
+ alarms: ParsedAlarm[];
57
+ recurrence_rule: string | null;
58
+ created: string | null;
59
+ last_modified: string | null;
60
+ occurrence_date: string | null;
61
+ }
62
+ export interface ParsedJournal {
63
+ uid: string;
64
+ title: string;
65
+ date: string;
66
+ description: string | null;
67
+ categories: string[];
68
+ status: string | null;
69
+ created: string | null;
70
+ last_modified: string | null;
71
+ }
72
+ export interface TimeRange {
73
+ start: string;
74
+ end: string;
75
+ }
76
+ export interface EventCreateProps {
77
+ title: string;
78
+ start: string;
79
+ end: string;
80
+ all_day?: boolean;
81
+ location?: string;
82
+ description?: string;
83
+ attendees?: Array<{
84
+ email: string;
85
+ }>;
86
+ uid?: string;
87
+ timezone?: string;
88
+ alarms?: Array<{
89
+ type: "relative" | "absolute";
90
+ trigger: number | string;
91
+ }>;
92
+ categories?: string[];
93
+ recurrence_rule?: string;
94
+ organizer?: {
95
+ email: string;
96
+ name?: string | null;
97
+ };
98
+ availability?: "busy" | "free";
99
+ }
100
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/ics/types.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ // packages/core/src/ics/types.ts
2
+ export {};
3
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/ics/types.ts"],"names":[],"mappings":"AAAA,iCAAiC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@miguelarios/pim-core",
3
- "version": "0.5.0",
3
+ "version": "0.6.0",
4
4
  "description": "Shared config, validation, errors, and utilities for PIM agent MCP servers",
5
5
  "keywords": [
6
6
  "pim",
@@ -24,6 +24,10 @@
24
24
  ".": {
25
25
  "import": "./dist/index.js",
26
26
  "types": "./dist/index.d.ts"
27
+ },
28
+ "./ics": {
29
+ "import": "./dist/ics/index.js",
30
+ "types": "./dist/ics/index.d.ts"
27
31
  }
28
32
  },
29
33
  "scripts": {
@@ -32,6 +36,8 @@
32
36
  "test": "vitest run"
33
37
  },
34
38
  "dependencies": {
39
+ "@touch4it/ical-timezones": "^1.9.0",
40
+ "ical.js": "^2.2.1",
35
41
  "valibot": "^1.0.0"
36
42
  },
37
43
  "devDependencies": {