My agentic slop goes here. Not intended for anyone else!

more

+4 -5
jmap/bin/fastmail_connect.ml
···
open Printf
-
open Jmap.Method_names
(* Result monad operator for cleaner error handling *)
let (let+) x f = Result.bind x f
···
let builder = Jmap_unix.build ctx in
let builder = Jmap_unix.using builder [`Core; `Mail] in
-
let builder = Jmap_unix.add_method_call builder (method_to_string `Email_query) query_json "q1" in
-
let builder = Jmap_unix.add_method_call builder (method_to_string `Email_get) get_json "g1" in
+
let builder = Jmap_unix.add_method_call builder `Email_query query_json "q1" in
+
let builder = Jmap_unix.add_method_call builder `Email_get get_json "g1" in
let+ response = Jmap_unix.execute env builder in
printf "✓ Got JMAP response\n";
-
let+ query_response_json = Jmap_unix.Response.extract_method ~method_name:(method_to_string `Email_query) ~method_call_id:"q1" response in
+
let+ query_response_json = Jmap_unix.Response.extract_method ~method_name:`Email_query ~method_call_id:"q1" response in
let+ query_response = Jmap_email.Email_response.parse_query_response query_response_json in
printf "✓ Found %d emails\n\n" (Jmap_email.Email_response.ids_from_query_response query_response |> List.length);
-
let+ get_response_json = Jmap_unix.Response.extract_method ~method_name:(method_to_string `Email_get) ~method_call_id:"g1" response in
+
let+ get_response_json = Jmap_unix.Response.extract_method ~method_name:`Email_get ~method_call_id:"g1" response in
let+ get_response = Jmap_email.Email_response.parse_get_response
~from_json:(fun json -> match Jmap_email.of_json json with
| Ok email -> email
+2 -2
jmap/jmap-email/jmap_email_query.ml
···
open Jmap.Methods.Filter
(* Email-specific filter constructors using core utilities *)
-
let in_mailbox mailbox_id =
+
let in_mailbox (mailbox_id : Jmap.Types.id) =
condition (`Assoc [("inMailbox", `String mailbox_id)])
let in_mailbox_role role =
···
end
type query_builder = {
-
account_id : string option;
+
account_id : Jmap.Types.id option;
filter : Filter.t option;
sort : Sort.t list;
limit_count : Jmap.Types.uint option;
+3 -3
jmap/jmap-email/jmap_email_query.mli
···
type t = Jmap.Methods.Filter.t
(** Filter by mailbox *)
-
val in_mailbox : string -> t
+
val in_mailbox : Jmap.Types.id -> t
(** Filter by mailbox role (e.g., "inbox", "sent", "drafts") *)
val in_mailbox_role : string -> t
···
val query : unit -> query_builder
(** Set the account ID (uses primary mail account if not set) *)
-
val with_account : string -> query_builder -> query_builder
+
val with_account : Jmap.Types.id -> query_builder -> query_builder
(** Add a filter condition *)
val where : Filter.t -> query_builder -> query_builder
···
@param result_of Method call ID to reference (e.g., "q1")
@return JSON object for Email/get method arguments *)
val build_email_get_with_ref :
-
account_id:string ->
+
account_id:Jmap.Types.id ->
properties:property list ->
result_of:string ->
Yojson.Safe.t
+11 -11
jmap/jmap-email/jmap_email_set.ml
···
module Create = struct
type t = {
mailbox_ids : (id * bool) list;
-
keywords : (string * bool) list;
-
received_at : string option; (* UTC date as string *)
+
keywords : (Jmap_email_keywords.keyword * bool) list;
+
received_at : Jmap.Types.utc_date option;
(* Additional fields as needed *)
}
···
let to_json t : Yojson.Safe.t =
let fields = [
("mailboxIds", (`Assoc (List.map (fun (id, v) -> (id, `Bool v)) t.mailbox_ids) : Yojson.Safe.t));
-
("keywords", (`Assoc (List.map (fun (kw, v) -> (kw, `Bool v)) t.keywords) : Yojson.Safe.t));
+
("keywords", (`Assoc (List.map (fun (kw, v) -> (Jmap_email_keywords.keyword_to_string kw, `Bool v)) t.keywords) : Yojson.Safe.t));
] in
let fields = match t.received_at with
-
| Some date_str -> ("receivedAt", (`String date_str : Yojson.Safe.t)) :: fields
+
| Some timestamp -> ("receivedAt", (`String (Jmap.Date.of_timestamp timestamp |> Jmap.Date.to_rfc3339) : Yojson.Safe.t)) :: fields
| None -> fields
in
(`Assoc fields : Yojson.Safe.t)
···
let patch_builder () = []
let set_keywords keywords patch =
-
("keywords", `Assoc (List.map (fun (kw, v) -> (kw, `Bool v)) keywords)) :: patch
+
("keywords", `Assoc (List.map (fun (kw, v) -> (Jmap_email_keywords.keyword_to_string kw, `Bool v)) keywords)) :: patch
let add_keyword keyword patch =
-
("keywords/" ^ keyword, `Bool true) :: patch
+
("keywords/" ^ (Jmap_email_keywords.keyword_to_string keyword), `Bool true) :: patch
let remove_keyword keyword patch =
-
("keywords/" ^ keyword, `Null) :: patch
+
("keywords/" ^ (Jmap_email_keywords.keyword_to_string keyword), `Null) :: patch
let move_to_mailbox mailbox_id patch =
(* Clear all existing mailboxes and set new one *)
···
let mark_as_read ~account_id email_ids =
let update_map : patch_object id_map = Hashtbl.create (List.length email_ids) in
List.iter (fun id ->
-
Hashtbl.add update_map id (Update.add_keyword "$seen" [])
+
Hashtbl.add update_map id (Update.add_keyword Jmap_email_keywords.Seen [])
) email_ids;
build_set_args ~account_id ~update:update_map ()
···
let mark_as_unread ~account_id email_ids =
let update_map : patch_object id_map = Hashtbl.create (List.length email_ids) in
List.iter (fun id ->
-
Hashtbl.add update_map id (Update.remove_keyword "$seen" [])
+
Hashtbl.add update_map id (Update.remove_keyword Jmap_email_keywords.Seen [])
) email_ids;
build_set_args ~account_id ~update:update_map ()
···
let flag_emails ~account_id email_ids =
let update_map : patch_object id_map = Hashtbl.create (List.length email_ids) in
List.iter (fun id ->
-
Hashtbl.add update_map id (Update.add_keyword "$flagged" [])
+
Hashtbl.add update_map id (Update.add_keyword Jmap_email_keywords.Flagged [])
) email_ids;
build_set_args ~account_id ~update:update_map ()
···
let unflag_emails ~account_id email_ids =
let update_map : patch_object id_map = Hashtbl.create (List.length email_ids) in
List.iter (fun id ->
-
Hashtbl.add update_map id (Update.remove_keyword "$flagged" [])
+
Hashtbl.add update_map id (Update.remove_keyword Jmap_email_keywords.Flagged [])
) email_ids;
build_set_args ~account_id ~update:update_map ()
+6 -6
jmap/jmap-email/jmap_email_set.mli
···
@return Email creation arguments *)
val make :
mailbox_ids:(id * bool) list ->
-
?keywords:(string * bool) list ->
-
?received_at:string ->
+
?keywords:(Jmap_email_keywords.keyword * bool) list ->
+
?received_at:Jmap.Types.utc_date ->
unit -> t
(** Convert creation arguments to JSON *)
···
val patch_builder : unit -> patch_object
(** Set all keywords (replaces existing) *)
-
val set_keywords : (string * bool) list -> patch_object -> patch_object
+
val set_keywords : (Jmap_email_keywords.keyword * bool) list -> patch_object -> patch_object
(** Add a single keyword *)
-
val add_keyword : string -> patch_object -> patch_object
+
val add_keyword : Jmap_email_keywords.keyword -> patch_object -> patch_object
(** Remove a single keyword *)
-
val remove_keyword : string -> patch_object -> patch_object
+
val remove_keyword : Jmap_email_keywords.keyword -> patch_object -> patch_object
(** Move to a single mailbox (removes from all others) *)
val move_to_mailbox : id -> patch_object -> patch_object
···
val create_draft :
account_id:id ->
mailbox_ids:(id * bool) list ->
-
?keywords:(string * bool) list ->
+
?keywords:(Jmap_email_keywords.keyword * bool) list ->
?subject:string ->
?from:string ->
?to_:string list ->
+32 -26
jmap/jmap-unix/jmap_unix.ml
···
builder
let add_method_call builder method_name arguments method_call_id =
-
let invocation = Wire.Invocation.v ~method_name ~arguments ~method_call_id () in
+
let method_name_str = Jmap.Method_names.method_to_string method_name in
+
let invocation = Wire.Invocation.v ~method_name:method_name_str ~arguments ~method_call_id () in
builder.method_calls <- builder.method_calls @ [invocation];
builder
···
("blobIds", `List (List.map (fun id -> `String id) blob_ids));
] in
let builder = build ctx
-
|> fun b -> add_method_call b (Jmap.Method_names.method_to_string `Blob_copy) args "copy-1"
+
|> fun b -> add_method_call b `Blob_copy args "copy-1"
in
(match execute env builder with
| Ok _response ->
···
| None -> `Assoc []
in
let builder = build ctx
-
|> fun b -> add_method_call b (Jmap.Method_names.method_to_string `Core_echo) args "echo-1" in
+
|> fun b -> add_method_call b `Core_echo args "echo-1" in
match execute env builder with
| Ok _ -> Ok args
| Error e -> Error e
···
] in
let builder = build ctx
|> fun b -> using b [`Core; `Mail]
-
|> fun b -> add_method_call b (Jmap.Method_names.method_to_string `Email_get) args "get-1"
+
|> fun b -> add_method_call b `Email_get args "get-1"
in
match execute env builder with
(* TODO: Implement email parsing from JMAP response
···
] in
let builder = build ctx
|> fun b -> using b [`Core; `Mail]
-
|> fun b -> add_method_call b (Jmap.Method_names.method_to_string `Email_query) args "query-1"
+
|> fun b -> add_method_call b `Email_query args "query-1"
in
match execute env builder with
| Ok _ -> Ok ([], None)
···
] in
let builder = build ctx
|> fun b -> using b [`Core; `Mail]
-
|> fun b -> add_method_call b (Jmap.Method_names.method_to_string `Email_set) args "set-1"
+
|> fun b -> add_method_call b `Email_set args "set-1"
in
match execute env builder with
| Ok _ -> Ok ()
···
] in
let builder = build ctx
|> fun b -> using b [`Core; `Mail]
-
|> fun b -> add_method_call b (Jmap.Method_names.method_to_string `Email_import) args "import-1"
+
|> fun b -> add_method_call b `Email_import args "import-1"
in
match execute env builder with
| Ok _ -> Ok ("email-" ^ account_id ^ "-" ^ string_of_int (Random.int 1000000))
···
module Response = struct
let extract_method ~method_name ~method_call_id response =
+
let method_name_str = Jmap.Method_names.method_to_string method_name in
let method_responses = Jmap.Protocol.Wire.Response.method_responses response in
let find_response = List.find_map (function
| Ok invocation ->
if Jmap.Protocol.Wire.Invocation.method_call_id invocation = method_call_id &&
-
Jmap.Protocol.Wire.Invocation.method_name invocation = method_name then
+
Jmap.Protocol.Wire.Invocation.method_name invocation = method_name_str then
Some (Jmap.Protocol.Wire.Invocation.arguments invocation)
else None
| Error _ -> None
···
match find_response with
| Some response_args -> Ok response_args
| None -> Error (Jmap.Protocol.Error.protocol_error
-
(Printf.sprintf "%s response (call_id: %s) not found" method_name method_call_id))
+
(Printf.sprintf "%s response (call_id: %s) not found" method_name_str method_call_id))
let extract_method_by_name ~method_name response =
+
let method_name_str = Jmap.Method_names.method_to_string method_name in
let method_responses = Jmap.Protocol.Wire.Response.method_responses response in
let find_response = List.find_map (function
| Ok invocation ->
-
if Jmap.Protocol.Wire.Invocation.method_name invocation = method_name then
+
if Jmap.Protocol.Wire.Invocation.method_name invocation = method_name_str then
Some (Jmap.Protocol.Wire.Invocation.arguments invocation)
else None
| Error _ -> None
···
match find_response with
| Some response_args -> Ok response_args
| None -> Error (Jmap.Protocol.Error.protocol_error
-
(Printf.sprintf "%s response not found" method_name))
+
(Printf.sprintf "%s response not found" method_name_str))
end
(* Email High-Level Operations *)
···
(* Build the request using the request builder pattern *)
let req_builder = build builder.ctx in
let req_builder = using req_builder [`Core; `Mail] in
-
let final_builder = List.fold_left (fun rb (method_name, args, call_id) ->
+
let final_builder = List.fold_left (fun rb (method_name_str, args, call_id) ->
+
let method_name = match Jmap.Method_names.method_of_string method_name_str with
+
| Some m -> m
+
| None -> failwith ("Unknown method name: " ^ method_name_str) in
add_method_call rb method_name args call_id
) req_builder (List.rev builder.methods) in
execute env final_builder
···
(* Bridge response parsers that maintain architectural layering *)
module EmailQueryResponse = struct
let extract_json_list ?call_id response =
-
let method_name = Jmap.Method_names.method_to_string `Email_query in
+
let method_name = `Email_query in
match call_id with
| Some cid -> Response.extract_method ~method_name ~method_call_id:cid response
| None -> Response.extract_method_by_name ~method_name response
···
module EmailGetResponse = struct
let extract_email_list ?call_id response =
-
let method_name = Jmap.Method_names.method_to_string `Email_get in
+
let method_name = `Email_get in
let extract_method_result = match call_id with
| Some cid -> Response.extract_method ~method_name ~method_call_id:cid response
| None -> Response.extract_method_by_name ~method_name response
···
module ThreadGetResponse = struct
let extract_thread_list ?call_id response =
-
let method_name = Jmap.Method_names.method_to_string `Thread_get in
+
let method_name = `Thread_get in
let extract_method_result = match call_id with
| Some cid -> Response.extract_method ~method_name ~method_call_id:cid response
| None -> Response.extract_method_by_name ~method_name response
···
module MailboxGetResponse = struct
let extract_mailbox_list ?call_id response =
-
let method_name = Jmap.Method_names.method_to_string `Mailbox_get in
+
let method_name = `Mailbox_get in
let extract_method_result = match call_id with
| Some cid -> Response.extract_method ~method_name ~method_call_id:cid response
| None -> Response.extract_method_by_name ~method_name response
···
let call_id = "email-query-" ^ string_of_int (Random.int 10000) in
let req_builder = build ctx in
let req_builder = using req_builder [`Core; `Mail] in
-
let req_builder = add_method_call req_builder (Jmap.Method_names.method_to_string `Email_query) builder call_id
+
let req_builder = add_method_call req_builder `Email_query builder call_id
in
match jmap_execute env req_builder with
| Ok response ->
-
(match Response.extract_method ~method_name:(Jmap.Method_names.method_to_string `Email_query) ~method_call_id:call_id response with
+
(match Response.extract_method ~method_name:`Email_query ~method_call_id:call_id response with
| Ok json -> Ok json
| Error e -> Error e)
| Error e -> Error e
···
let req_builder = build ctx in
let req_builder = using req_builder [`Core; `Mail] in
-
let req_builder = add_method_call req_builder (Jmap.Method_names.method_to_string `Email_query) builder query_call_id in
-
let req_builder = add_method_call req_builder (Jmap.Method_names.method_to_string `Email_get) get_args get_call_id
+
let req_builder = add_method_call req_builder `Email_query builder query_call_id in
+
let req_builder = add_method_call req_builder `Email_get get_args get_call_id
in
match jmap_execute env req_builder with
| Ok response ->
-
(match Response.extract_method ~method_name:(Jmap.Method_names.method_to_string `Email_get) ~method_call_id:get_call_id response with
+
(match Response.extract_method ~method_name:`Email_get ~method_call_id:get_call_id response with
| Ok json -> Ok json
| Error e -> Error e)
| Error e -> Error e
···
let call_id = "batch-" ^ string_of_int (Random.int 10000) in
let req_builder = build ctx in
let req_builder = using req_builder [`Core; `Mail] in
-
let req_builder = add_method_call req_builder (Jmap.Method_names.method_to_string `Email_set) batch call_id
+
let req_builder = add_method_call req_builder `Email_set batch call_id
in
match jmap_execute env req_builder with
| Ok response ->
-
(match Response.extract_method ~method_name:(Jmap.Method_names.method_to_string `Email_set) ~method_call_id:call_id response with
+
(match Response.extract_method ~method_name:`Email_set ~method_call_id:call_id response with
| Ok json -> Ok json
| Error e -> Error e)
| Error e -> Error e
···
let req_builder = build ctx in
let req_builder = using req_builder [`Core; `Mail] in
-
let req_builder = add_method_call req_builder (Jmap.Method_names.method_to_string `Email_query) query_args query_call_id in
-
let req_builder = add_method_call req_builder (Jmap.Method_names.method_to_string `Email_set) set_args set_call_id
+
let req_builder = add_method_call req_builder `Email_query query_args query_call_id in
+
let req_builder = add_method_call req_builder `Email_set set_args set_call_id
in
match jmap_execute env req_builder with
| Ok response ->
-
(match Response.extract_method ~method_name:(Jmap.Method_names.method_to_string `Email_set) ~method_call_id:set_call_id response with
+
(match Response.extract_method ~method_name:`Email_set ~method_call_id:set_call_id response with
| Ok json -> Ok json
| Error e -> Error e)
| Error e -> Error e
+26 -26
jmap/jmap-unix/jmap_unix.mli
···
(** Add a method call to a request builder.
@param builder The request builder.
-
@param name Method name (e.g., "Email/get").
+
@param method_name Typed method name variant.
@param args Method arguments.
@param id Method call ID.
@return The updated request builder.
*)
val add_method_call :
request_builder ->
-
string ->
+
Jmap.Method_names.jmap_method ->
Yojson.Safe.t ->
string ->
request_builder
···
val get_object :
< net : 'a Eio.Net.t ; .. > ->
context ->
-
method_name:string ->
+
method_name:Jmap.Method_names.jmap_method ->
account_id:Jmap.Types.id ->
object_id:Jmap.Types.id ->
?properties:string list ->
···
@return Updated request builder *)
val add_query :
t ->
-
method_name:string ->
+
method_name:Jmap.Method_names.jmap_method ->
args:Yojson.Safe.t ->
method_call_id:string ->
t
(** Add a get method call to the request builder.
@param t The request builder
-
@param method_name The JMAP method name (e.g., "Email/get")
+
@param method_name The JMAP method name variant
@param args The get arguments, already converted to JSON
@param method_call_id Unique identifier for this method call
@return Updated request builder *)
val add_get :
t ->
-
method_name:string ->
+
method_name:Jmap.Method_names.jmap_method ->
args:Yojson.Safe.t ->
method_call_id:string ->
t
(** Add a get method call with result reference to the request builder.
@param t The request builder
-
@param method_name The JMAP method name (e.g., "Email/get")
+
@param method_name The JMAP method name variant
@param account_id The account ID to use
@param result_reference Reference to a previous method call result
@param ?properties Optional list of properties to fetch
···
@return Updated request builder *)
val add_get_with_reference :
t ->
-
method_name:string ->
-
account_id:string ->
+
method_name:Jmap.Method_names.jmap_method ->
+
account_id:Jmap.Types.id ->
result_reference:Jmap.Protocol.Wire.Result_reference.t ->
?properties:string list ->
method_call_id:string ->
···
(** Response utilities for extracting data from JMAP responses *)
module Response : sig
(** Extract a specific method response from a JMAP Response.
-
@param method_name The method name to search for (e.g., "Email/get")
+
@param method_name Typed method name to search for
@param method_call_id The method call ID to match
@param response The JMAP response to search
@return The method response arguments or an error *)
val extract_method :
-
method_name:string ->
+
method_name:Jmap.Method_names.jmap_method ->
method_call_id:string ->
Jmap.Protocol.Wire.Response.t ->
Yojson.Safe.t Jmap.Protocol.Error.result
(** Extract the first method response with a given name, ignoring call ID.
-
@param method_name The method name to search for
+
@param method_name Typed method name to search for
@param response The JMAP response to search
@return The method response arguments or an error *)
val extract_method_by_name :
-
method_name:string ->
+
method_name:Jmap.Method_names.jmap_method ->
Jmap.Protocol.Wire.Response.t ->
Yojson.Safe.t Jmap.Protocol.Error.result
end
···
(** Add Email/query method *)
val email_query :
-
?account_id:string ->
+
?account_id:Jmap.Types.id ->
?filter:Yojson.Safe.t ->
?sort:Jmap.Methods.Comparator.t list ->
?limit:int ->
···
(** Add Email/get method with automatic result reference *)
val email_get :
-
?account_id:string ->
+
?account_id:Jmap.Types.id ->
?ids:Jmap.Id.t list ->
?properties:string list ->
?reference_from:string -> (* Call ID to reference *)
···
(** Add Email/set method *)
val email_set :
-
?account_id:string ->
+
?account_id:Jmap.Types.id ->
?create:(string * Yojson.Safe.t) list ->
?update:(Jmap.Id.t * Jmap.Patch.t) list ->
?destroy:Jmap.Id.t list ->
···
(** Add Thread/get method *)
val thread_get :
-
?account_id:string ->
+
?account_id:Jmap.Types.id ->
?ids:Jmap.Id.t list ->
t -> t
(** Add Mailbox/query method *)
val mailbox_query :
-
?account_id:string ->
+
?account_id:Jmap.Types.id ->
?filter:Yojson.Safe.t ->
?sort:Jmap.Methods.Comparator.t list ->
t -> t
(** Add Mailbox/get method *)
val mailbox_get :
-
?account_id:string ->
+
?account_id:Jmap.Types.id ->
?ids:Jmap.Id.t list ->
t -> t
···
(** Get specific method response by type *)
val get_response :
-
method_:string ->
+
method_:Jmap.Method_names.jmap_method ->
?call_id:string ->
Jmap.Protocol.Wire.Response.t ->
(Yojson.Safe.t, Jmap.Protocol.Error.error) result
···
< net : 'a Eio.Net.t ; .. > ->
ctx:context ->
session:Jmap.Protocol.Session.Session.t ->
-
?account_id:string ->
+
?account_id:Jmap.Types.id ->
?filter:Yojson.Safe.t ->
?sort:Jmap.Methods.Comparator.t list ->
?limit:int ->
···
< net : 'a Eio.Net.t ; .. > ->
ctx:context ->
session:Jmap.Protocol.Session.Session.t ->
-
?account_id:string ->
+
?account_id:Jmap.Types.id ->
?properties:string list ->
Jmap.Id.t list ->
(Yojson.Safe.t list, Jmap.Protocol.Error.error) result
···
< net : 'a Eio.Net.t ; .. > ->
ctx:context ->
session:Jmap.Protocol.Session.Session.t ->
-
?account_id:string ->
+
?account_id:Jmap.Types.id ->
unit ->
(Yojson.Safe.t list, Jmap.Protocol.Error.error) result
···
< net : 'a Eio.Net.t ; .. > ->
ctx:context ->
session:Jmap.Protocol.Session.Session.t ->
-
?account_id:string ->
+
?account_id:Jmap.Types.id ->
string ->
(Yojson.Safe.t option, Jmap.Protocol.Error.error) result
end
···
< net : 'a Eio.Net.t ; .. > ->
ctx:context ->
session:Jmap.Protocol.Session.Session.t ->
-
?account_id:string ->
+
?account_id:Jmap.Types.id ->
Yojson.Safe.t ->
(Yojson.Safe.t, Jmap.Protocol.Error.error) result
···
< net : 'a Eio.Net.t ; .. > ->
ctx:context ->
session:Jmap.Protocol.Session.Session.t ->
-
?account_id:string ->
+
?account_id:Jmap.Types.id ->
progress_fn:(progress -> unit) ->
Yojson.Safe.t ->
(Yojson.Safe.t, Jmap.Protocol.Error.error) result
+3 -3
jmap/jmap/jmap.mli
···
@param capability The capability URI to check.
@return True if supported, false otherwise.
*)
-
val supports_capability : Protocol.Session.Session.t -> string -> bool
+
val supports_capability : Protocol.Session.Session.t -> Jmap_capability.t -> bool
(** Get the primary account ID for a given capability.
@param session The session object.
-
@param capability The capability URI.
+
@param capability The capability.
@return The account ID or an error if not found.
*)
-
val get_primary_account : Protocol.Session.Session.t -> string -> (Id.t, Protocol.Error.error) result
+
val get_primary_account : Protocol.Session.Session.t -> Jmap_capability.t -> (Id.t, Protocol.Error.error) result
(** Get the download URL for a blob.
@param session The session object.
+4 -3
jmap/jmap/jmap_protocol.ml
···
let supports_capability session capability =
-
Hashtbl.mem (Session.Session.capabilities session) capability
+
Hashtbl.mem (Session.Session.capabilities session) (Jmap_capability.to_string capability)
let get_primary_account session capability =
+
let capability_uri = Jmap_capability.to_string capability in
let primary_accounts = Session.Session.primary_accounts session in
-
match Hashtbl.find_opt primary_accounts capability with
+
match Hashtbl.find_opt primary_accounts capability_uri with
| Some id -> Ok id
| None ->
Error (Error.protocol_error
-
(Printf.sprintf "No primary account found for capability: %s" capability))
+
(Printf.sprintf "No primary account found for capability: %s" capability_uri))
let find_method_response response method_call_id =
let responses = Wire.Response.method_responses response in
+4 -4
jmap/jmap/jmap_protocol.mli
···
(** Check if a session supports a given capability.
@param session The session object.
-
@param capability The capability URI to check.
+
@param capability The capability to check.
@return True if supported, false otherwise. *)
-
val supports_capability : session -> string -> bool
+
val supports_capability : session -> Jmap_capability.t -> bool
(** Get the primary account ID for a given capability.
@param session The session object.
-
@param capability The capability URI.
+
@param capability The capability.
@return The account ID or an error if not found. *)
-
val get_primary_account : session -> string -> (Jmap_types.id, error) result
+
val get_primary_account : session -> Jmap_capability.t -> (Jmap_types.id, error) result
(** Find a method response by its call ID.
@param response The response object.
+3 -3
jmap/jmap/jmap_request.ml
···
let get_capabilities t = t.using
let has_capability t capability =
-
List.mem capability t.using
+
List.mem (Jmap_capability.to_string capability) t.using
(** {1 Request Inspection} *)
···
let validate_capabilities t =
(* Check that required capabilities are present *)
let required_caps = [
-
Jmap_capability.to_string `Core (* Always required *)
+
`Core (* Always required *)
] in
let missing_caps = List.filter (fun cap -> not (has_capability t cap)) required_caps in
if missing_caps = [] then
Ok ()
else
-
Error missing_caps
+
Error (List.map Jmap_capability.to_string missing_caps)
let validate t =
(* Comprehensive WIRE_TYPE validation for JMAP requests *)
+2 -2
jmap/jmap/jmap_request.mli
···
(** Check if a specific capability is included in the request.
@param request The request to check
-
@param capability The capability URI to check for
+
@param capability The capability to check for
@return True if the capability is included *)
-
val has_capability : t -> string -> bool
+
val has_capability : t -> Jmap_capability.t -> bool
(** {1 Request Inspection} *)
+6 -5
jmap/jmap/jmap_session.ml
···
| Error _ -> None)
| None -> None
-
let has_capability t capability_uri =
-
Hashtbl.mem t.capabilities capability_uri
+
let has_capability t capability =
+
Hashtbl.mem t.capabilities (Jmap_capability.to_string capability)
-
let get_primary_account t capability_uri =
-
Hashtbl.find_opt t.primary_accounts capability_uri
+
let get_primary_account t capability =
+
Hashtbl.find_opt t.primary_accounts (Jmap_capability.to_string capability)
let get_account t account_id =
Hashtbl.find_opt t.accounts account_id
···
if Account.is_personal account then (id, account) :: acc else acc
) t.accounts []
-
let get_capability_accounts t capability_uri =
+
let get_capability_accounts t capability =
+
let capability_uri = Jmap_capability.to_string capability in
Hashtbl.fold (fun id account acc ->
if Hashtbl.mem (Account.account_capabilities account) capability_uri then
(id, account) :: acc
+6 -6
jmap/jmap/jmap_session.mli
···
val get_core_capability : t -> Core_capability.t option
(** Check if the session supports a given capability.
-
@param capability_uri The capability URI to check
+
@param capability The capability to check
@return True if the capability is supported *)
-
val has_capability : t -> string -> bool
+
val has_capability : t -> Jmap_capability.t -> bool
(** Get the primary account ID for a given capability.
-
@param capability_uri The capability URI
+
@param capability The capability
@return Primary account ID if found, None otherwise *)
-
val get_primary_account : t -> string -> id option
+
val get_primary_account : t -> Jmap_capability.t -> id option
(** Get account information by account ID.
@param account_id The account ID to look up
···
val get_personal_accounts : t -> (id * Account.t) list
(** Get all accounts that support a given capability.
-
@param capability_uri The capability URI
+
@param capability The capability
@return List of (account_id, account) pairs that support the capability *)
-
val get_capability_accounts : t -> string -> (id * Account.t) list
+
val get_capability_accounts : t -> Jmap_capability.t -> (id * Account.t) list
end
(** {1 Session Discovery and Retrieval} *)