import { AddressbookCreateRequestSchema, AddressbookPatchRequestSchema, AddressbookResponseSchema, } from "@/worker/openapi/schemas"; import type { AddressbookRecord } from "@/worker/objects/card-dav-object"; import { createCollectionCrudRoutes, isoDate } from "@/worker/routes/api/collection-crud"; const addressbookErrorStatuses = [400, 401, 403, 404, 409, 500] as const; const addressbookDeleteErrorStatuses = [400, 401, 403, 404, 500] as const; function addressbookResponse(row: AddressbookRecord) { return { id: row.id, name: row.name, display_name: row.displayName, description: row.description, href: row.href, created_at: isoDate(row.createdAtMs), modified_at: isoDate(row.modifiedAtMs), sync_token: row.syncToken, }; } export function createAddressbookApiRoutes() { return createCollectionCrudRoutes({ tag: "addressbooks", idParam: "addressbook_id", summaries: { list: "List address books", create: "Create address book", get: "Get address book", update: "Update address book", delete: "Delete address book", }, deleteSuccessDescription: "Address book deleted", responseSchema: AddressbookResponseSchema, listResponseSchema: AddressbookResponseSchema.array(), createSchema: AddressbookCreateRequestSchema, patchSchema: AddressbookPatchRequestSchema, errorStatuses: addressbookErrorStatuses, deleteErrorStatuses: addressbookDeleteErrorStatuses, emptyPatch: { fields: ["display_name", "description"], code: "invalid_addressbook_update", message: "Address book update must change at least one field.", }, toResponse: addressbookResponse, list: async (c, subject) => ( await c.env.CARD_DAV.getByName(subject.storageId).listAddressbooks({ subjectId: subject.id, nowMs: Date.now(), }) ).addressbooks, create: async (c, subject, body) => { const result = await c.env.CARD_DAV.getByName(subject.storageId).createAddressbook({ subjectId: subject.id, name: body.name, displayName: body.display_name, description: body.description, nowMs: Date.now(), }); return result.ok ? { ok: true, value: result.addressbook } : result; }, get: async (c, subject, id) => { const result = await c.env.CARD_DAV.getByName(subject.storageId).getAddressbook({ subjectId: subject.id, id, nowMs: Date.now(), }); return result.ok ? { ok: true, value: result.addressbook } : result; }, patch: async (c, subject, id, body) => { const result = await c.env.CARD_DAV.getByName(subject.storageId).updateAddressbook({ subjectId: subject.id, id, displayName: body.display_name, description: body.description, nowMs: Date.now(), }); return result.ok ? { ok: true, value: result.addressbook } : result; }, delete: async (c, subject, id) => { const result = await c.env.CARD_DAV.getByName(subject.storageId).deleteAddressbook({ subjectId: subject.id, id, nowMs: Date.now(), }); return result.ok ? { ok: true, value: null } : result; }, }); }