use super::{KeyArgs, Location, NpmrcEdit, aube_config, resolve_aliases, setting_for_key};
use miette::miette;
use std::path::{Path, PathBuf};
pub type DeleteArgs = KeyArgs;
pub fn run(args: DeleteArgs) -> miette::Result<()> {
let aliases = resolve_aliases(&args.key);
let location = args.effective_location();
let meta = aube_config::is_aube_config_key(&args.key);
let key_is_npm_shared = super::is_npm_shared_key(&args.key);
if let Some(handled) = try_delete_aube_map_entry(&args.key, location)? {
return Ok(handled);
}
let mut removed_paths: Vec<PathBuf> = Vec::new();
if let Some(meta) = meta
&& matches!(location, Location::Project)
&& let Some(yaml_path) =
aube_manifest::workspace::workspace_yaml_existing(&crate::dirs::project_root_or_cwd()?)
&& aube_config::remove_workspace_yaml_aliases(&yaml_path, meta)?
{
removed_paths.push(yaml_path);
}
let config_path = match location {
Location::User | Location::Global => aube_config::user_aube_config_path()?,
Location::Project => {
aube_config::project_aube_config_path(&crate::dirs::project_root_or_cwd()?)
}
};
let mut config_edit = aube_config::AubeConfigEdit::load(&config_path)?;
let mut sweep: Vec<String> = aliases.clone();
if let Some(meta) = meta
&& !sweep.iter().any(|s| s == meta.name)
{
sweep.push(meta.name.to_string());
}
if !sweep.iter().any(|s| s == &args.key) {
sweep.push(args.key.clone());
}
if config_edit.remove_aliases(&sweep) {
config_edit.save(&config_path)?;
removed_paths.push(config_path.clone());
}
let should_sweep_npmrc = key_is_npm_shared || meta.is_none();
let npmrc_path = location.path()?;
if should_sweep_npmrc && npmrc_path.exists() {
let mut edit = NpmrcEdit::load(&npmrc_path)?;
let mut removed = false;
for alias in &aliases {
if edit.remove(alias) {
removed = true;
}
}
if !aliases.iter().any(|a| a == &args.key) && edit.remove(&args.key) {
removed = true;
}
if removed {
edit.save(&npmrc_path)?;
removed_paths.push(npmrc_path.clone());
}
}
if removed_paths.is_empty() {
if let Some(_meta) = meta
&& !key_is_npm_shared
{
return Err(missing_aube_key_error(
&args.key,
&aliases,
&config_path,
location,
));
}
return Err(miette!(
"{} not set in aube config or {}",
args.key,
npmrc_path.display()
));
}
let joined = removed_paths
.iter()
.map(|p| p.display().to_string())
.collect::<Vec<_>>()
.join(", ");
eprintln!("deleted {} ({})", args.key, joined);
Ok(())
}
fn try_delete_aube_map_entry(key: &str, location: Location) -> miette::Result<Option<()>> {
let Some((prefix, entry)) = key.split_once('.') else {
return Ok(None);
};
let Some(meta) = setting_for_key(prefix) else {
return Ok(None);
};
if meta.type_ != "object" {
return Ok(None);
}
if aube_config::is_aube_config_key(key).is_some() {
return Ok(None);
}
if !matches!(location, Location::Project) {
return Err(miette!(
"`{key}` only applies at project scope: `{prefix}` is read from `pnpm-workspace.yaml` / `package.json#<pnpm|aube>.{prefix}`, not user-scope aube config.\n\
use `aube config delete --local {prefix}.{entry}` to remove it from the project workspace yaml / `package.json`.",
));
}
let cwd = crate::dirs::project_root_or_cwd()?;
let removed = aube_manifest::workspace::remove_map_entry(&cwd, meta.name, entry)
.map_err(|e| miette!("failed to remove {}.{entry}: {e}", meta.name))?;
if !removed {
return Err(miette!(
"{}.{entry} not set in `pnpm-workspace.yaml` or `package.json`",
meta.name,
));
}
eprintln!("deleted {}.{entry} ({})", meta.name, cwd.display());
Ok(Some(()))
}
fn missing_aube_key_error(
key: &str,
aliases: &[String],
config_path: &Path,
location: Location,
) -> miette::Report {
if let Ok(npmrc_path) = location.path()
&& npmrc_path.exists()
&& let Ok(edit) = NpmrcEdit::load(&npmrc_path)
&& edit.entries().iter().any(|(k, _)| aliases.contains(k))
{
return miette!(
"{key} is not set in {} but an entry exists in {}.\n\
aube doesn't modify `.npmrc` for aube-only settings (it's shared with \
npm/pnpm/yarn) — edit that file directly to remove it, or run \
`aube config set {key} <value>` to override it from {}.",
config_path.display(),
npmrc_path.display(),
config_path.display(),
);
}
miette!("{key} not set in {}", config_path.display())
}