jiradc-cli 1.0.44 → 1.0.45
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/README.md
CHANGED
|
@@ -31,27 +31,27 @@ All commands output JSON. Add `--pretty` to pretty-print.
|
|
|
31
31
|
|
|
32
32
|
### issue
|
|
33
33
|
|
|
34
|
-
| Command | Description
|
|
35
|
-
| ------------------------------------- |
|
|
36
|
-
| `jiradc issue get <key>` | One issue, with every dimension hanging off it (see below). `--fields` selects fields by id or name, `--all-fields` returns everything Jira holds, `--expand` adds changelog/names
|
|
37
|
-
| `jiradc issue search <jql>` | Issues matching a JQL query. `--all` collects every match (capped at 1,000); `description` and `comment` are excluded unless asked for via `--fields`
|
|
38
|
-
| `jiradc issue create` | The new issue's key and id. Requires `--project`, `--type`, `--summary`; `--fields <json>` sets anything else
|
|
39
|
-
| `jiradc issue update <key>` | Applies field changes. Shortcuts for `--summary`/`--description`/`--priority`/`--assignee`, list flags for `--labels`/`--components`/`--fix-versions`
|
|
40
|
-
| `jiradc issue delete <key>` | Deletes the issue. `--delete-subtasks` to take its subtasks with it
|
|
41
|
-
| `jiradc issue assign <key>` | Sets the assignee. `--assignee` takes a username, `me`, or `none` to unassign
|
|
42
|
-
| `jiradc issue transition <key>` | Moves the issue
|
|
43
|
-
| `jiradc issue transitions <key>` | The transitions available from the current status, each with the screen fields it requires
|
|
44
|
-
| `jiradc issue createmeta` | The fields a new issue accepts and the values they allow. Requires `--project` and `--type`
|
|
45
|
-
| `jiradc issue editmeta <key>` | The fields this issue's edit screen accepts, with their allowed values
|
|
46
|
-
| `jiradc issue link` | Links two issues. Requires `--from`, `--to` and `--type` (a link type name)
|
|
47
|
-
| `jiradc issue unlink <id>` | Removes one issue link by its link id
|
|
48
|
-
| `jiradc issue link-types` | The link type names this instance accepts, for `issue link --type`
|
|
49
|
-
| `jiradc issue link-epic <keys...>` | Links one or more issues to `--epic <epicKey>`; reports a `failed` array if any link is rejected
|
|
50
|
-
| `jiradc issue changelog <key>` | The issue's change history
|
|
51
|
-
| `jiradc issue batch-changelog <keys>` |
|
|
52
|
-
| `jiradc issue clone <key>` | Creates a duplicate. `--include-links`, `--include-attachments`, `--summary` and `--project` control what carries over
|
|
53
|
-
| `jiradc issue batch-create` | Creates many issues from `--issues <json>` (an array of field objects)
|
|
54
|
-
| `jiradc issue dev-status <key>` | Branches, pull requests, commits and builds linked to the issue. `--detail` for the full records
|
|
34
|
+
| Command | Description |
|
|
35
|
+
| ------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
36
|
+
| `jiradc issue get <key>` | One issue, with every dimension hanging off it (see below). `--fields` selects fields by id or name, `--all-fields` returns everything Jira holds, `--expand` adds changelog/names |
|
|
37
|
+
| `jiradc issue search <jql>` | Issues matching a JQL query. `--all` collects every match (capped at 1,000); `description` and `comment` are excluded unless asked for via `--fields` |
|
|
38
|
+
| `jiradc issue create` | The new issue's key and id. Requires `--project`, `--type`, `--summary`; `--fields <json>` sets anything else |
|
|
39
|
+
| `jiradc issue update <key>` | Applies field changes and reads them back: `fields` holds the touched fields as Jira now has them. Shortcuts for `--summary`/`--description`/`--priority`/`--assignee`, list flags for `--labels`/`--components`/`--fix-versions` |
|
|
40
|
+
| `jiradc issue delete <key>` | Deletes the issue. `--delete-subtasks` to take its subtasks with it |
|
|
41
|
+
| `jiradc issue assign <key>` | Sets the assignee. `--assignee` takes a username, `me`, or `none` to unassign |
|
|
42
|
+
| `jiradc issue transition <key>` | Moves the issue and reads back `status` and `resolution`. `--to` accepts a transition id, name, or target status, each checked against what is available; `--fields` supplies screen fields, `--comment` a note |
|
|
43
|
+
| `jiradc issue transitions <key>` | The transitions available from the current status, each with the screen fields it requires |
|
|
44
|
+
| `jiradc issue createmeta` | The fields a new issue accepts and the values they allow. Requires `--project` and `--type` |
|
|
45
|
+
| `jiradc issue editmeta <key>` | The fields this issue's edit screen accepts, with their allowed values |
|
|
46
|
+
| `jiradc issue link` | Links two issues. Requires `--from`, `--to` and `--type` (a link type name) |
|
|
47
|
+
| `jiradc issue unlink <id>` | Removes one issue link by its link id |
|
|
48
|
+
| `jiradc issue link-types` | The link type names this instance accepts, for `issue link --type` |
|
|
49
|
+
| `jiradc issue link-epic <keys...>` | Links one or more issues to `--epic <epicKey>`; reports a `failed` array if any link is rejected |
|
|
50
|
+
| `jiradc issue changelog <key>` | The issue's whole change history, every entry. `--limit` caps it; `total` always says how many exist |
|
|
51
|
+
| `jiradc issue batch-changelog <keys>` | The same, for several issues at once, from a comma-separated key list |
|
|
52
|
+
| `jiradc issue clone <key>` | Creates a duplicate. `--include-links`, `--include-attachments`, `--summary` and `--project` control what carries over |
|
|
53
|
+
| `jiradc issue batch-create` | Creates many issues from `--issues <json>` (an array of field objects) |
|
|
54
|
+
| `jiradc issue dev-status <key>` | Branches, pull requests, commits and builds linked to the issue. `--detail` for the full records |
|
|
55
55
|
|
|
56
56
|
#### What a bare `issue get` returns
|
|
57
57
|
|
|
@@ -668,6 +668,7 @@ function classifyError(err, opts) {
|
|
|
668
668
|
envelope: {
|
|
669
669
|
error: {
|
|
670
670
|
type: n.type,
|
|
671
|
+
...n.status !== void 0 ? { status: n.status } : {},
|
|
671
672
|
message: n.message,
|
|
672
673
|
recovery: n.recovery,
|
|
673
674
|
retryable: n.retryable,
|
|
@@ -742,9 +743,19 @@ function suggestSubcommand(token, names) {
|
|
|
742
743
|
}
|
|
743
744
|
return best?.name;
|
|
744
745
|
}
|
|
746
|
+
function exitCleanlyOnClosedPipe(stream) {
|
|
747
|
+
stream.on("error", (err) => {
|
|
748
|
+
if (err.code === "EPIPE") {
|
|
749
|
+
process.exit(0);
|
|
750
|
+
return;
|
|
751
|
+
}
|
|
752
|
+
throw err;
|
|
753
|
+
});
|
|
754
|
+
}
|
|
745
755
|
async function runCli(program, opts) {
|
|
746
756
|
routeErrors(program);
|
|
747
757
|
attachSubcommandGuards(program);
|
|
758
|
+
exitCleanlyOnClosedPipe(process.stdout);
|
|
748
759
|
try {
|
|
749
760
|
await program.parseAsync();
|
|
750
761
|
} catch (err) {
|
|
@@ -1126,6 +1137,7 @@ export {
|
|
|
1126
1137
|
createErrorHandler,
|
|
1127
1138
|
routeErrors,
|
|
1128
1139
|
attachSubcommandGuards,
|
|
1140
|
+
exitCleanlyOnClosedPipe,
|
|
1129
1141
|
runCli,
|
|
1130
1142
|
assertConventions,
|
|
1131
1143
|
serializeCommandTree,
|
|
@@ -22,6 +22,7 @@ import {
|
|
|
22
22
|
dateTime,
|
|
23
23
|
enumArg,
|
|
24
24
|
examples,
|
|
25
|
+
exitCleanlyOnClosedPipe,
|
|
25
26
|
fieldsOption,
|
|
26
27
|
finiteNumber,
|
|
27
28
|
formatOption,
|
|
@@ -48,7 +49,7 @@ import {
|
|
|
48
49
|
text,
|
|
49
50
|
textOrFileOption,
|
|
50
51
|
uuid
|
|
51
|
-
} from "./chunk-
|
|
52
|
+
} from "./chunk-KEI7DXAL.js";
|
|
52
53
|
export {
|
|
53
54
|
BANNED_FLAGS,
|
|
54
55
|
CliAuthError,
|
|
@@ -73,6 +74,7 @@ export {
|
|
|
73
74
|
dateTime,
|
|
74
75
|
enumArg,
|
|
75
76
|
examples,
|
|
77
|
+
exitCleanlyOnClosedPipe,
|
|
76
78
|
fieldsOption,
|
|
77
79
|
finiteNumber,
|
|
78
80
|
formatOption,
|
package/dist/index.js
CHANGED
|
@@ -25,7 +25,7 @@ import {
|
|
|
25
25
|
subjectArg,
|
|
26
26
|
text,
|
|
27
27
|
textOrFileOption
|
|
28
|
-
} from "./chunk-
|
|
28
|
+
} from "./chunk-KEI7DXAL.js";
|
|
29
29
|
|
|
30
30
|
// src/program.ts
|
|
31
31
|
import { styleText } from "util";
|
|
@@ -478,6 +478,20 @@ function transformIssueFields(fields, key, opts) {
|
|
|
478
478
|
};
|
|
479
479
|
}
|
|
480
480
|
|
|
481
|
+
// src/utils/transformers/changelog.ts
|
|
482
|
+
function transformEntry(h) {
|
|
483
|
+
return {
|
|
484
|
+
id: h.id,
|
|
485
|
+
...h.author ? { author: transformUser(h.author) } : {},
|
|
486
|
+
created: h.created,
|
|
487
|
+
items: h.items
|
|
488
|
+
};
|
|
489
|
+
}
|
|
490
|
+
function transformChangelog(raw, opts = {}) {
|
|
491
|
+
const histories = opts.limit === void 0 ? raw.histories : raw.histories.slice(0, opts.limit);
|
|
492
|
+
return { total: raw.total, values: histories.map(transformEntry) };
|
|
493
|
+
}
|
|
494
|
+
|
|
481
495
|
// src/utils/transformers/transition.ts
|
|
482
496
|
function slimAllowedValue2(raw) {
|
|
483
497
|
if (!raw || typeof raw !== "object") return {};
|
|
@@ -1077,15 +1091,19 @@ function registerAttachmentCommands(parent) {
|
|
|
1077
1091
|
|
|
1078
1092
|
// src/commands/issue/batch-changelog.ts
|
|
1079
1093
|
function batchChangelog(parent) {
|
|
1080
|
-
const cmd = parent.command("batch-changelog").description("Get
|
|
1094
|
+
const cmd = parent.command("batch-changelog").description("Get the whole change history of several issues at once").argument("<keys>", "Comma-separated issue keys", keyList).option(
|
|
1095
|
+
"--limit <number>",
|
|
1096
|
+
"Return at most this many entries per issue, oldest first (default: every entry)",
|
|
1097
|
+
positiveInt
|
|
1098
|
+
);
|
|
1081
1099
|
examples(cmd, ["PROJ-1,PROJ-2,PROJ-3", "PROJ-123,PROJ-124 --limit 10"]);
|
|
1082
1100
|
cmd.action(async (keys, opts) => {
|
|
1083
1101
|
const client = getClient();
|
|
1084
1102
|
const entries = await Promise.all(
|
|
1085
1103
|
keys.map(async (key) => {
|
|
1086
1104
|
try {
|
|
1087
|
-
const data = await client.issues.getChangelog({ issueKeyOrId: key
|
|
1088
|
-
return [key, data];
|
|
1105
|
+
const data = await client.issues.getChangelog({ issueKeyOrId: key });
|
|
1106
|
+
return [key, transformChangelog(data, { limit: opts.limit })];
|
|
1089
1107
|
} catch (error) {
|
|
1090
1108
|
return [key, { error: error instanceof Error ? error.message : "Unknown error" }];
|
|
1091
1109
|
}
|
|
@@ -1121,12 +1139,12 @@ function batchCreate(parent) {
|
|
|
1121
1139
|
|
|
1122
1140
|
// src/commands/issue/changelog.ts
|
|
1123
1141
|
function changelog(parent) {
|
|
1124
|
-
const cmd = parent.command("changelog").description("Get
|
|
1142
|
+
const cmd = parent.command("changelog").description("Get the whole change history of an issue (several issues at once: batch-changelog)").argument("<key>", "Issue key", issueKey).option("--limit <number>", "Return at most this many entries, oldest first (default: every entry)", positiveInt);
|
|
1125
1143
|
examples(cmd, ["PROJ-123", "PROJ-123 --limit 10"]);
|
|
1126
1144
|
cmd.action(async (key, opts) => {
|
|
1127
1145
|
const client = getClient();
|
|
1128
|
-
const result = await client.issues.getChangelog({ issueKeyOrId: key
|
|
1129
|
-
output(result);
|
|
1146
|
+
const result = await client.issues.getChangelog({ issueKeyOrId: key });
|
|
1147
|
+
output(transformChangelog(result, { limit: opts.limit }));
|
|
1130
1148
|
});
|
|
1131
1149
|
}
|
|
1132
1150
|
|
|
@@ -1753,19 +1771,34 @@ function search2(parent) {
|
|
|
1753
1771
|
|
|
1754
1772
|
// src/commands/issue/transition.ts
|
|
1755
1773
|
import { z as z3 } from "zod";
|
|
1756
|
-
|
|
1774
|
+
|
|
1775
|
+
// src/utils/read-back.ts
|
|
1776
|
+
async function readBack(client, key, fields) {
|
|
1777
|
+
try {
|
|
1778
|
+
const issue = await client.issues.get({ issueKeyOrId: key, fields });
|
|
1779
|
+
return { fields: transformIssue(issue).fields };
|
|
1780
|
+
} catch (err) {
|
|
1781
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
1782
|
+
return {
|
|
1783
|
+
warning: `The write succeeded, but reading ${key} back failed: ${message}. Run jiradc issue get ${key} to see its current state.`
|
|
1784
|
+
};
|
|
1785
|
+
}
|
|
1786
|
+
}
|
|
1787
|
+
|
|
1788
|
+
// src/utils/resolve-transition.ts
|
|
1757
1789
|
function resolveTransitionId(to, transitions2) {
|
|
1790
|
+
const available = transitions2.map((t) => ({ id: t.id, name: t.name, to: t.to }));
|
|
1791
|
+
const recovery = "Re-run --to with one of the listed transitions (by id, name, or target status).";
|
|
1792
|
+
if (/^\d+$/.test(to)) {
|
|
1793
|
+
if (transitions2.some((t) => t.id === to)) return to;
|
|
1794
|
+
throw new CliUsageError(`Transition id ${to} is not available from the current status`, recovery, { available });
|
|
1795
|
+
}
|
|
1758
1796
|
const target = to.toLowerCase();
|
|
1759
1797
|
const byName = transitions2.filter((t) => t.name.toLowerCase() === target);
|
|
1760
1798
|
const matches = byName.length > 0 ? byName : transitions2.filter((t) => t.to.toLowerCase() === target);
|
|
1761
1799
|
if (matches.length === 1) return matches[0].id;
|
|
1762
|
-
const available = transitions2.map((t) => ({ id: t.id, name: t.name, to: t.to }));
|
|
1763
1800
|
if (matches.length === 0) {
|
|
1764
|
-
throw new CliUsageError(
|
|
1765
|
-
`Transition "${to}" not available from current status`,
|
|
1766
|
-
"Re-run --to with one of the listed transitions (by name, id, or target status).",
|
|
1767
|
-
{ available }
|
|
1768
|
-
);
|
|
1801
|
+
throw new CliUsageError(`Transition "${to}" not available from current status`, recovery, { available });
|
|
1769
1802
|
}
|
|
1770
1803
|
const ids = matches.map((t) => t.id).join(", ");
|
|
1771
1804
|
throw new CliUsageError(
|
|
@@ -1774,6 +1807,9 @@ function resolveTransitionId(to, transitions2) {
|
|
|
1774
1807
|
{ available }
|
|
1775
1808
|
);
|
|
1776
1809
|
}
|
|
1810
|
+
|
|
1811
|
+
// src/commands/issue/transition.ts
|
|
1812
|
+
var fieldsSchema2 = z3.record(z3.unknown());
|
|
1777
1813
|
function transition(parent) {
|
|
1778
1814
|
const cmd = parent.command("transition").description("Transition issue to a new status").argument("<key>", "Issue key", issueKey).requiredOption("--to <idOrName>", "Transition ID, transition name, or target status name (case-insensitive)", text).option(
|
|
1779
1815
|
"--fields <json>",
|
|
@@ -1792,18 +1828,11 @@ function transition(parent) {
|
|
|
1792
1828
|
async (key, opts) => {
|
|
1793
1829
|
const comment = resolveTextOrFile(opts, "comment", { required: false });
|
|
1794
1830
|
const client = getClient();
|
|
1795
|
-
|
|
1796
|
-
|
|
1797
|
-
transitionId = opts.to;
|
|
1798
|
-
} else {
|
|
1799
|
-
const raw = await client.issues.getTransitions({
|
|
1800
|
-
issueKeyOrId: key,
|
|
1801
|
-
expand: "transitions.fields"
|
|
1802
|
-
});
|
|
1803
|
-
transitionId = resolveTransitionId(opts.to, transformTransitions(raw));
|
|
1804
|
-
}
|
|
1831
|
+
const raw = await client.issues.getTransitions({ issueKeyOrId: key, expand: "transitions.fields" });
|
|
1832
|
+
const transitionId = resolveTransitionId(opts.to, transformTransitions(raw));
|
|
1805
1833
|
await client.issues.transition({ issueKeyOrId: key, transitionId, fields: opts.fields, comment });
|
|
1806
|
-
|
|
1834
|
+
const after = await readBack(client, key, ["status", "resolution", ...Object.keys(opts.fields ?? {})]);
|
|
1835
|
+
output({ transitioned: true, issue: transformIssueRef(key), ...after });
|
|
1807
1836
|
}
|
|
1808
1837
|
);
|
|
1809
1838
|
}
|
|
@@ -1938,6 +1967,8 @@ function update3(parent) {
|
|
|
1938
1967
|
notifyUsers: opts.notifyUsers
|
|
1939
1968
|
});
|
|
1940
1969
|
}
|
|
1970
|
+
const touched = [.../* @__PURE__ */ new Set([...Object.keys(fields), ...Object.keys(updateOps)])];
|
|
1971
|
+
const after = didFieldUpdate ? await readBack(client, key, touched) : {};
|
|
1941
1972
|
const uploaded = [];
|
|
1942
1973
|
if (opts.attachments) {
|
|
1943
1974
|
const filePaths = opts.attachments.split(",").map((p) => p.trim()).filter(Boolean);
|
|
@@ -1950,8 +1981,9 @@ function update3(parent) {
|
|
|
1950
1981
|
}
|
|
1951
1982
|
output({
|
|
1952
1983
|
...didFieldUpdate && { updated: true },
|
|
1953
|
-
|
|
1954
|
-
|
|
1984
|
+
issue: transformIssueRef(key),
|
|
1985
|
+
...after,
|
|
1986
|
+
...uploaded.length > 0 && { attached: true, attachments: uploaded }
|
|
1955
1987
|
});
|
|
1956
1988
|
});
|
|
1957
1989
|
}
|
|
@@ -2570,7 +2602,7 @@ function list9(parent) {
|
|
|
2570
2602
|
examples(cmd, ["", "--query billing", "--limit 50", "--all --permissions"]);
|
|
2571
2603
|
cmd.action(async (opts) => {
|
|
2572
2604
|
if (opts.all && process.argv.includes("--limit")) {
|
|
2573
|
-
const { CliUsageError: CliUsageError2 } = await import("./dist-
|
|
2605
|
+
const { CliUsageError: CliUsageError2 } = await import("./dist-YSXRGQRB.js");
|
|
2574
2606
|
throw new CliUsageError2("--all and --limit ask for opposite things; pass one or the other");
|
|
2575
2607
|
}
|
|
2576
2608
|
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.45",
|
|
4
4
|
"publish": true,
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/index.js",
|
|
@@ -13,7 +13,7 @@
|
|
|
13
13
|
"dependencies": {
|
|
14
14
|
"commander": "^13.1.0",
|
|
15
15
|
"zod": "^3.25.67",
|
|
16
|
-
"jira-data-center-client": "1.0.
|
|
16
|
+
"jira-data-center-client": "1.0.48"
|
|
17
17
|
},
|
|
18
18
|
"devDependencies": {
|
|
19
19
|
"@types/node": "24.10.4",
|
|
@@ -23,9 +23,9 @@
|
|
|
23
23
|
"tsx": "^4.19.2",
|
|
24
24
|
"typescript": "^5.7.2",
|
|
25
25
|
"vitest": "^4.0.16",
|
|
26
|
-
"config-eslint": "0.0.0",
|
|
27
26
|
"config-typescript": "0.0.0",
|
|
28
|
-
"cli-utils": "1.0.0"
|
|
27
|
+
"cli-utils": "1.0.0",
|
|
28
|
+
"config-eslint": "0.0.0"
|
|
29
29
|
},
|
|
30
30
|
"engines": {
|
|
31
31
|
"node": ">=22.0.0"
|