bitbucketdc-cli 1.0.12 → 1.0.14

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 +154 -89
  2. package/package.json +2 -2
package/dist/index.js CHANGED
@@ -1,8 +1,40 @@
1
1
  #!/usr/bin/env node
2
2
 
3
3
  // src/index.ts
4
+ import { readFileSync } from "fs";
5
+ import { dirname, join } from "path";
6
+ import { fileURLToPath } from "url";
4
7
  import { styleText } from "util";
5
- import { Command as Command8 } from "commander";
8
+ import { Command as Command9 } from "commander";
9
+
10
+ // src/utils/cli.ts
11
+ import { InvalidArgumentError } from "commander";
12
+ function intInRange(min, max) {
13
+ return (raw) => {
14
+ const n = parseInt(raw, 10);
15
+ if (Number.isNaN(n) || !Number.isFinite(n)) {
16
+ throw new InvalidArgumentError(`Not a number: "${raw}"`);
17
+ }
18
+ if (n < min || n > max) {
19
+ throw new InvalidArgumentError(`Must be between ${min} and ${max} (got ${n})`);
20
+ }
21
+ return n;
22
+ };
23
+ }
24
+ function nonNegativeInt(raw) {
25
+ const n = parseInt(raw, 10);
26
+ if (Number.isNaN(n) || n < 0) {
27
+ throw new InvalidArgumentError(`Must be a non-negative integer (got "${raw}")`);
28
+ }
29
+ return n;
30
+ }
31
+ function positiveInt(raw) {
32
+ const n = parseInt(raw, 10);
33
+ if (Number.isNaN(n) || n < 1) {
34
+ throw new InvalidArgumentError(`Must be a positive integer (got "${raw}")`);
35
+ }
36
+ return n;
37
+ }
6
38
 
7
39
  // src/utils/client.ts
8
40
  import { BitbucketClient } from "bitbucket-data-center-client";
