Skip to content
File

Blob: src/worker/routes/api/calendars.ts

typescript103 lines
1import {
2 CalendarCreateRequestSchema,
3 CalendarPatchRequestSchema,
4 CalendarResponseSchema,
5} from "@/worker/openapi/schemas";
6import type { CalendarRecord } from "@/worker/objects/cal-dav-object";
7import { createCollectionCrudRoutes, isoDate } from "@/worker/routes/api/collection-crud";
8 
9const calendarErrorStatuses = [400, 401, 403, 404, 409, 500] as const;
10const calendarDeleteErrorStatuses = [400, 401, 403, 404, 500] as const;
11 
12function calendarResponse(row: CalendarRecord) {
13 return {
14 id: row.id,
15 name: row.name,
16 display_name: row.displayName,
17 description: row.description,
18 href: row.href,
19 color: row.color,
20 order_index: row.orderIndex,
21 timezone_ical: row.timezoneIcal,
22 created_at: isoDate(row.createdAtMs),
23 modified_at: isoDate(row.modifiedAtMs),
24 sync_token: row.syncToken,
25 };
26}
27 
28export function createCalendarApiRoutes() {
29 return createCollectionCrudRoutes({
30 tag: "calendars",
31 idParam: "calendar_id",
32 summaries: {
33 list: "List calendars",
34 create: "Create calendar",
35 get: "Get calendar",
36 update: "Update calendar",
37 delete: "Delete calendar",
38 },
39 deleteSuccessDescription: "Calendar deleted",
40 responseSchema: CalendarResponseSchema,
41 listResponseSchema: CalendarResponseSchema.array(),
42 createSchema: CalendarCreateRequestSchema,
43 patchSchema: CalendarPatchRequestSchema,
44 errorStatuses: calendarErrorStatuses,
45 deleteErrorStatuses: calendarDeleteErrorStatuses,
46 emptyPatch: {
47 fields: ["display_name", "description", "color", "order_index", "timezone_ical"],
48 code: "invalid_calendar_update",
49 message: "Calendar update must change at least one field.",
50 },
51 toResponse: calendarResponse,
52 list: async (c, subject) =>
53 (
54 await c.env.CAL_DAV.getByName(subject.storageId).listCalendars({
55 subjectId: subject.id,
56 nowMs: Date.now(),
57 })
58 ).calendars,
59 create: async (c, subject, body) => {
60 const result = await c.env.CAL_DAV.getByName(subject.storageId).createCalendar({
61 subjectId: subject.id,
62 name: body.name,
63 displayName: body.display_name,
64 description: body.description,
65 color: body.color,
66 orderIndex: body.order_index,
67 timezoneIcal: body.timezone_ical,
68 nowMs: Date.now(),
69 });
70 return result.ok ? { ok: true, value: result.calendar } : result;
71 },
72 get: async (c, subject, id) => {
73 const result = await c.env.CAL_DAV.getByName(subject.storageId).getCalendar({
74 subjectId: subject.id,
75 id,
76 nowMs: Date.now(),
77 });
78 return result.ok ? { ok: true, value: result.calendar } : result;
79 },
80 patch: async (c, subject, id, body) => {
81 const result = await c.env.CAL_DAV.getByName(subject.storageId).updateCalendar({
82 subjectId: subject.id,
83 id,
84 displayName: body.display_name,
85 description: body.description,
86 color: body.color,
87 orderIndex: body.order_index,
88 timezoneIcal: body.timezone_ical,
89 nowMs: Date.now(),
90 });
91 return result.ok ? { ok: true, value: result.calendar } : result;
92 },
93 delete: async (c, subject, id) => {
94 const result = await c.env.CAL_DAV.getByName(subject.storageId).deleteCalendar({
95 subjectId: subject.id,
96 id,
97 nowMs: Date.now(),
98 });
99 return result.ok ? { ok: true, value: null } : result;
100 },
101 });
102}