88 lines
2.6 KiB
JavaScript
Executable File
88 lines
2.6 KiB
JavaScript
Executable File
#!/usr/bin/env node
|
|
|
|
// Get details for a specific Linear issue
|
|
// Usage: linear-issue.js <identifier> [--comments]
|
|
|
|
import { getClient, formatDate } from "./lib.js";
|
|
|
|
const args = process.argv.slice(2);
|
|
|
|
const showComments = args.includes("--comments");
|
|
const filtered = args.filter((a) => a !== "--comments");
|
|
|
|
const identifier = filtered[0];
|
|
|
|
if (!identifier) {
|
|
console.log("Usage: linear-issue.js <identifier> [--comments]");
|
|
console.log("\nExamples:");
|
|
console.log(" linear-issue.js ATT-1234");
|
|
console.log(" linear-issue.js ATT-1234 --comments");
|
|
process.exit(1);
|
|
}
|
|
|
|
const client = getClient();
|
|
|
|
// Parse team key and issue number from identifier (e.g. "SIP-1205")
|
|
const parts = identifier.match(/^([A-Za-z]+)-(\d+)$/);
|
|
if (!parts) {
|
|
console.error(`Invalid identifier format: ${identifier}. Expected format: TEAM-123`);
|
|
process.exit(1);
|
|
}
|
|
|
|
const teamKey = parts[1].toUpperCase();
|
|
const issueNumber = parseInt(parts[2], 10);
|
|
|
|
// Find the issue by team key + number
|
|
const issues = await client.issues({
|
|
filter: {
|
|
team: { key: { eq: teamKey } },
|
|
number: { eq: issueNumber },
|
|
},
|
|
first: 1,
|
|
});
|
|
|
|
const issue = issues.nodes[0];
|
|
if (!issue) {
|
|
console.error(`Issue ${identifier} not found.`);
|
|
process.exit(1);
|
|
}
|
|
|
|
const state = await issue.state;
|
|
const team = await issue.team;
|
|
const assignee = await issue.assignee;
|
|
const labels = await issue.labels();
|
|
const parent = await issue.parent;
|
|
const project = await issue.project;
|
|
const cycle = await issue.cycle;
|
|
|
|
console.log(`=== ${issue.identifier}: ${issue.title} ===`);
|
|
console.log(`URL: ${issue.url}`);
|
|
console.log(`State: ${state?.name || "Unknown"}`);
|
|
console.log(`Priority: ${issue.priorityLabel}`);
|
|
console.log(`Team: ${team?.key || "?"}`);
|
|
console.log(`Assignee: ${assignee?.name || "Unassigned"}`);
|
|
if (project) console.log(`Project: ${project.name}`);
|
|
if (cycle) console.log(`Cycle: ${cycle.name || cycle.number}`);
|
|
if (parent) console.log(`Parent: ${parent.identifier} - ${parent.title}`);
|
|
if (labels.nodes.length > 0) {
|
|
console.log(`Labels: ${labels.nodes.map((l) => l.name).join(", ")}`);
|
|
}
|
|
console.log(`Created: ${formatDate(issue.createdAt)}`);
|
|
console.log(`Updated: ${formatDate(issue.updatedAt)}`);
|
|
if (issue.dueDate) console.log(`Due: ${issue.dueDate}`);
|
|
console.log(`\nDescription:\n${issue.description || "(empty)"}`);
|
|
|
|
if (showComments) {
|
|
const comments = await issue.comments();
|
|
if (comments.nodes.length > 0) {
|
|
console.log(`\n--- Comments (${comments.nodes.length}) ---`);
|
|
for (const comment of comments.nodes) {
|
|
const author = await comment.user;
|
|
console.log(`\n[${formatDate(comment.createdAt)}] ${author?.name || "Unknown"}:`);
|
|
console.log(comment.body);
|
|
}
|
|
} else {
|
|
console.log("\nNo comments.");
|
|
}
|
|
}
|