@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.
- package/dist/ics/_shared.d.ts +11 -0
- package/dist/ics/_shared.d.ts.map +1 -0
- package/dist/ics/_shared.js +150 -0
- package/dist/ics/_shared.js.map +1 -0
- package/dist/ics/_tz-init.d.ts +2 -0
- package/dist/ics/_tz-init.d.ts.map +1 -0
- package/dist/ics/_tz-init.js +29 -0
- package/dist/ics/_tz-init.js.map +1 -0
- package/dist/ics/components.d.ts +26 -0
- package/dist/ics/components.d.ts.map +1 -0
- package/dist/ics/components.js +178 -0
- package/dist/ics/components.js.map +1 -0
- package/dist/ics/errors.d.ts +7 -0
- package/dist/ics/errors.d.ts.map +1 -0
- package/dist/ics/errors.js +13 -0
- package/dist/ics/errors.js.map +1 -0
- package/dist/ics/generate.d.ts +4 -0
- package/dist/ics/generate.d.ts.map +1 -0
- package/dist/ics/generate.js +101 -0
- package/dist/ics/generate.js.map +1 -0
- package/dist/ics/index.d.ts +11 -0
- package/dist/ics/index.d.ts.map +1 -0
- package/dist/ics/index.js +12 -0
- package/dist/ics/index.js.map +1 -0
- package/dist/ics/parse-events.d.ts +4 -0
- package/dist/ics/parse-events.d.ts.map +1 -0
- package/dist/ics/parse-events.js +223 -0
- package/dist/ics/parse-events.js.map +1 -0
- package/dist/ics/parse-journals.d.ts +4 -0
- package/dist/ics/parse-journals.d.ts.map +1 -0
- package/dist/ics/parse-journals.js +54 -0
- package/dist/ics/parse-journals.js.map +1 -0
- package/dist/ics/parse-todos.d.ts +4 -0
- package/dist/ics/parse-todos.d.ts.map +1 -0
- package/dist/ics/parse-todos.js +55 -0
- package/dist/ics/parse-todos.js.map +1 -0
- package/dist/ics/rrule.d.ts +2 -0
- package/dist/ics/rrule.d.ts.map +1 -0
- package/dist/ics/rrule.js +23 -0
- package/dist/ics/rrule.js.map +1 -0
- package/dist/ics/types.d.ts +100 -0
- package/dist/ics/types.d.ts.map +1 -0
- package/dist/ics/types.js +3 -0
- package/dist/ics/types.js.map +1 -0
- 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 @@
|
|
|
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 @@
|
|
|
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 @@
|
|
|
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 @@
|
|
|
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":"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"}
|
|
@@ -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 @@
|
|
|
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 @@
|
|
|
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 @@
|
|
|
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.
|
|
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": {
|