jira-ai 0.3.21 ā 0.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cli.js +7 -2
- package/dist/commands/about.js +1 -1
- package/dist/commands/add-comment.js +3 -2
- package/dist/commands/add-label.js +2 -1
- package/dist/commands/create-task.js +8 -10
- package/dist/commands/delete-label.js +2 -1
- package/dist/commands/task-with-details.js +3 -2
- package/dist/commands/transition.js +3 -2
- package/dist/commands/update-description.js +3 -2
- package/dist/lib/formatters.js +9 -11
- package/dist/lib/settings.js +1 -1
- package/dist/lib/validation.js +3 -5
- package/package.json +1 -1
package/dist/cli.js
CHANGED
|
@@ -27,14 +27,16 @@ import { CliError } from './types/errors.js';
|
|
|
27
27
|
import { CommandError } from './lib/errors.js';
|
|
28
28
|
import { ui } from './lib/ui.js';
|
|
29
29
|
import { validateOptions, CreateTaskSchema, AddCommentSchema, UpdateDescriptionSchema, RunJqlSchema, IssueKeySchema, ProjectKeySchema } from './lib/validation.js';
|
|
30
|
+
import { realpathSync } from 'fs';
|
|
30
31
|
// Load environment variables
|
|
32
|
+
// @ts-ignore - quiet option exists but is not in types
|
|
31
33
|
dotenv.config({ quiet: true });
|
|
32
34
|
// Create CLI program
|
|
33
35
|
const program = new Command();
|
|
34
36
|
program
|
|
35
37
|
.name('jira-ai')
|
|
36
38
|
.description('CLI tool for interacting with Atlassian Jira')
|
|
37
|
-
.version('0.3.
|
|
39
|
+
.version('0.3.22')
|
|
38
40
|
.option('-o, --organization <alias>', 'Override the active Jira organization');
|
|
39
41
|
// Hook to handle the global option before any command runs
|
|
40
42
|
program.on('option:organization', (alias) => {
|
|
@@ -289,7 +291,10 @@ export async function main() {
|
|
|
289
291
|
}
|
|
290
292
|
}
|
|
291
293
|
}
|
|
292
|
-
if
|
|
294
|
+
// Check if this file is being run directly (handles symlinks)
|
|
295
|
+
const scriptPath = process.argv[1] ? realpathSync(process.argv[1]) : '';
|
|
296
|
+
const isMainModule = scriptPath.endsWith('cli.ts') || scriptPath.endsWith('cli.js');
|
|
297
|
+
if (isMainModule) {
|
|
293
298
|
main();
|
|
294
299
|
}
|
|
295
300
|
export { program };
|
package/dist/commands/about.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import chalk from 'chalk';
|
|
2
2
|
export async function aboutCommand() {
|
|
3
3
|
console.log(chalk.bold.cyan('\nš Jira AI\n'));
|
|
4
|
-
console.log(`${chalk.bold('Version:')} 0.
|
|
4
|
+
console.log(`${chalk.bold('Version:')} 0.4.0`);
|
|
5
5
|
console.log(`${chalk.bold('GitHub:')} https://github.com/festoinc/jira-ai\n`);
|
|
6
6
|
}
|
|
@@ -44,11 +44,12 @@ export async function addCommentCommand(options) {
|
|
|
44
44
|
console.log(chalk.gray(`\nFile: ${absolutePath}`));
|
|
45
45
|
}
|
|
46
46
|
catch (error) {
|
|
47
|
+
const errorMsg = error.message?.toLowerCase() || '';
|
|
47
48
|
const hints = [];
|
|
48
|
-
if (
|
|
49
|
+
if (errorMsg.includes('404')) {
|
|
49
50
|
hints.push('Check that the issue key is correct');
|
|
50
51
|
}
|
|
51
|
-
else if (
|
|
52
|
+
else if (errorMsg.includes('403')) {
|
|
52
53
|
hints.push('You may not have permission to comment on this issue');
|
|
53
54
|
}
|
|
54
55
|
throw new CommandError(`Failed to add comment: ${error.message}`, { hints });
|
|
@@ -21,8 +21,9 @@ export async function addLabelCommand(taskId, labelsString) {
|
|
|
21
21
|
console.log(chalk.gray(`\nLabels: ${labels.join(', ')}`));
|
|
22
22
|
}
|
|
23
23
|
catch (error) {
|
|
24
|
+
const errorMsg = error.message?.toLowerCase() || '';
|
|
24
25
|
const hints = [];
|
|
25
|
-
if (
|
|
26
|
+
if (errorMsg.includes('404')) {
|
|
26
27
|
hints.push('Check that the issue ID/key is correct');
|
|
27
28
|
}
|
|
28
29
|
throw new CommandError(`Failed to add labels: ${error.message}`, { hints });
|
|
@@ -21,20 +21,18 @@ export async function createTaskCommand(options) {
|
|
|
21
21
|
console.log(chalk.cyan(`\nIssue Key: ${result.key}`));
|
|
22
22
|
}
|
|
23
23
|
catch (error) {
|
|
24
|
+
const errorMsg = error.message?.toLowerCase() || '';
|
|
24
25
|
const hints = [];
|
|
25
|
-
if (
|
|
26
|
-
hints.push('Check that the project key is correct');
|
|
27
|
-
hints.push('Use "jira-ai projects" to see available projects');
|
|
26
|
+
if (errorMsg.includes('project')) {
|
|
27
|
+
hints.push('Check that the project key is correct', 'Use "jira-ai projects" to see available projects');
|
|
28
28
|
}
|
|
29
|
-
else if (
|
|
30
|
-
hints.push('Check that the issue type is correct');
|
|
31
|
-
hints.push(`Use "jira-ai list-issue-types ${project}" to see available issue types`);
|
|
29
|
+
else if (errorMsg.includes('issue type') || errorMsg.includes('issuetype')) {
|
|
30
|
+
hints.push('Check that the issue type is correct', `Use "jira-ai list-issue-types ${project}" to see available issue types`);
|
|
32
31
|
}
|
|
33
|
-
else if (
|
|
34
|
-
hints.push('Check that the parent issue key is correct');
|
|
35
|
-
hints.push('Parent issues are required for subtasks');
|
|
32
|
+
else if (errorMsg.includes('parent')) {
|
|
33
|
+
hints.push('Check that the parent issue key is correct', 'Parent issues are required for subtasks');
|
|
36
34
|
}
|
|
37
|
-
else if (
|
|
35
|
+
else if (errorMsg.includes('403')) {
|
|
38
36
|
hints.push('You may not have permission to create issues in this project');
|
|
39
37
|
}
|
|
40
38
|
throw new CommandError(`Failed to create issue: ${error.message}`, { hints });
|
|
@@ -21,8 +21,9 @@ export async function deleteLabelCommand(taskId, labelsString) {
|
|
|
21
21
|
console.log(chalk.gray(`\nLabels: ${labels.join(', ')}`));
|
|
22
22
|
}
|
|
23
23
|
catch (error) {
|
|
24
|
+
const errorMsg = error.message?.toLowerCase() || '';
|
|
24
25
|
const hints = [];
|
|
25
|
-
if (
|
|
26
|
+
if (errorMsg.includes('404')) {
|
|
26
27
|
hints.push('Check that the issue ID/key is correct');
|
|
27
28
|
}
|
|
28
29
|
throw new CommandError(`Failed to remove labels: ${error.message}`, { hints });
|
|
@@ -15,11 +15,12 @@ export async function taskWithDetailsCommand(taskId, options = {}) {
|
|
|
15
15
|
console.log(formatTaskDetails(task));
|
|
16
16
|
}
|
|
17
17
|
catch (error) {
|
|
18
|
+
const errorMsg = error.message?.toLowerCase() || '';
|
|
18
19
|
const hints = [];
|
|
19
|
-
if (error.response?.status === 404 ||
|
|
20
|
+
if (error.response?.status === 404 || errorMsg.includes('404')) {
|
|
20
21
|
hints.push('Check that the task ID is correct');
|
|
21
22
|
}
|
|
22
|
-
else if (error.response?.status === 403 ||
|
|
23
|
+
else if (error.response?.status === 403 || errorMsg.includes('403')) {
|
|
23
24
|
hints.push('You may not have permission to view this issue');
|
|
24
25
|
}
|
|
25
26
|
throw new CommandError(`Failed to fetch task details: ${error.message}`, { hints });
|
|
@@ -35,11 +35,12 @@ export async function transitionCommand(taskId, toStatus) {
|
|
|
35
35
|
if (error instanceof CommandError) {
|
|
36
36
|
throw error;
|
|
37
37
|
}
|
|
38
|
+
const errorMsg = error.message?.toLowerCase() || '';
|
|
38
39
|
const hints = [];
|
|
39
|
-
if (
|
|
40
|
+
if (errorMsg.includes('403')) {
|
|
40
41
|
hints.push('You may not have permission to transition this issue');
|
|
41
42
|
}
|
|
42
|
-
else if (
|
|
43
|
+
else if (errorMsg.includes('required') || error.response?.data?.errors) {
|
|
43
44
|
hints.push('This transition might require mandatory fields that are not yet supported by this command.');
|
|
44
45
|
if (error.response?.data?.errors) {
|
|
45
46
|
const fields = Object.keys(error.response.data.errors).join(', ');
|
|
@@ -46,11 +46,12 @@ export async function updateDescriptionCommand(taskId, options) {
|
|
|
46
46
|
console.log(chalk.gray(`\nFile: ${absolutePath}`));
|
|
47
47
|
}
|
|
48
48
|
catch (error) {
|
|
49
|
+
const errorMsg = error.message?.toLowerCase() || '';
|
|
49
50
|
const hints = [];
|
|
50
|
-
if (
|
|
51
|
+
if (errorMsg.includes('404')) {
|
|
51
52
|
hints.push('Check that the task ID is correct');
|
|
52
53
|
}
|
|
53
|
-
else if (
|
|
54
|
+
else if (errorMsg.includes('403')) {
|
|
54
55
|
hints.push('You may not have permission to edit this issue');
|
|
55
56
|
}
|
|
56
57
|
throw new CommandError(`Failed to update description: ${error.message}`, { hints });
|
package/dist/lib/formatters.js
CHANGED
|
@@ -52,23 +52,21 @@ export function formatTaskDetails(task) {
|
|
|
52
52
|
const infoTable = createTable(['Property', 'Value'], [15, 65]);
|
|
53
53
|
infoTable.push(['Status', chalk.green(task.status.name)], ['Assignee', task.assignee?.displayName || chalk.gray('Unassigned')], ['Reporter', task.reporter?.displayName || chalk.gray('N/A')], ['Created', formatTimestamp(task.created)], ['Updated', formatTimestamp(task.updated)]);
|
|
54
54
|
// Add Due Date
|
|
55
|
-
let dueDateValue = chalk.gray('N/A');
|
|
56
55
|
if (task.dueDate) {
|
|
57
56
|
const today = new Date();
|
|
58
57
|
today.setHours(0, 0, 0, 0);
|
|
59
58
|
const dueDate = new Date(task.dueDate);
|
|
60
59
|
dueDate.setHours(0, 0, 0, 0);
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
60
|
+
const isOverdue = dueDate < today;
|
|
61
|
+
const isDone = task.status.category?.toLowerCase() === 'done';
|
|
62
|
+
const dueDateValue = isOverdue && !isDone
|
|
63
|
+
? chalk.red(task.dueDate)
|
|
64
|
+
: chalk.green(task.dueDate);
|
|
65
|
+
infoTable.push(['Due Date', dueDateValue]);
|
|
66
|
+
}
|
|
67
|
+
else {
|
|
68
|
+
infoTable.push(['Due Date', chalk.gray('N/A')]);
|
|
70
69
|
}
|
|
71
|
-
infoTable.push(['Due Date', dueDateValue]);
|
|
72
70
|
// Add labels to basic info table if present
|
|
73
71
|
if (task.labels && task.labels.length > 0) {
|
|
74
72
|
const labelsString = task.labels
|
package/dist/lib/settings.js
CHANGED
|
@@ -25,7 +25,7 @@ export function loadSettings() {
|
|
|
25
25
|
try {
|
|
26
26
|
const fileContents = fs.readFileSync(localSettingsPath, 'utf8');
|
|
27
27
|
fs.writeFileSync(SETTINGS_FILE, fileContents);
|
|
28
|
-
console.log(chalk
|
|
28
|
+
console.log(chalk.cyan(`Migrated settings.yaml to ${SETTINGS_FILE}`));
|
|
29
29
|
}
|
|
30
30
|
catch (error) {
|
|
31
31
|
console.error('Error migrating settings.yaml:', error);
|
package/dist/lib/validation.js
CHANGED
|
@@ -39,13 +39,11 @@ export const NumericStringSchema = z
|
|
|
39
39
|
export function validateOptions(schema, data) {
|
|
40
40
|
const result = schema.safeParse(data);
|
|
41
41
|
if (!result.success) {
|
|
42
|
-
const
|
|
43
|
-
const simpleErrorMessages = issues
|
|
42
|
+
const simpleErrorMessages = result.error.issues
|
|
44
43
|
.map((err) => {
|
|
45
|
-
|
|
46
|
-
if (err.path.length === 0)
|
|
44
|
+
if (err.path.length === 0) {
|
|
47
45
|
return err.message;
|
|
48
|
-
|
|
46
|
+
}
|
|
49
47
|
return `${err.path.join('.')}: ${err.message}`;
|
|
50
48
|
})
|
|
51
49
|
.join('\n');
|