jiradc-cli 1.0.11 → 1.0.12-g3332dfd.1
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 +423 -86
- package/package.json +4 -4
package/dist/index.js
CHANGED
|
@@ -5,7 +5,7 @@ import { readFileSync } from "fs";
|
|
|
5
5
|
import { dirname, join as join4 } from "path";
|
|
6
6
|
import { fileURLToPath } from "url";
|
|
7
7
|
import { styleText } from "util";
|
|
8
|
-
import { Command as
|
|
8
|
+
import { Command as Command8 } from "commander";
|
|
9
9
|
|
|
10
10
|
// src/commands/board/issues.ts
|
|
11
11
|
import { Argument } from "commander";
|
|
@@ -80,35 +80,13 @@ function getClient() {
|
|
|
80
80
|
return new JiraClient({ baseUrl, token });
|
|
81
81
|
}
|
|
82
82
|
|
|
83
|
-
// src/utils/strip-response.ts
|
|
84
|
-
function stripResponse(obj) {
|
|
85
|
-
if (Array.isArray(obj)) {
|
|
86
|
-
return obj.map(stripResponse);
|
|
87
|
-
}
|
|
88
|
-
if (obj === null || typeof obj !== "object") {
|
|
89
|
-
return obj;
|
|
90
|
-
}
|
|
91
|
-
const record = obj;
|
|
92
|
-
const result = {};
|
|
93
|
-
for (const [key, value] of Object.entries(record)) {
|
|
94
|
-
if (key === "self" || key === "_links" || key === "_expandable" || key === "expand" || key === "avatarUrls" || key === "avatarId" || key === "iconUrl") {
|
|
95
|
-
continue;
|
|
96
|
-
}
|
|
97
|
-
if (value === null || value === void 0) {
|
|
98
|
-
continue;
|
|
99
|
-
}
|
|
100
|
-
result[key] = stripResponse(value);
|
|
101
|
-
}
|
|
102
|
-
return result;
|
|
103
|
-
}
|
|
104
|
-
|
|
105
83
|
// src/utils/output.ts
|
|
106
84
|
var prettyPrint = false;
|
|
107
85
|
function setPretty(value) {
|
|
108
86
|
prettyPrint = value;
|
|
109
87
|
}
|
|
110
88
|
function output(data) {
|
|
111
|
-
process.stdout.write(`${JSON.stringify(
|
|
89
|
+
process.stdout.write(`${JSON.stringify(data, null, prettyPrint ? 2 : void 0)}
|
|
112
90
|
`);
|
|
113
91
|
}
|
|
114
92
|
function handleError(err) {
|
|
@@ -174,6 +152,234 @@ function handleError(err) {
|
|
|
174
152
|
process.exit(1);
|
|
175
153
|
}
|
|
176
154
|
|
|
155
|
+
// src/utils/transformers/base.ts
|
|
156
|
+
function jiraBaseUrl() {
|
|
157
|
+
return (process.env.JIRA_URL ?? "").replace(/\/+$/, "");
|
|
158
|
+
}
|
|
159
|
+
function transformPaged(response, fn) {
|
|
160
|
+
const { startAt, maxResults, total } = response;
|
|
161
|
+
if ("issues" in response) {
|
|
162
|
+
const mapped2 = response.issues.map(fn);
|
|
163
|
+
return { startAt, maxResults, total, isLast: startAt + mapped2.length >= total, issues: mapped2 };
|
|
164
|
+
}
|
|
165
|
+
if ("values" in response) {
|
|
166
|
+
const mapped2 = response.values.map(fn);
|
|
167
|
+
return { startAt, maxResults, total, isLast: startAt + mapped2.length >= total, values: mapped2 };
|
|
168
|
+
}
|
|
169
|
+
const mapped = response.worklogs.map(fn);
|
|
170
|
+
return { startAt, maxResults, total, isLast: startAt + mapped.length >= total, worklogs: mapped };
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
// src/utils/transformers/user.ts
|
|
174
|
+
function transformUser(user) {
|
|
175
|
+
const { self: _self, avatarUrls: _avatarUrls, expand: _expand, ...rest } = user;
|
|
176
|
+
return rest;
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
// src/utils/transformers/field.ts
|
|
180
|
+
function transformField(field) {
|
|
181
|
+
return field;
|
|
182
|
+
}
|
|
183
|
+
function transformCustomFieldOption(option) {
|
|
184
|
+
const { self: _self, ...rest } = option;
|
|
185
|
+
return rest;
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
// src/utils/transformers/project.ts
|
|
189
|
+
function projectBrowseUrl(key) {
|
|
190
|
+
return `${jiraBaseUrl()}/projects/${key}`;
|
|
191
|
+
}
|
|
192
|
+
function transformProject(p) {
|
|
193
|
+
const { self: _self, avatarUrls: _avatarUrls, expand: _expand, lead, ...rest } = p;
|
|
194
|
+
return {
|
|
195
|
+
...rest,
|
|
196
|
+
url: projectBrowseUrl(p.key),
|
|
197
|
+
...lead ? { lead: transformUser(lead) } : {}
|
|
198
|
+
};
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
// src/utils/transformers/component.ts
|
|
202
|
+
function componentBrowseUrl(projectKey) {
|
|
203
|
+
return `${jiraBaseUrl()}/projects/${projectKey}/components`;
|
|
204
|
+
}
|
|
205
|
+
function transformComponent(c) {
|
|
206
|
+
const { self: _self, lead, assignee, realAssignee, ...rest } = c;
|
|
207
|
+
return {
|
|
208
|
+
...rest,
|
|
209
|
+
...c.project ? { url: componentBrowseUrl(c.project) } : {},
|
|
210
|
+
...lead ? { lead: transformUser(lead) } : {},
|
|
211
|
+
...assignee ? { assignee: transformUser(assignee) } : {},
|
|
212
|
+
...realAssignee ? { realAssignee: transformUser(realAssignee) } : {}
|
|
213
|
+
};
|
|
214
|
+
}
|
|
215
|
+
function transformComponentIssueCounts(c) {
|
|
216
|
+
const { self: _self, ...rest } = c;
|
|
217
|
+
return rest;
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
// src/utils/transformers/board.ts
|
|
221
|
+
function boardBrowseUrl(boardId) {
|
|
222
|
+
return `${jiraBaseUrl()}/secure/RapidBoard.jspa?rapidView=${boardId}`;
|
|
223
|
+
}
|
|
224
|
+
function transformBoard(b) {
|
|
225
|
+
const { self: _self, ...rest } = b;
|
|
226
|
+
return { ...rest, url: boardBrowseUrl(b.id) };
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
// src/utils/transformers/sprint.ts
|
|
230
|
+
function sprintBrowseUrl(boardId, sprintId) {
|
|
231
|
+
return `${jiraBaseUrl()}/secure/RapidBoard.jspa?rapidView=${boardId}&view=planning&sprint=${sprintId}`;
|
|
232
|
+
}
|
|
233
|
+
function transformSprint(s) {
|
|
234
|
+
const { self: _self, ...rest } = s;
|
|
235
|
+
return {
|
|
236
|
+
...rest,
|
|
237
|
+
...s.originBoardId !== void 0 ? { url: sprintBrowseUrl(s.originBoardId, s.id) } : {}
|
|
238
|
+
};
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
// src/utils/transformers/issue.ts
|
|
242
|
+
function issueBrowseUrl(key) {
|
|
243
|
+
return `${jiraBaseUrl()}/browse/${key}`;
|
|
244
|
+
}
|
|
245
|
+
function transformIssueRef(key) {
|
|
246
|
+
return { key, url: issueBrowseUrl(key) };
|
|
247
|
+
}
|
|
248
|
+
function transformCreatedIssue(r) {
|
|
249
|
+
return { id: r.id, key: r.key, url: issueBrowseUrl(r.key) };
|
|
250
|
+
}
|
|
251
|
+
function transformIssueType(t) {
|
|
252
|
+
const { self: _self, iconUrl: _iconUrl, avatarId: _avatarId, ...rest } = t;
|
|
253
|
+
return rest;
|
|
254
|
+
}
|
|
255
|
+
function transformStatus(s) {
|
|
256
|
+
const { self: _self, iconUrl: _iconUrl, ...rest } = s;
|
|
257
|
+
return rest;
|
|
258
|
+
}
|
|
259
|
+
function transformPriority(p) {
|
|
260
|
+
const { self: _self, iconUrl: _iconUrl, ...rest } = p;
|
|
261
|
+
return rest;
|
|
262
|
+
}
|
|
263
|
+
function transformResolution(r) {
|
|
264
|
+
const { self: _self, ...rest } = r;
|
|
265
|
+
return rest;
|
|
266
|
+
}
|
|
267
|
+
function transformVersion(v) {
|
|
268
|
+
const { self: _self, ...rest } = v;
|
|
269
|
+
return rest;
|
|
270
|
+
}
|
|
271
|
+
function transformIssueLinkType(t) {
|
|
272
|
+
const { self: _self, ...rest } = t;
|
|
273
|
+
return rest;
|
|
274
|
+
}
|
|
275
|
+
function transformComment(c) {
|
|
276
|
+
const { self: _self, author, updateAuthor, ...rest } = c;
|
|
277
|
+
return {
|
|
278
|
+
...rest,
|
|
279
|
+
...author ? { author: transformUser(author) } : {},
|
|
280
|
+
...updateAuthor ? { updateAuthor: transformUser(updateAuthor) } : {}
|
|
281
|
+
};
|
|
282
|
+
}
|
|
283
|
+
function transformWorklog(w) {
|
|
284
|
+
const { self: _self, author, updateAuthor, ...rest } = w;
|
|
285
|
+
return {
|
|
286
|
+
...rest,
|
|
287
|
+
...author ? { author: transformUser(author) } : {},
|
|
288
|
+
...updateAuthor ? { updateAuthor: transformUser(updateAuthor) } : {}
|
|
289
|
+
};
|
|
290
|
+
}
|
|
291
|
+
function transformAttachment(a) {
|
|
292
|
+
const { self: _self, author, ...rest } = a;
|
|
293
|
+
return {
|
|
294
|
+
...rest,
|
|
295
|
+
...author ? { author: transformUser(author) } : {}
|
|
296
|
+
};
|
|
297
|
+
}
|
|
298
|
+
function transformIssueBasic(b) {
|
|
299
|
+
const { self: _self, fields, ...rest } = b;
|
|
300
|
+
return {
|
|
301
|
+
...rest,
|
|
302
|
+
url: issueBrowseUrl(b.key),
|
|
303
|
+
...fields ? {
|
|
304
|
+
fields: {
|
|
305
|
+
...fields.summary !== void 0 ? { summary: fields.summary } : {},
|
|
306
|
+
...fields.status ? { status: transformStatus(fields.status) } : {},
|
|
307
|
+
...fields.priority ? { priority: transformPriority(fields.priority) } : {},
|
|
308
|
+
...fields.issuetype ? { issuetype: transformIssueType(fields.issuetype) } : {}
|
|
309
|
+
}
|
|
310
|
+
} : {}
|
|
311
|
+
};
|
|
312
|
+
}
|
|
313
|
+
function transformIssueLink(l) {
|
|
314
|
+
const { self: _self, type, inwardIssue, outwardIssue, ...rest } = l;
|
|
315
|
+
return {
|
|
316
|
+
...rest,
|
|
317
|
+
type: transformIssueLinkType(type),
|
|
318
|
+
...inwardIssue ? { inwardIssue: transformIssueBasic(inwardIssue) } : {},
|
|
319
|
+
...outwardIssue ? { outwardIssue: transformIssueBasic(outwardIssue) } : {}
|
|
320
|
+
};
|
|
321
|
+
}
|
|
322
|
+
function transformIssue(issue) {
|
|
323
|
+
const { self: _self, expand: _expand, fields, ...rest } = issue;
|
|
324
|
+
return {
|
|
325
|
+
...rest,
|
|
326
|
+
url: issueBrowseUrl(issue.key),
|
|
327
|
+
fields: transformIssueFields(fields)
|
|
328
|
+
};
|
|
329
|
+
}
|
|
330
|
+
function transformIssueFields(fields) {
|
|
331
|
+
const {
|
|
332
|
+
issuetype,
|
|
333
|
+
status,
|
|
334
|
+
priority,
|
|
335
|
+
resolution,
|
|
336
|
+
assignee,
|
|
337
|
+
reporter,
|
|
338
|
+
creator,
|
|
339
|
+
fixVersions,
|
|
340
|
+
versions: versions2,
|
|
341
|
+
issuelinks,
|
|
342
|
+
subtasks,
|
|
343
|
+
parent,
|
|
344
|
+
comment: comment2,
|
|
345
|
+
worklog: worklog2,
|
|
346
|
+
attachment,
|
|
347
|
+
...rest
|
|
348
|
+
} = fields;
|
|
349
|
+
return {
|
|
350
|
+
...rest,
|
|
351
|
+
issuetype: transformIssueType(issuetype),
|
|
352
|
+
status: transformStatus(status),
|
|
353
|
+
...priority ? { priority: transformPriority(priority) } : {},
|
|
354
|
+
...resolution ? { resolution: transformResolution(resolution) } : {},
|
|
355
|
+
...assignee ? { assignee: transformUser(assignee) } : {},
|
|
356
|
+
...reporter ? { reporter: transformUser(reporter) } : {},
|
|
357
|
+
...creator ? { creator: transformUser(creator) } : {},
|
|
358
|
+
...fixVersions ? { fixVersions: fixVersions.map(transformVersion) } : {},
|
|
359
|
+
...versions2 ? { versions: versions2.map(transformVersion) } : {},
|
|
360
|
+
...issuelinks ? { issuelinks: issuelinks.map(transformIssueLink) } : {},
|
|
361
|
+
...subtasks ? { subtasks: subtasks.map(transformIssueBasic) } : {},
|
|
362
|
+
...parent ? { parent: transformIssueBasic(parent) } : {},
|
|
363
|
+
...comment2 ? {
|
|
364
|
+
comment: {
|
|
365
|
+
comments: comment2.comments.map(transformComment),
|
|
366
|
+
maxResults: comment2.maxResults,
|
|
367
|
+
total: comment2.total,
|
|
368
|
+
startAt: comment2.startAt
|
|
369
|
+
}
|
|
370
|
+
} : {},
|
|
371
|
+
...worklog2 ? {
|
|
372
|
+
worklog: {
|
|
373
|
+
worklogs: worklog2.worklogs.map(transformWorklog),
|
|
374
|
+
maxResults: worklog2.maxResults,
|
|
375
|
+
total: worklog2.total,
|
|
376
|
+
startAt: worklog2.startAt
|
|
377
|
+
}
|
|
378
|
+
} : {},
|
|
379
|
+
...attachment ? { attachment: attachment.map(transformAttachment) } : {}
|
|
380
|
+
};
|
|
381
|
+
}
|
|
382
|
+
|
|
177
383
|
// src/commands/board/issues.ts
|
|
178
384
|
function issues(parent) {
|
|
179
385
|
parent.command("issues").description("Get issues for a board").addArgument(new Argument("<id>", "Board ID").argParser(positiveInt)).option("--max <number>", "Max results (1-50, Jira DC caps at 50)", intInRange(1, 50), 25).option("--start-at <number>", "Starting index for pagination", nonNegativeInt).option("--fields <fields>", "Comma-separated field names to return").option("--jql <jql>", "Additional JQL filter within the board").addHelpText(
|
|
@@ -188,7 +394,7 @@ function issues(parent) {
|
|
|
188
394
|
fields: opts.fields?.split(",").map((f) => f.trim()),
|
|
189
395
|
jql: opts.jql
|
|
190
396
|
});
|
|
191
|
-
output(result);
|
|
397
|
+
output(transformPaged(result, transformIssue));
|
|
192
398
|
});
|
|
193
399
|
}
|
|
194
400
|
|
|
@@ -207,7 +413,7 @@ function list(parent) {
|
|
|
207
413
|
type: opts.type,
|
|
208
414
|
name: opts.name
|
|
209
415
|
});
|
|
210
|
-
output(result);
|
|
416
|
+
output(result.map(transformBoard));
|
|
211
417
|
});
|
|
212
418
|
}
|
|
213
419
|
|
|
@@ -226,6 +432,135 @@ Examples:
|
|
|
226
432
|
issues(board);
|
|
227
433
|
}
|
|
228
434
|
|
|
435
|
+
// src/commands/component/create.ts
|
|
436
|
+
import { Option as Option2 } from "commander";
|
|
437
|
+
var ASSIGNEE_TYPES = [
|
|
438
|
+
"PROJECT_DEFAULT",
|
|
439
|
+
"COMPONENT_LEAD",
|
|
440
|
+
"PROJECT_LEAD",
|
|
441
|
+
"UNASSIGNED"
|
|
442
|
+
];
|
|
443
|
+
function create(parent) {
|
|
444
|
+
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("--description <text>", "Component description").option("--lead <username>", "Username of the component lead").addOption(new Option2("--assignee-type <type>", "Assignee strategy").choices(ASSIGNEE_TYPES)).addHelpText(
|
|
445
|
+
"after",
|
|
446
|
+
`
|
|
447
|
+
Examples:
|
|
448
|
+
jiradc component create --project AI --name Backend
|
|
449
|
+
jiradc component create --project AI --name Frontend --description "UI work" --lead jsmith
|
|
450
|
+
jiradc component create --project AI --name Infra --assignee-type COMPONENT_LEAD --lead jsmith`
|
|
451
|
+
).action(
|
|
452
|
+
async (opts) => {
|
|
453
|
+
const client = getClient();
|
|
454
|
+
const result = await client.components.create({
|
|
455
|
+
project: opts.project,
|
|
456
|
+
name: opts.name,
|
|
457
|
+
description: opts.description,
|
|
458
|
+
leadUserName: opts.lead,
|
|
459
|
+
assigneeType: opts.assigneeType
|
|
460
|
+
});
|
|
461
|
+
output(transformComponent(result));
|
|
462
|
+
}
|
|
463
|
+
);
|
|
464
|
+
}
|
|
465
|
+
|
|
466
|
+
// src/commands/component/delete.ts
|
|
467
|
+
function deleteComponent(parent) {
|
|
468
|
+
parent.command("delete <id>").description("Delete a component, optionally reassigning its issues to another component").option("--move-issues-to <id>", "Reassign existing issues to this component ID before deletion").addHelpText(
|
|
469
|
+
"after",
|
|
470
|
+
`
|
|
471
|
+
Examples:
|
|
472
|
+
jiradc component delete 11289
|
|
473
|
+
jiradc component delete 11289 --move-issues-to 11290`
|
|
474
|
+
).action(async (id, opts) => {
|
|
475
|
+
const client = getClient();
|
|
476
|
+
await client.components.delete({ id, moveIssuesTo: opts.moveIssuesTo });
|
|
477
|
+
output({ deleted: true, componentId: id, ...opts.moveIssuesTo && { movedIssuesTo: opts.moveIssuesTo } });
|
|
478
|
+
});
|
|
479
|
+
}
|
|
480
|
+
|
|
481
|
+
// src/commands/component/get.ts
|
|
482
|
+
function get(parent) {
|
|
483
|
+
parent.command("get <id>").description("Get a component by ID").addHelpText("after", "\nExamples:\n jiradc component get 11289").action(async (id) => {
|
|
484
|
+
const client = getClient();
|
|
485
|
+
const result = await client.components.get({ id });
|
|
486
|
+
output(transformComponent(result));
|
|
487
|
+
});
|
|
488
|
+
}
|
|
489
|
+
|
|
490
|
+
// src/commands/component/issue-count.ts
|
|
491
|
+
function issueCount(parent) {
|
|
492
|
+
parent.command("issue-count <id>").description("Get the number of issues currently using this component").addHelpText("after", "\nExamples:\n jiradc component issue-count 11289").action(async (id) => {
|
|
493
|
+
const client = getClient();
|
|
494
|
+
const result = await client.components.getRelatedIssueCounts({ id });
|
|
495
|
+
output(transformComponentIssueCounts(result));
|
|
496
|
+
});
|
|
497
|
+
}
|
|
498
|
+
|
|
499
|
+
// src/commands/component/list.ts
|
|
500
|
+
function list2(parent) {
|
|
501
|
+
parent.command("list <projectKey>").description("List all components for a project").addHelpText("after", "\nExamples:\n jiradc component list AI").action(async (projectKey) => {
|
|
502
|
+
const client = getClient();
|
|
503
|
+
const result = await client.components.list({ projectKeyOrId: projectKey });
|
|
504
|
+
output(result.map(transformComponent));
|
|
505
|
+
});
|
|
506
|
+
}
|
|
507
|
+
|
|
508
|
+
// src/commands/component/update.ts
|
|
509
|
+
import { Option as Option3 } from "commander";
|
|
510
|
+
var ASSIGNEE_TYPES2 = [
|
|
511
|
+
"PROJECT_DEFAULT",
|
|
512
|
+
"COMPONENT_LEAD",
|
|
513
|
+
"PROJECT_LEAD",
|
|
514
|
+
"UNASSIGNED"
|
|
515
|
+
];
|
|
516
|
+
function update(parent) {
|
|
517
|
+
parent.command("update <id>").description("Update an existing component (only provided fields are changed)").option("--name <name>", "New component name").option("--description <text>", "New component description").option("--lead <username>", "Username of the component lead (empty string clears it)").addOption(new Option3("--assignee-type <type>", "New assignee strategy").choices(ASSIGNEE_TYPES2)).addHelpText(
|
|
518
|
+
"after",
|
|
519
|
+
`
|
|
520
|
+
Examples:
|
|
521
|
+
jiradc component update 11289 --name Backend
|
|
522
|
+
jiradc component update 11289 --description "Server-side code"
|
|
523
|
+
jiradc component update 11289 --lead jsmith --assignee-type COMPONENT_LEAD`
|
|
524
|
+
).action(
|
|
525
|
+
async (id, opts) => {
|
|
526
|
+
if (opts.name === void 0 && opts.description === void 0 && opts.lead === void 0 && opts.assigneeType === void 0) {
|
|
527
|
+
throw new Error("Provide at least one of --name, --description, --lead, --assignee-type");
|
|
528
|
+
}
|
|
529
|
+
const client = getClient();
|
|
530
|
+
const result = await client.components.update({
|
|
531
|
+
id,
|
|
532
|
+
name: opts.name,
|
|
533
|
+
description: opts.description,
|
|
534
|
+
leadUserName: opts.lead,
|
|
535
|
+
assigneeType: opts.assigneeType
|
|
536
|
+
});
|
|
537
|
+
output(transformComponent(result));
|
|
538
|
+
}
|
|
539
|
+
);
|
|
540
|
+
}
|
|
541
|
+
|
|
542
|
+
// src/commands/component/index.ts
|
|
543
|
+
function registerComponentCommands(program2) {
|
|
544
|
+
const component = program2.command("component").description("Project component operations").addHelpText(
|
|
545
|
+
"after",
|
|
546
|
+
`
|
|
547
|
+
Examples:
|
|
548
|
+
$ jiradc component list AI
|
|
549
|
+
$ jiradc component get 11289
|
|
550
|
+
$ jiradc component create --project AI --name Backend
|
|
551
|
+
$ jiradc component update 11289 --name Backend
|
|
552
|
+
$ jiradc component delete 11289 --move-issues-to 11290
|
|
553
|
+
$ jiradc component issue-count 11289
|
|
554
|
+
`
|
|
555
|
+
);
|
|
556
|
+
list2(component);
|
|
557
|
+
get(component);
|
|
558
|
+
create(component);
|
|
559
|
+
update(component);
|
|
560
|
+
deleteComponent(component);
|
|
561
|
+
issueCount(component);
|
|
562
|
+
}
|
|
563
|
+
|
|
229
564
|
// src/commands/field/options.ts
|
|
230
565
|
function options(parent) {
|
|
231
566
|
parent.command("options <id>").description("Get available options for a custom field").option("--query <text>", "Filter options by text").option("--max <number>", "Max results to return (1-1000)", intInRange(1, 1e3), 25).option("--page <number>", "Page number (1-indexed)", positiveInt).addHelpText(
|
|
@@ -239,7 +574,7 @@ function options(parent) {
|
|
|
239
574
|
maxResults: opts.max,
|
|
240
575
|
page: opts.page
|
|
241
576
|
});
|
|
242
|
-
output(result);
|
|
577
|
+
output(transformPaged({ ...result, startAt: result.startAt ?? 0 }, transformCustomFieldOption));
|
|
243
578
|
});
|
|
244
579
|
}
|
|
245
580
|
|
|
@@ -251,7 +586,7 @@ function search(parent) {
|
|
|
251
586
|
).action(async (keyword, opts) => {
|
|
252
587
|
const client = getClient();
|
|
253
588
|
const result = await client.fields.search(keyword, opts.limit);
|
|
254
|
-
output(result);
|
|
589
|
+
output(result.map(transformField));
|
|
255
590
|
});
|
|
256
591
|
}
|
|
257
592
|
|
|
@@ -343,7 +678,7 @@ function download(parent) {
|
|
|
343
678
|
}
|
|
344
679
|
|
|
345
680
|
// src/commands/issue/attachment/list.ts
|
|
346
|
-
function
|
|
681
|
+
function list3(parent) {
|
|
347
682
|
parent.command("list <key>").description("List attachments on an issue").addHelpText("after", "\nExamples:\n jiradc issue attachment list PROJ-123").action(async (key) => {
|
|
348
683
|
const client = getClient();
|
|
349
684
|
const issue = await client.issues.get({
|
|
@@ -406,7 +741,7 @@ Examples:
|
|
|
406
741
|
`
|
|
407
742
|
);
|
|
408
743
|
upload(attachment);
|
|
409
|
-
|
|
744
|
+
list3(attachment);
|
|
410
745
|
download(attachment);
|
|
411
746
|
downloadAll(attachment);
|
|
412
747
|
deleteAttachment(attachment);
|
|
@@ -489,7 +824,7 @@ Examples:
|
|
|
489
824
|
for (const issue of parsed) {
|
|
490
825
|
try {
|
|
491
826
|
const result = await client.issues.create(issue);
|
|
492
|
-
results.push(
|
|
827
|
+
results.push(transformCreatedIssue(result));
|
|
493
828
|
} catch (error) {
|
|
494
829
|
results.push({ error: error instanceof Error ? error.message : "Unknown error" });
|
|
495
830
|
}
|
|
@@ -550,12 +885,12 @@ Examples:
|
|
|
550
885
|
dueDate: f.duedate ?? void 0,
|
|
551
886
|
assignee: opts.assignee ?? f.assignee?.name
|
|
552
887
|
};
|
|
553
|
-
const
|
|
554
|
-
const newKey =
|
|
888
|
+
const created = transformCreatedIssue(await client.issues.create(createParams));
|
|
889
|
+
const newKey = created.key;
|
|
555
890
|
const cloneResult = {
|
|
556
891
|
cloned: true,
|
|
557
892
|
source: key,
|
|
558
|
-
newIssue:
|
|
893
|
+
newIssue: created
|
|
559
894
|
};
|
|
560
895
|
if (opts.includeAttachments && f.attachment?.length) {
|
|
561
896
|
const tmpFiles = [];
|
|
@@ -592,9 +927,9 @@ Examples:
|
|
|
592
927
|
return Promise.resolve();
|
|
593
928
|
})
|
|
594
929
|
);
|
|
595
|
-
const
|
|
930
|
+
const created2 = outcomes.filter((o) => o.status === "fulfilled").length;
|
|
596
931
|
const skipped = outcomes.filter((o) => o.status === "rejected").length;
|
|
597
|
-
cloneResult.linksCopied =
|
|
932
|
+
cloneResult.linksCopied = created2;
|
|
598
933
|
if (skipped > 0) cloneResult.linksSkipped = skipped;
|
|
599
934
|
}
|
|
600
935
|
output(cloneResult);
|
|
@@ -607,7 +942,7 @@ function commentEdit(parent) {
|
|
|
607
942
|
parent.command("comment-edit <key>").description("Edit an existing comment").requiredOption("--id <commentId>", "Comment ID to edit").requiredOption("--body <text>", "Updated comment body in wiki markup").addHelpText("after", '\nExamples:\n jiradc issue comment-edit PROJ-123 --id 12345 --body "Updated comment text"').action(async (key, opts) => {
|
|
608
943
|
const client = getClient();
|
|
609
944
|
const result = await client.issues.editComment({ issueKeyOrId: key, commentId: opts.id, body: opts.body });
|
|
610
|
-
output(result);
|
|
945
|
+
output(transformComment(result));
|
|
611
946
|
});
|
|
612
947
|
}
|
|
613
948
|
|
|
@@ -616,12 +951,12 @@ function comment(parent) {
|
|
|
616
951
|
parent.command("comment <key>").description("Add a comment to an issue").requiredOption("--body <text>", "Comment body in wiki markup").addHelpText("after", '\nExamples:\n jiradc issue comment PROJ-123 --body "Fixed in latest build"').action(async (key, opts) => {
|
|
617
952
|
const client = getClient();
|
|
618
953
|
const result = await client.issues.addComment({ issueKeyOrId: key, body: opts.body });
|
|
619
|
-
output(result);
|
|
954
|
+
output(transformComment(result));
|
|
620
955
|
});
|
|
621
956
|
}
|
|
622
957
|
|
|
623
958
|
// src/commands/issue/create.ts
|
|
624
|
-
function
|
|
959
|
+
function create2(parent) {
|
|
625
960
|
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("--description <text>", "Issue description in wiki markup").option("--assignee <username>", "Assignee username").option("--reporter <username>", "Reporter username").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("--custom-fields <json>", `Additional custom fields as JSON (e.g., '{"customfield_10100": "EPIC-1"}')`).addHelpText(
|
|
626
961
|
"after",
|
|
627
962
|
`
|
|
@@ -648,7 +983,7 @@ Examples:
|
|
|
648
983
|
parent: opts.parent,
|
|
649
984
|
customFields: opts.customFields ? JSON.parse(opts.customFields) : void 0
|
|
650
985
|
});
|
|
651
|
-
output(result);
|
|
986
|
+
output(transformCreatedIssue(result));
|
|
652
987
|
}
|
|
653
988
|
);
|
|
654
989
|
}
|
|
@@ -756,7 +1091,7 @@ function getWorklog(parent) {
|
|
|
756
1091
|
startAt: opts.startAt,
|
|
757
1092
|
maxResults: opts.max
|
|
758
1093
|
});
|
|
759
|
-
output(result);
|
|
1094
|
+
output(transformPaged(result, transformWorklog));
|
|
760
1095
|
});
|
|
761
1096
|
}
|
|
762
1097
|
|
|
@@ -777,7 +1112,7 @@ var DEFAULT_FIELDS = [
|
|
|
777
1112
|
];
|
|
778
1113
|
|
|
779
1114
|
// src/commands/issue/get.ts
|
|
780
|
-
function
|
|
1115
|
+
function get2(parent) {
|
|
781
1116
|
parent.command("get <key>").description("Get issue details").option("--fields <fields>", "Comma-separated fields to return (defaults to essential fields)").option("--all-fields", "Return all fields instead of defaults").option("--expand <expand>", 'Expand options (e.g., "transitions", "changelog")').addHelpText(
|
|
782
1117
|
"after",
|
|
783
1118
|
"\nExamples:\n jiradc issue get PROJ-123\n jiradc issue get PROJ-123 --fields summary,status,assignee\n jiradc issue get PROJ-123 --all-fields\n jiradc issue get PROJ-123 --expand changelog,transitions"
|
|
@@ -789,7 +1124,7 @@ function get(parent) {
|
|
|
789
1124
|
fields,
|
|
790
1125
|
expand: opts.expand
|
|
791
1126
|
});
|
|
792
|
-
output(result);
|
|
1127
|
+
output(transformIssue(result));
|
|
793
1128
|
});
|
|
794
1129
|
}
|
|
795
1130
|
|
|
@@ -801,7 +1136,11 @@ function linkEpic(parent) {
|
|
|
801
1136
|
issueKeyOrId: key,
|
|
802
1137
|
fields: { customfield_10100: opts.epic }
|
|
803
1138
|
});
|
|
804
|
-
output({
|
|
1139
|
+
output({
|
|
1140
|
+
linked: true,
|
|
1141
|
+
issue: transformIssueRef(key),
|
|
1142
|
+
epic: transformIssueRef(opts.epic)
|
|
1143
|
+
});
|
|
805
1144
|
});
|
|
806
1145
|
}
|
|
807
1146
|
|
|
@@ -810,7 +1149,7 @@ function linkTypes(parent) {
|
|
|
810
1149
|
parent.command("link-types").description("List all issue link types").addHelpText("after", "\nExamples:\n jiradc issue link-types").action(async () => {
|
|
811
1150
|
const client = getClient();
|
|
812
1151
|
const result = await client.links.getTypes();
|
|
813
|
-
output(result);
|
|
1152
|
+
output(result.map(transformIssueLinkType));
|
|
814
1153
|
});
|
|
815
1154
|
}
|
|
816
1155
|
|
|
@@ -827,7 +1166,12 @@ function link(parent) {
|
|
|
827
1166
|
outwardIssueKey: opts.to,
|
|
828
1167
|
comment: opts.comment
|
|
829
1168
|
});
|
|
830
|
-
output({
|
|
1169
|
+
output({
|
|
1170
|
+
created: true,
|
|
1171
|
+
type: opts.type,
|
|
1172
|
+
inward: transformIssueRef(opts.from),
|
|
1173
|
+
outward: transformIssueRef(opts.to)
|
|
1174
|
+
});
|
|
831
1175
|
});
|
|
832
1176
|
}
|
|
833
1177
|
|
|
@@ -845,7 +1189,7 @@ function search2(parent) {
|
|
|
845
1189
|
maxResults: opts.max,
|
|
846
1190
|
fields
|
|
847
1191
|
});
|
|
848
|
-
output(result);
|
|
1192
|
+
output(transformPaged(result, transformIssue));
|
|
849
1193
|
});
|
|
850
1194
|
}
|
|
851
1195
|
|
|
@@ -857,7 +1201,7 @@ function transition(parent) {
|
|
|
857
1201
|
).action(async (key, opts) => {
|
|
858
1202
|
const client = getClient();
|
|
859
1203
|
await client.issues.transition({ issueKeyOrId: key, transitionId: opts.to, comment: opts.comment });
|
|
860
|
-
output({ transitioned: true,
|
|
1204
|
+
output({ transitioned: true, issue: transformIssueRef(key) });
|
|
861
1205
|
});
|
|
862
1206
|
}
|
|
863
1207
|
|
|
@@ -880,7 +1224,7 @@ function unlink2(parent) {
|
|
|
880
1224
|
}
|
|
881
1225
|
|
|
882
1226
|
// src/commands/issue/update.ts
|
|
883
|
-
function
|
|
1227
|
+
function update2(parent) {
|
|
884
1228
|
parent.command("update <key>").description("Update issue fields").option("--fields <json>", "JSON string of fields to update").option("--notify-users", "Notify users about the update (default: true)").option("--attachments <paths>", "Comma-separated local file paths to attach").addHelpText(
|
|
885
1229
|
"after",
|
|
886
1230
|
`
|
|
@@ -891,8 +1235,7 @@ Examples:
|
|
|
891
1235
|
jiradc issue update PROJ-123 --fields '{"summary": "With attachment"}' --attachments ./report.pdf`
|
|
892
1236
|
).action(async (key, opts) => {
|
|
893
1237
|
if (!opts.fields && !opts.attachments) {
|
|
894
|
-
|
|
895
|
-
process.exit(1);
|
|
1238
|
+
throw new Error("Provide --fields and/or --attachments");
|
|
896
1239
|
}
|
|
897
1240
|
const client = getClient();
|
|
898
1241
|
if (opts.fields) {
|
|
@@ -909,7 +1252,11 @@ Examples:
|
|
|
909
1252
|
}
|
|
910
1253
|
}
|
|
911
1254
|
}
|
|
912
|
-
output({
|
|
1255
|
+
output({
|
|
1256
|
+
updated: true,
|
|
1257
|
+
issue: transformIssueRef(key),
|
|
1258
|
+
...uploaded.length > 0 && { attachments: uploaded }
|
|
1259
|
+
});
|
|
913
1260
|
});
|
|
914
1261
|
}
|
|
915
1262
|
|
|
@@ -926,7 +1273,7 @@ function worklog(parent) {
|
|
|
926
1273
|
comment: opts.comment,
|
|
927
1274
|
started: opts.started
|
|
928
1275
|
});
|
|
929
|
-
output(result);
|
|
1276
|
+
output(transformWorklog(result));
|
|
930
1277
|
});
|
|
931
1278
|
}
|
|
932
1279
|
|
|
@@ -944,10 +1291,10 @@ Examples:
|
|
|
944
1291
|
$ jiradc issue attachment list PROJ-123
|
|
945
1292
|
`
|
|
946
1293
|
);
|
|
947
|
-
|
|
1294
|
+
get2(issue);
|
|
948
1295
|
search2(issue);
|
|
949
|
-
|
|
950
|
-
|
|
1296
|
+
create2(issue);
|
|
1297
|
+
update2(issue);
|
|
951
1298
|
deleteIssue(issue);
|
|
952
1299
|
transition(issue);
|
|
953
1300
|
transitions(issue);
|
|
@@ -968,24 +1315,15 @@ Examples:
|
|
|
968
1315
|
devStatus(issue);
|
|
969
1316
|
}
|
|
970
1317
|
|
|
971
|
-
// src/commands/project/components.ts
|
|
972
|
-
function components(parent) {
|
|
973
|
-
parent.command("components <key>").description("Get all components for a project").addHelpText("after", "\nExamples:\n jiradc project components PROJ").action(async (key) => {
|
|
974
|
-
const client = getClient();
|
|
975
|
-
const result = await client.projects.getComponents({ projectKeyOrId: key });
|
|
976
|
-
output(result);
|
|
977
|
-
});
|
|
978
|
-
}
|
|
979
|
-
|
|
980
1318
|
// src/commands/project/list.ts
|
|
981
|
-
function
|
|
1319
|
+
function list4(parent) {
|
|
982
1320
|
parent.command("list").description("List all projects").option("--expand <expand>", 'Expand options (e.g., "description,lead")').option("--include-archived", "Include archived projects (default: false)").addHelpText(
|
|
983
1321
|
"after",
|
|
984
1322
|
"\nExamples:\n jiradc project list\n jiradc project list --expand description,lead\n jiradc project list --include-archived"
|
|
985
1323
|
).action(async (opts) => {
|
|
986
1324
|
const client = getClient();
|
|
987
1325
|
const result = await client.projects.getAll({ expand: opts.expand, includeArchived: opts.includeArchived });
|
|
988
|
-
output(result);
|
|
1326
|
+
output(result.map(transformProject));
|
|
989
1327
|
});
|
|
990
1328
|
}
|
|
991
1329
|
|
|
@@ -997,7 +1335,7 @@ function versions(parent) {
|
|
|
997
1335
|
).action(async (key, opts) => {
|
|
998
1336
|
const client = getClient();
|
|
999
1337
|
const result = await client.projects.getVersions({ projectKeyOrId: key, expand: opts.expand });
|
|
1000
|
-
output(result);
|
|
1338
|
+
output(result.map(transformVersion));
|
|
1001
1339
|
});
|
|
1002
1340
|
}
|
|
1003
1341
|
|
|
@@ -1009,16 +1347,14 @@ function registerProjectCommands(program2) {
|
|
|
1009
1347
|
Examples:
|
|
1010
1348
|
$ jiradc project list
|
|
1011
1349
|
$ jiradc project versions PROJ
|
|
1012
|
-
$ jiradc project components PROJ
|
|
1013
1350
|
`
|
|
1014
1351
|
);
|
|
1015
|
-
|
|
1352
|
+
list4(project);
|
|
1016
1353
|
versions(project);
|
|
1017
|
-
components(project);
|
|
1018
1354
|
}
|
|
1019
1355
|
|
|
1020
1356
|
// src/commands/sprint/create.ts
|
|
1021
|
-
function
|
|
1357
|
+
function create3(parent) {
|
|
1022
1358
|
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").addHelpText(
|
|
1023
1359
|
"after",
|
|
1024
1360
|
'\nExamples:\n jiradc sprint create --board 42 --name "Sprint 10"\n jiradc sprint create --board 42 --name "Sprint 10" --start-date 2026-03-20 --end-date 2026-04-03 --goal "Complete auth module"'
|
|
@@ -1031,7 +1367,7 @@ function create2(parent) {
|
|
|
1031
1367
|
endDate: opts.endDate,
|
|
1032
1368
|
goal: opts.goal
|
|
1033
1369
|
});
|
|
1034
|
-
output(result);
|
|
1370
|
+
output(transformSprint(result));
|
|
1035
1371
|
});
|
|
1036
1372
|
}
|
|
1037
1373
|
|
|
@@ -1050,15 +1386,15 @@ function issues2(parent) {
|
|
|
1050
1386
|
fields: opts.fields?.split(",").map((f) => f.trim()),
|
|
1051
1387
|
jql: opts.jql
|
|
1052
1388
|
});
|
|
1053
|
-
output(result);
|
|
1389
|
+
output(transformPaged(result, transformIssue));
|
|
1054
1390
|
});
|
|
1055
1391
|
}
|
|
1056
1392
|
|
|
1057
1393
|
// src/commands/sprint/list.ts
|
|
1058
|
-
import { Option as
|
|
1394
|
+
import { Option as Option4 } from "commander";
|
|
1059
1395
|
var SPRINT_STATES = ["future", "active", "closed"];
|
|
1060
|
-
function
|
|
1061
|
-
parent.command("list").description("List sprints for a board").requiredOption("--board <id>", "Board ID", positiveInt).addOption(new
|
|
1396
|
+
function list5(parent) {
|
|
1397
|
+
parent.command("list").description("List sprints for a board").requiredOption("--board <id>", "Board ID", positiveInt).addOption(new Option4("--state <state>", "Filter by sprint state").choices(SPRINT_STATES)).addHelpText(
|
|
1062
1398
|
"after",
|
|
1063
1399
|
"\nExamples:\n jiradc sprint list --board 42\n jiradc sprint list --board 42 --state active"
|
|
1064
1400
|
).action(async (opts) => {
|
|
@@ -1067,15 +1403,15 @@ function list4(parent) {
|
|
|
1067
1403
|
boardId: opts.board,
|
|
1068
1404
|
state: opts.state
|
|
1069
1405
|
});
|
|
1070
|
-
output(result);
|
|
1406
|
+
output(result.map(transformSprint));
|
|
1071
1407
|
});
|
|
1072
1408
|
}
|
|
1073
1409
|
|
|
1074
1410
|
// src/commands/sprint/update.ts
|
|
1075
|
-
import { Argument as Argument3, Option as
|
|
1411
|
+
import { Argument as Argument3, Option as Option5 } from "commander";
|
|
1076
1412
|
var SPRINT_STATES2 = ["future", "active", "closed"];
|
|
1077
|
-
function
|
|
1078
|
-
parent.command("update").description("Update an existing sprint").addArgument(new Argument3("<id>", "Sprint ID").argParser(positiveInt)).option("--name <name>", "New sprint name").addOption(new
|
|
1413
|
+
function update3(parent) {
|
|
1414
|
+
parent.command("update").description("Update an existing sprint").addArgument(new Argument3("<id>", "Sprint ID").argParser(positiveInt)).option("--name <name>", "New sprint name").addOption(new Option5("--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").addHelpText(
|
|
1079
1415
|
"after",
|
|
1080
1416
|
'\nExamples:\n jiradc sprint update 100 --name "Sprint 10 - Extended"\n jiradc sprint update 100 --state active\n jiradc sprint update 100 --end-date 2026-04-10 --goal "Updated goal"'
|
|
1081
1417
|
).action(
|
|
@@ -1089,7 +1425,7 @@ function update2(parent) {
|
|
|
1089
1425
|
endDate: opts.endDate,
|
|
1090
1426
|
goal: opts.goal
|
|
1091
1427
|
});
|
|
1092
|
-
output(result);
|
|
1428
|
+
output(transformSprint(result));
|
|
1093
1429
|
}
|
|
1094
1430
|
);
|
|
1095
1431
|
}
|
|
@@ -1106,10 +1442,10 @@ Examples:
|
|
|
1106
1442
|
$ jiradc sprint create --board 42 --name "Sprint 10" --start-date 2026-04-01 --end-date 2026-04-14
|
|
1107
1443
|
`
|
|
1108
1444
|
);
|
|
1109
|
-
|
|
1445
|
+
list5(sprint);
|
|
1110
1446
|
issues2(sprint);
|
|
1111
|
-
|
|
1112
|
-
|
|
1447
|
+
create3(sprint);
|
|
1448
|
+
update3(sprint);
|
|
1113
1449
|
}
|
|
1114
1450
|
|
|
1115
1451
|
// src/commands/user/me.ts
|
|
@@ -1147,7 +1483,7 @@ function readPackageVersion() {
|
|
|
1147
1483
|
}
|
|
1148
1484
|
var DIM = "\x1B[2m";
|
|
1149
1485
|
var RESET = "\x1B[0m";
|
|
1150
|
-
var program = new
|
|
1486
|
+
var program = new Command8();
|
|
1151
1487
|
program.name("jiradc").description("Jira Data Center CLI").version(readPackageVersion()).configureHelp({
|
|
1152
1488
|
styleTitle: (str) => styleText("bold", str),
|
|
1153
1489
|
styleUsage: (str) => styleText("dim", str),
|
|
@@ -1179,6 +1515,7 @@ program.hook("preAction", (thisCommand) => {
|
|
|
1179
1515
|
});
|
|
1180
1516
|
registerIssueCommands(program);
|
|
1181
1517
|
registerProjectCommands(program);
|
|
1518
|
+
registerComponentCommands(program);
|
|
1182
1519
|
registerBoardCommands(program);
|
|
1183
1520
|
registerSprintCommands(program);
|
|
1184
1521
|
registerFieldCommands(program);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "jiradc-cli",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.12-g3332dfd.1",
|
|
4
4
|
"publish": true,
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/index.js",
|
|
@@ -12,7 +12,7 @@
|
|
|
12
12
|
],
|
|
13
13
|
"dependencies": {
|
|
14
14
|
"commander": "^13.1.0",
|
|
15
|
-
"jira-data-center-client": "1.0.
|
|
15
|
+
"jira-data-center-client": "1.0.31-g3332dfd.1"
|
|
16
16
|
},
|
|
17
17
|
"devDependencies": {
|
|
18
18
|
"@types/node": "24.10.4",
|
|
@@ -22,8 +22,8 @@
|
|
|
22
22
|
"tsx": "^4.19.2",
|
|
23
23
|
"typescript": "^5.7.2",
|
|
24
24
|
"vitest": "^4.0.16",
|
|
25
|
-
"config-
|
|
26
|
-
"config-
|
|
25
|
+
"config-typescript": "0.0.0",
|
|
26
|
+
"config-eslint": "0.0.0"
|
|
27
27
|
},
|
|
28
28
|
"engines": {
|
|
29
29
|
"node": ">=22.0.0"
|