use crate::config::CliConfig;
use std::process::Command;
pub async fn run(env: Option<&str>) -> eyre::Result<()> {
let config = CliConfig::load_with_env(env)?;
if let Some(ref name) = config.env_name {
println!("Environment: {}", name);
}
let output = Command::new("cargo")
.args(["run", "--", "--emit-manifest"])
.output()?;
if !output.status.success() {
eyre::bail!("Failed to build service. Run from a cufflink service directory.");
}
let stdout = String::from_utf8(output.stdout)?;
let manifest: serde_json::Value = serde_json::from_str(stdout.trim())?;
let service_name = manifest["name"].as_str().unwrap_or("unknown");
let client = config.http_client();
let resp = config
.auth_request(
&client,
reqwest::Method::GET,
&format!("{}/api/services", config.api_url),
)
.send()
.await?;
let body: serde_json::Value = resp.json().await?;
let services = body["services"].as_array();
let service = services.and_then(|svcs| {
svcs.iter()
.find(|s| s["name"].as_str() == Some(service_name))
});
match service {
Some(svc) => {
let id = svc["id"].as_str().unwrap_or("?");
println!("Service: {}", service_name);
println!(" ID: {}", id);
println!(" Version: v{}", svc["current_version"]);
println!(" Status: {}", svc["status"].as_str().unwrap_or("?"));
println!(" Tenant: {}", svc["tenant_slug"].as_str().unwrap_or("?"));
println!(" Created: {}", svc["created_at"].as_str().unwrap_or("?"));
println!(" Updated: {}", svc["updated_at"].as_str().unwrap_or("?"));
let deploy_resp = config
.auth_request(
&client,
reqwest::Method::GET,
&format!("{}/api/services/{}/deployments", config.api_url, id),
)
.send()
.await?;
if deploy_resp.status().is_success() {
let deploy_body: serde_json::Value = deploy_resp.json().await?;
if let Some(deployments) = deploy_body["deployments"].as_array() {
println!("\n Deployments ({}):", deployments.len());
for d in deployments.iter().take(5) {
let commit_suffix = d["commit_hash"]
.as_str()
.map(|h| {
let short = if h.len() > 7 { &h[..7] } else { h };
format!(" ({})", short)
})
.unwrap_or_default();
println!(
" v{} — {} ({}){}",
d["version"],
d["status"].as_str().unwrap_or("?"),
d["deployed_at"].as_str().unwrap_or("?"),
commit_suffix,
);
}
}
}
if let Some(tables) = manifest["tables"].as_array() {
println!("\n Tables:");
for t in tables {
let cols = t["columns"].as_array().map(|c| c.len()).unwrap_or(0);
println!(
" {} ({} columns)",
t["name"].as_str().unwrap_or("?"),
cols
);
}
}
if let Some(tables) = manifest["tables"].as_array() {
let tenant = svc["tenant_slug"].as_str().unwrap_or("default");
println!("\n Endpoints:");
for t in tables {
let table_name = t["name"].as_str().unwrap_or("?");
println!(" GET /svc/{}/{}/{}", tenant, service_name, table_name);
println!(" POST /svc/{}/{}/{}", tenant, service_name, table_name);
println!(
" GET /svc/{}/{}/{}/:id",
tenant, service_name, table_name
);
println!(
" PUT /svc/{}/{}/{}/:id",
tenant, service_name, table_name
);
println!(
" DELETE /svc/{}/{}/{}/:id",
tenant, service_name, table_name
);
}
}
}
None => {
println!("Service '{}' not found on the platform.", service_name);
println!("Use `cufflink deploy` to deploy it.");
}
}
Ok(())
}