this repo has no description
1(**
2 * JMAP protocol implementation based on RFC8620
3 * https://datatracker.ietf.org/doc/html/rfc8620
4 *)
5
6(** Initialize and configure logging for JMAP *)
7val init_logging : ?level:int -> ?enable_logs:bool -> ?redact_sensitive:bool -> unit -> unit
8
9(** Redact sensitive data like tokens *)
10val redact_token : ?redact:bool -> string -> string
11
12(** Module for managing JMAP capability URIs and other constants *)
13module Capability : sig
14 (** Core JMAP capability URI *)
15 type core = Core
16
17 (** JMAP capability URI as specified in RFC8620 *)
18 val core_uri : string
19
20 (** Convert core capability to URI string *)
21 val string_of_core : core -> string
22
23 (** Parse a string to a core capability, returns None if not a valid capability URI *)
24 val core_of_string : string -> core option
25
26 (** All JMAP capability types *)
27 type t =
28 | Core of core
29 | Extension of string
30
31 (** Convert capability to URI string *)
32 val to_string : t -> string
33
34 (** Parse a string to a capability, returns Extension for non-core capabilities *)
35 val of_string : string -> t
36
37 (** Check if a capability matches a core capability *)
38 val is_core : t -> bool
39
40 (** Check if a capability string is a core capability *)
41 val is_core_string : string -> bool
42
43 (** Create a list of capability strings *)
44 val strings_of_capabilities : t list -> string list
45end
46
47(** {1 Types} *)
48
49module Types : sig
50 (** Id string as per Section 1.2 *)
51 type id = string
52
53 (** Int bounded within the range -2^53+1 to 2^53-1 as per Section 1.3 *)
54 type int_t = int
55
56 (** UnsignedInt bounded within the range 0 to 2^53-1 as per Section 1.3 *)
57 type unsigned_int = int
58
59 (** Date string in RFC3339 format as per Section 1.4 *)
60 type date = string
61
62 (** UTCDate is a Date with 'Z' time zone as per Section 1.4 *)
63 type utc_date = string
64
65 (** Error object as per Section 3.6.2 *)
66 type error = {
67 type_: string;
68 description: string option;
69 }
70
71 (** Set error object as per Section 5.3 *)
72 type set_error = {
73 type_: string;
74 description: string option;
75 properties: string list option;
76 (* Additional properties for specific error types *)
77 existing_id: id option; (* For alreadyExists error *)
78 }
79
80 (** Invocation object as per Section 3.2 *)
81 type 'a invocation = {
82 name: string;
83 arguments: 'a;
84 method_call_id: string;
85 }
86
87 (** ResultReference object as per Section 3.7 *)
88 type result_reference = {
89 result_of: string;
90 name: string;
91 path: string;
92 }
93
94 (** FilterOperator, FilterCondition and Filter as per Section 5.5 *)
95 type filter_operator = {
96 operator: string; (* "AND", "OR", "NOT" *)
97 conditions: filter list;
98 }
99 and filter_condition = (string * Ezjsonm.value) list
100 and filter =
101 | Operator of filter_operator
102 | Condition of filter_condition
103
104 (** Comparator object for sorting as per Section 5.5 *)
105 type comparator = {
106 property: string;
107 is_ascending: bool option; (* Optional, defaults to true *)
108 collation: string option; (* Optional, server-dependent default *)
109 }
110
111 (** PatchObject as per Section 5.3 *)
112 type patch_object = (string * Ezjsonm.value) list
113
114 (** AddedItem structure as per Section 5.6 *)
115 type added_item = {
116 id: id;
117 index: unsigned_int;
118 }
119
120 (** Account object as per Section 1.6.2 *)
121 type account = {
122 name: string;
123 is_personal: bool;
124 is_read_only: bool;
125 account_capabilities: (string * Ezjsonm.value) list;
126 }
127
128 (** Core capability object as per Section 2 *)
129 type core_capability = {
130 max_size_upload: unsigned_int;
131 max_concurrent_upload: unsigned_int;
132 max_size_request: unsigned_int;
133 max_concurrent_requests: unsigned_int;
134 max_calls_in_request: unsigned_int;
135 max_objects_in_get: unsigned_int;
136 max_objects_in_set: unsigned_int;
137 collation_algorithms: string list;
138 }
139
140 (** PushSubscription keys object as per Section 7.2 *)
141 type push_keys = {
142 p256dh: string;
143 auth: string;
144 }
145
146 (** Session object as per Section 2 *)
147 type session = {
148 capabilities: (string * Ezjsonm.value) list;
149 accounts: (id * account) list;
150 primary_accounts: (string * id) list;
151 username: string;
152 api_url: string;
153 download_url: string;
154 upload_url: string;
155 event_source_url: string option;
156 state: string;
157 }
158
159 (** TypeState for state changes as per Section 7.1 *)
160 type type_state = (string * string) list
161
162 (** StateChange object as per Section 7.1 *)
163 type state_change = {
164 changed: (id * type_state) list;
165 }
166
167 (** PushVerification object as per Section 7.2.2 *)
168 type push_verification = {
169 push_subscription_id: id;
170 verification_code: string;
171 }
172
173 (** PushSubscription object as per Section 7.2 *)
174 type push_subscription = {
175 id: id;
176 device_client_id: string;
177 url: string;
178 keys: push_keys option;
179 verification_code: string option;
180 expires: utc_date option;
181 types: string list option;
182 }
183
184 (** Request object as per Section 3.3 *)
185 type request = {
186 using: string list;
187 method_calls: Ezjsonm.value invocation list;
188 created_ids: (id * id) list option;
189 }
190
191 (** Response object as per Section 3.4 *)
192 type response = {
193 method_responses: Ezjsonm.value invocation list;
194 created_ids: (id * id) list option;
195 session_state: string;
196 }
197
198 (** Standard method arguments and responses *)
199
200 (** Arguments for Foo/get method as per Section 5.1 *)
201 type 'a get_arguments = {
202 account_id: id;
203 ids: id list option;
204 properties: string list option;
205 }
206
207 (** Response for Foo/get method as per Section 5.1 *)
208 type 'a get_response = {
209 account_id: id;
210 state: string;
211 list: 'a list;
212 not_found: id list;
213 }
214
215 (** Arguments for Foo/changes method as per Section 5.2 *)
216 type changes_arguments = {
217 account_id: id;
218 since_state: string;
219 max_changes: unsigned_int option;
220 }
221
222 (** Response for Foo/changes method as per Section 5.2 *)
223 type changes_response = {
224 account_id: id;
225 old_state: string;
226 new_state: string;
227 has_more_changes: bool;
228 created: id list;
229 updated: id list;
230 destroyed: id list;
231 }
232
233 (** Arguments for Foo/set method as per Section 5.3 *)
234 type 'a set_arguments = {
235 account_id: id;
236 if_in_state: string option;
237 create: (id * 'a) list option;
238 update: (id * patch_object) list option;
239 destroy: id list option;
240 }
241
242 (** Response for Foo/set method as per Section 5.3 *)
243 type 'a set_response = {
244 account_id: id;
245 old_state: string option;
246 new_state: string;
247 created: (id * 'a) list option;
248 updated: (id * 'a option) list option;
249 destroyed: id list option;
250 not_created: (id * set_error) list option;
251 not_updated: (id * set_error) list option;
252 not_destroyed: (id * set_error) list option;
253 }
254
255 (** Arguments for Foo/copy method as per Section 5.4 *)
256 type 'a copy_arguments = {
257 from_account_id: id;
258 if_from_in_state: string option;
259 account_id: id;
260 if_in_state: string option;
261 create: (id * 'a) list;
262 on_success_destroy_original: bool option;
263 destroy_from_if_in_state: string option;
264 }
265
266 (** Response for Foo/copy method as per Section 5.4 *)
267 type 'a copy_response = {
268 from_account_id: id;
269 account_id: id;
270 old_state: string option;
271 new_state: string;
272 created: (id * 'a) list option;
273 not_created: (id * set_error) list option;
274 }
275
276 (** Arguments for Foo/query method as per Section 5.5 *)
277 type query_arguments = {
278 account_id: id;
279 filter: filter option;
280 sort: comparator list option;
281 position: int_t option;
282 anchor: id option;
283 anchor_offset: int_t option;
284 limit: unsigned_int option;
285 calculate_total: bool option;
286 }
287
288 (** Response for Foo/query method as per Section 5.5 *)
289 type query_response = {
290 account_id: id;
291 query_state: string;
292 can_calculate_changes: bool;
293 position: unsigned_int;
294 ids: id list;
295 total: unsigned_int option;
296 limit: unsigned_int option;
297 }
298
299 (** Arguments for Foo/queryChanges method as per Section 5.6 *)
300 type query_changes_arguments = {
301 account_id: id;
302 filter: filter option;
303 sort: comparator list option;
304 since_query_state: string;
305 max_changes: unsigned_int option;
306 up_to_id: id option;
307 calculate_total: bool option;
308 }
309
310 (** Response for Foo/queryChanges method as per Section 5.6 *)
311 type query_changes_response = {
312 account_id: id;
313 old_query_state: string;
314 new_query_state: string;
315 total: unsigned_int option;
316 removed: id list;
317 added: added_item list option;
318 }
319
320 (** Arguments for Blob/copy method as per Section 6.3 *)
321 type blob_copy_arguments = {
322 from_account_id: id;
323 account_id: id;
324 blob_ids: id list;
325 }
326
327 (** Response for Blob/copy method as per Section 6.3 *)
328 type blob_copy_response = {
329 from_account_id: id;
330 account_id: id;
331 copied: (id * id) list option;
332 not_copied: (id * set_error) list option;
333 }
334
335 (** Upload response as per Section 6.1 *)
336 type upload_response = {
337 account_id: id;
338 blob_id: id;
339 type_: string;
340 size: unsigned_int;
341 }
342
343 (** Problem details object as per RFC7807 and Section 3.6.1 *)
344 type problem_details = {
345 type_: string;
346 status: int option;
347 detail: string option;
348 limit: string option; (* For "limit" error *)
349 }
350end
351
352(** {1 API Client} *)
353
354(** Module for making JMAP API requests over HTTP.
355 Provides functionality to interact with JMAP servers according to RFC8620. *)
356module Api : sig
357 (** Error that may occur during API requests *)
358 type error =
359 | Connection_error of string
360 | HTTP_error of int * string
361 | Parse_error of string
362 | Authentication_error
363
364 (** Result type for API operations *)
365 type 'a result = ('a, error) Stdlib.result
366
367 (** Configuration for a JMAP API client *)
368 type config = {
369 api_uri: Uri.t;
370 username: string;
371 authentication_token: string;
372 }
373
374 (** Make a raw JMAP API request *)
375 val make_request :
376 config ->
377 Types.request ->
378 Types.response result Lwt.t
379
380 (** Fetch a Session object from a JMAP server.
381 Can authenticate with either username/password or API token. *)
382 val get_session :
383 Uri.t ->
384 ?username:string ->
385 ?authentication_token:string ->
386 ?api_token:string ->
387 unit ->
388 Types.session result Lwt.t
389
390 (** Upload a binary blob to the server *)
391 val upload_blob :
392 config ->
393 account_id:Types.id ->
394 content_type:string ->
395 string ->
396 Types.upload_response result Lwt.t
397
398 (** Download a binary blob from the server *)
399 val download_blob :
400 config ->
401 account_id:Types.id ->
402 blob_id:Types.id ->
403 ?type_:string ->
404 ?name:string ->
405 unit ->
406 string result Lwt.t
407end