Something went wrong. Try again.
CLI for Linear via GraphQL API
Something went wrong. Try again.
4.6 kB · 196 lines
TypeScript
at main
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197import { graphql } from "../api.ts";import { formatDate, printTable, requireToken, useJson } from "./shared.ts";
function formatProgress(progress: number): string { return `${Math.round(progress * 100)}%`;}
export interface ListCyclesOptions { team?: string; limit?: number; json?: boolean;}
export async function listCycles(options: ListCyclesOptions): Promise<void> { const token = await requireToken(); const limit = options.limit ?? 50; const json = await useJson(options.json);
const query = ` query Cycles($first: Int, $filter: CycleFilter) { cycles(first: $first, filter: $filter) { nodes { id number name startsAt endsAt completedAt progress team { key name } issues { nodes { id } } } } } `;
const filter: Record<string, unknown> = {}; if (options.team) { filter.team = { key: { eq: options.team } }; }
const data = await graphql<{ cycles: { nodes: Array<{ id: string; number: number; name: string | null; startsAt: string; endsAt: string; completedAt: string | null; progress: number; team: { key: string; name: string }; issues: { nodes: Array<{ id: string }> }; }>; }; }>(token, query, { first: limit, filter: Object.keys(filter).length > 0 ? filter : undefined, });
const cycles = data.cycles.nodes;
if (json) { console.log(JSON.stringify(cycles, null, 2)); return; }
if (cycles.length === 0) { console.log("No cycles found."); return; }
const headers = [ "NUMBER", "NAME", "TEAM", "START", "END", "PROGRESS", "ISSUES", ]; const rows = cycles.map((c) => [ String(c.number), c.name ?? "-", c.team.key, formatDate(c.startsAt), formatDate(c.endsAt), formatProgress(c.progress), String(c.issues.nodes.length), ]); printTable(headers, rows);}
export interface GetCycleOptions { id: string; json?: boolean;}
export async function getCycle(options: GetCycleOptions): Promise<void> { const token = await requireToken(); const json = await useJson(options.json);
const query = ` query Cycle($id: String!) { cycle(id: $id) { id number name description startsAt endsAt completedAt progress team { key name } issues { nodes { identifier title state { name } assignee { name } priority priorityLabel } } createdAt updatedAt } } `;
const data = await graphql<{ cycle: { id: string; number: number; name: string | null; description: string | null; startsAt: string; endsAt: string; completedAt: string | null; progress: number; team: { key: string; name: string }; issues: { nodes: Array<{ identifier: string; title: string; state: { name: string }; assignee: { name: string } | null; priority: number; priorityLabel: string; }>; }; createdAt: string; updatedAt: string; }; }>(token, query, { id: options.id });
const cycle = data.cycle;
if (json) { console.log(JSON.stringify(cycle, null, 2)); return; }
console.log(`Number: ${cycle.number}`); console.log(`Name: ${cycle.name ?? "-"}`); console.log(`Team: ${cycle.team.key} (${cycle.team.name})`); console.log(`Description: ${cycle.description ?? "-"}`); console.log(`Start: ${formatDate(cycle.startsAt)}`); console.log(`End: ${formatDate(cycle.endsAt)}`); console.log(`Completed: ${formatDate(cycle.completedAt)}`); console.log(`Progress: ${formatProgress(cycle.progress)}`); console.log(`Created: ${formatDate(cycle.createdAt)}`); console.log(`Updated: ${formatDate(cycle.updatedAt)}`);
const issues = cycle.issues.nodes; if (issues.length > 0) { console.log(`\nIssues (${issues.length}):`); const issueHeaders = [ "IDENTIFIER", "TITLE", "STATE", "PRIORITY", "ASSIGNEE", ]; const issueRows = issues.map((i) => [ i.identifier, i.title, i.state.name, i.priorityLabel, i.assignee?.name ?? "-", ]); printTable(issueHeaders, issueRows); } else { console.log("\nNo issues in this cycle."); }}