import { CalendarCreateRequestSchema, CalendarPatchRequestSchema, CalendarResponseSchema, } from "@/worker/openapi/schemas"; import type { CalendarRecord } from "@/worker/objects/cal-dav-object"; import { createCollectionCrudRoutes, isoDate } from "@/worker/routes/api/collection-crud"; const calendarErrorStatuses = [400, 401, 403, 404, 409, 500] as const; const calendarDeleteErrorStatuses = [400, 401, 403, 404, 500] as const; function calendarResponse(row: CalendarRecord) { return { id: row.id, name: row.name, display_name: row.displayName, description: row.description, href: row.href, color: row.color, order_index: row.orderIndex, timezone_ical: row.timezoneIcal, created_at: isoDate(row.createdAtMs), modified_at: isoDate(row.modifiedAtMs), sync_token: row.syncToken, }; } export function createCalendarApiRoutes() { return createCollectionCrudRoutes({ tag: "calendars", idParam: "calendar_id", summaries: { list: "List calendars", create: "Create calendar", get: "Get calendar", update: "Update calendar", delete: "Delete calendar", }, deleteSuccessDescription: "Calendar deleted", responseSchema: CalendarResponseSchema, listResponseSchema: CalendarResponseSchema.array(), createSchema: CalendarCreateRequestSchema, patchSchema: CalendarPatchRequestSchema, errorStatuses: calendarErrorStatuses, deleteErrorStatuses: calendarDeleteErrorStatuses, emptyPatch: { fields: ["display_name", "description", "color", "order_index", "timezone_ical"], code: "invalid_calendar_update", message: "Calendar update must change at least one field.", }, toResponse: calendarResponse, list: async (c, subject) => ( await c.env.CAL_DAV.getByName(subject.storageId).listCalendars({ subjectId: subject.id, nowMs: Date.now(), }) ).calendars, create: async (c, subject, body) => { const result = await c.env.CAL_DAV.getByName(subject.storageId).createCalendar({ subjectId: subject.id, name: body.name, displayName: body.display_name, description: body.description, color: body.color, orderIndex: body.order_index, timezoneIcal: body.timezone_ical, nowMs: Date.now(), }); return result.ok ? { ok: true, value: result.calendar } : result; }, get: async (c, subject, id) => { const result = await c.env.CAL_DAV.getByName(subject.storageId).getCalendar({ subjectId: subject.id, id, nowMs: Date.now(), }); return result.ok ? { ok: true, value: result.calendar } : result; }, patch: async (c, subject, id, body) => { const result = await c.env.CAL_DAV.getByName(subject.storageId).updateCalendar({ subjectId: subject.id, id, displayName: body.display_name, description: body.description, color: body.color, orderIndex: body.order_index, timezoneIcal: body.timezone_ical, nowMs: Date.now(), }); return result.ok ? { ok: true, value: result.calendar } : result; }, delete: async (c, subject, id) => { const result = await c.env.CAL_DAV.getByName(subject.storageId).deleteCalendar({ subjectId: subject.id, id, nowMs: Date.now(), }); return result.ok ? { ok: true, value: null } : result; }, }); }