metabase_api_rs/service/
traits.rs

1//! Service layer traits
2//!
3//! This module defines the core traits for the service layer.
4
5use crate::core::error::Error;
6use async_trait::async_trait;
7use std::fmt::Debug;
8
9/// Service-specific error type
10#[derive(Debug, thiserror::Error)]
11pub enum ServiceError {
12    #[error("Validation error: {0}")]
13    Validation(String),
14
15    #[error("Business rule violation: {0}")]
16    BusinessRule(String),
17
18    #[error("Not found: {0}")]
19    NotFound(String),
20
21    #[error("Unauthorized: {0}")]
22    Unauthorized(String),
23
24    #[error("Repository error: {0}")]
25    Repository(#[from] crate::repository::traits::RepositoryError),
26
27    #[error("Other error: {0}")]
28    Other(String),
29}
30
31impl From<Error> for ServiceError {
32    fn from(err: Error) -> Self {
33        match err {
34            Error::NotFound(msg) => ServiceError::NotFound(msg),
35            Error::Authentication(msg) => ServiceError::Unauthorized(msg),
36            Error::Validation(msg) => ServiceError::Validation(msg),
37            _ => ServiceError::Other(err.to_string()),
38        }
39    }
40}
41
42impl From<ServiceError> for Error {
43    fn from(err: ServiceError) -> Self {
44        match err {
45            ServiceError::NotFound(msg) => Error::NotFound(msg),
46            ServiceError::Unauthorized(msg) => Error::Authentication(msg),
47            ServiceError::Validation(msg) => Error::Validation(msg),
48            _ => Error::Unknown(err.to_string()),
49        }
50    }
51}
52
53/// Service result type
54pub type ServiceResult<T> = Result<T, ServiceError>;
55
56/// Base service trait
57#[async_trait]
58pub trait Service: Send + Sync {
59    /// Service name for identification
60    fn name(&self) -> &str;
61
62    /// Validate business rules
63    async fn validate(&self) -> ServiceResult<()> {
64        Ok(())
65    }
66}
67
68/// Validation helpers
69pub struct ValidationContext {
70    errors: Vec<String>,
71}
72
73impl ValidationContext {
74    /// Create a new validation context
75    pub fn new() -> Self {
76        Self { errors: Vec::new() }
77    }
78
79    /// Add a validation error
80    pub fn add_error(&mut self, error: impl Into<String>) {
81        self.errors.push(error.into());
82    }
83
84    /// Check if validation passed
85    pub fn is_valid(&self) -> bool {
86        self.errors.is_empty()
87    }
88
89    /// Get validation errors
90    pub fn errors(&self) -> &[String] {
91        &self.errors
92    }
93
94    /// Convert to result
95    pub fn to_result(self) -> ServiceResult<()> {
96        if self.is_valid() {
97            Ok(())
98        } else {
99            Err(ServiceError::Validation(self.errors.join(", ")))
100        }
101    }
102}
103
104impl Default for ValidationContext {
105    fn default() -> Self {
106        Self::new()
107    }
108}