jiradc-cli 1.0.25 → 1.0.26
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/index.js +154 -83
- package/package.json +2 -1
package/dist/index.js
CHANGED
|
@@ -25,10 +25,10 @@ function intInRange(min, max) {
|
|
|
25
25
|
return (raw) => {
|
|
26
26
|
const n = parseInt(raw, 10);
|
|
27
27
|
if (Number.isNaN(n) || !Number.isFinite(n)) {
|
|
28
|
-
throw new InvalidArgumentError(
|
|
28
|
+
throw new InvalidArgumentError("Must be an integer.");
|
|
29
29
|
}
|
|
30
30
|
if (n < min || n > max) {
|
|
31
|
-
throw new InvalidArgumentError(`Must be between ${min} and ${max}
|
|
31
|
+
throw new InvalidArgumentError(`Must be between ${min} and ${max}.`);
|
|
32
32
|
}
|
|
33
33
|
return n;
|
|
34
34
|
};
|
|
@@ -36,37 +36,80 @@ function intInRange(min, max) {
|
|
|
36
36
|
function nonNegativeInt(raw) {
|
|
37
37
|
const n = parseInt(raw, 10);
|
|
38
38
|
if (Number.isNaN(n) || n < 0) {
|
|
39
|
-
throw new InvalidArgumentError(
|
|
39
|
+
throw new InvalidArgumentError("Must be a non-negative integer.");
|
|
40
40
|
}
|
|
41
41
|
return n;
|
|
42
42
|
}
|
|
43
43
|
function positiveInt(raw) {
|
|
44
44
|
const n = parseInt(raw, 10);
|
|
45
45
|
if (Number.isNaN(n) || n < 1) {
|
|
46
|
-
throw new InvalidArgumentError(
|
|
46
|
+
throw new InvalidArgumentError("Must be a positive integer.");
|
|
47
47
|
}
|
|
48
48
|
return n;
|
|
49
49
|
}
|
|
50
|
+
function text(raw) {
|
|
51
|
+
return raw;
|
|
52
|
+
}
|
|
53
|
+
function date(raw) {
|
|
54
|
+
const m = /^(\d{4})-(\d{2})-(\d{2})$/.exec(raw);
|
|
55
|
+
if (!m) {
|
|
56
|
+
throw new InvalidArgumentError("Must be a date in YYYY-MM-DD format.");
|
|
57
|
+
}
|
|
58
|
+
const [, y, mo, d] = m;
|
|
59
|
+
const year = Number(y);
|
|
60
|
+
const month = Number(mo);
|
|
61
|
+
const day = Number(d);
|
|
62
|
+
const dt = new Date(Date.UTC(year, month - 1, day));
|
|
63
|
+
if (dt.getUTCFullYear() !== year || dt.getUTCMonth() !== month - 1 || dt.getUTCDate() !== day) {
|
|
64
|
+
throw new InvalidArgumentError("Not a real calendar date.");
|
|
65
|
+
}
|
|
66
|
+
return raw;
|
|
67
|
+
}
|
|
68
|
+
function dateTime(raw) {
|
|
69
|
+
if (!/^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}/.test(raw) || Number.isNaN(Date.parse(raw))) {
|
|
70
|
+
throw new InvalidArgumentError("Must be an ISO 8601 date-time, e.g. 2026-06-08T14:30:00Z.");
|
|
71
|
+
}
|
|
72
|
+
return raw;
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
// ../../cli-utils/dist/json.js
|
|
76
|
+
import { InvalidArgumentError as InvalidArgumentError2 } from "commander";
|
|
77
|
+
function jsonShape(schema) {
|
|
78
|
+
return (raw) => {
|
|
79
|
+
let parsed;
|
|
80
|
+
try {
|
|
81
|
+
parsed = JSON.parse(raw);
|
|
82
|
+
} catch {
|
|
83
|
+
throw new InvalidArgumentError2("Must be valid JSON.");
|
|
84
|
+
}
|
|
85
|
+
const result = schema.safeParse(parsed);
|
|
86
|
+
if (!result.success) {
|
|
87
|
+
const issues3 = result.error.issues.map((i) => `${i.path.join(".") || "(root)"}: ${i.message}`).join("; ");
|
|
88
|
+
throw new InvalidArgumentError2(`Invalid JSON shape \u2014 ${issues3}`);
|
|
89
|
+
}
|
|
90
|
+
return result.data;
|
|
91
|
+
};
|
|
92
|
+
}
|
|
50
93
|
|
|
51
94
|
// ../../cli-utils/dist/text-or-file.js
|
|
52
95
|
import { readFileSync as readFileSync3 } from "fs";
|
|
53
|
-
import { InvalidArgumentError as
|
|
96
|
+
import { InvalidArgumentError as InvalidArgumentError3, Option } from "commander";
|
|
54
97
|
var STDIN_REF = "-";
|
|
55
98
|
function rejectStdinSentinel(value) {
|
|
56
99
|
if (value === "@-" || value === STDIN_REF) {
|
|
57
|
-
throw new
|
|
100
|
+
throw new InvalidArgumentError3(`"${value}" looks like a stdin redirect, which is not supported here. Pass the text directly, or read it from a file/stdin with the matching --\u2026-file <path|-> option.`);
|
|
58
101
|
}
|
|
59
102
|
return value;
|
|
60
103
|
}
|
|
61
104
|
function readFileOrStdin(ref) {
|
|
62
105
|
if (ref === STDIN_REF) {
|
|
63
106
|
if (process.stdin.isTTY) {
|
|
64
|
-
throw new
|
|
107
|
+
throw new InvalidArgumentError3('"--\u2026-file -" reads stdin, but stdin is a terminal (nothing piped).');
|
|
65
108
|
}
|
|
66
109
|
try {
|
|
67
110
|
return readFileSync3(0, "utf8");
|
|
68
111
|
} catch (err) {
|
|
69
|
-
throw new
|
|
112
|
+
throw new InvalidArgumentError3(`failed to read stdin for "--\u2026-file -": ${err.message}`);
|
|
70
113
|
}
|
|
71
114
|
}
|
|
72
115
|
try {
|
|
@@ -74,28 +117,28 @@ function readFileOrStdin(ref) {
|
|
|
74
117
|
} catch (err) {
|
|
75
118
|
const e = err;
|
|
76
119
|
if (e.code === "ENOENT") {
|
|
77
|
-
throw new
|
|
120
|
+
throw new InvalidArgumentError3(`file not found: "${ref}".`);
|
|
78
121
|
}
|
|
79
|
-
throw new
|
|
122
|
+
throw new InvalidArgumentError3(`failed to read file "${ref}": ${e.message}`);
|
|
80
123
|
}
|
|
81
124
|
}
|
|
82
125
|
function textOrFileOption(cmd, name, opts = {}) {
|
|
83
126
|
const label = `${name.charAt(0).toUpperCase()}${name.slice(1)} content`;
|
|
84
127
|
cmd.option(`--${name} <text>`, opts.description ?? label, rejectStdinSentinel);
|
|
85
|
-
cmd.addOption(new Option(`--${name}-file <path>`, `Read --${name} from a file, or "-" for stdin (mutually exclusive with --${name})`).conflicts(name));
|
|
128
|
+
cmd.addOption(new Option(`--${name}-file <path>`, `Read --${name} from a file, or "-" for stdin (mutually exclusive with --${name})`).conflicts(name).argParser(text));
|
|
86
129
|
return cmd;
|
|
87
130
|
}
|
|
88
131
|
function resolveTextOrFile(opts, name, { required = true } = {}) {
|
|
89
132
|
const literal = opts[name];
|
|
90
133
|
const ref = opts[`${name}File`];
|
|
91
134
|
if (literal !== void 0 && ref !== void 0) {
|
|
92
|
-
throw new
|
|
135
|
+
throw new InvalidArgumentError3(`--${name} and --${name}-file are mutually exclusive; provide only one.`);
|
|
93
136
|
}
|
|
94
137
|
if (ref !== void 0) {
|
|
95
138
|
return readFileOrStdin(ref);
|
|
96
139
|
}
|
|
97
140
|
if (literal === void 0 && required) {
|
|
98
|
-
throw new
|
|
141
|
+
throw new InvalidArgumentError3(`a ${name} is required: provide --${name} <text> or --${name}-file <path>.`);
|
|
99
142
|
}
|
|
100
143
|
return literal;
|
|
101
144
|
}
|
|
@@ -127,7 +170,7 @@ function subjectArg(cmd, name, opts = {}) {
|
|
|
127
170
|
function subEntityOption(cmd, entity, opts = {}) {
|
|
128
171
|
const numeric = opts.numeric ?? SUB_ENTITY_ID_NUMERIC[entity] ?? true;
|
|
129
172
|
const description = `${entity.charAt(0).toUpperCase()}${entity.slice(1)} id`;
|
|
130
|
-
return defineOption(cmd, `--${entity}-id <id>`, description, numeric ? positiveInt :
|
|
173
|
+
return defineOption(cmd, `--${entity}-id <id>`, description, numeric ? positiveInt : text, opts.mandatory);
|
|
131
174
|
}
|
|
132
175
|
function bodyOption(cmd, opts = {}) {
|
|
133
176
|
return textOrFileOption(cmd, "body", { description: "Prose body content", ...opts });
|
|
@@ -717,7 +760,7 @@ function transformTransitions(response) {
|
|
|
717
760
|
|
|
718
761
|
// src/commands/board/issues.ts
|
|
719
762
|
function issues(parent) {
|
|
720
|
-
const cmd = parent.command("issues").description("Get issues for a board").addArgument(new Argument("<id>", "Board ID").argParser(positiveInt)).option("--limit <number>", "Max results (1-50, Jira DC caps at 50)", intInRange(1, 50), 25).option("--start <number>", "Starting index for pagination", nonNegativeInt).option("--fields <fields>", "Comma-separated field names to return").option("--jql <jql>", "Additional JQL filter within the board");
|
|
763
|
+
const cmd = parent.command("issues").description("Get issues for a board").addArgument(new Argument("<id>", "Board ID").argParser(positiveInt)).option("--limit <number>", "Max results (1-50, Jira DC caps at 50)", intInRange(1, 50), 25).option("--start <number>", "Starting index for pagination", nonNegativeInt).option("--fields <fields>", "Comma-separated field names to return", text).option("--jql <jql>", "Additional JQL filter within the board", text);
|
|
721
764
|
examples(cmd, [
|
|
722
765
|
"42",
|
|
723
766
|
"42 --limit 10",
|
|
@@ -741,7 +784,7 @@ function issues(parent) {
|
|
|
741
784
|
import { Option as Option2 } from "commander";
|
|
742
785
|
var BOARD_TYPES = ["scrum", "kanban", "simple"];
|
|
743
786
|
function list(parent) {
|
|
744
|
-
const cmd = parent.command("list").description("List agile boards").option("--limit <number>", "Max results (1-1000)", intInRange(1, 1e3), 25).option("--project <key>", "Filter boards by project key or ID").addOption(new Option2("--type <type>", "Board type filter").choices(BOARD_TYPES)).option("--name <name>", "Filter boards by name");
|
|
787
|
+
const cmd = parent.command("list").description("List agile boards").option("--limit <number>", "Max results (1-1000)", intInRange(1, 1e3), 25).option("--project <key>", "Filter boards by project key or ID", text).addOption(new Option2("--type <type>", "Board type filter").choices(BOARD_TYPES)).option("--name <name>", "Filter boards by name", text);
|
|
745
788
|
examples(cmd, ["", "--limit 10", "--project PROJ", '--type scrum --name "Team Board"']);
|
|
746
789
|
cmd.action(async (opts) => {
|
|
747
790
|
const client = getClient();
|
|
@@ -772,7 +815,7 @@ var ASSIGNEE_TYPES = [
|
|
|
772
815
|
"UNASSIGNED"
|
|
773
816
|
];
|
|
774
817
|
function create(parent) {
|
|
775
|
-
const cmd = parent.command("create").description("Create a new component in a project").requiredOption("--project <key>", "Project key (e.g., AI)").requiredOption("--name <name>", "Component name").option("--lead <username>", "Username of the component lead").addOption(new Option3("--assignee-type <type>", "Assignee strategy").choices(ASSIGNEE_TYPES));
|
|
818
|
+
const cmd = parent.command("create").description("Create a new component in a project").requiredOption("--project <key>", "Project key (e.g., AI)", text).requiredOption("--name <name>", "Component name", text).option("--lead <username>", "Username of the component lead", text).addOption(new Option3("--assignee-type <type>", "Assignee strategy").choices(ASSIGNEE_TYPES));
|
|
776
819
|
textOrFileOption(cmd, "description", { description: "Component description" });
|
|
777
820
|
examples(cmd, [
|
|
778
821
|
"--project AI --name Backend",
|
|
@@ -797,40 +840,40 @@ function create(parent) {
|
|
|
797
840
|
|
|
798
841
|
// src/commands/component/delete.ts
|
|
799
842
|
function deleteComponent(parent) {
|
|
800
|
-
const cmd = parent.command("delete
|
|
843
|
+
const cmd = parent.command("delete").description("Delete a component, optionally reassigning its issues to another component").argument("<id>", "Component ID", positiveInt).option("--move-issues-to <id>", "Reassign existing issues to this component ID before deletion", text);
|
|
801
844
|
examples(cmd, ["11289", "11289 --move-issues-to 11290"]);
|
|
802
845
|
cmd.action(async (id, opts) => {
|
|
803
846
|
const client = getClient();
|
|
804
|
-
await client.components.delete({ id, moveIssuesTo: opts.moveIssuesTo });
|
|
847
|
+
await client.components.delete({ id: String(id), moveIssuesTo: opts.moveIssuesTo });
|
|
805
848
|
output({ deleted: true, componentId: id, ...opts.moveIssuesTo && { movedIssuesTo: opts.moveIssuesTo } });
|
|
806
849
|
});
|
|
807
850
|
}
|
|
808
851
|
|
|
809
852
|
// src/commands/component/get.ts
|
|
810
853
|
function get(parent) {
|
|
811
|
-
const cmd = parent.command("get
|
|
854
|
+
const cmd = parent.command("get").description("Get a component by ID").argument("<id>", "Component ID", positiveInt);
|
|
812
855
|
examples(cmd, ["11289"]);
|
|
813
856
|
cmd.action(async (id) => {
|
|
814
857
|
const client = getClient();
|
|
815
|
-
const result = await client.components.get({ id });
|
|
858
|
+
const result = await client.components.get({ id: String(id) });
|
|
816
859
|
output(transformComponent(result));
|
|
817
860
|
});
|
|
818
861
|
}
|
|
819
862
|
|
|
820
863
|
// src/commands/component/issue-count.ts
|
|
821
864
|
function issueCount(parent) {
|
|
822
|
-
const cmd = parent.command("issue-count
|
|
865
|
+
const cmd = parent.command("issue-count").description("Get the number of issues currently using this component").argument("<id>", "Component ID", positiveInt);
|
|
823
866
|
examples(cmd, ["11289"]);
|
|
824
867
|
cmd.action(async (id) => {
|
|
825
868
|
const client = getClient();
|
|
826
|
-
const result = await client.components.getRelatedIssueCounts({ id });
|
|
869
|
+
const result = await client.components.getRelatedIssueCounts({ id: String(id) });
|
|
827
870
|
output(transformComponentIssueCounts(result));
|
|
828
871
|
});
|
|
829
872
|
}
|
|
830
873
|
|
|
831
874
|
// src/commands/component/list.ts
|
|
832
875
|
function list2(parent) {
|
|
833
|
-
const cmd = parent.command("list").description("List all components for a project").requiredOption("--project <key>", "Project key (e.g., AI)");
|
|
876
|
+
const cmd = parent.command("list").description("List all components for a project").requiredOption("--project <key>", "Project key (e.g., AI)", text);
|
|
834
877
|
examples(cmd, ["--project AI"]);
|
|
835
878
|
cmd.action(async (opts) => {
|
|
836
879
|
const client = getClient();
|
|
@@ -848,7 +891,7 @@ var ASSIGNEE_TYPES2 = [
|
|
|
848
891
|
"UNASSIGNED"
|
|
849
892
|
];
|
|
850
893
|
function update(parent) {
|
|
851
|
-
const cmd = parent.command("update
|
|
894
|
+
const cmd = parent.command("update").description("Update an existing component (only provided fields are changed)").argument("<id>", "Component ID", positiveInt).option("--name <name>", "New component name", text).option("--lead <username>", "Username of the component lead (empty string clears it)", text).addOption(new Option4("--assignee-type <type>", "New assignee strategy").choices(ASSIGNEE_TYPES2));
|
|
852
895
|
textOrFileOption(cmd, "description", { description: "New component description" });
|
|
853
896
|
examples(cmd, [
|
|
854
897
|
"11289 --name Backend",
|
|
@@ -863,7 +906,7 @@ function update(parent) {
|
|
|
863
906
|
}
|
|
864
907
|
const client = getClient();
|
|
865
908
|
const result = await client.components.update({
|
|
866
|
-
id,
|
|
909
|
+
id: String(id),
|
|
867
910
|
name: opts.name,
|
|
868
911
|
description,
|
|
869
912
|
leadUserName: opts.lead,
|
|
@@ -895,7 +938,7 @@ function registerComponentCommands(program) {
|
|
|
895
938
|
|
|
896
939
|
// src/commands/field/options.ts
|
|
897
940
|
function options(parent) {
|
|
898
|
-
const cmd = parent.command("options
|
|
941
|
+
const cmd = parent.command("options").description("Get available options for a custom field").argument("<id>", "Field ID", text).option("--query <text>", "Filter options by text", text).option("--limit <number>", "Max results to return (1-1000)", intInRange(1, 1e3), 25).option("--start <number>", "Page number (1-indexed)", positiveInt);
|
|
899
942
|
examples(cmd, ["10001", '10001 --query "High"', "10001 --limit 20 --start 2"]);
|
|
900
943
|
cmd.action(async (id, opts) => {
|
|
901
944
|
const client = getClient();
|
|
@@ -911,7 +954,7 @@ function options(parent) {
|
|
|
911
954
|
|
|
912
955
|
// src/commands/field/search.ts
|
|
913
956
|
function search(parent) {
|
|
914
|
-
const cmd = parent.command("search
|
|
957
|
+
const cmd = parent.command("search").description("Search for fields by name or ID").argument("<keyword>", "Search keyword", text).option("--limit <number>", "Maximum number of results (1-1000)", intInRange(1, 1e3), 25);
|
|
915
958
|
examples(cmd, ["epic", "customfield_10100", "priority --limit 5"]);
|
|
916
959
|
cmd.action(async (keyword, opts) => {
|
|
917
960
|
const client = getClient();
|
|
@@ -944,9 +987,18 @@ async function resolveUserToken(token) {
|
|
|
944
987
|
return token;
|
|
945
988
|
}
|
|
946
989
|
|
|
990
|
+
// src/utils/validators.ts
|
|
991
|
+
import { InvalidArgumentError as InvalidArgumentError4 } from "commander";
|
|
992
|
+
function issueKey(raw) {
|
|
993
|
+
if (!/^(\d+|[A-Z][A-Z0-9]+-\d+)$/.test(raw)) {
|
|
994
|
+
throw new InvalidArgumentError4("Must be a Jira issue key (e.g. PROJ-123) or a numeric issue id.");
|
|
995
|
+
}
|
|
996
|
+
return raw;
|
|
997
|
+
}
|
|
998
|
+
|
|
947
999
|
// src/commands/issue/assign.ts
|
|
948
1000
|
function assign(parent) {
|
|
949
|
-
const cmd = parent.command("assign
|
|
1001
|
+
const cmd = parent.command("assign").description('Assign an issue. --assignee is a username, "me", or "none" to unassign.').argument("<key>", "Issue key", issueKey).requiredOption("--assignee <user>", 'Username to assign, "me" for the current user, or "none" to unassign', text);
|
|
950
1002
|
examples(cmd, ["PROJ-123 --assignee jsmith", "PROJ-123 --assignee me", "PROJ-123 --assignee none"]);
|
|
951
1003
|
cmd.action(async (key, opts) => {
|
|
952
1004
|
const resolved = await resolveUserToken(opts.assignee);
|
|
@@ -961,7 +1013,7 @@ function assign(parent) {
|
|
|
961
1013
|
|
|
962
1014
|
// src/commands/issue/attachment/delete.ts
|
|
963
1015
|
function deleteAttachment(parent) {
|
|
964
|
-
const cmd = parent.command("delete
|
|
1016
|
+
const cmd = parent.command("delete").description("Delete an attachment by ID").argument("<key>", "Issue key", issueKey);
|
|
965
1017
|
subEntityOption(cmd, "attachment", { mandatory: true });
|
|
966
1018
|
examples(cmd, ["PROJ-123 --attachment-id 12345"]);
|
|
967
1019
|
cmd.action(async (key, opts) => {
|
|
@@ -975,7 +1027,7 @@ function deleteAttachment(parent) {
|
|
|
975
1027
|
import { mkdirSync as mkdirSync2 } from "fs";
|
|
976
1028
|
import { join as join3 } from "path";
|
|
977
1029
|
function downloadAll(parent) {
|
|
978
|
-
const cmd = parent.command("download-all
|
|
1030
|
+
const cmd = parent.command("download-all").description("Download all attachments from an issue").argument("<key>", "Issue key", issueKey).requiredOption("--output <dir>", "Local directory to save attachments into", text);
|
|
979
1031
|
examples(cmd, ["PROJ-123 --output ./downloads"]);
|
|
980
1032
|
cmd.action(async (key, opts) => {
|
|
981
1033
|
const client = getClient();
|
|
@@ -1016,9 +1068,9 @@ function downloadAll(parent) {
|
|
|
1016
1068
|
|
|
1017
1069
|
// src/commands/issue/attachment/download.ts
|
|
1018
1070
|
function download(parent) {
|
|
1019
|
-
const cmd = parent.command("download
|
|
1071
|
+
const cmd = parent.command("download").description("Download a single attachment by ID").argument("<key>", "Issue key", issueKey);
|
|
1020
1072
|
subEntityOption(cmd, "attachment", { mandatory: true });
|
|
1021
|
-
cmd.requiredOption("--output <path>", "Local file path to save the attachment");
|
|
1073
|
+
cmd.requiredOption("--output <path>", "Local file path to save the attachment", text);
|
|
1022
1074
|
examples(cmd, ["PROJ-123 --attachment-id 12345 --output ./report.pdf"]);
|
|
1023
1075
|
cmd.action(async (key, opts) => {
|
|
1024
1076
|
const client = getClient();
|
|
@@ -1043,7 +1095,7 @@ function download(parent) {
|
|
|
1043
1095
|
|
|
1044
1096
|
// src/commands/issue/attachment/list.ts
|
|
1045
1097
|
function list3(parent) {
|
|
1046
|
-
const cmd = parent.command("list
|
|
1098
|
+
const cmd = parent.command("list").description("List attachments on an issue").argument("<key>", "Issue key", issueKey);
|
|
1047
1099
|
examples(cmd, ["PROJ-123"]);
|
|
1048
1100
|
cmd.action(async (key) => {
|
|
1049
1101
|
const client = getClient();
|
|
@@ -1068,7 +1120,7 @@ function list3(parent) {
|
|
|
1068
1120
|
|
|
1069
1121
|
// src/commands/issue/attachment/upload.ts
|
|
1070
1122
|
function upload(parent) {
|
|
1071
|
-
const cmd = parent.command("upload
|
|
1123
|
+
const cmd = parent.command("upload").description("Upload attachments to an issue").argument("<key>", "Issue key", issueKey).requiredOption("--files <paths>", "Comma-separated file paths to upload", text);
|
|
1072
1124
|
examples(cmd, ["PROJ-123 --files ./report.pdf", "PROJ-123 --files ./a.txt,./b.png"]);
|
|
1073
1125
|
cmd.action(async (key, opts) => {
|
|
1074
1126
|
const client = getClient();
|
|
@@ -1111,7 +1163,7 @@ function registerAttachmentCommands(parent) {
|
|
|
1111
1163
|
|
|
1112
1164
|
// src/commands/issue/batch-changelog.ts
|
|
1113
1165
|
function batchChangelog(parent) {
|
|
1114
|
-
const cmd = parent.command("batch-changelog
|
|
1166
|
+
const cmd = parent.command("batch-changelog").description("Get changelogs for multiple issues at once").argument("<keys>", "Comma-separated issue keys", text).option("--limit <number>", "Max changelog entries per issue (1-50, Jira DC caps at 50)", intInRange(1, 50), 25);
|
|
1115
1167
|
examples(cmd, ["PROJ-1,PROJ-2,PROJ-3", "PROJ-123,PROJ-124 --limit 10"]);
|
|
1116
1168
|
cmd.action(async (keys, opts) => {
|
|
1117
1169
|
const client = getClient();
|
|
@@ -1131,14 +1183,16 @@ function batchChangelog(parent) {
|
|
|
1131
1183
|
}
|
|
1132
1184
|
|
|
1133
1185
|
// src/commands/issue/batch-create.ts
|
|
1186
|
+
import { z } from "zod";
|
|
1187
|
+
var issuesSchema = z.array(z.record(z.unknown())).min(1, "must be a non-empty array");
|
|
1134
1188
|
function batchCreate(parent) {
|
|
1135
|
-
const cmd = parent.command("batch-create").description("Create multiple issues from a JSON array").requiredOption("--issues <json>", "JSON array of issue objects");
|
|
1189
|
+
const cmd = parent.command("batch-create").description("Create multiple issues from a JSON array").requiredOption("--issues <json>", "JSON array of issue objects", jsonShape(issuesSchema));
|
|
1136
1190
|
examples(cmd, [
|
|
1137
1191
|
`--issues '[{"projectKeyOrId":"PROJ","issueTypeName":"Task","summary":"Task 1"},{"projectKeyOrId":"PROJ","issueTypeName":"Task","summary":"Task 2"}]'`
|
|
1138
1192
|
]);
|
|
1139
1193
|
cmd.action(async (opts) => {
|
|
1140
1194
|
const client = getClient();
|
|
1141
|
-
const parsed =
|
|
1195
|
+
const parsed = opts.issues;
|
|
1142
1196
|
const results = [];
|
|
1143
1197
|
for (const issue of parsed) {
|
|
1144
1198
|
try {
|
|
@@ -1154,7 +1208,7 @@ function batchCreate(parent) {
|
|
|
1154
1208
|
|
|
1155
1209
|
// src/commands/issue/changelog.ts
|
|
1156
1210
|
function changelog(parent) {
|
|
1157
|
-
const cmd = parent.command("changelog
|
|
1211
|
+
const cmd = parent.command("changelog").description("Get changelog for an issue").argument("<key>", "Issue key", issueKey).option("--limit <number>", "Max changelog entries (1-50, Jira DC caps at 50)", intInRange(1, 50), 25);
|
|
1158
1212
|
examples(cmd, ["PROJ-123", "PROJ-123 --limit 10"]);
|
|
1159
1213
|
cmd.action(async (key, opts) => {
|
|
1160
1214
|
const client = getClient();
|
|
@@ -1182,7 +1236,7 @@ var CLONE_FIELDS = [
|
|
|
1182
1236
|
"issuelinks"
|
|
1183
1237
|
];
|
|
1184
1238
|
function clone(parent) {
|
|
1185
|
-
const cmd = parent.command("clone
|
|
1239
|
+
const cmd = parent.command("clone").description("Clone an issue (create a duplicate with the same fields)").argument("<key>", "Issue key", issueKey).option("--summary <text>", 'Override the summary (default: "CLONE - <original>")', text).option("--project <key>", "Create in a different project", text).option("--assignee <username>", "Override assignee", text).option("--include-attachments", "Copy attachments to the cloned issue").option("--include-links", "Copy issue links to the cloned issue");
|
|
1186
1240
|
examples(cmd, [
|
|
1187
1241
|
"PROJ-123",
|
|
1188
1242
|
'PROJ-123 --summary "Cloned: new title"',
|
|
@@ -1259,7 +1313,7 @@ function clone(parent) {
|
|
|
1259
1313
|
|
|
1260
1314
|
// src/commands/issue/comment/create.ts
|
|
1261
1315
|
function create2(parent) {
|
|
1262
|
-
const cmd = parent.command("create
|
|
1316
|
+
const cmd = parent.command("create").description("Add a comment to an issue").argument("<key>", "Issue key", issueKey);
|
|
1263
1317
|
bodyOption(cmd);
|
|
1264
1318
|
examples(cmd, ['PROJ-123 --body "Fixed in latest build"']);
|
|
1265
1319
|
cmd.action(async (key, opts) => {
|
|
@@ -1272,7 +1326,7 @@ function create2(parent) {
|
|
|
1272
1326
|
|
|
1273
1327
|
// src/commands/issue/comment/delete.ts
|
|
1274
1328
|
function deleteComment(parent) {
|
|
1275
|
-
const cmd = parent.command("delete
|
|
1329
|
+
const cmd = parent.command("delete").description("Delete a comment from an issue").argument("<key>", "Issue key", issueKey);
|
|
1276
1330
|
subEntityOption(cmd, "comment", { mandatory: true });
|
|
1277
1331
|
examples(cmd, ["PROJ-123 --comment-id 12345"]);
|
|
1278
1332
|
cmd.action(async (key, opts) => {
|
|
@@ -1284,7 +1338,7 @@ function deleteComment(parent) {
|
|
|
1284
1338
|
|
|
1285
1339
|
// src/commands/issue/comment/update.ts
|
|
1286
1340
|
function update2(parent) {
|
|
1287
|
-
const cmd = parent.command("update
|
|
1341
|
+
const cmd = parent.command("update").description("Update an existing comment").argument("<key>", "Issue key", issueKey);
|
|
1288
1342
|
subEntityOption(cmd, "comment", { mandatory: true });
|
|
1289
1343
|
bodyOption(cmd);
|
|
1290
1344
|
examples(cmd, ['PROJ-123 --comment-id 12345 --body "Updated comment text"']);
|
|
@@ -1314,8 +1368,14 @@ function registerCommentCommands(parent) {
|
|
|
1314
1368
|
}
|
|
1315
1369
|
|
|
1316
1370
|
// src/commands/issue/create.ts
|
|
1371
|
+
import { z as z2 } from "zod";
|
|
1372
|
+
var customFieldsSchema = z2.record(z2.unknown());
|
|
1317
1373
|
function create3(parent) {
|
|
1318
|
-
const cmd = parent.command("create").description("Create a new issue").requiredOption("--project <key>", "Project key or ID").requiredOption("--type <name>", "Issue type name (e.g., Task, Bug, Story)").requiredOption("--summary <text>", "Issue summary/title").option("--assignee <user>", 'Assignee. Username, "me", or "none" to leave unassigned.').option("--reporter <user>", 'Reporter. Username or "me".').option("--priority <name>", "Priority name (e.g., High, Medium, Low)").option("--labels <labels>", "Comma-separated labels").option("--components <names>", "Comma-separated component names").option("--fix-versions <versions>", "Comma-separated fix version names").option("--due-date <date>", "Due date in YYYY-MM-DD format").option("--parent <key>", "Parent issue key (for subtasks)").option(
|
|
1374
|
+
const cmd = parent.command("create").description("Create a new issue").requiredOption("--project <key>", "Project key or ID", text).requiredOption("--type <name>", "Issue type name (e.g., Task, Bug, Story)", text).requiredOption("--summary <text>", "Issue summary/title", text).option("--assignee <user>", 'Assignee. Username, "me", or "none" to leave unassigned.', text).option("--reporter <user>", 'Reporter. Username or "me".', text).option("--priority <name>", "Priority name (e.g., High, Medium, Low)", text).option("--labels <labels>", "Comma-separated labels", text).option("--components <names>", "Comma-separated component names", text).option("--fix-versions <versions>", "Comma-separated fix version names", text).option("--due-date <date>", "Due date in YYYY-MM-DD format", date).option("--parent <key>", "Parent issue key (for subtasks)", issueKey).option(
|
|
1375
|
+
"--custom-fields <json>",
|
|
1376
|
+
`Additional custom fields as JSON (e.g., '{"customfield_10100": "EPIC-1"}')`,
|
|
1377
|
+
jsonShape(customFieldsSchema)
|
|
1378
|
+
);
|
|
1319
1379
|
textOrFileOption(cmd, "description", { description: "Issue description in wiki markup" });
|
|
1320
1380
|
examples(cmd, [
|
|
1321
1381
|
'--project PROJ --type Task --summary "Fix login bug"',
|
|
@@ -1341,7 +1401,7 @@ function create3(parent) {
|
|
|
1341
1401
|
fixVersions: opts.fixVersions?.split(",").map((v) => v.trim()),
|
|
1342
1402
|
dueDate: opts.dueDate,
|
|
1343
1403
|
parent: opts.parent,
|
|
1344
|
-
customFields: opts.customFields
|
|
1404
|
+
customFields: opts.customFields
|
|
1345
1405
|
});
|
|
1346
1406
|
output(transformCreatedIssue(result));
|
|
1347
1407
|
}
|
|
@@ -1350,7 +1410,7 @@ function create3(parent) {
|
|
|
1350
1410
|
|
|
1351
1411
|
// src/commands/issue/delete.ts
|
|
1352
1412
|
function deleteIssue(parent) {
|
|
1353
|
-
const cmd = parent.command("delete
|
|
1413
|
+
const cmd = parent.command("delete").description("Delete an issue").argument("<key>", "Issue key", issueKey).option("--delete-subtasks", "Also delete subtasks (default: false)");
|
|
1354
1414
|
examples(cmd, ["PROJ-123", "PROJ-123 --delete-subtasks"]);
|
|
1355
1415
|
cmd.action(async (key, opts) => {
|
|
1356
1416
|
const client = getClient();
|
|
@@ -1361,7 +1421,7 @@ function deleteIssue(parent) {
|
|
|
1361
1421
|
|
|
1362
1422
|
// src/commands/issue/dev-status.ts
|
|
1363
1423
|
function devStatus(parent) {
|
|
1364
|
-
const cmd = parent.command("dev-status
|
|
1424
|
+
const cmd = parent.command("dev-status").description("Get development status (PRs, commits, branches, builds) for an issue").argument("<key>", "Issue key", issueKey).option("--detail", "Include PR URLs, commit IDs, and other details");
|
|
1365
1425
|
examples(cmd, ["PROJ-123", "PROJ-123 --detail"]);
|
|
1366
1426
|
cmd.action(async (key, opts) => {
|
|
1367
1427
|
const client = getClient();
|
|
@@ -1455,7 +1515,7 @@ var DEFAULT_FIELDS = [
|
|
|
1455
1515
|
|
|
1456
1516
|
// src/commands/issue/get.ts
|
|
1457
1517
|
function get2(parent) {
|
|
1458
|
-
const cmd = parent.command("get
|
|
1518
|
+
const cmd = parent.command("get").description("Get issue details").argument("<key>", "Issue key", issueKey).option("--fields <fields>", "Comma-separated fields to return (defaults to essential fields)", text).option("--all-fields", "Return all fields instead of defaults").option("--expand <expand>", 'Expand options (e.g., "transitions", "changelog")', text);
|
|
1459
1519
|
examples(cmd, [
|
|
1460
1520
|
"PROJ-123",
|
|
1461
1521
|
"PROJ-123 --fields summary,status,assignee",
|
|
@@ -1476,7 +1536,7 @@ function get2(parent) {
|
|
|
1476
1536
|
|
|
1477
1537
|
// src/commands/issue/link-epic.ts
|
|
1478
1538
|
function linkEpic(parent) {
|
|
1479
|
-
const cmd = parent.command("link-epic
|
|
1539
|
+
const cmd = parent.command("link-epic").description("Link one or more issues to an epic").argument("<keys...>", "Issue keys to link", issueKey).requiredOption("--epic <epicKey>", "Epic issue key", issueKey);
|
|
1480
1540
|
examples(cmd, ["PROJ-456 --epic PROJ-123", "PROJ-456 PROJ-457 PROJ-458 --epic PROJ-123"]);
|
|
1481
1541
|
cmd.action(async (keys, opts) => {
|
|
1482
1542
|
const client = getClient();
|
|
@@ -1519,7 +1579,7 @@ function linkTypes(parent) {
|
|
|
1519
1579
|
|
|
1520
1580
|
// src/commands/issue/link.ts
|
|
1521
1581
|
function link(parent) {
|
|
1522
|
-
const cmd = parent.command("link").description("Link two issues together").requiredOption("--type <name>", "Link type name (e.g., 'Blocks', 'Duplicate', 'Relates')").requiredOption("--from <key>", 'Source issue key (e.g., the issue that "blocks")').requiredOption("--to <key>", 'Target issue key (e.g., the issue that "is blocked by")');
|
|
1582
|
+
const cmd = parent.command("link").description("Link two issues together").requiredOption("--type <name>", "Link type name (e.g., 'Blocks', 'Duplicate', 'Relates')", text).requiredOption("--from <key>", 'Source issue key (e.g., the issue that "blocks")', issueKey).requiredOption("--to <key>", 'Target issue key (e.g., the issue that "is blocked by")', issueKey);
|
|
1523
1583
|
commentOption(cmd, { description: "Optional comment" });
|
|
1524
1584
|
examples(cmd, [
|
|
1525
1585
|
"--type Relates --from AI-154 --to AI-149",
|
|
@@ -1545,7 +1605,7 @@ function link(parent) {
|
|
|
1545
1605
|
|
|
1546
1606
|
// src/commands/issue/search.ts
|
|
1547
1607
|
function search2(parent) {
|
|
1548
|
-
const cmd = parent.command("search
|
|
1608
|
+
const cmd = parent.command("search").description("Search issues using JQL").argument("<jql>", "JQL query string", text).option("--limit <number>", "Max results (1-50, Jira DC caps at 50)", intInRange(1, 50), 25).option("--start <number>", "Starting index for pagination", nonNegativeInt).option("--fields <fields>", "Comma-separated fields to return (defaults to essential fields)", text).option("--all-fields", "Return all fields instead of defaults");
|
|
1549
1609
|
examples(cmd, [
|
|
1550
1610
|
'"project = PROJ AND status = Open"',
|
|
1551
1611
|
'"assignee = currentUser()" --limit 10 --fields summary,status',
|
|
@@ -1566,7 +1626,7 @@ function search2(parent) {
|
|
|
1566
1626
|
|
|
1567
1627
|
// src/commands/issue/transition.ts
|
|
1568
1628
|
function transition(parent) {
|
|
1569
|
-
const cmd = parent.command("transition
|
|
1629
|
+
const cmd = parent.command("transition").description("Transition issue to a new status").argument("<key>", "Issue key", issueKey).requiredOption("--to <idOrName>", "Transition ID, or status name (case-insensitive)", text);
|
|
1570
1630
|
commentOption(cmd, { description: "Comment to add during transition" });
|
|
1571
1631
|
examples(cmd, [
|
|
1572
1632
|
"PROJ-123 --to 31",
|
|
@@ -1604,7 +1664,7 @@ function transition(parent) {
|
|
|
1604
1664
|
|
|
1605
1665
|
// src/commands/issue/transitions.ts
|
|
1606
1666
|
function transitions(parent) {
|
|
1607
|
-
const cmd = parent.command("transitions
|
|
1667
|
+
const cmd = parent.command("transitions").description("Get available transitions for an issue").argument("<key>", "Issue key", issueKey);
|
|
1608
1668
|
examples(cmd, ["PROJ-123"]);
|
|
1609
1669
|
cmd.action(async (key) => {
|
|
1610
1670
|
const client = getClient();
|
|
@@ -1618,30 +1678,33 @@ function transitions(parent) {
|
|
|
1618
1678
|
|
|
1619
1679
|
// src/commands/issue/unlink.ts
|
|
1620
1680
|
function unlink2(parent) {
|
|
1621
|
-
const cmd = parent.command("unlink
|
|
1681
|
+
const cmd = parent.command("unlink").description("Remove a link between two issues").argument("<id>", "Link ID", positiveInt);
|
|
1622
1682
|
examples(cmd, ["12345"]);
|
|
1623
1683
|
cmd.action(async (id) => {
|
|
1624
1684
|
const client = getClient();
|
|
1625
|
-
await client.links.remove({ linkId: id });
|
|
1685
|
+
await client.links.remove({ linkId: String(id) });
|
|
1626
1686
|
output({ removed: true, linkId: id });
|
|
1627
1687
|
});
|
|
1628
1688
|
}
|
|
1629
1689
|
|
|
1690
|
+
// src/commands/issue/update.ts
|
|
1691
|
+
import { z as z3 } from "zod";
|
|
1692
|
+
|
|
1630
1693
|
// src/utils/multi-value.ts
|
|
1631
|
-
import { InvalidArgumentError as
|
|
1694
|
+
import { InvalidArgumentError as InvalidArgumentError5 } from "commander";
|
|
1632
1695
|
function parseMultiValue(flagName, raw) {
|
|
1633
1696
|
const items = raw.split(",").map((s) => s.trim()).filter((s) => s.length > 0);
|
|
1634
1697
|
if (items.length === 0) {
|
|
1635
|
-
throw new
|
|
1698
|
+
throw new InvalidArgumentError5(`${flagName} cannot be empty`);
|
|
1636
1699
|
}
|
|
1637
1700
|
const lonePrefix = items.find((s) => s === "+" || s === "-");
|
|
1638
1701
|
if (lonePrefix !== void 0) {
|
|
1639
|
-
throw new
|
|
1702
|
+
throw new InvalidArgumentError5(`${flagName} has an empty value after '${lonePrefix}' prefix`);
|
|
1640
1703
|
}
|
|
1641
1704
|
const prefixed = items.filter((s) => s.startsWith("+") || s.startsWith("-"));
|
|
1642
1705
|
const bare = items.filter((s) => !s.startsWith("+") && !s.startsWith("-"));
|
|
1643
1706
|
if (prefixed.length > 0 && bare.length > 0) {
|
|
1644
|
-
throw new
|
|
1707
|
+
throw new InvalidArgumentError5(
|
|
1645
1708
|
`${flagName} mixes set and mutate syntax. Either all values have +/- prefix, or none do.`
|
|
1646
1709
|
);
|
|
1647
1710
|
}
|
|
@@ -1654,6 +1717,7 @@ function parseMultiValue(flagName, raw) {
|
|
|
1654
1717
|
}
|
|
1655
1718
|
|
|
1656
1719
|
// src/commands/issue/update.ts
|
|
1720
|
+
var fieldsSchema = z3.record(z3.unknown());
|
|
1657
1721
|
function buildUpdateOps(parsed, wrap) {
|
|
1658
1722
|
if (parsed.mode !== "mutate") return void 0;
|
|
1659
1723
|
return [...parsed.adds.map((v) => ({ add: wrap(v) })), ...parsed.removes.map((v) => ({ remove: wrap(v) }))];
|
|
@@ -1663,7 +1727,11 @@ function buildSetValue(parsed, wrap) {
|
|
|
1663
1727
|
return parsed.values.map(wrap);
|
|
1664
1728
|
}
|
|
1665
1729
|
function update3(parent) {
|
|
1666
|
-
const cmd = parent.command("update
|
|
1730
|
+
const cmd = parent.command("update").description("Update issue fields").argument("<key>", "Issue key", issueKey).option(
|
|
1731
|
+
"--fields <json>",
|
|
1732
|
+
"JSON string of fields to update (advanced; merges with shortcuts, wins on conflict)",
|
|
1733
|
+
jsonShape(fieldsSchema)
|
|
1734
|
+
).option("--no-notify-users", "Suppress notification emails (default: notify)").option("--attachments <paths>", "Comma-separated local file paths to attach", text).option("--summary <text>", "Set the issue summary", text).option("--priority <name>", "Set the priority by name (e.g. High)", text).option("--assignee <user>", 'Set the assignee. Username, "me", or "none" to unassign.', text).option("--labels <list>", 'Set labels ("a,b,c") or mutate ("+add,-remove")', text).option("--components <list>", 'Set components ("a,b") or mutate ("+add,-remove")', text).option("--fix-versions <list>", 'Set fix versions ("1.0,2.0") or mutate ("+1.0,-0.9")', text);
|
|
1667
1735
|
textOrFileOption(cmd, "description", { description: "Set the issue description (wiki markup)" });
|
|
1668
1736
|
examples(cmd, [
|
|
1669
1737
|
'PROJ-123 --summary "New title"',
|
|
@@ -1712,8 +1780,7 @@ function update3(parent) {
|
|
|
1712
1780
|
if (ops) updateOps.fixVersions = ops;
|
|
1713
1781
|
}
|
|
1714
1782
|
if (opts.fields) {
|
|
1715
|
-
|
|
1716
|
-
Object.assign(fields, parsedFields);
|
|
1783
|
+
Object.assign(fields, opts.fields);
|
|
1717
1784
|
}
|
|
1718
1785
|
const client = getClient();
|
|
1719
1786
|
const didFieldUpdate = Object.keys(fields).length > 0 || Object.keys(updateOps).length > 0;
|
|
@@ -1745,7 +1812,7 @@ function update3(parent) {
|
|
|
1745
1812
|
|
|
1746
1813
|
// src/commands/issue/worklog/create.ts
|
|
1747
1814
|
function create4(parent) {
|
|
1748
|
-
const cmd = parent.command("create
|
|
1815
|
+
const cmd = parent.command("create").description("Log time spent on an issue").argument("<key>", "Issue key", issueKey).requiredOption("--time <timeSpent>", "Time spent (e.g., '2h', '30m', '1d 4h')", text).option("--started <datetime>", "Start time in ISO 8601 format", dateTime);
|
|
1749
1816
|
commentOption(cmd, { description: "Worklog comment" });
|
|
1750
1817
|
examples(cmd, [
|
|
1751
1818
|
"PROJ-123 --time 2h",
|
|
@@ -1769,11 +1836,12 @@ function create4(parent) {
|
|
|
1769
1836
|
import { Option as Option5 } from "commander";
|
|
1770
1837
|
var ADJUST_ESTIMATE = ["new", "leave", "manual", "auto"];
|
|
1771
1838
|
function deleteWorklog(parent) {
|
|
1772
|
-
const cmd = parent.command("delete
|
|
1839
|
+
const cmd = parent.command("delete").description("Delete a worklog entry").argument("<key>", "Issue key", issueKey);
|
|
1773
1840
|
subEntityOption(cmd, "worklog", { mandatory: true });
|
|
1774
|
-
cmd.addOption(new Option5("--adjust-estimate <mode>", "How to adjust the remaining estimate").choices(ADJUST_ESTIMATE)).option("--new-estimate <estimate>", 'New remaining estimate; required when --adjust-estimate is "new"').option(
|
|
1841
|
+
cmd.addOption(new Option5("--adjust-estimate <mode>", "How to adjust the remaining estimate").choices(ADJUST_ESTIMATE)).option("--new-estimate <estimate>", 'New remaining estimate; required when --adjust-estimate is "new"', text).option(
|
|
1775
1842
|
"--increase-by <amount>",
|
|
1776
|
-
'Amount to increase the estimate by; required when --adjust-estimate is "manual"'
|
|
1843
|
+
'Amount to increase the estimate by; required when --adjust-estimate is "manual"',
|
|
1844
|
+
text
|
|
1777
1845
|
);
|
|
1778
1846
|
examples(cmd, [
|
|
1779
1847
|
"PROJ-123 --worklog-id 12345",
|
|
@@ -1797,7 +1865,7 @@ function deleteWorklog(parent) {
|
|
|
1797
1865
|
|
|
1798
1866
|
// src/commands/issue/worklog/list.ts
|
|
1799
1867
|
function list4(parent) {
|
|
1800
|
-
const cmd = parent.command("list
|
|
1868
|
+
const cmd = parent.command("list").description("Get worklogs for an issue").argument("<key>", "Issue key", issueKey).option("--start <number>", "Starting index for pagination", nonNegativeInt).option("--limit <number>", "Max results per page (1-1000)", intInRange(1, 1e3), 25);
|
|
1801
1869
|
examples(cmd, ["PROJ-123", "PROJ-123 --limit 10", "PROJ-123 --start 10 --limit 5"]);
|
|
1802
1870
|
cmd.action(async (key, opts) => {
|
|
1803
1871
|
const client = getClient();
|
|
@@ -1814,9 +1882,9 @@ function list4(parent) {
|
|
|
1814
1882
|
import { Option as Option6 } from "commander";
|
|
1815
1883
|
var ADJUST_ESTIMATE2 = ["new", "leave", "auto"];
|
|
1816
1884
|
function update4(parent) {
|
|
1817
|
-
const cmd = parent.command("update
|
|
1885
|
+
const cmd = parent.command("update").description("Update an existing worklog entry").argument("<key>", "Issue key", issueKey);
|
|
1818
1886
|
subEntityOption(cmd, "worklog", { mandatory: true });
|
|
1819
|
-
cmd.option("--time <timeSpent>", "Time spent (e.g., '2h', '30m', '1d 4h')").option("--started <datetime>", "Start time in ISO 8601 format").addOption(new Option6("--adjust-estimate <mode>", "How to adjust the remaining estimate").choices(ADJUST_ESTIMATE2)).option("--new-estimate <estimate>", 'New remaining estimate; required when --adjust-estimate is "new"');
|
|
1887
|
+
cmd.option("--time <timeSpent>", "Time spent (e.g., '2h', '30m', '1d 4h')", text).option("--started <datetime>", "Start time in ISO 8601 format", dateTime).addOption(new Option6("--adjust-estimate <mode>", "How to adjust the remaining estimate").choices(ADJUST_ESTIMATE2)).option("--new-estimate <estimate>", 'New remaining estimate; required when --adjust-estimate is "new"', text);
|
|
1820
1888
|
commentOption(cmd, { description: "Worklog comment" });
|
|
1821
1889
|
examples(cmd, [
|
|
1822
1890
|
'PROJ-123 --worklog-id 12345 --time "1h 30m"',
|
|
@@ -1891,7 +1959,7 @@ function registerIssueCommands(program) {
|
|
|
1891
1959
|
|
|
1892
1960
|
// src/commands/project/list.ts
|
|
1893
1961
|
function list5(parent) {
|
|
1894
|
-
const cmd = parent.command("list").description("List all projects").option("--expand <expand>", 'Expand options (e.g., "description,lead")').option("--include-archived", "Include archived projects (default: false)");
|
|
1962
|
+
const cmd = parent.command("list").description("List all projects").option("--expand <expand>", 'Expand options (e.g., "description,lead")', text).option("--include-archived", "Include archived projects (default: false)");
|
|
1895
1963
|
examples(cmd, ["", "--expand description,lead", "--include-archived"]);
|
|
1896
1964
|
cmd.action(async (opts) => {
|
|
1897
1965
|
const client = getClient();
|
|
@@ -1902,7 +1970,7 @@ function list5(parent) {
|
|
|
1902
1970
|
|
|
1903
1971
|
// src/commands/project/versions.ts
|
|
1904
1972
|
function versions(parent) {
|
|
1905
|
-
const cmd = parent.command("versions
|
|
1973
|
+
const cmd = parent.command("versions").description("Get all versions for a project").argument("<key>", "Project key", text).option("--expand <expand>", "Expand options", text);
|
|
1906
1974
|
examples(cmd, ["PROJ", "PROJ --expand operations"]);
|
|
1907
1975
|
cmd.action(async (key, opts) => {
|
|
1908
1976
|
const client = getClient();
|
|
@@ -1921,7 +1989,7 @@ function registerProjectCommands(program) {
|
|
|
1921
1989
|
|
|
1922
1990
|
// src/commands/sprint/create.ts
|
|
1923
1991
|
function create5(parent) {
|
|
1924
|
-
const cmd = parent.command("create").description("Create a new sprint").requiredOption("--board <id>", "Board ID to create sprint in", positiveInt).requiredOption("--name <name>", "Sprint name").option("--start-date <date>", "Start date in ISO 8601 format").option("--end-date <date>", "End date in ISO 8601 format").option("--goal <goal>", "Sprint goal");
|
|
1992
|
+
const cmd = parent.command("create").description("Create a new sprint").requiredOption("--board <id>", "Board ID to create sprint in", positiveInt).requiredOption("--name <name>", "Sprint name", text).option("--start-date <date>", "Start date in ISO 8601 format", text).option("--end-date <date>", "End date in ISO 8601 format", text).option("--goal <goal>", "Sprint goal", text);
|
|
1925
1993
|
examples(cmd, [
|
|
1926
1994
|
'--board 42 --name "Sprint 10"',
|
|
1927
1995
|
'--board 42 --name "Sprint 10" --start-date 2026-03-20 --end-date 2026-04-03 --goal "Complete auth module"'
|
|
@@ -1954,7 +2022,7 @@ function deleteSprint(parent) {
|
|
|
1954
2022
|
// src/commands/sprint/issues.ts
|
|
1955
2023
|
import { Argument as Argument3 } from "commander";
|
|
1956
2024
|
function issues2(parent) {
|
|
1957
|
-
const cmd = parent.command("issues").description("Get issues in a sprint").addArgument(new Argument3("<id>", "Sprint ID").argParser(positiveInt)).option("--limit <number>", "Max results (1-50, Jira DC caps at 50)", intInRange(1, 50), 25).option("--start <number>", "Starting index for pagination", nonNegativeInt).option("--fields <fields>", "Comma-separated field names to return").option("--jql <jql>", "Additional JQL filter within the sprint");
|
|
2025
|
+
const cmd = parent.command("issues").description("Get issues in a sprint").addArgument(new Argument3("<id>", "Sprint ID").argParser(positiveInt)).option("--limit <number>", "Max results (1-50, Jira DC caps at 50)", intInRange(1, 50), 25).option("--start <number>", "Starting index for pagination", nonNegativeInt).option("--fields <fields>", "Comma-separated field names to return", text).option("--jql <jql>", "Additional JQL filter within the sprint", text);
|
|
1958
2026
|
examples(cmd, [
|
|
1959
2027
|
"100",
|
|
1960
2028
|
"100 --limit 20",
|
|
@@ -1994,7 +2062,7 @@ function list6(parent) {
|
|
|
1994
2062
|
import { Argument as Argument4, Option as Option8 } from "commander";
|
|
1995
2063
|
var SPRINT_STATES2 = ["future", "active", "closed"];
|
|
1996
2064
|
function update5(parent) {
|
|
1997
|
-
const cmd = parent.command("update").description("Update an existing sprint").addArgument(new Argument4("<id>", "Sprint ID").argParser(positiveInt)).option("--name <name>", "New sprint name").addOption(new Option8("--state <state>", "New sprint state").choices(SPRINT_STATES2)).option("--start-date <date>", "New start date in ISO 8601 format").option("--end-date <date>", "New end date in ISO 8601 format").option("--goal <goal>", "New sprint goal");
|
|
2065
|
+
const cmd = parent.command("update").description("Update an existing sprint").addArgument(new Argument4("<id>", "Sprint ID").argParser(positiveInt)).option("--name <name>", "New sprint name", text).addOption(new Option8("--state <state>", "New sprint state").choices(SPRINT_STATES2)).option("--start-date <date>", "New start date in ISO 8601 format", text).option("--end-date <date>", "New end date in ISO 8601 format", text).option("--goal <goal>", "New sprint goal", text);
|
|
1998
2066
|
examples(cmd, [
|
|
1999
2067
|
'100 --name "Sprint 10 - Extended"',
|
|
2000
2068
|
"100 --state active",
|
|
@@ -2052,13 +2120,14 @@ function getTokenClient(options2 = {}) {
|
|
|
2052
2120
|
|
|
2053
2121
|
// src/commands/token/create.ts
|
|
2054
2122
|
function create6(parent) {
|
|
2055
|
-
const cmd = parent.command("create").description("Create a Personal Access Token. The secret is returned exactly once.").requiredOption("--name <name>", "Token name").option(
|
|
2123
|
+
const cmd = parent.command("create").description("Create a Personal Access Token. The secret is returned exactly once.").requiredOption("--name <name>", "Token name", text).option(
|
|
2056
2124
|
"--expiration-duration <days>",
|
|
2057
2125
|
"Token lifetime in days. Omit for a non-expiring token (admin policy permitting).",
|
|
2058
2126
|
positiveInt
|
|
2059
|
-
).option("--basic-username <u>", "Override $JIRA_BASIC_USERNAME").option(
|
|
2127
|
+
).option("--basic-username <u>", "Override $JIRA_BASIC_USERNAME", text).option(
|
|
2060
2128
|
"--basic-password <p>",
|
|
2061
|
-
"Override $JIRA_BASIC_PASSWORD (caution: visible in process table; prefer the env var)"
|
|
2129
|
+
"Override $JIRA_BASIC_PASSWORD (caution: visible in process table; prefer the env var)",
|
|
2130
|
+
text
|
|
2062
2131
|
);
|
|
2063
2132
|
examples(cmd, [["--name my-pat", "non-expiring"], "--name svc-token --expiration-duration 365"]);
|
|
2064
2133
|
cmd.action(async (opts) => {
|
|
@@ -2078,9 +2147,10 @@ function create6(parent) {
|
|
|
2078
2147
|
|
|
2079
2148
|
// src/commands/token/list.ts
|
|
2080
2149
|
function list7(parent) {
|
|
2081
|
-
const cmd = parent.command("list").description("List Personal Access Tokens owned by the authenticated user (secrets not included)").option("--basic-username <u>", "Override $JIRA_BASIC_USERNAME").option(
|
|
2150
|
+
const cmd = parent.command("list").description("List Personal Access Tokens owned by the authenticated user (secrets not included)").option("--basic-username <u>", "Override $JIRA_BASIC_USERNAME", text).option(
|
|
2082
2151
|
"--basic-password <p>",
|
|
2083
|
-
"Override $JIRA_BASIC_PASSWORD (caution: visible in process table; prefer the env var)"
|
|
2152
|
+
"Override $JIRA_BASIC_PASSWORD (caution: visible in process table; prefer the env var)",
|
|
2153
|
+
text
|
|
2084
2154
|
);
|
|
2085
2155
|
examples(cmd, [""]);
|
|
2086
2156
|
cmd.action(async (opts) => {
|
|
@@ -2094,9 +2164,10 @@ function list7(parent) {
|
|
|
2094
2164
|
|
|
2095
2165
|
// src/commands/token/revoke.ts
|
|
2096
2166
|
function revoke(parent) {
|
|
2097
|
-
const cmd = parent.command("revoke").description("Revoke a Personal Access Token by id").option("--basic-username <u>", "Override $JIRA_BASIC_USERNAME").option(
|
|
2167
|
+
const cmd = parent.command("revoke").description("Revoke a Personal Access Token by id").option("--basic-username <u>", "Override $JIRA_BASIC_USERNAME", text).option(
|
|
2098
2168
|
"--basic-password <p>",
|
|
2099
|
-
"Override $JIRA_BASIC_PASSWORD (caution: visible in process table; prefer the env var)"
|
|
2169
|
+
"Override $JIRA_BASIC_PASSWORD (caution: visible in process table; prefer the env var)",
|
|
2170
|
+
text
|
|
2100
2171
|
);
|
|
2101
2172
|
subjectArg(cmd, "tokenId", { parser: positiveInt, description: "Token id to revoke" });
|
|
2102
2173
|
examples(cmd, ["173"]);
|
|
@@ -2125,7 +2196,7 @@ function registerTokenCommands(program) {
|
|
|
2125
2196
|
|
|
2126
2197
|
// src/commands/user/get.ts
|
|
2127
2198
|
function get3(parent) {
|
|
2128
|
-
const cmd = parent.command("get
|
|
2199
|
+
const cmd = parent.command("get").description("Get a user profile by exact username or key").argument("<username>", "Username or user key", text).option("--by-key", "Treat the positional argument as a user key instead of a username");
|
|
2129
2200
|
examples(cmd, ["jsmith", "JIRAUSER10100 --by-key"]);
|
|
2130
2201
|
cmd.action(async (identifier, opts) => {
|
|
2131
2202
|
const client = getClient();
|
|
@@ -2147,7 +2218,7 @@ function me(parent) {
|
|
|
2147
2218
|
|
|
2148
2219
|
// src/commands/user/search.ts
|
|
2149
2220
|
function search3(parent) {
|
|
2150
|
-
const cmd = parent.command("search
|
|
2221
|
+
const cmd = parent.command("search").description("Search users by partial username, display name or email").argument("<query>", "Search query", text).option("--limit <n>", "Maximum results (1-50)", intInRange(1, 50), 25).option("--start <n>", "Starting index (pagination offset)", nonNegativeInt, 0).option("--include-inactive", "Include inactive users in results", false);
|
|
2151
2222
|
examples(cmd, ["Smith", '"John Smith"', "jsmith@example.com --limit 5"]);
|
|
2152
2223
|
cmd.action(async (query, opts) => {
|
|
2153
2224
|
const client = getClient();
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "jiradc-cli",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.26",
|
|
4
4
|
"publish": true,
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/index.js",
|
|
@@ -12,6 +12,7 @@
|
|
|
12
12
|
],
|
|
13
13
|
"dependencies": {
|
|
14
14
|
"commander": "^13.1.0",
|
|
15
|
+
"zod": "^3.25.67",
|
|
15
16
|
"jira-data-center-client": "1.0.39"
|
|
16
17
|
},
|
|
17
18
|
"devDependencies": {
|