OpenAPI generator for OCaml with Requests/Eio/Jsont
1(*---------------------------------------------------------------------------
2 Copyright (c) 2025 Anil Madhavapeddy. All rights reserved.
3 SPDX-License-Identifier: ISC
4 ---------------------------------------------------------------------------*)
5
6(** NestJS-style API error handling.
7
8 NestJS/Express applications return errors in a standard format:
9 {[
10 {
11 "message": "Missing required permission: person.read",
12 "error": "Forbidden",
13 "statusCode": 403,
14 "correlationId": "koskgk9d"
15 }
16 ]}
17
18 This module provides types and utilities for parsing and handling
19 these errors in a structured way.
20
21 {2 Usage}
22
23 {[
24 match Immich.People.get_all_people client () with
25 | people -> ...
26 | exception Openapi.Runtime.Api_error e ->
27 match Openapi.Nestjs.of_api_error e with
28 | Some nestjs_error ->
29 Fmt.epr "Error: %s (correlation: %s)@."
30 nestjs_error.message
31 (Option.value ~default:"none" nestjs_error.correlation_id)
32 | None ->
33 (* Not a NestJS error, use raw body *)
34 Fmt.epr "Error: %s@." e.body
35 ]}
36*)
37
38(** {1 Error Types} *)
39
40(** A structured NestJS HTTP exception. *)
41type t = {
42 status_code : int;
43 (** HTTP status code (e.g., 403, 404, 500). *)
44
45 error : string option;
46 (** Error category (e.g., "Forbidden", "Not Found", "Internal Server Error"). *)
47
48 message : string;
49 (** Human-readable error message. Can be a single string or concatenated
50 from an array of validation messages. *)
51
52 correlation_id : string option;
53 (** Request correlation ID for debugging/support. *)
54}
55
56(** {1 JSON Codec} *)
57
58val jsont : t Jsont.t
59(** Jsont codec for NestJS errors. *)
60
61(** {1 Parsing} *)
62
63val of_string : string -> t option
64(** Parse a JSON string into a NestJS error.
65 Returns [None] if the string is not valid NestJS error JSON. *)
66
67val of_api_error : Openapi_runtime.api_error -> t option
68(** Parse an {!Openapi_runtime.api_error} into a structured NestJS error.
69 Returns [None] if the error body is not valid NestJS error JSON. *)
70
71(** {1 Convenience Functions} *)
72
73val is_auth_error : t -> bool
74(** Check if this is a permission/authorization error (401 or 403). *)
75
76val is_not_found : t -> bool
77(** Check if this is a "not found" error (404). *)
78
79val is_validation_error : t -> bool
80(** Check if this is a validation error (400 with message array). *)
81
82val is_server_error : t -> bool
83(** Check if this is a server error (5xx). *)
84
85(** {1 Pretty Printing} *)
86
87val pp : Format.formatter -> t -> unit
88(** Pretty-print a NestJS error. *)
89
90val to_string : t -> string
91(** Convert to a human-readable string. *)
92
93(** {1 Exception Handling} *)
94
95exception Error of t
96(** Exception for NestJS-specific errors.
97 Use this when you want to distinguish NestJS errors from generic API errors. *)
98
99val raise_if_nestjs : Openapi_runtime.api_error -> 'a
100(** Handle an {!Openapi_runtime.api_error}, converting it to a NestJS error
101 if possible.
102
103 @raise Error if the error body parses as a NestJS error
104 @raise Openapi_runtime.Api_error if parsing fails (re-raises original) *)