baton-issue-tracker 1.7.0 → 1.9.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/package.json +1 -1
- package/source/cli.js +7 -0
- package/source/commands/delete.js +99 -0
- package/source/commands/reject.js +99 -0
package/package.json
CHANGED
package/source/cli.js
CHANGED
|
@@ -18,12 +18,14 @@ import { run as runNext } from './commands/next.js';
|
|
|
18
18
|
import { run as runLoop } from './commands/loop.js';
|
|
19
19
|
import { run as runStatus } from './commands/status.js';
|
|
20
20
|
import { run as runApprove } from './commands/approve.js';
|
|
21
|
+
import { run as runReject } from './commands/reject.js';
|
|
21
22
|
import { wantsHelp } from './util.js';
|
|
22
23
|
import { run as runView} from './commands/view.js';
|
|
23
24
|
import { run as runSearch } from './commands/search.js';
|
|
24
25
|
import { run as runList } from './commands/list.js';
|
|
25
26
|
import { run as runCreate } from './commands/create.js'
|
|
26
27
|
import { run as runUpdate } from './commands/update.js';
|
|
28
|
+
import { run as runDelete } from './commands/delete.js';
|
|
27
29
|
import { run as runPriority } from './commands/priority.js';
|
|
28
30
|
import { run as runLog } from './commands/log.js';
|
|
29
31
|
import { run as runRegister } from './commands/register.js';
|
|
@@ -48,6 +50,7 @@ Commands:
|
|
|
48
50
|
approve Move an issue from in-review to closed
|
|
49
51
|
priority Set an issue's priority level
|
|
50
52
|
update Updates an issue's specified fields
|
|
53
|
+
delete Deletes an issue
|
|
51
54
|
log Show activity history for an issue
|
|
52
55
|
|
|
53
56
|
Options:
|
|
@@ -76,6 +79,7 @@ Options:
|
|
|
76
79
|
create --token-limit <n> Optional token budget for this issue
|
|
77
80
|
create --json Output as JSON (for AI agents)
|
|
78
81
|
approve <id> [--json]
|
|
82
|
+
reject <id> --reason <text> Reject an issue with a given reason
|
|
79
83
|
priority <id> <level> [--json] low | medium | high
|
|
80
84
|
update --title <text> New title
|
|
81
85
|
update --description <text> New description
|
|
@@ -83,6 +87,7 @@ Options:
|
|
|
83
87
|
update --status <s> open | in-progress | closed
|
|
84
88
|
update --priority <level> low | medium | high
|
|
85
89
|
update --json Output as JSON (for AI agents)
|
|
90
|
+
delete <id> [--yes]
|
|
86
91
|
log <id> [--json]
|
|
87
92
|
|
|
88
93
|
Examples:
|
|
@@ -135,9 +140,11 @@ async function main() {
|
|
|
135
140
|
search: () => runSearch(args),
|
|
136
141
|
list: () => runList(args),
|
|
137
142
|
approve: () => runApprove(args),
|
|
143
|
+
reject: () => runReject(args),
|
|
138
144
|
priority: () => runPriority(args),
|
|
139
145
|
create: () => runCreate(args),
|
|
140
146
|
update: () => runUpdate(args),
|
|
147
|
+
delete: () => runDelete(args),
|
|
141
148
|
log: () => runLog(args),
|
|
142
149
|
};
|
|
143
150
|
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
// delete.js
|
|
2
|
+
// supports deleting an issue.
|
|
3
|
+
//
|
|
4
|
+
// AI was used to modify this file to support JSON outputs.
|
|
5
|
+
//
|
|
6
|
+
// Usage:
|
|
7
|
+
// baton delete <id> [--yes] [--json]
|
|
8
|
+
//
|
|
9
|
+
// Options:
|
|
10
|
+
// --yes Skip confirmation prompt
|
|
11
|
+
// --json Output in JSON format
|
|
12
|
+
// -h, --help Show this help
|
|
13
|
+
//
|
|
14
|
+
// Examples:
|
|
15
|
+
// baton delete 4
|
|
16
|
+
// baton delete 4 --yes
|
|
17
|
+
|
|
18
|
+
import { deleteIssue, getIssue } from '../services/issuesService.js';
|
|
19
|
+
import { hasFlag, wantsHelp, renderOutput, renderError } from '../util.js';
|
|
20
|
+
import { confirm } from '@inquirer/prompts';
|
|
21
|
+
|
|
22
|
+
const USAGE = "Usage: baton delete <id> [options]\n\nOptions:\n --yes Skip confirmation prompt\n --json Output in JSON format\n -h, --help Show this help";
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
* Deletes an issue for a specified ID.
|
|
26
|
+
*
|
|
27
|
+
* @param {string[]} args - The command line arguments
|
|
28
|
+
* @returns {Promise<number>} The exit code: 0 is success, 1 is error.
|
|
29
|
+
*/
|
|
30
|
+
export async function run(args) {
|
|
31
|
+
const isJson = hasFlag(args, '--json');
|
|
32
|
+
|
|
33
|
+
// (0) Help check
|
|
34
|
+
if (wantsHelp(args)) {
|
|
35
|
+
console.log(USAGE);
|
|
36
|
+
return 0;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
// (1) Parse arguments
|
|
40
|
+
const idArgs = args.filter(arg => !arg.startsWith('-'));
|
|
41
|
+
if (idArgs.length === 0) {
|
|
42
|
+
renderError(isJson, `No ID provided.\n${USAGE}`, 'MISSING_ID');
|
|
43
|
+
return 1;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
const id = Number(idArgs[0]);
|
|
47
|
+
if (!Number.isInteger(id)) {
|
|
48
|
+
renderError(isJson, `Invalid ID "${idArgs[0]}". ID must be an integer.`, 'INVALID_ID');
|
|
49
|
+
return 1;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
const isYes = hasFlag(args, "--yes");
|
|
53
|
+
|
|
54
|
+
try {
|
|
55
|
+
// (2) Check if issue exists before confirming
|
|
56
|
+
try {
|
|
57
|
+
await getIssue(id);
|
|
58
|
+
} catch (error) {
|
|
59
|
+
if (error.message.includes("not found")) {
|
|
60
|
+
renderError(isJson, error.message, 'NOT_FOUND');
|
|
61
|
+
} else {
|
|
62
|
+
renderError(isJson, error.message);
|
|
63
|
+
}
|
|
64
|
+
return 1;
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
// (3) Confirmation prompt
|
|
68
|
+
let confirmed = isYes;
|
|
69
|
+
if (!confirmed && !isJson) { // Only prompt if not JSON and not --yes
|
|
70
|
+
try {
|
|
71
|
+
confirmed = await confirm({ message: `Are you sure you want to delete issue #${id}?`, default: false });
|
|
72
|
+
} catch {
|
|
73
|
+
return 1;
|
|
74
|
+
}
|
|
75
|
+
} else if (!confirmed && isJson) {
|
|
76
|
+
// In JSON mode, do not prompt. If --yes is missing, we fail or assume no.
|
|
77
|
+
renderError(isJson, "Confirmation required. Use --yes to confirm deletion in JSON mode.", 'CONFIRMATION_REQUIRED');
|
|
78
|
+
return 1;
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
if (!confirmed) {
|
|
82
|
+
console.log("Deletion cancelled.");
|
|
83
|
+
return 0;
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
// (4) Execution
|
|
87
|
+
await deleteIssue(id);
|
|
88
|
+
|
|
89
|
+
const envelope = { status: 'success', id: id, message: `Issue #${id} deleted successfully.` };
|
|
90
|
+
renderOutput(isJson, envelope, () => {
|
|
91
|
+
console.log(`Issue #${id} deleted successfully.`);
|
|
92
|
+
});
|
|
93
|
+
|
|
94
|
+
return 0;
|
|
95
|
+
} catch (error) {
|
|
96
|
+
renderError(isJson, error.message);
|
|
97
|
+
return 1;
|
|
98
|
+
}
|
|
99
|
+
}
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
// reject.js
|
|
2
|
+
// supports rejecting an issue.
|
|
3
|
+
//
|
|
4
|
+
// AI Was used in generating this file.
|
|
5
|
+
// Usage:
|
|
6
|
+
// baton reject <id> [options]
|
|
7
|
+
//
|
|
8
|
+
// Options:
|
|
9
|
+
// --reason <text> Reason for rejection (required)
|
|
10
|
+
// --json Output in JSON format
|
|
11
|
+
// -h, --help Show this help
|
|
12
|
+
//
|
|
13
|
+
// Examples:
|
|
14
|
+
// baton reject 5 --reason "Needs more detail"
|
|
15
|
+
|
|
16
|
+
import { rejectIssue, getIssue } from '../services/issuesService.js';
|
|
17
|
+
import { Status } from '../models/issue.js';
|
|
18
|
+
import { hasFlag, getFlagValue, wantsHelp, renderOutput, renderError, serializeIssue } from '../util.js';
|
|
19
|
+
|
|
20
|
+
const USAGE = "Usage:\n baton reject <id> [options]\n\nOptions:\n --reason <text> Reason for rejection (required)\n --json Output in JSON format\n -h, --help Show this help";
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* Rejects an issue for a specified ID.
|
|
24
|
+
*
|
|
25
|
+
* @param {string[]} args - The command line arguments
|
|
26
|
+
* @returns {Promise<number>} The exit code: 0 is success, 1 is error.
|
|
27
|
+
*/
|
|
28
|
+
export async function run(args) {
|
|
29
|
+
const isJson = hasFlag(args, '--json');
|
|
30
|
+
|
|
31
|
+
// (0) Help check
|
|
32
|
+
if (wantsHelp(args)) {
|
|
33
|
+
console.log(USAGE);
|
|
34
|
+
return 0;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
// (1) Parse arguments
|
|
38
|
+
const idArgs = args.filter(arg => !arg.startsWith('-'));
|
|
39
|
+
if (idArgs.length === 0) {
|
|
40
|
+
renderError(isJson, `No ID provided.\n${USAGE}`, 'MISSING_ID');
|
|
41
|
+
return 1;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
const id = Number(idArgs[0]);
|
|
45
|
+
if (!Number.isInteger(id)) {
|
|
46
|
+
renderError(isJson, `Invalid ID "${idArgs[0]}". ID must be an integer.`, 'INVALID_ID');
|
|
47
|
+
return 1;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
if (!hasFlag(args, "--reason")) {
|
|
51
|
+
renderError(isJson, `Missing reason for reject.\n${USAGE}`, 'MISSING_REASON');
|
|
52
|
+
return 1;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
let reasonText;
|
|
56
|
+
try {
|
|
57
|
+
reasonText = getFlagValue(args, "--reason");
|
|
58
|
+
} catch (error) {
|
|
59
|
+
renderError(isJson, error.message, 'INVALID_REASON');
|
|
60
|
+
return 1;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
if (!reasonText || reasonText.trim() === "") {
|
|
64
|
+
renderError(isJson, "Reason for rejection cannot be empty.", 'EMPTY_REASON');
|
|
65
|
+
return 1;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
let issue;
|
|
69
|
+
try {
|
|
70
|
+
issue = await getIssue(id);
|
|
71
|
+
} catch (error) {
|
|
72
|
+
if (error.message.includes("not found")) {
|
|
73
|
+
renderError(isJson, error.message, 'NOT_FOUND');
|
|
74
|
+
} else {
|
|
75
|
+
renderError(isJson, error.message);
|
|
76
|
+
}
|
|
77
|
+
return 1;
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
if (issue.status !== Status.IN_REVIEW) {
|
|
81
|
+
renderError(isJson, `Issue #${id} is currently "${issue.status}". Only issues in "${Status.IN_REVIEW}" status can be rejected.`, 'INVALID_STATE');
|
|
82
|
+
return 1;
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
try {
|
|
86
|
+
// (3) Perform rejection
|
|
87
|
+
const updatedIssue = await rejectIssue(id, reasonText);
|
|
88
|
+
const envelope = { status: 'success', issue: serializeIssue(updatedIssue) };
|
|
89
|
+
|
|
90
|
+
renderOutput(isJson, envelope, () => {
|
|
91
|
+
console.log(`Issue #${id} rejected successfully and moved back to "${updatedIssue.status}".`);
|
|
92
|
+
});
|
|
93
|
+
|
|
94
|
+
return 0;
|
|
95
|
+
} catch (error) {
|
|
96
|
+
renderError(isJson, error.message);
|
|
97
|
+
return 1;
|
|
98
|
+
}
|
|
99
|
+
}
|