Skip to main content

bb_cli/commands/
project.rs

1use crate::api::models::Project;
2use crate::error::Result;
3use crate::output::{self, Format};
4use crate::workspace::{self, WorkspaceCtx};
5use serde::Serialize;
6
7#[derive(Debug, Serialize)]
8struct ProjectRow {
9    key: String,
10    name: String,
11    access: String,
12}
13
14fn rows(projects: &[Project], name: Option<String>, limit: usize) -> Vec<ProjectRow> {
15    let needle = name.map(|n| n.to_lowercase());
16    projects
17        .iter()
18        .filter(|p| match &needle {
19            Some(needle) => {
20                p.name_or_dash().to_lowercase().contains(needle)
21                    || p.key_or_dash().to_lowercase().contains(needle)
22            }
23            None => true,
24        })
25        .take(limit)
26        .map(|p| ProjectRow {
27            key: p.key_or_dash().to_string(),
28            name: p.name_or_dash().to_string(),
29            access: p.access().to_string(),
30        })
31        .collect()
32}
33
34pub async fn list(ctx: &WorkspaceCtx, name: Option<String>, limit: usize) -> Result<()> {
35    let spinner = output::spinner("fetching projects");
36    let projects = workspace::projects(ctx).await?;
37    spinner.finish_and_clear();
38
39    let rows = rows(&projects, name, limit);
40
41    match ctx.format {
42        Format::Json => output::print_json(&rows)?,
43        Format::Human => output::print_table(
44            &["KEY", "NAME", "ACCESS"],
45            rows.iter()
46                .map(|r| vec![r.key.clone(), r.name.clone(), r.access.clone()])
47                .collect(),
48        ),
49    }
50    Ok(())
51}