jiradc-cli 1.0.24 → 1.0.25-g6beae79.4
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 +159 -86
- package/package.json +3 -2
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 (!/^[A-Z][A-Z0-9]+-\d+$/.test(raw)) {
|
|
994
|
+
throw new InvalidArgumentError4("Must be a Jira issue key like PROJ-123.");
|
|
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,32 +1368,40 @@ 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 <
|
|
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"',
|
|
1322
|
-
'--project PROJ --type Story --summary "New feature" --assignee
|
|
1382
|
+
'--project PROJ --type Story --summary "New feature" --assignee me --priority High',
|
|
1323
1383
|
'--project PROJ --type Bug --summary "Urgent" --labels urgent,production --components Backend'
|
|
1324
1384
|
]);
|
|
1325
1385
|
cmd.action(
|
|
1326
1386
|
async (opts) => {
|
|
1327
1387
|
const description = resolveTextOrFile(opts, "description", { required: false });
|
|
1388
|
+
const assignee = opts.assignee !== void 0 ? await resolveUserToken(opts.assignee) : void 0;
|
|
1389
|
+
const reporter = opts.reporter !== void 0 ? await resolveUserToken(opts.reporter) : void 0;
|
|
1328
1390
|
const client = getClient();
|
|
1329
1391
|
const result = await client.issues.create({
|
|
1330
1392
|
projectKeyOrId: opts.project,
|
|
1331
1393
|
issueTypeName: opts.type,
|
|
1332
1394
|
summary: opts.summary,
|
|
1333
1395
|
description,
|
|
1334
|
-
assignee:
|
|
1335
|
-
reporter:
|
|
1396
|
+
assignee: assignee ?? void 0,
|
|
1397
|
+
reporter: reporter ?? void 0,
|
|
1336
1398
|
priority: opts.priority,
|
|
1337
1399
|
labels: opts.labels?.split(",").map((l) => l.trim()),
|
|
1338
1400
|
components: opts.components?.split(",").map((c) => c.trim()),
|
|
1339
1401
|
fixVersions: opts.fixVersions?.split(",").map((v) => v.trim()),
|
|
1340
1402
|
dueDate: opts.dueDate,
|
|
1341
1403
|
parent: opts.parent,
|
|
1342
|
-
customFields: opts.customFields
|
|
1404
|
+
customFields: opts.customFields
|
|
1343
1405
|
});
|
|
1344
1406
|
output(transformCreatedIssue(result));
|
|
1345
1407
|
}
|
|
@@ -1348,7 +1410,7 @@ function create3(parent) {
|
|
|
1348
1410
|
|
|
1349
1411
|
// src/commands/issue/delete.ts
|
|
1350
1412
|
function deleteIssue(parent) {
|
|
1351
|
-
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)");
|
|
1352
1414
|
examples(cmd, ["PROJ-123", "PROJ-123 --delete-subtasks"]);
|
|
1353
1415
|
cmd.action(async (key, opts) => {
|
|
1354
1416
|
const client = getClient();
|
|
@@ -1359,7 +1421,7 @@ function deleteIssue(parent) {
|
|
|
1359
1421
|
|
|
1360
1422
|
// src/commands/issue/dev-status.ts
|
|
1361
1423
|
function devStatus(parent) {
|
|
1362
|
-
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");
|
|
1363
1425
|
examples(cmd, ["PROJ-123", "PROJ-123 --detail"]);
|
|
1364
1426
|
cmd.action(async (key, opts) => {
|
|
1365
1427
|
const client = getClient();
|
|
@@ -1453,7 +1515,7 @@ var DEFAULT_FIELDS = [
|
|
|
1453
1515
|
|
|
1454
1516
|
// src/commands/issue/get.ts
|
|
1455
1517
|
function get2(parent) {
|
|
1456
|
-
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);
|
|
1457
1519
|
examples(cmd, [
|
|
1458
1520
|
"PROJ-123",
|
|
1459
1521
|
"PROJ-123 --fields summary,status,assignee",
|
|
@@ -1474,7 +1536,7 @@ function get2(parent) {
|
|
|
1474
1536
|
|
|
1475
1537
|
// src/commands/issue/link-epic.ts
|
|
1476
1538
|
function linkEpic(parent) {
|
|
1477
|
-
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);
|
|
1478
1540
|
examples(cmd, ["PROJ-456 --epic PROJ-123", "PROJ-456 PROJ-457 PROJ-458 --epic PROJ-123"]);
|
|
1479
1541
|
cmd.action(async (keys, opts) => {
|
|
1480
1542
|
const client = getClient();
|
|
@@ -1517,7 +1579,7 @@ function linkTypes(parent) {
|
|
|
1517
1579
|
|
|
1518
1580
|
// src/commands/issue/link.ts
|
|
1519
1581
|
function link(parent) {
|
|
1520
|
-
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);
|
|
1521
1583
|
commentOption(cmd, { description: "Optional comment" });
|
|
1522
1584
|
examples(cmd, [
|
|
1523
1585
|
"--type Relates --from AI-154 --to AI-149",
|
|
@@ -1543,7 +1605,7 @@ function link(parent) {
|
|
|
1543
1605
|
|
|
1544
1606
|
// src/commands/issue/search.ts
|
|
1545
1607
|
function search2(parent) {
|
|
1546
|
-
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");
|
|
1547
1609
|
examples(cmd, [
|
|
1548
1610
|
'"project = PROJ AND status = Open"',
|
|
1549
1611
|
'"assignee = currentUser()" --limit 10 --fields summary,status',
|
|
@@ -1564,7 +1626,7 @@ function search2(parent) {
|
|
|
1564
1626
|
|
|
1565
1627
|
// src/commands/issue/transition.ts
|
|
1566
1628
|
function transition(parent) {
|
|
1567
|
-
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);
|
|
1568
1630
|
commentOption(cmd, { description: "Comment to add during transition" });
|
|
1569
1631
|
examples(cmd, [
|
|
1570
1632
|
"PROJ-123 --to 31",
|
|
@@ -1602,7 +1664,7 @@ function transition(parent) {
|
|
|
1602
1664
|
|
|
1603
1665
|
// src/commands/issue/transitions.ts
|
|
1604
1666
|
function transitions(parent) {
|
|
1605
|
-
const cmd = parent.command("transitions
|
|
1667
|
+
const cmd = parent.command("transitions").description("Get available transitions for an issue").argument("<key>", "Issue key", issueKey);
|
|
1606
1668
|
examples(cmd, ["PROJ-123"]);
|
|
1607
1669
|
cmd.action(async (key) => {
|
|
1608
1670
|
const client = getClient();
|
|
@@ -1616,30 +1678,33 @@ function transitions(parent) {
|
|
|
1616
1678
|
|
|
1617
1679
|
// src/commands/issue/unlink.ts
|
|
1618
1680
|
function unlink2(parent) {
|
|
1619
|
-
const cmd = parent.command("unlink
|
|
1681
|
+
const cmd = parent.command("unlink").description("Remove a link between two issues").argument("<id>", "Link ID", positiveInt);
|
|
1620
1682
|
examples(cmd, ["12345"]);
|
|
1621
1683
|
cmd.action(async (id) => {
|
|
1622
1684
|
const client = getClient();
|
|
1623
|
-
await client.links.remove({ linkId: id });
|
|
1685
|
+
await client.links.remove({ linkId: String(id) });
|
|
1624
1686
|
output({ removed: true, linkId: id });
|
|
1625
1687
|
});
|
|
1626
1688
|
}
|
|
1627
1689
|
|
|
1690
|
+
// src/commands/issue/update.ts
|
|
1691
|
+
import { z as z3 } from "zod";
|
|
1692
|
+
|
|
1628
1693
|
// src/utils/multi-value.ts
|
|
1629
|
-
import { InvalidArgumentError as
|
|
1694
|
+
import { InvalidArgumentError as InvalidArgumentError5 } from "commander";
|
|
1630
1695
|
function parseMultiValue(flagName, raw) {
|
|
1631
1696
|
const items = raw.split(",").map((s) => s.trim()).filter((s) => s.length > 0);
|
|
1632
1697
|
if (items.length === 0) {
|
|
1633
|
-
throw new
|
|
1698
|
+
throw new InvalidArgumentError5(`${flagName} cannot be empty`);
|
|
1634
1699
|
}
|
|
1635
1700
|
const lonePrefix = items.find((s) => s === "+" || s === "-");
|
|
1636
1701
|
if (lonePrefix !== void 0) {
|
|
1637
|
-
throw new
|
|
1702
|
+
throw new InvalidArgumentError5(`${flagName} has an empty value after '${lonePrefix}' prefix`);
|
|
1638
1703
|
}
|
|
1639
1704
|
const prefixed = items.filter((s) => s.startsWith("+") || s.startsWith("-"));
|
|
1640
1705
|
const bare = items.filter((s) => !s.startsWith("+") && !s.startsWith("-"));
|
|
1641
1706
|
if (prefixed.length > 0 && bare.length > 0) {
|
|
1642
|
-
throw new
|
|
1707
|
+
throw new InvalidArgumentError5(
|
|
1643
1708
|
`${flagName} mixes set and mutate syntax. Either all values have +/- prefix, or none do.`
|
|
1644
1709
|
);
|
|
1645
1710
|
}
|
|
@@ -1652,6 +1717,7 @@ function parseMultiValue(flagName, raw) {
|
|
|
1652
1717
|
}
|
|
1653
1718
|
|
|
1654
1719
|
// src/commands/issue/update.ts
|
|
1720
|
+
var fieldsSchema = z3.record(z3.unknown());
|
|
1655
1721
|
function buildUpdateOps(parsed, wrap) {
|
|
1656
1722
|
if (parsed.mode !== "mutate") return void 0;
|
|
1657
1723
|
return [...parsed.adds.map((v) => ({ add: wrap(v) })), ...parsed.removes.map((v) => ({ remove: wrap(v) }))];
|
|
@@ -1661,7 +1727,11 @@ function buildSetValue(parsed, wrap) {
|
|
|
1661
1727
|
return parsed.values.map(wrap);
|
|
1662
1728
|
}
|
|
1663
1729
|
function update3(parent) {
|
|
1664
|
-
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);
|
|
1665
1735
|
textOrFileOption(cmd, "description", { description: "Set the issue description (wiki markup)" });
|
|
1666
1736
|
examples(cmd, [
|
|
1667
1737
|
'PROJ-123 --summary "New title"',
|
|
@@ -1710,8 +1780,7 @@ function update3(parent) {
|
|
|
1710
1780
|
if (ops) updateOps.fixVersions = ops;
|
|
1711
1781
|
}
|
|
1712
1782
|
if (opts.fields) {
|
|
1713
|
-
|
|
1714
|
-
Object.assign(fields, parsedFields);
|
|
1783
|
+
Object.assign(fields, opts.fields);
|
|
1715
1784
|
}
|
|
1716
1785
|
const client = getClient();
|
|
1717
1786
|
const didFieldUpdate = Object.keys(fields).length > 0 || Object.keys(updateOps).length > 0;
|
|
@@ -1743,7 +1812,7 @@ function update3(parent) {
|
|
|
1743
1812
|
|
|
1744
1813
|
// src/commands/issue/worklog/create.ts
|
|
1745
1814
|
function create4(parent) {
|
|
1746
|
-
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);
|
|
1747
1816
|
commentOption(cmd, { description: "Worklog comment" });
|
|
1748
1817
|
examples(cmd, [
|
|
1749
1818
|
"PROJ-123 --time 2h",
|
|
@@ -1767,11 +1836,12 @@ function create4(parent) {
|
|
|
1767
1836
|
import { Option as Option5 } from "commander";
|
|
1768
1837
|
var ADJUST_ESTIMATE = ["new", "leave", "manual", "auto"];
|
|
1769
1838
|
function deleteWorklog(parent) {
|
|
1770
|
-
const cmd = parent.command("delete
|
|
1839
|
+
const cmd = parent.command("delete").description("Delete a worklog entry").argument("<key>", "Issue key", issueKey);
|
|
1771
1840
|
subEntityOption(cmd, "worklog", { mandatory: true });
|
|
1772
|
-
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(
|
|
1773
1842
|
"--increase-by <amount>",
|
|
1774
|
-
'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
|
|
1775
1845
|
);
|
|
1776
1846
|
examples(cmd, [
|
|
1777
1847
|
"PROJ-123 --worklog-id 12345",
|
|
@@ -1795,7 +1865,7 @@ function deleteWorklog(parent) {
|
|
|
1795
1865
|
|
|
1796
1866
|
// src/commands/issue/worklog/list.ts
|
|
1797
1867
|
function list4(parent) {
|
|
1798
|
-
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);
|
|
1799
1869
|
examples(cmd, ["PROJ-123", "PROJ-123 --limit 10", "PROJ-123 --start 10 --limit 5"]);
|
|
1800
1870
|
cmd.action(async (key, opts) => {
|
|
1801
1871
|
const client = getClient();
|
|
@@ -1812,9 +1882,9 @@ function list4(parent) {
|
|
|
1812
1882
|
import { Option as Option6 } from "commander";
|
|
1813
1883
|
var ADJUST_ESTIMATE2 = ["new", "leave", "auto"];
|
|
1814
1884
|
function update4(parent) {
|
|
1815
|
-
const cmd = parent.command("update
|
|
1885
|
+
const cmd = parent.command("update").description("Update an existing worklog entry").argument("<key>", "Issue key", issueKey);
|
|
1816
1886
|
subEntityOption(cmd, "worklog", { mandatory: true });
|
|
1817
|
-
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);
|
|
1818
1888
|
commentOption(cmd, { description: "Worklog comment" });
|
|
1819
1889
|
examples(cmd, [
|
|
1820
1890
|
'PROJ-123 --worklog-id 12345 --time "1h 30m"',
|
|
@@ -1889,7 +1959,7 @@ function registerIssueCommands(program) {
|
|
|
1889
1959
|
|
|
1890
1960
|
// src/commands/project/list.ts
|
|
1891
1961
|
function list5(parent) {
|
|
1892
|
-
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)");
|
|
1893
1963
|
examples(cmd, ["", "--expand description,lead", "--include-archived"]);
|
|
1894
1964
|
cmd.action(async (opts) => {
|
|
1895
1965
|
const client = getClient();
|
|
@@ -1900,7 +1970,7 @@ function list5(parent) {
|
|
|
1900
1970
|
|
|
1901
1971
|
// src/commands/project/versions.ts
|
|
1902
1972
|
function versions(parent) {
|
|
1903
|
-
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);
|
|
1904
1974
|
examples(cmd, ["PROJ", "PROJ --expand operations"]);
|
|
1905
1975
|
cmd.action(async (key, opts) => {
|
|
1906
1976
|
const client = getClient();
|
|
@@ -1919,7 +1989,7 @@ function registerProjectCommands(program) {
|
|
|
1919
1989
|
|
|
1920
1990
|
// src/commands/sprint/create.ts
|
|
1921
1991
|
function create5(parent) {
|
|
1922
|
-
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);
|
|
1923
1993
|
examples(cmd, [
|
|
1924
1994
|
'--board 42 --name "Sprint 10"',
|
|
1925
1995
|
'--board 42 --name "Sprint 10" --start-date 2026-03-20 --end-date 2026-04-03 --goal "Complete auth module"'
|
|
@@ -1952,7 +2022,7 @@ function deleteSprint(parent) {
|
|
|
1952
2022
|
// src/commands/sprint/issues.ts
|
|
1953
2023
|
import { Argument as Argument3 } from "commander";
|
|
1954
2024
|
function issues2(parent) {
|
|
1955
|
-
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);
|
|
1956
2026
|
examples(cmd, [
|
|
1957
2027
|
"100",
|
|
1958
2028
|
"100 --limit 20",
|
|
@@ -1992,7 +2062,7 @@ function list6(parent) {
|
|
|
1992
2062
|
import { Argument as Argument4, Option as Option8 } from "commander";
|
|
1993
2063
|
var SPRINT_STATES2 = ["future", "active", "closed"];
|
|
1994
2064
|
function update5(parent) {
|
|
1995
|
-
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);
|
|
1996
2066
|
examples(cmd, [
|
|
1997
2067
|
'100 --name "Sprint 10 - Extended"',
|
|
1998
2068
|
"100 --state active",
|
|
@@ -2050,13 +2120,14 @@ function getTokenClient(options2 = {}) {
|
|
|
2050
2120
|
|
|
2051
2121
|
// src/commands/token/create.ts
|
|
2052
2122
|
function create6(parent) {
|
|
2053
|
-
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(
|
|
2054
2124
|
"--expiration-duration <days>",
|
|
2055
2125
|
"Token lifetime in days. Omit for a non-expiring token (admin policy permitting).",
|
|
2056
2126
|
positiveInt
|
|
2057
|
-
).option("--basic-username <u>", "Override $JIRA_BASIC_USERNAME").option(
|
|
2127
|
+
).option("--basic-username <u>", "Override $JIRA_BASIC_USERNAME", text).option(
|
|
2058
2128
|
"--basic-password <p>",
|
|
2059
|
-
"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
|
|
2060
2131
|
);
|
|
2061
2132
|
examples(cmd, [["--name my-pat", "non-expiring"], "--name svc-token --expiration-duration 365"]);
|
|
2062
2133
|
cmd.action(async (opts) => {
|
|
@@ -2076,9 +2147,10 @@ function create6(parent) {
|
|
|
2076
2147
|
|
|
2077
2148
|
// src/commands/token/list.ts
|
|
2078
2149
|
function list7(parent) {
|
|
2079
|
-
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(
|
|
2080
2151
|
"--basic-password <p>",
|
|
2081
|
-
"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
|
|
2082
2154
|
);
|
|
2083
2155
|
examples(cmd, [""]);
|
|
2084
2156
|
cmd.action(async (opts) => {
|
|
@@ -2092,9 +2164,10 @@ function list7(parent) {
|
|
|
2092
2164
|
|
|
2093
2165
|
// src/commands/token/revoke.ts
|
|
2094
2166
|
function revoke(parent) {
|
|
2095
|
-
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(
|
|
2096
2168
|
"--basic-password <p>",
|
|
2097
|
-
"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
|
|
2098
2171
|
);
|
|
2099
2172
|
subjectArg(cmd, "tokenId", { parser: positiveInt, description: "Token id to revoke" });
|
|
2100
2173
|
examples(cmd, ["173"]);
|
|
@@ -2123,7 +2196,7 @@ function registerTokenCommands(program) {
|
|
|
2123
2196
|
|
|
2124
2197
|
// src/commands/user/get.ts
|
|
2125
2198
|
function get3(parent) {
|
|
2126
|
-
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");
|
|
2127
2200
|
examples(cmd, ["jsmith", "JIRAUSER10100 --by-key"]);
|
|
2128
2201
|
cmd.action(async (identifier, opts) => {
|
|
2129
2202
|
const client = getClient();
|
|
@@ -2145,7 +2218,7 @@ function me(parent) {
|
|
|
2145
2218
|
|
|
2146
2219
|
// src/commands/user/search.ts
|
|
2147
2220
|
function search3(parent) {
|
|
2148
|
-
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);
|
|
2149
2222
|
examples(cmd, ["Smith", '"John Smith"', "jsmith@example.com --limit 5"]);
|
|
2150
2223
|
cmd.action(async (query, opts) => {
|
|
2151
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.25-g6beae79.4",
|
|
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": {
|
|
@@ -22,8 +23,8 @@
|
|
|
22
23
|
"tsx": "^4.19.2",
|
|
23
24
|
"typescript": "^5.7.2",
|
|
24
25
|
"vitest": "^4.0.16",
|
|
25
|
-
"cli-utils": "1.0.0",
|
|
26
26
|
"config-eslint": "0.0.0",
|
|
27
|
+
"cli-utils": "1.0.0",
|
|
27
28
|
"config-typescript": "0.0.0"
|
|
28
29
|
},
|
|
29
30
|
"engines": {
|