My agentic slop goes here. Not intended for anyone else!
1(** JSON API Helpers for Requests 2 3 This module provides high-level combinators for working with JSON APIs, 4 reducing boilerplate when building API clients. 5 6 {2 Example Usage} 7 8 {[ 9 open Requests_json_api 10 11 (* Define a Jsont codec for your type *) 12 type user = { id : int; name : string } 13 14 let user_jsont = 15 Jsont.Object.map (fun id name -> { id; name }) 16 |> Jsont.Object.mem "id" Jsont.int ~enc:(fun u -> u.id) 17 |> Jsont.Object.mem "name" Jsont.string ~enc:(fun u -> u.name) 18 |> Jsont.Object.finish 19 20 let users_jsont = Jsont.list user_jsont 21 22 let fetch_users session = 23 get_json_exn session (base_url / "users") users_jsont 24 ]} 25*) 26 27(** {1 JSON Request Helpers} *) 28 29val get_json_exn : (_ Eio.Time.clock, _ Eio.Net.t) Requests.t -> string -> 'a Jsont.t -> 'a 30(** [get_json_exn session url decoder] makes a GET request, checks status is 2xx, 31 reads and parses JSON body using the provided Jsont decoder. 32 Raises [Failure] on any error (HTTP, network, or JSON parse). *) 33 34val get_json : (_ Eio.Time.clock, _ Eio.Net.t) Requests.t -> string -> 'a Jsont.t -> 35 ('a, [> `Http of int * string | `Json_error of string]) result 36(** Like [get_json_exn] but returns [Result] instead of raising exceptions. 37 Returns [Ok parsed_value] on success, or [Error] with details on failure. *) 38 39val post_json : (_ Eio.Time.clock, _ Eio.Net.t) Requests.t -> string -> 'a Jsont.t -> 'a -> Requests.Response.t 40(** [post_json session url codec value] encodes [value] using the Jsont codec and POSTs it to the URL. 41 Returns the raw response for custom handling. *) 42 43val post_json_exn : (_ Eio.Time.clock, _ Eio.Net.t) Requests.t -> string -> 'a Jsont.t -> 'a -> string 44(** Like [post_json] but checks status is 2xx and returns the response body as a string. 45 Raises [Failure] on non-2xx status. *) 46 47val post_json_result : (_ Eio.Time.clock, _ Eio.Net.t) Requests.t -> string -> 'a Jsont.t -> 'a -> 48 (string, int * string) result 49(** Like [post_json_exn] but returns [Result] instead of raising. 50 [Ok body] on 2xx status, [Error (status, body)] otherwise. *) 51 52val post_json_decode_exn : (_ Eio.Time.clock, _ Eio.Net.t) Requests.t -> string -> 53 req:'a Jsont.t -> 'a -> resp:'b Jsont.t -> 'b 54(** [post_json_decode_exn session url ~req req_value ~resp] encodes [req_value] using the [req] codec, 55 POSTs it to the URL, checks status is 2xx, and decodes the response using the [resp] codec. 56 Raises [Failure] on any error. *) 57 58val post_json_decode : (_ Eio.Time.clock, _ Eio.Net.t) Requests.t -> string -> 59 req:'a Jsont.t -> 'a -> resp:'b Jsont.t -> 60 ('b, [> `Http of int * string | `Json_error of string]) result 61(** Like [post_json_decode_exn] but returns [Result] instead of raising. *) 62 63val put_json_exn : (_ Eio.Time.clock, _ Eio.Net.t) Requests.t -> string -> 'a Jsont.t -> 'a -> string 64(** [put_json_exn session url codec value] encodes [value] and PUTs it to the URL. 65 Returns response body. Raises [Failure] on non-2xx status. *) 66 67val put_json_decode_exn : (_ Eio.Time.clock, _ Eio.Net.t) Requests.t -> string -> 68 req:'a Jsont.t -> 'a -> resp:'b Jsont.t -> 'b 69(** Like [post_json_decode_exn] but uses PUT method. *) 70 71val patch_json_exn : (_ Eio.Time.clock, _ Eio.Net.t) Requests.t -> string -> 'a Jsont.t -> 'a -> string 72(** [patch_json_exn session url codec value] encodes [value] and PATCHes it to the URL. 73 Returns response body. Raises [Failure] on non-2xx status. *) 74 75val delete_json_exn : (_ Eio.Time.clock, _ Eio.Net.t) Requests.t -> string -> string 76(** [delete_json_exn session url] makes a DELETE request. 77 Returns response body. Raises [Failure] on non-2xx status. *) 78 79(** {1 JSON Parsing Helpers} *) 80 81val parse_json : 'a Jsont.t -> string -> 'a 82(** [parse_json decoder body_str] parses a JSON string using the provided Jsont decoder. 83 Raises exception on parse error. *) 84 85val parse_json_result : 'a Jsont.t -> string -> ('a, string) result 86(** Like [parse_json] but returns [Result] on parse error instead of raising. *) 87 88(** {1 Low-Level Helpers} *) 89 90val read_body : Requests.Response.t -> string 91(** [read_body response] reads the entire response body as a string. 92 Equivalent to [Requests.Response.body response |> Eio.Flow.read_all] *) 93 94val get_result : (_ Eio.Time.clock, _ Eio.Net.t) Requests.t -> string -> (string, int * string) result 95(** [get_result session url] makes a GET request and returns the result. 96 Returns [Ok body] on 2xx status, [Error (status, body)] otherwise. *) 97 98val check_2xx : Requests.Response.t -> (string, int * string) result 99(** [check_2xx response] checks if the response status is 2xx. 100 Returns [Ok body] if status is 2xx, [Error (status, body)] otherwise. *) 101 102val check_ok : Requests.Response.t -> (string, int * string) result 103(** [check_ok response] checks if the response status is exactly 200. 104 Returns [Ok body] if status is 200, [Error (status, body)] otherwise. *) 105 106(** {1 URL Helpers} *) 107 108val ( / ) : string -> string -> string 109(** [base_url / path] joins base URL and path, handling trailing/leading slashes. 110 111 Example: ["https://api.com" / "users" / "123" = "https://api.com/users/123"] *) 112 113val make_url : string -> string -> string 114(** [make_url base_url path] is the function form of the [/] operator. *) 115 116(** {1 Result Composition} *) 117 118module Syntax : sig 119 val ( let* ) : ('a, 'e) result -> ('a -> ('b, 'e) result) -> ('b, 'e) result 120 (** Result bind operator for chaining operations *) 121 122 val ( let+ ) : ('a, 'e) result -> ('a -> 'b) -> ('b, 'e) result 123 (** Result map operator *) 124 125 val ( and* ) : ('a, 'e) result -> ('b, 'e) result -> ('a * 'b, 'e) result 126 (** Result product for parallel operations *) 127 128 val ( and+ ) : ('a, 'e) result -> ('b, 'e) result -> ('a * 'b, 'e) result 129 (** Result product for parallel operations (alias) *) 130end 131 132(** {1 Error Handling} *) 133 134val or_fail : ('a, [< `Http of int * string | `Json_error of string]) result -> 'a 135(** [or_fail result] unwraps a [Result] or raises [Failure] with an error message. 136 Useful for converting Result-based APIs to exception-based code. *) 137 138val or_fail_with : string -> ('a, [< `Http of int * string | `Json_error of string]) result -> 'a 139(** Like [or_fail] but prepends a custom error prefix to the failure message. *)