@ntrr/calendar-kit 0.2.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/CHANGELOG.md ADDED
@@ -0,0 +1,18 @@
1
+ # Changelog
2
+
3
+ ## [0.2.0] — 2026-08-23
4
+
5
+ First **minor** release — stable baseline before Reliant (and other products) consume the kit.
6
+
7
+ - Apple CalDAV: `discoverPrimaryCalendar`, `fetchEvents`, `verifyAppleCalDavConnection`
8
+ - ICS: `parseIcs` (ical.js + Luxon) with Luxon fallback for Apple quirks / numeric offsets
9
+ - CalDAV REPORT: `parseCalDavReport`, primary-calendar pick helpers
10
+ - Public types: `AppleCalDavAuth`, `DiscoveredCalendar`, `ParsedCalendarEvent`, `FloatingZoneOptions`
11
+ - Dist committed for git installs (`github:sm00thindian/ntrr-calendar#v0.2.0`)
12
+
13
+ ## [0.1.0] — 2026-08-23
14
+
15
+ Initial extraction from Hub (development tag; prefer **0.2.0**).
16
+
17
+ [0.2.0]: https://github.com/sm00thindian/ntrr-calendar/releases/tag/v0.2.0
18
+ [0.1.0]: https://github.com/sm00thindian/ntrr-calendar/releases/tag/v0.1.0
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Not The Runaround
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,78 @@
1
+ # `@ntrr/calendar-kit`
2
+
3
+ Portable CalDAV / ICS helpers shared by **Not The Runaround** products (Hub, Reliant, future services).
4
+
5
+ ## What this is
6
+
7
+ | In the kit | Out of the kit (product adapters) |
8
+ |------------|-----------------------------------|
9
+ | Apple CalDAV discover + REPORT | Encrypt / store app passwords |
10
+ | ICS → UTC (`ical.js` + Luxon) | Supabase schemas / RLS |
11
+ | Parsed event shape + provenance fields | Hub households / Focus / Settings UI |
12
+ | Namespace-agnostic CalDAV XML | Reliant dial gate / reminders / voice |
13
+
14
+ Products stay independent: each app vaults its own credentials and maps `ParsedCalendarEvent` into its own store.
15
+
16
+ ## Install
17
+
18
+ ```bash
19
+ npm install @ntrr/calendar-kit
20
+ ```
21
+
22
+ Node 18+ (global `fetch` and `Buffer`). Not Edge-compatible without a polyfill.
23
+
24
+ ## Support
25
+
26
+ **Published as-is, with no support.** This exists because two products needed it;
27
+ it is shared in case it is useful to someone else. There is no issue tracker for
28
+ it, no roadmap, and no commitment to answer questions or accept changes. MIT
29
+ licensed, so fork it freely.
30
+
31
+ If you depend on it, pin an exact version — the API may change to suit the
32
+ products it was built for.
33
+
34
+ ## API (Apple — v0.2)
35
+
36
+ ```ts
37
+ import {
38
+ discoverPrimaryCalendar,
39
+ fetchEvents,
40
+ parseIcs,
41
+ parseCalDavReport,
42
+ type AppleCalDavAuth,
43
+ type ParsedCalendarEvent,
44
+ } from "@ntrr/calendar-kit";
45
+
46
+ const auth: AppleCalDavAuth = { appleId, appPassword };
47
+ const { calendarUrl, calendarName } = await discoverPrimaryCalendar(auth);
48
+
49
+ const events = await fetchEvents(
50
+ auth,
51
+ calendarUrl,
52
+ { start: rangeStart, end: rangeEnd },
53
+ { floatingZone: "America/Chicago" }, // household / profile TZ
54
+ );
55
+
56
+ // Pure parse (tests / fixtures)
57
+ const fromIcs = parseIcs(icsText, { floatingZone: "America/Chicago" });
58
+ const fromReport = parseCalDavReport(xml, { floatingZone: "America/Chicago" });
59
+ ```
60
+
61
+ Runtime: **Node** (`fetch` + `Buffer`). Not Edge-only unless you polyfill.
62
+
63
+ ## Scripts
64
+
65
+ ```bash
66
+ npm install
67
+ npm test # build + TZ=UTC node:test
68
+ npm run build
69
+ ```
70
+
71
+ ## Versioning
72
+
73
+ Semver. ICS / timezone fixes that change parsed instants are **patch** for bugfixes that restore correct civil time, **minor** for new providers (e.g. `google/`), **major** for breaking `ParsedCalendarEvent` shape changes.
74
+
75
+ ## Related
76
+
77
+ - Hub adapter: `ntrr-hub` → `lib/sync/apple/caldav.ts`
78
+ - Platform home: [ntrr.com](https://ntrr.com) (`ntrr-com`)
@@ -0,0 +1,23 @@
1
+ import type { AppleCalDavAuth, DiscoveredCalendar, FetchEventsRange, FloatingZoneOptions, ParsedCalendarEvent } from "../types.js";
2
+ /**
3
+ * True when resourcetype includes a CalDAV calendar collection and is not an
4
+ * inbox/outbox/notification/proxy collection.
5
+ */
6
+ export declare function isCalDavCalendarCollection(block: string): boolean;
7
+ /**
8
+ * Pick the primary event calendar from a calendar-home PROPFIND Depth:1 body.
9
+ * Prefers common default names, otherwise the first real calendar collection.
10
+ */
11
+ export declare function pickPrimaryCalendarFromHomeXml(calendarsXml: string, baseUrl: string): DiscoveredCalendar | null;
12
+ /**
13
+ * Parse a CalDAV calendar-query REPORT body into events, attaching each
14
+ * response's getetag onto every VEVENT from that response's calendar-data.
15
+ */
16
+ export declare function parseCalDavReport(xml: string, options?: FloatingZoneOptions): ParsedCalendarEvent[];
17
+ /** Discover the primary iCloud CalDAV calendar for an Apple ID. */
18
+ export declare function discoverPrimaryCalendar(auth: AppleCalDavAuth): Promise<DiscoveredCalendar>;
19
+ /** Fetch VEVENTs from a CalDAV calendar URL for a time range. */
20
+ export declare function fetchEvents(auth: AppleCalDavAuth, calendarUrl: string, range: FetchEventsRange, options?: FloatingZoneOptions): Promise<ParsedCalendarEvent[]>;
21
+ /** Verify credentials by discovering a primary calendar. */
22
+ export declare function verifyAppleCalDavConnection(auth: AppleCalDavAuth): Promise<DiscoveredCalendar>;
23
+ //# sourceMappingURL=caldav.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"caldav.d.ts","sourceRoot":"","sources":["../../src/apple/caldav.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EACV,eAAe,EACf,kBAAkB,EAClB,gBAAgB,EAChB,mBAAmB,EACnB,mBAAmB,EACpB,MAAM,aAAa,CAAC;AA+CrB;;;GAGG;AACH,wBAAgB,0BAA0B,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAkBjE;AAED;;;GAGG;AACH,wBAAgB,8BAA8B,CAC5C,YAAY,EAAE,MAAM,EACpB,OAAO,EAAE,MAAM,GACd,kBAAkB,GAAG,IAAI,CA+B3B;AA6DD;;;GAGG;AACH,wBAAgB,iBAAiB,CAC/B,GAAG,EAAE,MAAM,EACX,OAAO,CAAC,EAAE,mBAAmB,GAC5B,mBAAmB,EAAE,CA0BvB;AAED,mEAAmE;AACnE,wBAAsB,uBAAuB,CAAC,IAAI,EAAE,eAAe,GAAG,OAAO,CAAC,kBAAkB,CAAC,CAkFhG;AAED,iEAAiE;AACjE,wBAAsB,WAAW,CAC/B,IAAI,EAAE,eAAe,EACrB,WAAW,EAAE,MAAM,EACnB,KAAK,EAAE,gBAAgB,EACvB,OAAO,CAAC,EAAE,mBAAmB,GAC5B,OAAO,CAAC,mBAAmB,EAAE,CAAC,CAmBhC;AAED,4DAA4D;AAC5D,wBAAsB,2BAA2B,CAC/C,IAAI,EAAE,eAAe,GACpB,OAAO,CAAC,kBAAkB,CAAC,CAE7B"}
@@ -0,0 +1,228 @@
1
+ import { parseIcs } from "./ics-parse.js";
2
+ const ICLOUD_ROOT = "https://caldav.icloud.com/";
3
+ function basicAuth(appleId, appPassword) {
4
+ return Buffer.from(`${appleId}:${appPassword}`).toString("base64");
5
+ }
6
+ function extractHref(xml, tag) {
7
+ const pattern = new RegExp(`<(?:[A-Za-z0-9_-]+:)?${tag}[^>]*>\\s*<(?:[A-Za-z0-9_-]+:)?href[^>]*>([^<]+)</(?:[A-Za-z0-9_-]+:)?href>`, "i");
8
+ const match = xml.match(pattern);
9
+ return match?.[1]?.trim() ?? null;
10
+ }
11
+ function extractHrefAfter(xml, marker) {
12
+ const index = xml.toLowerCase().indexOf(marker.toLowerCase());
13
+ if (index === -1) {
14
+ return null;
15
+ }
16
+ const slice = xml.slice(index);
17
+ const hrefMatch = slice.match(/<(?:[A-Za-z0-9_-]+:)?href[^>]*>([^<]+)<\/(?:[A-Za-z0-9_-]+:)?href>/i);
18
+ return hrefMatch?.[1]?.trim() ?? null;
19
+ }
20
+ function splitMultistatusResponses(xml) {
21
+ if (!/<(?:[A-Za-z0-9_-]+:)?response\b/i.test(xml)) {
22
+ return [];
23
+ }
24
+ return xml.split(/<(?:[A-Za-z0-9_-]+:)?response\b/i).slice(1);
25
+ }
26
+ function extractResponseHref(block) {
27
+ const match = block.match(/<(?:[A-Za-z0-9_-]+:)?href[^>]*>([^<]+)<\/(?:[A-Za-z0-9_-]+:)?href>/i);
28
+ return match?.[1]?.trim() ?? null;
29
+ }
30
+ function extractDisplayName(block) {
31
+ const match = block.match(/<(?:[A-Za-z0-9_-]+:)?displayname[^>]*>([^<]*)<\/(?:[A-Za-z0-9_-]+:)?displayname>/i);
32
+ const name = match?.[1]?.trim();
33
+ return name || null;
34
+ }
35
+ /**
36
+ * True when resourcetype includes a CalDAV calendar collection and is not an
37
+ * inbox/outbox/notification/proxy collection.
38
+ */
39
+ export function isCalDavCalendarCollection(block) {
40
+ const typeMatch = block.match(/<(?:[A-Za-z0-9_-]+:)?resourcetype[^>]*>([\s\S]*?)<\/(?:[A-Za-z0-9_-]+:)?resourcetype>/i);
41
+ const types = typeMatch?.[1] ?? "";
42
+ if (!/<(?:[A-Za-z0-9_-]+:)?calendar(?:\s|\/|>)/i.test(types)) {
43
+ return false;
44
+ }
45
+ if (/<(?:[A-Za-z0-9_-]+:)?schedule-inbox(?:\s|\/|>)/i.test(types) ||
46
+ /<(?:[A-Za-z0-9_-]+:)?schedule-outbox(?:\s|\/|>)/i.test(types) ||
47
+ /<(?:[A-Za-z0-9_-]+:)?notification(?:\s|\/|>)/i.test(types) ||
48
+ /<(?:[A-Za-z0-9_-]+:)?dropbox(?:\s|\/|>)/i.test(types) ||
49
+ /<(?:[A-Za-z0-9_-]+:)?shared-owner(?:\s|\/|>)/i.test(types)) {
50
+ return false;
51
+ }
52
+ return true;
53
+ }
54
+ /**
55
+ * Pick the primary event calendar from a calendar-home PROPFIND Depth:1 body.
56
+ * Prefers common default names, otherwise the first real calendar collection.
57
+ */
58
+ export function pickPrimaryCalendarFromHomeXml(calendarsXml, baseUrl) {
59
+ const candidates = [];
60
+ for (const block of splitMultistatusResponses(calendarsXml)) {
61
+ if (!isCalDavCalendarCollection(block)) {
62
+ continue;
63
+ }
64
+ const href = extractResponseHref(block);
65
+ if (!href) {
66
+ continue;
67
+ }
68
+ const absolute = new URL(href, baseUrl);
69
+ const base = new URL(baseUrl);
70
+ if (absolute.pathname.replace(/\/$/, "") === base.pathname.replace(/\/$/, "")) {
71
+ continue;
72
+ }
73
+ candidates.push({
74
+ calendarUrl: absolute.toString(),
75
+ calendarName: extractDisplayName(block) || "iCloud Calendar",
76
+ });
77
+ }
78
+ if (!candidates.length) {
79
+ return null;
80
+ }
81
+ const preferred = candidates.find((entry) => /^(home|calendar|icloud|personal)$/i.test(entry.calendarName.trim()));
82
+ return preferred ?? candidates[0];
83
+ }
84
+ async function caldavRequest(url, method, auth, body, depth = "0") {
85
+ const response = await fetch(url, {
86
+ method,
87
+ headers: {
88
+ Authorization: `Basic ${auth}`,
89
+ Depth: depth,
90
+ "Content-Type": "application/xml; charset=utf-8",
91
+ },
92
+ body,
93
+ redirect: "follow",
94
+ });
95
+ if (!response.ok) {
96
+ const text = await response.text();
97
+ throw new Error(`CalDAV ${method} failed (${response.status}): ${text.slice(0, 200)}`);
98
+ }
99
+ return { xml: await response.text(), finalUrl: response.url || url };
100
+ }
101
+ function formatCalDavUtc(date) {
102
+ return date.toISOString().replace(/[-:]/g, "").replace(/\.\d{3}Z$/, "Z");
103
+ }
104
+ function decodeXmlText(value) {
105
+ return value
106
+ .replace(/&lt;/g, "<")
107
+ .replace(/&gt;/g, ">")
108
+ .replace(/&quot;/g, '"')
109
+ .replace(/&apos;/g, "'")
110
+ .replace(/&amp;/g, "&")
111
+ .trim();
112
+ }
113
+ function extractGetEtag(block) {
114
+ const match = block.match(/<(?:[A-Za-z]+:)?getetag[^>]*>([\s\S]*?)<\/(?:[A-Za-z]+:)?getetag>/i);
115
+ if (!match?.[1]) {
116
+ return undefined;
117
+ }
118
+ const etag = decodeXmlText(match[1]).replace(/^W\//i, "").replace(/^"|"$/g, "").trim();
119
+ return etag || undefined;
120
+ }
121
+ function extractCalendarData(block) {
122
+ const match = block.match(/<(?:[A-Za-z]+:)?calendar-data[^>]*>([\s\S]*?)<\/(?:[A-Za-z]+:)?calendar-data>/i);
123
+ if (!match?.[1]) {
124
+ return null;
125
+ }
126
+ return decodeXmlText(match[1]);
127
+ }
128
+ /**
129
+ * Parse a CalDAV calendar-query REPORT body into events, attaching each
130
+ * response's getetag onto every VEVENT from that response's calendar-data.
131
+ */
132
+ export function parseCalDavReport(xml, options) {
133
+ const events = [];
134
+ const responseBlocks = xml.includes("<") && /<(?:[A-Za-z]+:)?response\b/i.test(xml)
135
+ ? xml.split(/<(?:[A-Za-z]+:)?response\b/i).slice(1)
136
+ : [xml];
137
+ for (const block of responseBlocks) {
138
+ const ics = extractCalendarData(block);
139
+ if (!ics) {
140
+ continue;
141
+ }
142
+ const etag = extractGetEtag(block);
143
+ const normalized = ics.replace(/\r\n/g, "\n").replace(/\r/g, "\n");
144
+ try {
145
+ const parsed = parseIcs(normalized, options);
146
+ for (const event of parsed) {
147
+ events.push(etag ? { ...event, etag } : event);
148
+ }
149
+ }
150
+ catch {
151
+ // One bad calendar-data object must not fail the whole pull.
152
+ continue;
153
+ }
154
+ }
155
+ return events;
156
+ }
157
+ /** Discover the primary iCloud CalDAV calendar for an Apple ID. */
158
+ export async function discoverPrimaryCalendar(auth) {
159
+ const token = basicAuth(auth.appleId, auth.appPassword);
160
+ let rootUrl = ICLOUD_ROOT;
161
+ try {
162
+ const wellKnown = await caldavRequest("https://caldav.icloud.com/.well-known/caldav", "PROPFIND", token, `<?xml version="1.0" encoding="UTF-8"?>
163
+ <D:propfind xmlns:D="DAV:">
164
+ <D:prop><D:current-user-principal /></D:prop>
165
+ </D:propfind>`, "0");
166
+ rootUrl = wellKnown.finalUrl;
167
+ }
168
+ catch {
169
+ // Older accounts / edge responses still work from ICLOUD_ROOT
170
+ }
171
+ const principalProbe = await caldavRequest(rootUrl, "PROPFIND", token, `<?xml version="1.0" encoding="UTF-8"?>
172
+ <D:propfind xmlns:D="DAV:">
173
+ <D:prop><D:current-user-principal /></D:prop>
174
+ </D:propfind>`, "0");
175
+ const principalHref = extractHref(principalProbe.xml, "current-user-principal") ??
176
+ extractHrefAfter(principalProbe.xml, "current-user-principal");
177
+ if (!principalHref) {
178
+ throw new Error("Could not discover iCloud CalDAV principal.");
179
+ }
180
+ const principalUrl = new URL(principalHref, principalProbe.finalUrl || rootUrl).toString();
181
+ const homeProbe = await caldavRequest(principalUrl, "PROPFIND", token, `<?xml version="1.0" encoding="UTF-8"?>
182
+ <D:propfind xmlns:D="DAV:" xmlns:CS="http://calendarserver.org/ns/" xmlns:C="urn:ietf:params:xml:ns:caldav">
183
+ <D:prop><C:calendar-home-set /></D:prop>
184
+ </D:propfind>`, "0");
185
+ const homeHref = extractHrefAfter(homeProbe.xml, "calendar-home-set");
186
+ if (!homeHref) {
187
+ throw new Error("Could not discover iCloud calendar home.");
188
+ }
189
+ const homeUrl = new URL(homeHref, homeProbe.finalUrl || principalUrl).toString();
190
+ const calendarsProbe = await caldavRequest(homeUrl, "PROPFIND", token, `<?xml version="1.0" encoding="UTF-8"?>
191
+ <D:propfind xmlns:D="DAV:" xmlns:C="urn:ietf:params:xml:ns:caldav" xmlns:CS="http://calendarserver.org/ns/">
192
+ <D:prop>
193
+ <D:displayname />
194
+ <C:calendar-description />
195
+ <D:resourcetype />
196
+ </D:prop>
197
+ </D:propfind>`, "1");
198
+ const picked = pickPrimaryCalendarFromHomeXml(calendarsProbe.xml, calendarsProbe.finalUrl || homeUrl);
199
+ if (picked) {
200
+ return picked;
201
+ }
202
+ throw new Error("No CalDAV calendar collection found on this iCloud account. Open the Calendar app once, confirm iCloud Calendar is on, add an event, then try again.");
203
+ }
204
+ /** Fetch VEVENTs from a CalDAV calendar URL for a time range. */
205
+ export async function fetchEvents(auth, calendarUrl, range, options) {
206
+ const token = basicAuth(auth.appleId, auth.appPassword);
207
+ const body = `<?xml version="1.0" encoding="utf-8" ?>
208
+ <C:calendar-query xmlns:D="DAV:" xmlns:C="urn:ietf:params:xml:ns:caldav">
209
+ <D:prop>
210
+ <D:getetag />
211
+ <C:calendar-data />
212
+ </D:prop>
213
+ <C:filter>
214
+ <C:comp-filter name="VCALENDAR">
215
+ <C:comp-filter name="VEVENT">
216
+ <C:time-range start="${formatCalDavUtc(range.start)}" end="${formatCalDavUtc(range.end)}" />
217
+ </C:comp-filter>
218
+ </C:comp-filter>
219
+ </C:filter>
220
+ </C:calendar-query>`;
221
+ const { xml } = await caldavRequest(calendarUrl, "REPORT", token, body, "1");
222
+ return parseCalDavReport(xml, options);
223
+ }
224
+ /** Verify credentials by discovering a primary calendar. */
225
+ export async function verifyAppleCalDavConnection(auth) {
226
+ return discoverPrimaryCalendar(auth);
227
+ }
228
+ //# sourceMappingURL=caldav.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"caldav.js","sourceRoot":"","sources":["../../src/apple/caldav.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,33 @@
1
+ import ICAL from "ical.js";
2
+ import type { FloatingZoneOptions, ParsedCalendarEvent } from "../types.js";
3
+ /**
4
+ * Convert an ICAL.Time to UTC ISO using Luxon for IANA zones.
5
+ * Never use ICAL.Time#toJSDate() for TZID events — without a registered
6
+ * VTIMEZONE, ical.js treats them as floating and toJSDate() uses process TZ
7
+ * (UTC on Vercel ⇒ noon Chicago becomes 12:00Z).
8
+ */
9
+ export declare function icalTimeToUtcIso(time: ICAL.Time, tzid: string | null | undefined, floatingZone: string): {
10
+ iso: string;
11
+ allDay: boolean;
12
+ zoneUsed: string;
13
+ civil: string;
14
+ } | null;
15
+ /** Luxon conversion for raw ICS date-time tokens (fallback path). */
16
+ export declare function luxonFromIcsToken(value: string, tzid: string | null | undefined, floatingZone: string): {
17
+ iso: string;
18
+ allDay: boolean;
19
+ zoneUsed: string;
20
+ civil: string;
21
+ } | null;
22
+ /**
23
+ * Resilient Luxon-only extractor when ical.js throws (Apple CalDAV quirks /
24
+ * designSet.propertyGroups crashes on some fragments).
25
+ */
26
+ export declare function parseIcsLuxonFallback(ics: string, options?: FloatingZoneOptions): ParsedCalendarEvent[];
27
+ /**
28
+ * Parse ICS text into normalized calendar events.
29
+ * Prefers ical.js structure + Luxon zones; falls back to Luxon-only extraction
30
+ * when ical.js throws (e.g. designSet.propertyGroups on some Apple fragments).
31
+ */
32
+ export declare function parseIcs(ics: string, options?: FloatingZoneOptions): ParsedCalendarEvent[];
33
+ //# sourceMappingURL=ics-parse.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ics-parse.d.ts","sourceRoot":"","sources":["../../src/apple/ics-parse.ts"],"names":[],"mappings":"AAAA,OAAO,IAAI,MAAM,SAAS,CAAC;AAG3B,OAAO,KAAK,EAAE,mBAAmB,EAAE,mBAAmB,EAAE,MAAM,aAAa,CAAC;AAsD5E;;;;;GAKG;AACH,wBAAgB,gBAAgB,CAC9B,IAAI,EAAE,IAAI,CAAC,IAAI,EACf,IAAI,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,EAC/B,YAAY,EAAE,MAAM,GACnB;IAAE,GAAG,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,OAAO,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,GAAG,IAAI,CA2C1E;AAED,qEAAqE;AACrE,wBAAgB,iBAAiB,CAC/B,KAAK,EAAE,MAAM,EACb,IAAI,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,EAC/B,YAAY,EAAE,MAAM,GACnB;IAAE,GAAG,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,OAAO,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,GAAG,IAAI,CA8D1E;AAgBD;;;GAGG;AACH,wBAAgB,qBAAqB,CACnC,GAAG,EAAE,MAAM,EACX,OAAO,CAAC,EAAE,mBAAmB,GAC5B,mBAAmB,EAAE,CAmDvB;AAgID;;;;GAIG;AACH,wBAAgB,QAAQ,CAAC,GAAG,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,mBAAmB,GAAG,mBAAmB,EAAE,CAa1F"}
@@ -0,0 +1,308 @@
1
+ import ICAL from "ical.js";
2
+ import { DateTime } from "luxon";
3
+ function wrapCalendar(ics) {
4
+ const trimmed = ics.trim();
5
+ if (/BEGIN:VCALENDAR/i.test(trimmed)) {
6
+ return trimmed;
7
+ }
8
+ return `BEGIN:VCALENDAR\r\nVERSION:2.0\r\n${trimmed}\r\nEND:VCALENDAR`;
9
+ }
10
+ function unfoldIcs(ics) {
11
+ return ics.replace(/\r\n[ \t]/g, "").replace(/\n[ \t]/g, "").replace(/\r\n/g, "\n").replace(/\r/g, "\n");
12
+ }
13
+ function pad2(n) {
14
+ return String(n).padStart(2, "0");
15
+ }
16
+ function civilFromParts(year, month, day, hour, minute, second, allDay) {
17
+ if (allDay) {
18
+ return `${year}-${pad2(month)}-${pad2(day)}`;
19
+ }
20
+ return `${year}-${pad2(month)}-${pad2(day)}T${pad2(hour ?? 0)}:${pad2(minute ?? 0)}:${pad2(second ?? 0)}`;
21
+ }
22
+ function civilString(time) {
23
+ if (time.isDate) {
24
+ return civilFromParts(time.year, time.month, time.day, 0, 0, 0, true);
25
+ }
26
+ return civilFromParts(time.year, time.month, time.day, time.hour, time.minute, time.second);
27
+ }
28
+ function rawProperty(prop) {
29
+ if (!prop) {
30
+ return undefined;
31
+ }
32
+ const tzid = prop.getParameter("tzid");
33
+ const value = prop.getFirstValue();
34
+ const body = value.isDate
35
+ ? `${value.year}${pad2(value.month)}${pad2(value.day)}`
36
+ : `${value.year}${pad2(value.month)}${pad2(value.day)}T${pad2(value.hour)}${pad2(value.minute)}${pad2(value.second)}${value.zone?.tzid === "UTC" ? "Z" : ""}`;
37
+ return tzid ? `TZID=${tzid}:${body}` : body;
38
+ }
39
+ /**
40
+ * Convert an ICAL.Time to UTC ISO using Luxon for IANA zones.
41
+ * Never use ICAL.Time#toJSDate() for TZID events — without a registered
42
+ * VTIMEZONE, ical.js treats them as floating and toJSDate() uses process TZ
43
+ * (UTC on Vercel ⇒ noon Chicago becomes 12:00Z).
44
+ */
45
+ export function icalTimeToUtcIso(time, tzid, floatingZone) {
46
+ const civil = civilString(time);
47
+ if (time.isDate) {
48
+ const iso = DateTime.utc(time.year, time.month, time.day, 0, 0, 0).toISO();
49
+ return iso ? { iso, allDay: true, zoneUsed: "UTC", civil } : null;
50
+ }
51
+ if (time.zone?.tzid === "UTC") {
52
+ const iso = DateTime.utc(time.year, time.month, time.day, time.hour, time.minute, time.second).toISO();
53
+ return iso ? { iso, allDay: false, zoneUsed: "UTC", civil } : null;
54
+ }
55
+ const zone = (typeof tzid === "string" && tzid.trim()) ||
56
+ (time.zone?.tzid && time.zone.tzid !== "floating" ? time.zone.tzid : null) ||
57
+ floatingZone;
58
+ const local = DateTime.fromObject({
59
+ year: time.year,
60
+ month: time.month,
61
+ day: time.day,
62
+ hour: time.hour,
63
+ minute: time.minute,
64
+ second: time.second,
65
+ }, { zone });
66
+ if (!local.isValid) {
67
+ return null;
68
+ }
69
+ const iso = local.toUTC().toISO();
70
+ return iso ? { iso, allDay: false, zoneUsed: zone, civil } : null;
71
+ }
72
+ /** Luxon conversion for raw ICS date-time tokens (fallback path). */
73
+ export function luxonFromIcsToken(value, tzid, floatingZone) {
74
+ const cleaned = value.trim();
75
+ if (/^\d{8}$/.test(cleaned)) {
76
+ const year = Number(cleaned.slice(0, 4));
77
+ const month = Number(cleaned.slice(4, 6));
78
+ const day = Number(cleaned.slice(6, 8));
79
+ const iso = DateTime.utc(year, month, day, 0, 0, 0).toISO();
80
+ return iso
81
+ ? { iso, allDay: true, zoneUsed: "UTC", civil: civilFromParts(year, month, day, 0, 0, 0, true) }
82
+ : null;
83
+ }
84
+ const offsetMatch = cleaned.match(/^(\d{4})(\d{2})(\d{2})T(\d{2})(\d{2})(\d{2})([+-])(\d{2}):?(\d{2})$/);
85
+ if (offsetMatch) {
86
+ const isoLocal = `${offsetMatch[1]}-${offsetMatch[2]}-${offsetMatch[3]}T${offsetMatch[4]}:${offsetMatch[5]}:${offsetMatch[6]}`;
87
+ const dt = DateTime.fromISO(`${isoLocal}${offsetMatch[7]}${offsetMatch[8]}:${offsetMatch[9]}`);
88
+ if (!dt.isValid) {
89
+ return null;
90
+ }
91
+ const iso = dt.toUTC().toISO();
92
+ return iso
93
+ ? {
94
+ iso,
95
+ allDay: false,
96
+ zoneUsed: "UTC",
97
+ civil: `${isoLocal}`,
98
+ }
99
+ : null;
100
+ }
101
+ const match = cleaned.match(/^(\d{4})(\d{2})(\d{2})T(\d{2})(\d{2})(\d{2})(Z)?$/i);
102
+ if (!match) {
103
+ return null;
104
+ }
105
+ const year = Number(match[1]);
106
+ const month = Number(match[2]);
107
+ const day = Number(match[3]);
108
+ const hour = Number(match[4]);
109
+ const minute = Number(match[5]);
110
+ const second = Number(match[6]);
111
+ const isUtc = Boolean(match[7]);
112
+ const civil = civilFromParts(year, month, day, hour, minute, second);
113
+ if (isUtc) {
114
+ const iso = DateTime.utc(year, month, day, hour, minute, second).toISO();
115
+ return iso ? { iso, allDay: false, zoneUsed: "UTC", civil } : null;
116
+ }
117
+ const zone = (tzid?.replace(/^"|"$/g, "").trim() || floatingZone).trim();
118
+ const local = DateTime.fromObject({ year, month, day, hour, minute, second }, { zone });
119
+ if (!local.isValid) {
120
+ return null;
121
+ }
122
+ const iso = local.toUTC().toISO();
123
+ return iso ? { iso, allDay: false, zoneUsed: zone, civil } : null;
124
+ }
125
+ function fieldLine(block, name) {
126
+ const re = new RegExp(`^${name}([^:\\n]*):(.+)$`, "im");
127
+ const match = block.match(re);
128
+ if (!match) {
129
+ return null;
130
+ }
131
+ return { params: match[1] ?? "", value: (match[2] ?? "").trim() };
132
+ }
133
+ function tzidFromParams(params) {
134
+ const match = params.match(/TZID=([^;]+)/i);
135
+ return match?.[1]?.replace(/^"|"$/g, "").trim() || null;
136
+ }
137
+ /**
138
+ * Resilient Luxon-only extractor when ical.js throws (Apple CalDAV quirks /
139
+ * designSet.propertyGroups crashes on some fragments).
140
+ */
141
+ export function parseIcsLuxonFallback(ics, options) {
142
+ const floatingZone = options?.floatingZone?.trim() || "UTC";
143
+ const text = unfoldIcs(ics);
144
+ const wr = text.match(/^X-WR-TIMEZONE:(.+)$/im)?.[1]?.trim();
145
+ const defaultFloating = wr && DateTime.now().setZone(wr).isValid ? wr : floatingZone;
146
+ const events = [];
147
+ const blocks = text.split(/BEGIN:VEVENT/i).slice(1);
148
+ for (const blockRaw of blocks) {
149
+ const block = blockRaw.split(/END:VEVENT/i)[0] ?? "";
150
+ const uid = fieldLine(block, "UID")?.value;
151
+ const summary = fieldLine(block, "SUMMARY")?.value;
152
+ const dtstart = fieldLine(block, "DTSTART");
153
+ const dtend = fieldLine(block, "DTEND") ?? dtstart;
154
+ if (!uid || !summary || !dtstart || !dtend) {
155
+ continue;
156
+ }
157
+ const startTzid = tzidFromParams(dtstart.params);
158
+ const endTzid = tzidFromParams(dtend.params) ?? startTzid;
159
+ const sharedTzid = startTzid || endTzid;
160
+ const start = luxonFromIcsToken(dtstart.value, startTzid || sharedTzid, defaultFloating);
161
+ const end = luxonFromIcsToken(dtend.value, endTzid || sharedTzid, defaultFloating);
162
+ if (!start || !end) {
163
+ continue;
164
+ }
165
+ const description = fieldLine(block, "DESCRIPTION")?.value;
166
+ const location = fieldLine(block, "LOCATION")?.value;
167
+ events.push({
168
+ uid,
169
+ title: summary,
170
+ description,
171
+ location,
172
+ startsAt: start.iso,
173
+ endsAt: end.iso,
174
+ allDay: start.allDay,
175
+ startsTzid: start.zoneUsed !== "UTC" ? start.zoneUsed : sharedTzid || undefined,
176
+ endsTzid: end.zoneUsed !== "UTC" ? end.zoneUsed : sharedTzid || undefined,
177
+ startsCivil: start.civil,
178
+ endsCivil: end.civil,
179
+ rawDtStart: startTzid ? `TZID=${startTzid}:${dtstart.value}` : dtstart.value,
180
+ rawDtEnd: endTzid ? `TZID=${endTzid}:${dtend.value}` : dtend.value,
181
+ });
182
+ }
183
+ return events;
184
+ }
185
+ /** ical.js drops ±HHMM offsets during parse — detect them in raw ICS. */
186
+ function icsHasNumericUtcOffsets(ics) {
187
+ return /^DT(?:START|END)[^:\n]*:\d{8}T\d{6}[+-]\d{2}/im.test(unfoldIcs(ics));
188
+ }
189
+ function parseWithIcalJs(ics, floatingZone) {
190
+ const text = wrapCalendar(unfoldIcs(ics));
191
+ const root = new ICAL.Component(ICAL.parse(text));
192
+ for (const tzComp of root.getAllSubcomponents("vtimezone")) {
193
+ try {
194
+ const timezone = new ICAL.Timezone({ component: tzComp });
195
+ if (timezone.tzid) {
196
+ ICAL.TimezoneService.register(timezone);
197
+ }
198
+ }
199
+ catch {
200
+ // Luxon handles IANA TZIDs; ignore bad VTIMEZONE blocks.
201
+ }
202
+ }
203
+ const calZoneProp = root.getFirstProperty("x-wr-timezone");
204
+ const calendarZone = typeof calZoneProp?.getFirstValue() === "string"
205
+ ? String(calZoneProp.getFirstValue()).trim()
206
+ : "";
207
+ const defaultFloating = calendarZone && DateTime.now().setZone(calendarZone).isValid
208
+ ? calendarZone
209
+ : floatingZone;
210
+ const events = [];
211
+ for (const vevent of root.getAllSubcomponents("vevent")) {
212
+ const summaryProp = vevent.getFirstProperty("summary");
213
+ const uidProp = vevent.getFirstProperty("uid");
214
+ const dtstartProp = vevent.getFirstProperty("dtstart");
215
+ const dtendProp = vevent.getFirstProperty("dtend") ?? dtstartProp;
216
+ if (!summaryProp || !uidProp || !dtstartProp || !dtendProp) {
217
+ continue;
218
+ }
219
+ const startTime = dtstartProp.getFirstValue();
220
+ const endTime = dtendProp.getFirstValue();
221
+ const startTzid = dtstartProp.getParameter("tzid");
222
+ const endTzid = dtendProp.getParameter("tzid") ?? startTzid;
223
+ const sharedTzid = startTzid || endTzid;
224
+ let start = icalTimeToUtcIso(startTime, startTzid || sharedTzid, defaultFloating);
225
+ let end = icalTimeToUtcIso(endTime, endTzid || sharedTzid, defaultFloating);
226
+ if (!start || !end) {
227
+ continue;
228
+ }
229
+ const startIsUtc = !startTzid && startTime.zone?.tzid === "UTC";
230
+ const endIsUtc = !endTzid && endTime.zone?.tzid === "UTC";
231
+ const durationMs = Date.parse(end.iso) - Date.parse(start.iso);
232
+ if (!start.allDay &&
233
+ startIsUtc !== endIsUtc &&
234
+ sharedTzid &&
235
+ Number.isFinite(durationMs) &&
236
+ (durationMs < 0 || durationMs > 2 * 60 * 60 * 1000)) {
237
+ if (startIsUtc && !endIsUtc) {
238
+ const repaired = DateTime.fromObject({
239
+ year: startTime.year,
240
+ month: startTime.month,
241
+ day: startTime.day,
242
+ hour: startTime.hour,
243
+ minute: startTime.minute,
244
+ second: startTime.second,
245
+ }, { zone: sharedTzid });
246
+ if (repaired.isValid) {
247
+ const iso = repaired.toUTC().toISO();
248
+ if (iso) {
249
+ start = { iso, allDay: false, zoneUsed: sharedTzid, civil: civilString(startTime) };
250
+ }
251
+ }
252
+ }
253
+ else if (endIsUtc && !startIsUtc) {
254
+ const repaired = DateTime.fromObject({
255
+ year: endTime.year,
256
+ month: endTime.month,
257
+ day: endTime.day,
258
+ hour: endTime.hour,
259
+ minute: endTime.minute,
260
+ second: endTime.second,
261
+ }, { zone: sharedTzid });
262
+ if (repaired.isValid) {
263
+ const iso = repaired.toUTC().toISO();
264
+ if (iso) {
265
+ end = { iso, allDay: false, zoneUsed: sharedTzid, civil: civilString(endTime) };
266
+ }
267
+ }
268
+ }
269
+ }
270
+ const description = vevent.getFirstPropertyValue("description");
271
+ const location = vevent.getFirstPropertyValue("location");
272
+ events.push({
273
+ uid: String(uidProp.getFirstValue()),
274
+ title: String(summaryProp.getFirstValue()),
275
+ description: description != null ? String(description) : undefined,
276
+ location: location != null ? String(location) : undefined,
277
+ startsAt: start.iso,
278
+ endsAt: end.iso,
279
+ allDay: start.allDay,
280
+ startsTzid: start.zoneUsed !== "UTC" ? start.zoneUsed : sharedTzid || undefined,
281
+ endsTzid: end.zoneUsed !== "UTC" ? end.zoneUsed : sharedTzid || undefined,
282
+ startsCivil: start.civil,
283
+ endsCivil: end.civil,
284
+ rawDtStart: rawProperty(dtstartProp),
285
+ rawDtEnd: rawProperty(dtendProp),
286
+ });
287
+ }
288
+ return events;
289
+ }
290
+ /**
291
+ * Parse ICS text into normalized calendar events.
292
+ * Prefers ical.js structure + Luxon zones; falls back to Luxon-only extraction
293
+ * when ical.js throws (e.g. designSet.propertyGroups on some Apple fragments).
294
+ */
295
+ export function parseIcs(ics, options) {
296
+ const floatingZone = options?.floatingZone?.trim() || "UTC";
297
+ // ical.js strips numeric offsets (e.g. 20260824T120000-0500 → floating noon).
298
+ if (icsHasNumericUtcOffsets(ics)) {
299
+ return parseIcsLuxonFallback(ics, { floatingZone });
300
+ }
301
+ try {
302
+ return parseWithIcalJs(ics, floatingZone);
303
+ }
304
+ catch {
305
+ return parseIcsLuxonFallback(ics, { floatingZone });
306
+ }
307
+ }
308
+ //# sourceMappingURL=ics-parse.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ics-parse.js","sourceRoot":"","sources":["../../src/apple/ics-parse.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ export { discoverPrimaryCalendar, fetchEvents, isCalDavCalendarCollection, parseCalDavReport, pickPrimaryCalendarFromHomeXml, verifyAppleCalDavConnection, } from "./caldav.js";
2
+ export { icalTimeToUtcIso, luxonFromIcsToken, parseIcs, parseIcsLuxonFallback, } from "./ics-parse.js";
3
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/apple/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,uBAAuB,EACvB,WAAW,EACX,0BAA0B,EAC1B,iBAAiB,EACjB,8BAA8B,EAC9B,2BAA2B,GAC5B,MAAM,aAAa,CAAC;AAErB,OAAO,EACL,gBAAgB,EAChB,iBAAiB,EACjB,QAAQ,EACR,qBAAqB,GACtB,MAAM,gBAAgB,CAAC"}
@@ -0,0 +1,3 @@
1
+ export { discoverPrimaryCalendar, fetchEvents, isCalDavCalendarCollection, parseCalDavReport, pickPrimaryCalendarFromHomeXml, verifyAppleCalDavConnection, } from "./caldav.js";
2
+ export { icalTimeToUtcIso, luxonFromIcsToken, parseIcs, parseIcsLuxonFallback, } from "./ics-parse.js";
3
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/apple/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,uBAAuB,EACvB,WAAW,EACX,0BAA0B,EAC1B,iBAAiB,EACjB,8BAA8B,EAC9B,2BAA2B,GAC5B,MAAM,aAAa,CAAC;AAErB,OAAO,EACL,gBAAgB,EAChB,iBAAiB,EACjB,QAAQ,EACR,qBAAqB,GACtB,MAAM,gBAAgB,CAAC"}
@@ -0,0 +1,9 @@
1
+ /**
2
+ * @ntrr/calendar-kit
3
+ *
4
+ * Shared CalDAV/ICS helpers for NTRR products.
5
+ * No React, no Supabase, no product DB schemas — adapters live in each app.
6
+ */
7
+ export type { AppleCalDavAuth, DiscoveredCalendar, FetchEventsRange, FloatingZoneOptions, ParsedCalendarEvent, } from "./types.js";
8
+ export { discoverPrimaryCalendar, fetchEvents, icalTimeToUtcIso, isCalDavCalendarCollection, luxonFromIcsToken, parseCalDavReport, parseIcs, parseIcsLuxonFallback, pickPrimaryCalendarFromHomeXml, verifyAppleCalDavConnection, } from "./apple/index.js";
9
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,YAAY,EACV,eAAe,EACf,kBAAkB,EAClB,gBAAgB,EAChB,mBAAmB,EACnB,mBAAmB,GACpB,MAAM,YAAY,CAAC;AAEpB,OAAO,EACL,uBAAuB,EACvB,WAAW,EACX,gBAAgB,EAChB,0BAA0B,EAC1B,iBAAiB,EACjB,iBAAiB,EACjB,QAAQ,EACR,qBAAqB,EACrB,8BAA8B,EAC9B,2BAA2B,GAC5B,MAAM,kBAAkB,CAAC"}
package/dist/index.js ADDED
@@ -0,0 +1,8 @@
1
+ /**
2
+ * @ntrr/calendar-kit
3
+ *
4
+ * Shared CalDAV/ICS helpers for NTRR products.
5
+ * No React, no Supabase, no product DB schemas — adapters live in each app.
6
+ */
7
+ export { discoverPrimaryCalendar, fetchEvents, icalTimeToUtcIso, isCalDavCalendarCollection, luxonFromIcsToken, parseCalDavReport, parseIcs, parseIcsLuxonFallback, pickPrimaryCalendarFromHomeXml, verifyAppleCalDavConnection, } from "./apple/index.js";
8
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAUH,OAAO,EACL,uBAAuB,EACvB,WAAW,EACX,gBAAgB,EAChB,0BAA0B,EAC1B,iBAAiB,EACjB,iBAAiB,EACjB,QAAQ,EACR,qBAAqB,EACrB,8BAA8B,EAC9B,2BAA2B,GAC5B,MAAM,kBAAkB,CAAC"}
@@ -0,0 +1,41 @@
1
+ /** Apple CalDAV Basic-auth credentials (app-specific password). */
2
+ export type AppleCalDavAuth = {
3
+ appleId: string;
4
+ appPassword: string;
5
+ };
6
+ export type DiscoveredCalendar = {
7
+ calendarUrl: string;
8
+ calendarName: string;
9
+ };
10
+ /**
11
+ * Normalized calendar event after ICS/CalDAV parse.
12
+ * Times are UTC ISO strings; civil + TZID preserve Apple provenance.
13
+ */
14
+ export type ParsedCalendarEvent = {
15
+ uid: string;
16
+ title: string;
17
+ description?: string;
18
+ location?: string;
19
+ startsAt: string;
20
+ endsAt: string;
21
+ allDay: boolean;
22
+ etag?: string;
23
+ startsTzid?: string;
24
+ endsTzid?: string;
25
+ startsCivil?: string;
26
+ endsCivil?: string;
27
+ rawDtStart?: string;
28
+ rawDtEnd?: string;
29
+ };
30
+ export type FloatingZoneOptions = {
31
+ /**
32
+ * IANA zone for floating (no TZID / no Z) times when X-WR-TIMEZONE is absent.
33
+ * Product adapters pass household/profile timezone (e.g. America/Chicago).
34
+ */
35
+ floatingZone?: string;
36
+ };
37
+ export type FetchEventsRange = {
38
+ start: Date;
39
+ end: Date;
40
+ };
41
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA,mEAAmE;AACnE,MAAM,MAAM,eAAe,GAAG;IAC5B,OAAO,EAAE,MAAM,CAAC;IAChB,WAAW,EAAE,MAAM,CAAC;CACrB,CAAC;AAEF,MAAM,MAAM,kBAAkB,GAAG;IAC/B,WAAW,EAAE,MAAM,CAAC;IACpB,YAAY,EAAE,MAAM,CAAC;CACtB,CAAC;AAEF;;;GAGG;AACH,MAAM,MAAM,mBAAmB,GAAG;IAChC,GAAG,EAAE,MAAM,CAAC;IACZ,KAAK,EAAE,MAAM,CAAC;IACd,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,QAAQ,EAAE,MAAM,CAAC;IACjB,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,OAAO,CAAC;IAChB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB,CAAC;AAEF,MAAM,MAAM,mBAAmB,GAAG;IAChC;;;OAGG;IACH,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB,CAAC;AAEF,MAAM,MAAM,gBAAgB,GAAG;IAC7B,KAAK,EAAE,IAAI,CAAC;IACZ,GAAG,EAAE,IAAI,CAAC;CACX,CAAC"}
package/dist/types.js ADDED
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":""}
package/package.json ADDED
@@ -0,0 +1,65 @@
1
+ {
2
+ "name": "@ntrr/calendar-kit",
3
+ "version": "0.2.0",
4
+ "description": "Portable CalDAV/ICS calendar helpers for NTRR products (Hub, Reliant, future services).",
5
+ "license": "MIT",
6
+ "private": false,
7
+ "type": "module",
8
+ "main": "./dist/index.js",
9
+ "types": "./dist/index.d.ts",
10
+ "exports": {
11
+ ".": {
12
+ "types": "./dist/index.d.ts",
13
+ "import": "./dist/index.js",
14
+ "default": "./dist/index.js"
15
+ },
16
+ "./apple": {
17
+ "types": "./dist/apple/index.d.ts",
18
+ "import": "./dist/apple/index.js",
19
+ "default": "./dist/apple/index.js"
20
+ }
21
+ },
22
+ "files": [
23
+ "dist",
24
+ "README.md",
25
+ "CHANGELOG.md",
26
+ "LICENSE"
27
+ ],
28
+ "scripts": {
29
+ "build": "tsc -p tsconfig.json",
30
+ "clean": "rm -rf dist dist-test",
31
+ "prepare": "npm run build",
32
+ "prepublishOnly": "npm run build",
33
+ "test": "npm run build && tsc -p tsconfig.test.json && TZ=UTC node --test dist-test/test/*.test.js",
34
+ "typecheck": "tsc -p tsconfig.json --noEmit"
35
+ },
36
+ "engines": {
37
+ "node": ">=18"
38
+ },
39
+ "dependencies": {
40
+ "ical.js": "^2.2.1",
41
+ "luxon": "^3.7.2"
42
+ },
43
+ "devDependencies": {
44
+ "@types/luxon": "^3.7.5",
45
+ "@types/node": "^20.19.1",
46
+ "typescript": "^5.8.3"
47
+ },
48
+ "publishConfig": {
49
+ "access": "public"
50
+ },
51
+ "repository": {
52
+ "type": "git",
53
+ "url": "git+https://github.com/sm00thindian/ntrr-calendar.git"
54
+ },
55
+ "keywords": [
56
+ "caldav",
57
+ "icalendar",
58
+ "ics",
59
+ "icloud",
60
+ "apple",
61
+ "calendar",
62
+ "timezone",
63
+ "luxon"
64
+ ]
65
+ }