jax-daemon 0.1.10

End-to-end encrypted storage buckets with peer-to-peer synchronization
Documentation
// CLI modules
mod cli;

use clap::{Parser, Subcommand};
use cli::{args::Args, op::Op, Bucket, Daemon, Health, Init, Update, Version};
use std::io::IsTerminal;

use owo_colors::OwoColorize;

#[cfg(feature = "fuse")]
use cli::Mount;

#[cfg(feature = "fuse")]
command_enum! {
    (Bucket, Bucket),
    (Daemon, Daemon),
    (Health, Health),
    (Init, Init),
    (Mount, Mount),
    (Update, Update),
    (Version, Version),
}

#[cfg(not(feature = "fuse"))]
command_enum! {
    (Bucket, Bucket),
    (Daemon, Daemon),
    (Health, Health),
    (Init, Init),
    (Update, Update),
    (Version, Version),
}

#[tokio::main]
async fn main() {
    let args = Args::parse();

    // Resolve remote URL: explicit flag > config api_port > hardcoded 5001
    let remote = cli::op::resolve_remote(args.remote, args.config_path.clone());

    // Build context - always has API client initialized
    let mp = indicatif::MultiProgress::new();
    if !std::io::stdout().is_terminal() {
        mp.set_draw_target(indicatif::ProgressDrawTarget::hidden());
    }

    let ctx = match cli::op::OpContext::new(remote, args.config_path, mp) {
        Ok(ctx) => ctx,
        Err(e) => {
            print_error(&e);
            std::process::exit(1);
        }
    };

    match args.command.execute(&ctx).await {
        Ok(output) => {
            println!("{output}");
            std::process::exit(0);
        }
        Err(e) => {
            print_error(&e);
            std::process::exit(1);
        }
    }
}

fn print_error(e: &dyn std::error::Error) {
    eprintln!("{} {e}", "error:".red().bold());
    let mut source = e.source();
    while let Some(cause) = source {
        eprintln!("  {} {cause}", "caused by:".yellow());
        source = cause.source();
    }
}