1mod account;
4mod billing;
5mod config;
6mod service;
7
8use std::error::Error;
9use std::fmt::{self, Debug, Display, Formatter};
10
11#[cfg(feature = "backend")]
12use actix_web::{body::BoxBody, HttpResponse, ResponseError};
13
14use serde::{Deserialize, Serialize};
15use thiserror::Error;
16
17use crate::domain::meta::MetaKind;
18use crate::media::MediaGroupKind;
19
20pub use account::AccountError;
21pub use billing::BillingError;
22pub use config::ConfigError;
23pub use service::{ServiceError, ServiceKindError};
24
25#[derive(Serialize, Deserialize, Debug, Default, thiserror::Error)]
27#[error("EmptyError")]
28pub struct EmptyError {}
29
30#[derive(Serialize, Deserialize, Debug)]
32pub struct MetadataNotFound {
33 pub id: Option<uuid::Uuid>,
35 pub index: Option<i16>,
37 pub kind: MetaKind,
39 pub media_group_kind: Option<MediaGroupKind>,
42}
43impl Display for MetadataNotFound {
44 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
45 write!(f, "Metadata not found")
46 }
47}
48impl Error for MetadataNotFound {}
49
50pub trait IntoAnyhow<T> {
52 fn into_anyhow(self) -> anyhow::Result<T>;
58}
59
60impl<T, E> IntoAnyhow<T> for Result<T, E>
62where
63 E: Error + Send + Sync + 'static + Into<anyhow::Error>,
64{
65 fn into_anyhow(self) -> anyhow::Result<T> {
66 self.map_err(Into::into)
67 }
68}
69
70#[derive(Debug, Error)]
73pub enum TransientError<T: Debug + Display> {
74 #[error("API error {0}")]
76 Error(T),
77 #[error("")]
79 Missing,
80}
81
82impl<T: Debug + Display> Default for TransientError<T> {
83 fn default() -> Self {
84 Self::Missing
85 }
86}
87
88impl<T: Debug + Display> From<T> for TransientError<T> {
89 fn from(value: T) -> Self {
90 Self::Error(value)
91 }
92}
93
94#[cfg(feature = "backend")]
95impl<T> TransientError<T>
96where
97 T: ResponseError + Debug + Display,
98{
99 #[allow(missing_docs)]
100 fn status_code(&self) -> http::StatusCode {
101 match self {
102 Self::Error(inner) => inner.status_code(),
103 Self::Missing => http::StatusCode::INTERNAL_SERVER_ERROR,
104 }
105 }
106}
107
108#[allow(missing_docs)]
109#[derive(Debug, Serialize, Deserialize)]
110#[serde(untagged)]
111pub enum ApiError<T> {
112 ApiError(T),
113 ConfigError(ConfigError),
114}
115
116#[cfg(feature = "backend")]
117impl<T> ResponseError for ApiError<T>
118where
119 T: ResponseError + Serialize,
120{
121 fn status_code(&self) -> http::StatusCode {
122 match self {
123 Self::ConfigError(error) => error.status_code(),
124 Self::ApiError(error) => error.status_code(),
125 }
126 }
127
128 fn error_response(&self) -> HttpResponse<BoxBody> {
129 HttpResponse::build(self.status_code()).json(self)
130 }
131}
132
133impl<T: Display> Display for ApiError<T> {
134 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
135 match self {
136 Self::ConfigError(error) => write!(f, "{error}"),
137 Self::ApiError(error) => write!(f, "{error}"),
138 }
139 }
140}