@pilatos/bitbucket-cli 1.6.0 → 1.8.0

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 (3) hide show
  1. package/README.md +35 -168
  2. package/dist/index.js +1056 -844
  3. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -10901,6 +10901,17 @@ var require_db = __commonJS((exports, module) => {
10901
10901
  };
10902
10902
  });
10903
10903
 
10904
+ // node_modules/mime-db/index.js
10905
+ var require_mime_db = __commonJS((exports, module) => {
10906
+ /*!
10907
+ * mime-db
10908
+ * Copyright(c) 2014 Jonathan Ong
10909
+ * Copyright(c) 2015-2022 Douglas Christopher Wilson
10910
+ * MIT Licensed
10911
+ */
10912
+ module.exports = require_db();
10913
+ });
10914
+
10904
10915
  // node_modules/mime-types/index.js
10905
10916
  var require_mime_types = __commonJS((exports) => {
10906
10917
  /*!
@@ -10909,7 +10920,7 @@ var require_mime_types = __commonJS((exports) => {
10909
10920
  * Copyright(c) 2015 Douglas Christopher Wilson
10910
10921
  * MIT Licensed
10911
10922
  */
10912
- var db = require_db();
10923
+ var db = require_mime_db();
10913
10924
  var extname = __require("path").extname;
10914
10925
  var EXTRACT_TYPE_REGEXP = /^\s*([^;\s]*)(?:;|\s|$)/;
10915
10926
  var TEXT_TYPE_REGEXP = /^text\//i;
@@ -11256,7 +11267,7 @@ var require_round = __commonJS((exports, module) => {
11256
11267
 
11257
11268
  // node_modules/math-intrinsics/isNaN.js
11258
11269
  var require_isNaN = __commonJS((exports, module) => {
11259
- module.exports = Number.isNaN || function isNaN2(a) {
11270
+ module.exports = Number.isNaN || function isNaN(a) {
11260
11271
  return a !== a;
11261
11272
  };
11262
11273
  });
@@ -11390,7 +11401,7 @@ var require_implementation = __commonJS((exports, module) => {
11390
11401
  var toStr = Object.prototype.toString;
11391
11402
  var max = Math.max;
11392
11403
  var funcType = "[object Function]";
11393
- var concatty = function concatty2(a, b) {
11404
+ var concatty = function concatty(a, b) {
11394
11405
  var arr = [];
11395
11406
  for (var i = 0;i < a.length; i += 1) {
11396
11407
  arr[i] = a[i];
@@ -11400,7 +11411,7 @@ var require_implementation = __commonJS((exports, module) => {
11400
11411
  }
11401
11412
  return arr;
11402
11413
  };
11403
- var slicy = function slicy2(arrLike, offset) {
11414
+ var slicy = function slicy(arrLike, offset) {
11404
11415
  var arr = [];
11405
11416
  for (var i = offset || 0, j = 0;i < arrLike.length; i += 1, j += 1) {
11406
11417
  arr[j] = arrLike[i];
@@ -11417,7 +11428,7 @@ var require_implementation = __commonJS((exports, module) => {
11417
11428
  }
11418
11429
  return str;
11419
11430
  };
11420
- module.exports = function bind2(that) {
11431
+ module.exports = function bind(that) {
11421
11432
  var target = this;
11422
11433
  if (typeof target !== "function" || toStr.apply(target) !== funcType) {
11423
11434
  throw new TypeError(ERROR_MESSAGE + target);
@@ -11441,7 +11452,7 @@ var require_implementation = __commonJS((exports, module) => {
11441
11452
  }
11442
11453
  bound = Function("binder", "return function (" + joiny(boundArgs, ",") + "){ return binder.apply(this,arguments); }")(binder);
11443
11454
  if (target.prototype) {
11444
- var Empty = function Empty2() {};
11455
+ var Empty = function Empty() {};
11445
11456
  Empty.prototype = target.prototype;
11446
11457
  bound.prototype = new Empty;
11447
11458
  Empty.prototype = null;
@@ -11680,7 +11691,7 @@ var require_get_intrinsic = __commonJS((exports, module) => {
11680
11691
  }
11681
11692
  }
11682
11693
  var errorProto;
11683
- var doEval = function doEval2(name) {
11694
+ var doEval = function doEval(name) {
11684
11695
  var value;
11685
11696
  if (name === "%AsyncFunction%") {
11686
11697
  value = getEvalledConstructor("async function () {}");
@@ -11689,12 +11700,12 @@ var require_get_intrinsic = __commonJS((exports, module) => {
11689
11700
  } else if (name === "%AsyncGeneratorFunction%") {
11690
11701
  value = getEvalledConstructor("async function* () {}");
11691
11702
  } else if (name === "%AsyncGenerator%") {
11692
- var fn = doEval2("%AsyncGeneratorFunction%");
11703
+ var fn = doEval("%AsyncGeneratorFunction%");
11693
11704
  if (fn) {
11694
11705
  value = fn.prototype;
11695
11706
  }
11696
11707
  } else if (name === "%AsyncIteratorPrototype%") {
11697
- var gen = doEval2("%AsyncGenerator%");
11708
+ var gen = doEval("%AsyncGenerator%");
11698
11709
  if (gen && getProto) {
11699
11710
  value = getProto(gen.prototype);
11700
11711
  }
@@ -11765,7 +11776,7 @@ var require_get_intrinsic = __commonJS((exports, module) => {
11765
11776
  var $exec = bind2.call($call, RegExp.prototype.exec);
11766
11777
  var rePropName = /[^%.[\]]+|\[(?:(-?\d+(?:\.\d+)?)|(["'])((?:(?!\2)[^\\]|\\.)*?)\2)\]|(?=(?:\.|\[\])(?:\.|\[\]|%$))/g;
11767
11778
  var reEscapeChar = /\\(\\)?/g;
11768
- var stringToPath = function stringToPath2(string) {
11779
+ var stringToPath = function stringToPath(string) {
11769
11780
  var first = $strSlice(string, 0, 1);
11770
11781
  var last = $strSlice(string, -1);
11771
11782
  if (first === "%" && last !== "%") {
@@ -11779,7 +11790,7 @@ var require_get_intrinsic = __commonJS((exports, module) => {
11779
11790
  });
11780
11791
  return result;
11781
11792
  };
11782
- var getBaseIntrinsic = function getBaseIntrinsic2(name, allowMissing) {
11793
+ var getBaseIntrinsic = function getBaseIntrinsic(name, allowMissing) {
11783
11794
  var intrinsicName = name;
11784
11795
  var alias;
11785
11796
  if (hasOwn(LEGACY_ALIASES, intrinsicName)) {
@@ -15954,7 +15965,7 @@ var require_lodash = __commonJS((exports, module) => {
15954
15965
  function unicodeWords(string) {
15955
15966
  return string.match(reUnicodeWord) || [];
15956
15967
  }
15957
- var runInContext = function runInContext2(context) {
15968
+ var runInContext = function runInContext(context) {
15958
15969
  context = context == null ? root : _.defaults(root.Object(), context, _.pick(root, contextProps));
15959
15970
  var { Array: Array2, Date: Date2, Error: Error2, Function: Function2, Math: Math2, Object: Object2, RegExp: RegExp2, String: String2, TypeError: TypeError2 } = context;
15960
15971
  var arrayProto = Array2.prototype, funcProto = Function2.prototype, objectProto = Object2.prototype;
@@ -20467,7 +20478,7 @@ __p += '`;
20467
20478
  lodash.replace = replace;
20468
20479
  lodash.result = result;
20469
20480
  lodash.round = round;
20470
- lodash.runInContext = runInContext2;
20481
+ lodash.runInContext = runInContext;
20471
20482
  lodash.sample = sample2;
20472
20483
  lodash.size = size;
20473
20484
  lodash.snakeCase = snakeCase;
@@ -29121,7 +29132,7 @@ var require_multicast = __commonJS((exports) => {
29121
29132
  if (typeof subjectOrSubjectFactory === "function") {
29122
29133
  subjectFactory = subjectOrSubjectFactory;
29123
29134
  } else {
29124
- subjectFactory = function subjectFactory2() {
29135
+ subjectFactory = function subjectFactory() {
29125
29136
  return subjectOrSubjectFactory;
29126
29137
  };
29127
29138
  }
@@ -32592,7 +32603,7 @@ var require_signal_exit = __commonJS((exports, module) => {
32592
32603
  emitter.on(ev, cb);
32593
32604
  return remove;
32594
32605
  };
32595
- unload = function unload2() {
32606
+ unload = function unload() {
32596
32607
  if (!loaded || !processOk(global.process)) {
32597
32608
  return;
32598
32609
  }
@@ -32607,7 +32618,7 @@ var require_signal_exit = __commonJS((exports, module) => {
32607
32618
  emitter.count -= 1;
32608
32619
  };
32609
32620
  module.exports.unload = unload;
32610
- emit = function emit2(event, code, signal) {
32621
+ emit = function emit(event, code, signal) {
32611
32622
  if (emitter.emitted[event]) {
32612
32623
  return;
32613
32624
  }
@@ -32636,7 +32647,7 @@ var require_signal_exit = __commonJS((exports, module) => {
32636
32647
  return signals;
32637
32648
  };
32638
32649
  loaded = false;
32639
- load = function load2() {
32650
+ load = function load() {
32640
32651
  if (loaded || !processOk(global.process)) {
32641
32652
  return;
32642
32653
  }
@@ -32655,7 +32666,7 @@ var require_signal_exit = __commonJS((exports, module) => {
32655
32666
  };
32656
32667
  module.exports.load = load;
32657
32668
  originalProcessReallyExit = process3.reallyExit;
32658
- processReallyExit = function processReallyExit2(code) {
32669
+ processReallyExit = function processReallyExit(code) {
32659
32670
  if (!processOk(global.process)) {
32660
32671
  return;
32661
32672
  }
@@ -32665,7 +32676,7 @@ var require_signal_exit = __commonJS((exports, module) => {
32665
32676
  originalProcessReallyExit.call(process3, process3.exitCode);
32666
32677
  };
32667
32678
  originalProcessEmit = process3.emit;
32668
- processEmit = function processEmit2(ev, arg) {
32679
+ processEmit = function processEmit(ev, arg) {
32669
32680
  if (ev === "exit" && processOk(global.process)) {
32670
32681
  if (arg !== undefined) {
32671
32682
  process3.exitCode = arg;
@@ -42622,7 +42633,7 @@ var require_lib = __commonJS((exports, module) => {
42622
42633
  iconv.encodings = null;
42623
42634
  iconv.defaultCharUnicode = "\uFFFD";
42624
42635
  iconv.defaultCharSingleByte = "?";
42625
- iconv.encode = function encode3(str, encoding, options) {
42636
+ iconv.encode = function encode(str, encoding, options) {
42626
42637
  str = "" + (str || "");
42627
42638
  var encoder = iconv.getEncoder(encoding, options);
42628
42639
  var res = encoder.write(str);
@@ -44099,9 +44110,7 @@ class Container {
44099
44110
  services = new Map;
44100
44111
  static instance = null;
44101
44112
  static getInstance() {
44102
- if (!Container.instance) {
44103
- Container.instance = new Container;
44104
- }
44113
+ Container.instance ??= new Container;
44105
44114
  return Container.instance;
44106
44115
  }
44107
44116
  static reset() {
@@ -44446,14 +44455,14 @@ class ContextService {
44446
44455
  this.configService = configService;
44447
44456
  }
44448
44457
  parseRemoteUrl(url) {
44449
- const sshMatch = url.match(/git@bitbucket\.org:([^/]+)\/([^.]+)(?:\.git)?/);
44458
+ const sshMatch = new RegExp(/git@bitbucket\.org:([^/]+)\/([^.]+)(?:\.git)?/).exec(url);
44450
44459
  if (sshMatch) {
44451
44460
  return {
44452
44461
  workspace: sshMatch[1],
44453
44462
  repoSlug: sshMatch[2]
44454
44463
  };
44455
44464
  }
44456
- const httpsMatch = url.match(/https?:\/\/(?:[^@]+@)?bitbucket\.org\/([^/]+)\/([^/.]+)(?:\.git)?/);
44465
+ const httpsMatch = new RegExp(/https?:\/\/(?:[^@]+@)?bitbucket\.org\/([^/]+)\/([^/.]+)(?:\.git)?/).exec(url);
44457
44466
  if (httpsMatch) {
44458
44467
  return {
44459
44468
  workspace: httpsMatch[1],
@@ -45069,7 +45078,126 @@ class OutputService {
45069
45078
  bold(text) {
45070
45079
  return this.format(text, source_default.bold);
45071
45080
  }
45081
+ red(text) {
45082
+ return this.format(text, source_default.red);
45083
+ }
45084
+ green(text) {
45085
+ return this.format(text, source_default.green);
45086
+ }
45087
+ yellow(text) {
45088
+ return this.format(text, source_default.yellow);
45089
+ }
45090
+ cyan(text) {
45091
+ return this.format(text, source_default.cyan);
45092
+ }
45093
+ magenta(text) {
45094
+ return this.format(text, source_default.magenta);
45095
+ }
45096
+ gray(text) {
45097
+ return this.format(text, source_default.gray);
45098
+ }
45099
+ blue(text) {
45100
+ return this.format(text, source_default.blue);
45101
+ }
45102
+ underline(text) {
45103
+ return this.format(text, source_default.underline);
45104
+ }
45105
+ }
45106
+ // src/types/config.ts
45107
+ var SETTABLE_CONFIG_KEYS = [
45108
+ "defaultWorkspace",
45109
+ "skipVersionCheck",
45110
+ "versionCheckInterval"
45111
+ ];
45112
+ var READABLE_CONFIG_KEYS = [
45113
+ "username",
45114
+ "defaultWorkspace",
45115
+ "skipVersionCheck",
45116
+ "versionCheckInterval"
45117
+ ];
45118
+ function isSettableConfigKey(key) {
45119
+ return SETTABLE_CONFIG_KEYS.includes(key);
45120
+ }
45121
+ function isReadableConfigKey(key) {
45122
+ return READABLE_CONFIG_KEYS.includes(key);
45123
+ }
45124
+ function parseBooleanLiteral(value) {
45125
+ const normalized = value.trim().toLowerCase();
45126
+ if (normalized === "true") {
45127
+ return true;
45128
+ }
45129
+ if (normalized === "false") {
45130
+ return false;
45131
+ }
45132
+ return;
45133
+ }
45134
+ function parsePositiveIntegerLiteral(value) {
45135
+ const normalized = value.trim();
45136
+ if (!/^[1-9]\d*$/.test(normalized)) {
45137
+ return;
45138
+ }
45139
+ const parsed = Number.parseInt(normalized, 10);
45140
+ if (!Number.isSafeInteger(parsed)) {
45141
+ return;
45142
+ }
45143
+ return parsed;
45144
+ }
45145
+ function parseSettableConfigValue(key, value) {
45146
+ switch (key) {
45147
+ case "defaultWorkspace":
45148
+ return value;
45149
+ case "skipVersionCheck": {
45150
+ const parsed = parseBooleanLiteral(value);
45151
+ if (parsed === undefined) {
45152
+ throw new Error("Invalid value for 'skipVersionCheck'. Expected 'true' or 'false'.");
45153
+ }
45154
+ return parsed;
45155
+ }
45156
+ case "versionCheckInterval": {
45157
+ const parsed = parsePositiveIntegerLiteral(value);
45158
+ if (parsed === undefined) {
45159
+ throw new Error("Invalid value for 'versionCheckInterval'. Expected a positive integer (1 or greater).");
45160
+ }
45161
+ return parsed;
45162
+ }
45163
+ }
45164
+ }
45165
+ function coerceSkipVersionCheckValue(value) {
45166
+ if (typeof value === "boolean") {
45167
+ return value;
45168
+ }
45169
+ if (typeof value === "string") {
45170
+ return parseBooleanLiteral(value);
45171
+ }
45172
+ return;
45173
+ }
45174
+ function coerceVersionCheckIntervalValue(value) {
45175
+ if (typeof value === "number") {
45176
+ if (!Number.isSafeInteger(value) || value < 1) {
45177
+ return;
45178
+ }
45179
+ return value;
45180
+ }
45181
+ if (typeof value === "string") {
45182
+ return parsePositiveIntegerLiteral(value);
45183
+ }
45184
+ return;
45185
+ }
45186
+ function normalizeReadableConfigValue(key, value) {
45187
+ if (value === undefined || value === null) {
45188
+ return;
45189
+ }
45190
+ switch (key) {
45191
+ case "skipVersionCheck":
45192
+ return coerceSkipVersionCheckValue(value);
45193
+ case "versionCheckInterval":
45194
+ return coerceVersionCheckIntervalValue(value);
45195
+ case "username":
45196
+ case "defaultWorkspace":
45197
+ return typeof value === "string" ? value : undefined;
45198
+ }
45072
45199
  }
45200
+
45073
45201
  // src/services/version.service.ts
45074
45202
  var NPM_REGISTRY_URL = "https://registry.npmjs.org/@pilatos/bitbucket-cli";
45075
45203
  var PACKAGE_NAME = "@pilatos/bitbucket-cli";
@@ -45082,7 +45210,8 @@ class VersionService {
45082
45210
  this.currentVersion = currentVersion;
45083
45211
  }
45084
45212
  async checkForUpdate() {
45085
- const skipCheck = await this.configService.getValue("skipVersionCheck");
45213
+ const skipCheckRaw = await this.configService.getValue("skipVersionCheck");
45214
+ const skipCheck = coerceSkipVersionCheckValue(skipCheckRaw);
45086
45215
  if (skipCheck === true) {
45087
45216
  return null;
45088
45217
  }
@@ -45115,7 +45244,7 @@ class VersionService {
45115
45244
  const now = new Date;
45116
45245
  const timeSinceLastCheck = now.getTime() - lastCheckDate.getTime();
45117
45246
  const intervalDays = await this.configService.getValue("versionCheckInterval");
45118
- const days = typeof intervalDays === "number" ? intervalDays : 1;
45247
+ const days = coerceVersionCheckIntervalValue(intervalDays) ?? 1;
45119
45248
  const intervalMs = days * 24 * 60 * 60 * 1000;
45120
45249
  return timeSinceLastCheck >= intervalMs;
45121
45250
  }
@@ -45158,7 +45287,7 @@ class VersionService {
45158
45287
  const cleanVersion = version.replace(/^v/, "");
45159
45288
  return cleanVersion.split(".").map((part) => {
45160
45289
  const numPart = part.split("-")[0];
45161
- return parseInt(numPart, 10) || 0;
45290
+ return Number.parseInt(numPart, 10) || 0;
45162
45291
  });
45163
45292
  };
45164
45293
  const newParts = parseVersion(newVersion);
@@ -51476,6 +51605,14 @@ class BaseCommand {
51476
51605
  constructor(output) {
51477
51606
  this.output = output;
51478
51607
  }
51608
+ async run(options, context) {
51609
+ try {
51610
+ return await this.execute(options, context);
51611
+ } catch (error) {
51612
+ this.handleError(error, context);
51613
+ throw error;
51614
+ }
51615
+ }
51479
51616
  handleError(error, context) {
51480
51617
  if (error instanceof Error) {
51481
51618
  this.output.error(error.message);
@@ -51512,24 +51649,30 @@ class LoginCommand extends BaseCommand {
51512
51649
  const username = options.username || process.env.BB_USERNAME;
51513
51650
  const apiToken = options.password || process.env.BB_API_TOKEN;
51514
51651
  if (!username) {
51515
- const error = new Error("Username is required. Use --username option or set BB_USERNAME environment variable.");
51516
- this.output.error(error.message);
51517
- throw error;
51652
+ throw new Error("Username is required. Use --username option or set BB_USERNAME environment variable.");
51518
51653
  }
51519
51654
  if (!apiToken) {
51520
- const error = new Error("API token is required. Use --password option or set BB_API_TOKEN environment variable.");
51521
- this.output.error(error.message);
51522
- throw error;
51655
+ throw new Error("API token is required. Use --password option or set BB_API_TOKEN environment variable.");
51523
51656
  }
51524
51657
  await this.configService.setCredentials({ username, apiToken });
51525
51658
  try {
51526
51659
  const response = await this.usersApi.userGet();
51527
51660
  const user = response.data;
51661
+ if (context.globalOptions.json) {
51662
+ this.output.json({
51663
+ authenticated: true,
51664
+ user: {
51665
+ username: user.username,
51666
+ displayName: user.display_name,
51667
+ accountId: user.account_id
51668
+ }
51669
+ });
51670
+ return;
51671
+ }
51528
51672
  this.output.success(`Logged in as ${user.display_name} (${user.username})`);
51529
51673
  } catch (error) {
51530
51674
  await this.configService.clearConfig();
51531
- this.output.error(`Authentication failed: ${error instanceof Error ? error.message : String(error)}`);
51532
- throw error;
51675
+ throw new Error(`Authentication failed: ${error instanceof Error ? error.message : String(error)}`);
51533
51676
  }
51534
51677
  }
51535
51678
  }
@@ -51543,8 +51686,12 @@ class LogoutCommand extends BaseCommand {
51543
51686
  super(output);
51544
51687
  this.configService = configService;
51545
51688
  }
51546
- async execute(_options, _context) {
51689
+ async execute(_options, context) {
51547
51690
  await this.configService.clearConfig();
51691
+ if (context.globalOptions.json) {
51692
+ this.output.json({ authenticated: false, success: true });
51693
+ return;
51694
+ }
51548
51695
  this.output.success("Logged out of Bitbucket");
51549
51696
  }
51550
51697
  }
@@ -51563,24 +51710,38 @@ class StatusCommand extends BaseCommand {
51563
51710
  async execute(_options, context) {
51564
51711
  const config = await this.configService.getConfig();
51565
51712
  if (!config.username || !config.apiToken) {
51713
+ if (context.globalOptions.json) {
51714
+ this.output.json({ authenticated: false });
51715
+ return;
51716
+ }
51566
51717
  this.output.info("Not logged in");
51567
- this.output.text(`Run ${source_default.cyan("bb auth login")} to authenticate.`);
51718
+ this.output.text(`Run ${this.output.highlight("bb auth login")} to authenticate.`);
51568
51719
  return;
51569
51720
  }
51570
51721
  try {
51571
51722
  const response = await this.usersApi.userGet();
51572
51723
  const user = response.data;
51724
+ if (context.globalOptions.json) {
51725
+ this.output.json({
51726
+ authenticated: true,
51727
+ user: {
51728
+ username: user.username,
51729
+ displayName: user.display_name,
51730
+ accountId: user.account_id
51731
+ },
51732
+ defaultWorkspace: config.defaultWorkspace
51733
+ });
51734
+ return;
51735
+ }
51573
51736
  this.output.success("Logged in to Bitbucket");
51574
- this.output.text(` Username: ${source_default.cyan(user.username)}`);
51737
+ this.output.text(` Username: ${this.output.highlight(user.username ?? "")}`);
51575
51738
  this.output.text(` Display name: ${user.display_name}`);
51576
51739
  this.output.text(` Account ID: ${user.account_id}`);
51577
51740
  if (config.defaultWorkspace) {
51578
- this.output.text(` Default workspace: ${source_default.cyan(config.defaultWorkspace)}`);
51741
+ this.output.text(` Default workspace: ${this.output.highlight(config.defaultWorkspace)}`);
51579
51742
  }
51580
51743
  } catch (error) {
51581
- this.output.error("Authentication is invalid or expired");
51582
- this.output.text(`Run ${source_default.cyan("bb auth login")} to re-authenticate.`);
51583
- throw error;
51744
+ throw new Error(`Authentication is invalid or expired. Run ${this.output.highlight("bb auth login")} to re-authenticate.`);
51584
51745
  }
51585
51746
  }
51586
51747
  }
@@ -51594,14 +51755,16 @@ class TokenCommand extends BaseCommand {
51594
51755
  super(output);
51595
51756
  this.configService = configService;
51596
51757
  }
51597
- async execute(_options, _context) {
51758
+ async execute(_options, context) {
51598
51759
  const credentials = await this.configService.getCredentials();
51599
51760
  if (!credentials.username || !credentials.apiToken) {
51600
- const error = new Error("Not authenticated. Run 'bb auth login' first.");
51601
- this.output.error(error.message);
51602
- throw error;
51761
+ throw new Error("Not authenticated. Run 'bb auth login' first.");
51603
51762
  }
51604
51763
  const token = Buffer.from(`${credentials.username}:${credentials.apiToken}`).toString("base64");
51764
+ if (context.globalOptions.json) {
51765
+ this.output.json({ token });
51766
+ return;
51767
+ }
51605
51768
  this.output.text(token);
51606
51769
  }
51607
51770
  }
@@ -51622,6 +51785,15 @@ class CloneCommand extends BaseCommand {
51622
51785
  const repoUrl = await this.resolveRepositoryUrl(repository);
51623
51786
  await this.gitService.clone(repoUrl, directory);
51624
51787
  const targetDir = directory || this.extractRepoName(repository);
51788
+ if (context.globalOptions.json) {
51789
+ this.output.json({
51790
+ success: true,
51791
+ repository,
51792
+ path: targetDir,
51793
+ cloneUrl: repoUrl
51794
+ });
51795
+ return;
51796
+ }
51625
51797
  this.output.success(`Cloned ${repository} into ${targetDir}`);
51626
51798
  }
51627
51799
  async resolveRepositoryUrl(repository) {
@@ -51648,7 +51820,10 @@ class CloneCommand extends BaseCommand {
51648
51820
  }
51649
51821
  extractRepoName(repository) {
51650
51822
  const parts = repository.split("/");
51651
- const lastPart = parts[parts.length - 1];
51823
+ const lastPart = parts.at(-1);
51824
+ if (!lastPart) {
51825
+ throw new Error("Invalid repository format.");
51826
+ }
51652
51827
  return lastPart.replace(".git", "");
51653
51828
  }
51654
51829
  }
@@ -51680,22 +51855,21 @@ class CreateRepoCommand extends BaseCommand {
51680
51855
  if (project) {
51681
51856
  request.project = { type: "project", key: project };
51682
51857
  }
51683
- try {
51684
- const response = await this.repositoriesApi.repositoriesWorkspaceRepoSlugPost({
51685
- workspace,
51686
- repoSlug: name,
51687
- body: request
51688
- });
51689
- const repo = response.data;
51690
- this.output.success(`Created repository ${repo.full_name}`);
51691
- this.output.text(` ${source_default.dim("URL:")} ${repo.links?.html?.href}`);
51692
- const sshClone = Array.from(repo.links?.clone ?? []).find((c) => c.name === "ssh");
51693
- if (sshClone?.href) {
51694
- this.output.text(` ${source_default.dim("Clone:")} git clone ${sshClone.href}`);
51695
- }
51696
- } catch (error) {
51697
- this.handleError(error, context);
51698
- throw error;
51858
+ const response = await this.repositoriesApi.repositoriesWorkspaceRepoSlugPost({
51859
+ workspace,
51860
+ repoSlug: name,
51861
+ body: request
51862
+ });
51863
+ const repo = response.data;
51864
+ if (context.globalOptions.json) {
51865
+ this.output.json(repo);
51866
+ return;
51867
+ }
51868
+ this.output.success(`Created repository ${repo.full_name}`);
51869
+ this.output.text(` ${this.output.dim("URL:")} ${repo.links?.html?.href}`);
51870
+ const sshClone = Array.from(repo.links?.clone ?? []).find((c) => c.name === "ssh");
51871
+ if (sshClone?.href) {
51872
+ this.output.text(` ${this.output.dim("Clone:")} git clone ${sshClone.href}`);
51699
51873
  }
51700
51874
  }
51701
51875
  async resolveWorkspace(workspace) {
@@ -51722,27 +51896,30 @@ class ListReposCommand extends BaseCommand {
51722
51896
  this.configService = configService;
51723
51897
  }
51724
51898
  async execute(options, context) {
51725
- const workspace = await this.resolveWorkspace(options.workspace);
51726
- const limit = parseInt(options.limit || "25", 10);
51727
- try {
51728
- const response = await this.repositoriesApi.repositoriesWorkspaceGet({
51729
- workspace
51899
+ const workspace = await this.resolveWorkspace(options.workspace ?? context.globalOptions.workspace);
51900
+ const limit = Number.parseInt(options.limit || "25", 10);
51901
+ const response = await this.repositoriesApi.repositoriesWorkspaceGet({
51902
+ workspace
51903
+ });
51904
+ const repos = Array.from(response.data.values ?? []).slice(0, limit);
51905
+ if (context.globalOptions.json) {
51906
+ this.output.json({
51907
+ workspace,
51908
+ count: repos.length,
51909
+ repositories: repos
51730
51910
  });
51731
- const repos = Array.from(response.data.values ?? []).slice(0, limit);
51732
- if (repos.length === 0) {
51733
- this.output.text("No repositories found");
51734
- return;
51735
- }
51736
- const rows = repos.map((repo) => [
51737
- repo.full_name ?? "",
51738
- repo.is_private ? "private" : "public",
51739
- (repo.description || "").substring(0, 50)
51740
- ]);
51741
- this.output.table(["REPOSITORY", "VISIBILITY", "DESCRIPTION"], rows);
51742
- } catch (error) {
51743
- this.handleError(error, context);
51744
- throw error;
51911
+ return;
51912
+ }
51913
+ if (repos.length === 0) {
51914
+ this.output.text("No repositories found");
51915
+ return;
51745
51916
  }
51917
+ const rows = repos.map((repo) => [
51918
+ repo.full_name ?? "",
51919
+ repo.is_private ? "private" : "public",
51920
+ (repo.description || "").substring(0, 50)
51921
+ ]);
51922
+ this.output.table(["REPOSITORY", "VISIBILITY", "DESCRIPTION"], rows);
51746
51923
  }
51747
51924
  async resolveWorkspace(workspace) {
51748
51925
  if (workspace) {
@@ -51779,36 +51956,35 @@ class ViewRepoCommand extends BaseCommand {
51779
51956
  }
51780
51957
  }
51781
51958
  const repoContext = await this.contextService.requireRepoContext(contextOptions);
51782
- try {
51783
- const response = await this.repositoriesApi.repositoriesWorkspaceRepoSlugGet({
51784
- workspace: repoContext.workspace,
51785
- repoSlug: repoContext.repoSlug
51786
- });
51787
- const repo = response.data;
51788
- this.output.text(source_default.bold(repo.full_name ?? ""));
51789
- if (repo.description) {
51790
- this.output.text(source_default.dim(repo.description));
51791
- }
51792
- this.output.text("");
51793
- this.output.text(` ${source_default.dim("Visibility:")} ${repo.is_private ? "Private" : "Public"}`);
51794
- this.output.text(` ${source_default.dim("Owner:")} ${repo.owner?.display_name ?? "Unknown"}`);
51795
- if (repo.language) {
51796
- this.output.text(` ${source_default.dim("Language:")} ${repo.language}`);
51797
- }
51798
- if (repo.mainbranch) {
51799
- this.output.text(` ${source_default.dim("Default branch:")} ${repo.mainbranch.name}`);
51800
- }
51801
- this.output.text(` ${source_default.dim("Created:")} ${this.output.formatDate(repo.created_on ?? "")}`);
51802
- this.output.text(` ${source_default.dim("Updated:")} ${this.output.formatDate(repo.updated_on ?? "")}`);
51803
- this.output.text("");
51804
- this.output.text(` ${source_default.dim("URL:")} ${repo.links?.html?.href}`);
51805
- const sshClone = Array.from(repo.links?.clone ?? []).find((c) => c.name === "ssh");
51806
- if (sshClone?.href) {
51807
- this.output.text(` ${source_default.dim("SSH:")} ${sshClone.href}`);
51808
- }
51809
- } catch (error) {
51810
- this.handleError(error, context);
51811
- throw error;
51959
+ const response = await this.repositoriesApi.repositoriesWorkspaceRepoSlugGet({
51960
+ workspace: repoContext.workspace,
51961
+ repoSlug: repoContext.repoSlug
51962
+ });
51963
+ const repo = response.data;
51964
+ if (context.globalOptions.json) {
51965
+ this.output.json(repo);
51966
+ return;
51967
+ }
51968
+ this.output.text(this.output.bold(repo.full_name ?? ""));
51969
+ if (repo.description) {
51970
+ this.output.text(this.output.dim(repo.description));
51971
+ }
51972
+ this.output.text("");
51973
+ this.output.text(` ${this.output.dim("Visibility:")} ${repo.is_private ? "Private" : "Public"}`);
51974
+ this.output.text(` ${this.output.dim("Owner:")} ${repo.owner?.display_name ?? "Unknown"}`);
51975
+ if (repo.language) {
51976
+ this.output.text(` ${this.output.dim("Language:")} ${repo.language}`);
51977
+ }
51978
+ if (repo.mainbranch) {
51979
+ this.output.text(` ${this.output.dim("Default branch:")} ${repo.mainbranch.name}`);
51980
+ }
51981
+ this.output.text(` ${this.output.dim("Created:")} ${this.output.formatDate(repo.created_on ?? "")}`);
51982
+ this.output.text(` ${this.output.dim("Updated:")} ${this.output.formatDate(repo.updated_on ?? "")}`);
51983
+ this.output.text("");
51984
+ this.output.text(` ${this.output.dim("URL:")} ${repo.links?.html?.href}`);
51985
+ const sshClone = Array.from(repo.links?.clone ?? []).find((c) => c.name === "ssh");
51986
+ if (sshClone?.href) {
51987
+ this.output.text(` ${this.output.dim("SSH:")} ${sshClone.href}`);
51812
51988
  }
51813
51989
  }
51814
51990
  }
@@ -51836,24 +52012,22 @@ class DeleteRepoCommand extends BaseCommand {
51836
52012
  }
51837
52013
  const repoContext = await this.contextService.requireRepoContext(contextOptions);
51838
52014
  if (!yes) {
51839
- const error = new Error(`This will permanently delete ${repoContext.workspace}/${repoContext.repoSlug}.
52015
+ throw new Error(`This will permanently delete ${repoContext.workspace}/${repoContext.repoSlug}.
51840
52016
  ` + "Use --yes to confirm deletion.");
51841
- this.output.error(error.message);
51842
- if (true) {
51843
- process.exitCode = 1;
51844
- }
51845
- throw error;
51846
52017
  }
51847
- try {
51848
- await this.repositoriesApi.repositoriesWorkspaceRepoSlugDelete({
52018
+ await this.repositoriesApi.repositoriesWorkspaceRepoSlugDelete({
52019
+ workspace: repoContext.workspace,
52020
+ repoSlug: repoContext.repoSlug
52021
+ });
52022
+ if (context.globalOptions.json) {
52023
+ this.output.json({
52024
+ success: true,
51849
52025
  workspace: repoContext.workspace,
51850
52026
  repoSlug: repoContext.repoSlug
51851
52027
  });
51852
- this.output.success(`Deleted repository ${repoContext.workspace}/${repoContext.repoSlug}`);
51853
- } catch (error) {
51854
- this.handleError(error, context);
51855
- throw error;
52028
+ return;
51856
52029
  }
52030
+ this.output.success(`Deleted repository ${repoContext.workspace}/${repoContext.repoSlug}`);
51857
52031
  }
51858
52032
  }
51859
52033
 
@@ -51872,11 +52046,7 @@ class CreatePRCommand extends BaseCommand {
51872
52046
  }
51873
52047
  async execute(options, context) {
51874
52048
  if (!options.title) {
51875
- this.output.error("Pull request title is required. Use --title option.");
51876
- if (true) {
51877
- process.exitCode = 1;
51878
- }
51879
- throw new Error("Pull request title is required");
52049
+ throw new Error("Pull request title is required. Use --title option.");
51880
52050
  }
51881
52051
  const repoContext = await this.contextService.requireRepoContext({
51882
52052
  ...context.globalOptions,
@@ -51906,21 +52076,20 @@ class CreatePRCommand extends BaseCommand {
51906
52076
  if (options.draft) {
51907
52077
  request.draft = true;
51908
52078
  }
51909
- try {
51910
- const response = await this.pullrequestsApi.repositoriesWorkspaceRepoSlugPullrequestsPost({
51911
- workspace: repoContext.workspace,
51912
- repoSlug: repoContext.repoSlug,
51913
- body: request
51914
- });
51915
- const pr = response.data;
51916
- const links = pr.links;
51917
- this.output.success(`Created pull request #${pr.id}`);
51918
- this.output.text(` ${source_default.dim("Title:")} ${pr.title}`);
51919
- this.output.text(` ${source_default.dim("URL:")} ${links?.html?.href}`);
51920
- } catch (error) {
51921
- this.handleError(error, context);
51922
- throw error;
52079
+ const response = await this.pullrequestsApi.repositoriesWorkspaceRepoSlugPullrequestsPost({
52080
+ workspace: repoContext.workspace,
52081
+ repoSlug: repoContext.repoSlug,
52082
+ body: request
52083
+ });
52084
+ const pr = response.data;
52085
+ const links = pr.links;
52086
+ if (context.globalOptions.json) {
52087
+ this.output.json(pr);
52088
+ return;
51923
52089
  }
52090
+ this.output.success(`Created pull request #${pr.id}`);
52091
+ this.output.text(` ${this.output.dim("Title:")} ${pr.title}`);
52092
+ this.output.text(` ${this.output.dim("URL:")} ${links?.html?.href}`);
51924
52093
  }
51925
52094
  }
51926
52095
 
@@ -51941,34 +52110,39 @@ class ListPRsCommand extends BaseCommand {
51941
52110
  ...options
51942
52111
  });
51943
52112
  const state = options.state || "OPEN";
51944
- try {
51945
- const response = await this.pullrequestsApi.repositoriesWorkspaceRepoSlugPullrequestsGet({
52113
+ const response = await this.pullrequestsApi.repositoriesWorkspaceRepoSlugPullrequestsGet({
52114
+ workspace: repoContext.workspace,
52115
+ repoSlug: repoContext.repoSlug,
52116
+ state
52117
+ });
52118
+ const data = response.data;
52119
+ const values = data.values ? Array.from(data.values) : [];
52120
+ if (context.globalOptions.json) {
52121
+ this.output.json({
51946
52122
  workspace: repoContext.workspace,
51947
52123
  repoSlug: repoContext.repoSlug,
51948
- state
51949
- });
51950
- const data = response.data;
51951
- const values = data.values ? Array.from(data.values) : [];
51952
- if (values.length === 0) {
51953
- this.output.text(`No ${state.toLowerCase()} pull requests found`);
51954
- return;
51955
- }
51956
- const rows = values.map((pr) => {
51957
- const title = pr.draft ? `[DRAFT] ${pr.title}` : pr.title;
51958
- const source = pr.source;
51959
- const destination = pr.destination;
51960
- return [
51961
- `#${pr.id}`,
51962
- this.truncate(title ?? "", 50),
51963
- pr.author?.display_name ?? "Unknown",
51964
- `${source?.branch?.name ?? "unknown"} \u2192 ${destination?.branch?.name ?? "unknown"}`
51965
- ];
52124
+ state,
52125
+ count: values.length,
52126
+ pullRequests: values
51966
52127
  });
51967
- this.output.table(["ID", "TITLE", "AUTHOR", "BRANCHES"], rows);
51968
- } catch (error) {
51969
- this.handleError(error, context);
51970
- throw error;
52128
+ return;
51971
52129
  }
52130
+ if (values.length === 0) {
52131
+ this.output.text(`No ${state.toLowerCase()} pull requests found`);
52132
+ return;
52133
+ }
52134
+ const rows = values.map((pr) => {
52135
+ const title = pr.draft ? `[DRAFT] ${pr.title}` : pr.title;
52136
+ const source = pr.source;
52137
+ const destination = pr.destination;
52138
+ return [
52139
+ `#${pr.id}`,
52140
+ this.truncate(title ?? "", 50),
52141
+ pr.author?.display_name ?? "Unknown",
52142
+ `${source?.branch?.name ?? "unknown"} \u2192 ${destination?.branch?.name ?? "unknown"}`
52143
+ ];
52144
+ });
52145
+ this.output.table(["ID", "TITLE", "AUTHOR", "BRANCHES"], rows);
51972
52146
  }
51973
52147
  truncate(text, maxLength) {
51974
52148
  if (text.length <= maxLength) {
@@ -51994,31 +52168,30 @@ class ViewPRCommand extends BaseCommand {
51994
52168
  ...context.globalOptions,
51995
52169
  ...options
51996
52170
  });
51997
- const prId = parseInt(options.id, 10);
51998
- try {
51999
- const response = await this.pullrequestsApi.repositoriesWorkspaceRepoSlugPullrequestsPullRequestIdGet({
52000
- workspace: repoContext.workspace,
52001
- repoSlug: repoContext.repoSlug,
52002
- pullRequestId: prId
52003
- });
52004
- const pr = response.data;
52005
- this.renderHeader(pr);
52006
- this.renderDescription(pr);
52007
- this.renderBranchInfo(pr);
52008
- this.renderMetadata(pr);
52009
- this.renderReviewers(pr);
52010
- this.renderFooter(pr);
52011
- } catch (error) {
52012
- this.handleError(error, context);
52013
- throw error;
52171
+ const prId = Number.parseInt(options.id, 10);
52172
+ const response = await this.pullrequestsApi.repositoriesWorkspaceRepoSlugPullrequestsPullRequestIdGet({
52173
+ workspace: repoContext.workspace,
52174
+ repoSlug: repoContext.repoSlug,
52175
+ pullRequestId: prId
52176
+ });
52177
+ const pr = response.data;
52178
+ if (context.globalOptions.json) {
52179
+ this.output.json(pr);
52180
+ return;
52014
52181
  }
52182
+ this.renderHeader(pr);
52183
+ this.renderDescription(pr);
52184
+ this.renderBranchInfo(pr);
52185
+ this.renderMetadata(pr);
52186
+ this.renderReviewers(pr);
52187
+ this.renderFooter(pr);
52015
52188
  }
52016
52189
  renderHeader(pr) {
52017
52190
  const stateColor = this.getStateColor(pr.state);
52018
- const draftLabel = pr.draft ? source_default.yellow(" [DRAFT]") : "";
52191
+ const draftLabel = pr.draft ? this.output.yellow(" [DRAFT]") : "";
52019
52192
  this.output.text("");
52020
- this.output.text(`${source_default.bold(`#${pr.id}`)} ${pr.title}${draftLabel} ${stateColor(`[${pr.state}]`)}`);
52021
- this.output.text(source_default.gray("\u2500".repeat(60)));
52193
+ this.output.text(`${this.output.bold(`#${pr.id}`)} ${pr.title}${draftLabel} ${stateColor(`[${pr.state}]`)}`);
52194
+ this.output.text(this.output.gray("\u2500".repeat(60)));
52022
52195
  }
52023
52196
  renderDescription(pr) {
52024
52197
  if (pr.description) {
@@ -52029,75 +52202,75 @@ class ViewPRCommand extends BaseCommand {
52029
52202
  renderBranchInfo(pr) {
52030
52203
  const source = pr.source;
52031
52204
  const destination = pr.destination;
52032
- const sourceBranch = source_default.cyan(source?.branch?.name ?? "unknown");
52033
- const destBranch = source_default.cyan(destination?.branch?.name ?? "unknown");
52034
- const arrow = source_default.gray(" \u2192 ");
52035
- this.output.text(`${source_default.dim("Branch:")} ${sourceBranch}${arrow}${destBranch}`);
52205
+ const sourceBranch = this.output.cyan(source?.branch?.name ?? "unknown");
52206
+ const destBranch = this.output.cyan(destination?.branch?.name ?? "unknown");
52207
+ const arrow = this.output.gray(" \u2192 ");
52208
+ this.output.text(`${this.output.dim("Branch:")} ${sourceBranch}${arrow}${destBranch}`);
52036
52209
  if (source?.commit?.hash || destination?.commit?.hash) {
52037
- const sourceHash = source?.commit?.hash ? source_default.gray(source.commit.hash.slice(0, 7)) : source_default.gray("unknown");
52038
- const destHash = destination?.commit?.hash ? source_default.gray(destination.commit.hash.slice(0, 7)) : source_default.gray("unknown");
52039
- this.output.text(`${source_default.dim("Commits:")} ${sourceHash}${arrow}${destHash}`);
52210
+ const sourceHash = source?.commit?.hash ? this.output.gray(source.commit.hash.slice(0, 7)) : this.output.gray("unknown");
52211
+ const destHash = destination?.commit?.hash ? this.output.gray(destination.commit.hash.slice(0, 7)) : this.output.gray("unknown");
52212
+ this.output.text(`${this.output.dim("Commits:")} ${sourceHash}${arrow}${destHash}`);
52040
52213
  }
52041
52214
  }
52042
52215
  renderMetadata(pr) {
52043
- this.output.text(`${source_default.dim("Author:")} ${pr.author?.display_name ?? "Unknown"}`);
52216
+ this.output.text(`${this.output.dim("Author:")} ${pr.author?.display_name ?? "Unknown"}`);
52044
52217
  if (pr.closed_by) {
52045
52218
  const action = pr.state === "MERGED" ? "Merged" : "Closed";
52046
- this.output.text(`${source_default.dim(action + ":")} ${pr.closed_by.display_name}`);
52219
+ this.output.text(`${this.output.dim(action + ":")} ${pr.closed_by.display_name}`);
52047
52220
  }
52048
52221
  const createdOn = pr.created_on ? this.output.formatDate(pr.created_on) : "Unknown";
52049
52222
  const updatedOn = pr.updated_on ? this.output.formatDate(pr.updated_on) : "Unknown";
52050
- this.output.text(`${source_default.dim("Created:")} ${createdOn}`);
52051
- this.output.text(`${source_default.dim("Updated:")} ${updatedOn}`);
52223
+ this.output.text(`${this.output.dim("Created:")} ${createdOn}`);
52224
+ this.output.text(`${this.output.dim("Updated:")} ${updatedOn}`);
52052
52225
  const mergeCommit = pr.merge_commit;
52053
52226
  if (mergeCommit?.hash) {
52054
- this.output.text(`${source_default.dim("Merge:")} ${source_default.magenta(mergeCommit.hash.slice(0, 7))}`);
52227
+ this.output.text(`${this.output.dim("Merge:")} ${this.output.magenta(mergeCommit.hash.slice(0, 7))}`);
52055
52228
  }
52056
- const closeBranchIndicator = pr.close_source_branch ? source_default.green("\u2713") : source_default.gray("\u2717");
52057
- this.output.text(`${source_default.dim("Close Src:")} ${closeBranchIndicator} ${source_default.gray("(close source branch on merge)")}`);
52058
- this.output.text(`${source_default.dim("Activity:")} ${pr.comment_count ?? 0} comments \xB7 ${pr.task_count ?? 0} tasks`);
52229
+ const closeBranchIndicator = pr.close_source_branch ? this.output.green("\u2713") : this.output.gray("\u2717");
52230
+ this.output.text(`${this.output.dim("Close Src:")} ${closeBranchIndicator} ${this.output.gray("(close source branch on merge)")}`);
52231
+ this.output.text(`${this.output.dim("Activity:")} ${pr.comment_count ?? 0} comments \xB7 ${pr.task_count ?? 0} tasks`);
52059
52232
  }
52060
52233
  renderReviewers(pr) {
52061
52234
  const participants = pr.participants ? Array.from(pr.participants) : [];
52062
52235
  const reviewers = participants.filter((p) => p.role === "REVIEWER");
52063
52236
  if (reviewers.length === 0) {
52064
52237
  this.output.text("");
52065
- this.output.text(source_default.gray("No reviewers assigned"));
52238
+ this.output.text(this.output.gray("No reviewers assigned"));
52066
52239
  return;
52067
52240
  }
52068
52241
  this.output.text("");
52069
- this.output.text(source_default.dim("Reviewers:"));
52242
+ this.output.text(this.output.dim("Reviewers:"));
52070
52243
  for (const reviewer of reviewers) {
52071
52244
  const status = this.getReviewerStatus(reviewer);
52072
- this.output.text(` ${status.icon} ${reviewer.user?.display_name ?? "Unknown"} ${source_default.gray(status.label)}`);
52245
+ this.output.text(` ${status.icon} ${reviewer.user?.display_name ?? "Unknown"} ${this.output.gray(status.label)}`);
52073
52246
  }
52074
52247
  }
52075
52248
  getReviewerStatus(reviewer) {
52076
52249
  if (reviewer.approved) {
52077
- return { icon: source_default.green("\u2713"), label: "approved" };
52250
+ return { icon: this.output.green("\u2713"), label: "approved" };
52078
52251
  }
52079
52252
  if (reviewer.state === "changes_requested") {
52080
- return { icon: source_default.red("\u2717"), label: "changes requested" };
52253
+ return { icon: this.output.red("\u2717"), label: "changes requested" };
52081
52254
  }
52082
- return { icon: source_default.yellow("\u25CB"), label: "pending" };
52255
+ return { icon: this.output.yellow("\u25CB"), label: "pending" };
52083
52256
  }
52084
52257
  renderFooter(pr) {
52085
52258
  const links = pr.links;
52086
52259
  this.output.text("");
52087
- this.output.text(source_default.gray("\u2500".repeat(60)));
52088
- this.output.text(`${source_default.dim("URL:")} ${source_default.blue.underline(links?.html?.href ?? "")}`);
52260
+ this.output.text(this.output.gray("\u2500".repeat(60)));
52261
+ this.output.text(`${this.output.dim("URL:")} ${this.output.underline(this.output.blue(links?.html?.href ?? ""))}`);
52089
52262
  this.output.text("");
52090
52263
  }
52091
52264
  getStateColor(state) {
52092
52265
  switch (state) {
52093
52266
  case "OPEN":
52094
- return source_default.green;
52267
+ return (text) => this.output.green(text);
52095
52268
  case "MERGED":
52096
- return source_default.magenta;
52269
+ return (text) => this.output.magenta(text);
52097
52270
  case "DECLINED":
52098
- return source_default.red;
52271
+ return (text) => this.output.red(text);
52099
52272
  default:
52100
- return source_default.gray;
52273
+ return (text) => this.output.gray(text);
52101
52274
  }
52102
52275
  }
52103
52276
  }
@@ -52123,7 +52296,7 @@ class EditPRCommand extends BaseCommand {
52123
52296
  });
52124
52297
  let prId;
52125
52298
  if (options.id) {
52126
- prId = parseInt(options.id, 10);
52299
+ prId = Number.parseInt(options.id, 10);
52127
52300
  } else {
52128
52301
  const currentBranch = await this.gitService.getCurrentBranch();
52129
52302
  const prsResponse = await this.pullrequestsApi.repositoriesWorkspaceRepoSlugPullrequestsGet({
@@ -52132,17 +52305,12 @@ class EditPRCommand extends BaseCommand {
52132
52305
  state: "OPEN"
52133
52306
  });
52134
52307
  const values = prsResponse.data.values ? Array.from(prsResponse.data.values) : [];
52135
- const matchingPR = values.find((pr) => {
52136
- const source = pr.source;
52308
+ const matchingPR = values.find((pr2) => {
52309
+ const source = pr2.source;
52137
52310
  return source?.branch?.name === currentBranch;
52138
52311
  });
52139
52312
  if (!matchingPR) {
52140
- const error = new Error(`No open pull request found for current branch '${currentBranch}'. Specify a PR ID explicitly.`);
52141
- this.output.error(error.message);
52142
- if (true) {
52143
- process.exitCode = 1;
52144
- }
52145
- throw error;
52313
+ throw new Error(`No open pull request found for current branch '${currentBranch}'. Specify a PR ID explicitly.`);
52146
52314
  }
52147
52315
  prId = matchingPR.id;
52148
52316
  }
@@ -52151,21 +52319,11 @@ class EditPRCommand extends BaseCommand {
52151
52319
  try {
52152
52320
  body = fs.readFileSync(options.bodyFile, "utf-8");
52153
52321
  } catch (err) {
52154
- const error = new Error(`Failed to read file '${options.bodyFile}': ${err instanceof Error ? err.message : "Unknown error"}`);
52155
- this.output.error(error.message);
52156
- if (true) {
52157
- process.exitCode = 1;
52158
- }
52159
- throw error;
52322
+ throw new Error(`Failed to read file '${options.bodyFile}': ${err instanceof Error ? err.message : "Unknown error"}`);
52160
52323
  }
52161
52324
  }
52162
52325
  if (!options.title && !body) {
52163
- const error = new Error("At least one of --title or --body (or --body-file) is required.");
52164
- this.output.error(error.message);
52165
- if (true) {
52166
- process.exitCode = 1;
52167
- }
52168
- throw error;
52326
+ throw new Error("At least one of --title or --body (or --body-file) is required.");
52169
52327
  }
52170
52328
  const request = {
52171
52329
  type: "pullrequest"
@@ -52176,26 +52334,25 @@ class EditPRCommand extends BaseCommand {
52176
52334
  if (body) {
52177
52335
  request.description = body;
52178
52336
  }
52179
- try {
52180
- const response = await this.pullrequestsApi.repositoriesWorkspaceRepoSlugPullrequestsPullRequestIdPut({
52181
- workspace: repoContext.workspace,
52182
- repoSlug: repoContext.repoSlug,
52183
- pullRequestId: prId,
52184
- body: request
52185
- });
52186
- const pr = response.data;
52187
- const links = pr.links;
52188
- this.output.success(`Updated pull request #${pr.id}`);
52189
- this.output.text(` ${source_default.dim("Title:")} ${pr.title}`);
52190
- if (pr.description) {
52191
- const truncatedDesc = pr.description.length > 100 ? pr.description.substring(0, 100) + "..." : pr.description;
52192
- this.output.text(` ${source_default.dim("Description:")} ${truncatedDesc}`);
52193
- }
52194
- this.output.text(` ${source_default.dim("URL:")} ${links?.html?.href}`);
52195
- } catch (error) {
52196
- this.handleError(error, context);
52197
- throw error;
52337
+ const response = await this.pullrequestsApi.repositoriesWorkspaceRepoSlugPullrequestsPullRequestIdPut({
52338
+ workspace: repoContext.workspace,
52339
+ repoSlug: repoContext.repoSlug,
52340
+ pullRequestId: prId,
52341
+ body: request
52342
+ });
52343
+ const pr = response.data;
52344
+ const links = pr.links;
52345
+ if (context.globalOptions.json) {
52346
+ this.output.json(pr);
52347
+ return;
52348
+ }
52349
+ this.output.success(`Updated pull request #${pr.id}`);
52350
+ this.output.text(` ${this.output.dim("Title:")} ${pr.title}`);
52351
+ if (pr.description) {
52352
+ const truncatedDesc = pr.description.length > 100 ? pr.description.substring(0, 100) + "..." : pr.description;
52353
+ this.output.text(` ${this.output.dim("Description:")} ${truncatedDesc}`);
52198
52354
  }
52355
+ this.output.text(` ${this.output.dim("URL:")} ${links?.html?.href}`);
52199
52356
  }
52200
52357
  }
52201
52358
 
@@ -52215,7 +52372,7 @@ class MergePRCommand extends BaseCommand {
52215
52372
  ...context.globalOptions,
52216
52373
  ...options
52217
52374
  });
52218
- const prId = parseInt(options.id, 10);
52375
+ const prId = Number.parseInt(options.id, 10);
52219
52376
  const request = {
52220
52377
  type: "pullrequest_merge_parameters"
52221
52378
  };
@@ -52228,19 +52385,22 @@ class MergePRCommand extends BaseCommand {
52228
52385
  if (options.strategy) {
52229
52386
  request.merge_strategy = options.strategy;
52230
52387
  }
52231
- try {
52232
- const response = await this.pullrequestsApi.repositoriesWorkspaceRepoSlugPullrequestsPullRequestIdMergePost({
52233
- workspace: repoContext.workspace,
52234
- repoSlug: repoContext.repoSlug,
52388
+ const response = await this.pullrequestsApi.repositoriesWorkspaceRepoSlugPullrequestsPullRequestIdMergePost({
52389
+ workspace: repoContext.workspace,
52390
+ repoSlug: repoContext.repoSlug,
52391
+ pullRequestId: prId,
52392
+ body: request
52393
+ });
52394
+ const pr = response.data;
52395
+ if (context.globalOptions.json) {
52396
+ this.output.json({
52397
+ success: true,
52235
52398
  pullRequestId: prId,
52236
- body: request
52399
+ pullRequest: pr
52237
52400
  });
52238
- const pr = response.data;
52239
- this.output.success(`Merged pull request #${prId}: ${pr.title}`);
52240
- } catch (error) {
52241
- this.handleError(error, context);
52242
- throw error;
52401
+ return;
52243
52402
  }
52403
+ this.output.success(`Merged pull request #${prId}: ${pr.title}`);
52244
52404
  }
52245
52405
  }
52246
52406
 
@@ -52260,18 +52420,20 @@ class ApprovePRCommand extends BaseCommand {
52260
52420
  ...context.globalOptions,
52261
52421
  ...options
52262
52422
  });
52263
- const prId = parseInt(options.id, 10);
52264
- try {
52265
- await this.pullrequestsApi.repositoriesWorkspaceRepoSlugPullrequestsPullRequestIdApprovePost({
52266
- workspace: repoContext.workspace,
52267
- repoSlug: repoContext.repoSlug,
52423
+ const prId = Number.parseInt(options.id, 10);
52424
+ await this.pullrequestsApi.repositoriesWorkspaceRepoSlugPullrequestsPullRequestIdApprovePost({
52425
+ workspace: repoContext.workspace,
52426
+ repoSlug: repoContext.repoSlug,
52427
+ pullRequestId: prId
52428
+ });
52429
+ if (context.globalOptions.json) {
52430
+ this.output.json({
52431
+ success: true,
52268
52432
  pullRequestId: prId
52269
52433
  });
52270
- this.output.success(`Approved pull request #${prId}`);
52271
- } catch (error) {
52272
- this.handleError(error, context);
52273
- throw error;
52434
+ return;
52274
52435
  }
52436
+ this.output.success(`Approved pull request #${prId}`);
52275
52437
  }
52276
52438
  }
52277
52439
 
@@ -52291,19 +52453,22 @@ class DeclinePRCommand extends BaseCommand {
52291
52453
  ...context.globalOptions,
52292
52454
  ...options
52293
52455
  });
52294
- const prId = parseInt(options.id, 10);
52295
- try {
52296
- const response = await this.pullrequestsApi.repositoriesWorkspaceRepoSlugPullrequestsPullRequestIdDeclinePost({
52297
- workspace: repoContext.workspace,
52298
- repoSlug: repoContext.repoSlug,
52299
- pullRequestId: prId
52456
+ const prId = Number.parseInt(options.id, 10);
52457
+ const response = await this.pullrequestsApi.repositoriesWorkspaceRepoSlugPullrequestsPullRequestIdDeclinePost({
52458
+ workspace: repoContext.workspace,
52459
+ repoSlug: repoContext.repoSlug,
52460
+ pullRequestId: prId
52461
+ });
52462
+ const pr = response.data;
52463
+ if (context.globalOptions.json) {
52464
+ this.output.json({
52465
+ success: true,
52466
+ pullRequestId: prId,
52467
+ pullRequest: pr
52300
52468
  });
52301
- const pr = response.data;
52302
- this.output.success(`Declined pull request #${prId}: ${pr.title}`);
52303
- } catch (error) {
52304
- this.handleError(error, context);
52305
- throw error;
52469
+ return;
52306
52470
  }
52471
+ this.output.success(`Declined pull request #${prId}: ${pr.title}`);
52307
52472
  }
52308
52473
  }
52309
52474
 
@@ -52323,24 +52488,27 @@ class ReadyPRCommand extends BaseCommand {
52323
52488
  ...context.globalOptions,
52324
52489
  ...options
52325
52490
  });
52326
- const prId = parseInt(options.id, 10);
52327
- try {
52328
- const response = await this.pullrequestsApi.repositoriesWorkspaceRepoSlugPullrequestsPullRequestIdPut({
52329
- workspace: repoContext.workspace,
52330
- repoSlug: repoContext.repoSlug,
52491
+ const prId = Number.parseInt(options.id, 10);
52492
+ const response = await this.pullrequestsApi.repositoriesWorkspaceRepoSlugPullrequestsPullRequestIdPut({
52493
+ workspace: repoContext.workspace,
52494
+ repoSlug: repoContext.repoSlug,
52495
+ pullRequestId: prId,
52496
+ body: {
52497
+ type: "pullrequest",
52498
+ draft: false
52499
+ }
52500
+ });
52501
+ const pr = response.data;
52502
+ if (context.globalOptions.json) {
52503
+ this.output.json({
52504
+ success: true,
52331
52505
  pullRequestId: prId,
52332
- body: {
52333
- type: "pullrequest",
52334
- draft: false
52335
- }
52506
+ pullRequest: pr
52336
52507
  });
52337
- const pr = response.data;
52338
- this.output.success(`Marked pull request #${prId} as ready for review`);
52339
- this.output.text(` ${pr.title}`);
52340
- } catch (error) {
52341
- this.handleError(error, context);
52342
- throw error;
52508
+ return;
52343
52509
  }
52510
+ this.output.success(`Marked pull request #${prId} as ready for review`);
52511
+ this.output.text(` ${pr.title}`);
52344
52512
  }
52345
52513
  }
52346
52514
 
@@ -52362,32 +52530,48 @@ class CheckoutPRCommand extends BaseCommand {
52362
52530
  ...context.globalOptions,
52363
52531
  ...options
52364
52532
  });
52365
- const prId = parseInt(options.id, 10);
52533
+ const prId = Number.parseInt(options.id, 10);
52534
+ const prResponse = await this.pullrequestsApi.repositoriesWorkspaceRepoSlugPullrequestsPullRequestIdGet({
52535
+ workspace: repoContext.workspace,
52536
+ repoSlug: repoContext.repoSlug,
52537
+ pullRequestId: prId
52538
+ });
52539
+ const pr = prResponse.data;
52540
+ const branchName = pr.source?.branch?.name;
52541
+ const localBranchName = `pr-${prId}`;
52542
+ if (!branchName) {
52543
+ throw new Error("Pull request source branch not found");
52544
+ }
52545
+ await this.gitService.fetch();
52546
+ let checkedOutBranch;
52366
52547
  try {
52367
- const prResponse = await this.pullrequestsApi.repositoriesWorkspaceRepoSlugPullrequestsPullRequestIdGet({
52368
- workspace: repoContext.workspace,
52369
- repoSlug: repoContext.repoSlug,
52370
- pullRequestId: prId
52371
- });
52372
- const pr = prResponse.data;
52373
- const branchName = pr.source?.branch?.name;
52374
- const localBranchName = `pr-${prId}`;
52375
- if (!branchName) {
52376
- throw new Error("Pull request source branch not found");
52548
+ await this.gitService.checkout(branchName);
52549
+ checkedOutBranch = branchName;
52550
+ if (context.globalOptions.json) {
52551
+ this.output.json({
52552
+ success: true,
52553
+ pullRequestId: prId,
52554
+ branch: checkedOutBranch,
52555
+ pullRequest: pr
52556
+ });
52557
+ return;
52377
52558
  }
52378
- await this.gitService.fetch();
52379
- try {
52380
- await this.gitService.checkout(branchName);
52381
- this.output.success(`Checked out PR #${prId} as '${branchName}'`);
52382
- } catch {
52383
- await this.gitService.checkoutNewBranch(localBranchName, `origin/${branchName}`);
52384
- this.output.success(`Checked out PR #${prId} as '${localBranchName}'`);
52559
+ this.output.success(`Checked out PR #${prId} as '${branchName}'`);
52560
+ } catch {
52561
+ await this.gitService.checkoutNewBranch(localBranchName, `origin/${branchName}`);
52562
+ checkedOutBranch = localBranchName;
52563
+ if (context.globalOptions.json) {
52564
+ this.output.json({
52565
+ success: true,
52566
+ pullRequestId: prId,
52567
+ branch: checkedOutBranch,
52568
+ pullRequest: pr
52569
+ });
52570
+ return;
52385
52571
  }
52386
- this.output.text(` Title: ${pr.title}`);
52387
- } catch (error) {
52388
- this.handleError(error, context);
52389
- throw error;
52572
+ this.output.success(`Checked out PR #${prId} as '${localBranchName}'`);
52390
52573
  }
52574
+ this.output.text(` Title: ${pr.title}`);
52391
52575
  }
52392
52576
  }
52393
52577
 
@@ -52415,9 +52599,9 @@ class DiffPRCommand extends BaseCommand {
52415
52599
  });
52416
52600
  let prId;
52417
52601
  if (options.id) {
52418
- prId = parseInt(options.id, 10);
52419
- if (isNaN(prId)) {
52420
- throw new Error("Invalid PR ID");
52602
+ prId = Number.parseInt(options.id, 10);
52603
+ if (Number.isNaN(prId)) {
52604
+ throw new TypeError("Invalid PR ID");
52421
52605
  }
52422
52606
  } else {
52423
52607
  const currentBranch = await this.gitService.getCurrentBranch();
@@ -52433,34 +52617,58 @@ class DiffPRCommand extends BaseCommand {
52433
52617
  prId = pr.id;
52434
52618
  }
52435
52619
  if (options.web) {
52436
- const prResponse = await this.pullrequestsApi.repositoriesWorkspaceRepoSlugPullrequestsPullRequestIdGet({
52437
- workspace: repoContext.workspace,
52438
- repoSlug: repoContext.repoSlug,
52439
- pullRequestId: prId
52440
- });
52441
- const diffUrl = prResponse.data.links?.diff?.href;
52442
- if (!diffUrl) {
52443
- throw new Error("Could not get diff URL");
52620
+ const webUrl = await this.getWebDiffUrl(repoContext.workspace, repoContext.repoSlug, prId);
52621
+ if (context.globalOptions.json) {
52622
+ this.output.json({
52623
+ workspace: repoContext.workspace,
52624
+ repoSlug: repoContext.repoSlug,
52625
+ pullRequestId: prId,
52626
+ mode: "web",
52627
+ url: webUrl
52628
+ });
52629
+ return;
52444
52630
  }
52445
- const webUrl = diffUrl.replace(/api\.bitbucket\.org\/2\.0\/repositories\/(.*?)\/pullrequests\/(\d+)\/diff/, "bitbucket.org/$1/pull-requests/$2/diff");
52446
- await this.openInBrowser(webUrl, context);
52631
+ await this.openInBrowser(webUrl);
52447
52632
  return;
52448
52633
  }
52449
52634
  if (options.stat) {
52450
- await this.showStat(repoContext.workspace, repoContext.repoSlug, prId, context);
52635
+ const statResult = await this.showStat(repoContext.workspace, repoContext.repoSlug, prId, Boolean(context.globalOptions.json));
52636
+ if (context.globalOptions.json) {
52637
+ this.output.json({
52638
+ workspace: repoContext.workspace,
52639
+ repoSlug: repoContext.repoSlug,
52640
+ pullRequestId: prId,
52641
+ mode: "stat",
52642
+ ...statResult
52643
+ });
52644
+ }
52451
52645
  return;
52452
52646
  }
52453
52647
  if (options.nameOnly) {
52454
- await this.showNameOnly(repoContext.workspace, repoContext.repoSlug, prId, context);
52648
+ const files = await this.showNameOnly(repoContext.workspace, repoContext.repoSlug, prId, Boolean(context.globalOptions.json));
52649
+ if (context.globalOptions.json) {
52650
+ this.output.json({
52651
+ workspace: repoContext.workspace,
52652
+ repoSlug: repoContext.repoSlug,
52653
+ pullRequestId: prId,
52654
+ mode: "name-only",
52655
+ files
52656
+ });
52657
+ }
52455
52658
  return;
52456
52659
  }
52457
- await this.showDiff(repoContext.workspace, repoContext.repoSlug, prId, options, context);
52458
- }
52459
- async openInBrowser(url2, context) {
52660
+ const diff = await this.showDiff(repoContext.workspace, repoContext.repoSlug, prId, options, Boolean(context.globalOptions.json));
52460
52661
  if (context.globalOptions.json) {
52461
- this.output.json({ url: url2 });
52462
- return;
52662
+ this.output.json({
52663
+ workspace: repoContext.workspace,
52664
+ repoSlug: repoContext.repoSlug,
52665
+ pullRequestId: prId,
52666
+ mode: "diff",
52667
+ diff
52668
+ });
52463
52669
  }
52670
+ }
52671
+ async openInBrowser(url2) {
52464
52672
  this.output.info(`Opening ${url2} in your browser...`);
52465
52673
  const platform = process.platform;
52466
52674
  let command;
@@ -52473,7 +52681,19 @@ class DiffPRCommand extends BaseCommand {
52473
52681
  }
52474
52682
  await execAsync(command);
52475
52683
  }
52476
- async showStat(workspace, repoSlug, prId, context) {
52684
+ async getWebDiffUrl(workspace, repoSlug, prId) {
52685
+ const prResponse = await this.pullrequestsApi.repositoriesWorkspaceRepoSlugPullrequestsPullRequestIdGet({
52686
+ workspace,
52687
+ repoSlug,
52688
+ pullRequestId: prId
52689
+ });
52690
+ const diffUrl = prResponse.data.links?.diff?.href;
52691
+ if (!diffUrl) {
52692
+ throw new Error("Could not get diff URL");
52693
+ }
52694
+ return diffUrl.replace(/api\.bitbucket\.org\/2\.0\/repositories\/(.*?)\/pullrequests\/(\d+)\/diff/, "bitbucket.org/$1/pull-requests/$2/diff");
52695
+ }
52696
+ async showStat(workspace, repoSlug, prId, useJson) {
52477
52697
  const diffstatResponse = await this.pullrequestsApi.repositoriesWorkspaceRepoSlugPullrequestsPullRequestIdDiffstatGet({
52478
52698
  workspace,
52479
52699
  repoSlug,
@@ -52491,21 +52711,35 @@ class DiffPRCommand extends BaseCommand {
52491
52711
  const totalAdditions = files.reduce((sum, f) => sum + f.additions, 0);
52492
52712
  const totalDeletions = files.reduce((sum, f) => sum + f.deletions, 0);
52493
52713
  const filesChanged = files.length;
52714
+ if (useJson) {
52715
+ return {
52716
+ files,
52717
+ filesChanged,
52718
+ totalAdditions,
52719
+ totalDeletions
52720
+ };
52721
+ }
52494
52722
  for (const file of files) {
52495
- const additions = file.additions > 0 ? source_default.green(`+${file.additions}`) : "";
52496
- const deletions = file.deletions > 0 ? source_default.red(`-${file.deletions}`) : "";
52723
+ const additions = file.additions > 0 ? this.output.green(`+${file.additions}`) : "";
52724
+ const deletions = file.deletions > 0 ? this.output.red(`-${file.deletions}`) : "";
52497
52725
  const stats = [additions, deletions].filter(Boolean).join(" ");
52498
52726
  this.output.text(`${file.path} ${stats ? `| ${stats}` : ""}`);
52499
52727
  }
52500
52728
  this.output.text("");
52501
52729
  const summary = [
52502
- `${filesChanged} file${filesChanged !== 1 ? "s" : ""} changed`,
52503
- totalAdditions > 0 ? source_default.green(`${totalAdditions} insertion${totalAdditions !== 1 ? "s" : ""}(+)`) : null,
52504
- totalDeletions > 0 ? source_default.red(`${totalDeletions} deletion${totalDeletions !== 1 ? "s" : ""}(-)`) : null
52730
+ `${filesChanged} file${filesChanged === 1 ? "" : "s"} changed`,
52731
+ totalAdditions > 0 ? this.output.green(`${totalAdditions} insertion${totalAdditions === 1 ? "" : "s"}(+)`) : null,
52732
+ totalDeletions > 0 ? this.output.red(`${totalDeletions} deletion${totalDeletions === 1 ? "" : "s"}(-)`) : null
52505
52733
  ].filter(Boolean).join(", ");
52506
52734
  this.output.text(summary);
52735
+ return {
52736
+ files,
52737
+ filesChanged,
52738
+ totalAdditions,
52739
+ totalDeletions
52740
+ };
52507
52741
  }
52508
- async showNameOnly(workspace, repoSlug, prId, context) {
52742
+ async showNameOnly(workspace, repoSlug, prId, useJson) {
52509
52743
  const diffstatResponse = await this.pullrequestsApi.repositoriesWorkspaceRepoSlugPullrequestsPullRequestIdDiffstatGet({
52510
52744
  workspace,
52511
52745
  repoSlug,
@@ -52513,11 +52747,15 @@ class DiffPRCommand extends BaseCommand {
52513
52747
  });
52514
52748
  const diffstat = diffstatResponse.data;
52515
52749
  const fileNames = Array.from(diffstat.values ?? []).map((file) => file.new?.path || file.old?.path || "unknown");
52750
+ if (useJson) {
52751
+ return fileNames;
52752
+ }
52516
52753
  for (const fileName of fileNames) {
52517
52754
  this.output.text(fileName);
52518
52755
  }
52756
+ return fileNames;
52519
52757
  }
52520
- async showDiff(workspace, repoSlug, prId, options, context) {
52758
+ async showDiff(workspace, repoSlug, prId, options, useJson) {
52521
52759
  const diffResponse = await this.pullrequestsApi.repositoriesWorkspaceRepoSlugPullrequestsPullRequestIdDiffGet({
52522
52760
  workspace,
52523
52761
  repoSlug,
@@ -52525,8 +52763,12 @@ class DiffPRCommand extends BaseCommand {
52525
52763
  });
52526
52764
  const diff = diffResponse.data;
52527
52765
  const shouldColorize = this.shouldColorize(options.color);
52766
+ if (useJson) {
52767
+ return String(diff);
52768
+ }
52528
52769
  const colorizedDiff = shouldColorize ? this.colorizeDiff(String(diff)) : String(diff);
52529
52770
  this.output.text(colorizedDiff);
52771
+ return String(diff);
52530
52772
  }
52531
52773
  shouldColorize(colorOption) {
52532
52774
  if (!colorOption || colorOption === "auto") {
@@ -52539,15 +52781,15 @@ class DiffPRCommand extends BaseCommand {
52539
52781
  `);
52540
52782
  return lines.map((line) => {
52541
52783
  if (line.startsWith("+") && !line.startsWith("+++")) {
52542
- return source_default.green(line);
52784
+ return this.output.green(line);
52543
52785
  } else if (line.startsWith("-") && !line.startsWith("---")) {
52544
- return source_default.red(line);
52786
+ return this.output.red(line);
52545
52787
  } else if (line.startsWith("@@")) {
52546
- return source_default.cyan(line);
52788
+ return this.output.cyan(line);
52547
52789
  } else if (line.startsWith("diff --git")) {
52548
- return source_default.bold(line);
52790
+ return this.output.bold(line);
52549
52791
  } else if (line.startsWith("index ") || line.startsWith("---") || line.startsWith("+++")) {
52550
- return source_default.dim(line);
52792
+ return this.output.dim(line);
52551
52793
  }
52552
52794
  return line;
52553
52795
  }).join(`
@@ -52571,40 +52813,47 @@ class ActivityPRCommand extends BaseCommand {
52571
52813
  ...context.globalOptions,
52572
52814
  ...options
52573
52815
  });
52574
- const prId = parseInt(options.id, 10);
52575
- const limit = options.limit ? parseInt(options.limit, 10) : 25;
52576
- try {
52577
- const response = await this.pullrequestsApi.repositoriesWorkspaceRepoSlugPullrequestsPullRequestIdActivityGet({
52816
+ const prId = Number.parseInt(options.id, 10);
52817
+ const response = await this.pullrequestsApi.repositoriesWorkspaceRepoSlugPullrequestsPullRequestIdActivityGet({
52818
+ workspace: repoContext.workspace,
52819
+ repoSlug: repoContext.repoSlug,
52820
+ pullRequestId: prId
52821
+ });
52822
+ const data = response.data;
52823
+ const values = data?.values ? Array.from(data.values) : [];
52824
+ const filterTypes = this.parseTypeFilter(options.type);
52825
+ const activities = filterTypes.length > 0 ? values.filter((activity) => filterTypes.includes(this.getActivityType(activity))) : values;
52826
+ if (context.globalOptions.json) {
52827
+ this.output.json({
52578
52828
  workspace: repoContext.workspace,
52579
52829
  repoSlug: repoContext.repoSlug,
52580
- pullRequestId: prId
52830
+ pullRequestId: prId,
52831
+ filters: {
52832
+ types: filterTypes
52833
+ },
52834
+ count: activities.length,
52835
+ activities
52581
52836
  });
52582
- const data = response.data;
52583
- const values = data?.values ? Array.from(data.values) : [];
52584
- const filterTypes = this.parseTypeFilter(options.type);
52585
- const activities = filterTypes.length > 0 ? values.filter((activity) => filterTypes.includes(this.getActivityType(activity))) : values;
52586
- if (activities.length === 0) {
52587
- if (filterTypes.length > 0) {
52588
- this.output.info("No activity entries matched the requested filter");
52589
- } else {
52590
- this.output.info("No activity found on this pull request");
52591
- }
52592
- return;
52837
+ return;
52838
+ }
52839
+ if (activities.length === 0) {
52840
+ if (filterTypes.length > 0) {
52841
+ this.output.info("No activity entries matched the requested filter");
52842
+ } else {
52843
+ this.output.info("No activity found on this pull request");
52593
52844
  }
52594
- const rows = activities.map((activity) => {
52595
- const activityType = this.getActivityType(activity);
52596
- return [
52597
- activityType.toUpperCase(),
52598
- this.getActorName(activity),
52599
- this.formatActivityDate(activity),
52600
- this.buildActivityDetails(activity, activityType)
52601
- ];
52602
- });
52603
- this.output.table(["TYPE", "ACTOR", "DATE", "DETAILS"], rows);
52604
- } catch (error) {
52605
- this.handleError(error, context);
52606
- throw error;
52845
+ return;
52607
52846
  }
52847
+ const rows = activities.map((activity) => {
52848
+ const activityType = this.getActivityType(activity);
52849
+ return [
52850
+ activityType.toUpperCase(),
52851
+ this.getActorName(activity),
52852
+ this.formatActivityDate(activity),
52853
+ this.buildActivityDetails(activity, activityType)
52854
+ ];
52855
+ });
52856
+ this.output.table(["TYPE", "ACTOR", "DATE", "DETAILS"], rows);
52608
52857
  }
52609
52858
  parseTypeFilter(typeOption) {
52610
52859
  if (!typeOption) {
@@ -52713,27 +52962,78 @@ class CommentPRCommand extends BaseCommand {
52713
52962
  this.contextService = contextService;
52714
52963
  }
52715
52964
  async execute(options, context) {
52965
+ if ((options.lineTo || options.lineFrom) && !options.file) {
52966
+ throw new BBError({
52967
+ code: 5001 /* VALIDATION_REQUIRED */,
52968
+ message: "--file is required when using --line-to or --line-from"
52969
+ });
52970
+ }
52971
+ if (options.file && !options.lineTo && !options.lineFrom) {
52972
+ throw new BBError({
52973
+ code: 5001 /* VALIDATION_REQUIRED */,
52974
+ message: "At least one of --line-to or --line-from is required when using --file"
52975
+ });
52976
+ }
52977
+ if (options.lineTo) {
52978
+ const parsed = Number.parseInt(options.lineTo, 10);
52979
+ if (Number.isNaN(parsed) || parsed < 1) {
52980
+ throw new BBError({
52981
+ code: 5002 /* VALIDATION_INVALID */,
52982
+ message: "--line-to must be a positive integer"
52983
+ });
52984
+ }
52985
+ }
52986
+ if (options.lineFrom) {
52987
+ const parsed = Number.parseInt(options.lineFrom, 10);
52988
+ if (Number.isNaN(parsed) || parsed < 1) {
52989
+ throw new BBError({
52990
+ code: 5002 /* VALIDATION_INVALID */,
52991
+ message: "--line-from must be a positive integer"
52992
+ });
52993
+ }
52994
+ }
52716
52995
  const repoContext = await this.contextService.requireRepoContext({
52717
52996
  ...context.globalOptions,
52718
52997
  ...options
52719
52998
  });
52720
- const prId = parseInt(options.id, 10);
52721
- try {
52722
- await this.pullrequestsApi.repositoriesWorkspaceRepoSlugPullrequestsPullRequestIdCommentsPost({
52723
- workspace: repoContext.workspace,
52724
- repoSlug: repoContext.repoSlug,
52999
+ const prId = Number.parseInt(options.id, 10);
53000
+ const inline = options.file ? {
53001
+ path: options.file,
53002
+ ...options.lineTo ? { to: Number.parseInt(options.lineTo, 10) } : {},
53003
+ ...options.lineFrom ? { from: Number.parseInt(options.lineFrom, 10) } : {}
53004
+ } : undefined;
53005
+ const body = {
53006
+ content: {
53007
+ raw: options.message
53008
+ },
53009
+ ...inline ? { inline } : {}
53010
+ };
53011
+ const response = await this.pullrequestsApi.repositoriesWorkspaceRepoSlugPullrequestsPullRequestIdCommentsPost({
53012
+ workspace: repoContext.workspace,
53013
+ repoSlug: repoContext.repoSlug,
53014
+ pullRequestId: prId,
53015
+ body
53016
+ });
53017
+ if (context.globalOptions.json) {
53018
+ const jsonOutput = {
53019
+ success: true,
52725
53020
  pullRequestId: prId,
52726
- body: {
52727
- type: "pullrequest_comment",
52728
- content: {
52729
- raw: options.message
52730
- }
52731
- }
52732
- });
53021
+ comment: response.data
53022
+ };
53023
+ if (inline) {
53024
+ jsonOutput.inline = inline;
53025
+ }
53026
+ this.output.json(jsonOutput);
53027
+ return;
53028
+ }
53029
+ if (inline) {
53030
+ if (inline.to) {
53031
+ this.output.success(`Added inline comment on ${inline.path}:${inline.to} to pull request #${prId}`);
53032
+ } else {
53033
+ this.output.success(`Added inline comment on ${inline.path} (old line ${inline.from}) to pull request #${prId}`);
53034
+ }
53035
+ } else {
52733
53036
  this.output.success(`Added comment to pull request #${prId}`);
52734
- } catch (error) {
52735
- this.handleError(error, context);
52736
- throw error;
52737
53037
  }
52738
53038
  }
52739
53039
  }
@@ -52754,34 +53054,36 @@ class ListCommentsPRCommand extends BaseCommand {
52754
53054
  ...context.globalOptions,
52755
53055
  ...options
52756
53056
  });
52757
- const prId = parseInt(options.id, 10);
52758
- const limit = options.limit ? parseInt(options.limit, 10) : 25;
52759
- try {
52760
- const response = await this.pullrequestsApi.repositoriesWorkspaceRepoSlugPullrequestsPullRequestIdCommentsGet({
52761
- workspace: repoContext.workspace,
52762
- repoSlug: repoContext.repoSlug,
52763
- pullRequestId: prId
52764
- });
52765
- const data = response.data;
52766
- const values = data.values ? Array.from(data.values) : [];
52767
- if (values.length === 0) {
52768
- this.output.info("No comments found on this pull request");
52769
- return;
52770
- }
52771
- const rows = values.map((comment) => {
52772
- const content = comment.content?.raw ?? "";
52773
- return [
52774
- comment.id?.toString() ?? "",
52775
- comment.user?.nickname ?? comment.user?.display_name ?? "Unknown",
52776
- comment.deleted ? "[deleted]" : options.truncate === false ? content : content.slice(0, 60) + (content.length > 60 ? "..." : ""),
52777
- this.output.formatDate(comment.created_on ?? "")
52778
- ];
53057
+ const prId = Number.parseInt(options.id, 10);
53058
+ const response = await this.pullrequestsApi.repositoriesWorkspaceRepoSlugPullrequestsPullRequestIdCommentsGet({
53059
+ workspace: repoContext.workspace,
53060
+ repoSlug: repoContext.repoSlug,
53061
+ pullRequestId: prId
53062
+ });
53063
+ const data = response.data;
53064
+ const values = data.values ? Array.from(data.values) : [];
53065
+ if (context.globalOptions.json) {
53066
+ this.output.json({
53067
+ pullRequestId: prId,
53068
+ count: values.length,
53069
+ comments: values
52779
53070
  });
52780
- this.output.table(["ID", "Author", "Content", "Date"], rows);
52781
- } catch (error) {
52782
- this.handleError(error, context);
52783
- throw error;
53071
+ return;
52784
53072
  }
53073
+ if (values.length === 0) {
53074
+ this.output.info("No comments found on this pull request");
53075
+ return;
53076
+ }
53077
+ const rows = values.map((comment) => {
53078
+ const content = comment.content?.raw ?? "";
53079
+ return [
53080
+ comment.id?.toString() ?? "",
53081
+ comment.user?.nickname ?? comment.user?.display_name ?? "Unknown",
53082
+ comment.deleted ? "[deleted]" : options.truncate === false ? content : content.slice(0, 60) + (content.length > 60 ? "..." : ""),
53083
+ this.output.formatDate(comment.created_on ?? "")
53084
+ ];
53085
+ });
53086
+ this.output.table(["ID", "Author", "Content", "Date"], rows);
52785
53087
  }
52786
53088
  }
52787
53089
 
@@ -52801,26 +53103,30 @@ class EditCommentPRCommand extends BaseCommand {
52801
53103
  ...context.globalOptions,
52802
53104
  ...options
52803
53105
  });
52804
- const prId = parseInt(options.prId, 10);
52805
- const commentId = parseInt(options.commentId, 10);
52806
- try {
52807
- await this.pullrequestsApi.repositoriesWorkspaceRepoSlugPullrequestsPullRequestIdCommentsCommentIdPut({
52808
- workspace: repoContext.workspace,
52809
- repoSlug: repoContext.repoSlug,
53106
+ const prId = Number.parseInt(options.prId, 10);
53107
+ const commentId = Number.parseInt(options.commentId, 10);
53108
+ const response = await this.pullrequestsApi.repositoriesWorkspaceRepoSlugPullrequestsPullRequestIdCommentsCommentIdPut({
53109
+ workspace: repoContext.workspace,
53110
+ repoSlug: repoContext.repoSlug,
53111
+ pullRequestId: prId,
53112
+ commentId,
53113
+ body: {
53114
+ type: "pullrequest_comment",
53115
+ content: {
53116
+ raw: options.message
53117
+ }
53118
+ }
53119
+ });
53120
+ if (context.globalOptions.json) {
53121
+ this.output.json({
53122
+ success: true,
52810
53123
  pullRequestId: prId,
52811
53124
  commentId,
52812
- body: {
52813
- type: "pullrequest_comment",
52814
- content: {
52815
- raw: options.message
52816
- }
52817
- }
53125
+ comment: response.data
52818
53126
  });
52819
- this.output.success(`Updated comment #${commentId}`);
52820
- } catch (error) {
52821
- this.handleError(error, context);
52822
- throw error;
53127
+ return;
52823
53128
  }
53129
+ this.output.success(`Updated comment #${commentId} on PR #${prId}`);
52824
53130
  }
52825
53131
  }
52826
53132
 
@@ -52840,20 +53146,23 @@ class DeleteCommentPRCommand extends BaseCommand {
52840
53146
  ...context.globalOptions,
52841
53147
  ...options
52842
53148
  });
52843
- const prId = parseInt(options.prId, 10);
52844
- const commentId = parseInt(options.commentId, 10);
52845
- try {
52846
- await this.pullrequestsApi.repositoriesWorkspaceRepoSlugPullrequestsPullRequestIdCommentsCommentIdDelete({
52847
- workspace: repoContext.workspace,
52848
- repoSlug: repoContext.repoSlug,
53149
+ const prId = Number.parseInt(options.prId, 10);
53150
+ const commentId = Number.parseInt(options.commentId, 10);
53151
+ await this.pullrequestsApi.repositoriesWorkspaceRepoSlugPullrequestsPullRequestIdCommentsCommentIdDelete({
53152
+ workspace: repoContext.workspace,
53153
+ repoSlug: repoContext.repoSlug,
53154
+ pullRequestId: prId,
53155
+ commentId
53156
+ });
53157
+ if (context.globalOptions.json) {
53158
+ this.output.json({
53159
+ success: true,
52849
53160
  pullRequestId: prId,
52850
53161
  commentId
52851
53162
  });
52852
- this.output.success(`Deleted comment #${commentId} from PR #${prId}`);
52853
- } catch (error) {
52854
- this.handleError(error, context);
52855
- throw error;
53163
+ return;
52856
53164
  }
53165
+ this.output.success(`Deleted comment #${commentId} from PR #${prId}`);
52857
53166
  }
52858
53167
  }
52859
53168
 
@@ -52875,37 +53184,44 @@ class AddReviewerPRCommand extends BaseCommand {
52875
53184
  ...context.globalOptions,
52876
53185
  ...options
52877
53186
  });
52878
- const prId = parseInt(options.id, 10);
52879
- try {
52880
- const userResponse = await this.usersApi.usersSelectedUserGet({
52881
- selectedUser: options.username
52882
- });
52883
- const user = userResponse.data;
52884
- const prResponse = await this.pullrequestsApi.repositoriesWorkspaceRepoSlugPullrequestsPullRequestIdGet({
52885
- workspace: repoContext.workspace,
52886
- repoSlug: repoContext.repoSlug,
52887
- pullRequestId: prId
52888
- });
52889
- const pr = prResponse.data;
52890
- const existingReviewers = pr.reviewers ? Array.from(pr.reviewers) : [];
52891
- const reviewerUuids = existingReviewers.map((r) => r.uuid).filter(Boolean);
52892
- if (!reviewerUuids.includes(user.uuid)) {
52893
- reviewerUuids.push(user.uuid);
53187
+ const prId = Number.parseInt(options.id, 10);
53188
+ const userResponse = await this.usersApi.usersSelectedUserGet({
53189
+ selectedUser: options.username
53190
+ });
53191
+ const user = userResponse.data;
53192
+ const prResponse = await this.pullrequestsApi.repositoriesWorkspaceRepoSlugPullrequestsPullRequestIdGet({
53193
+ workspace: repoContext.workspace,
53194
+ repoSlug: repoContext.repoSlug,
53195
+ pullRequestId: prId
53196
+ });
53197
+ const pr = prResponse.data;
53198
+ const existingReviewers = pr.reviewers ? Array.from(pr.reviewers) : [];
53199
+ const reviewerUuids = existingReviewers.map((r) => r.uuid).filter(Boolean);
53200
+ if (!reviewerUuids.includes(user.uuid)) {
53201
+ reviewerUuids.push(user.uuid);
53202
+ }
53203
+ const response = await this.pullrequestsApi.repositoriesWorkspaceRepoSlugPullrequestsPullRequestIdPut({
53204
+ workspace: repoContext.workspace,
53205
+ repoSlug: repoContext.repoSlug,
53206
+ pullRequestId: prId,
53207
+ body: {
53208
+ type: "pullrequest",
53209
+ reviewers: reviewerUuids.map((uuid) => ({ uuid }))
52894
53210
  }
52895
- await this.pullrequestsApi.repositoriesWorkspaceRepoSlugPullrequestsPullRequestIdPut({
52896
- workspace: repoContext.workspace,
52897
- repoSlug: repoContext.repoSlug,
53211
+ });
53212
+ if (context.globalOptions.json) {
53213
+ this.output.json({
53214
+ success: true,
52898
53215
  pullRequestId: prId,
52899
- body: {
52900
- type: "pullrequest",
52901
- reviewers: reviewerUuids.map((uuid) => ({ uuid }))
52902
- }
53216
+ reviewer: {
53217
+ username: options.username,
53218
+ uuid: user.uuid
53219
+ },
53220
+ pullRequest: response.data
52903
53221
  });
52904
- this.output.success(`Added ${options.username} as reviewer to pull request #${prId}`);
52905
- } catch (error) {
52906
- this.handleError(error, context);
52907
- throw error;
53222
+ return;
52908
53223
  }
53224
+ this.output.success(`Added ${options.username} as reviewer to pull request #${prId}`);
52909
53225
  }
52910
53226
  }
52911
53227
 
@@ -52927,34 +53243,41 @@ class RemoveReviewerPRCommand extends BaseCommand {
52927
53243
  ...context.globalOptions,
52928
53244
  ...options
52929
53245
  });
52930
- const prId = parseInt(options.id, 10);
52931
- try {
52932
- const userResponse = await this.usersApi.usersSelectedUserGet({
52933
- selectedUser: options.username
52934
- });
52935
- const user = userResponse.data;
52936
- const prResponse = await this.pullrequestsApi.repositoriesWorkspaceRepoSlugPullrequestsPullRequestIdGet({
52937
- workspace: repoContext.workspace,
52938
- repoSlug: repoContext.repoSlug,
52939
- pullRequestId: prId
52940
- });
52941
- const pr = prResponse.data;
52942
- const existingReviewers = pr.reviewers ? Array.from(pr.reviewers) : [];
52943
- const reviewerUuids = existingReviewers.map((r) => r.uuid).filter((uuid) => uuid && uuid !== user.uuid);
52944
- await this.pullrequestsApi.repositoriesWorkspaceRepoSlugPullrequestsPullRequestIdPut({
52945
- workspace: repoContext.workspace,
52946
- repoSlug: repoContext.repoSlug,
53246
+ const prId = Number.parseInt(options.id, 10);
53247
+ const userResponse = await this.usersApi.usersSelectedUserGet({
53248
+ selectedUser: options.username
53249
+ });
53250
+ const user = userResponse.data;
53251
+ const prResponse = await this.pullrequestsApi.repositoriesWorkspaceRepoSlugPullrequestsPullRequestIdGet({
53252
+ workspace: repoContext.workspace,
53253
+ repoSlug: repoContext.repoSlug,
53254
+ pullRequestId: prId
53255
+ });
53256
+ const pr = prResponse.data;
53257
+ const existingReviewers = pr.reviewers ? Array.from(pr.reviewers) : [];
53258
+ const reviewerUuids = existingReviewers.map((r) => r.uuid).filter((uuid) => uuid && uuid !== user.uuid);
53259
+ const response = await this.pullrequestsApi.repositoriesWorkspaceRepoSlugPullrequestsPullRequestIdPut({
53260
+ workspace: repoContext.workspace,
53261
+ repoSlug: repoContext.repoSlug,
53262
+ pullRequestId: prId,
53263
+ body: {
53264
+ type: "pullrequest",
53265
+ reviewers: reviewerUuids.map((uuid) => ({ uuid }))
53266
+ }
53267
+ });
53268
+ if (context.globalOptions.json) {
53269
+ this.output.json({
53270
+ success: true,
52947
53271
  pullRequestId: prId,
52948
- body: {
52949
- type: "pullrequest",
52950
- reviewers: reviewerUuids.map((uuid) => ({ uuid }))
52951
- }
53272
+ reviewer: {
53273
+ username: options.username,
53274
+ uuid: user.uuid
53275
+ },
53276
+ pullRequest: response.data
52952
53277
  });
52953
- this.output.success(`Removed ${options.username} as reviewer from pull request #${prId}`);
52954
- } catch (error) {
52955
- this.handleError(error, context);
52956
- throw error;
53278
+ return;
52957
53279
  }
53280
+ this.output.success(`Removed ${options.username} as reviewer from pull request #${prId}`);
52958
53281
  }
52959
53282
  }
52960
53283
 
@@ -52974,28 +53297,26 @@ class ListReviewersPRCommand extends BaseCommand {
52974
53297
  ...context.globalOptions,
52975
53298
  ...options
52976
53299
  });
52977
- const prId = parseInt(options.id, 10);
52978
- try {
52979
- const response = await this.pullrequestsApi.repositoriesWorkspaceRepoSlugPullrequestsPullRequestIdGet({
52980
- workspace: repoContext.workspace,
52981
- repoSlug: repoContext.repoSlug,
52982
- pullRequestId: prId
53300
+ const prId = Number.parseInt(options.id, 10);
53301
+ const response = await this.pullrequestsApi.repositoriesWorkspaceRepoSlugPullrequestsPullRequestIdGet({
53302
+ workspace: repoContext.workspace,
53303
+ repoSlug: repoContext.repoSlug,
53304
+ pullRequestId: prId
53305
+ });
53306
+ const pr = response.data;
53307
+ const reviewers = Array.from(pr.reviewers ?? []);
53308
+ if (context.globalOptions.json) {
53309
+ this.output.json({
53310
+ pullRequestId: prId,
53311
+ count: reviewers.length,
53312
+ reviewers
52983
53313
  });
52984
- const pr = response.data;
52985
- const reviewers = pr.reviewers ?? [];
52986
- if (context.globalOptions.json) {
52987
- this.output.json(reviewers);
52988
- } else if (reviewers.length === 0) {
52989
- this.output.info("No reviewers assigned to this pull request");
52990
- } else {
52991
- this.output.table(["Display Name", "Account ID"], reviewers.map((r) => [
52992
- r.display_name ?? "Unknown",
52993
- r.account_id ?? ""
52994
- ]));
52995
- }
52996
- } catch (error) {
52997
- this.handleError(error, context);
52998
- throw error;
53314
+ return;
53315
+ }
53316
+ if (reviewers.length === 0) {
53317
+ this.output.info("No reviewers assigned to this pull request");
53318
+ } else {
53319
+ this.output.table(["Display Name", "Account ID"], reviewers.map((r) => [r.display_name ?? "Unknown", r.account_id ?? ""]));
52999
53320
  }
53000
53321
  }
53001
53322
  }
@@ -53016,35 +53337,32 @@ class ChecksPRCommand extends BaseCommand {
53016
53337
  ...context.globalOptions,
53017
53338
  ...options
53018
53339
  });
53019
- const prId = parseInt(options.id, 10);
53020
- try {
53021
- const response = await this.commitStatusesApi.repositoriesWorkspaceRepoSlugPullrequestsPullRequestIdStatusesGet({
53340
+ const prId = Number.parseInt(options.id, 10);
53341
+ const response = await this.commitStatusesApi.repositoriesWorkspaceRepoSlugPullrequestsPullRequestIdStatusesGet({
53342
+ workspace: repoContext.workspace,
53343
+ repoSlug: repoContext.repoSlug,
53344
+ pullRequestId: prId
53345
+ });
53346
+ const data = response.data;
53347
+ const statuses = data?.values ? Array.from(data.values) : [];
53348
+ const summary = this.getSummary(statuses);
53349
+ const useJson = options.json || context.globalOptions.json;
53350
+ if (useJson) {
53351
+ this.output.json({
53352
+ pullRequestId: prId,
53022
53353
  workspace: repoContext.workspace,
53023
53354
  repoSlug: repoContext.repoSlug,
53024
- pullRequestId: prId
53355
+ summary,
53356
+ statuses: statuses.map((status) => this.formatStatusForJson(status))
53025
53357
  });
53026
- const data = response.data;
53027
- const statuses = data?.values ? Array.from(data.values) : [];
53028
- const useJson = options.json || context.globalOptions.json;
53029
- if (useJson) {
53030
- this.output.json({
53031
- pullRequestId: prId,
53032
- workspace: repoContext.workspace,
53033
- repoSlug: repoContext.repoSlug,
53034
- statuses: statuses.map((status) => this.formatStatusForJson(status))
53035
- });
53036
- return;
53037
- }
53038
- if (statuses.length === 0) {
53039
- this.output.info("No CI/CD checks found for this pull request");
53040
- return;
53041
- }
53042
- this.renderHeader(prId, statuses.length);
53043
- this.renderStatuses(statuses);
53044
- } catch (error) {
53045
- this.handleError(error, context);
53046
- throw error;
53358
+ return;
53359
+ }
53360
+ if (statuses.length === 0) {
53361
+ this.output.info("No CI/CD checks found for this pull request");
53362
+ return;
53047
53363
  }
53364
+ this.renderHeader(prId, statuses.length);
53365
+ this.renderStatuses(statuses, summary);
53048
53366
  }
53049
53367
  formatStatusForJson(status) {
53050
53368
  return {
@@ -53061,10 +53379,11 @@ class ChecksPRCommand extends BaseCommand {
53061
53379
  }
53062
53380
  renderHeader(prId, count) {
53063
53381
  this.output.text("");
53064
- this.output.text(`${source_default.bold(`Pull Request #${prId}`)} - ${count} check${count === 1 ? "" : "s"}`);
53065
- this.output.text(source_default.gray("-".repeat(60)));
53382
+ const title = this.output.bold("Pull Request #" + prId);
53383
+ this.output.text(`${title} - ${count} check${count === 1 ? "" : "s"}`);
53384
+ this.output.text(this.output.gray("-".repeat(60)));
53066
53385
  }
53067
- renderStatuses(statuses) {
53386
+ renderStatuses(statuses, summary) {
53068
53387
  const rows = statuses.map((status) => {
53069
53388
  const stateIcon = this.getStateIcon(status.state);
53070
53389
  const stateLabel = this.getStateLabel(status.state);
@@ -53072,29 +53391,28 @@ class ChecksPRCommand extends BaseCommand {
53072
53391
  const description = status.description ?? "-";
53073
53392
  return [
53074
53393
  `${stateIcon} ${stateLabel}`,
53075
- source_default.bold(name),
53394
+ this.output.bold(name),
53076
53395
  this.truncate(description, 40),
53077
53396
  status.updated_on ? this.output.formatDate(status.updated_on) : "-"
53078
53397
  ];
53079
53398
  });
53080
53399
  this.output.table(["STATUS", "NAME", "DESCRIPTION", "UPDATED"], rows);
53081
- const summary = this.getSummary(statuses);
53082
53400
  this.output.text("");
53083
- this.output.text(`${source_default.green("OK")} ${summary.successful} successful, ${source_default.red("FAIL")} ${summary.failed} failed, ${source_default.yellow("RUN")} ${summary.pending} pending`);
53401
+ this.output.text(`${this.output.green("OK")} ${summary.successful} successful, ${this.output.red("FAIL")} ${summary.failed} failed, ${this.output.yellow("RUN")} ${summary.pending} pending`);
53084
53402
  this.output.text("");
53085
53403
  }
53086
53404
  getStateIcon(state) {
53087
53405
  switch (state?.toUpperCase()) {
53088
53406
  case "SUCCESSFUL":
53089
- return source_default.green("OK");
53407
+ return this.output.green("OK");
53090
53408
  case "FAILED":
53091
- return source_default.red("FAIL");
53409
+ return this.output.red("FAIL");
53092
53410
  case "INPROGRESS":
53093
- return source_default.yellow("RUN");
53411
+ return this.output.yellow("RUN");
53094
53412
  case "STOPPED":
53095
- return source_default.gray("STOP");
53413
+ return this.output.gray("STOP");
53096
53414
  default:
53097
- return source_default.gray("?");
53415
+ return this.output.gray("?");
53098
53416
  }
53099
53417
  }
53100
53418
  getStateLabel(state) {
@@ -53132,25 +53450,6 @@ class ChecksPRCommand extends BaseCommand {
53132
53450
  }
53133
53451
  }
53134
53452
 
53135
- // src/types/config.ts
53136
- var SETTABLE_CONFIG_KEYS = [
53137
- "defaultWorkspace",
53138
- "skipVersionCheck",
53139
- "versionCheckInterval"
53140
- ];
53141
- var READABLE_CONFIG_KEYS = [
53142
- "username",
53143
- "defaultWorkspace",
53144
- "skipVersionCheck",
53145
- "versionCheckInterval"
53146
- ];
53147
- function isSettableConfigKey(key) {
53148
- return SETTABLE_CONFIG_KEYS.includes(key);
53149
- }
53150
- function isReadableConfigKey(key) {
53151
- return READABLE_CONFIG_KEYS.includes(key);
53152
- }
53153
-
53154
53453
  // src/commands/config/get.command.ts
53155
53454
  class GetConfigCommand extends BaseCommand {
53156
53455
  configService;
@@ -53161,20 +53460,24 @@ class GetConfigCommand extends BaseCommand {
53161
53460
  super(output);
53162
53461
  this.configService = configService;
53163
53462
  }
53164
- async execute(options, _context) {
53463
+ async execute(options, context) {
53165
53464
  const { key } = options;
53166
53465
  if (GetConfigCommand.HIDDEN_KEYS.includes(key)) {
53167
- const error = new Error(`Cannot display '${key}' - use 'bb auth token' to get authentication credentials`);
53168
- this.output.error(error.message);
53169
- throw error;
53466
+ throw new Error(`Cannot display '${key}' - use 'bb auth token' to get authentication credentials`);
53170
53467
  }
53171
53468
  if (!isReadableConfigKey(key)) {
53172
- const error = new Error(`Unknown config key '${key}'. Valid keys: username, defaultWorkspace`);
53173
- this.output.error(error.message);
53174
- throw error;
53469
+ throw new Error(`Unknown config key '${key}'. Valid keys: ${READABLE_CONFIG_KEYS.join(", ")}`);
53470
+ }
53471
+ const rawValue = await this.configService.getValue(key);
53472
+ const value = normalizeReadableConfigValue(key, rawValue);
53473
+ if (context.globalOptions.json) {
53474
+ this.output.json({
53475
+ key,
53476
+ value: value ?? null
53477
+ });
53478
+ return;
53175
53479
  }
53176
- const value = await this.configService.getValue(key);
53177
- this.output.text(String(value || ""));
53480
+ this.output.text(String(value ?? ""));
53178
53481
  }
53179
53482
  }
53180
53483
 
@@ -53188,20 +53491,25 @@ class SetConfigCommand extends BaseCommand {
53188
53491
  super(output);
53189
53492
  this.configService = configService;
53190
53493
  }
53191
- async execute(options, _context) {
53494
+ async execute(options, context) {
53192
53495
  const { key, value } = options;
53193
53496
  if (SetConfigCommand.PROTECTED_KEYS.includes(key)) {
53194
- const error = new Error(`Cannot set '${key}' directly. Use 'bb auth login' to configure authentication.`);
53195
- this.output.error(error.message);
53196
- throw error;
53497
+ throw new Error(`Cannot set '${key}' directly. Use 'bb auth login' to configure authentication.`);
53197
53498
  }
53198
53499
  if (!isSettableConfigKey(key)) {
53199
- const error = new Error(`Unknown config key '${key}'. Valid keys: defaultWorkspace`);
53200
- this.output.error(error.message);
53201
- throw error;
53500
+ throw new Error(`Unknown config key '${key}'. Valid keys: ${SETTABLE_CONFIG_KEYS.join(", ")}`);
53202
53501
  }
53203
- await this.configService.setValue(key, value);
53204
- this.output.success(`Set ${key} = ${value}`);
53502
+ const parsedValue = parseSettableConfigValue(key, value);
53503
+ await this.configService.setValue(key, parsedValue);
53504
+ if (context.globalOptions.json) {
53505
+ this.output.json({
53506
+ success: true,
53507
+ key,
53508
+ value: parsedValue
53509
+ });
53510
+ return;
53511
+ }
53512
+ this.output.success(`Set ${key} = ${parsedValue}`);
53205
53513
  }
53206
53514
  }
53207
53515
 
@@ -53214,16 +53522,39 @@ class ListConfigCommand extends BaseCommand {
53214
53522
  super(output);
53215
53523
  this.configService = configService;
53216
53524
  }
53217
- async execute(_options, _context) {
53525
+ async execute(_options, context) {
53218
53526
  const config = await this.configService.getConfig();
53219
- const displayConfig = {
53220
- username: config.username || "",
53221
- defaultWorkspace: config.defaultWorkspace || "",
53222
- apiToken: config.apiToken ? "********" : ""
53223
- };
53224
- this.output.text(source_default.dim(`Config file: ${this.configService.getConfigPath()}`));
53527
+ const displayConfig = {};
53528
+ if (config.username) {
53529
+ displayConfig.username = config.username;
53530
+ }
53531
+ if (config.defaultWorkspace) {
53532
+ displayConfig.defaultWorkspace = config.defaultWorkspace;
53533
+ }
53534
+ if (config.apiToken) {
53535
+ displayConfig.apiToken = "********";
53536
+ }
53537
+ const skipVersionCheck = coerceSkipVersionCheckValue(config.skipVersionCheck);
53538
+ if (skipVersionCheck !== undefined) {
53539
+ displayConfig.skipVersionCheck = skipVersionCheck;
53540
+ }
53541
+ const versionCheckInterval = coerceVersionCheckIntervalValue(config.versionCheckInterval);
53542
+ if (versionCheckInterval !== undefined) {
53543
+ displayConfig.versionCheckInterval = versionCheckInterval;
53544
+ }
53545
+ if (context.globalOptions.json) {
53546
+ this.output.json({
53547
+ configPath: this.configService.getConfigPath(),
53548
+ config: displayConfig
53549
+ });
53550
+ return;
53551
+ }
53552
+ this.output.text(this.output.dim(`Config file: ${this.configService.getConfigPath()}`));
53225
53553
  this.output.text("");
53226
- const rows = Object.entries(displayConfig).filter(([, value]) => value !== "").map(([key, value]) => [key, value]);
53554
+ const rows = Object.entries(displayConfig).map(([key, value]) => [
53555
+ key,
53556
+ String(value)
53557
+ ]);
53227
53558
  if (rows.length === 0) {
53228
53559
  this.output.text("No configuration set");
53229
53560
  return;
@@ -53241,17 +53572,26 @@ class InstallCompletionCommand extends BaseCommand {
53241
53572
  constructor(output) {
53242
53573
  super(output);
53243
53574
  }
53244
- async execute(_options, _context) {
53575
+ async execute(_options, context) {
53245
53576
  try {
53246
53577
  await import_tabtab.default.install({
53247
53578
  name: "bb",
53248
53579
  completer: "bb"
53249
53580
  });
53581
+ if (context.globalOptions.json) {
53582
+ this.output.json({
53583
+ success: true,
53584
+ shellCompletion: {
53585
+ command: "bb",
53586
+ installed: true
53587
+ }
53588
+ });
53589
+ return;
53590
+ }
53250
53591
  this.output.success("Shell completions installed successfully!");
53251
53592
  this.output.text("Restart your shell or source your profile to enable completions.");
53252
53593
  } catch (error) {
53253
- this.output.error(`Failed to install completions: ${error}`);
53254
- throw error;
53594
+ throw new Error(`Failed to install completions: ${error}`);
53255
53595
  }
53256
53596
  }
53257
53597
  }
@@ -53265,15 +53605,24 @@ class UninstallCompletionCommand extends BaseCommand {
53265
53605
  constructor(output) {
53266
53606
  super(output);
53267
53607
  }
53268
- async execute(_options, _context) {
53608
+ async execute(_options, context) {
53269
53609
  try {
53270
53610
  await import_tabtab2.default.uninstall({
53271
53611
  name: "bb"
53272
53612
  });
53613
+ if (context.globalOptions.json) {
53614
+ this.output.json({
53615
+ success: true,
53616
+ shellCompletion: {
53617
+ command: "bb",
53618
+ installed: false
53619
+ }
53620
+ });
53621
+ return;
53622
+ }
53273
53623
  this.output.success("Shell completions uninstalled successfully!");
53274
53624
  } catch (error) {
53275
- this.output.error(`Failed to uninstall completions: ${error}`);
53276
- throw error;
53625
+ throw new Error(`Failed to uninstall completions: ${error}`);
53277
53626
  }
53278
53627
  }
53279
53628
  }
@@ -53281,11 +53630,11 @@ class UninstallCompletionCommand extends BaseCommand {
53281
53630
  // src/bootstrap.ts
53282
53631
  var require2 = createRequire(import.meta.url);
53283
53632
  var pkg = require2("../package.json");
53284
- function bootstrap() {
53633
+ function bootstrap(options = {}) {
53285
53634
  const container = Container.getInstance();
53286
53635
  container.register(ServiceTokens.ConfigService, () => new ConfigService);
53287
53636
  container.register(ServiceTokens.GitService, () => new GitService);
53288
- container.register(ServiceTokens.OutputService, () => new OutputService);
53637
+ container.register(ServiceTokens.OutputService, () => new OutputService({ noColor: options.noColor }));
53289
53638
  container.register(ServiceTokens.PullrequestsApi, () => {
53290
53639
  const configService = container.resolve(ServiceTokens.ConfigService);
53291
53640
  const axiosInstance = createApiClient(configService);
@@ -53529,6 +53878,7 @@ if (process.argv.includes("--get-yargs-completions") || process.env.COMP_LINE) {
53529
53878
  "--help",
53530
53879
  "--version",
53531
53880
  "--json",
53881
+ "--no-color",
53532
53882
  "--workspace",
53533
53883
  "--repo"
53534
53884
  ];
@@ -53549,17 +53899,44 @@ if (process.argv.includes("--get-yargs-completions") || process.env.COMP_LINE) {
53549
53899
  process.exit(0);
53550
53900
  }
53551
53901
  }
53552
- var container = bootstrap();
53902
+ function resolveNoColorSetting(argv, env2) {
53903
+ const hasColorArg = argv.includes("--color");
53904
+ const hasNoColorArg = argv.includes("--no-color");
53905
+ const hasForceColorEnv = env2.FORCE_COLOR !== undefined && env2.FORCE_COLOR !== "0";
53906
+ const hasNoColorEnv = env2.NO_COLOR !== undefined;
53907
+ if (hasColorArg) {
53908
+ return false;
53909
+ }
53910
+ if (hasForceColorEnv) {
53911
+ return false;
53912
+ }
53913
+ if (hasNoColorArg) {
53914
+ return true;
53915
+ }
53916
+ return hasNoColorEnv;
53917
+ }
53918
+ var noColor = resolveNoColorSetting(process.argv, process.env);
53919
+ var container = bootstrap({ noColor });
53553
53920
  function createContext(program2) {
53554
53921
  const opts = program2.opts();
53555
53922
  return {
53556
53923
  globalOptions: {
53557
53924
  json: opts.json,
53925
+ noColor: opts.color === false,
53558
53926
  workspace: opts.workspace,
53559
53927
  repo: opts.repo
53560
53928
  }
53561
53929
  };
53562
53930
  }
53931
+ async function runCommand(token, options, program2, context) {
53932
+ const cmd = container.resolve(token);
53933
+ const resolvedContext = context ?? createContext(program2);
53934
+ try {
53935
+ return await cmd.run(options, resolvedContext);
53936
+ } catch {
53937
+ return;
53938
+ }
53939
+ }
53563
53940
  function withGlobalOptions(options, context) {
53564
53941
  return {
53565
53942
  ...options,
@@ -53568,321 +53945,156 @@ function withGlobalOptions(options, context) {
53568
53945
  };
53569
53946
  }
53570
53947
  var cli = new Command;
53571
- cli.name("bb").description("A command-line interface for Bitbucket Cloud").version(pkg2.version).option("--json", "Output as JSON").option("-w, --workspace <workspace>", "Specify workspace").option("-r, --repo <repo>", "Specify repository").action(async () => {
53948
+ cli.name("bb").description("A command-line interface for Bitbucket Cloud").version(pkg2.version).option("--json", "Output as JSON").option("--no-color", "Disable color output").option("-w, --workspace <workspace>", "Specify workspace").option("-r, --repo <repo>", "Specify repository").action(async () => {
53572
53949
  cli.outputHelp();
53573
53950
  const versionService = container.resolve(ServiceTokens.VersionService);
53574
53951
  const output = container.resolve(ServiceTokens.OutputService);
53575
53952
  try {
53576
53953
  const result = await versionService.checkForUpdate();
53577
53954
  if (result?.updateAvailable) {
53578
- console.log("");
53579
- console.log("\u2500".repeat(50));
53580
- console.log(`\u26A0 A new version is available: ${result.latestVersion} (you have ${result.currentVersion})`);
53581
- console.log(` Run '${versionService.getInstallCommand()}' to update`);
53582
- console.log(` Or disable with 'bb config set skipVersionCheck true'`);
53583
- console.log("\u2500".repeat(50));
53955
+ output.text("");
53956
+ output.text("\u2500".repeat(50));
53957
+ output.text(`\u26A0 A new version is available: ${result.latestVersion} (you have ${result.currentVersion})`);
53958
+ output.text(` Run '${versionService.getInstallCommand()}' to update`);
53959
+ output.text(` Or disable with 'bb config set skipVersionCheck true'`);
53960
+ output.text("\u2500".repeat(50));
53584
53961
  }
53585
53962
  } catch {}
53586
53963
  });
53587
53964
  var authCmd = new Command("auth").description("Authenticate with Bitbucket");
53588
53965
  authCmd.command("login").description("Authenticate with Bitbucket using an API token").option("-u, --username <username>", "Bitbucket username").option("-p, --password <password>", "Bitbucket API token").action(async (options) => {
53589
- try {
53590
- const cmd = container.resolve(ServiceTokens.LoginCommand);
53591
- await cmd.execute(options, createContext(cli));
53592
- } catch {
53593
- process.exit(1);
53594
- }
53966
+ await runCommand(ServiceTokens.LoginCommand, options, cli);
53595
53967
  });
53596
53968
  authCmd.command("logout").description("Log out of Bitbucket").action(async () => {
53597
- try {
53598
- const cmd = container.resolve(ServiceTokens.LogoutCommand);
53599
- await cmd.execute(undefined, createContext(cli));
53600
- } catch {
53601
- process.exit(1);
53602
- }
53969
+ await runCommand(ServiceTokens.LogoutCommand, undefined, cli);
53603
53970
  });
53604
53971
  authCmd.command("status").description("Show authentication status").action(async () => {
53605
- try {
53606
- const cmd = container.resolve(ServiceTokens.StatusCommand);
53607
- await cmd.execute(undefined, createContext(cli));
53608
- } catch {
53609
- process.exit(1);
53610
- }
53972
+ await runCommand(ServiceTokens.StatusCommand, undefined, cli);
53611
53973
  });
53612
53974
  authCmd.command("token").description("Print the current access token").action(async () => {
53613
- try {
53614
- const cmd = container.resolve(ServiceTokens.TokenCommand);
53615
- await cmd.execute(undefined, createContext(cli));
53616
- } catch {
53617
- process.exit(1);
53618
- }
53975
+ await runCommand(ServiceTokens.TokenCommand, undefined, cli);
53619
53976
  });
53620
53977
  cli.addCommand(authCmd);
53621
53978
  var repoCmd = new Command("repo").description("Manage repositories");
53622
53979
  repoCmd.command("clone <repository>").description("Clone a Bitbucket repository").option("-d, --directory <dir>", "Directory to clone into").action(async (repository, options) => {
53623
- try {
53624
- const cmd = container.resolve(ServiceTokens.CloneCommand);
53625
- await cmd.execute({ repository, ...options }, createContext(cli));
53626
- } catch {
53627
- process.exit(1);
53628
- }
53980
+ await runCommand(ServiceTokens.CloneCommand, { repository, ...options }, cli);
53629
53981
  });
53630
53982
  repoCmd.command("create <name>").description("Create a new repository").option("-d, --description <description>", "Repository description").option("--private", "Create a private repository (default)").option("--public", "Create a public repository").option("-p, --project <project>", "Project key").action(async (name, options) => {
53631
- try {
53632
- const cmd = container.resolve(ServiceTokens.CreateRepoCommand);
53633
- const context = createContext(cli);
53634
- await cmd.execute(withGlobalOptions({ name, ...options }, context), context);
53635
- } catch {
53636
- process.exit(1);
53637
- }
53983
+ const context = createContext(cli);
53984
+ await runCommand(ServiceTokens.CreateRepoCommand, withGlobalOptions({ name, ...options }, context), cli, context);
53638
53985
  });
53639
53986
  repoCmd.command("list").description("List repositories").option("--limit <number>", "Maximum number of repositories to list", "25").action(async (options) => {
53640
- try {
53641
- const cmd = container.resolve(ServiceTokens.ListReposCommand);
53642
- const context = createContext(cli);
53643
- await cmd.execute(withGlobalOptions(options, context), context);
53644
- } catch {
53645
- process.exit(1);
53646
- }
53987
+ const context = createContext(cli);
53988
+ await runCommand(ServiceTokens.ListReposCommand, withGlobalOptions(options, context), cli, context);
53647
53989
  });
53648
53990
  repoCmd.command("view [repository]").description("View repository details").action(async (repository, options) => {
53649
- try {
53650
- const cmd = container.resolve(ServiceTokens.ViewRepoCommand);
53651
- const context = createContext(cli);
53652
- await cmd.execute(withGlobalOptions({ repository, ...options }, context), context);
53653
- } catch {
53654
- process.exit(1);
53655
- }
53991
+ const context = createContext(cli);
53992
+ await runCommand(ServiceTokens.ViewRepoCommand, withGlobalOptions({ repository, ...options }, context), cli, context);
53656
53993
  });
53657
53994
  repoCmd.command("delete <repository>").description("Delete a repository").option("-y, --yes", "Skip confirmation prompt").action(async (repository, options) => {
53658
- try {
53659
- const cmd = container.resolve(ServiceTokens.DeleteRepoCommand);
53660
- const context = createContext(cli);
53661
- await cmd.execute(withGlobalOptions({ repository, ...options }, context), context);
53662
- } catch {
53663
- process.exit(1);
53664
- }
53995
+ const context = createContext(cli);
53996
+ await runCommand(ServiceTokens.DeleteRepoCommand, withGlobalOptions({ repository, ...options }, context), cli, context);
53665
53997
  });
53666
53998
  cli.addCommand(repoCmd);
53667
53999
  var prCmd = new Command("pr").description("Manage pull requests");
53668
54000
  prCmd.command("create").description("Create a pull request").option("-t, --title <title>", "Pull request title").option("-b, --body <body>", "Pull request description").option("-s, --source <branch>", "Source branch (default: current branch)").option("-d, --destination <branch>", "Destination branch (default: main)").option("--close-source-branch", "Close source branch after merge").option("--draft", "Create the pull request as draft").action(async (options) => {
53669
- try {
53670
- const cmd = container.resolve(ServiceTokens.CreatePRCommand);
53671
- const context = createContext(cli);
53672
- await cmd.execute(withGlobalOptions(options, context), context);
53673
- } catch {
53674
- process.exit(1);
53675
- }
54001
+ const context = createContext(cli);
54002
+ await runCommand(ServiceTokens.CreatePRCommand, withGlobalOptions(options, context), cli, context);
53676
54003
  });
53677
54004
  prCmd.command("list").description("List pull requests").option("-s, --state <state>", "Filter by state (OPEN, MERGED, DECLINED, SUPERSEDED)", "OPEN").option("--limit <number>", "Maximum number of PRs to list", "25").action(async (options) => {
53678
- try {
53679
- const cmd = container.resolve(ServiceTokens.ListPRsCommand);
53680
- const context = createContext(cli);
53681
- await cmd.execute(withGlobalOptions(options, context), context);
53682
- } catch {
53683
- process.exit(1);
53684
- }
54005
+ const context = createContext(cli);
54006
+ await runCommand(ServiceTokens.ListPRsCommand, withGlobalOptions(options, context), cli, context);
53685
54007
  });
53686
54008
  prCmd.command("view <id>").description("View pull request details").action(async (id, options) => {
53687
- try {
53688
- const cmd = container.resolve(ServiceTokens.ViewPRCommand);
53689
- const context = createContext(cli);
53690
- await cmd.execute(withGlobalOptions({ id, ...options }, context), context);
53691
- } catch {
53692
- process.exit(1);
53693
- }
54009
+ const context = createContext(cli);
54010
+ await runCommand(ServiceTokens.ViewPRCommand, withGlobalOptions({ id, ...options }, context), cli, context);
53694
54011
  });
53695
54012
  prCmd.command("activity <id>").description("Show pull request activity log").option("--limit <number>", "Maximum number of activity entries", "25").option("--type <types>", "Filter activity by type (comma-separated)").action(async (id, options) => {
53696
- try {
53697
- const cmd = container.resolve(ServiceTokens.ActivityPRCommand);
53698
- const context = createContext(cli);
53699
- await cmd.execute(withGlobalOptions({ id, ...options }, context), context);
53700
- } catch {
53701
- process.exit(1);
53702
- }
54013
+ const context = createContext(cli);
54014
+ await runCommand(ServiceTokens.ActivityPRCommand, withGlobalOptions({ id, ...options }, context), cli, context);
53703
54015
  });
53704
54016
  prCmd.command("checks <id>").description("Show CI/CD checks and build status for a pull request").option("--json", "Output as JSON").action(async (id, options) => {
53705
- try {
53706
- const cmd = container.resolve(ServiceTokens.ChecksPRCommand);
53707
- const context = createContext(cli);
53708
- await cmd.execute(withGlobalOptions({ id, ...options }, context), context);
53709
- } catch {
53710
- process.exit(1);
53711
- }
54017
+ const context = createContext(cli);
54018
+ await runCommand(ServiceTokens.ChecksPRCommand, withGlobalOptions({ id, ...options }, context), cli, context);
53712
54019
  });
53713
54020
  prCmd.command("edit [id]").description("Edit a pull request").option("-t, --title <title>", "New pull request title").option("-b, --body <body>", "New pull request description").option("-F, --body-file <file>", "Read description from file").action(async (id, options) => {
53714
- try {
53715
- const cmd = container.resolve(ServiceTokens.EditPRCommand);
53716
- const context = createContext(cli);
53717
- await cmd.execute(withGlobalOptions({ id, ...options }, context), context);
53718
- } catch {
53719
- process.exit(1);
53720
- }
54021
+ const context = createContext(cli);
54022
+ await runCommand(ServiceTokens.EditPRCommand, withGlobalOptions({ id, ...options }, context), cli, context);
53721
54023
  });
53722
54024
  prCmd.command("merge <id>").description("Merge a pull request").option("-m, --message <message>", "Merge commit message").option("--close-source-branch", "Delete the source branch after merging").option("--strategy <strategy>", "Merge strategy (merge_commit, squash, fast_forward)").action(async (id, options) => {
53723
- try {
53724
- const cmd = container.resolve(ServiceTokens.MergePRCommand);
53725
- const context = createContext(cli);
53726
- await cmd.execute(withGlobalOptions({ id, ...options }, context), context);
53727
- } catch {
53728
- process.exit(1);
53729
- }
54025
+ const context = createContext(cli);
54026
+ await runCommand(ServiceTokens.MergePRCommand, withGlobalOptions({ id, ...options }, context), cli, context);
53730
54027
  });
53731
54028
  prCmd.command("approve <id>").description("Approve a pull request").action(async (id, options) => {
53732
- try {
53733
- const cmd = container.resolve(ServiceTokens.ApprovePRCommand);
53734
- const context = createContext(cli);
53735
- await cmd.execute(withGlobalOptions({ id, ...options }, context), context);
53736
- } catch {
53737
- process.exit(1);
53738
- }
54029
+ const context = createContext(cli);
54030
+ await runCommand(ServiceTokens.ApprovePRCommand, withGlobalOptions({ id, ...options }, context), cli, context);
53739
54031
  });
53740
54032
  prCmd.command("decline <id>").description("Decline a pull request").action(async (id, options) => {
53741
- try {
53742
- const cmd = container.resolve(ServiceTokens.DeclinePRCommand);
53743
- const context = createContext(cli);
53744
- await cmd.execute(withGlobalOptions({ id, ...options }, context), context);
53745
- } catch {
53746
- process.exit(1);
53747
- }
54033
+ const context = createContext(cli);
54034
+ await runCommand(ServiceTokens.DeclinePRCommand, withGlobalOptions({ id, ...options }, context), cli, context);
53748
54035
  });
53749
54036
  prCmd.command("ready <id>").description("Mark a draft pull request as ready for review").action(async (id, options) => {
53750
- try {
53751
- const cmd = container.resolve(ServiceTokens.ReadyPRCommand);
53752
- const context = createContext(cli);
53753
- await cmd.execute(withGlobalOptions({ id, ...options }, context), context);
53754
- } catch {
53755
- process.exit(1);
53756
- }
54037
+ const context = createContext(cli);
54038
+ await runCommand(ServiceTokens.ReadyPRCommand, withGlobalOptions({ id, ...options }, context), cli, context);
53757
54039
  });
53758
54040
  prCmd.command("checkout <id>").description("Checkout a pull request locally").action(async (id, options) => {
53759
- try {
53760
- const cmd = container.resolve(ServiceTokens.CheckoutPRCommand);
53761
- const context = createContext(cli);
53762
- await cmd.execute(withGlobalOptions({ id, ...options }, context), context);
53763
- } catch {
53764
- process.exit(1);
53765
- }
54041
+ const context = createContext(cli);
54042
+ await runCommand(ServiceTokens.CheckoutPRCommand, withGlobalOptions({ id, ...options }, context), cli, context);
53766
54043
  });
53767
54044
  prCmd.command("diff [id]").description("View pull request diff").option("--color <when>", "Colorize output (auto, always, never)", "auto").option("--name-only", "Show only names of changed files").option("--stat", "Show diffstat").option("-w, --web", "Open diff in web browser").action(async (id, options) => {
53768
- try {
53769
- const cmd = container.resolve(ServiceTokens.DiffPRCommand);
53770
- const context = createContext(cli);
53771
- await cmd.execute(withGlobalOptions({ id, ...options }, context), context);
53772
- } catch {
53773
- process.exit(1);
53774
- }
54045
+ const context = createContext(cli);
54046
+ await runCommand(ServiceTokens.DiffPRCommand, withGlobalOptions({ id, ...options }, context), cli, context);
53775
54047
  });
53776
54048
  var prCommentsCmd = new Command("comments").description("Manage pull request comments");
53777
54049
  prCommentsCmd.command("list <id>").description("List comments on a pull request").option("--limit <number>", "Maximum number of comments (default: 25)").option("--no-truncate", "Show full comment content without truncation").action(async (id, options) => {
53778
- try {
53779
- const cmd = container.resolve(ServiceTokens.ListCommentsPRCommand);
53780
- const context = createContext(cli);
53781
- await cmd.execute(withGlobalOptions({ id, ...options }, context), context);
53782
- } catch {
53783
- process.exit(1);
53784
- }
54050
+ const context = createContext(cli);
54051
+ await runCommand(ServiceTokens.ListCommentsPRCommand, withGlobalOptions({ id, ...options }, context), cli, context);
53785
54052
  });
53786
- prCommentsCmd.command("add <id> <message>").description("Add a comment to a pull request").action(async (id, message, options) => {
53787
- try {
53788
- const cmd = container.resolve(ServiceTokens.CommentPRCommand);
53789
- const context = createContext(cli);
53790
- await cmd.execute(withGlobalOptions({ id, message }, context), context);
53791
- } catch {
53792
- process.exit(1);
53793
- }
54053
+ prCommentsCmd.command("add <id> <message>").description("Add a comment to a pull request").option("--file <path>", "File path in the diff for inline comment").option("--line-to <number>", "Line number in the new file version").option("--line-from <number>", "Line number in the old file version").action(async (id, message, options) => {
54054
+ const context = createContext(cli);
54055
+ await runCommand(ServiceTokens.CommentPRCommand, withGlobalOptions({ id, message, ...options }, context), cli, context);
53794
54056
  });
53795
54057
  prCommentsCmd.command("edit <pr-id> <comment-id> <message>").description("Edit a comment on a pull request").action(async (prId, commentId, message, options) => {
53796
- try {
53797
- const cmd = container.resolve(ServiceTokens.EditCommentPRCommand);
53798
- const context = createContext(cli);
53799
- await cmd.execute(withGlobalOptions({ prId, commentId, message }, context), context);
53800
- } catch {
53801
- process.exit(1);
53802
- }
54058
+ const context = createContext(cli);
54059
+ await runCommand(ServiceTokens.EditCommentPRCommand, withGlobalOptions({ prId, commentId, message }, context), cli, context);
53803
54060
  });
53804
54061
  prCommentsCmd.command("delete <pr-id> <comment-id>").description("Delete a comment on a pull request").action(async (prId, commentId, options) => {
53805
- try {
53806
- const cmd = container.resolve(ServiceTokens.DeleteCommentPRCommand);
53807
- const context = createContext(cli);
53808
- await cmd.execute(withGlobalOptions({ prId, commentId }, context), context);
53809
- } catch {
53810
- process.exit(1);
53811
- }
54062
+ const context = createContext(cli);
54063
+ await runCommand(ServiceTokens.DeleteCommentPRCommand, withGlobalOptions({ prId, commentId }, context), cli, context);
53812
54064
  });
53813
54065
  var prReviewersCmd = new Command("reviewers").description("Manage pull request reviewers");
53814
54066
  prReviewersCmd.command("list <id>").description("List reviewers on a pull request").action(async (id, options) => {
53815
- try {
53816
- const cmd = container.resolve(ServiceTokens.ListReviewersPRCommand);
53817
- const context = createContext(cli);
53818
- await cmd.execute(withGlobalOptions({ id, ...options }, context), context);
53819
- } catch {
53820
- process.exit(1);
53821
- }
54067
+ const context = createContext(cli);
54068
+ await runCommand(ServiceTokens.ListReviewersPRCommand, withGlobalOptions({ id, ...options }, context), cli, context);
53822
54069
  });
53823
54070
  prReviewersCmd.command("add <id> <username>").description("Add a reviewer to a pull request").action(async (id, username, options) => {
53824
- try {
53825
- const cmd = container.resolve(ServiceTokens.AddReviewerPRCommand);
53826
- const context = createContext(cli);
53827
- await cmd.execute(withGlobalOptions({ id, username, ...options }, context), context);
53828
- } catch {
53829
- process.exit(1);
53830
- }
54071
+ const context = createContext(cli);
54072
+ await runCommand(ServiceTokens.AddReviewerPRCommand, withGlobalOptions({ id, username, ...options }, context), cli, context);
53831
54073
  });
53832
54074
  prReviewersCmd.command("remove <id> <username>").description("Remove a reviewer from a pull request").action(async (id, username, options) => {
53833
- try {
53834
- const cmd = container.resolve(ServiceTokens.RemoveReviewerPRCommand);
53835
- const context = createContext(cli);
53836
- await cmd.execute(withGlobalOptions({ id, username, ...options }, context), context);
53837
- } catch {
53838
- process.exit(1);
53839
- }
54075
+ const context = createContext(cli);
54076
+ await runCommand(ServiceTokens.RemoveReviewerPRCommand, withGlobalOptions({ id, username, ...options }, context), cli, context);
53840
54077
  });
53841
54078
  cli.addCommand(prCmd);
53842
54079
  prCmd.addCommand(prCommentsCmd);
53843
54080
  prCmd.addCommand(prReviewersCmd);
53844
54081
  var configCmd = new Command("config").description("Manage configuration");
53845
54082
  configCmd.command("get <key>").description("Get a configuration value").action(async (key) => {
53846
- try {
53847
- const cmd = container.resolve(ServiceTokens.GetConfigCommand);
53848
- await cmd.execute({ key }, createContext(cli));
53849
- } catch {
53850
- process.exit(1);
53851
- }
54083
+ await runCommand(ServiceTokens.GetConfigCommand, { key }, cli);
53852
54084
  });
53853
54085
  configCmd.command("set <key> <value>").description("Set a configuration value").action(async (key, value) => {
53854
- try {
53855
- const cmd = container.resolve(ServiceTokens.SetConfigCommand);
53856
- await cmd.execute({ key, value }, createContext(cli));
53857
- } catch {
53858
- process.exit(1);
53859
- }
54086
+ await runCommand(ServiceTokens.SetConfigCommand, { key, value }, cli);
53860
54087
  });
53861
54088
  configCmd.command("list").description("List all configuration values").action(async () => {
53862
- try {
53863
- const cmd = container.resolve(ServiceTokens.ListConfigCommand);
53864
- await cmd.execute(undefined, createContext(cli));
53865
- } catch {
53866
- process.exit(1);
53867
- }
54089
+ await runCommand(ServiceTokens.ListConfigCommand, undefined, cli);
53868
54090
  });
53869
54091
  cli.addCommand(configCmd);
53870
54092
  var completionCmd = new Command("completion").description("Shell completion utilities");
53871
54093
  completionCmd.command("install").description("Install shell completions for bash, zsh, or fish").action(async () => {
53872
- try {
53873
- const cmd = container.resolve(ServiceTokens.InstallCompletionCommand);
53874
- await cmd.execute(undefined, createContext(cli));
53875
- } catch {
53876
- process.exit(1);
53877
- }
54094
+ await runCommand(ServiceTokens.InstallCompletionCommand, undefined, cli);
53878
54095
  });
53879
54096
  completionCmd.command("uninstall").description("Uninstall shell completions").action(async () => {
53880
- try {
53881
- const cmd = container.resolve(ServiceTokens.UninstallCompletionCommand);
53882
- await cmd.execute(undefined, createContext(cli));
53883
- } catch {
53884
- process.exit(1);
53885
- }
54097
+ await runCommand(ServiceTokens.UninstallCompletionCommand, undefined, cli);
53886
54098
  });
53887
54099
  cli.addCommand(completionCmd);
53888
54100