@@ -131,15 +163,23 @@ function handleError(err) {
131
163
  `
132
164
  );
133
165
  } else {
134
- process.stderr.write(`${JSON.stringify({ error: message })}
135
- `);
166
+ const responseData = err?.response?.data;
167
+ const detail = responseData && typeof responseData === "object" ? responseData : void 0;
168
+ process.stderr.write(
169
+ `${JSON.stringify({
170
+ error: message,
171
+ ...axiosStatus !== void 0 && { statusCode: axiosStatus },
172
+ ...detail && { detail }
173
+ })}
174
+ `
175
+ );
136
176
  }
137
177
  process.exit(1);
138
178
  }
139
179
 
140
180
  // src/commands/commit/changes.ts
141
181
  function changes(parent) {
142
- parent.command("changes").description("List files changed in a specific commit").requiredOption("--project <key>", "Bitbucket project key").requiredOption("--repo <slug>", "Repository slug").requiredOption("--commit <hash>", "Commit hash").option("--limit <n>", "Number of items to return (default: 25)", parseInt).option("--start <n>", "Start index for pagination (default: 0)", parseInt).addHelpText(
182
+ parent.command("changes").description("List files changed in a specific commit").requiredOption("--project <key>", "Bitbucket project key").requiredOption("--repo <slug>", "Repository slug").requiredOption("--commit <hash>", "Commit hash").option("--limit <n>", "Number of items to return (1-1000)", intInRange(1, 1e3), 25).option("--start <n>", "Start index for pagination", nonNegativeInt).addHelpText(
143
183
  "after",
144
184
  `
145
185
  Examples:
@@ -160,8 +200,10 @@ Examples:
160
200
 
161
201
  // src/commands/commit/diff.ts
162
202
  import { Option } from "commander";
203
+ var WHITESPACE_MODES = ["show", "ignore-all"];
204
+ var DIFF_FORMATS = ["text", "json"];
163
205
  function diff(parent) {
164
- parent.command("diff").description("Get diff for a specific commit").requiredOption("--project <key>", "Bitbucket project key").requiredOption("--repo <slug>", "Repository slug").requiredOption("--commit <hash>", "Commit hash").option("--path <path>", "Scope diff to a single file").option("--context <n>", "Number of context lines around changes", parseInt).addOption(new Option("--whitespace <mode>", "Whitespace handling").choices(["show", "ignore-all"])).addOption(new Option("--format <fmt>", "Response format (default: text)").choices(["text", "json"])).addHelpText(
206
+ parent.command("diff").description("Get diff for a specific commit").requiredOption("--project <key>", "Bitbucket project key").requiredOption("--repo <slug>", "Repository slug").requiredOption("--commit <hash>", "Commit hash").option("--path <path>", "Scope diff to a single file").option("--context <n>", "Number of context lines around changes (0-500)", intInRange(0, 500)).addOption(new Option("--whitespace <mode>", "Whitespace handling").choices(WHITESPACE_MODES)).addOption(new Option("--format <fmt>", "Response format").choices(DIFF_FORMATS).default("text")).addHelpText(
165
207
  "after",
166
208
  `
167
209
  Examples:
@@ -178,7 +220,7 @@ Examples:
178
220
  path: opts.path,
179
221
  contextLines: opts.context,
180
222
  whitespace: opts.whitespace,
181
- format: opts.format || "text"
223
+ format: opts.format
182
224
  });
183
225
  if (typeof result === "string") {
184
226
  process.stdout.write(result);
@@ -206,7 +248,7 @@ Examples:
206
248
 
207
249
  // src/commands/compare/changes.ts
208
250
  function changes2(parent) {
209
- parent.command("changes").description("List files that differ between two refs").requiredOption("--project <key>", "Bitbucket project key").requiredOption("--repo <slug>", "Repository slug").requiredOption("--from <ref>", "Source ref (branch, tag, or commit)").requiredOption("--to <ref>", "Target ref (branch, tag, or commit)").option("--limit <n>", "Number of items to return (default: 25)", parseInt).option("--start <n>", "Start index for pagination (default: 0)", parseInt).addHelpText(
251
+ parent.command("changes").description("List files that differ between two refs").requiredOption("--project <key>", "Bitbucket project key").requiredOption("--repo <slug>", "Repository slug").requiredOption("--from <ref>", "Source ref (branch, tag, or commit)").requiredOption("--to <ref>", "Target ref (branch, tag, or commit)").option("--limit <n>", "Number of items to return (1-1000)", intInRange(1, 1e3), 25).option("--start <n>", "Start index for pagination", nonNegativeInt).addHelpText(
210
252
  "after",
211
253
  `
212
254
  Examples:
@@ -231,8 +273,9 @@ Examples:
231
273
 
232
274
  // src/commands/compare/diff.ts
233
275
  import { Option as Option2 } from "commander";
276
+ var WHITESPACE_MODES2 = ["show", "ignore-all"];
234
277
  function diff2(parent) {
235
- parent.command("diff").description("Get diff between two refs (structured JSON)").requiredOption("--project <key>", "Bitbucket project key").requiredOption("--repo <slug>", "Repository slug").requiredOption("--from <ref>", "Source ref (branch, tag, or commit)").requiredOption("--to <ref>", "Target ref (branch, tag, or commit)").option("--path <path>", "Scope diff to a single file").option("--context <n>", "Number of context lines around changes", parseInt).addOption(new Option2("--whitespace <mode>", "Whitespace handling").choices(["show", "ignore-all"])).addHelpText(
278
+ parent.command("diff").description("Get diff between two refs (structured JSON)").requiredOption("--project <key>", "Bitbucket project key").requiredOption("--repo <slug>", "Repository slug").requiredOption("--from <ref>", "Source ref (branch, tag, or commit)").requiredOption("--to <ref>", "Target ref (branch, tag, or commit)").option("--path <path>", "Scope diff to a single file").option("--context <n>", "Number of context lines around changes (0-500)", intInRange(0, 500)).addOption(new Option2("--whitespace <mode>", "Whitespace handling").choices(WHITESPACE_MODES2)).addHelpText(
236
279
  "after",
237
280
  `
238
281
  Examples:
@@ -272,7 +315,7 @@ Examples:
272
315
 
273
316
  // src/commands/file/list.ts
274
317
  function list(parent) {
275
- parent.command("list").description("List directory contents in a repository").requiredOption("--project <key>", "Bitbucket project key").requiredOption("--repo <slug>", "Repository slug").option("--path <path>", "Directory path (defaults to root)").option("--at <ref>", "Branch, tag, or commit hash").option("--limit <n>", "Number of items to return (default: 500)", parseInt).option("--start <n>", "Start index for pagination (default: 0)", parseInt).addHelpText(
318
+ parent.command("list").description("List directory contents in a repository").requiredOption("--project <key>", "Bitbucket project key").requiredOption("--repo <slug>", "Repository slug").option("--path <path>", "Directory path (defaults to root)").option("--at <ref>", "Branch, tag, or commit hash").option("--branch <ref>", "Alias for --at").option("--limit <n>", "Number of items to return (1-1000)", intInRange(1, 1e3), 25).option("--start <n>", "Start index for pagination", nonNegativeInt).addHelpText(
276
319
  "after",
277
320
  `
278
321
  Examples:
@@ -282,11 +325,12 @@ Examples:
282
325
  ).action(
283
326
  async (opts) => {
284
327
  const client = getClient();
328
+ const ref = opts.at ?? opts.branch;
285
329
  const result = await client.repositories.browse({
286
330
  projectKey: opts.project,
287
331
  repositorySlug: opts.repo,
288
332
  path: opts.path,
289
- at: opts.at,
333
+ at: ref,
290
334
  limit: opts.limit,
291
335
  start: opts.start
292
336
  });
@@ -297,7 +341,7 @@ Examples:
297
341
 
298
342
  // src/commands/file/show.ts
299
343
  function show(parent) {
300
- parent.command("show").description("Show raw file content from a repository").requiredOption("--project <key>", "Bitbucket project key").requiredOption("--repo <slug>", "Repository slug").requiredOption("--path <path>", "File path").option("--at <ref>", "Branch, tag, or commit hash").addHelpText(
344
+ parent.command("show").description("Show raw file content from a repository").requiredOption("--project <key>", "Bitbucket project key").requiredOption("--repo <slug>", "Repository slug").requiredOption("--path <path>", "File path").option("--at <ref>", "Branch, tag, or commit hash").option("--branch <ref>", "Alias for --at").addHelpText(
301
345
  "after",
302
346
  `
303
347
  Examples:
@@ -305,11 +349,12 @@ Examples:
305
349
  bitbucketdc file show --project PROJ --repo my-app --path config/settings.yaml --at release/2.0`
306
350
  ).action(async (opts) => {
307
351
  const client = getClient();
352
+ const ref = opts.at ?? opts.branch;
308
353
  const result = await client.repositories.getRawContent({
309
354
  projectKey: opts.project,
310
355
  repositorySlug: opts.repo,
311
356
  path: opts.path,
312
- at: opts.at
357
+ at: ref
313
358
  });
314
359
  process.stdout.write(result);
315
360
  });
@@ -332,10 +377,10 @@ Examples:
332
377
 
333
378
  // src/commands/pr/activities.ts
334
379
  function activities(parent) {
335
- parent.command("activities").description("Get activity on a pull request (comments, approvals, merges, etc.)").requiredOption("--project <key>", "Bitbucket project key").requiredOption("--repo <slug>", "Repository slug").requiredOption("--id <n>", "Pull request ID").option(
380
+ parent.command("activities").description("Get activity on a pull request (comments, approvals, merges, etc.)").requiredOption("--project <key>", "Bitbucket project key").requiredOption("--repo <slug>", "Repository slug").requiredOption("--id <n>", "Pull request ID", positiveInt).option(
336
381
  "--types <types>",
337
382
  "Comma-separated activity types (APPROVED, COMMENTED, DECLINED, MERGED, OPENED, REOPENED, RESCOPED, REVIEW_COMMENTED, REVIEW_DISCARDED, REVIEW_FINISHED, REVIEWED, UNAPPROVED, UPDATED)"
338
- ).option("--start <n>", "Starting index for pagination (default: 0)", parseInt).option("--limit <n>", "Maximum number of items to return (default: 25)", parseInt).addHelpText(
383
+ ).option("--start <n>", "Starting index for pagination", nonNegativeInt).option("--limit <n>", "Maximum number of items to return (1-1000)", intInRange(1, 1e3), 25).addHelpText(
339
384
  "after",
340
385
  `
341
386
  Examples:
@@ -348,7 +393,7 @@ Examples:
348
393
  const result = await client.pullRequests.getActivities({
349
394
  projectKey: opts.project,
350
395
  repositorySlug: opts.repo,
351
- pullRequestId: parseInt(opts.id),
396
+ pullRequestId: opts.id,
352
397
  start: opts.start,
353
398
  limit: opts.limit
354
399
  });
@@ -365,7 +410,7 @@ Examples:
365
410
 
366
411
  // src/commands/pr/can-merge.ts
367
412
  function canMerge(parent) {
368
- parent.command("can-merge").description("Check if a pull request can be merged").requiredOption("--project <key>", "Bitbucket project key").requiredOption("--repo <slug>", "Repository slug").requiredOption("--id <n>", "Pull request ID", parseInt).addHelpText("after", "\nExamples:\n bitbucketdc pr can-merge --project PROJ --repo my-repo --id 42").action(async (opts) => {
413
+ parent.command("can-merge").description("Check if a pull request can be merged").requiredOption("--project <key>", "Bitbucket project key").requiredOption("--repo <slug>", "Repository slug").requiredOption("--id <n>", "Pull request ID", positiveInt).addHelpText("after", "\nExamples:\n bitbucketdc pr can-merge --project PROJ --repo my-repo --id 42").action(async (opts) => {
369
414
  const client = getClient();
370
415
  const result = await client.pullRequests.canMerge({
371
416
  projectKey: opts.project,
@@ -378,7 +423,7 @@ function canMerge(parent) {
378
423
 
379
424
  // src/commands/pr/changes.ts
380
425
  function changes3(parent) {
381
- parent.command("changes").description("List changed files in a pull request").requiredOption("--project <key>", "Bitbucket project key").requiredOption("--repo <slug>", "Repository slug").requiredOption("--id <n>", "Pull request ID").option("--limit <n>", "Number of items to return (default: 25)", parseInt).addHelpText(
426
+ parent.command("changes").description("List changed files in a pull request").requiredOption("--project <key>", "Bitbucket project key").requiredOption("--repo <slug>", "Repository slug").requiredOption("--id <n>", "Pull request ID", positiveInt).option("--limit <n>", "Number of items to return (1-1000)", intInRange(1, 1e3), 25).addHelpText(
382
427
  "after",
383
428
  "\nExamples:\n bitbucketdc pr changes --project PROJ --repo my-repo --id 42\n bitbucketdc pr changes --project PROJ --repo my-repo --id 42 --limit 100"
384
429
  ).action(async (opts) => {
@@ -386,7 +431,7 @@ function changes3(parent) {
386
431
  const result = await client.pullRequests.getChanges({
387
432
  projectKey: opts.project,
388
433
  repositorySlug: opts.repo,
389
- pullRequestId: parseInt(opts.id),
434
+ pullRequestId: opts.id,
390
435
  limit: opts.limit
391
436
  });
392
437
  output(result);
@@ -395,7 +440,7 @@ function changes3(parent) {
395
440
 
396
441
  // src/commands/pr/comment.ts
397
442
  function comment(parent) {
398
- parent.command("comment").description("Add a general comment to a pull request").requiredOption("--project <key>", "Bitbucket project key").requiredOption("--repo <slug>", "Repository slug").requiredOption("--id <n>", "Pull request ID").requiredOption("--text <text>", "Comment text").option("--parent <n>", "Parent comment ID to reply to").addHelpText(
443
+ parent.command("comment").description("Add a general comment to a pull request").requiredOption("--project <key>", "Bitbucket project key").requiredOption("--repo <slug>", "Repository slug").requiredOption("--id <n>", "Pull request ID", positiveInt).requiredOption("--text <text>", "Comment text").option("--parent <n>", "Parent comment ID to reply to", positiveInt).addHelpText(
399
444
  "after",
400
445
  `
401
446
  Examples:
@@ -406,9 +451,9 @@ Examples:
406
451
  const result = await client.pullRequests.addComment({
407
452
  projectKey: opts.project,
408
453
  repositorySlug: opts.repo,
409
- pullRequestId: parseInt(opts.id),
454
+ pullRequestId: opts.id,
410
455
  text: opts.text,
411
- parentId: opts.parent ? parseInt(opts.parent) : void 0
456
+ parentId: opts.parent
412
457
  });
413
458
  outputCommentResult(result);
414
459
  });
@@ -458,7 +503,7 @@ Examples:
458
503
 
459
504
  // src/commands/pr/decline.ts
460
505
  function decline(parent) {
461
- parent.command("decline").description("Decline a pull request").requiredOption("--project <key>", "Bitbucket project key").requiredOption("--repo <slug>", "Repository slug").requiredOption("--id <n>", "Pull request ID", parseInt).addHelpText("after", "\nExamples:\n bitbucketdc pr decline --project PROJ --repo my-repo --id 42").action(async (opts) => {
506
+ parent.command("decline").description("Decline a pull request").requiredOption("--project <key>", "Bitbucket project key").requiredOption("--repo <slug>", "Repository slug").requiredOption("--id <n>", "Pull request ID", positiveInt).addHelpText("after", "\nExamples:\n bitbucketdc pr decline --project PROJ --repo my-repo --id 42").action(async (opts) => {
462
507
  const client = getClient();
463
508
  const result = await client.pullRequests.decline({
464
509
  projectKey: opts.project,
@@ -471,7 +516,7 @@ function decline(parent) {
471
516
 
472
517
  // src/commands/pr/delete-comment.ts
473
518
  function deleteComment(parent) {
474
- parent.command("delete-comment").description("Delete a pull request comment").requiredOption("--project <key>", "Bitbucket project key").requiredOption("--repo <slug>", "Repository slug").requiredOption("--id <n>", "Pull request ID", parseInt).requiredOption("--comment-id <n>", "Comment ID to delete", parseInt).addHelpText(
519
+ parent.command("delete-comment").description("Delete a pull request comment").requiredOption("--project <key>", "Bitbucket project key").requiredOption("--repo <slug>", "Repository slug").requiredOption("--id <n>", "Pull request ID", positiveInt).requiredOption("--comment-id <n>", "Comment ID to delete", positiveInt).addHelpText(
475
520
  "after",
476
521
  "\nExamples:\n bitbucketdc pr delete-comment --project PROJ --repo my-repo --id 42 --comment-id 123"
477
522
  ).action(async (opts) => {
@@ -495,7 +540,7 @@ function deleteComment(parent) {
495
540
 
496
541
  // src/commands/pr/delete.ts
497
542
  function deletePr(parent) {
498
- parent.command("delete").description("Delete a pull request").requiredOption("--project <key>", "Bitbucket project key").requiredOption("--repo <slug>", "Repository slug").requiredOption("--id <n>", "Pull request ID", parseInt).addHelpText("after", "\nExamples:\n bitbucketdc pr delete --project PROJ --repo my-repo --id 42").action(async (opts) => {
543
+ parent.command("delete").description("Delete a pull request").requiredOption("--project <key>", "Bitbucket project key").requiredOption("--repo <slug>", "Repository slug").requiredOption("--id <n>", "Pull request ID", positiveInt).addHelpText("after", "\nExamples:\n bitbucketdc pr delete --project PROJ --repo my-repo --id 42").action(async (opts) => {
499
544
  const client = getClient();
500
545
  await client.pullRequests.deletePullRequest({
501
546
  projectKey: opts.project,
@@ -508,8 +553,10 @@ function deletePr(parent) {
508
553
 
509
554
  // src/commands/pr/diff.ts
510
555
  import { Option as Option3 } from "commander";
556
+ var WHITESPACE_MODES3 = ["show", "ignore-all"];
557
+ var DIFF_FORMATS2 = ["text", "json"];
511
558
  function diff3(parent) {
512
- parent.command("diff").description("Get diff for a pull request").requiredOption("--project <key>", "Bitbucket project key").requiredOption("--repo <slug>", "Repository slug").requiredOption("--id <n>", "Pull request ID").option("--path <path>", "File path (omit for full PR diff)").option("--since <hash>", "Since commit hash").option("--until <hash>", "Until commit hash").option("--context <n>", "Number of context lines around changes (default: 10)", parseInt).addOption(new Option3("--whitespace <mode>", "Whitespace handling (default: show)").choices(["show", "ignore-all"])).addOption(new Option3("--format <fmt>", "Response format (default: text)").choices(["text", "json"])).addHelpText(
559
+ parent.command("diff").description("Get diff for a pull request").requiredOption("--project <key>", "Bitbucket project key").requiredOption("--repo <slug>", "Repository slug").requiredOption("--id <n>", "Pull request ID", positiveInt).option("--path <path>", "File path (omit for full PR diff)").option("--since <hash>", "Since commit hash").option("--until <hash>", "Until commit hash").option("--context <n>", "Number of context lines around changes (0-500)", intInRange(0, 500), 10).addOption(new Option3("--whitespace <mode>", "Whitespace handling").choices(WHITESPACE_MODES3).default("show")).addOption(new Option3("--format <fmt>", "Response format").choices(DIFF_FORMATS2).default("text")).addHelpText(
513
560
  "after",
514
561
  `
515
562
  Examples:
@@ -523,13 +570,13 @@ Examples:
523
570
  const result = await client.pullRequests.getDiff({
524
571
  projectKey: opts.project,
525
572
  repositorySlug: opts.repo,
526
- pullRequestId: parseInt(opts.id),
573
+ pullRequestId: opts.id,
527
574
  path: opts.path,
528
575
  sinceId: opts.since,
529
576
  untilId: opts.until,
530
577
  contextLines: opts.context,
531
578
  whitespace: opts.whitespace,
532
- format: opts.format || "text"
579
+ format: opts.format
533
580
  });
534
581
  if (typeof result === "string") {
535
582
  process.stdout.write(result);
@@ -542,7 +589,7 @@ Examples:
542
589
 
543
590
  // src/commands/pr/edit-comment.ts
544
591
  function editComment(parent) {
545
- parent.command("edit-comment").description("Edit a pull request comment").requiredOption("--project <key>", "Bitbucket project key").requiredOption("--repo <slug>", "Repository slug").requiredOption("--id <n>", "Pull request ID", parseInt).requiredOption("--comment-id <n>", "Comment ID to edit", parseInt).requiredOption("--text <content>", "New comment text").addHelpText(
592
+ parent.command("edit-comment").description("Edit a pull request comment").requiredOption("--project <key>", "Bitbucket project key").requiredOption("--repo <slug>", "Repository slug").requiredOption("--id <n>", "Pull request ID", positiveInt).requiredOption("--comment-id <n>", "Comment ID to edit", positiveInt).requiredOption("--text <content>", "New comment text").addHelpText(
546
593
  "after",
547
594
  '\nExamples:\n bitbucketdc pr edit-comment --project PROJ --repo my-repo --id 42 --comment-id 123 --text "Updated text"'
548
595
  ).action(async (opts) => {
@@ -567,7 +614,7 @@ function editComment(parent) {
567
614
 
568
615
  // src/commands/pr/file-comment.ts
569
616
  function fileComment(parent) {
570
- parent.command("file-comment").description("Add a file-level comment to a pull request").requiredOption("--project <key>", "Bitbucket project key").requiredOption("--repo <slug>", "Repository slug").requiredOption("--id <n>", "Pull request ID").requiredOption("--text <text>", "Comment text").requiredOption("--path <path>", "File path to attach comment to (e.g., src/main.ts)").addHelpText(
617
+ parent.command("file-comment").description("Add a file-level comment to a pull request").requiredOption("--project <key>", "Bitbucket project key").requiredOption("--repo <slug>", "Repository slug").requiredOption("--id <n>", "Pull request ID", positiveInt).requiredOption("--text <text>", "Comment text").requiredOption("--path <path>", "File path to attach comment to (e.g., src/main.ts)").addHelpText(
571
618
  "after",
572
619
  '\nExamples:\n bitbucketdc pr file-comment --project PROJ --repo my-repo --id 42 --text "This file needs refactoring" --path src/main.ts'
573
620
  ).action(async (opts) => {
@@ -575,7 +622,7 @@ function fileComment(parent) {
575
622
  const result = await client.pullRequests.addComment({
576
623
  projectKey: opts.project,
577
624
  repositorySlug: opts.repo,
578
- pullRequestId: parseInt(opts.id),
625
+ pullRequestId: opts.id,
579
626
  text: opts.text,
580
627
  path: opts.path
581
628
  });
@@ -585,7 +632,7 @@ function fileComment(parent) {
585
632
 
586
633
  // src/commands/pr/file-diff.ts
587
634
  function fileDiff(parent) {
588
- parent.command("file-diff").description("Get structured line-by-line diff for a specific file").requiredOption("--project <key>", "Bitbucket project key").requiredOption("--repo <slug>", "Repository slug").requiredOption("--id <n>", "Pull request ID").requiredOption("--path <path>", "File path (e.g., src/main.ts)").option("--context <n>", "Number of context lines around changes (default: 10)", parseInt).addHelpText(
635
+ parent.command("file-diff").description("Get structured line-by-line diff for a specific file").requiredOption("--project <key>", "Bitbucket project key").requiredOption("--repo <slug>", "Repository slug").requiredOption("--id <n>", "Pull request ID", positiveInt).requiredOption("--path <path>", "File path (e.g., src/main.ts)").option("--context <n>", "Number of context lines around changes (0-500)", intInRange(0, 500), 10).addHelpText(
589
636
  "after",
590
637
  "\nExamples:\n bitbucketdc pr file-diff --project PROJ --repo my-repo --id 42 --path src/main.ts\n bitbucketdc pr file-diff --project PROJ --repo my-repo --id 42 --path src/main.ts --context 5"
591
638
  ).action(async (opts) => {
@@ -593,7 +640,7 @@ function fileDiff(parent) {
593
640
  const result = await client.pullRequests.getFileDiff({
594
641
  projectKey: opts.project,
595
642
  repositorySlug: opts.repo,
596
- pullRequestId: parseInt(opts.id),
643
+ pullRequestId: opts.id,
597
644
  path: opts.path,
598
645
  contextLines: opts.context
599
646
  });
@@ -603,12 +650,12 @@ function fileDiff(parent) {
603
650
 
604
651
  // src/commands/pr/get.ts
605
652
  function get(parent) {
606
- parent.command("get").description("Get pull request details").requiredOption("--project <key>", "Bitbucket project key").requiredOption("--repo <slug>", "Repository slug").requiredOption("--id <n>", "Pull request ID").addHelpText("after", "\nExamples:\n bitbucketdc pr get --project PROJ --repo my-repo --id 42").action(async (opts) => {
653
+ parent.command("get").description("Get pull request details").requiredOption("--project <key>", "Bitbucket project key").requiredOption("--repo <slug>", "Repository slug").requiredOption("--id <n>", "Pull request ID", positiveInt).addHelpText("after", "\nExamples:\n bitbucketdc pr get --project PROJ --repo my-repo --id 42").action(async (opts) => {
607
654
  const client = getClient();
608
655
  const result = await client.pullRequests.get({
609
656
  projectKey: opts.project,
610
657
  repositorySlug: opts.repo,
611
- pullRequestId: parseInt(opts.id)
658
+ pullRequestId: opts.id
612
659
  });
613
660
  output(result);
614
661
  });
@@ -616,7 +663,7 @@ function get(parent) {
616
663
 
617
664
  // src/commands/pr/inbox.ts
618
665
  function inbox(parent) {
619
- parent.command("inbox").description("List pull requests in your reviewer inbox").option("--start <n>", "Starting index for pagination (default: 0)", parseInt).option("--limit <n>", "Maximum number of pull requests to return (default: 25)", parseInt).addHelpText(
666
+ parent.command("inbox").description("List pull requests in your reviewer inbox").option("--start <n>", "Starting index for pagination", nonNegativeInt).option("--limit <n>", "Maximum number of pull requests to return (1-1000)", intInRange(1, 1e3), 25).addHelpText(
620
667
  "after",
621
668
  "\nExamples:\n bitbucketdc pr inbox\n bitbucketdc pr inbox --limit 10\n bitbucketdc pr inbox --start 25 --limit 25"
622
669
  ).action(async (opts) => {
@@ -631,11 +678,11 @@ function inbox(parent) {
631
678
 
632
679
  // src/commands/pr/line-comment.ts
633
680
  import { Option as Option4 } from "commander";
681
+ var LINE_TYPES = ["ADDED", "REMOVED", "CONTEXT"];
682
+ var FILE_TYPES = ["FROM", "TO"];
634
683
  function lineComment(parent) {
635
- parent.command("line-comment").description("Add an inline comment to a specific line in a pull request").requiredOption("--project <key>", "Bitbucket project key").requiredOption("--repo <slug>", "Repository slug").requiredOption("--id <n>", "Pull request ID").requiredOption("--text <text>", "Comment text").requiredOption("--path <path>", "File path (e.g., src/main.ts)").requiredOption("--line <n>", "Line number to comment on").addOption(
636
- new Option4("--line-type <type>", "Type of line").choices(["ADDED", "REMOVED", "CONTEXT"]).makeOptionMandatory()
637
- ).addOption(
638
- new Option4("--file-type <type>", "Side of diff: FROM (source/old) or TO (destination/new)").choices(["FROM", "TO"]).makeOptionMandatory()
684
+ parent.command("line-comment").description("Add an inline comment to a specific line in a pull request").requiredOption("--project <key>", "Bitbucket project key").requiredOption("--repo <slug>", "Repository slug").requiredOption("--id <n>", "Pull request ID", positiveInt).requiredOption("--text <text>", "Comment text").requiredOption("--path <path>", "File path (e.g., src/main.ts)").requiredOption("--line <n>", "Line number to comment on", positiveInt).addOption(new Option4("--line-type <type>", "Type of line").choices(LINE_TYPES).makeOptionMandatory()).addOption(
685
+ new Option4("--file-type <type>", "Side of diff: FROM (source/old) or TO (destination/new)").choices(FILE_TYPES).makeOptionMandatory()
639
686
  ).addHelpText(
640
687
  "after",
641
688
  `
@@ -648,10 +695,10 @@ Examples:
648
695
  const result = await client.pullRequests.addComment({
649
696
  projectKey: opts.project,
650
697
  repositorySlug: opts.repo,
651
- pullRequestId: parseInt(opts.id),
698
+ pullRequestId: opts.id,
652
699
  text: opts.text,
653
700
  path: opts.path,
654
- line: parseInt(opts.line),
701
+ line: opts.line,
655
702
  lineType: opts.lineType,
656
703
  fileType: opts.fileType
657
704
  });
@@ -662,7 +709,7 @@ Examples:
662
709
 
663
710
  // src/commands/pr/merge.ts
664
711
  function merge(parent) {
665
- parent.command("merge").description("Merge a pull request").requiredOption("--project <key>", "Bitbucket project key").requiredOption("--repo <slug>", "Repository slug").requiredOption("--id <n>", "Pull request ID", parseInt).option("--strategy <id>", "Merge strategy (e.g., squash, no-ff, ff, ff-only, rebase-no-ff, rebase-ff-only)").option("--message <text>", "Custom merge commit message").addHelpText(
712
+ parent.command("merge").description("Merge a pull request").requiredOption("--project <key>", "Bitbucket project key").requiredOption("--repo <slug>", "Repository slug").requiredOption("--id <n>", "Pull request ID", positiveInt).option("--strategy <id>", "Merge strategy (e.g., squash, no-ff, ff, ff-only, rebase-no-ff, rebase-ff-only)").option("--message <text>", "Custom merge commit message").addHelpText(
666
713
  "after",
667
714
  `
668
715
  Examples:
@@ -685,7 +732,7 @@ Examples:
685
732
  // src/commands/pr/reaction-add.ts
686
733
  import { Option as Option5 } from "commander";
687
734
  function reactionAdd(parent) {
688
- parent.command("reaction-add").description("Add an emoticon reaction to a PR comment").requiredOption("--project <key>", "Bitbucket project key").requiredOption("--repo <slug>", "Repository slug").requiredOption("--id <n>", "Pull request ID").requiredOption("--comment-id <n>", "Comment ID").addOption(
735
+ parent.command("reaction-add").description("Add an emoticon reaction to a PR comment").requiredOption("--project <key>", "Bitbucket project key").requiredOption("--repo <slug>", "Repository slug").requiredOption("--id <n>", "Pull request ID", positiveInt).requiredOption("--comment-id <n>", "Comment ID", positiveInt).addOption(
689
736
  new Option5("--emoticon <name>", "Emoticon to react with").choices(["thumbsup", "thumbsdown", "heart", "thinking_face", "laughing"]).makeOptionMandatory()
690
737
  ).addHelpText(
691
738
  "after",
@@ -693,48 +740,51 @@ function reactionAdd(parent) {
693
740
  Examples:
694
741
  bitbucketdc pr reaction-add --project PROJ --repo my-repo --id 42 --comment-id 123 --emoticon thumbsup
695
742
  bitbucketdc pr reaction-add --project PROJ --repo my-repo --id 42 --comment-id 123 --emoticon heart`
696
- ).action(async (opts) => {
697
- const client = getClient();
698
- const result = await client.pullRequests.addReaction({
699
- projectKey: opts.project,
700
- repositorySlug: opts.repo,
701
- pullRequestId: parseInt(opts.id),
702
- commentId: parseInt(opts.commentId),
703
- emoticon: opts.emoticon
704
- });
705
- output(result);
706
- });
743
+ ).action(
744
+ async (opts) => {
745
+ const client = getClient();
746
+ const result = await client.pullRequests.addReaction({
747
+ projectKey: opts.project,
748
+ repositorySlug: opts.repo,
749
+ pullRequestId: opts.id,
750
+ commentId: opts.commentId,
751
+ emoticon: opts.emoticon
752
+ });
753
+ output(result);
754
+ }
755
+ );
707
756
  }
708
757
 
709
758
  // src/commands/pr/reaction-remove.ts
710
759
  import { Option as Option6 } from "commander";
711
760
  function reactionRemove(parent) {
712
- parent.command("reaction-remove").description("Remove an emoticon reaction from a PR comment").requiredOption("--project <key>", "Bitbucket project key").requiredOption("--repo <slug>", "Repository slug").requiredOption("--id <n>", "Pull request ID").requiredOption("--comment-id <n>", "Comment ID").addOption(
761
+ parent.command("reaction-remove").description("Remove an emoticon reaction from a PR comment").requiredOption("--project <key>", "Bitbucket project key").requiredOption("--repo <slug>", "Repository slug").requiredOption("--id <n>", "Pull request ID", positiveInt).requiredOption("--comment-id <n>", "Comment ID", positiveInt).addOption(
713
762
  new Option6("--emoticon <name>", "Emoticon to remove").choices(["thumbsup", "thumbsdown", "heart", "thinking_face", "laughing"]).makeOptionMandatory()
714
763
  ).addHelpText(
715
764
  "after",
716
765
  `
717
766
  Examples:
718
767
  bitbucketdc pr reaction-remove --project PROJ --repo my-repo --id 42 --comment-id 123 --emoticon thumbsup`
719
- ).action(async (opts) => {
720
- const client = getClient();
721
- await client.pullRequests.removeReaction({
722
- projectKey: opts.project,
723
- repositorySlug: opts.repo,
724
- pullRequestId: parseInt(opts.id),
725
- commentId: parseInt(opts.commentId),
726
- emoticon: opts.emoticon
727
- });
728
- output({ removed: true, emoticon: opts.emoticon });
729
- });
768
+ ).action(
769
+ async (opts) => {
770
+ const client = getClient();
771
+ await client.pullRequests.removeReaction({
772
+ projectKey: opts.project,
773
+ repositorySlug: opts.repo,
774
+ pullRequestId: opts.id,
775
+ commentId: opts.commentId,
776
+ emoticon: opts.emoticon
777
+ });
778
+ output({ removed: true, emoticon: opts.emoticon });
779
+ }
780
+ );
730
781
  }
731
782
 
732
783
  // src/commands/pr/review.ts
733
784
  import { Option as Option7 } from "commander";
785
+ var REVIEW_STATUSES = ["APPROVED", "NEEDS_WORK", "UNAPPROVED"];
734
786
  function review(parent) {
735
- parent.command("review").description("Update review status for a pull request").requiredOption("--project <key>", "Bitbucket project key").requiredOption("--repo <slug>", "Repository slug").requiredOption("--id <n>", "Pull request ID").addOption(
736
- new Option7("--status <status>", "Review status").choices(["APPROVED", "NEEDS_WORK", "UNAPPROVED"]).makeOptionMandatory()
737
- ).addHelpText(
787
+ parent.command("review").description("Update review status for a pull request").requiredOption("--project <key>", "Bitbucket project key").requiredOption("--repo <slug>", "Repository slug").requiredOption("--id <n>", "Pull request ID", positiveInt).addOption(new Option7("--status <status>", "Review status").choices(REVIEW_STATUSES).makeOptionMandatory()).addHelpText(
738
788
  "after",
739
789
  `
740
790
  Examples:
@@ -746,7 +796,7 @@ Examples:
746
796
  const result = await client.pullRequests.updateReviewStatus({
747
797
  projectKey: opts.project,
748
798
  repositorySlug: opts.repo,
749
- pullRequestId: parseInt(opts.id),
799
+ pullRequestId: opts.id,
750
800
  status: opts.status
751
801
  });
752
802
  output(result);
@@ -755,7 +805,7 @@ Examples:
755
805
 
756
806
  // src/commands/pr/update.ts
757
807
  function update(parent) {
758
- parent.command("update").description("Update a pull request title and/or description").requiredOption("--project <key>", "Bitbucket project key").requiredOption("--repo <slug>", "Repository slug").requiredOption("--id <n>", "Pull request ID", parseInt).option("--title <title>", "New pull request title").option("--description <text>", "New pull request description").addHelpText(
808
+ parent.command("update").description("Update a pull request title and/or description").requiredOption("--project <key>", "Bitbucket project key").requiredOption("--repo <slug>", "Repository slug").requiredOption("--id <n>", "Pull request ID", positiveInt).option("--title <title>", "New pull request title").option("--description <text>", "New pull request description").addHelpText(
759
809
  "after",
760
810
  `
761
811
  Examples:
@@ -824,7 +874,7 @@ Examples:
824
874
 
825
875
  // src/commands/project/list.ts
826
876
  function list2(parent) {
827
- parent.command("list").description("List projects").option("--name <name>", "Filter projects by name (partial match)").option("--permission <permission>", "Filter by permission (e.g., PROJECT_READ, PROJECT_WRITE, PROJECT_ADMIN)").option("--start <start>", "Starting index for pagination", parseInt).option("--limit <limit>", "Maximum number of projects to return", parseInt).addHelpText(
877
+ parent.command("list").description("List projects").option("--name <name>", "Filter projects by name (partial match)").option("--permission <permission>", "Filter by permission (e.g., PROJECT_READ, PROJECT_WRITE, PROJECT_ADMIN)").option("--start <start>", "Starting index for pagination", nonNegativeInt).option("--limit <limit>", "Maximum number of projects to return (1-1000)", intInRange(1, 1e3), 25).addHelpText(
828
878
  "after",
829
879
  '\nExamples:\n bitbucketdc project list\n bitbucketdc project list --name "My Project"\n bitbucketdc project list --permission PROJECT_READ --limit 10'
830
880
  ).action(async (opts) => {
@@ -877,20 +927,22 @@ function upload(parent) {
877
927
  ).action(async (opts) => {
878
928
  const client = getClient();
879
929
  const filePaths = opts.files.split(",").map((p) => p.trim()).filter(Boolean);
880
- const results = [];
881
- const failed = [];
882
- for (const filePath of filePaths) {
883
- try {
884
- const result = await client.repositories.uploadAttachment({
885
- projectKey: opts.project,
886
- repositorySlug: opts.repo,
887
- filePath
888
- });
889
- results.push({ id: result.id, url: result.url });
890
- } catch (err) {
891
- failed.push({ filePath, error: err instanceof Error ? err.message : String(err) });
892
- }
893
- }
930
+ const outcomes = await Promise.all(
931
+ filePaths.map(async (filePath) => {
932
+ try {
933
+ const result = await client.repositories.uploadAttachment({
934
+ projectKey: opts.project,
935
+ repositorySlug: opts.repo,
936
+ filePath
937
+ });
938
+ return { ok: true, id: result.id, url: result.url };
939
+ } catch (err) {
940
+ return { ok: false, filePath, error: err instanceof Error ? err.message : String(err) };
941
+ }
942
+ })
943
+ );
944
+ const results = outcomes.filter((o) => o.ok).map(({ id, url }) => ({ id, url }));
945
+ const failed = outcomes.filter((o) => !o.ok).map(({ filePath, error }) => ({ filePath, error }));
894
946
  output({
895
947
  project: opts.project,
896
948
  repo: opts.repo,
@@ -943,8 +995,11 @@ Examples:
943
995
  }
944
996
 
945
997
  // src/commands/repo/list.ts
998
+ import { Option as Option8 } from "commander";
999
+ var VISIBILITIES = ["public", "private"];
1000
+ var ARCHIVE_STATES = ["ACTIVE", "ARCHIVED", "ALL"];
946
1001
  function list3(parent) {
947
- parent.command("list").description("List repositories with optional filters").option("--name <name>", "Filter by repository name (case-insensitive)").option("--project-key <key>", "Filter by project key").option("--project-name <name>", "Filter by project name (case-insensitive)").option("--visibility <type>", "Filter by visibility (public or private)").option("--archived <status>", "Filter by archived status (ACTIVE, ARCHIVED, ALL)").option("--start <n>", "Starting index for pagination (default: 0)", parseInt).option("--limit <n>", "Maximum results to return (default: 25)", parseInt).addHelpText(
1002
+ parent.command("list").description("List repositories with optional filters").option("--name <name>", "Filter by repository name (case-insensitive)").option("--project-key <key>", "Filter by project key").option("--project-name <name>", "Filter by project name (case-insensitive)").addOption(new Option8("--visibility <type>", "Filter by visibility").choices(VISIBILITIES)).addOption(new Option8("--archived <status>", "Filter by archived status").choices(ARCHIVE_STATES)).option("--start <n>", "Starting index for pagination", nonNegativeInt).option("--limit <n>", "Maximum results to return (1-1000)", intInRange(1, 1e3), 25).addHelpText(
948
1003
  "after",
949
1004
  `
950
1005
  Examples:
@@ -1019,10 +1074,20 @@ Examples:
1019
1074
  }
1020
1075
 
1021
1076
  // src/index.ts
1077
+ function readPackageVersion() {
1078
+ try {
1079
+ const here = dirname(fileURLToPath(import.meta.url));
1080
+ const pkgPath = join(here, "..", "package.json");
1081
+ const pkg = JSON.parse(readFileSync(pkgPath, "utf-8"));
1082
+ return pkg.version ?? "0.0.0";
1083
+ } catch {
1084
+ return "0.0.0";
1085
+ }
1086
+ }
1022
1087
  var DIM = "\x1B[2m";
1023
1088
  var RESET = "\x1B[0m";
1024
- var program = new Command8();
1025
- program.name("bitbucketdc").description("Bitbucket Data Center CLI").version("1.0.0").configureHelp({
1089
+ var program = new Command9();
1090
+ program.name("bitbucketdc").description("Bitbucket Data Center CLI").version(readPackageVersion()).configureHelp({
1026
1091
  styleTitle: (str) => styleText("bold", str),
1027
1092
  styleUsage: (str) => styleText("dim", str),
1028
1093
  styleCommandDescription: (str) => styleText("dim", str),
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "bitbucketdc-cli",
3
- "version": "1.0.12",
3
+ "version": "1.0.14",
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
- "bitbucket-data-center-client": "1.4.15"
15
+ "bitbucket-data-center-client": "1.4.16"
16
16
  },
17
17
  "devDependencies": {
18
18
  "@types/node": "24.10.4",