linear-api 0.1.0

Unofficial async Rust client for the Linear GraphQL API (API-key auth)
Documentation
//! Read-only tour of the typed surface: viewer, organization, teams, board
//! states, projects, issues, and one issue's comments + relations.
//!
//! Usage: `LINEAR_API_KEY=lin_api_... cargo run --example workspace_tour`
//!
//! Runs **queries only** — it never mutates the workspace.

use linear_api::comments::CommentListRequest;
use linear_api::issues::ListIssuesRequest;
use linear_api::projects::ListProjectsRequest;
use linear_api::workspace::ListTeamsRequest;

#[tokio::main]
async fn main() -> anyhow::Result<()> {
    let client = linear_api::LinearClient::from_env()?;

    let viewer = client.viewer().await?;
    let org = client.organization().await?;
    println!(
        "workspace: {} (linear.app/{})\nviewer:    {} <{}>\n",
        org.name, org.url_key, viewer.display_name, viewer.email
    );

    let teams = client
        .teams()
        .list(ListTeamsRequest::builder().first(10).build())
        .await?;
    println!("teams ({}):", teams.nodes.len());
    for team in &teams.nodes {
        println!("  [{}] {}", team.key, team.name);
    }

    if let Some(team) = teams.nodes.first() {
        let states = client.teams().states(&team.id).await?;
        println!("\nboard states of [{}]:", team.key);
        for state in &states {
            println!("  {:<20} {:?}", state.name, state.state_type);
        }
    }

    let projects = client
        .projects()
        .list(ListProjectsRequest::builder().first(5).build())
        .await?;
    println!("\nprojects (first {}):", projects.nodes.len());
    for project in &projects.nodes {
        println!(
            "  {:<40} {:?} {:>4.0}%",
            project.name,
            project.status.status_type,
            project.progress * 100.0
        );
    }

    let issues = client
        .issues()
        .list(ListIssuesRequest::builder().first(5).build())
        .await?;
    println!("\nissues (first {}):", issues.nodes.len());
    for issue in &issues.nodes {
        println!(
            "  {:<10} {} [{}]",
            issue.identifier, issue.title, issue.state.name
        );
    }

    if let Some(issue) = issues.nodes.first() {
        let comments = client
            .comments()
            .list_for_issue(&issue.id, CommentListRequest::builder().first(5).build())
            .await?;
        let relations = client.relations().of_issue(&issue.id).await?;
        println!(
            "\n{}: {} comment(s) fetched, blocks {}, blocked by {}",
            issue.identifier,
            comments.nodes.len(),
            relations.blocks().len(),
            relations.blocked_by().len()
        );
    }

    if let Some(info) = client.last_rate_limit() {
        println!(
            "\nrate budget: {:?}/{:?} requests remaining, complexity {:?}/{:?}",
            info.requests_remaining,
            info.requests_limit,
            info.complexity_remaining,
            info.complexity_limit
        );
    }
    Ok(())
}