// Shared wire shapes for the /calendar and /contacts workspaces. // // These mirror what the officer-caldav sidecar returns from its JSON door under /api/caldav/_officer/* — // see src/servers/sidecar/caldav/{collections,ical}.ts, which is where they are produced. The sidecar // parses the iCalendar/vCard itself so nothing here ever sees DAV XML. /** One calendar or address book. `path` is the DAV path (/dav///) and doubles as the id. */ export type DavCollection = { path: string; displayName: string; kind: 'calendar' | 'addressbook'; color?: string; }; export type CalendarEvent = { uid: string; summary: string; description?: string; location?: string; start?: string; end?: string; allDay: boolean; /** Raw RRULE, unexpanded — the sidecar does not expand a series, so this is a badge, not occurrences. */ rrule?: string; status?: string; }; export type DavContact = { uid: string; fullName: string; emails: string[]; phones: string[]; org?: string; title?: string; hasPhoto: boolean; }; /** * The query param both screens select with. A collection id contains slashes, so it cannot be a path * segment without escaping — and per the navigation rules the selection still has to live in the URL, * so it is a query param on the screen you are already on. */ export const COLLECTION_PARAM = 'collection'; /** The one place the two screens' URLs are spelled, so nav links and guards cannot drift. */ export const davCollectionPath = (base: '/calendar' | '/contacts', collection: string) => `${base}?${COLLECTION_PARAM}=${encodeURIComponent(collection)}`;