envoy-cli 0.1.3-hotfix

A Git-like CLI for managing encrypted environment files
use console::style;
use indicatif::{ProgressBar, ProgressStyle};
use reqwest::Client;
use std::fs;
use std::path::Path;

use crate::{
    commands::auth::login,
    utils::config::{auth_server_url, load_token},
};

#[derive(serde::Deserialize)]
struct CreateProjectResponse {
    #[serde(rename = "projectId")]
    project_id: String,
}

pub async fn ensure_logged_in() -> anyhow::Result<String> {
    match load_token() {
        Ok(token) => Ok(token),
        Err(_) => {
            login().await?;
            load_token()
        }
    }
}

use std::fs::OpenOptions;
use std::io::Write;

pub fn ensure_gitignore() -> anyhow::Result<()> {
    let path = Path::new(".gitignore");

    let envoy_block = r#"
# Envoy

!.envoy/

.envoy/cache/
.envoy/*.blob

"#;

    let existing = if path.exists() {
        fs::read_to_string(path)?
    } else {
        String::new()
    };

    if existing.contains(".envoy/cache/") {
        return Ok(());
    }

    let mut file = OpenOptions::new().create(true).append(true).open(path)?;

    if !existing.ends_with('\n') && !existing.is_empty() {
        writeln!(file)?;
    }

    writeln!(file, "{}", envoy_block)?;

    Ok(())
}

pub async fn init_project(name: Option<String>) -> anyhow::Result<()> {
    let api_token = ensure_logged_in().await?;

    let root = Path::new(".envoy");

    if root.exists() {
        println!(
            "{} {}",
            style("").cyan(),
            style("Envoy project already initialized.").cyan()
        );
        return Ok(());
    }

    let spinner = ProgressBar::new_spinner();
    spinner.set_style(
        ProgressStyle::default_spinner()
            .tick_strings(&["", "", "", "", "", "", "", "", "", ""])
            .template("{spinner:.cyan} {msg}")
            .unwrap(),
    );
    spinner.enable_steady_tick(std::time::Duration::from_millis(80));
    spinner.set_message("Creating project...");

    let client = Client::new();
    let res: CreateProjectResponse = client
        .post(format!("{}/projects", auth_server_url()))
        .bearer_auth(&api_token)
        .send()
        .await?
        .json::<CreateProjectResponse>()
        .await?;

    let project_id = res.project_id;

    fs::create_dir(root)?;
    fs::create_dir(root.join("cache"))?;

    let project_name = name.unwrap_or_else(|| "My Envoy Project".to_string());
    let server_url = auth_server_url().to_owned();
    let config = format!(
        r#"
version = 1
project_id = "{}"
name = "{}"

default_remote = "origin"

[remotes]
origin = "{}"


"#,
        project_id, project_name, server_url
    );

    fs::write(root.join("config.toml"), config)?;
    ensure_gitignore()?;
    println!("Envoy project initialized");
    println!("Project ID: {}", project_id);

    Ok(())
}