File
Blob: src/worker/routes/api/addressbooks.ts
| 1 | import { |
| 2 | AddressbookCreateRequestSchema, |
| 3 | AddressbookPatchRequestSchema, |
| 4 | AddressbookResponseSchema, |
| 5 | } from "@/worker/openapi/schemas"; |
| 6 | import type { AddressbookRecord } from "@/worker/objects/card-dav-object"; |
| 7 | import { createCollectionCrudRoutes, isoDate } from "@/worker/routes/api/collection-crud"; |
| 8 | |
| 9 | const addressbookErrorStatuses = [400, 401, 403, 404, 409, 500] as const; |
| 10 | const addressbookDeleteErrorStatuses = [400, 401, 403, 404, 500] as const; |
| 11 | |
| 12 | function addressbookResponse(row: AddressbookRecord) { |
| 13 | return { |
| 14 | id: row.id, |
| 15 | name: row.name, |
| 16 | display_name: row.displayName, |
| 17 | description: row.description, |
| 18 | href: row.href, |
| 19 | created_at: isoDate(row.createdAtMs), |
| 20 | modified_at: isoDate(row.modifiedAtMs), |
| 21 | sync_token: row.syncToken, |
| 22 | }; |
| 23 | } |
| 24 | |
| 25 | export function createAddressbookApiRoutes() { |
| 26 | return createCollectionCrudRoutes({ |
| 27 | tag: "addressbooks", |
| 28 | idParam: "addressbook_id", |
| 29 | summaries: { |
| 30 | list: "List address books", |
| 31 | create: "Create address book", |
| 32 | get: "Get address book", |
| 33 | update: "Update address book", |
| 34 | delete: "Delete address book", |
| 35 | }, |
| 36 | deleteSuccessDescription: "Address book deleted", |
| 37 | responseSchema: AddressbookResponseSchema, |
| 38 | listResponseSchema: AddressbookResponseSchema.array(), |
| 39 | createSchema: AddressbookCreateRequestSchema, |
| 40 | patchSchema: AddressbookPatchRequestSchema, |
| 41 | errorStatuses: addressbookErrorStatuses, |
| 42 | deleteErrorStatuses: addressbookDeleteErrorStatuses, |
| 43 | emptyPatch: { |
| 44 | fields: ["display_name", "description"], |
| 45 | code: "invalid_addressbook_update", |
| 46 | message: "Address book update must change at least one field.", |
| 47 | }, |
| 48 | toResponse: addressbookResponse, |
| 49 | list: async (c, subject) => |
| 50 | ( |
| 51 | await c.env.CARD_DAV.getByName(subject.storageId).listAddressbooks({ |
| 52 | subjectId: subject.id, |
| 53 | nowMs: Date.now(), |
| 54 | }) |
| 55 | ).addressbooks, |
| 56 | create: async (c, subject, body) => { |
| 57 | const result = await c.env.CARD_DAV.getByName(subject.storageId).createAddressbook({ |
| 58 | subjectId: subject.id, |
| 59 | name: body.name, |
| 60 | displayName: body.display_name, |
| 61 | description: body.description, |
| 62 | nowMs: Date.now(), |
| 63 | }); |
| 64 | return result.ok ? { ok: true, value: result.addressbook } : result; |
| 65 | }, |
| 66 | get: async (c, subject, id) => { |
| 67 | const result = await c.env.CARD_DAV.getByName(subject.storageId).getAddressbook({ |
| 68 | subjectId: subject.id, |
| 69 | id, |
| 70 | nowMs: Date.now(), |
| 71 | }); |
| 72 | return result.ok ? { ok: true, value: result.addressbook } : result; |
| 73 | }, |
| 74 | patch: async (c, subject, id, body) => { |
| 75 | const result = await c.env.CARD_DAV.getByName(subject.storageId).updateAddressbook({ |
| 76 | subjectId: subject.id, |
| 77 | id, |
| 78 | displayName: body.display_name, |
| 79 | description: body.description, |
| 80 | nowMs: Date.now(), |
| 81 | }); |
| 82 | return result.ok ? { ok: true, value: result.addressbook } : result; |
| 83 | }, |
| 84 | delete: async (c, subject, id) => { |
| 85 | const result = await c.env.CARD_DAV.getByName(subject.storageId).deleteAddressbook({ |
| 86 | subjectId: subject.id, |
| 87 | id, |
| 88 | nowMs: Date.now(), |
| 89 | }); |
| 90 | return result.ok ? { ok: true, value: null } : result; |
| 91 | }, |
| 92 | }); |
| 93 | } |