main
Colby Knox Publish 0.1.0 fb6e12f 11d ago
mod cli;
mod convert;
mod output;
mod resend;
mod sendgrid;
mod server;
mod settings;
mod store;

use std::sync::Arc;

use clap::Parser;
use cli::{Cli, Command};

fn main() {
    let cli = Cli::parse();
    match cli.command {
        Command::Serve { port, dev, open_tab } => {
            if let Err(e) = serve(port, dev, open_tab) {
                output::err(e);
                std::process::exit(1);
            }
        }
        Command::Health { port } => health(port),
        Command::Install => {
            output::ok(format!("adom-resend-studio v{} installed", env!("CARGO_PKG_VERSION")));
        }
    }
}

fn serve(port: u16, dev: bool, open_tab: bool) -> anyhow::Result<()> {
    let dir = settings::data_dir();
    let settings = settings::Settings::load(&dir)?;
    if settings.resend_key().0.is_none() {
        output::hint("No Resend API key yet: open the studio and add one in Settings (or set RESEND_API_KEY).");
    }
    let db_path = std::env::var("RESEND_STUDIO_DB")
        .unwrap_or_else(|_| dir.join("resend-studio.db").display().to_string());
    let state = Arc::new(server::AppState::new(dev, port, &db_path, settings)?);
    if open_tab {
        open_hydrogen_tab(port);
    }
    server::run(port, state)
}

fn health(port: u16) {
    match ureq::get(&format!("http://127.0.0.1:{port}/health")).call() {
        Ok(resp) => {
            let body: serde_json::Value = resp.into_json().unwrap_or_default();
            output::ok(format!(
                "adom-resend-studio is reachable on port {port} (version {}).",
                body.get("version").and_then(|v| v.as_str()).unwrap_or("unknown")
            ));
        }
        Err(e) => {
            output::err(format!("Cannot reach adom-resend-studio on port {port}: {e}"));
            output::hint(format!("Start it with `adom-resend-studio serve --port {port} &`"));
            std::process::exit(1);
        }
    }
}

/// Opens the app in a NEW Hydrogen pane (split off the first panel) rather
/// than as a tab inside whatever is focused, which is usually the editor.
fn open_hydrogen_tab(port: u16) {
    let proxy_url = match std::env::var("VSCODE_PROXY_URI") {
        Ok(template) => template.replace("{{port}}", &port.to_string()),
        Err(_) => format!("http://127.0.0.1:{port}/"),
    };
    let icon = server::icon_data_url();
    let restart = format!("adom-resend-studio serve --port {port}");
    let status = std::process::Command::new("adom-cli")
        .args([
            "hydrogen",
            "webview",
            "open-or-refresh",
            "--name",
            "Resend Studio",
            "--url",
            &proxy_url,
            "--display-icon",
            &icon,
            "--reason",
            "Resend email template editor",
            "--restart",
            &restart,
        ])
        .status();
    match status {
        Ok(s) if s.success() => output::ok("opened Resend Studio in a Hydrogen webview tab"),
        _ => output::hint(format!("couldn't open the webview tab automatically; open {proxy_url} manually.")),
    }
}