use anyhow::{anyhow, Result};
use clap::{Args, Subcommand};
use crate::client::RommClient;
use crate::commands::OutputFormat;
#[derive(Args, Debug)]
pub struct ApiCommand {
#[command(subcommand)]
pub action: Option<ApiAction>,
pub method: Option<String>,
pub path: Option<String>,
#[arg(long = "query", global = true)]
pub query: Vec<String>,
#[arg(long, global = true)]
pub data: Option<String>,
}
#[derive(Subcommand, Debug)]
pub enum ApiAction {
Call {
method: String,
path: String,
},
Get {
path: String,
},
Post {
path: String,
},
}
pub async fn handle(cmd: ApiCommand, client: &RommClient, format: OutputFormat) -> Result<()> {
let (method, path) = match cmd.action {
Some(ApiAction::Call { method, path }) => (method, path),
Some(ApiAction::Get { path }) => ("GET".to_string(), path),
Some(ApiAction::Post { path }) => ("POST".to_string(), path),
None => {
let m = cmd
.method
.ok_or_else(|| anyhow!("Method is required (e.g. 'api call GET /api/roms')"))?;
let p = cmd
.path
.ok_or_else(|| anyhow!("Path is required (e.g. 'api call GET /api/roms')"))?;
(m, p)
}
};
let mut query_pairs = Vec::new();
for q in &cmd.query {
if let Some((k, v)) = q.split_once('=') {
query_pairs.push((k.to_string(), v.to_string()));
} else {
eprintln!(
"warning: ignoring malformed --query value {:?}; expected key=value",
q
);
}
}
let body = if let Some(data) = &cmd.data {
Some(serde_json::from_str(data)?)
} else {
None
};
let value = client
.request_json(&method, &path, &query_pairs, body)
.await?;
match format {
OutputFormat::Json => {
println!("{}", serde_json::to_string_pretty(&value)?);
}
OutputFormat::Text => {
println!("{}", serde_json::to_string_pretty(&value)?);
}
}
Ok(())
}