import { DAVClient } from 'tsdav'; // iCloud CalDAV Server URL const ICLOUD_CALDAV_URL = 'https://caldav.icloud.com'; export interface AppleReminderList { id: string; // URL title: string; color?: string; } /** * Create a configured DAV client for Apple iCloud */ const createClient = (email: string, appSpecificPassword: string) => { return new DAVClient({ serverUrl: ICLOUD_CALDAV_URL, credentials: { username: email, password: appSpecificPassword, }, authMethod: 'Basic', defaultAccountType: 'caldav', }); }; /** * Fetch all reminder lists (VTODO collections) */ export const fetchAppleReminderLists = async (email: string, appSpecificPassword: string): Promise => { try { const client = createClient(email, appSpecificPassword); await client.login(); const calendars = await client.fetchCalendars(); // Filter to VTODO collections (Reminders) const reminderLists = calendars.filter(cal => { const components: string[] = (cal as any).components || []; return components.includes('VTODO'); }); return reminderLists.map(cal => ({ id: cal.url, title: (cal.displayName as string) || 'Untitled List', color: (cal as any).calendarColor, })); } catch (error) { console.error('Error fetching Apple reminder lists:', error); throw error; } }; /** * Create a new reminder list (collection) */ export const createAppleReminderList = async (email: string, appSpecificPassword: string, title: string): Promise => { try { const client = createClient(email, appSpecificPassword); await client.login(); // tsdav's createDAVClient returns an object where we can use makeCalendar // First we need a base URL. We can derive it from existing calendars. const calendars = await client.fetchCalendars(); if (calendars.length === 0) { throw new Error('No existing Apple calendars found to derive base URL'); } // Deriving the base URL for new collections (usually parent of existing calendars) const firstCalUrl = calendars[0].url; const urlParts = firstCalUrl.split('/'); // Remove the last part (and trailing slash if exists) if (firstCalUrl.endsWith('/')) urlParts.pop(); urlParts.pop(); const baseWebDavUrl = urlParts.join('/') + '/'; const newId = crypto.randomUUID(); const newCalendarUrl = `${baseWebDavUrl}${newId}/`; // Create the calendar (reminder list) await (client as any).makeCalendar({ url: newCalendarUrl, props: { 'displayname': title, 'supported-calendar-component-set': { 'comp': { _attributes: { name: 'VTODO' } } } } }); return { id: newCalendarUrl, title: title, }; } catch (error) { console.error('Error creating Apple reminder list:', error); throw error; } };