linear-cmd
Version:
A GitHub CLI-like tool for Linear - manage issues, accounts, and more
136 lines (135 loc) • 5.93 kB
JavaScript
import { Command } from 'commander';
import inquirer from 'inquirer';
import { ConfigManager } from '../../lib/config-manager.js';
import { getLinearClientForAccount, handleValidationError, ValidationError } from '../../lib/linear-client.js';
import { Logger } from '../../lib/logger.js';
import { linearIssuePayloadSchema } from '../../types/linear.js';
export function createCreateIssueCommand() {
return new Command('create')
.description('Create a new Linear issue')
.requiredOption('-a, --account <account>', 'specify account to use')
.option('-t, --title <title>', 'issue title')
.option('-d, --description <description>', 'issue description')
.option('-p, --priority <priority>', 'priority (0: none, 1: urgent, 2: high, 3: medium, 4: low)')
.option('-l, --label <label>', 'label name')
.option('--team <team>', 'team identifier')
.option('--project <project>', 'project identifier')
.option('--assignee <assignee>', 'assignee email or identifier')
.action(async (options) => {
const configManager = new ConfigManager();
try {
const { client, account } = await getLinearClientForAccount(configManager, options.account);
// Get teams if not specified
let teamId = options.team;
if (!teamId) {
const teams = await client.teams();
if (teams.nodes.length === 0) {
Logger.error('No teams found');
return;
}
if (teams.nodes.length === 1) {
teamId = teams.nodes[0].id;
}
else {
const teamAnswer = await inquirer.prompt([
{
type: 'list',
name: 'team',
message: 'Select team:',
choices: teams.nodes.map((t) => ({ name: `${t.name} (${t.key})`, value: t.id }))
}
]);
teamId = teamAnswer.team;
}
}
// Get issue details interactively if not provided
const answers = await inquirer.prompt([
{
type: 'input',
name: 'title',
message: 'Issue title:',
when: !options.title,
validate: (input) => input.length > 0 || 'Title is required'
},
{
type: 'input',
name: 'description',
message: 'Issue description (optional):',
when: !options.description
}
]);
const title = options.title || answers.title;
const description = options.description || answers.description || undefined;
// Create the issue
Logger.loading(`Creating issue in account: ${account.name}...`);
const issuePayload = {
teamId,
title,
description
};
// Add priority if specified
if (options.priority !== undefined) {
const priority = parseInt(options.priority);
if (priority >= 0 && priority <= 4) {
issuePayload.priority = priority;
}
}
// Add assignee if specified
if (options.assignee) {
const users = await client.users({ filter: { email: { eq: options.assignee } } });
if (users.nodes.length > 0) {
issuePayload.assigneeId = users.nodes[0].id;
}
else {
Logger.warning(`User '${options.assignee}' not found, creating without assignee`);
}
}
// Add project if specified
if (options.project) {
const projects = await client.projects({ filter: { name: { eq: options.project } } });
if (projects.nodes.length > 0) {
issuePayload.projectId = projects.nodes[0].id;
}
else {
Logger.warning(`Project '${options.project}' not found, creating without project`);
}
}
// Add label if specified
if (options.label) {
const labels = await client.issueLabels({ filter: { name: { eq: options.label } } });
if (labels.nodes.length > 0) {
issuePayload.labelIds = [labels.nodes[0].id];
}
else {
Logger.warning(`Label '${options.label}' not found, creating without label`);
}
}
// Validate the payload
const validPayload = linearIssuePayloadSchema.parse(issuePayload);
const issue = await client.createIssue(validPayload);
const createdIssue = await issue.issue;
if (!createdIssue) {
throw new Error('Failed to create issue');
}
Logger.success('Issue created successfully!');
Logger.info(`📋 ID: ${createdIssue.identifier}`);
Logger.link(createdIssue.url, 'URL:');
const assignee = await createdIssue.assignee;
if (assignee) {
Logger.dim(`👤 Assigned to: ${assignee.name}`);
}
const project = await createdIssue.project;
if (project) {
Logger.dim(`📁 Project: ${project.name}`);
}
}
catch (error) {
if (error instanceof ValidationError) {
handleValidationError(error);
}
else {
Logger.error('Error creating issue', error);
}
}
});
}