use serde::Deserialize;
use serde_json::Value;
use crate::client::CellosClient;
use crate::exit::{CtlError, CtlResult};
#[derive(Debug, Default, Deserialize)]
struct ServerVersion {
#[serde(default)]
version: Option<String>,
#[serde(rename = "gitSha", default)]
git_sha: Option<String>,
#[serde(rename = "buildProfile", default)]
build_profile: Option<String>,
}
pub async fn run(client: &CellosClient) -> CtlResult<()> {
println!("client: cellctl {}", env!("CARGO_PKG_VERSION"));
match client.get_json::<Value>("/v1/version").await {
Ok(v) => {
println!("server: {}", format_server_line(&v));
Ok(())
}
Err(e) => {
Err(CtlError::api(format!(
"unable to connect to the server: {e}"
)))
}
}
}
fn format_server_line(v: &Value) -> String {
let server = v
.get("server")
.and_then(|s| serde_json::from_value::<ServerVersion>(s.clone()).ok())
.unwrap_or_else(|| ServerVersion {
version: v.get("version").and_then(|x| x.as_str()).map(str::to_owned),
..Default::default()
});
let version = server.version.as_deref().unwrap_or("unknown");
let mut parts: Vec<&str> = Vec::with_capacity(2);
if let Some(s) = server.git_sha.as_deref() {
parts.push(s);
}
if let Some(p) = server.build_profile.as_deref() {
parts.push(p);
}
if parts.is_empty() {
format!("cellos-server {version}")
} else {
format!("cellos-server {version} ({})", parts.join(" "))
}
}
#[cfg(test)]
mod tests {
use super::*;
use serde_json::json;
#[test]
fn renders_full_nested_shape() {
let v = json!({
"server": {
"version": "0.5.0",
"gitSha": "abc1234",
"buildProfile": "release",
},
"api": { "version": "v1" },
});
assert_eq!(
format_server_line(&v),
"cellos-server 0.5.0 (abc1234 release)"
);
}
#[test]
fn renders_nested_shape_without_git_sha() {
let v = json!({
"server": { "version": "0.5.0", "buildProfile": "debug" },
"api": { "version": "v1" },
});
assert_eq!(format_server_line(&v), "cellos-server 0.5.0 (debug)");
}
#[test]
fn renders_flat_legacy_shape() {
let v = json!({ "version": "0.4.0" });
assert_eq!(format_server_line(&v), "cellos-server 0.4.0");
}
#[test]
fn renders_unknown_when_version_missing() {
let v = json!({ "server": { "buildProfile": "release" } });
assert_eq!(format_server_line(&v), "cellos-server unknown (release)");
}
}