use crate::context::CliContext;
use anyhow::Result;
pub async fn handle_status(ctx: &mut CliContext) -> Result<()> {
println!();
println!("📊 Mecha10 Project Status");
println!("━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━");
println!();
if !ctx.is_project_initialized() {
println!("⚠️ Not in a Mecha10 project directory");
println!();
println!("Run `mecha10 init` to create a new project");
return Ok(());
}
let config = ctx.load_project_config().await?;
println!("Project Information:");
println!(" Robot ID: {}", config.robot.id);
println!();
let project = ctx.project()?;
match project.list_nodes() {
Ok(nodes) => {
println!("Nodes: {} configured", nodes.len());
for node in &nodes {
println!(" • {}", node);
}
println!();
}
Err(_) => {
println!("Nodes: 0 configured");
println!();
}
}
println!("Infrastructure Services:");
println!();
let redis_url = ctx.redis_url().to_string();
print!(" Redis: ");
match ctx.redis() {
Ok(redis_service) => {
if redis_service.is_healthy().await {
println!("✅ Connected");
println!(" URL: {}", redis_url);
} else {
println!("❌ Not reachable");
println!(" URL: {}", redis_url);
println!(" Hint: Start Redis with `docker compose up -d` or `redis-server`");
}
}
Err(_) => {
println!("❌ Invalid URL");
println!(" URL: {}", redis_url);
}
}
println!();
if let Some(database_url) = ctx.postgres_url().map(|s| s.to_string()) {
print!(" PostgreSQL: ");
match check_postgres_health(&database_url).await {
true => {
println!("✅ Connected");
println!(" URL: {}", mask_database_url(&database_url));
}
false => {
println!("❌ Not reachable");
println!(" URL: {}", mask_database_url(&database_url));
}
}
println!();
}
println!(" Docker:");
let docker = ctx.docker();
match docker.check_installation() {
Ok(info) => {
println!(" ✅ {}", info.version);
println!(" Compose: {}", info.compose_version);
}
Err(_) => {
println!(" ❌ Not installed");
}
}
println!();
println!("━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━");
println!();
Ok(())
}
async fn check_postgres_health(url: &str) -> bool {
if let Some(host_port) = url.split('@').nth(1) {
if let Some(host) = host_port.split('/').next() {
if let Ok(stream) = tokio::net::TcpStream::connect(host).await {
drop(stream);
return true;
}
}
}
false
}
fn mask_database_url(url: &str) -> String {
if let Some(at_pos) = url.find('@') {
if let Some(proto_end) = url.find("://") {
let protocol = &url[..proto_end + 3];
let after_at = &url[at_pos..];
return format!("{}***{}", protocol, after_at);
}
}
url.to_string()
}