claude_code_toolkit/providers/
mod.rs

1//! External service provider integrations for credential synchronization.
2//!
3//! This module contains provider implementations for various external services
4//! like GitHub, following the Repository Pattern and Dependency Injection principles.
5//! Providers handle secure credential synchronization, API interactions, and
6//! service-specific configuration management.
7//!
8//! ## Supported Providers
9//!
10//! - [`github`] - GitHub API integration for repository and organization sync
11//! - [`registry`] - Provider registry management and factory patterns
12//!
13//! ## Provider Architecture
14//!
15//! The provider system uses several design patterns:
16//!
17//! - **Factory Pattern**: [`ProviderFactory`] creates providers dynamically
18//! - **Repository Pattern**: Providers implement [`SecretProvider`] trait
19//! - **Dependency Injection**: Providers receive configuration via constructor
20//!
21//! ## Usage Examples
22//!
23//! ### Using the Provider Factory
24//!
25//! ```rust,no_run
26//! use claude_code_toolkit::providers::ProviderFactory;
27//! use std::collections::HashMap;
28//!
29//! #[tokio::main]
30//! async fn main() -> claude_code_toolkit::Result<()> {
31//!     let factory = ProviderFactory::new();
32//!     
33//!     // List available providers
34//!     let providers = factory.available_providers();
35//!     println!("Available providers: {:?}", providers);
36//!     
37//!     // Create a GitHub provider
38//!     let mut config = HashMap::new();
39//!     config.insert("token".to_string(), "your-github-token".to_string());
40//!     config.insert("org".to_string(), "your-org".to_string());
41//!     
42//!     let provider = factory.create("github", &config)?;
43//!     // Use provider for operations...
44//!     
45//!     Ok(())
46//! }
47//! ```
48//!
49//! ### Direct Provider Usage
50//!
51//! ```rust,no_run
52//! use claude_code_toolkit::providers::github::GitHubProvider;
53//! use std::collections::HashMap;
54//!
55//! #[tokio::main]
56//! async fn main() -> claude_code_toolkit::Result<()> {
57//!     let mut config = HashMap::new();
58//!     config.insert("token".to_string(), "your-token".to_string());
59//!     
60//!     let provider = GitHubProvider::new(config)?;
61//!     
62//!     // Use provider for operations...
63//!     
64//!     Ok(())
65//! }
66//! ```
67//!
68//! ## Configuration Requirements
69//!
70//! Each provider has specific configuration requirements:
71//!
72//! ### GitHub Provider
73//! - **Required**: `token` (GitHub personal access token)
74//! - **Optional**: `org` (default organization), `base_url` (GitHub Enterprise URL)
75//!
76//! ## Security Considerations
77//!
78//! - All API tokens are stored securely and never logged
79//! - Network communications use HTTPS with certificate validation
80//! - Sensitive configuration is validated before use
81//! - Rate limiting and retry logic prevent API abuse
82
83pub mod github;
84pub mod registry;
85
86use crate::error::Result;
87use crate::traits::SecretProvider;
88use std::collections::HashMap;
89
90/// Provider factory following Factory Pattern
91pub struct ProviderFactory {
92  creators: HashMap<String, Box<dyn ProviderCreator>>,
93}
94
95impl ProviderFactory {
96  pub fn new() -> Self {
97    let mut factory = Self {
98      creators: HashMap::new(),
99    };
100
101    // Register built-in providers
102    factory.register("github", Box::new(github::GitHubProviderCreator));
103
104    factory
105  }
106
107  pub fn register(&mut self, name: &str, creator: Box<dyn ProviderCreator>) {
108    self.creators.insert(name.to_string(), creator);
109  }
110
111  pub fn create(
112    &self,
113    name: &str,
114    config: &HashMap<String, String>
115  ) -> Result<Box<dyn SecretProvider>> {
116    let creator = self.creators
117      .get(name)
118      .ok_or_else(|| {
119        crate::error::ClaudeCodeError::Generic(format!("Unknown provider: {}", name))
120      })?;
121
122    creator.create(config)
123  }
124
125  pub fn available_providers(&self) -> Vec<&str> {
126    self.creators
127      .keys()
128      .map(|s| s.as_str())
129      .collect()
130  }
131}
132
133impl Default for ProviderFactory {
134  fn default() -> Self {
135    Self::new()
136  }
137}
138
139/// Provider creator trait for Factory Pattern
140pub trait ProviderCreator: Send + Sync {
141  fn create(&self, config: &HashMap<String, String>) -> Result<Box<dyn SecretProvider>>;
142  fn provider_type(&self) -> &str;
143  fn required_config(&self) -> Vec<&str>;
144  fn optional_config(&self) -> Vec<&str> {
145    Vec::new()
146  }
147}
148
149/// Base provider implementation with common functionality
150pub struct BaseProvider {
151  pub name: String,
152  pub config: HashMap<String, String>,
153}
154
155impl BaseProvider {
156  pub fn new(name: &str, config: HashMap<String, String>) -> Self {
157    Self {
158      name: name.to_string(),
159      config,
160    }
161  }
162
163  pub fn get_config(&self, key: &str) -> Option<&String> {
164    self.config.get(key)
165  }
166
167  pub fn require_config(&self, key: &str) -> Result<&String> {
168    self
169      .get_config(key)
170      .ok_or_else(|| {
171        crate::error::ClaudeCodeError::Generic(format!("Missing required config: {}", key))
172      })
173  }
174}