rh-foundation 0.2.0

Foundation crate providing common utilities, error handling, and shared functionality
Documentation
use url::Url;

use crate::http::HttpClient;

use super::{LoaderError, LoaderResult, PackageManifest, RegistryResponse};

pub(super) async fn fetch_registry_response(
    http_client: &HttpClient,
    registry_url: &str,
    package_name: &str,
) -> LoaderResult<RegistryResponse> {
    let registry_url = Url::parse(registry_url)?;
    let package_url = registry_url.join(package_name)?;

    tracing::debug!("Fetching registry response from: {}", package_url);

    http_client
        .download_json(package_url.as_str())
        .await
        .map_err(|_| LoaderError::PackageNotFound {
            package: package_name.to_string(),
            version: "any".to_string(),
        })
}

pub(super) fn sorted_versions(response: &RegistryResponse) -> Vec<String> {
    let mut versions: Vec<String> = response.versions.keys().cloned().collect();
    versions.sort();
    versions
}

pub(super) fn latest_version(
    package_name: &str,
    response: &RegistryResponse,
) -> LoaderResult<String> {
    if let Some(dist_tags) = &response.dist_tags {
        if let Some(latest) = dist_tags.get("latest") {
            return Ok(latest.clone());
        }
    }

    sorted_versions(response)
        .last()
        .cloned()
        .ok_or_else(|| LoaderError::PackageNotFound {
            package: package_name.to_string(),
            version: "latest".to_string(),
        })
}

pub(super) fn package_manifest(
    package_name: &str,
    version: &str,
    response: &RegistryResponse,
) -> LoaderResult<PackageManifest> {
    response
        .versions
        .get(version)
        .cloned()
        .ok_or_else(|| LoaderError::PackageNotFound {
            package: package_name.to_string(),
            version: version.to_string(),
        })
}