+57
-23
stack/jmap/CLAUDE.md
+57
-23
stack/jmap/CLAUDE.md
······-4. Use `Jmap_invocation.response_to_json` to safely extract response data from packed responses···
·········
+43
-33
stack/jmap/README.md
+43
-33
stack/jmap/README.md
············
············
+169
stack/jmap/USAGE_GUIDE.md
+169
stack/jmap/USAGE_GUIDE.md
···
···+The JMAP library provides a clean, ergonomic API with short module names and a unified entry point.+The unified `Jmap` module combines `jmap-core`, `jmap-mail`, and `jmap-client` into a single, easy-to-use interface.+Most users should depend on `jmap`, which pulls in all three libraries. For specialized use cases (e.g., you only need parsing), you can depend on individual packages.
+11
stack/jmap/dune-project
+11
stack/jmap/dune-project
···+(description "Ergonomic, unified interface to the complete JMAP library (RFC 8620, RFC 8621). This is the recommended entry point for most users.")
+8
-8
stack/jmap/jmap-client/jmap_client.ml
+8
-8
stack/jmap/jmap-client/jmap_client.ml
···post_request : timeout:Requests.Timeout.t -> headers:Requests.Headers.t -> body:Requests.Body.t -> string -> Requests.Response.t;············
···post_request : timeout:Requests.Timeout.t -> headers:Requests.Headers.t -> body:Requests.Body.t -> string -> Requests.Response.t;············
+4
-4
stack/jmap/jmap-client/jmap_client.mli
+4
-4
stack/jmap/jmap-client/jmap_client.mli
······
······
+1
-1
stack/jmap/jmap-core/dune
+1
-1
stack/jmap/jmap-core/dune
+14
-15
stack/jmap/jmap-core/jmap_core.ml
+14
-15
stack/jmap/jmap-core/jmap_core.ml
···
···
+14
-15
stack/jmap/jmap-core/jmap_core.mli
+14
-15
stack/jmap/jmap-core/jmap_core.mli
···
···
+203
-203
stack/jmap/jmap-mail/jmap_email.ml
+203
-203
stack/jmap/jmap-mail/jmap_email.ml
······························-let received_at = Jmap_core.Jmap_primitives.UTCDate.of_json (require_field "receivedAt" fields) in············-in_mailbox_other_than : Jmap_core.Jmap_id.t list option; (** Email is in a mailbox other than these *)···············-max_body_value_bytes : Jmap_core.Jmap_primitives.UnsignedInt.t option; (** Truncate large body values *)·········-| Some mbvb -> ("maxBodyValueBytes", Jmap_core.Jmap_primitives.UnsignedInt.to_json mbvb) :: fields···············-emails : (Jmap_core.Jmap_id.t * import_email) list; (** Map of creation id to import object *)············
··········································+in_mailbox_other_than : Jmap_core.Id.t list option; (** Email is in a mailbox other than these *)···············+max_body_value_bytes : Jmap_core.Primitives.UnsignedInt.t option; (** Truncate large body values *)····································
+144
-144
stack/jmap/jmap-mail/jmap_email.mli
+144
-144
stack/jmap/jmap-mail/jmap_email.mli
····························································
····························································
+47
-47
stack/jmap/jmap-mail/jmap_email_submission.ml
+47
-47
stack/jmap/jmap-mail/jmap_email_submission.ml
············delivery_status : (string * DeliveryStatus.t) list option; (** Map of email to delivery status *)······-raise (Jmap_core.Jmap_error.Parse_error "EmailSubmission.Get.request_of_json not yet implemented")···-raise (Jmap_core.Jmap_error.Parse_error "EmailSubmission.Get.response_of_json not yet implemented")-raise (Jmap_core.Jmap_error.Parse_error "EmailSubmission.Changes.request_of_json not yet implemented")-raise (Jmap_core.Jmap_error.Parse_error "EmailSubmission.Changes.response_of_json not yet implemented")-identity_ids : Jmap_core.Jmap_id.t list option; (** Submission uses one of these identities *)-thread_ids : Jmap_core.Jmap_id.t list option; (** Submission is for email in one of these threads *)···-raise (Jmap_core.Jmap_error.Parse_error "EmailSubmission.Query.request_of_json not yet implemented")-raise (Jmap_core.Jmap_error.Parse_error "EmailSubmission.Query.response_of_json not yet implemented")-raise (Jmap_core.Jmap_error.Parse_error "EmailSubmission.QueryChanges.request_of_json not yet implemented")-raise (Jmap_core.Jmap_error.Parse_error "EmailSubmission.QueryChanges.response_of_json not yet implemented")···-set_email_keywords : (Jmap_core.Jmap_id.t * (string * bool) list) option; (** Set keywords on sent email *)-update : (Jmap_core.Jmap_id.t * Jmap_core.Jmap_standard_methods.Set.patch_object) list option;-on_success_update_email : (Jmap_core.Jmap_id.t * on_success) list option; (** Actions to perform on success *)-on_success_destroy_email : Jmap_core.Jmap_id.t list option; (** Email IDs to destroy on success *)···-raise (Jmap_core.Jmap_error.Parse_error "EmailSubmission.Set.request_of_json not yet implemented")-raise (Jmap_core.Jmap_error.Parse_error "EmailSubmission.Set.response_of_json not yet implemented")···
············delivery_status : (string * DeliveryStatus.t) list option; (** Map of email to delivery status *)·········+raise (Jmap_core.Error.Parse_error "EmailSubmission.Get.response_of_json not yet implemented")+raise (Jmap_core.Error.Parse_error "EmailSubmission.Changes.request_of_json not yet implemented")+raise (Jmap_core.Error.Parse_error "EmailSubmission.Changes.response_of_json not yet implemented")+thread_ids : Jmap_core.Id.t list option; (** Submission is for email in one of these threads *)···+raise (Jmap_core.Error.Parse_error "EmailSubmission.Query.request_of_json not yet implemented")+raise (Jmap_core.Error.Parse_error "EmailSubmission.Query.response_of_json not yet implemented")+raise (Jmap_core.Error.Parse_error "EmailSubmission.QueryChanges.request_of_json not yet implemented")+raise (Jmap_core.Error.Parse_error "EmailSubmission.QueryChanges.response_of_json not yet implemented")···+set_email_keywords : (Jmap_core.Id.t * (string * bool) list) option; (** Set keywords on sent email *)+on_success_update_email : (Jmap_core.Id.t * on_success) list option; (** Actions to perform on success *)···+raise (Jmap_core.Error.Parse_error "EmailSubmission.Set.response_of_json not yet implemented")···
+66
-66
stack/jmap/jmap-mail/jmap_email_submission.mli
+66
-66
stack/jmap/jmap-mail/jmap_email_submission.mli
··················
··················
+15
-15
stack/jmap/jmap-mail/jmap_identity.ml
+15
-15
stack/jmap/jmap-mail/jmap_identity.ml
············-raise (Jmap_core.Jmap_error.Parse_error "Identity.Changes.request_of_json not yet implemented")-raise (Jmap_core.Jmap_error.Parse_error "Identity.Changes.response_of_json not yet implemented")······
··················
+9
-9
stack/jmap/jmap-mail/jmap_identity.mli
+9
-9
stack/jmap/jmap-mail/jmap_identity.mli
··················
··················
-11
stack/jmap/jmap-mail/jmap_mail.ml
-11
stack/jmap/jmap-mail/jmap_mail.ml
······
+8
-9
stack/jmap/jmap-mail/jmap_mail.mli
+8
-9
stack/jmap/jmap-mail/jmap_mail.mli
···
···
+65
-65
stack/jmap/jmap-mail/jmap_mailbox.ml
+65
-65
stack/jmap/jmap-mail/jmap_mailbox.ml
······-total_emails : Jmap_core.Jmap_primitives.UnsignedInt.t; (** Total number of emails in mailbox *)-unread_emails : Jmap_core.Jmap_primitives.UnsignedInt.t; (** Number of emails without $seen keyword *)-total_threads : Jmap_core.Jmap_primitives.UnsignedInt.t; (** Total number of threads with emails in mailbox *)-unread_threads : Jmap_core.Jmap_primitives.UnsignedInt.t; (** Number of threads with unread emails in mailbox *)···-let sort_order = Jmap_core.Jmap_primitives.UnsignedInt.of_json (require_field "sortOrder" fields) in-let total_emails = Jmap_core.Jmap_primitives.UnsignedInt.of_json (require_field "totalEmails" fields) in-let unread_emails = Jmap_core.Jmap_primitives.UnsignedInt.of_json (require_field "unreadEmails" fields) in-let total_threads = Jmap_core.Jmap_primitives.UnsignedInt.of_json (require_field "totalThreads" fields) in-let unread_threads = Jmap_core.Jmap_primitives.UnsignedInt.of_json (require_field "unreadThreads" fields) in··················
······+unread_emails : Jmap_core.Primitives.UnsignedInt.t; (** Number of emails without $seen keyword *)+total_threads : Jmap_core.Primitives.UnsignedInt.t; (** Total number of threads with emails in mailbox *)+unread_threads : Jmap_core.Primitives.UnsignedInt.t; (** Number of threads with unread emails in mailbox *)···+let sort_order = Jmap_core.Primitives.UnsignedInt.of_json (require_field "sortOrder" fields) in+let total_emails = Jmap_core.Primitives.UnsignedInt.of_json (require_field "totalEmails" fields) in+let unread_emails = Jmap_core.Primitives.UnsignedInt.of_json (require_field "unreadEmails" fields) in+let total_threads = Jmap_core.Primitives.UnsignedInt.of_json (require_field "totalThreads" fields) in+let unread_threads = Jmap_core.Primitives.UnsignedInt.of_json (require_field "unreadThreads" fields) in··················
+54
-54
stack/jmap/jmap-mail/jmap_mailbox.mli
+54
-54
stack/jmap/jmap-mail/jmap_mailbox.mli
···························
···························
+10
-10
stack/jmap/jmap-mail/jmap_search_snippet.ml
+10
-10
stack/jmap/jmap-mail/jmap_search_snippet.ml
·········-raise (Jmap_core.Jmap_error.Parse_error "SearchSnippet.Get.request_of_json not yet implemented")···-raise (Jmap_core.Jmap_error.Parse_error "SearchSnippet.Get.response_of_json not yet implemented")···
···············
+18
-18
stack/jmap/jmap-mail/jmap_search_snippet.mli
+18
-18
stack/jmap/jmap-mail/jmap_search_snippet.mli
···
···
+8
-8
stack/jmap/jmap-mail/jmap_thread.ml
+8
-8
stack/jmap/jmap-mail/jmap_thread.ml
···-email_ids : Jmap_core.Jmap_id.t list; (** List of email ids in this thread, sorted by date (oldest first) *)············
···+email_ids : Jmap_core.Id.t list; (** List of email ids in this thread, sorted by date (oldest first) *)············
+7
-7
stack/jmap/jmap-mail/jmap_thread.mli
+7
-7
stack/jmap/jmap-mail/jmap_thread.mli
···
···
+13
-13
stack/jmap/jmap-mail/jmap_vacation_response.ml
+13
-13
stack/jmap/jmap-mail/jmap_vacation_response.ml
·········-raise (Jmap_core.Jmap_error.Parse_error "VacationResponse.Get.request_of_json not yet implemented")···-raise (Jmap_core.Jmap_error.Parse_error "VacationResponse.Get.response_of_json not yet implemented")···-raise (Jmap_core.Jmap_error.Parse_error "VacationResponse.Set.request_of_json not yet implemented")-raise (Jmap_core.Jmap_error.Parse_error "VacationResponse.Set.response_of_json not yet implemented")···-raise (Jmap_core.Jmap_error.Parse_error "VacationResponse.Parser.of_json not yet implemented")-raise (Jmap_core.Jmap_error.Parse_error "VacationResponse.Parser.to_json not yet implemented")
············+raise (Jmap_core.Error.Parse_error "VacationResponse.Get.response_of_json not yet implemented")···+raise (Jmap_core.Error.Parse_error "VacationResponse.Set.request_of_json not yet implemented")+raise (Jmap_core.Error.Parse_error "VacationResponse.Set.response_of_json not yet implemented")···
+13
-13
stack/jmap/jmap-mail/jmap_vacation_response.mli
+13
-13
stack/jmap/jmap-mail/jmap_vacation_response.mli
·········
·········
+34
stack/jmap/jmap.opam
+34
stack/jmap/jmap.opam
···
···+"Ergonomic, unified interface to the complete JMAP library (RFC 8620, RFC 8621). This is the recommended entry point for most users."
+5
stack/jmap/lib/dune
+5
stack/jmap/lib/dune
+94
stack/jmap/lib/jmap.ml
+94
stack/jmap/lib/jmap.ml
···
···
+125
stack/jmap/lib/jmap.mli
+125
stack/jmap/lib/jmap.mli
···
···
+5
stack/jmap/test/dune
+5
stack/jmap/test/dune
+28
-28
stack/jmap/test/test_fastmail.ml
+28
-28
stack/jmap/test/test_fastmail.ml
············
············
+264
-264
stack/jmap/test/test_jmap.ml
+264
-264
stack/jmap/test/test_jmap.ml
······-check string "INBOX id" "mb001" (Jmap_core.Jmap_id.to_string (Jmap_mail.Jmap_mailbox.id inbox));-check string "INBOX role" "inbox" (match Jmap_mail.Jmap_mailbox.role inbox with Some r -> r | None -> "");-check int "INBOX sortOrder" 10 (Jmap_core.Jmap_primitives.UnsignedInt.to_int (Jmap_mail.Jmap_mailbox.sort_order inbox));-check int "INBOX totalEmails" 1523 (Jmap_core.Jmap_primitives.UnsignedInt.to_int (Jmap_mail.Jmap_mailbox.total_emails inbox));-check int "INBOX unreadEmails" 42 (Jmap_core.Jmap_primitives.UnsignedInt.to_int (Jmap_mail.Jmap_mailbox.unread_emails inbox));-check int "INBOX totalThreads" 987 (Jmap_core.Jmap_primitives.UnsignedInt.to_int (Jmap_mail.Jmap_mailbox.total_threads inbox));-check int "INBOX unreadThreads" 35 (Jmap_core.Jmap_primitives.UnsignedInt.to_int (Jmap_mail.Jmap_mailbox.unread_threads inbox));-check bool "INBOX mayReadItems" true (Jmap_mail.Jmap_mailbox.Rights.may_read_items inbox_rights);-check bool "INBOX mayAddItems" true (Jmap_mail.Jmap_mailbox.Rights.may_add_items inbox_rights);-check bool "INBOX mayRemoveItems" true (Jmap_mail.Jmap_mailbox.Rights.may_remove_items inbox_rights);-check bool "INBOX maySetKeywords" true (Jmap_mail.Jmap_mailbox.Rights.may_set_keywords inbox_rights);-check bool "INBOX mayCreateChild" true (Jmap_mail.Jmap_mailbox.Rights.may_create_child inbox_rights);-check string "Sent id" "mb002" (Jmap_core.Jmap_id.to_string (Jmap_mail.Jmap_mailbox.id sent));-check string "Sent role" "sent" (match Jmap_mail.Jmap_mailbox.role sent with Some r -> r | None -> "");-check int "Sent sortOrder" 20 (Jmap_core.Jmap_primitives.UnsignedInt.to_int (Jmap_mail.Jmap_mailbox.sort_order sent));-check string "Work id" "mb005" (Jmap_core.Jmap_id.to_string (Jmap_mail.Jmap_mailbox.id work));-check int "Work totalEmails" 342 (Jmap_core.Jmap_primitives.UnsignedInt.to_int (Jmap_mail.Jmap_mailbox.total_emails work));-check bool "Created mailbox parentId is None" true (Jmap_mail.Jmap_mailbox.parent_id mailbox = None);-check int "Created mailbox sortOrder" 60 (Jmap_core.Jmap_primitives.UnsignedInt.to_int (Jmap_mail.Jmap_mailbox.sort_order mailbox));-check string "Created mailbox ID" "mb020" (Jmap_core.Jmap_id.to_string (Jmap_mail.Jmap_mailbox.id mailbox));-check int "Created mailbox totalEmails" 0 (Jmap_core.Jmap_primitives.UnsignedInt.to_int (Jmap_mail.Jmap_mailbox.total_emails mailbox));-check int "Created mailbox unreadEmails" 0 (Jmap_core.Jmap_primitives.UnsignedInt.to_int (Jmap_mail.Jmap_mailbox.unread_emails mailbox));-check bool "Created mailbox mayRename" true (Jmap_mail.Jmap_mailbox.Rights.may_rename rights);-check bool "Not created is None" true (Jmap_core.Jmap_standard_methods.Set.not_created resp = None);-check bool "Not updated is None" true (Jmap_core.Jmap_standard_methods.Set.not_updated resp = None);-check bool "Not destroyed is None" true (Jmap_core.Jmap_standard_methods.Set.not_destroyed resp = None)···-check string "Email 1 ID" "e001" (Jmap_core.Jmap_id.to_string (Jmap_mail.Jmap_email.id email1));-check string "Email 1 thread ID" "t001" (Jmap_core.Jmap_id.to_string (Jmap_mail.Jmap_email.thread_id email1));···-check string "Email 2 ID" "e002" (Jmap_core.Jmap_id.to_string (Jmap_mail.Jmap_email.id email2));···-check string "Text part ID" "1" (Option.get (Jmap_mail.Jmap_email.BodyPart.part_id text_part));-(Jmap_core.Jmap_primitives.UnsignedInt.to_int (Jmap_mail.Jmap_email.BodyPart.size text_part));-check string "HTML part ID" "2" (Option.get (Jmap_mail.Jmap_email.BodyPart.part_id html_part));-(Jmap_core.Jmap_primitives.UnsignedInt.to_int (Jmap_mail.Jmap_email.BodyPart.size html_part));-(Jmap_core.Jmap_primitives.UnsignedInt.to_int (Jmap_mail.Jmap_email.BodyPart.size attach_part));···-check string "Created email ID" "e101" (Jmap_core.Jmap_id.to_string (Jmap_mail.Jmap_email.id email));-check string "First email ID" "e102" (Jmap_core.Jmap_id.to_string (Jmap_mail.Jmap_email.id email1));-check string "Second email ID" "e103" (Jmap_core.Jmap_id.to_string (Jmap_mail.Jmap_email.id email2))-(Jmap_core.Jmap_primitives.UnsignedInt.to_int (Jmap_mail.Jmap_email.BodyPart.size body_part));
······+check string "INBOX role" "inbox" (match Jmap_mail.Mailbox.role inbox with Some r -> r | None -> "");+check int "INBOX sortOrder" 10 (Jmap_core.Primitives.UnsignedInt.to_int (Jmap_mail.Mailbox.sort_order inbox));+check int "INBOX totalEmails" 1523 (Jmap_core.Primitives.UnsignedInt.to_int (Jmap_mail.Mailbox.total_emails inbox));+check int "INBOX unreadEmails" 42 (Jmap_core.Primitives.UnsignedInt.to_int (Jmap_mail.Mailbox.unread_emails inbox));+check int "INBOX totalThreads" 987 (Jmap_core.Primitives.UnsignedInt.to_int (Jmap_mail.Mailbox.total_threads inbox));+check int "INBOX unreadThreads" 35 (Jmap_core.Primitives.UnsignedInt.to_int (Jmap_mail.Mailbox.unread_threads inbox));+check bool "INBOX mayRemoveItems" true (Jmap_mail.Mailbox.Rights.may_remove_items inbox_rights);+check bool "INBOX maySetKeywords" true (Jmap_mail.Mailbox.Rights.may_set_keywords inbox_rights);+check bool "INBOX mayCreateChild" true (Jmap_mail.Mailbox.Rights.may_create_child inbox_rights);+check string "Sent role" "sent" (match Jmap_mail.Mailbox.role sent with Some r -> r | None -> "");+check int "Sent sortOrder" 20 (Jmap_core.Primitives.UnsignedInt.to_int (Jmap_mail.Mailbox.sort_order sent));+check int "Work totalEmails" 342 (Jmap_core.Primitives.UnsignedInt.to_int (Jmap_mail.Mailbox.total_emails work));+check bool "Created mailbox parentId is None" true (Jmap_mail.Mailbox.parent_id mailbox = None);+check int "Created mailbox sortOrder" 60 (Jmap_core.Primitives.UnsignedInt.to_int (Jmap_mail.Mailbox.sort_order mailbox));+check string "Created mailbox ID" "mb020" (Jmap_core.Id.to_string (Jmap_mail.Mailbox.id mailbox));+check int "Created mailbox totalEmails" 0 (Jmap_core.Primitives.UnsignedInt.to_int (Jmap_mail.Mailbox.total_emails mailbox));+check int "Created mailbox unreadEmails" 0 (Jmap_core.Primitives.UnsignedInt.to_int (Jmap_mail.Mailbox.unread_emails mailbox));+check bool "Not created is None" true (Jmap_core.Standard_methods.Set.not_created resp = None);+check bool "Not updated is None" true (Jmap_core.Standard_methods.Set.not_updated resp = None);+check bool "Not destroyed is None" true (Jmap_core.Standard_methods.Set.not_destroyed resp = None)···+check string "Email 1 thread ID" "t001" (Jmap_core.Id.to_string (Jmap_mail.Email.thread_id email1));·········
+69
stack/jmap/test/test_unified_api.ml
+69
stack/jmap/test/test_unified_api.ml
···
···