91 lines
2.5 KiB
JavaScript
Executable File
91 lines
2.5 KiB
JavaScript
Executable File
#!/usr/bin/env node
|
|
|
|
// List Linear issues with filters
|
|
// Usage: linear-issues.js [--team <key>] [--state <name>] [--assignee <name|me>] [--label <name>] [--project <name>] [-n <num>]
|
|
|
|
import { getClient, formatDate, truncate } from "./lib.js";
|
|
|
|
const args = process.argv.slice(2);
|
|
|
|
function extractArg(flag) {
|
|
const idx = args.indexOf(flag);
|
|
if (idx !== -1 && args[idx + 1]) {
|
|
const val = args[idx + 1];
|
|
args.splice(idx, 2);
|
|
return val;
|
|
}
|
|
return null;
|
|
}
|
|
|
|
const numResults = parseInt(extractArg("-n") || "25", 10);
|
|
const teamKey = extractArg("--team");
|
|
const stateName = extractArg("--state");
|
|
const assigneeName = extractArg("--assignee");
|
|
const labelName = extractArg("--label");
|
|
const projectName = extractArg("--project");
|
|
|
|
if (args.includes("--help") || args.includes("-h")) {
|
|
console.log("Usage: linear-issues.js [options]");
|
|
console.log("\nOptions:");
|
|
console.log(" --team <key> Filter by team key (e.g. ENG)");
|
|
console.log(" --state <name> Filter by state (e.g. 'In Progress', 'Todo')");
|
|
console.log(" --assignee <name> Filter by assignee name or 'me'");
|
|
console.log(" --label <name> Filter by label name");
|
|
console.log(" --project <name> Filter by project name");
|
|
console.log(" -n <num> Number of results (default: 25)");
|
|
process.exit(0);
|
|
}
|
|
|
|
const client = getClient();
|
|
|
|
// Build filter
|
|
const filter = {};
|
|
|
|
if (teamKey) {
|
|
filter.team = { key: { eq: teamKey.toUpperCase() } };
|
|
}
|
|
|
|
if (stateName) {
|
|
filter.state = { name: { eqIgnoreCase: stateName } };
|
|
}
|
|
|
|
if (assigneeName) {
|
|
if (assigneeName.toLowerCase() === "me") {
|
|
const me = await client.viewer;
|
|
filter.assignee = { id: { eq: me.id } };
|
|
} else {
|
|
filter.assignee = { name: { containsIgnoreCase: assigneeName } };
|
|
}
|
|
}
|
|
|
|
if (labelName) {
|
|
filter.labels = { name: { eqIgnoreCase: labelName } };
|
|
}
|
|
|
|
if (projectName) {
|
|
filter.project = { name: { containsIgnoreCase: projectName } };
|
|
}
|
|
|
|
const issues = await client.issues({
|
|
filter,
|
|
first: numResults,
|
|
orderBy: "updatedAt",
|
|
});
|
|
|
|
if (issues.nodes.length === 0) {
|
|
console.log("No issues found matching filters.");
|
|
process.exit(0);
|
|
}
|
|
|
|
for (const issue of issues.nodes) {
|
|
const state = await issue.state;
|
|
const team = await issue.team;
|
|
const assignee = await issue.assignee;
|
|
|
|
console.log(
|
|
`${issue.identifier.padEnd(12)} ${(state?.name || "?").padEnd(14)} ${(issue.priorityLabel || "").padEnd(8)} ${(assignee?.name || "Unassigned").padEnd(20)} ${truncate(issue.title, 80)}`
|
|
);
|
|
}
|
|
|
|
console.log(`\n${issues.nodes.length} issue(s) shown.`);
|