123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107(** Polymorphic error types for composable error handling.
This module provides extensible error types using polymorphic variants,
allowing different parts of the codebase to define their own error cases
while maintaining composability. *)(** {1 Base Error Types} *)typehttp_error={status:int;body:string;message:string}(** HTTP-related errors. *)typeparse_error={context:string;message:string}(** JSON parsing errors. *)typenetwork_error={message:string}(** Network/connection errors. *)typerate_limit_error={retry_after:float;route_key:string}(** Rate limiting errors. *)(** {1 Polymorphic Error Variants} *)typehttp_errors=[`Http_errorofhttp_error|`Parse_errorofparse_error|`Network_errorofnetwork_error](** Core HTTP client errors. *)typerate_limit_errors=[`Rate_limitedofrate_limit_error](** Rate limiting errors. *)typeapi_errors=[http_errors|rate_limit_errors](** All API errors (HTTP + rate limiting). *)(** {1 Error Constructors} *)lethttp_error~status~body~message:[>`Http_errorofhttp_error]=`Http_error{status;body;message}letparse_error~context~message:[>`Parse_errorofparse_error]=`Parse_error{context;message}letnetwork_error~message:[>`Network_errorofnetwork_error]=`Network_error{message}letrate_limited~retry_after~route_key:[>`Rate_limitedofrate_limit_error]=`Rate_limited{retry_after;route_key}(** {1 Error Formatting} *)lethttp_error_to_string{status;message;_}=Printf.sprintf"HTTP %d: %s"statusmessageletparse_error_to_string{context;message}=Printf.sprintf"Parse error in %s: %s"contextmessageletnetwork_error_to_string{message}=Printf.sprintf"Network error: %s"messageletrate_limit_error_to_string{retry_after;route_key}=Printf.sprintf"Rate limited on %s, retry after %.2fs"route_keyretry_after(** Convert HTTP errors to string. *)lethttp_errors_to_string:http_errors->string=function|`Http_errore->http_error_to_stringe|`Parse_errore->parse_error_to_stringe|`Network_errore->network_error_to_stringe(** Convert API errors (including rate limiting) to string. *)letapi_errors_to_string:api_errors->string=function|`Http_errore->http_error_to_stringe|`Parse_errore->parse_error_to_stringe|`Network_errore->network_error_to_stringe|`Rate_limitede->rate_limit_error_to_stringe(** {1 Pretty Printers} *)letpp_http_errorsfmte=Format.fprintffmt"%s"(http_errors_to_stringe)letpp_api_errorsfmte=Format.fprintffmt"%s"(api_errors_to_stringe)(** {1 Error Parsing Helpers} *)(** Parse an HTTP error response body to extract error message. *)letparse_http_error~statusbody=letmessage=tryletjson=Yojson.Safe.from_stringbodyinmatchjsonwith|`Assocfields->(matchList.assoc_opt"error"fieldswith|Some(`Stringmsg)->msg|_->body)|_->bodywith_->bodyinhttp_error~status~body~message(** {1 Result Helpers} *)(** Map over the error type of a result. *)letmap_errorf=functionOkx->Okx|Errore->Error(fe)(** Lift an http_errors result to an api_errors result. *)letlift_http_error:('a,http_errors)result->('a,[>http_errors])result=funr->map_error(fune->(e:>api_errors))r