1use crate::types::ChalkError;
8
9#[derive(Debug, thiserror::Error)]
11pub enum ChalkClientError {
12 #[error("configuration error: {0}")]
14 Config(String),
15
16 #[error("authentication error: {0}")]
18 Auth(String),
19
20 #[error("HTTP error: {0}")]
23 Http(#[from] reqwest::Error),
24
25 #[error("API error (status {status}): {message}")]
29 Api {
30 status: u16,
32 message: String,
34 },
35
36 #[error("JSON error: {0}")]
38 Json(#[from] serde_json::Error),
39
40 #[error("YAML error: {0}")]
42 Yaml(#[from] serde_yaml::Error),
43
44 #[error("Arrow error: {0}")]
47 Arrow(#[from] arrow::error::ArrowError),
48
49 #[error("I/O error: {0}")]
51 Io(#[from] std::io::Error),
52
53 #[error("gRPC error: {0}")]
55 Grpc(Box<tonic::Status>),
56
57 #[error("gRPC transport error: {0}")]
59 GrpcTransport(#[from] tonic::transport::Error),
60
61 #[error("server returned {} error(s): {}", .0.len(), .0.first().map(|e| e.message.as_str()).unwrap_or("unknown"))]
63 ServerErrors(Vec<ChalkError>),
64}
65
66impl From<tonic::Status> for ChalkClientError {
67 fn from(status: tonic::Status) -> Self {
68 ChalkClientError::Grpc(Box::new(status))
69 }
70}
71
72pub type Result<T> = std::result::Result<T, ChalkClientError>;
75
76#[cfg(test)]
77mod tests {
78 use super::*;
79
80 #[test]
81 fn test_error_display() {
82 let err = ChalkClientError::Config("missing client_id".into());
83 assert!(err.to_string().contains("missing client_id"));
84
85 let err = ChalkClientError::Api {
86 status: 401,
87 message: "unauthorized".into(),
88 };
89 assert!(err.to_string().contains("401"));
90 assert!(err.to_string().contains("unauthorized"));
91 }
92
93 #[test]
94 fn test_server_errors_display() {
95 let errors = vec![
96 ChalkError {
97 code: "RESOLVER_FAILED".into(),
98 category: "FIELD".into(),
99 message: "resolver timed out".into(),
100 feature: Some("user.age".into()),
101 resolver: Some("get_user_age".into()),
102 exception: None,
103 },
104 ChalkError {
105 code: "RESOLVER_FAILED".into(),
106 category: "FIELD".into(),
107 message: "another error".into(),
108 feature: None,
109 resolver: None,
110 exception: None,
111 },
112 ];
113 let err = ChalkClientError::ServerErrors(errors);
114 let msg = err.to_string();
115 assert!(msg.contains("2 error(s)"));
116 assert!(msg.contains("resolver timed out"));
117 }
118}