use crate::config::Config;
use crate::github_api::GithubApi;
pub fn run() {
let config = Config::load_or_exit();
let api = GithubApi::new(&config.oauth_token, &config.vibestats_data_repo);
match api.get_file_content("registry.json") {
Ok(Some(content)) => {
let json: serde_json::Value =
serde_json::from_str(&content).unwrap_or(serde_json::Value::Null);
let machines = json["machines"].as_array();
if let Some(machines) = machines {
for m in machines {
let machine_id = m["machine_id"].as_str().unwrap_or("unknown");
let hostname = m["hostname"].as_str().unwrap_or("unknown");
let status = m["status"].as_str().unwrap_or("unknown");
let last_seen = m["last_seen"].as_str().unwrap_or("never");
println!(
"machine: {} hostname: {} status: {} last_seen: {}",
machine_id, hostname, status, last_seen
);
}
}
}
Ok(None) => {
println!("No machines registered yet.");
}
Err(_) => {
println!("vibestats: failed to fetch registry — check your connection.");
}
}
match api.get_user() {
Ok(login) => {
println!("Auth: OK (github.com/{})", login);
}
Err(_) => {
println!("Auth: ERROR — run `vibestats auth` to re-authenticate");
}
}
}
#[cfg(test)]
mod tests {
#[test]
fn test_registry_parse_two_machines() {
let json_str = r#"{
"machines": [
{
"machine_id": "mbp-abc123",
"hostname": "my-macbook.local",
"status": "active",
"last_seen": "2026-04-10T14:23:00Z"
},
{
"machine_id": "desktop-xyz789",
"hostname": "desktop.local",
"status": "inactive",
"last_seen": "2026-03-01T08:00:00Z"
}
]
}"#;
let json: serde_json::Value =
serde_json::from_str(json_str).unwrap_or(serde_json::Value::Null);
let machines = json["machines"].as_array();
assert!(machines.is_some(), "machines array should be present");
let machines = machines.unwrap();
assert_eq!(machines.len(), 2, "should have 2 machines");
assert_eq!(
machines[0]["machine_id"].as_str().unwrap_or(""),
"mbp-abc123"
);
assert_eq!(
machines[0]["hostname"].as_str().unwrap_or(""),
"my-macbook.local"
);
assert_eq!(machines[0]["status"].as_str().unwrap_or(""), "active");
assert_eq!(
machines[0]["last_seen"].as_str().unwrap_or(""),
"2026-04-10T14:23:00Z"
);
assert_eq!(
machines[1]["machine_id"].as_str().unwrap_or(""),
"desktop-xyz789"
);
assert_eq!(machines[1]["status"].as_str().unwrap_or(""), "inactive");
}
#[test]
fn test_registry_parse_empty_machines_array() {
let json_str = r#"{"machines": []}"#;
let json: serde_json::Value =
serde_json::from_str(json_str).unwrap_or(serde_json::Value::Null);
let machines = json["machines"].as_array();
assert!(machines.is_some(), "machines array should be present");
assert_eq!(
machines.unwrap().len(),
0,
"empty machines array should yield zero entries"
);
}
#[test]
fn test_registry_parse_malformed_json_does_not_panic() {
let json_str = r#"{ this is not valid json }"#;
let json: serde_json::Value =
serde_json::from_str(json_str).unwrap_or(serde_json::Value::Null);
let machines = json["machines"].as_array();
assert!(
machines.is_none(),
"malformed JSON should yield None for machines array, not panic"
);
}
#[test]
fn test_registry_parse_machine_with_missing_fields() {
let json_str = r#"{"machines": [{"machine_id": "only-id"}]}"#;
let json: serde_json::Value =
serde_json::from_str(json_str).unwrap_or(serde_json::Value::Null);
let machines = json["machines"].as_array().unwrap();
let m = &machines[0];
assert_eq!(m["machine_id"].as_str().unwrap_or("unknown"), "only-id");
assert_eq!(m["hostname"].as_str().unwrap_or("unknown"), "unknown");
assert_eq!(m["status"].as_str().unwrap_or("unknown"), "unknown");
assert_eq!(m["last_seen"].as_str().unwrap_or("never"), "never");
}
}