use serde::{Deserialize, Serialize};
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub(crate) struct CliError {
pub code: String,
pub message: String,
#[serde(skip_serializing_if = "Option::is_none", default)]
pub request_id: Option<String>,
#[serde(skip_serializing_if = "Option::is_none", default)]
pub details: Option<Box<loonfs_api::ErrorDetails>>,
}
impl From<crate::backend_error::BackendError> for CliError {
fn from(error: crate::backend_error::BackendError) -> Self {
Self {
code: error.code,
message: error.message,
request_id: error.request_id,
details: error.details,
}
}
}
impl CliError {
pub(crate) fn io_for_path(path: &std::path::Path, error: std::io::Error) -> Self {
Self::new(
"io_error",
format!("i/o error for `{}`: {error}", path.display()),
)
}
pub(crate) fn new(code: impl Into<String>, message: impl Into<String>) -> Self {
Self {
code: code.into(),
message: message.into(),
request_id: None,
details: None,
}
}
pub(crate) fn invalid_config(message: impl Into<String>) -> Self {
Self::new("invalid_config", message)
}
pub(crate) fn invalid_input(message: impl Into<String>) -> Self {
Self::new("invalid_input", message)
}
pub(crate) fn profile_not_found(name: &str) -> Self {
Self::new("profile_not_found", format!("profile `{name}` not found"))
}
pub(crate) fn no_default_profile() -> Self {
Self::new(
"no_default_profile",
"no default profile is set; use `profile use` or `--profile`",
)
}
pub(crate) fn no_default_namespace(profile: &str) -> Self {
Self::new(
"no_default_namespace",
format!(
"no default namespace is set for profile `{profile}`; use `loonfs use <namespace>` or `--namespace`"
),
)
}
pub(crate) fn profile_already_exists(name: &str) -> Self {
Self::new(
"profile_already_exists",
format!("profile `{name}` already exists"),
)
}
pub(crate) fn config_already_exists(path: &str) -> Self {
Self::new(
"config_already_exists",
format!(
"config file already exists at `{path}`. use `loonfs profile create` to create a new profile, `loonfs profile update` to modify an existing profile, or `loonfs profile use` to change the default profile"
),
)
}
pub(crate) fn non_interactive_input_required(requirement: impl Into<String>) -> Self {
Self::new("non_interactive_input_required", requirement)
}
pub(crate) fn non_interactive_field_required(field: &str) -> Self {
Self::non_interactive_input_required(format!(
"missing required `{field}` while `--no-input` is active"
))
}
pub(crate) fn destination_exists(path: &std::path::Path) -> Self {
Self::new(
"destination_exists",
format!(
"local file `{}` already exists; pass --force to overwrite",
path.display()
),
)
}
pub(crate) fn invalid_usage(message: impl Into<String>) -> Self {
Self::new("invalid_usage", message)
}
pub(crate) fn json_not_supported_for_streaming() -> Self {
Self::new(
"json_not_supported_for_streaming",
"streaming commands do not support `--json`",
)
}
pub(crate) fn io(error: std::io::Error) -> Self {
Self::new("io_error", format!("i/o error: {error}"))
}
pub(crate) fn cancelled() -> Self {
Self::new("cancelled", "operation cancelled")
}
}