jiradc-cli 1.0.11 → 1.0.12-g39f1036.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.
Files changed (2) hide show
  1. package/dist/index.js +342 -48
  2. package/package.json +2 -2
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 Command6 } from "commander";
8
+ import { Command as Command8 } from "commander";
9
9
 
10
10
  // src/commands/board/issues.ts
11
11
  import { Argument } from "commander";
@@ -226,6 +226,135 @@ Examples:
226
226
  issues(board);
227
227
  }
228
228
 
229
+ // src/commands/component/create.ts
230
+ import { Option as Option2 } from "commander";
231
+ var ASSIGNEE_TYPES = [
232
+ "PROJECT_DEFAULT",
233
+ "COMPONENT_LEAD",
234
+ "PROJECT_LEAD",
235
+ "UNASSIGNED"
236
+ ];
237
+ function create(parent) {
238
+ 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(
239
+ "after",
240
+ `
241
+ Examples:
242
+ jiradc component create --project AI --name Backend
243
+ jiradc component create --project AI --name Frontend --description "UI work" --lead jsmith
244
+ jiradc component create --project AI --name Infra --assignee-type COMPONENT_LEAD --lead jsmith`
245
+ ).action(
246
+ async (opts) => {
247
+ const client = getClient();
248
+ const result = await client.components.create({
249
+ project: opts.project,
250
+ name: opts.name,
251
+ description: opts.description,
252
+ leadUserName: opts.lead,
253
+ assigneeType: opts.assigneeType
254
+ });
255
+ output(result);
256
+ }
257
+ );
258
+ }
259
+
260
+ // src/commands/component/delete.ts
261
+ function deleteComponent(parent) {
262
+ 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(
263
+ "after",
264
+ `
265
+ Examples:
266
+ jiradc component delete 11289
267
+ jiradc component delete 11289 --move-issues-to 11290`
268
+ ).action(async (id, opts) => {
269
+ const client = getClient();
270
+ await client.components.delete({ id, moveIssuesTo: opts.moveIssuesTo });
271
+ output({ deleted: true, componentId: id, ...opts.moveIssuesTo && { movedIssuesTo: opts.moveIssuesTo } });
272
+ });
273
+ }
274
+
275
+ // src/commands/component/get.ts
276
+ function get(parent) {
277
+ parent.command("get <id>").description("Get a component by ID").addHelpText("after", "\nExamples:\n jiradc component get 11289").action(async (id) => {
278
+ const client = getClient();
279
+ const result = await client.components.get({ id });
280
+ output(result);
281
+ });
282
+ }
283
+
284
+ // src/commands/component/issue-count.ts
285
+ function issueCount(parent) {
286
+ 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) => {
287
+ const client = getClient();
288
+ const result = await client.components.getRelatedIssueCounts({ id });
289
+ output(result);
290
+ });
291
+ }
292
+
293
+ // src/commands/component/list.ts
294
+ function list2(parent) {
295
+ parent.command("list <projectKey>").description("List all components for a project").addHelpText("after", "\nExamples:\n jiradc component list AI").action(async (projectKey) => {
296
+ const client = getClient();
297
+ const result = await client.components.list({ projectKeyOrId: projectKey });
298
+ output(result);
299
+ });
300
+ }
301
+
302
+ // src/commands/component/update.ts
303
+ import { Option as Option3 } from "commander";
304
+ var ASSIGNEE_TYPES2 = [
305
+ "PROJECT_DEFAULT",
306
+ "COMPONENT_LEAD",
307
+ "PROJECT_LEAD",
308
+ "UNASSIGNED"
309
+ ];
310
+ function update(parent) {
311
+ 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(
312
+ "after",
313
+ `
314
+ Examples:
315
+ jiradc component update 11289 --name Backend
316
+ jiradc component update 11289 --description "Server-side code"
317
+ jiradc component update 11289 --lead jsmith --assignee-type COMPONENT_LEAD`
318
+ ).action(
319
+ async (id, opts) => {
320
+ if (opts.name === void 0 && opts.description === void 0 && opts.lead === void 0 && opts.assigneeType === void 0) {
321
+ throw new Error("Provide at least one of --name, --description, --lead, --assignee-type");
322
+ }
323
+ const client = getClient();
324
+ const result = await client.components.update({
325
+ id,
326
+ name: opts.name,
327
+ description: opts.description,
328
+ leadUserName: opts.lead,
329
+ assigneeType: opts.assigneeType
330
+ });
331
+ output(result);
332
+ }
333
+ );
334
+ }
335
+
336
+ // src/commands/component/index.ts
337
+ function registerComponentCommands(program2) {
338
+ const component = program2.command("component").description("Project component operations").addHelpText(
339
+ "after",
340
+ `
341
+ Examples:
342
+ $ jiradc component list AI
343
+ $ jiradc component get 11289
344
+ $ jiradc component create --project AI --name Backend
345
+ $ jiradc component update 11289 --name Backend
346
+ $ jiradc component delete 11289 --move-issues-to 11290
347
+ $ jiradc component issue-count 11289
348
+ `
349
+ );
350
+ list2(component);
351
+ get(component);
352
+ create(component);
353
+ update(component);
354
+ deleteComponent(component);
355
+ issueCount(component);
356
+ }
357
+
229
358
  // src/commands/field/options.ts
