use std::path::PathBuf;
use std::process::ExitCode;
use clap::{Parser, Subcommand};
use heliosdb_proxy::plugin_registry;
#[derive(Parser)]
#[command(
name = "helios-plugin",
about = "HeliosProxy plugin registry + install"
)]
struct Cli {
#[command(subcommand)]
cmd: Cmd,
}
#[derive(Subcommand)]
enum Cmd {
Install {
name: String,
#[arg(long)]
registry: PathBuf,
#[arg(long)]
dest: PathBuf,
#[arg(long)]
trust_root: Option<PathBuf>,
#[arg(long)]
version: Option<String>,
},
List {
#[arg(long)]
registry: PathBuf,
},
Verify {
wasm: PathBuf,
#[arg(long)]
trust_root: Option<PathBuf>,
#[arg(long)]
sig: Option<PathBuf>,
},
New {
name: String,
#[arg(long, default_value = ".")]
dir: PathBuf,
},
}
fn main() -> ExitCode {
let cli = Cli::parse();
let result = match cli.cmd {
Cmd::Install {
name,
registry,
dest,
trust_root,
version,
} => {
match plugin_registry::install(
®istry,
&name,
version.as_deref(),
&dest,
trust_root.as_deref(),
) {
Ok(r) => {
println!(
"installed {} v{} -> {}",
r.name,
if r.version.is_empty() {
"?"
} else {
&r.version
},
r.wasm_path.display()
);
println!(" sha256: {}", r.sha256);
match r.signed_by {
Some(k) => println!(" signature: verified by '{k}'"),
None if trust_root.is_some() => unreachable!(),
None => println!(" signature: not checked (no trust root)"),
}
Ok(())
}
Err(e) => Err(e),
}
}
Cmd::List { registry } => plugin_registry::load_index(®istry).map(|idx| {
for e in &idx.plugins {
let sig = if e.signature.is_some() {
"signed"
} else {
"unsigned"
};
println!(
"{:<24} {:<10} {:<8} {}",
e.name, e.version, sig, e.description
);
}
}),
Cmd::Verify {
wasm,
trust_root,
sig,
} => plugin_registry::verify(&wasm, trust_root.as_deref(), sig.as_deref()).map(|r| {
println!("{}", wasm.display());
println!(" sha256: {}", r.sha256);
match r.signed_by {
Some(k) => println!(" signature: verified by '{k}'"),
None if trust_root.is_some() => unreachable!(),
None => println!(" signature: not checked (no trust root)"),
}
}),
Cmd::New { name, dir } => plugin_registry::scaffold(&name, &dir).map(|root| {
println!("scaffolded plugin at {}", root.display());
}),
};
match result {
Ok(()) => ExitCode::SUCCESS,
Err(e) => {
eprintln!("error: {e}");
ExitCode::FAILURE
}
}
}