warpgate 0.36.2

Download, resolve, and manage Extism WASM plugins.
Documentation
#![allow(unused_assignments)]

use crate::clients::WarpgateHttpClientError;
use oci_client::Reference;
use oci_client::errors::OciDistributionError;
use starbase_archive::ArchiveError;
use starbase_styles::{Style, Stylize};
use starbase_utils::fs::FsError;
use starbase_utils::glob::GlobError;
use starbase_utils::hash::base64::native::DecodeError;
use starbase_utils::net::NetError;
use std::path::PathBuf;
use thiserror::Error;
use warpgate_api::Id;

/// Loader errors.
#[derive(Debug, Error)]
#[cfg_attr(feature = "miette", derive(miette::Diagnostic))]
pub enum WarpgateLoaderError {
    #[cfg_attr(feature = "miette", diagnostic(transparent))]
    #[error(transparent)]
    Archive(#[from] Box<ArchiveError>),

    #[cfg_attr(feature = "miette", diagnostic(transparent))]
    #[error(transparent)]
    Fs(#[from] Box<FsError>),

    #[cfg_attr(feature = "miette", diagnostic(transparent))]
    #[error(transparent)]
    HttpClient(#[from] Box<WarpgateHttpClientError>),

    #[cfg_attr(feature = "miette", diagnostic(transparent))]
    #[error(transparent)]
    Glob(#[from] Box<GlobError>),

    #[cfg_attr(feature = "miette", diagnostic(code(plugin::loader::failed_download)))]
    #[error(
        "Failed to download plugin from {}.",
        .url.style(Style::Url),
    )]
    FailedDownload {
        url: String,
        #[source]
        error: Box<NetError>,
    },

    #[cfg_attr(
        feature = "miette",
        diagnostic(code(plugin::loader::github::asset_missing))
    )]
    #[error(
        "Cannot download {} plugin from GitHub ({}), no applicable asset found for release {}.",
        .id.to_string().style(Style::Id),
        .repo_slug.style(Style::Id),
        .tag,
    )]
    MissingGitHubAsset {
        id: Id,
        repo_slug: String,
        tag: String,
    },

    #[cfg_attr(
        feature = "miette",
        diagnostic(code(plugin::loader::github::unknown_tag))
    )]
    #[error(
        "Cannot download {} plugin from GitHub ({}), no tag found, matched, or provided.",
        .id.to_string().style(Style::Id),
        .repo_slug.style(Style::Id),
    )]
    MissingGitHubTag { id: Id, repo_slug: String },

    #[cfg_attr(feature = "miette", diagnostic(code(plugin::loader::file::missing)))]
    #[error(
        "Cannot load {} plugin, source file {} does not exist.",
        .id.to_string().style(Style::Id),
        .path.style(Style::Path),
    )]
    MissingSourceFile { id: Id, path: PathBuf },

    #[cfg_attr(feature = "miette", diagnostic(code(plugin::loader::no_wasm)))]
    #[error(
        "No applicable {} file could be found in downloaded plugin {}.",
        ".wasm".style(Style::File),
        .path.style(Style::Path),
    )]
    NoWasmFound { path: PathBuf },

    #[cfg_attr(
        feature = "miette",
        diagnostic(
            code(plugin::loader::not_found),
            help = "Please refer to the plugin's official documentation."
        )
    )]
    #[error(
        "Plugin download {} does not exist. Either this version may not be supported for your current operating system or architecture, or the URL is incorrect or malformed.",
        .url.style(Style::Url),
    )]
    NotFound { url: String },

    #[cfg_attr(feature = "miette", diagnostic(code(plugin::offline)))]
    #[error(
        "{message} An internet connection is required for {}.",
        .locator.style(Style::Url),
    )]
    RequiredInternetConnection { message: String, locator: String },

    #[cfg_attr(
        feature = "miette",
        diagnostic(code(plugin::loader::unsupported_extension))
    )]
    #[error(
        "Unsupported file extension {} for downloaded plugin {}.",
        .ext.style(Style::File),
        .path.style(Style::Path),
    )]
    UnsupportedDownloadExtension { ext: String, path: PathBuf },

    #[cfg_attr(feature = "miette", diagnostic(code(plugin::loader::unknown_type)))]
    #[error(
        "Unsure how to handle downloaded plugin {} as no file extension/type could be derived.",
        .path.style(Style::Path),
    )]
    UnknownDownloadType { path: PathBuf },

    #[cfg_attr(
        feature = "miette",
        diagnostic(code(plugin::loader::registry::load_failure))
    )]
    #[error(
        "Failed to load plugin from {} registry.",
        .reference.to_string().style(Style::Path),
    )]
    OciDistributionError {
        #[source]
        error: Box<OciDistributionError>,
        reference: Box<Reference>,
    },

    #[cfg_attr(
        feature = "miette",
        diagnostic(code(plugin::loader::registry::reference_failure))
    )]
    #[error("OCI reference error: {message}")]
    OCIReferenceError { message: String },

    #[cfg_attr(
        feature = "miette",
        diagnostic(code(plugin::loader::data::decode_failure))
    )]
    #[error("Failed to decode base64 data for plugin.")]
    Base64DecodeError {
        #[source]
        error: Box<DecodeError>,
    },
}

impl From<ArchiveError> for WarpgateLoaderError {
    fn from(e: ArchiveError) -> WarpgateLoaderError {
        WarpgateLoaderError::Archive(Box::new(e))
    }
}

impl From<WarpgateHttpClientError> for WarpgateLoaderError {
    fn from(e: WarpgateHttpClientError) -> WarpgateLoaderError {
        WarpgateLoaderError::HttpClient(Box::new(e))
    }
}

impl From<FsError> for WarpgateLoaderError {
    fn from(e: FsError) -> WarpgateLoaderError {
        WarpgateLoaderError::Fs(Box::new(e))
    }
}

impl From<GlobError> for WarpgateLoaderError {
    fn from(e: GlobError) -> WarpgateLoaderError {
        WarpgateLoaderError::Glob(Box::new(e))
    }
}