230
359
  function options(parent) {
231
360
  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(
@@ -343,7 +472,7 @@ function download(parent) {
343
472
  }
344
473
 
345
474
  // src/commands/issue/attachment/list.ts
346
- function list2(parent) {
475
+ function list3(parent) {
347
476
  parent.command("list <key>").description("List attachments on an issue").addHelpText("after", "\nExamples:\n jiradc issue attachment list PROJ-123").action(async (key) => {
348
477
  const client = getClient();
349
478
  const issue = await client.issues.get({
@@ -406,7 +535,7 @@ Examples:
406
535
  `
407
536
  );
408
537
  upload(attachment);
409
- list2(attachment);
538
+ list3(attachment);
410
539
  download(attachment);
411
540
  downloadAll(attachment);
412
541
  deleteAttachment(attachment);
@@ -475,6 +604,162 @@ function batchChangelog(parent) {
475
604
  });
476
605
  }
477
606
 
607
+ // src/utils/transformers.ts
608
+ function transformPaged(response, fn) {
609
+ const { startAt, maxResults, total } = response;
610
+ if ("issues" in response) {
611
+ const mapped2 = response.issues.map(fn);
612
+ return { startAt, maxResults, total, isLast: startAt + mapped2.length >= total, issues: mapped2 };
613
+ }
614
+ if ("values" in response) {
615
+ const mapped2 = response.values.map(fn);
616
+ return { startAt, maxResults, total, isLast: startAt + mapped2.length >= total, values: mapped2 };
617
+ }
618
+ const mapped = response.worklogs.map(fn);
619
+ return { startAt, maxResults, total, isLast: startAt + mapped.length >= total, worklogs: mapped };
620
+ }
621
+ function issueBrowseUrl(key, ctx) {
622
+ return `${ctx.baseUrl}/browse/${key}`;
623
+ }
624
+ function transformCreatedIssue(r, ctx) {
625
+ return { id: r.id, key: r.key, url: issueBrowseUrl(r.key, ctx) };
626
+ }
627
+ function transformUser(user) {
628
+ const { self: _self, avatarUrls: _avatarUrls, expand: _expand, ...rest } = user;
629
+ return rest;
630
+ }
631
+ function transformIssueType(t) {
632
+ const { self: _self, iconUrl: _iconUrl, avatarId: _avatarId, ...rest } = t;
633
+ return rest;
634
+ }
635
+ function transformStatus(s) {
636
+ const { self: _self, iconUrl: _iconUrl, ...rest } = s;
637
+ return rest;
638
+ }
639
+ function transformPriority(p) {
640
+ const { self: _self, iconUrl: _iconUrl, ...rest } = p;
641
+ return rest;
642
+ }
643
+ function transformResolution(r) {
644
+ const { self: _self, ...rest } = r;
645
+ return rest;
646
+ }
647
+ function transformVersion(v) {
648
+ const { self: _self, ...rest } = v;
649
+ return rest;
650
+ }
651
+ function transformIssueLinkType(t) {
652
+ const { self: _self, ...rest } = t;
653
+ return rest;
654
+ }
655
+ function transformComment(c) {
656
+ const { self: _self, author, updateAuthor, ...rest } = c;
657
+ return {
658
+ ...rest,
659
+ ...author ? { author: transformUser(author) } : {},
660
+ ...updateAuthor ? { updateAuthor: transformUser(updateAuthor) } : {}
661
+ };
662
+ }
663
+ function transformWorklog(w) {
664
+ const { self: _self, author, updateAuthor, ...rest } = w;
665
+ return {
666
+ ...rest,
667
+ ...author ? { author: transformUser(author) } : {},
668
+ ...updateAuthor ? { updateAuthor: transformUser(updateAuthor) } : {}
669
+ };
670
+ }
671
+ function transformAttachment(a) {
672
+ const { self: _self, author, ...rest } = a;
673
+ return {
674
+ ...rest,
675
+ ...author ? { author: transformUser(author) } : {}
676
+ };
677
+ }
678
+ function transformIssueBasic(b, ctx) {
679
+ const { self: _self, fields, ...rest } = b;
680
+ return {
681
+ ...rest,
682
+ url: issueBrowseUrl(b.key, ctx),
683
+ ...fields ? {
684
+ fields: {
685
+ ...fields.summary !== void 0 ? { summary: fields.summary } : {},
686
+ ...fields.status ? { status: transformStatus(fields.status) } : {},
687
+ ...fields.priority ? { priority: transformPriority(fields.priority) } : {},
688
+ ...fields.issuetype ? { issuetype: transformIssueType(fields.issuetype) } : {}
689
+ }
690
+ } : {}
691
+ };
692
+ }
693
+ function transformIssueLink(l, ctx) {
694
+ const { self: _self, type, inwardIssue, outwardIssue, ...rest } = l;
695
+ return {
696
+ ...rest,
697
+ type: transformIssueLinkType(type),
698
+ ...inwardIssue ? { inwardIssue: transformIssueBasic(inwardIssue, ctx) } : {},
699
+ ...outwardIssue ? { outwardIssue: transformIssueBasic(outwardIssue, ctx) } : {}
700
+ };
701
+ }
702
+ function transformIssue(issue, ctx) {
703
+ const { self: _self, expand: _expand, fields, ...rest } = issue;
704
+ return {
705
+ ...rest,
706
+ url: issueBrowseUrl(issue.key, ctx),
707
+ fields: transformIssueFields(fields, ctx)
708
+ };
709
+ }
710
+ function transformIssueFields(fields, ctx) {
711
+ const {
712
+ issuetype,
713
+ status,
714
+ priority,
715
+ resolution,
716
+ assignee,
717
+ reporter,
718
+ creator,
719
+ fixVersions,
720
+ versions: versions2,
721
+ issuelinks,
722
+ subtasks,
723
+ parent,
724
+ comment: comment2,
725
+ worklog: worklog2,
726
+ attachment,
727
+ ...rest
728
+ } = fields;
729
+ return {
730
+ ...rest,
731
+ issuetype: transformIssueType(issuetype),
732
+ status: transformStatus(status),
733
+ ...priority ? { priority: transformPriority(priority) } : {},
734
+ ...resolution ? { resolution: transformResolution(resolution) } : {},
735
+ ...assignee ? { assignee: transformUser(assignee) } : {},
736
+ ...reporter ? { reporter: transformUser(reporter) } : {},
737
+ ...creator ? { creator: transformUser(creator) } : {},
738
+ ...fixVersions ? { fixVersions: fixVersions.map(transformVersion) } : {},
739
+ ...versions2 ? { versions: versions2.map(transformVersion) } : {},
740
+ ...issuelinks ? { issuelinks: issuelinks.map((l) => transformIssueLink(l, ctx)) } : {},
741
+ ...subtasks ? { subtasks: subtasks.map((s) => transformIssueBasic(s, ctx)) } : {},
742
+ ...parent ? { parent: transformIssueBasic(parent, ctx) } : {},
743
+ ...comment2 ? {
744
+ comment: {
745
+ comments: comment2.comments.map(transformComment),
746
+ maxResults: comment2.maxResults,
747
+ total: comment2.total,
748
+ startAt: comment2.startAt
749
+ }
750
+ } : {},
751
+ ...worklog2 ? {
752
+ worklog: {
753
+ worklogs: worklog2.worklogs.map(transformWorklog),
754
+ maxResults: worklog2.maxResults,
755
+ total: worklog2.total,
756
+ startAt: worklog2.startAt
757
+ }
758
+ } : {},
759
+ ...attachment ? { attachment: attachment.map(transformAttachment) } : {}
760
+ };
761
+ }
762
+
478
763
  // src/commands/issue/batch-create.ts
479
764
  function batchCreate(parent) {
480
765
  parent.command("batch-create").description("Create multiple issues from a JSON array").requiredOption("--issues <json>", "JSON array of issue objects").addHelpText(
@@ -484,12 +769,13 @@ Examples:
484
769
  jiradc issue batch-create --issues '[{"projectKeyOrId":"PROJ","issueTypeName":"Task","summary":"Task 1"},{"projectKeyOrId":"PROJ","issueTypeName":"Task","summary":"Task 2"}]'`
485
770
  ).action(async (opts) => {
486
771
  const client = getClient();
772
+ const ctx = { baseUrl: client.baseUrl };
487
773
  const parsed = JSON.parse(opts.issues);
488
774
  const results = [];
489
775
  for (const issue of parsed) {
490
776
  try {
491
777
  const result = await client.issues.create(issue);
492
- results.push({ key: result.key });
778
+ results.push({ key: result.key, url: issueBrowseUrl(result.key, ctx) });
493
779
  } catch (error) {
494
780
  results.push({ error: error instanceof Error ? error.message : "Unknown error" });
495
781
  }
@@ -536,6 +822,7 @@ Examples:
536
822
  ).action(
537
823
  async (key, opts) => {
538
824
  const client = getClient();
825
+ const ctx = { baseUrl: client.baseUrl };
539
826
  const source = await client.issues.get({ issueKeyOrId: key, fields: CLONE_FIELDS });
540
827
  const f = source.fields;
541
828
  const createParams = {
@@ -555,7 +842,8 @@ Examples:
555
842
  const cloneResult = {
556
843
  cloned: true,
557
844
  source: key,
558
- newIssue: result
845
+ newIssue: result,
846
+ url: issueBrowseUrl(newKey, ctx)
559
847
  };
560
848
  if (opts.includeAttachments && f.attachment?.length) {
561
849
  const tmpFiles = [];
@@ -607,7 +895,7 @@ function commentEdit(parent) {
607
895
  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
896
  const client = getClient();
609
897
  const result = await client.issues.editComment({ issueKeyOrId: key, commentId: opts.id, body: opts.body });
610
- output(result);
898
+ output(transformComment(result));
611
899
  });
612
900
  }
613
901
 
@@ -616,12 +904,12 @@ function comment(parent) {
616
904
  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
905
  const client = getClient();
618
906
  const result = await client.issues.addComment({ issueKeyOrId: key, body: opts.body });
619
- output(result);
907
+ output(transformComment(result));
620
908
  });
621
909
  }
622
910
 
623
911
  // src/commands/issue/create.ts
624
- function create(parent) {
912
+ function create2(parent) {
625
913
  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
914
  "after",
627
915
  `
@@ -633,6 +921,7 @@ Examples:
633
921
  ).action(
634
922
  async (opts) => {
635
923
  const client = getClient();
924
+ const ctx = { baseUrl: client.baseUrl };
636
925
  const result = await client.issues.create({
637
926
  projectKeyOrId: opts.project,
638
927
  issueTypeName: opts.type,
@@ -648,7 +937,7 @@ Examples:
648
937
  parent: opts.parent,
649
938
  customFields: opts.customFields ? JSON.parse(opts.customFields) : void 0
650
939
  });
651
- output(result);
940
+ output(transformCreatedIssue(result, ctx));
652
941
  }
653
942
  );
654
943
  }
@@ -756,7 +1045,7 @@ function getWorklog(parent) {
756
1045
  startAt: opts.startAt,
757
1046
  maxResults: opts.max
758
1047
  });
759
- output(result);
1048
+ output(transformPaged(result, transformWorklog));
760
1049
  });
761
1050
  }
762
1051
 
@@ -777,19 +1066,20 @@ var DEFAULT_FIELDS = [
777
1066
  ];
778
1067
 
779
1068
  // src/commands/issue/get.ts
780
- function get(parent) {
1069
+ function get2(parent) {
781
1070
  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
1071
  "after",
783
1072
  "\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"
784
1073
  ).action(async (key, opts) => {
785
1074
  const client = getClient();
1075
+ const ctx = { baseUrl: client.baseUrl };
786
1076
  const fields = opts.allFields ? void 0 : opts.fields?.split(",").map((f) => f.trim()) ?? DEFAULT_FIELDS;
787
1077
  const result = await client.issues.get({
788
1078
  issueKeyOrId: key,
789
1079
  fields,
790
1080
  expand: opts.expand
791
1081
  });
792
- output(result);
1082
+ output(transformIssue(result, ctx));
793
1083
  });
794
1084
  }
795
1085
 
@@ -797,11 +1087,18 @@ function get(parent) {
797
1087
  function linkEpic(parent) {
798
1088
  parent.command("link-epic <key>").description("Link an issue to an epic").requiredOption("--epic <epicKey>", "Epic issue key").addHelpText("after", "\nExamples:\n jiradc issue link-epic PROJ-456 --epic PROJ-123").action(async (key, opts) => {
799
1089
  const client = getClient();
1090
+ const ctx = { baseUrl: client.baseUrl };
800
1091
  await client.issues.update({
801
1092
  issueKeyOrId: key,
802
1093
  fields: { customfield_10100: opts.epic }
803
1094
  });
804
- output({ linked: true, issue: key, epic: opts.epic });
1095
+ output({
1096
+ linked: true,
1097
+ issue: key,
1098
+ url: issueBrowseUrl(key, ctx),
1099
+ epic: opts.epic,
1100
+ epicUrl: issueBrowseUrl(opts.epic, ctx)
1101
+ });
805
1102
  });
806
1103
  }
807
1104
 
@@ -810,7 +1107,7 @@ function linkTypes(parent) {
810
1107
  parent.command("link-types").description("List all issue link types").addHelpText("after", "\nExamples:\n jiradc issue link-types").action(async () => {
811
1108
  const client = getClient();
812
1109
  const result = await client.links.getTypes();
813
- output(result);
1110
+ output(result.map(transformIssueLinkType));
814
1111
  });
815
1112
  }
816
1113
 
@@ -838,6 +1135,7 @@ function search2(parent) {
838
1135
  '\nExamples:\n jiradc issue search "project = PROJ AND status = Open"\n jiradc issue search "assignee = currentUser()" --max 10 --fields summary,status\n jiradc issue search "project = PROJ" --start-at 50 --max 50'
839
1136
  ).action(async (jql, opts) => {
840
1137
  const client = getClient();
1138
+ const ctx = { baseUrl: client.baseUrl };
841
1139
  const fields = opts.allFields ? void 0 : opts.fields?.split(",").map((f) => f.trim()) ?? DEFAULT_FIELDS;
842
1140
  const result = await client.issues.search({
843
1141
  jql,
@@ -845,7 +1143,7 @@ function search2(parent) {
845
1143
  maxResults: opts.max,
846
1144
  fields
847
1145
  });
848
- output(result);
1146
+ output(transformPaged(result, (i) => transformIssue(i, ctx)));
849
1147
  });
850
1148
  }
851
1149
 
@@ -856,8 +1154,9 @@ function transition(parent) {
856
1154
  '\nExamples:\n jiradc issue transition PROJ-123 --to 31\n jiradc issue transition PROJ-123 --to 31 --comment "Moving to review"'
857
1155
  ).action(async (key, opts) => {
858
1156
  const client = getClient();
1157
+ const ctx = { baseUrl: client.baseUrl };
859
1158
  await client.issues.transition({ issueKeyOrId: key, transitionId: opts.to, comment: opts.comment });
860
- output({ transitioned: true, issueKey: key });
1159
+ output({ transitioned: true, issueKey: key, url: issueBrowseUrl(key, ctx) });
861
1160
  });
862
1161
  }
863
1162
 
@@ -880,7 +1179,7 @@ function unlink2(parent) {
880
1179
  }
881
1180
 
882
1181
  // src/commands/issue/update.ts
883
- function update(parent) {
1182
+ function update2(parent) {
884
1183
  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
1184
  "after",
886
1185
  `
@@ -891,10 +1190,10 @@ Examples:
891
1190
  jiradc issue update PROJ-123 --fields '{"summary": "With attachment"}' --attachments ./report.pdf`
892
1191
  ).action(async (key, opts) => {
893
1192
  if (!opts.fields && !opts.attachments) {
894
- console.error(JSON.stringify({ error: "Provide --fields and/or --attachments" }));
895
- process.exit(1);
1193
+ throw new Error("Provide --fields and/or --attachments");
896
1194
  }
897
1195
  const client = getClient();
1196
+ const ctx = { baseUrl: client.baseUrl };
898
1197
  if (opts.fields) {
899
1198
  const parsed = JSON.parse(opts.fields);
900
1199
  await client.issues.update({ issueKeyOrId: key, fields: parsed, notifyUsers: opts.notifyUsers });
@@ -909,7 +1208,12 @@ Examples:
909
1208
  }
910
1209
  }
911
1210
  }
912
- output({ updated: true, issueKey: key, ...uploaded.length > 0 && { attachments: uploaded } });
1211
+ output({
1212
+ updated: true,
1213
+ issueKey: key,
1214
+ url: issueBrowseUrl(key, ctx),
1215
+ ...uploaded.length > 0 && { attachments: uploaded }
1216
+ });
913
1217
  });
914
1218
  }
915
1219
 
@@ -926,7 +1230,7 @@ function worklog(parent) {
926
1230
  comment: opts.comment,
927
1231
  started: opts.started
928
1232
  });
929
- output(result);
1233
+ output(transformWorklog(result));
930
1234
  });
931
1235
  }
932
1236
 
@@ -944,10 +1248,10 @@ Examples:
944
1248
  $ jiradc issue attachment list PROJ-123
945
1249
  `
946
1250
  );
947
- get(issue);
1251
+ get2(issue);
948
1252
  search2(issue);
949
- create(issue);
950
- update(issue);
1253
+ create2(issue);
1254
+ update2(issue);
951
1255
  deleteIssue(issue);
952
1256
  transition(issue);
953
1257
  transitions(issue);
@@ -968,17 +1272,8 @@ Examples:
968
1272
  devStatus(issue);
969
1273
  }
970
1274
 
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
1275
  // src/commands/project/list.ts
981
- function list3(parent) {
1276
+ function list4(parent) {
982
1277
  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
1278
  "after",
984
1279
  "\nExamples:\n jiradc project list\n jiradc project list --expand description,lead\n jiradc project list --include-archived"
@@ -1009,16 +1304,14 @@ function registerProjectCommands(program2) {
1009
1304
  Examples:
1010
1305
  $ jiradc project list
1011
1306
  $ jiradc project versions PROJ
1012
- $ jiradc project components PROJ
1013
1307
  `
1014
1308
  );
1015
- list3(project);
1309
+ list4(project);
1016
1310
  versions(project);
1017
- components(project);
1018
1311
  }
1019
1312
 
1020
1313
  // src/commands/sprint/create.ts
1021
- function create2(parent) {
1314
+ function create3(parent) {
1022
1315
  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
1316
  "after",
1024
1317
  '\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"'
@@ -1055,10 +1348,10 @@ function issues2(parent) {
1055
1348
  }
1056
1349
 
1057
1350
  // src/commands/sprint/list.ts
1058
- import { Option as Option2 } from "commander";
1351
+ import { Option as Option4 } from "commander";
1059
1352
  var SPRINT_STATES = ["future", "active", "closed"];
1060
- function list4(parent) {
1061
- parent.command("list").description("List sprints for a board").requiredOption("--board <id>", "Board ID", positiveInt).addOption(new Option2("--state <state>", "Filter by sprint state").choices(SPRINT_STATES)).addHelpText(
1353
+ function list5(parent) {
1354
+ 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
1355
  "after",
1063
1356
  "\nExamples:\n jiradc sprint list --board 42\n jiradc sprint list --board 42 --state active"
1064
1357
  ).action(async (opts) => {
@@ -1072,10 +1365,10 @@ function list4(parent) {
1072
1365
  }
1073
1366
 
1074
1367
  // src/commands/sprint/update.ts
1075
- import { Argument as Argument3, Option as Option3 } from "commander";
1368
+ import { Argument as Argument3, Option as Option5 } from "commander";
1076
1369
  var SPRINT_STATES2 = ["future", "active", "closed"];
1077
- function update2(parent) {
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 Option3("--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(
1370
+ function update3(parent) {
1371
+ 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
1372
  "after",
1080
1373
  '\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
1374
  ).action(
@@ -1106,10 +1399,10 @@ Examples:
1106
1399
  $ jiradc sprint create --board 42 --name "Sprint 10" --start-date 2026-04-01 --end-date 2026-04-14
1107
1400
  `
1108
1401
  );
1109
- list4(sprint);
1402
+ list5(sprint);
1110
1403
  issues2(sprint);
1111
- create2(sprint);
1112
- update2(sprint);
1404
+ create3(sprint);
1405
+ update3(sprint);
1113
1406
  }
1114
1407
 
1115
1408
  // src/commands/user/me.ts
@@ -1147,7 +1440,7 @@ function readPackageVersion() {
1147
1440
  }
1148
1441
  var DIM = "\x1B[2m";
1149
1442
  var RESET = "\x1B[0m";
1150
- var program = new Command6();
1443
+ var program = new Command8();
1151
1444
  program.name("jiradc").description("Jira Data Center CLI").version(readPackageVersion()).configureHelp({
1152
1445
  styleTitle: (str) => styleText("bold", str),
1153
1446
  styleUsage: (str) => styleText("dim", str),
@@ -1179,6 +1472,7 @@ program.hook("preAction", (thisCommand) => {
1179
1472
  });
1180
1473
  registerIssueCommands(program);
1181
1474
  registerProjectCommands(program);
1475
+ registerComponentCommands(program);
1182
1476
  registerBoardCommands(program);
1183
1477
  registerSprintCommands(program);
1184
1478
  registerFieldCommands(program);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "jiradc-cli",
3
- "version": "1.0.11",
3
+ "version": "1.0.12-g39f1036.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.30"
15
+ "jira-data-center-client": "1.0.31-g39f1036.1"
16
16
  },
17
17
  "devDependencies": {
18
18
  "@types/node": "24.10.4",