feat(xy): clap CLI scaffold
This commit is contained in:
@@ -0,0 +1,10 @@
|
||||
use crate::paths::Paths;
|
||||
use anyhow::{bail, Result};
|
||||
|
||||
pub async fn list(_p: Paths) -> Result<i32> { bail!("not implemented") }
|
||||
pub async fn status(_p: Paths, _name: String) -> Result<i32> { bail!("not implemented") }
|
||||
pub async fn start(_p: Paths, _all: bool, _name: Option<String>) -> Result<i32> { bail!("not implemented") }
|
||||
pub async fn stop(_p: Paths, _all: bool, _name: Option<String>) -> Result<i32> { bail!("not implemented") }
|
||||
pub async fn restart(_p: Paths, _all: bool, _name: Option<String>) -> Result<i32> { bail!("not implemented") }
|
||||
pub async fn reload(_p: Paths) -> Result<i32> { bail!("not implemented") }
|
||||
pub async fn logs(_p: Paths, _name: String, _tail: Option<u32>, _follow: bool) -> Result<i32> { bail!("not implemented") }
|
||||
@@ -0,0 +1,4 @@
|
||||
use crate::paths::Paths;
|
||||
use anyhow::{bail, Result};
|
||||
|
||||
pub async fn run(_paths: Paths) -> Result<()> { bail!("not implemented") }
|
||||
+73
-4
@@ -1,8 +1,77 @@
|
||||
use clap::{Parser, Subcommand};
|
||||
|
||||
mod cli;
|
||||
mod daemon;
|
||||
mod paths;
|
||||
#[allow(dead_code)]
|
||||
mod pidfile;
|
||||
|
||||
fn main() {
|
||||
let p = paths::Paths::resolve().unwrap();
|
||||
eprintln!("xy: socket would be at {}", p.socket.display());
|
||||
#[derive(Debug, Parser)]
|
||||
#[command(name = "xy", version, about = "HTTP MCP server supervisor")]
|
||||
struct Cli {
|
||||
#[command(subcommand)]
|
||||
cmd: Cmd,
|
||||
}
|
||||
|
||||
#[derive(Debug, Subcommand)]
|
||||
enum Cmd {
|
||||
/// Run the daemon in the foreground.
|
||||
Daemon,
|
||||
/// List all configured servers with state.
|
||||
List,
|
||||
/// Show detailed status for a single server.
|
||||
Status { name: String },
|
||||
/// Start a server (or all configured servers with --all).
|
||||
Start {
|
||||
#[arg(long, conflicts_with = "name")] all: bool,
|
||||
#[arg(required_unless_present = "all")] name: Option<String>,
|
||||
},
|
||||
/// Stop a server (or --all).
|
||||
Stop {
|
||||
#[arg(long, conflicts_with = "name")] all: bool,
|
||||
#[arg(required_unless_present = "all")] name: Option<String>,
|
||||
},
|
||||
/// Restart a server (or --all).
|
||||
Restart {
|
||||
#[arg(long, conflicts_with = "name")] all: bool,
|
||||
#[arg(required_unless_present = "all")] name: Option<String>,
|
||||
},
|
||||
/// Re-read config dir and reconcile running servers.
|
||||
Reload,
|
||||
/// Stream a server's log.
|
||||
Logs {
|
||||
name: String,
|
||||
#[arg(long)] tail: Option<u32>,
|
||||
#[arg(short = 'f', long)] follow: bool,
|
||||
},
|
||||
}
|
||||
|
||||
#[tokio::main]
|
||||
async fn main() -> std::process::ExitCode {
|
||||
tracing_subscriber::fmt()
|
||||
.with_env_filter(tracing_subscriber::EnvFilter::try_from_default_env()
|
||||
.unwrap_or_else(|_| tracing_subscriber::EnvFilter::new("info")))
|
||||
.with_writer(std::io::stderr)
|
||||
.init();
|
||||
|
||||
let cli = Cli::parse();
|
||||
let paths = match paths::Paths::resolve() {
|
||||
Ok(p) => p,
|
||||
Err(e) => { eprintln!("xy: failed to resolve XDG paths: {e}"); return std::process::ExitCode::from(3); }
|
||||
};
|
||||
|
||||
let result: anyhow::Result<i32> = match cli.cmd {
|
||||
Cmd::Daemon => daemon::run(paths).await.map(|_| 0),
|
||||
Cmd::List => cli::list(paths).await,
|
||||
Cmd::Status { name } => cli::status(paths, name).await,
|
||||
Cmd::Start { all, name } => cli::start(paths, all, name).await,
|
||||
Cmd::Stop { all, name } => cli::stop(paths, all, name).await,
|
||||
Cmd::Restart { all, name } => cli::restart(paths, all, name).await,
|
||||
Cmd::Reload => cli::reload(paths).await,
|
||||
Cmd::Logs { name, tail, follow } => cli::logs(paths, name, tail, follow).await,
|
||||
};
|
||||
|
||||
match result {
|
||||
Ok(code) => std::process::ExitCode::from(code as u8),
|
||||
Err(e) => { eprintln!("xy: {e:#}"); std::process::ExitCode::from(1) }
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user