use async_trait::async_trait;
use crate::models::{PullRequest, PrIdentifier};
pub mod registry;
pub mod mock;
pub mod github;
pub mod bitbucket;
#[derive(Debug, Clone, PartialEq)]
pub enum AuthStatus {
Available,
Missing { reason: String },
}
#[derive(Debug, thiserror::Error)]
pub enum ProviderError {
#[error("Auth not available for provider '{provider}': {reason}")]
AuthMissing { provider: String, reason: String },
#[error("API request failed for '{provider}': HTTP {status} — {message}")]
ApiError { provider: String, status: u16, message: String },
#[error("Rate limit exceeded for '{provider}', resets at {reset_at}")]
RateLimited { provider: String, reset_at: chrono::DateTime<chrono::Utc> },
#[error("Failed to parse response from '{provider}': {message}")]
ParseError { provider: String, message: String },
#[error("Operation not implemented for provider '{provider}'")]
NotImplemented { provider: String },
#[error("I/O error for provider '{provider}': {message}")]
IoError { provider: String, message: String },
}
#[async_trait]
pub trait Provider: Send + Sync {
fn name(&self) -> &'static str;
fn display_name(&self) -> &'static str;
async fn check_auth(&self) -> AuthStatus;
async fn list_prs(&self) -> Result<Vec<PullRequest>, ProviderError>;
async fn get_pr_details(&self, pr_id: &PrIdentifier) -> Result<PullRequest, ProviderError>;
async fn get_pr_diff(&self, pr_id: &PrIdentifier) -> Result<String, ProviderError>;
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn provider_error_display() {
let e = ProviderError::NotImplemented { provider: "mock".to_string() };
assert!(e.to_string().to_lowercase().contains("not implemented"));
}
}