claude_code_toolkit/traits/
validation.rs

1//! Validation traits and types
2
3use super::Credentials;
4use crate::error::Result;
5use crate::types::Config;
6use async_trait::async_trait;
7
8/// Validation error details
9#[derive(Debug, Clone)]
10pub struct ValidationError {
11  pub field: String,
12  pub message: String,
13  pub severity: ValidationSeverity,
14  pub suggestion: Option<String>,
15}
16
17#[derive(Debug, Clone, PartialEq)]
18pub enum ValidationSeverity {
19  Error,
20  Warning,
21  Info,
22}
23
24impl ValidationError {
25  pub fn new(field: &str, message: &str, severity: ValidationSeverity) -> Self {
26    Self {
27      field: field.to_string(),
28      message: message.to_string(),
29      severity,
30      suggestion: None,
31    }
32  }
33
34  pub fn with_suggestion(mut self, suggestion: &str) -> Self {
35    self.suggestion = Some(suggestion.to_string());
36    self
37  }
38
39  pub fn error(field: &str, message: &str) -> Self {
40    Self::new(field, message, ValidationSeverity::Error)
41  }
42
43  pub fn warning(field: &str, message: &str) -> Self {
44    Self::new(field, message, ValidationSeverity::Warning)
45  }
46
47  pub fn info(field: &str, message: &str) -> Self {
48    Self::new(field, message, ValidationSeverity::Info)
49  }
50}
51
52/// Individual validation rule
53#[async_trait]
54pub trait ValidationRule: Send + Sync {
55  /// Get rule identifier
56  fn rule_id(&self) -> &str;
57
58  /// Get rule description
59  fn description(&self) -> &str;
60
61  /// Validate configuration
62  async fn validate_config(&self, config: &Config) -> Result<Vec<ValidationError>>;
63
64  /// Validate credentials
65  async fn validate_credentials(&self, credentials: &Credentials) -> Result<Vec<ValidationError>>;
66
67  /// Check if rule applies to config
68  fn applies_to(&self, _config: &Config) -> bool {
69    true
70  }
71}
72
73/// Validation service
74#[async_trait]
75pub trait ValidationService: Send + Sync {
76  /// Register validation rule
77  fn register_rule(&mut self, rule: Box<dyn ValidationRule>);
78
79  /// Validate complete configuration
80  async fn validate_config(&self, config: &Config) -> Result<Vec<ValidationError>>;
81
82  /// Validate credentials
83  async fn validate_credentials(&self, credentials: &Credentials) -> Result<Vec<ValidationError>>;
84
85  /// Get validation summary
86  async fn get_validation_summary(
87    &self,
88    config: &Config,
89    credentials: Option<&Credentials>
90  ) -> Result<ValidationSummary>;
91
92  /// Fix auto-fixable issues
93  async fn auto_fix(&self, config: &mut Config) -> Result<Vec<String>>;
94}
95
96/// Summary of validation results
97#[derive(Debug)]
98pub struct ValidationSummary {
99  pub total_issues: usize,
100  pub errors: usize,
101  pub warnings: usize,
102  pub info: usize,
103  pub auto_fixable: usize,
104  pub is_valid: bool,
105}
106
107impl ValidationSummary {
108  pub fn from_errors(errors: &[ValidationError]) -> Self {
109    let errors_count = errors
110      .iter()
111      .filter(|e| e.severity == ValidationSeverity::Error)
112      .count();
113    let warnings_count = errors
114      .iter()
115      .filter(|e| e.severity == ValidationSeverity::Warning)
116      .count();
117    let info_count = errors
118      .iter()
119      .filter(|e| e.severity == ValidationSeverity::Info)
120      .count();
121
122    Self {
123      total_issues: errors.len(),
124      errors: errors_count,
125      warnings: warnings_count,
126      info: info_count,
127      auto_fixable: 0, // Would need to implement auto-fix detection
128      is_valid: errors_count == 0,
129    }
130  }
131}