Skip to content
File

Blob: src/worker/objects/card-dav/types.ts

typescript139 lines
1import type { CardDavResource as RepositoryCardDavResource } from "@/worker/db/card-dav-do/repository";
2import type { ParsedIfHeader } from "@/worker/dav/if-header";
3import type { CardDavFilterTest, CardDavSearchFilter } from "@/worker/carddav/types";
4 
5export type CardDavErrorCode =
6 | "bad_request"
7 | "conflict"
8 | "forbidden"
9 | "method_not_allowed"
10 | "not_found"
11 | "payload_too_large"
12 | "precondition_failed";
13 
14export interface CardDavError {
15 ok: false;
16 status: number;
17 code: CardDavErrorCode;
18 message: string;
19}
20 
21export type CardDavResource = RepositoryCardDavResource;
22 
23export interface AddressbookRecord {
24 id: string;
25 name: string;
26 displayName: string;
27 description: string | null;
28 href: string;
29 createdAtMs: number;
30 modifiedAtMs: number;
31 syncToken: string;
32}
33 
34export interface PutAddressObjectInput {
35 subjectId: string;
36 bookName: string;
37 objectName: string;
38 body: ArrayBuffer;
39 ifMatch: string | null;
40 ifNoneMatch: string | null;
41 ifHeader: ParsedIfHeader;
42 nowMs: number;
43 maxBytes: number;
44 // RFC 6352 6.3.2: if the Content-Type media supplies a version parameter,
45 // it must match the parsed vCard VERSION value.
46 expectedVersion?: string | null;
47}
48 
49export type SearchFilter = CardDavSearchFilter;
50export type FilterTest = CardDavFilterTest;
51 
52export interface EnsureInitializedInput {
53 subjectId: string;
54 nowMs: number;
55}
56 
57export type AddressbookListInput = EnsureInitializedInput;
58 
59export interface AddressbookGetInput extends EnsureInitializedInput {
60 id: string;
61}
62 
63export interface AddressbookCreateInput extends EnsureInitializedInput {
64 name: string;
65 displayName?: string;
66 description?: string | null;
67}
68 
69export interface AddressbookUpdateInput extends EnsureInitializedInput {
70 id: string;
71 displayName?: string;
72 description?: string | null;
73}
74 
75export interface AddressbookDeleteInput extends EnsureInitializedInput {
76 id: string;
77}
78 
79export interface DescribeInput extends EnsureInitializedInput {
80 kind: "home" | "addressbook" | "object";
81 bookName?: string;
82 objectName?: string;
83 depth: "0" | "1";
84 maxResults: number;
85}
86 
87export interface GetAddressObjectInput extends EnsureInitializedInput {
88 bookName: string;
89 objectName: string;
90}
91 
92export interface DeleteAddressObjectInput extends EnsureInitializedInput {
93 bookName: string;
94 objectName: string;
95 ifMatch: string | null;
96 ifNoneMatch: string | null;
97 ifHeader: ParsedIfHeader;
98}
99 
100export interface ProppatchInput extends EnsureInitializedInput {
101 kind: "home" | "addressbook" | "object";
102 resourceId: string | null;
103 bookName?: string;
104 objectName?: string;
105 instructions: (
106 | { kind: "set"; nsUri: string; localName: string; xmlValue: string }
107 | { kind: "remove"; nsUri: string; localName: string }
108 )[];
109 ifMatch: string | null;
110 ifNoneMatch: string | null;
111 ifHeader: ParsedIfHeader;
112}
113 
114export interface AddressbookQueryInput extends EnsureInitializedInput {
115 bookName: string;
116 filters: SearchFilter[];
117 filterTest: FilterTest;
118 maxResults: number;
119}
120 
121export interface AddressbookMultigetInput extends EnsureInitializedInput {
122 bookName: string;
123 hrefs: string[];
124 maxResults: number;
125 // Origins (scheme + host[:port]) that absolute hrefs are allowed to use. The
126 // canonical subject host is always accepted; empty means relative-only.
127 acceptedOrigins?: string[];
128}
129 
130export interface SyncCollectionInput extends EnsureInitializedInput {
131 bookName: string;
132 token: string | null;
133 maxResults: number;
134}
135 
136export function cardDavError(status: number, code: CardDavErrorCode, message: string): CardDavError {
137 return { ok: false, status, code, message };
138}