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