nbi 0.1.7

TUI for checking package name availability across npm, crates.io, PyPI, .dev domains and registering via GitHub
use anyhow::Result;
use directories::ProjectDirs;
use serde::{Deserialize, Serialize};
use std::fs;
use std::path::PathBuf;

const APP_NAME: &str = "nbi";

#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct RegistrySettings {
  pub npm: bool,
  pub crates: bool,
  pub pypi: bool,
  pub brew: bool,
  pub flatpak: bool,
  pub debian: bool,
  pub dev_domain: bool,
}

impl Default for RegistrySettings {
  fn default() -> Self {
    Self {
      npm: true,
      crates: true,
      pypi: true,
      brew: true,
      flatpak: true,
      debian: true,
      dev_domain: true,
    }
  }
}

#[derive(Debug, Clone, Serialize, Deserialize, Default)]
pub struct Config {
  pub github_token: Option<String>,
  #[serde(default)]
  pub registries: RegistrySettings,
}

impl Config {
  /// Get the config file path
  fn config_path() -> Option<PathBuf> {
    ProjectDirs::from("", "", APP_NAME).map(|dirs| dirs.config_dir().join("config.toml"))
  }

  /// Load config from file
  pub fn load() -> Result<Self> {
    let path =
      Self::config_path().ok_or_else(|| anyhow::anyhow!("Could not find config directory"))?;

    if !path.exists() {
      return Ok(Self::default());
    }

    let content = fs::read_to_string(&path)?;
    let config: Config = toml::from_str(&content)?;
    Ok(config)
  }

  /// Save config to file
  pub fn save(&self) -> Result<()> {
    let path =
      Self::config_path().ok_or_else(|| anyhow::anyhow!("Could not find config directory"))?;

    if let Some(parent) = path.parent() {
      fs::create_dir_all(parent)?;
    }

    let content = toml::to_string_pretty(self)?;
    fs::write(&path, content)?;
    Ok(())
  }

  /// Set GitHub token and save
  #[allow(dead_code)]
  pub fn set_github_token(&mut self, token: String) -> Result<()> {
    self.github_token = Some(token);
    self.save()
  }

  /// Get GitHub token from config or environment
  pub fn get_github_token(&self) -> Option<String> {
    self.github_token
      .clone()
      .or_else(|| std::env::var("GITHUB_TOKEN").ok())
  }
}