lin-cli 0.4.0

A fast CLI for Linear
use anyhow::Result;
use serde_json::json;

use crate::api::client::LinearClient;
use crate::api::queries::*;
use crate::api::types::*;
use crate::output;

pub async fn list(client: &LinearClient, limit: i32) -> Result<()> {
    let variables = json!({ "first": limit });

    let data: InitiativesData = client.execute(INITIATIVES_QUERY, Some(variables)).await?;
    let initiatives = data.initiatives.nodes;

    output::print_header(&format!("Initiatives ({})", initiatives.len()));

    let headers = &["ID", "Name", "Status"];
    let rows: Vec<Vec<String>> = initiatives
        .iter()
        .map(|i| {
            vec![
                truncate(&i.id, 8),
                i.name.clone(),
                i.status.clone().unwrap_or_default(),
            ]
        })
        .collect();

    output::print_table(headers, &rows);
    Ok(())
}

pub async fn view(client: &LinearClient, id: &str) -> Result<()> {
    let data: InitiativeDetailData = client
        .execute(INITIATIVE_QUERY, Some(json!({ "id": id })))
        .await?;

    let init = data.initiative;

    output::print_header(&init.name);

    if let Some(ref status) = init.status {
        output::print_field("Status", status);
    }

    if let Some(ref desc) = init.description
        && !desc.is_empty()
    {
        println!();
        output::print_header("Description");
        println!("  {desc}");
    }

    if let Some(ref projects) = init.projects
        && !projects.nodes.is_empty()
    {
        println!();
        output::print_header(&format!("Projects ({})", projects.nodes.len()));
        let headers = &["Name", "State"];
        let rows: Vec<Vec<String>> = projects
            .nodes
            .iter()
            .map(|p| vec![p.name.clone(), p.state.clone().unwrap_or_default()])
            .collect();
        output::print_table(headers, &rows);
    }

    Ok(())
}

fn truncate(s: &str, max: usize) -> String {
    if s.len() <= max {
        s.to_string()
    } else {
        format!("{}", &s[..max - 1])
    }
}