this repo has no description
1(* Standard JMAP Methods and Core/echo. *)
2
3open Jmap_types
4open Jmap_error
5
6(* Generic representation of a record type. Actual types defined elsewhere. *)
7type generic_record = Yojson.Safe.t
8
9(* Arguments for /get methods. *)
10module Get_args = struct
11 type 'record t = {
12 account_id: id;
13 ids: id list option;
14 properties: string list option;
15 }
16
17 let account_id t = t.account_id
18 let ids t = t.ids
19 let properties t = t.properties
20
21 let v ~account_id ?ids ?properties () =
22 { account_id; ids; properties }
23end
24
25(* Response for /get methods. *)
26module Get_response = struct
27 type 'record t = {
28 account_id: id;
29 state: string;
30 list: 'record list;
31 not_found: id list;
32 }
33
34 let account_id t = t.account_id
35 let state t = t.state
36 let list t = t.list
37 let not_found t = t.not_found
38
39 let v ~account_id ~state ~list ~not_found () =
40 { account_id; state; list; not_found }
41end
42
43(* Arguments for /changes methods. *)
44module Changes_args = struct
45 type t = {
46 account_id: id;
47 since_state: string;
48 max_changes: uint option;
49 }
50
51 let account_id t = t.account_id
52 let since_state t = t.since_state
53 let max_changes t = t.max_changes
54
55 let v ~account_id ~since_state ?max_changes () =
56 { account_id; since_state; max_changes }
57end
58
59(* Response for /changes methods. *)
60module Changes_response = struct
61 type t = {
62 account_id: id;
63 old_state: string;
64 new_state: string;
65 has_more_changes: bool;
66 created: id list;
67 updated: id list;
68 destroyed: id list;
69 updated_properties: string list option;
70 }
71
72 let account_id t = t.account_id
73 let old_state t = t.old_state
74 let new_state t = t.new_state
75 let has_more_changes t = t.has_more_changes
76 let created t = t.created
77 let updated t = t.updated
78 let destroyed t = t.destroyed
79 let updated_properties t = t.updated_properties
80
81 let v ~account_id ~old_state ~new_state ~has_more_changes
82 ~created ~updated ~destroyed ?updated_properties () =
83 { account_id; old_state; new_state; has_more_changes;
84 created; updated; destroyed; updated_properties }
85end
86
87(* Patch object for /set update.
88 A list of (JSON Pointer path, value) pairs. *)
89type patch_object = (json_pointer * Yojson.Safe.t) list
90
91(* Arguments for /set methods. *)
92module Set_args = struct
93 type ('create_record, 'update_record) t = {
94 account_id: id;
95 if_in_state: string option;
96 create: 'create_record id_map option;
97 update: 'update_record id_map option;
98 destroy: id list option;
99 on_success_destroy_original: bool option;
100 destroy_from_if_in_state: string option;
101 on_destroy_remove_emails: bool option;
102 }
103
104 let account_id t = t.account_id
105 let if_in_state t = t.if_in_state
106 let create t = t.create
107 let update t = t.update
108 let destroy t = t.destroy
109 let on_success_destroy_original t = t.on_success_destroy_original
110 let destroy_from_if_in_state t = t.destroy_from_if_in_state
111 let on_destroy_remove_emails t = t.on_destroy_remove_emails
112
113 let v ~account_id ?if_in_state ?create ?update ?destroy
114 ?on_success_destroy_original ?destroy_from_if_in_state
115 ?on_destroy_remove_emails () =
116 { account_id; if_in_state; create; update; destroy;
117 on_success_destroy_original; destroy_from_if_in_state;
118 on_destroy_remove_emails }
119end
120
121(* Response for /set methods. *)
122module Set_response = struct
123 type ('created_record_info, 'updated_record_info) t = {
124 account_id: id;
125 old_state: string option;
126 new_state: string;
127 created: 'created_record_info id_map option;
128 updated: 'updated_record_info option id_map option;
129 destroyed: id list option;
130 not_created: Set_error.t id_map option;
131 not_updated: Set_error.t id_map option;
132 not_destroyed: Set_error.t id_map option;
133 }
134
135 let account_id t = t.account_id
136 let old_state t = t.old_state
137 let new_state t = t.new_state
138 let created t = t.created
139 let updated t = t.updated
140 let destroyed t = t.destroyed
141 let not_created t = t.not_created
142 let not_updated t = t.not_updated
143 let not_destroyed t = t.not_destroyed
144
145 let v ~account_id ?old_state ~new_state ?created ?updated ?destroyed
146 ?not_created ?not_updated ?not_destroyed () =
147 { account_id; old_state; new_state; created; updated; destroyed;
148 not_created; not_updated; not_destroyed }
149end
150
151(* Arguments for /copy methods. *)
152module Copy_args = struct
153 type 'copy_record_override t = {
154 from_account_id: id;
155 if_from_in_state: string option;
156 account_id: id;
157 if_in_state: string option;
158 create: 'copy_record_override id_map;
159 on_success_destroy_original: bool;
160 destroy_from_if_in_state: string option;
161 }
162
163 let from_account_id t = t.from_account_id
164 let if_from_in_state t = t.if_from_in_state
165 let account_id t = t.account_id
166 let if_in_state t = t.if_in_state
167 let create t = t.create
168 let on_success_destroy_original t = t.on_success_destroy_original
169 let destroy_from_if_in_state t = t.destroy_from_if_in_state
170
171 let v ~from_account_id ?if_from_in_state ~account_id ?if_in_state
172 ~create ?(on_success_destroy_original=false) ?destroy_from_if_in_state () =
173 { from_account_id; if_from_in_state; account_id; if_in_state;
174 create; on_success_destroy_original; destroy_from_if_in_state }
175end
176
177(* Response for /copy methods. *)
178module Copy_response = struct
179 type 'created_record_info t = {
180 from_account_id: id;
181 account_id: id;
182 old_state: string option;
183 new_state: string;
184 created: 'created_record_info id_map option;
185 not_created: Set_error.t id_map option;
186 }
187
188 let from_account_id t = t.from_account_id
189 let account_id t = t.account_id
190 let old_state t = t.old_state
191 let new_state t = t.new_state
192 let created t = t.created
193 let not_created t = t.not_created
194
195 let v ~from_account_id ~account_id ?old_state ~new_state
196 ?created ?not_created () =
197 { from_account_id; account_id; old_state; new_state;
198 created; not_created }
199end
200
201(* Module for generic filter representation. *)
202module Filter = struct
203 type t =
204 | Condition of Yojson.Safe.t
205 | Operator of [ `AND | `OR | `NOT ] * t list
206
207 let condition json = Condition json
208
209 let operator op filters = Operator (op, filters)
210
211 let and_ filters = operator `AND filters
212
213 let or_ filters = operator `OR filters
214
215 let not_ filter = operator `NOT [filter]
216
217 let rec to_json = function
218 | Condition json -> json
219 | Operator (op, filters) ->
220 let key = match op with
221 | `AND -> "AND"
222 | `OR -> "OR"
223 | `NOT -> "NOT"
224 in
225 `Assoc [(key, `List (List.map to_json filters))]
226
227 (* Helper functions for common filter conditions *)
228
229 let text_contains property value =
230 condition (`Assoc [
231 (property, `Assoc [("contains", `String value)])
232 ])
233
234 let property_equals property value =
235 condition (`Assoc [(property, value)])
236
237 let property_not_equals property value =
238 condition (`Assoc [
239 (property, `Assoc [("!",value)])
240 ])
241
242 let property_gt property value =
243 condition (`Assoc [
244 (property, `Assoc [("gt", value)])
245 ])
246
247 let property_ge property value =
248 condition (`Assoc [
249 (property, `Assoc [("ge", value)])
250 ])
251
252 let property_lt property value =
253 condition (`Assoc [
254 (property, `Assoc [("lt", value)])
255 ])
256
257 let property_le property value =
258 condition (`Assoc [
259 (property, `Assoc [("le", value)])
260 ])
261
262 let property_in property values =
263 condition (`Assoc [
264 (property, `Assoc [("in", `List values)])
265 ])
266
267 let property_not_in property values =
268 condition (`Assoc [
269 (property, `Assoc [("!in", `List values)])
270 ])
271
272 let property_exists property =
273 condition (`Assoc [
274 (property, `Null) (* Using just the property name means "property exists" *)
275 ])
276
277 let string_starts_with property prefix =
278 condition (`Assoc [
279 (property, `Assoc [("startsWith", `String prefix)])
280 ])
281
282 let string_ends_with property suffix =
283 condition (`Assoc [
284 (property, `Assoc [("endsWith", `String suffix)])
285 ])
286end
287
288(* Comparator for sorting. *)
289module Comparator = struct
290 type t = {
291 property: string;
292 is_ascending: bool option;
293 collation: string option;
294 keyword: string option;
295 other_fields: Yojson.Safe.t string_map;
296 }
297
298 let property t = t.property
299 let is_ascending t = t.is_ascending
300 let collation t = t.collation
301 let keyword t = t.keyword
302 let other_fields t = t.other_fields
303
304 let v ~property ?is_ascending ?collation ?keyword
305 ?(other_fields=Hashtbl.create 0) () =
306 { property; is_ascending; collation; keyword; other_fields }
307end
308
309(* Arguments for /query methods. *)
310module Query_args = struct
311 type t = {
312 account_id: id;
313 filter: Filter.t option;
314 sort: Comparator.t list option;
315 position: jint option;
316 anchor: id option;
317 anchor_offset: jint option;
318 limit: uint option;
319 calculate_total: bool option;
320 collapse_threads: bool option;
321 sort_as_tree: bool option;
322 filter_as_tree: bool option;
323 }
324
325 let account_id t = t.account_id
326 let filter t = t.filter
327 let sort t = t.sort
328 let position t = t.position
329 let anchor t = t.anchor
330 let anchor_offset t = t.anchor_offset
331 let limit t = t.limit
332 let calculate_total t = t.calculate_total
333 let collapse_threads t = t.collapse_threads
334 let sort_as_tree t = t.sort_as_tree
335 let filter_as_tree t = t.filter_as_tree
336
337 let v ~account_id ?filter ?sort ?position ?anchor ?anchor_offset
338 ?limit ?calculate_total ?collapse_threads ?sort_as_tree ?filter_as_tree () =
339 { account_id; filter; sort; position; anchor; anchor_offset;
340 limit; calculate_total; collapse_threads; sort_as_tree; filter_as_tree }
341end
342
343(* Response for /query methods. *)
344module Query_response = struct
345 type t = {
346 account_id: id;
347 query_state: string;
348 can_calculate_changes: bool;
349 position: uint;
350 ids: id list;
351 total: uint option;
352 limit: uint option;
353 }
354
355 let account_id t = t.account_id
356 let query_state t = t.query_state
357 let can_calculate_changes t = t.can_calculate_changes
358 let position t = t.position
359 let ids t = t.ids
360 let total t = t.total
361 let limit t = t.limit
362
363 let v ~account_id ~query_state ~can_calculate_changes ~position ~ids
364 ?total ?limit () =
365 { account_id; query_state; can_calculate_changes; position; ids;
366 total; limit }
367end
368
369(* Item indicating an added record in /queryChanges. *)
370module Added_item = struct
371 type t = {
372 id: id;
373 index: uint;
374 }
375
376 let id t = t.id
377 let index t = t.index
378
379 let v ~id ~index () = { id; index }
380end
381
382(* Arguments for /queryChanges methods. *)
383module Query_changes_args = struct
384 type t = {
385 account_id: id;
386 filter: Filter.t option;
387 sort: Comparator.t list option;
388 since_query_state: string;
389 max_changes: uint option;
390 up_to_id: id option;
391 calculate_total: bool option;
392 collapse_threads: bool option;
393 }
394
395 let account_id t = t.account_id
396 let filter t = t.filter
397 let sort t = t.sort
398 let since_query_state t = t.since_query_state
399 let max_changes t = t.max_changes
400 let up_to_id t = t.up_to_id
401 let calculate_total t = t.calculate_total
402 let collapse_threads t = t.collapse_threads
403
404 let v ~account_id ?filter ?sort ~since_query_state ?max_changes
405 ?up_to_id ?calculate_total ?collapse_threads () =
406 { account_id; filter; sort; since_query_state; max_changes;
407 up_to_id; calculate_total; collapse_threads }
408end
409
410(* Response for /queryChanges methods. *)
411module Query_changes_response = struct
412 type t = {
413 account_id: id;
414 old_query_state: string;
415 new_query_state: string;
416 total: uint option;
417 removed: id list;
418 added: Added_item.t list;
419 }
420
421 let account_id t = t.account_id
422 let old_query_state t = t.old_query_state
423 let new_query_state t = t.new_query_state
424 let total t = t.total
425 let removed t = t.removed
426 let added t = t.added
427
428 let v ~account_id ~old_query_state ~new_query_state ?total
429 ~removed ~added () =
430 { account_id; old_query_state; new_query_state; total;
431 removed; added }
432end
433
434(* Core/echo method: Arguments are mirrored in the response. *)
435type core_echo_args = Yojson.Safe.t
436type core_echo_response = Yojson.Safe.t