integrationos_domain/domain/error/
mod.rs

1pub mod axum_error;
2
3use crate::prelude::StringExt;
4use http::StatusCode;
5use mongodb::error::WriteFailure;
6use serde::Serialize;
7use serde_json::{json, Value};
8use std::convert::AsRef;
9use std::{
10    error::Error as StdError,
11    fmt::{Debug, Display, Formatter, Result as FmtResult},
12    sync::Arc,
13};
14use strum::AsRefStr;
15use thiserror::Error as ThisError;
16
17pub trait ErrorMeta {
18    fn code(&self) -> ErrorCode;
19    fn key(&self) -> ErrorKey;
20    fn message(&self) -> ErrorMessage;
21    fn meta(&self) -> Option<Value>;
22}
23
24#[derive(Debug, Clone, Hash, Eq, PartialEq, Ord, PartialOrd, Serialize)]
25pub struct ErrorCode(u16);
26
27impl ErrorCode {
28    pub fn as_u16(&self) -> u16 {
29        self.0
30    }
31}
32
33impl Display for ErrorCode {
34    fn fmt(&self, f: &mut Formatter<'_>) -> FmtResult {
35        write!(f, "{}", self.0)
36    }
37}
38
39#[derive(Debug, Clone, Hash, Eq, PartialEq, Ord, PartialOrd, Serialize)]
40pub struct ErrorKey(String);
41
42impl ErrorKey {
43    pub fn internal(key: &str, subtype: Option<&str>) -> Self {
44        if let Some(subtype) = subtype {
45            ErrorKey(format!("err::internal::{}::{}", key, subtype))
46        } else {
47            ErrorKey(format!("err::internal::{}", key))
48        }
49    }
50
51    pub fn application(key: &str, subtype: Option<&str>) -> Self {
52        if let Some(subtype) = subtype {
53            ErrorKey(format!("err::application::{}::{}", key, subtype))
54        } else {
55            ErrorKey(format!("err::application::{}", key))
56        }
57    }
58}
59
60impl Display for ErrorKey {
61    fn fmt(&self, f: &mut Formatter<'_>) -> FmtResult {
62        write!(f, "{}", self.0)
63    }
64}
65
66#[derive(Debug, Clone, Hash, Eq, PartialEq, Ord, PartialOrd, Serialize)]
67pub struct ErrorMessage(String);
68
69impl AsRef<str> for ErrorMessage {
70    fn as_ref(&self) -> &str {
71        &self.0
72    }
73}
74
75impl Display for ErrorMessage {
76    fn fmt(&self, f: &mut Formatter<'_>) -> FmtResult {
77        write!(f, "{}", self.0)
78    }
79}
80
81#[derive(ThisError, Clone, Eq, PartialEq, Serialize, AsRefStr)]
82#[serde(rename_all = "camelCase")]
83#[strum(serialize_all = "PascalCase")]
84pub enum InternalError {
85    #[error("An unknown error occurred: {}", .message)]
86    UnknownError {
87        message: String,
88        subtype: Option<String>,
89        meta: Option<Value>,
90    },
91    #[error("A unique field violation occurred: {}", .message)]
92    UniqueFieldViolation {
93        message: String,
94        subtype: Option<String>,
95        meta: Option<Value>,
96    },
97    #[error("A timeout occurred: {}", .message)]
98    Timeout {
99        message: String,
100        subtype: Option<String>,
101        meta: Option<Value>,
102    },
103    #[error("A connection error occurred: {}", .message)]
104    ConnectionError {
105        message: String,
106        subtype: Option<String>,
107        meta: Option<Value>,
108    },
109    #[error("Entity not found: {}", .message)]
110    KeyNotFound {
111        message: String,
112        subtype: Option<String>,
113        meta: Option<Value>,
114    },
115    #[error("Argument provided is invalid: {}", .message)]
116    InvalidArgument {
117        message: String,
118        subtype: Option<String>,
119        meta: Option<Value>,
120    },
121    #[error("An error while performing an IO operation: {}", .message)]
122    IOErr {
123        message: String,
124        subtype: Option<String>,
125        meta: Option<Value>,
126    },
127    #[error("Encription error: {}", .message)]
128    EncryptionError {
129        message: String,
130        subtype: Option<String>,
131        meta: Option<Value>,
132    },
133    #[error("Decryption error: {}", .message)]
134    DecryptionError {
135        message: String,
136        subtype: Option<String>,
137        meta: Option<Value>,
138    },
139    #[error("Configuration error: {}", .message)]
140    ConfigurationError {
141        message: String,
142        subtype: Option<String>,
143        meta: Option<Value>,
144    },
145    #[error("Serialization error: {}", .message)]
146    SerializeError {
147        message: String,
148        subtype: Option<String>,
149        meta: Option<Value>,
150    },
151    #[error("Deserialization error: {}", .message)]
152    DeserializeError {
153        message: String,
154        subtype: Option<String>,
155        meta: Option<Value>,
156    },
157    #[error("An error occurred running the javascript function: {}", .message)]
158    ScriptError {
159        message: String,
160        subtype: Option<String>,
161        meta: Option<Value>,
162    },
163}
164
165impl From<anyhow::Error> for InternalError {
166    fn from(error: anyhow::Error) -> Self {
167        match error.downcast_ref::<InternalError>() {
168            Some(integration_error) => integration_error.clone(),
169            None => InternalError::UnknownError {
170                message: error.to_string(),
171                subtype: None,
172                meta: None,
173            },
174        }
175    }
176}
177
178impl InternalError {
179    pub fn unknown(message: &str, subtype: Option<&str>) -> IntegrationOSError {
180        IntegrationOSError::internal(InternalError::UnknownError {
181            message: message.to_string(),
182            subtype: subtype.map(|s| s.to_string().snake_case()),
183            meta: None,
184        })
185    }
186
187    pub fn unique_field_violation(message: &str, subtype: Option<&str>) -> IntegrationOSError {
188        IntegrationOSError::internal(InternalError::UniqueFieldViolation {
189            message: message.to_string(),
190            subtype: subtype.map(|s| s.to_string().snake_case()),
191            meta: None,
192        })
193    }
194
195    pub fn timeout(message: &str, subtype: Option<&str>) -> IntegrationOSError {
196        IntegrationOSError::internal(InternalError::Timeout {
197            message: message.to_string(),
198            subtype: subtype.map(|s| s.to_string().snake_case()),
199            meta: None,
200        })
201    }
202
203    pub fn script_error(message: &str, subtype: Option<&str>) -> IntegrationOSError {
204        IntegrationOSError::internal(InternalError::ScriptError {
205            message: message.to_string(),
206            subtype: subtype.map(|s| s.to_string().snake_case()),
207            meta: None,
208        })
209    }
210
211    pub fn serialize_error(message: &str, subtype: Option<&str>) -> IntegrationOSError {
212        IntegrationOSError::internal(InternalError::SerializeError {
213            message: message.to_string(),
214            subtype: subtype.map(|s| s.to_string().snake_case()),
215            meta: None,
216        })
217    }
218
219    pub fn deserialize_error(message: &str, subtype: Option<&str>) -> IntegrationOSError {
220        IntegrationOSError::internal(InternalError::DeserializeError {
221            message: message.to_string(),
222            subtype: subtype.map(|s| s.to_string().snake_case()),
223            meta: None,
224        })
225    }
226
227    pub fn configuration_error(message: &str, subtype: Option<&str>) -> IntegrationOSError {
228        IntegrationOSError::internal(InternalError::ConfigurationError {
229            message: message.to_string(),
230            subtype: subtype.map(|s| s.to_string().snake_case()),
231            meta: None,
232        })
233    }
234
235    pub fn encryption_error(message: &str, subtype: Option<&str>) -> IntegrationOSError {
236        IntegrationOSError::internal(InternalError::EncryptionError {
237            message: message.to_string(),
238            subtype: subtype.map(|s| s.to_string().snake_case()),
239            meta: None,
240        })
241    }
242
243    pub fn decryption_error(message: &str, subtype: Option<&str>) -> IntegrationOSError {
244        IntegrationOSError::internal(InternalError::DecryptionError {
245            message: message.to_string(),
246            subtype: subtype.map(|s| s.to_string().snake_case()),
247            meta: None,
248        })
249    }
250
251    pub fn connection_error(message: &str, subtype: Option<&str>) -> IntegrationOSError {
252        IntegrationOSError::internal(InternalError::ConnectionError {
253            message: message.to_string(),
254            subtype: subtype.map(|s| s.to_string().snake_case()),
255            meta: None,
256        })
257    }
258
259    pub fn io_err(message: &str, subtype: Option<&str>) -> IntegrationOSError {
260        IntegrationOSError::internal(InternalError::IOErr {
261            message: message.to_string(),
262            subtype: subtype.map(|s| s.to_string().snake_case()),
263            meta: None,
264        })
265    }
266
267    pub fn key_not_found(message: &str, subtype: Option<&str>) -> IntegrationOSError {
268        IntegrationOSError::internal(InternalError::KeyNotFound {
269            message: message.to_string(),
270            subtype: subtype.map(|s| s.to_string().snake_case()),
271            meta: None,
272        })
273    }
274
275    pub fn invalid_argument(message: &str, subtype: Option<&str>) -> IntegrationOSError {
276        IntegrationOSError::internal(InternalError::InvalidArgument {
277            message: message.to_string(),
278            subtype: subtype.map(|s| s.to_string().snake_case()),
279            meta: None,
280        })
281    }
282
283    fn set_meta(self, metadata: Value) -> Self {
284        match self {
285            InternalError::UnknownError {
286                message, subtype, ..
287            } => InternalError::UnknownError {
288                message,
289                subtype,
290                meta: Some(metadata),
291            },
292            InternalError::UniqueFieldViolation {
293                message, subtype, ..
294            } => InternalError::UniqueFieldViolation {
295                message,
296                subtype,
297                meta: Some(metadata),
298            },
299            InternalError::Timeout {
300                message, subtype, ..
301            } => InternalError::Timeout {
302                message,
303                subtype,
304                meta: Some(metadata),
305            },
306            InternalError::ConnectionError {
307                message, subtype, ..
308            } => InternalError::ConnectionError {
309                message,
310                subtype,
311                meta: Some(metadata),
312            },
313            InternalError::KeyNotFound {
314                message, subtype, ..
315            } => InternalError::KeyNotFound {
316                message,
317                subtype,
318                meta: Some(metadata),
319            },
320            InternalError::InvalidArgument {
321                message, subtype, ..
322            } => InternalError::InvalidArgument {
323                message,
324                subtype,
325                meta: Some(metadata),
326            },
327            InternalError::IOErr {
328                message, subtype, ..
329            } => InternalError::IOErr {
330                message,
331                subtype,
332                meta: Some(metadata),
333            },
334            InternalError::EncryptionError {
335                message, subtype, ..
336            } => InternalError::EncryptionError {
337                message,
338                subtype,
339                meta: Some(metadata),
340            },
341            InternalError::DecryptionError {
342                message, subtype, ..
343            } => InternalError::DecryptionError {
344                message,
345                subtype,
346                meta: Some(metadata),
347            },
348            InternalError::ConfigurationError {
349                message, subtype, ..
350            } => InternalError::ConfigurationError {
351                message,
352                subtype,
353                meta: Some(metadata),
354            },
355            InternalError::ScriptError {
356                message, subtype, ..
357            } => InternalError::ScriptError {
358                message,
359                subtype,
360                meta: Some(metadata),
361            },
362            InternalError::SerializeError {
363                message, subtype, ..
364            } => InternalError::SerializeError {
365                message,
366                subtype,
367                meta: Some(metadata),
368            },
369            InternalError::DeserializeError {
370                message, subtype, ..
371            } => InternalError::DeserializeError {
372                message,
373                subtype,
374                meta: Some(metadata),
375            },
376        }
377    }
378}
379
380impl ErrorMeta for InternalError {
381    fn code(&self) -> ErrorCode {
382        match self {
383            InternalError::UnknownError { .. } => ErrorCode(1000),
384            InternalError::UniqueFieldViolation { .. } => ErrorCode(1001),
385            InternalError::Timeout { .. } => ErrorCode(1002),
386            InternalError::ConnectionError { .. } => ErrorCode(1003),
387            InternalError::KeyNotFound { .. } => ErrorCode(1004),
388            InternalError::InvalidArgument { .. } => ErrorCode(1005),
389            InternalError::IOErr { .. } => ErrorCode(1006),
390            InternalError::EncryptionError { .. } => ErrorCode(1007),
391            InternalError::DecryptionError { .. } => ErrorCode(1008),
392            InternalError::ConfigurationError { .. } => ErrorCode(1009),
393            InternalError::ScriptError { .. } => ErrorCode(1010),
394            InternalError::SerializeError { .. } => ErrorCode(1011),
395            InternalError::DeserializeError { .. } => ErrorCode(1012),
396        }
397    }
398
399    fn key(&self) -> ErrorKey {
400        match self {
401            InternalError::UnknownError { subtype, .. } => {
402                ErrorKey::internal("unknown", subtype.as_deref())
403            }
404            InternalError::UniqueFieldViolation { subtype, .. } => {
405                ErrorKey::internal("unique_violation", subtype.as_deref())
406            }
407            InternalError::Timeout { subtype, .. } => {
408                ErrorKey::internal("timeout", subtype.as_deref())
409            }
410            InternalError::ConnectionError { subtype, .. } => {
411                ErrorKey::internal("connection_error", subtype.as_deref())
412            }
413            InternalError::KeyNotFound { subtype, .. } => {
414                ErrorKey::internal("key_not_found", subtype.as_deref())
415            }
416            InternalError::InvalidArgument { subtype, .. } => {
417                ErrorKey::internal("invalid_argument", subtype.as_deref())
418            }
419            InternalError::IOErr { subtype, .. } => {
420                ErrorKey::internal("io_err", subtype.as_deref())
421            }
422            InternalError::EncryptionError { subtype, .. } => {
423                ErrorKey::internal("encryption_error", subtype.as_deref())
424            }
425            InternalError::DecryptionError { subtype, .. } => {
426                ErrorKey::internal("decryption_error", subtype.as_deref())
427            }
428            InternalError::ConfigurationError { subtype, .. } => {
429                ErrorKey::internal("configuration_error", subtype.as_deref())
430            }
431            InternalError::ScriptError { subtype, .. } => {
432                ErrorKey::internal("script_error", subtype.as_deref())
433            }
434            InternalError::SerializeError { subtype, .. } => {
435                ErrorKey::internal("serialize_error", subtype.as_deref())
436            }
437            InternalError::DeserializeError { subtype, .. } => {
438                ErrorKey::internal("deserialize_error", subtype.as_deref())
439            }
440        }
441    }
442
443    fn message(&self) -> ErrorMessage {
444        match self {
445            InternalError::UnknownError { message, .. } => ErrorMessage(message.to_string()),
446            InternalError::UniqueFieldViolation { message, .. } => {
447                ErrorMessage(message.to_string())
448            }
449            InternalError::Timeout { message, .. } => ErrorMessage(message.to_string()),
450            InternalError::ConnectionError { message, .. } => ErrorMessage(message.to_string()),
451            InternalError::KeyNotFound { message, .. } => ErrorMessage(message.to_string()),
452            InternalError::InvalidArgument { message, .. } => ErrorMessage(message.to_string()),
453            InternalError::IOErr { message, .. } => ErrorMessage(message.to_string()),
454            InternalError::EncryptionError { message, .. } => ErrorMessage(message.to_string()),
455            InternalError::DecryptionError { message, .. } => ErrorMessage(message.to_string()),
456            InternalError::ConfigurationError { message, .. } => ErrorMessage(message.to_string()),
457            InternalError::ScriptError { message, .. } => ErrorMessage(message.to_string()),
458            InternalError::SerializeError { message, .. } => ErrorMessage(message.to_string()),
459            InternalError::DeserializeError { message, .. } => ErrorMessage(message.to_string()),
460        }
461    }
462
463    // TODO: Implement this
464    fn meta(&self) -> Option<Value> {
465        match self {
466            InternalError::UnknownError { meta, .. } => meta.clone(),
467            InternalError::UniqueFieldViolation { meta, .. } => meta.clone(),
468            InternalError::Timeout { meta, .. } => meta.clone(),
469            InternalError::ConnectionError { meta, .. } => meta.clone(),
470            InternalError::KeyNotFound { meta, .. } => meta.clone(),
471            InternalError::InvalidArgument { meta, .. } => meta.clone(),
472            InternalError::IOErr { meta, .. } => meta.clone(),
473            InternalError::EncryptionError { meta, .. } => meta.clone(),
474            InternalError::DecryptionError { meta, .. } => meta.clone(),
475            InternalError::ConfigurationError { meta, .. } => meta.clone(),
476            InternalError::ScriptError { meta, .. } => meta.clone(),
477            InternalError::SerializeError { meta, .. } => meta.clone(),
478            InternalError::DeserializeError { meta, .. } => meta.clone(),
479        }
480    }
481}
482
483impl Debug for InternalError {
484    fn fmt(&self, f: &mut Formatter<'_>) -> FmtResult {
485        writeln!(f, "{}\n", &self)?;
486        let mut current = self.source();
487
488        while let Some(cause) = current {
489            writeln!(f, "Caused by:\n\t{}", cause)?;
490            current = cause.source();
491        }
492
493        Ok(())
494    }
495}
496
497#[derive(ThisError, Clone, Eq, PartialEq, Serialize, AsRefStr)]
498#[serde(rename_all = "camelCase")]
499#[strum(serialize_all = "PascalCase")]
500pub enum ApplicationError {
501    #[error("Bad Request: {}", .message)]
502    BadRequest {
503        message: String,
504        subtype: Option<String>,
505        meta: Option<Value>,
506    },
507    #[error("Conflict: {}", .message)]
508    Conflict {
509        message: String,
510        subtype: Option<String>,
511        meta: Option<Value>,
512    },
513    #[error("Forbidden: {}", .message)]
514    Forbidden {
515        message: String,
516        subtype: Option<String>,
517        meta: Option<Value>,
518    },
519    #[error("Internal Server Error: {}", .message)]
520    InternalServerError {
521        message: String,
522        subtype: Option<String>,
523        meta: Option<Value>,
524    },
525    #[error("Method Not Allowed: {}", .message)]
526    MethodNotAllowed {
527        message: String,
528        subtype: Option<String>,
529        meta: Option<Value>,
530    },
531    #[error("Not Found: {}", .message)]
532    NotFound {
533        message: String,
534        subtype: Option<String>,
535        meta: Option<Value>,
536    },
537    #[error("Not Implemented: {}", .message)]
538    NotImplemented {
539        message: String,
540        subtype: Option<String>,
541        meta: Option<Value>,
542    },
543    #[error("Precondition Failed: {}", .message)]
544    FailedDependency {
545        message: String,
546        subtype: Option<String>,
547        meta: Option<Value>,
548    },
549    #[error("Service Unavailable: {}", .message)]
550    ServiceUnavailable {
551        message: String,
552        subtype: Option<String>,
553        meta: Option<Value>,
554    },
555    #[error("Too Many Requests: {}", .message)]
556    TooManyRequests {
557        message: String,
558        subtype: Option<String>,
559        meta: Option<Value>,
560    },
561    #[error("Unauthorized: {}", .message)]
562    Unauthorized {
563        message: String,
564        subtype: Option<String>,
565        meta: Option<Value>,
566    },
567    #[error("Unprocessable Entity: {}", .message)]
568    UnprocessableEntity {
569        message: String,
570        subtype: Option<String>,
571        meta: Option<Value>,
572    },
573}
574
575impl From<anyhow::Error> for ApplicationError {
576    fn from(error: anyhow::Error) -> Self {
577        match error.downcast_ref::<ApplicationError>() {
578            Some(integration_error) => integration_error.clone(),
579            None => ApplicationError::InternalServerError {
580                message: error.to_string(),
581                subtype: None,
582                meta: None,
583            },
584        }
585    }
586}
587
588impl ApplicationError {
589    pub fn bad_request(message: &str, subtype: Option<&str>) -> IntegrationOSError {
590        IntegrationOSError::application(ApplicationError::BadRequest {
591            message: message.to_string(),
592            subtype: subtype.map(|s| s.to_string().snake_case()),
593            meta: None,
594        })
595    }
596
597    pub fn conflict(message: &str, subtype: Option<&str>) -> IntegrationOSError {
598        IntegrationOSError::application(ApplicationError::Conflict {
599            message: message.to_string(),
600            subtype: subtype.map(|s| s.to_string().snake_case()),
601            meta: None,
602        })
603    }
604
605    pub fn forbidden(message: &str, subtype: Option<&str>) -> IntegrationOSError {
606        IntegrationOSError::application(ApplicationError::Forbidden {
607            message: message.to_string(),
608            subtype: subtype.map(|s| s.to_string().snake_case()),
609            meta: None,
610        })
611    }
612
613    pub fn internal_server_error(message: &str, subtype: Option<&str>) -> IntegrationOSError {
614        IntegrationOSError::application(ApplicationError::InternalServerError {
615            message: message.to_string(),
616            subtype: subtype.map(|s| s.to_string().snake_case()),
617            meta: None,
618        })
619    }
620
621    pub fn method_not_allowed(message: &str, subtype: Option<&str>) -> IntegrationOSError {
622        IntegrationOSError::application(ApplicationError::MethodNotAllowed {
623            message: message.to_string(),
624            subtype: subtype.map(|s| s.to_string().snake_case()),
625            meta: None,
626        })
627    }
628
629    pub fn not_found(message: &str, subtype: Option<&str>) -> IntegrationOSError {
630        IntegrationOSError::application(ApplicationError::NotFound {
631            message: message.to_string(),
632            subtype: subtype.map(|s| s.to_string().snake_case()),
633            meta: None,
634        })
635    }
636
637    pub fn not_implemented(message: &str, subtype: Option<&str>) -> IntegrationOSError {
638        IntegrationOSError::application(ApplicationError::NotImplemented {
639            message: message.to_string(),
640            subtype: subtype.map(|s| s.to_string().snake_case()),
641            meta: None,
642        })
643    }
644
645    pub fn failed_dependency(message: &str, subtype: Option<&str>) -> IntegrationOSError {
646        IntegrationOSError::application(ApplicationError::FailedDependency {
647            message: message.to_string(),
648            subtype: subtype.map(|s| s.to_string().snake_case()),
649            meta: None,
650        })
651    }
652
653    pub fn service_unavailable(message: &str, subtype: Option<&str>) -> IntegrationOSError {
654        IntegrationOSError::application(ApplicationError::ServiceUnavailable {
655            message: message.to_string(),
656            subtype: subtype.map(|s| s.to_string().snake_case()),
657            meta: None,
658        })
659    }
660
661    pub fn too_many_requests(message: &str, subtype: Option<&str>) -> IntegrationOSError {
662        IntegrationOSError::application(ApplicationError::TooManyRequests {
663            message: message.to_string(),
664            subtype: subtype.map(|s| s.to_string().snake_case()),
665            meta: None,
666        })
667    }
668
669    pub fn unauthorized(message: &str, subtype: Option<&str>) -> IntegrationOSError {
670        IntegrationOSError::application(ApplicationError::Unauthorized {
671            message: message.to_string(),
672            subtype: subtype.map(|s| s.to_string().snake_case()),
673            meta: None,
674        })
675    }
676
677    pub fn unprocessable_entity(message: &str, subtype: Option<&str>) -> IntegrationOSError {
678        IntegrationOSError::application(ApplicationError::UnprocessableEntity {
679            message: message.to_string(),
680            subtype: subtype.map(|s| s.to_string().snake_case()),
681            meta: None,
682        })
683    }
684
685    fn set_meta(self, meta: Value) -> Self {
686        match self {
687            ApplicationError::BadRequest {
688                message, subtype, ..
689            } => ApplicationError::BadRequest {
690                message: message.clone(),
691                subtype: subtype.clone(),
692                meta: Some(meta),
693            },
694            ApplicationError::Conflict {
695                message, subtype, ..
696            } => ApplicationError::Conflict {
697                message: message.clone(),
698                subtype: subtype.clone(),
699                meta: Some(meta),
700            },
701            ApplicationError::Forbidden {
702                message, subtype, ..
703            } => ApplicationError::Forbidden {
704                message: message.clone(),
705                subtype: subtype.clone(),
706                meta: Some(meta),
707            },
708            ApplicationError::InternalServerError {
709                message, subtype, ..
710            } => ApplicationError::InternalServerError {
711                message: message.clone(),
712                subtype: subtype.clone(),
713                meta: Some(meta),
714            },
715            ApplicationError::MethodNotAllowed {
716                message, subtype, ..
717            } => ApplicationError::MethodNotAllowed {
718                message: message.clone(),
719                subtype: subtype.clone(),
720                meta: Some(meta),
721            },
722            ApplicationError::NotFound {
723                message, subtype, ..
724            } => ApplicationError::NotFound {
725                message: message.clone(),
726                subtype: subtype.clone(),
727                meta: Some(meta),
728            },
729            ApplicationError::NotImplemented {
730                message, subtype, ..
731            } => ApplicationError::NotImplemented {
732                message: message.clone(),
733                subtype: subtype.clone(),
734                meta: Some(meta),
735            },
736            ApplicationError::FailedDependency {
737                message, subtype, ..
738            } => ApplicationError::FailedDependency {
739                message: message.clone(),
740                subtype: subtype.clone(),
741                meta: Some(meta),
742            },
743            ApplicationError::ServiceUnavailable {
744                message, subtype, ..
745            } => ApplicationError::ServiceUnavailable {
746                message: message.clone(),
747                subtype: subtype.clone(),
748                meta: Some(meta),
749            },
750            ApplicationError::TooManyRequests {
751                message, subtype, ..
752            } => ApplicationError::TooManyRequests {
753                message: message.clone(),
754                subtype: subtype.clone(),
755                meta: Some(meta),
756            },
757            ApplicationError::Unauthorized {
758                message, subtype, ..
759            } => ApplicationError::Unauthorized {
760                message: message.clone(),
761                subtype: subtype.clone(),
762                meta: Some(meta),
763            },
764            ApplicationError::UnprocessableEntity {
765                message, subtype, ..
766            } => ApplicationError::UnprocessableEntity {
767                message: message.clone(),
768                subtype: subtype.clone(),
769                meta: Some(meta),
770            },
771        }
772    }
773}
774
775impl ErrorMeta for ApplicationError {
776    fn code(&self) -> ErrorCode {
777        match self {
778            ApplicationError::BadRequest { .. } => ErrorCode(2000),
779            ApplicationError::Conflict { .. } => ErrorCode(2001),
780            ApplicationError::Forbidden { .. } => ErrorCode(2002),
781            ApplicationError::InternalServerError { .. } => ErrorCode(2003),
782            ApplicationError::MethodNotAllowed { .. } => ErrorCode(2004),
783            ApplicationError::NotFound { .. } => ErrorCode(2005),
784            ApplicationError::NotImplemented { .. } => ErrorCode(2006),
785            ApplicationError::FailedDependency { .. } => ErrorCode(2007),
786            ApplicationError::ServiceUnavailable { .. } => ErrorCode(2008),
787            ApplicationError::TooManyRequests { .. } => ErrorCode(2009),
788            ApplicationError::Unauthorized { .. } => ErrorCode(2010),
789            ApplicationError::UnprocessableEntity { .. } => ErrorCode(2011),
790        }
791    }
792
793    fn key(&self) -> ErrorKey {
794        match self {
795            ApplicationError::BadRequest { subtype, .. } => {
796                ErrorKey::application("bad_request", subtype.as_deref())
797            }
798            ApplicationError::Conflict { subtype, .. } => {
799                ErrorKey::application("conflict", subtype.as_deref())
800            }
801            ApplicationError::Forbidden { subtype, .. } => {
802                ErrorKey::application("forbidden", subtype.as_deref())
803            }
804            ApplicationError::InternalServerError { subtype, .. } => {
805                ErrorKey::application("internal_server_error", subtype.as_deref())
806            }
807            ApplicationError::MethodNotAllowed { subtype, .. } => {
808                ErrorKey::application("method_not_allowed", subtype.as_deref())
809            }
810            ApplicationError::NotFound { subtype, .. } => {
811                ErrorKey::application("not_found", subtype.as_deref())
812            }
813            ApplicationError::NotImplemented { subtype, .. } => {
814                ErrorKey::application("not_implemented", subtype.as_deref())
815            }
816            ApplicationError::FailedDependency { subtype, .. } => {
817                ErrorKey::application("failed_dependency", subtype.as_deref())
818            }
819            ApplicationError::ServiceUnavailable { subtype, .. } => {
820                ErrorKey::application("service_unavailable", subtype.as_deref())
821            }
822            ApplicationError::TooManyRequests { subtype, .. } => {
823                ErrorKey::application("too_many_requests", subtype.as_deref())
824            }
825            ApplicationError::Unauthorized { subtype, .. } => {
826                ErrorKey::application("unauthorized", subtype.as_deref())
827            }
828            ApplicationError::UnprocessableEntity { subtype, .. } => {
829                ErrorKey::application("unprocessable_entity", subtype.as_deref())
830            }
831        }
832    }
833
834    fn message(&self) -> ErrorMessage {
835        match self {
836            ApplicationError::BadRequest { message, .. } => ErrorMessage(message.to_string()),
837            ApplicationError::Conflict { message, .. } => ErrorMessage(message.to_string()),
838            ApplicationError::Forbidden { message, .. } => ErrorMessage(message.to_string()),
839            ApplicationError::InternalServerError { message, .. } => {
840                ErrorMessage(message.to_string())
841            }
842            ApplicationError::MethodNotAllowed { message, .. } => ErrorMessage(message.to_string()),
843            ApplicationError::NotFound { message, .. } => ErrorMessage(message.to_string()),
844            ApplicationError::NotImplemented { message, .. } => ErrorMessage(message.to_string()),
845            ApplicationError::FailedDependency { message, .. } => ErrorMessage(message.to_string()),
846            ApplicationError::ServiceUnavailable { message, .. } => {
847                ErrorMessage(message.to_string())
848            }
849            ApplicationError::TooManyRequests { message, .. } => ErrorMessage(message.to_string()),
850            ApplicationError::Unauthorized { message, .. } => ErrorMessage(message.to_string()),
851            ApplicationError::UnprocessableEntity { message, .. } => {
852                ErrorMessage(message.to_string())
853            }
854        }
855    }
856
857    fn meta(&self) -> Option<Value> {
858        match self {
859            ApplicationError::BadRequest { meta, .. } => meta.clone(),
860            ApplicationError::Conflict { meta, .. } => meta.clone(),
861            ApplicationError::Forbidden { meta, .. } => meta.clone(),
862            ApplicationError::InternalServerError { meta, .. } => meta.clone(),
863            ApplicationError::MethodNotAllowed { meta, .. } => meta.clone(),
864            ApplicationError::NotFound { meta, .. } => meta.clone(),
865            ApplicationError::NotImplemented { meta, .. } => meta.clone(),
866            ApplicationError::FailedDependency { meta, .. } => meta.clone(),
867            ApplicationError::ServiceUnavailable { meta, .. } => meta.clone(),
868            ApplicationError::TooManyRequests { meta, .. } => meta.clone(),
869            ApplicationError::Unauthorized { meta, .. } => meta.clone(),
870            ApplicationError::UnprocessableEntity { meta, .. } => meta.clone(),
871        }
872    }
873}
874
875impl Debug for ApplicationError {
876    fn fmt(&self, f: &mut Formatter<'_>) -> FmtResult {
877        writeln!(f, "{}\n", &self)?;
878        let mut current = self.source();
879
880        while let Some(cause) = current {
881            writeln!(f, "Caused by:\n\t{}", cause)?;
882            current = cause.source();
883        }
884
885        Ok(())
886    }
887}
888
889impl From<InternalError> for ApplicationError {
890    fn from(error: InternalError) -> Self {
891        match error {
892            InternalError::Timeout { .. }
893            | InternalError::ConnectionError { .. }
894            | InternalError::IOErr { .. }
895            | InternalError::EncryptionError { .. }
896            | InternalError::DecryptionError { .. }
897            | InternalError::ScriptError { .. }
898            | InternalError::ConfigurationError { .. }
899            | InternalError::UnknownError { .. } => ApplicationError::InternalServerError {
900                message: "An unknown error occurred".into(),
901                subtype: None,
902                meta: None,
903            },
904            InternalError::UniqueFieldViolation {
905                message,
906                subtype,
907                meta,
908            } => ApplicationError::Conflict {
909                message,
910                subtype,
911                meta,
912            },
913            InternalError::KeyNotFound {
914                message,
915                subtype,
916                meta,
917            } => ApplicationError::NotFound {
918                message,
919                subtype,
920                meta,
921            },
922            InternalError::InvalidArgument {
923                message,
924                subtype,
925                meta,
926            }
927            | InternalError::SerializeError {
928                message,
929                subtype,
930                meta,
931            }
932            | InternalError::DeserializeError {
933                message,
934                subtype,
935                meta,
936            } => ApplicationError::BadRequest {
937                message,
938                subtype,
939                meta,
940            },
941        }
942    }
943}
944
945#[derive(ThisError, Debug, Clone, Eq, PartialEq, Serialize)]
946#[serde(untagged)]
947pub enum IntegrationOSError {
948    Internal(InternalError),
949    Application(ApplicationError),
950}
951
952impl AsRef<str> for IntegrationOSError {
953    fn as_ref(&self) -> &str {
954        match self {
955            IntegrationOSError::Internal(e) => e.as_ref(),
956            IntegrationOSError::Application(e) => e.as_ref(),
957        }
958    }
959}
960
961impl From<anyhow::Error> for IntegrationOSError {
962    fn from(error: anyhow::Error) -> Self {
963        match error.downcast_ref::<IntegrationOSError>() {
964            Some(integration_error) => match integration_error {
965                internal @ IntegrationOSError::Internal(_) => internal.clone(),
966                application @ IntegrationOSError::Application(_) => application.clone(),
967            },
968            None => IntegrationOSError::Internal(InternalError::UnknownError {
969                message: error.to_string(),
970                subtype: None,
971                meta: None,
972            }),
973        }
974    }
975}
976
977impl From<Arc<IntegrationOSError>> for IntegrationOSError {
978    fn from(error: Arc<IntegrationOSError>) -> Self {
979        Arc::unwrap_or_clone(error)
980    }
981}
982
983impl<'a> From<&'a IntegrationOSError> for StatusCode {
984    fn from(value: &'a IntegrationOSError) -> Self {
985        match value {
986            IntegrationOSError::Internal(e) => match e {
987                InternalError::UniqueFieldViolation { .. } => StatusCode::CONFLICT,
988                InternalError::Timeout { .. } => StatusCode::GATEWAY_TIMEOUT,
989                InternalError::ConnectionError { .. } => StatusCode::BAD_GATEWAY,
990                InternalError::KeyNotFound { .. } => StatusCode::NOT_FOUND,
991                InternalError::InvalidArgument { .. }
992                | InternalError::SerializeError { .. }
993                | InternalError::DeserializeError { .. } => StatusCode::BAD_REQUEST,
994                InternalError::UnknownError { .. }
995                | InternalError::IOErr { .. }
996                | InternalError::EncryptionError { .. }
997                | InternalError::ConfigurationError { .. }
998                | InternalError::ScriptError { .. }
999                | InternalError::DecryptionError { .. } => StatusCode::INTERNAL_SERVER_ERROR,
1000            },
1001            IntegrationOSError::Application(e) => match e {
1002                ApplicationError::BadRequest { .. } => StatusCode::BAD_REQUEST,
1003                ApplicationError::Conflict { .. } => StatusCode::CONFLICT,
1004                ApplicationError::Forbidden { .. } => StatusCode::FORBIDDEN,
1005                ApplicationError::InternalServerError { .. } => StatusCode::INTERNAL_SERVER_ERROR,
1006                ApplicationError::MethodNotAllowed { .. } => StatusCode::METHOD_NOT_ALLOWED,
1007                ApplicationError::NotFound { .. } => StatusCode::NOT_FOUND,
1008                ApplicationError::NotImplemented { .. } => StatusCode::NOT_IMPLEMENTED,
1009                ApplicationError::FailedDependency { .. } => StatusCode::FAILED_DEPENDENCY,
1010                ApplicationError::ServiceUnavailable { .. } => StatusCode::SERVICE_UNAVAILABLE,
1011                ApplicationError::TooManyRequests { .. } => StatusCode::TOO_MANY_REQUESTS,
1012                ApplicationError::Unauthorized { .. } => StatusCode::UNAUTHORIZED,
1013                ApplicationError::UnprocessableEntity { .. } => StatusCode::UNPROCESSABLE_ENTITY,
1014            },
1015        }
1016    }
1017}
1018
1019impl From<mongodb::error::Error> for IntegrationOSError {
1020    fn from(err: mongodb::error::Error) -> Self {
1021        match *err.kind {
1022            mongodb::error::ErrorKind::InvalidArgument { message, .. } => {
1023                InternalError::invalid_argument(&message, None)
1024            }
1025            mongodb::error::ErrorKind::Authentication { message, .. } => {
1026                InternalError::connection_error(&message, Some("Authentication failed"))
1027            }
1028            mongodb::error::ErrorKind::BsonDeserialization(error) => {
1029                InternalError::invalid_argument(
1030                    &error.to_string(),
1031                    Some("BSON deserialization error"),
1032                )
1033            }
1034            mongodb::error::ErrorKind::BsonSerialization(error) => InternalError::invalid_argument(
1035                &error.to_string(),
1036                Some("BSON serialization error"),
1037            ),
1038            mongodb::error::ErrorKind::BulkWrite(error) => InternalError::unknown(
1039                &error
1040                    .write_errors
1041                    .into_iter()
1042                    .map(|e| e.into_iter().map(|e| e.message).collect())
1043                    .collect::<Vec<String>>()
1044                    .join(", "),
1045                Some("Bulk write error"),
1046            ),
1047            mongodb::error::ErrorKind::Command(error) => {
1048                let code = error.code;
1049                if code == 11000 {
1050                    InternalError::unique_field_violation(
1051                        &error.message,
1052                        Some("A document with the same unique key already exists"),
1053                    )
1054                } else {
1055                    InternalError::unknown(&error.message, Some("Command error"))
1056                }
1057            }
1058            mongodb::error::ErrorKind::DnsResolve { message, .. } => {
1059                InternalError::connection_error(&message, Some("DNS resolution failed"))
1060            }
1061            mongodb::error::ErrorKind::GridFs { .. } => InternalError::unknown(
1062                "GridFS error",
1063                Some("An error occurred while interacting with GridFS"),
1064            ),
1065            mongodb::error::ErrorKind::Internal { message, .. } => {
1066                InternalError::unknown(&message, Some("Internal error"))
1067            }
1068            mongodb::error::ErrorKind::Io(error) => InternalError::io_err(&error.to_string(), None),
1069            mongodb::error::ErrorKind::ConnectionPoolCleared { message, .. } => {
1070                InternalError::connection_error(&message, Some("Connection pool cleared"))
1071            }
1072            mongodb::error::ErrorKind::InvalidResponse { message, .. } => {
1073                InternalError::invalid_argument(&message, Some("Invalid response"))
1074            }
1075            mongodb::error::ErrorKind::ServerSelection { message, .. } => {
1076                InternalError::connection_error(&message, Some("Server selection failed"))
1077            }
1078            mongodb::error::ErrorKind::SessionsNotSupported => {
1079                InternalError::invalid_argument("Sessions not supported", None)
1080            }
1081            mongodb::error::ErrorKind::InvalidTlsConfig { message, .. } => {
1082                InternalError::connection_error(&message, Some("Invalid TLS configuration"))
1083            }
1084            mongodb::error::ErrorKind::Write(error) => match error {
1085                WriteFailure::WriteConcernError(err) => {
1086                    let code = err.code;
1087
1088                    if code == 11000 {
1089                        InternalError::unique_field_violation(
1090                            &err.message,
1091                            Some("A document with the same unique key already exists"),
1092                        )
1093                    } else {
1094                        InternalError::unknown(&err.message, Some("Write concern error"))
1095                    }
1096                }
1097                WriteFailure::WriteError(err) => {
1098                    let code = err.code;
1099                    if code == 11000 {
1100                        InternalError::unique_field_violation(
1101                            &err.message,
1102                            Some("A document with the same unique key already exists"),
1103                        )
1104                    } else {
1105                        InternalError::unknown(&err.message, Some("Write error"))
1106                    }
1107                }
1108                _ => InternalError::unknown("Write error", Some("An error occurred while writing")),
1109            },
1110            mongodb::error::ErrorKind::Transaction { message, .. } => {
1111                InternalError::unknown(&message, Some("Transaction error"))
1112            }
1113            mongodb::error::ErrorKind::IncompatibleServer { message, .. } => {
1114                InternalError::connection_error(&message, Some("Incompatible server"))
1115            }
1116            mongodb::error::ErrorKind::MissingResumeToken => {
1117                InternalError::invalid_argument("Missing resume token", None)
1118            }
1119            mongodb::error::ErrorKind::Custom(_) => InternalError::unknown(
1120                "Unknown error",
1121                Some("An error occurred with the MongoDB driver"),
1122            ),
1123            mongodb::error::ErrorKind::Shutdown => {
1124                InternalError::unknown("Shutdown error", Some("The MongoDB driver has shut down"))
1125            }
1126            _ => InternalError::unknown("Unknown error", Some("An unknown error occurred")),
1127        }
1128    }
1129}
1130
1131impl From<IntegrationOSError> for StatusCode {
1132    fn from(value: IntegrationOSError) -> Self {
1133        (&value).into()
1134    }
1135}
1136
1137impl IntegrationOSError {
1138    pub fn status(&self) -> u16 {
1139        StatusCode::from(self).as_u16()
1140    }
1141
1142    fn internal(internal: InternalError) -> Self {
1143        IntegrationOSError::Internal(internal)
1144    }
1145
1146    fn application(application: ApplicationError) -> Self {
1147        IntegrationOSError::Application(application)
1148    }
1149
1150    pub fn from_err_code(status: StatusCode, message: &str, subtype: Option<&str>) -> Self {
1151        let message = message.to_string();
1152        let subtype = subtype.map(|s| s.to_string());
1153        let meta = None;
1154        match status {
1155            StatusCode::BAD_REQUEST => {
1156                IntegrationOSError::application(ApplicationError::BadRequest {
1157                    message,
1158                    subtype,
1159                    meta,
1160                })
1161            }
1162
1163            StatusCode::CONFLICT => IntegrationOSError::application(ApplicationError::Conflict {
1164                message,
1165                subtype,
1166                meta,
1167            }),
1168
1169            StatusCode::FORBIDDEN => IntegrationOSError::application(ApplicationError::Forbidden {
1170                message,
1171                subtype,
1172                meta,
1173            }),
1174
1175            StatusCode::INTERNAL_SERVER_ERROR => {
1176                IntegrationOSError::application(ApplicationError::InternalServerError {
1177                    message,
1178                    subtype,
1179                    meta,
1180                })
1181            }
1182
1183            StatusCode::METHOD_NOT_ALLOWED => {
1184                IntegrationOSError::application(ApplicationError::MethodNotAllowed {
1185                    message,
1186                    subtype,
1187                    meta,
1188                })
1189            }
1190
1191            StatusCode::NOT_FOUND => IntegrationOSError::application(ApplicationError::NotFound {
1192                message,
1193                subtype,
1194                meta,
1195            }),
1196
1197            StatusCode::NOT_IMPLEMENTED => {
1198                IntegrationOSError::application(ApplicationError::NotImplemented {
1199                    message,
1200                    subtype,
1201                    meta,
1202                })
1203            }
1204
1205            StatusCode::FAILED_DEPENDENCY => {
1206                IntegrationOSError::application(ApplicationError::FailedDependency {
1207                    message,
1208                    subtype,
1209                    meta,
1210                })
1211            }
1212
1213            StatusCode::SERVICE_UNAVAILABLE => {
1214                IntegrationOSError::application(ApplicationError::ServiceUnavailable {
1215                    message,
1216                    subtype,
1217                    meta,
1218                })
1219            }
1220
1221            StatusCode::TOO_MANY_REQUESTS => {
1222                IntegrationOSError::application(ApplicationError::TooManyRequests {
1223                    message,
1224                    subtype,
1225                    meta,
1226                })
1227            }
1228
1229            StatusCode::UNAUTHORIZED => {
1230                IntegrationOSError::application(ApplicationError::Unauthorized {
1231                    message,
1232                    subtype,
1233                    meta,
1234                })
1235            }
1236
1237            StatusCode::UNPROCESSABLE_ENTITY => {
1238                IntegrationOSError::application(ApplicationError::UnprocessableEntity {
1239                    message,
1240                    subtype,
1241                    meta,
1242                })
1243            }
1244
1245            _ => {
1246                if status.is_client_error() {
1247                    IntegrationOSError::application(ApplicationError::BadRequest {
1248                        message,
1249                        subtype,
1250                        meta,
1251                    })
1252                } else {
1253                    IntegrationOSError::internal(InternalError::IOErr {
1254                        message: format!(
1255                            "Unknown error with status code: {}, message: {}",
1256                            status, message
1257                        ),
1258                        subtype,
1259                        meta,
1260                    })
1261                }
1262            }
1263        }
1264    }
1265
1266    pub(crate) fn as_application(&self) -> IntegrationOSError {
1267        match self {
1268            IntegrationOSError::Application(e) => IntegrationOSError::Application(e.clone()),
1269            IntegrationOSError::Internal(e) => IntegrationOSError::Application(e.clone().into()),
1270        }
1271    }
1272
1273    pub(crate) fn as_json(&self) -> serde_json::Value {
1274        json!({
1275            "type": self.as_ref(),
1276            "code": self.code().as_u16(),
1277            "status": StatusCode::from(self).as_u16(),
1278            "key": self.key().to_string(),
1279            "message": self.message().to_string(),
1280            "meta": self.meta().unwrap_or_default(),
1281        })
1282    }
1283
1284    pub fn set_meta(self, meta: &Value) -> Self {
1285        match self {
1286            IntegrationOSError::Internal(e) => {
1287                IntegrationOSError::internal(e.set_meta(meta.clone()))
1288            }
1289            IntegrationOSError::Application(e) => {
1290                IntegrationOSError::application(e.set_meta(meta.clone()))
1291            }
1292        }
1293    }
1294
1295    pub fn is_internal(&self) -> bool {
1296        matches!(self, IntegrationOSError::Internal(_))
1297    }
1298
1299    pub fn is_application(&self) -> bool {
1300        matches!(self, IntegrationOSError::Application(_))
1301    }
1302}
1303
1304impl ErrorMeta for IntegrationOSError {
1305    fn code(&self) -> ErrorCode {
1306        match self {
1307            IntegrationOSError::Internal(e) => e.code(),
1308            IntegrationOSError::Application(e) => e.code(),
1309        }
1310    }
1311
1312    fn key(&self) -> ErrorKey {
1313        match self {
1314            IntegrationOSError::Internal(e) => e.key(),
1315            IntegrationOSError::Application(e) => e.key(),
1316        }
1317    }
1318
1319    fn message(&self) -> ErrorMessage {
1320        match self {
1321            IntegrationOSError::Internal(e) => e.message(),
1322            IntegrationOSError::Application(e) => e.message(),
1323        }
1324    }
1325
1326    fn meta(&self) -> Option<Value> {
1327        match self {
1328            IntegrationOSError::Internal(e) => e.meta(),
1329            IntegrationOSError::Application(e) => e.meta(),
1330        }
1331    }
1332}
1333
1334impl Display for IntegrationOSError {
1335    fn fmt(&self, f: &mut Formatter<'_>) -> FmtResult {
1336        match self {
1337            IntegrationOSError::Internal(e) => write!(f, "{}", e),
1338            IntegrationOSError::Application(e) => write!(f, "{}", e),
1339        }
1340    }
1341}
1342
1343#[cfg(test)]
1344mod tests {
1345    use super::*;
1346
1347    #[test]
1348    fn test_new_function() {
1349        let internal_error: IntegrationOSError = InternalError::unknown("test", None);
1350
1351        assert_eq!(internal_error.code(), ErrorCode(1000),);
1352        assert_eq!(internal_error.key(), ErrorKey::internal("unknown", None),);
1353        assert_eq!(internal_error.message(), ErrorMessage("test".to_string()),);
1354    }
1355
1356    #[test]
1357    fn test_error_code() {
1358        let code = ErrorCode(400);
1359        assert_eq!(code.to_string(), "400");
1360    }
1361
1362    #[test]
1363    fn test_error_key() {
1364        let key = ErrorKey::internal("test", None);
1365        assert_eq!(key.to_string(), "err::internal::test");
1366    }
1367
1368    #[test]
1369    fn test_error_message() {
1370        let message = ErrorMessage("test".to_string());
1371        assert_eq!(message.to_string(), "test");
1372    }
1373
1374    #[test]
1375    fn test_interoperability_between_anyhow_error_and_domain_error() {
1376        let err = InternalError::unknown("test", None);
1377        let any_err: anyhow::Error = err.clone().into();
1378        let code: ErrorCode = any_err.downcast_ref::<IntegrationOSError>().unwrap().code();
1379        let message: ErrorMessage = any_err
1380            .downcast_ref::<IntegrationOSError>()
1381            .unwrap()
1382            .message();
1383        let key: ErrorKey = any_err.downcast_ref::<IntegrationOSError>().unwrap().key();
1384
1385        assert_eq!(code, ErrorCode(1000));
1386        assert_eq!(message, ErrorMessage("test".to_string()));
1387        assert_eq!(key, ErrorKey::internal("unknown", None));
1388    }
1389
1390    #[test]
1391    fn test_round_trip_between_domain_error_and_anyhow_error() {
1392        let err = InternalError::unknown("test", None);
1393        let any_err: anyhow::Error = err.clone().into();
1394        let round_trip_err = any_err.into();
1395
1396        let app_err = ApplicationError::bad_request("test", None);
1397        let any_app_err: anyhow::Error = app_err.clone().into();
1398        let round_trip_app_err = any_app_err.into();
1399
1400        assert_eq!(err, round_trip_err);
1401        assert_eq!(app_err, round_trip_app_err);
1402    }
1403
1404    #[test]
1405    fn from_internal_error_to_application_error() {
1406        let internal_error = InternalError::UniqueFieldViolation {
1407            message: "test".to_string(),
1408            subtype: None,
1409            meta: None,
1410        };
1411        let app_error: ApplicationError = internal_error.into();
1412
1413        assert_eq!(
1414            app_error,
1415            ApplicationError::Conflict {
1416                message: "test".to_string(),
1417                subtype: None,
1418                meta: None
1419            }
1420        );
1421    }
1422}