feat(01-03): implement broker client, syncCalendar, and events route (CAL-01)
- client.ts: createFastmailClient(email, appPassword) → tsdav DAVClient via Basic auth - sync.ts: syncCalendar upserts calendar row, selects ID, fetches+parses VEVENTs with ical.js - all-day DATE → dtstartDate (Date obj at T00:00:00Z), dtstartUtc=null, allDay=true - timed → dtstartUtc (JS Date), dtstartDate=null, allDay=false (D-13/Pitfall #3) - onDuplicateKeyUpdate on calendarId+uid composite key (idempotent) - routes/events.ts: GET /api/events reads cache only — no tsdav import (T-03-02) - tsc --noEmit clean; all 6 sync tests pass
This commit is contained in:
@@ -0,0 +1,32 @@
|
||||
/**
|
||||
* Fastmail CalDAV client factory.
|
||||
*
|
||||
* Creates a tsdav DAVClient per Fastmail credential set (one per member, per D-02).
|
||||
* The broker module owns the client lifetime — never create one per API request (Pitfall #3).
|
||||
*
|
||||
* Source: https://github.com/natelindev/tsdav
|
||||
* CalDAV principal URL pattern: https://caldav.fastmail.com/dav/principals/user/{email}/
|
||||
* (Pitfall #1: tsdav service discovery via /.well-known/caldav resolves to this principal)
|
||||
*/
|
||||
|
||||
import { createDAVClient } from 'tsdav'
|
||||
|
||||
/** The resolved type of a tsdav client returned by createDAVClient. */
|
||||
export type FastmailClient = Awaited<ReturnType<typeof createDAVClient>>
|
||||
|
||||
/**
|
||||
* Creates a tsdav DAVClient authenticated with Basic auth (app password).
|
||||
* The returned client can call fetchCalendars() and fetchCalendarObjects().
|
||||
* This call performs a service-discovery round-trip (Pitfall #3 — cache this client).
|
||||
*/
|
||||
export async function createFastmailClient(email: string, appPassword: string): Promise<FastmailClient> {
|
||||
return createDAVClient({
|
||||
serverUrl: 'https://caldav.fastmail.com',
|
||||
credentials: {
|
||||
username: email,
|
||||
password: appPassword,
|
||||
},
|
||||
authMethod: 'Basic',
|
||||
defaultAccountType: 'caldav',
|
||||
})
|
||||
}
|
||||
Reference in New Issue
Block a user