use crate::actions::GlobalArgs;
use crate::paths::berg_data_dir;
use crate::render::json::JsonToStdout;
use crate::types::context::BergContext;
use crate::types::output::OutputMode;
use miette::IntoDiagnostic;
use clap::Parser;
#[derive(Parser, Debug)]
pub struct ListArgs {}
impl ListArgs {
pub async fn run(self, global_args: GlobalArgs) -> miette::Result<()> {
let ctx = BergContext::new(self, global_args).await?;
let data_dir = berg_data_dir()?;
let instances = data_dir
.read_dir()
.into_diagnostic()?
.filter_map(|dir| {
let entry = dir.ok()?;
let logged_in = entry.metadata().is_ok_and(|metadata| metadata.is_dir())
&& entry
.path()
.read_dir()
.into_iter()
.flatten()
.any(|content| content.is_ok_and(|content| content.file_name() == "TOKEN"));
Some(Instance {
base_url: entry.file_name().display().to_string(),
logged_in,
})
})
.collect::<Vec<_>>();
match ctx.global_args.output_mode {
OutputMode::Pretty => {
present_instance_list(ctx, instances);
}
OutputMode::Json => {
instances.print_json()?;
}
}
Ok(())
}
}
#[derive(Debug, Clone, serde::Serialize)]
struct Instance {
base_url: String,
logged_in: bool,
}
fn present_instance_list(ctx: BergContext<ListArgs>, instances: Vec<Instance>) {
let issues_empty = instances.is_empty();
let table = ctx
.make_table()
.set_header(vec!["Base URL", "Logged In"])
.add_rows(instances.into_iter().map(|instance| {
let Instance {
base_url,
logged_in,
} = instance;
vec![base_url, String::from(if logged_in { "Yes" } else { "No" })]
}));
let header = format!(
"Instances{}",
if issues_empty {
" (empty)"
} else {
Default::default()
}
);
let underscore = "=".repeat(header.len());
let out = [header, underscore, table.show()].join("\n");
println!("{out}");
}