Skip to main content

redmine_api/
lib.rs

1#![expect(
2    single_use_lifetimes,
3    reason = "endpoint structs hold Cow<'a, str> for cheap borrowed string parameters; the lifetime appears once in the struct but propagates to every call site"
4)]
5#![expect(
6    clippy::module_name_repetitions,
7    reason = "Redmine REST resource types share their module's name (e.g. ListIssues in api::issues) for self-documenting public re-exports"
8)]
9#![expect(
10    clippy::future_not_send,
11    reason = "the async client is not Send by design; the underlying reqwest::Client is shared via Arc"
12)]
13#![cfg_attr(
14    test,
15    expect(
16        unreachable_pub,
17        clippy::unwrap_used,
18        clippy::panic,
19        clippy::indexing_slicing,
20        clippy::arithmetic_side_effects,
21        clippy::print_stderr,
22        reason = "tests use panicking patterns and helper items idiomatically"
23    )
24)]
25#![doc = include_str!("../README.md")]
26
27pub mod api;
28/// re-export the reqwest crate so users of redmine-api can use the exact
29/// dependency version we use for constructing clients
30pub use reqwest;
31
32use thiserror::Error;
33
34/// Error type for redmine_api
35#[derive(Debug, Error)]
36pub enum Error {
37    /// An error occurred in the reqwest library (HTTP)
38    #[error("reqwest error: {0}")]
39    ReqwestError(#[from] reqwest::Error),
40    /// An error occurred when serializing/deserializing JSON
41    #[error("error in json serialization/deserialization: {0}")]
42    SerdeJsonError(#[from] serde_json::Error),
43    /// An error occurred when parsing a URL
44    #[error("error when parsing URL: {0}")]
45    UrlParseError(#[from] url::ParseError),
46    /// An error occurred when reading configuration from environment variables
47    #[error("error when reading environment variables: {0}")]
48    EnvyError(#[from] envy::Error),
49    /// Response body was empty so we can not deserialize it as JSON
50    #[error("empty response body with status: {0}")]
51    EmptyResponseBody(reqwest::StatusCode),
52    /// Response body was valid JSON but not an object
53    #[error("JSON but non-object response body with status: {0}")]
54    NonObjectResponseBody(reqwest::StatusCode),
55    /// Missing response pagination key (total_counts, offset, limit or the wrapper key)
56    #[error("JSON wrapper pagination key missing: {0}")]
57    PaginationKeyMissing(String),
58    /// Response pagination key has the wrong type (total_counts, offset, limit)
59    #[error("JSON wrapper pagination key has an unexpected type: {0}")]
60    PaginationKeyHasWrongType(String),
61    /// Parsing a time string to a time object (OffsetDateTime) failed
62    #[error("Parsing string {0} to time object failed")]
63    TimeParseError(String, time::error::Parse),
64    /// Error reading a file we are supposed to upload
65    #[error("Error when opening or reading file {0} to upload: {1}")]
66    UploadFileError(std::path::PathBuf, std::io::Error),
67    /// HTTP Error response
68    #[error("HTTP Error response: {0}")]
69    HttpErrorResponse(reqwest::StatusCode),
70}