//! Forgejo client implementation //! //! Forgejo API is fully compatible with Gitea API, so this implementation //! uses composition to wrap GiteaClient and delegate all operations to it. //! This allows Forgejo instances to work seamlessly with the same interface //! while maintaining independent backend identification. use async_trait::async_trait; use bytes::Bytes; use super::traits::{BackendType, ExtensionClient, ReleaseInfo, SourceClient}; use crate::error::Result; use crate::models::{Extension, ExtensionType, ExtensionVersion}; /// Forgejo client (wraps GiteaClient since Forgejo API is Gitea-compatible) pub struct ForgejoClient { backend_id: String, inner: crate::gitea::GiteaClient, } impl ForgejoClient { /// Create new Forgejo client from Gitea config pub fn new(config: &crate::config::GiteaConfig) -> Result { let backend_id = config .id .clone() .unwrap_or_else(|| format!("forgejo-{}", config.organization)); let inner = crate::gitea::GiteaClient::new(config)?; Ok(Self { backend_id, inner }) } } /// ExtensionClient trait implementation for Forgejo #[async_trait] impl ExtensionClient for ForgejoClient { fn backend_id(&self) -> &str { &self.backend_id } fn backend_type(&self) -> BackendType { BackendType::Forgejo } async fn list_extensions( &self, extension_type: Option, ) -> Result> { self.inner.list_extensions(extension_type).await } async fn get_extension(&self, extension_type: ExtensionType, name: &str) -> Result { self.inner.get_extension(extension_type, name).await } async fn list_versions( &self, extension_type: ExtensionType, name: &str, ) -> Result> { self.inner.list_versions(extension_type, name).await } async fn download_extension( &self, extension_type: ExtensionType, name: &str, version: &str, ) -> Result { self.inner .download_extension(extension_type, name, version) .await } async fn health_check(&self) -> Result<()> { self.inner.health_check().await } } /// SourceClient trait implementation for Forgejo #[async_trait] impl SourceClient for ForgejoClient { async fn get_repository_url( &self, extension_type: ExtensionType, name: &str, ) -> Result { self.inner.get_repository_url(extension_type, name).await } async fn list_releases(&self, repo_name: &str) -> Result> { self.inner.list_releases(repo_name).await } async fn get_release_notes(&self, repo_name: &str, version: &str) -> Result { self.inner.get_release_notes(repo_name, version).await } }