@pilatos/bitbucket-cli 1.7.1 → 1.8.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.js +507 -123
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -44211,7 +44211,7 @@ var ServiceTokens = {
|
|
|
44211
44211
|
};
|
|
44212
44212
|
|
|
44213
44213
|
// src/services/config.service.ts
|
|
44214
|
-
import { join } from "path";
|
|
44214
|
+
import { join, win32 } from "path";
|
|
44215
44215
|
import { homedir } from "os";
|
|
44216
44216
|
|
|
44217
44217
|
// src/types/errors.ts
|
|
@@ -44282,9 +44282,24 @@ class ConfigService {
|
|
|
44282
44282
|
configDir;
|
|
44283
44283
|
configFile;
|
|
44284
44284
|
configCache = null;
|
|
44285
|
-
constructor(configDir) {
|
|
44286
|
-
|
|
44287
|
-
|
|
44285
|
+
constructor(configDir, options = {}) {
|
|
44286
|
+
const platform = options.platform ?? process.platform;
|
|
44287
|
+
const joinPath = platform === "win32" ? win32.join : join;
|
|
44288
|
+
this.configDir = configDir ?? this.resolveDefaultConfigDir({ ...options, platform });
|
|
44289
|
+
this.configFile = joinPath(this.configDir, "config.json");
|
|
44290
|
+
}
|
|
44291
|
+
resolveDefaultConfigDir(options) {
|
|
44292
|
+
const platform = options.platform ?? process.platform;
|
|
44293
|
+
if (platform === "win32") {
|
|
44294
|
+
const appDataDir = options.appData ?? process.env.APPDATA;
|
|
44295
|
+
if (appDataDir) {
|
|
44296
|
+
return win32.join(appDataDir, "bb");
|
|
44297
|
+
}
|
|
44298
|
+
const homeDir2 = options.homeDir ?? homedir();
|
|
44299
|
+
return win32.join(homeDir2, "AppData", "Roaming", "bb");
|
|
44300
|
+
}
|
|
44301
|
+
const homeDir = options.homeDir ?? homedir();
|
|
44302
|
+
return join(homeDir, ".config", "bb");
|
|
44288
44303
|
}
|
|
44289
44304
|
async ensureConfigDir() {
|
|
44290
44305
|
try {
|
|
@@ -44354,6 +44369,11 @@ class ConfigService {
|
|
|
44354
44369
|
apiToken: credentials.apiToken
|
|
44355
44370
|
});
|
|
44356
44371
|
}
|
|
44372
|
+
async clearCredentials() {
|
|
44373
|
+
const config = await this.getConfig();
|
|
44374
|
+
const { username: _username, apiToken: _apiToken, ...rest } = config;
|
|
44375
|
+
await this.setConfig(rest);
|
|
44376
|
+
}
|
|
44357
44377
|
async clearConfig() {
|
|
44358
44378
|
this.configCache = null;
|
|
44359
44379
|
await this.setConfig({});
|
|
@@ -45018,6 +45038,9 @@ class OutputService {
|
|
|
45018
45038
|
json(data) {
|
|
45019
45039
|
console.log(JSON.stringify(data, null, 2));
|
|
45020
45040
|
}
|
|
45041
|
+
jsonError(data) {
|
|
45042
|
+
console.error(JSON.stringify(data));
|
|
45043
|
+
}
|
|
45021
45044
|
table(headers, rows) {
|
|
45022
45045
|
if (rows.length === 0) {
|
|
45023
45046
|
return;
|
|
@@ -45103,6 +45126,109 @@ class OutputService {
|
|
|
45103
45126
|
return this.format(text, source_default.underline);
|
|
45104
45127
|
}
|
|
45105
45128
|
}
|
|
45129
|
+
// src/types/config.ts
|
|
45130
|
+
var SETTABLE_CONFIG_KEYS = [
|
|
45131
|
+
"defaultWorkspace",
|
|
45132
|
+
"skipVersionCheck",
|
|
45133
|
+
"versionCheckInterval"
|
|
45134
|
+
];
|
|
45135
|
+
var READABLE_CONFIG_KEYS = [
|
|
45136
|
+
"username",
|
|
45137
|
+
"defaultWorkspace",
|
|
45138
|
+
"skipVersionCheck",
|
|
45139
|
+
"versionCheckInterval"
|
|
45140
|
+
];
|
|
45141
|
+
function isSettableConfigKey(key) {
|
|
45142
|
+
return SETTABLE_CONFIG_KEYS.includes(key);
|
|
45143
|
+
}
|
|
45144
|
+
function isReadableConfigKey(key) {
|
|
45145
|
+
return READABLE_CONFIG_KEYS.includes(key);
|
|
45146
|
+
}
|
|
45147
|
+
function parseBooleanLiteral(value) {
|
|
45148
|
+
const normalized = value.trim().toLowerCase();
|
|
45149
|
+
if (normalized === "true") {
|
|
45150
|
+
return true;
|
|
45151
|
+
}
|
|
45152
|
+
if (normalized === "false") {
|
|
45153
|
+
return false;
|
|
45154
|
+
}
|
|
45155
|
+
return;
|
|
45156
|
+
}
|
|
45157
|
+
function parsePositiveIntegerLiteral(value) {
|
|
45158
|
+
const normalized = value.trim();
|
|
45159
|
+
if (!/^[1-9]\d*$/.test(normalized)) {
|
|
45160
|
+
return;
|
|
45161
|
+
}
|
|
45162
|
+
const parsed = Number.parseInt(normalized, 10);
|
|
45163
|
+
if (!Number.isSafeInteger(parsed)) {
|
|
45164
|
+
return;
|
|
45165
|
+
}
|
|
45166
|
+
return parsed;
|
|
45167
|
+
}
|
|
45168
|
+
function parseSettableConfigValue(key, value) {
|
|
45169
|
+
switch (key) {
|
|
45170
|
+
case "defaultWorkspace":
|
|
45171
|
+
return value;
|
|
45172
|
+
case "skipVersionCheck": {
|
|
45173
|
+
const parsed = parseBooleanLiteral(value);
|
|
45174
|
+
if (parsed === undefined) {
|
|
45175
|
+
throw new BBError({
|
|
45176
|
+
code: 5002 /* VALIDATION_INVALID */,
|
|
45177
|
+
message: "Invalid value for 'skipVersionCheck'. Expected 'true' or 'false'.",
|
|
45178
|
+
context: { key, value }
|
|
45179
|
+
});
|
|
45180
|
+
}
|
|
45181
|
+
return parsed;
|
|
45182
|
+
}
|
|
45183
|
+
case "versionCheckInterval": {
|
|
45184
|
+
const parsed = parsePositiveIntegerLiteral(value);
|
|
45185
|
+
if (parsed === undefined) {
|
|
45186
|
+
throw new BBError({
|
|
45187
|
+
code: 5002 /* VALIDATION_INVALID */,
|
|
45188
|
+
message: "Invalid value for 'versionCheckInterval'. Expected a positive integer (1 or greater).",
|
|
45189
|
+
context: { key, value }
|
|
45190
|
+
});
|
|
45191
|
+
}
|
|
45192
|
+
return parsed;
|
|
45193
|
+
}
|
|
45194
|
+
}
|
|
45195
|
+
}
|
|
45196
|
+
function coerceSkipVersionCheckValue(value) {
|
|
45197
|
+
if (typeof value === "boolean") {
|
|
45198
|
+
return value;
|
|
45199
|
+
}
|
|
45200
|
+
if (typeof value === "string") {
|
|
45201
|
+
return parseBooleanLiteral(value);
|
|
45202
|
+
}
|
|
45203
|
+
return;
|
|
45204
|
+
}
|
|
45205
|
+
function coerceVersionCheckIntervalValue(value) {
|
|
45206
|
+
if (typeof value === "number") {
|
|
45207
|
+
if (!Number.isSafeInteger(value) || value < 1) {
|
|
45208
|
+
return;
|
|
45209
|
+
}
|
|
45210
|
+
return value;
|
|
45211
|
+
}
|
|
45212
|
+
if (typeof value === "string") {
|
|
45213
|
+
return parsePositiveIntegerLiteral(value);
|
|
45214
|
+
}
|
|
45215
|
+
return;
|
|
45216
|
+
}
|
|
45217
|
+
function normalizeReadableConfigValue(key, value) {
|
|
45218
|
+
if (value === undefined || value === null) {
|
|
45219
|
+
return;
|
|
45220
|
+
}
|
|
45221
|
+
switch (key) {
|
|
45222
|
+
case "skipVersionCheck":
|
|
45223
|
+
return coerceSkipVersionCheckValue(value);
|
|
45224
|
+
case "versionCheckInterval":
|
|
45225
|
+
return coerceVersionCheckIntervalValue(value);
|
|
45226
|
+
case "username":
|
|
45227
|
+
case "defaultWorkspace":
|
|
45228
|
+
return typeof value === "string" ? value : undefined;
|
|
45229
|
+
}
|
|
45230
|
+
}
|
|
45231
|
+
|
|
45106
45232
|
// src/services/version.service.ts
|
|
45107
45233
|
var NPM_REGISTRY_URL = "https://registry.npmjs.org/@pilatos/bitbucket-cli";
|
|
45108
45234
|
var PACKAGE_NAME = "@pilatos/bitbucket-cli";
|
|
@@ -45115,7 +45241,8 @@ class VersionService {
|
|
|
45115
45241
|
this.currentVersion = currentVersion;
|
|
45116
45242
|
}
|
|
45117
45243
|
async checkForUpdate() {
|
|
45118
|
-
const
|
|
45244
|
+
const skipCheckRaw = await this.configService.getValue("skipVersionCheck");
|
|
45245
|
+
const skipCheck = coerceSkipVersionCheckValue(skipCheckRaw);
|
|
45119
45246
|
if (skipCheck === true) {
|
|
45120
45247
|
return null;
|
|
45121
45248
|
}
|
|
@@ -45148,7 +45275,7 @@ class VersionService {
|
|
|
45148
45275
|
const now = new Date;
|
|
45149
45276
|
const timeSinceLastCheck = now.getTime() - lastCheckDate.getTime();
|
|
45150
45277
|
const intervalDays = await this.configService.getValue("versionCheckInterval");
|
|
45151
|
-
const days =
|
|
45278
|
+
const days = coerceVersionCheckIntervalValue(intervalDays) ?? 1;
|
|
45152
45279
|
const intervalMs = days * 24 * 60 * 60 * 1000;
|
|
45153
45280
|
return timeSinceLastCheck >= intervalMs;
|
|
45154
45281
|
}
|
|
@@ -51518,7 +51645,9 @@ class BaseCommand {
|
|
|
51518
51645
|
}
|
|
51519
51646
|
}
|
|
51520
51647
|
handleError(error, context) {
|
|
51521
|
-
if (
|
|
51648
|
+
if (context.globalOptions.json) {
|
|
51649
|
+
this.output.jsonError(this.normalizeErrorForJson(error));
|
|
51650
|
+
} else if (error instanceof Error) {
|
|
51522
51651
|
this.output.error(error.message);
|
|
51523
51652
|
} else {
|
|
51524
51653
|
this.output.error(String(error));
|
|
@@ -51527,6 +51656,23 @@ class BaseCommand {
|
|
|
51527
51656
|
process.exitCode = 1;
|
|
51528
51657
|
}
|
|
51529
51658
|
}
|
|
51659
|
+
normalizeErrorForJson(error) {
|
|
51660
|
+
if (error instanceof BBError) {
|
|
51661
|
+
return error.toJSON();
|
|
51662
|
+
}
|
|
51663
|
+
if (error instanceof Error) {
|
|
51664
|
+
return {
|
|
51665
|
+
name: error.name,
|
|
51666
|
+
code: 9999 /* UNKNOWN */,
|
|
51667
|
+
message: error.message
|
|
51668
|
+
};
|
|
51669
|
+
}
|
|
51670
|
+
return {
|
|
51671
|
+
name: "Error",
|
|
51672
|
+
code: 9999 /* UNKNOWN */,
|
|
51673
|
+
message: String(error)
|
|
51674
|
+
};
|
|
51675
|
+
}
|
|
51530
51676
|
requireOption(value, name, message) {
|
|
51531
51677
|
if (value === undefined || value === null || value === "") {
|
|
51532
51678
|
throw new BBError({
|
|
@@ -51553,10 +51699,16 @@ class LoginCommand extends BaseCommand {
|
|
|
51553
51699
|
const username = options.username || process.env.BB_USERNAME;
|
|
51554
51700
|
const apiToken = options.password || process.env.BB_API_TOKEN;
|
|
51555
51701
|
if (!username) {
|
|
51556
|
-
throw new
|
|
51702
|
+
throw new BBError({
|
|
51703
|
+
code: 5001 /* VALIDATION_REQUIRED */,
|
|
51704
|
+
message: "Username is required. Use --username option or set BB_USERNAME environment variable."
|
|
51705
|
+
});
|
|
51557
51706
|
}
|
|
51558
51707
|
if (!apiToken) {
|
|
51559
|
-
throw new
|
|
51708
|
+
throw new BBError({
|
|
51709
|
+
code: 5001 /* VALIDATION_REQUIRED */,
|
|
51710
|
+
message: "API token is required. Use --password option or set BB_API_TOKEN environment variable."
|
|
51711
|
+
});
|
|
51560
51712
|
}
|
|
51561
51713
|
await this.configService.setCredentials({ username, apiToken });
|
|
51562
51714
|
try {
|
|
@@ -51575,8 +51727,11 @@ class LoginCommand extends BaseCommand {
|
|
|
51575
51727
|
}
|
|
51576
51728
|
this.output.success(`Logged in as ${user.display_name} (${user.username})`);
|
|
51577
51729
|
} catch (error) {
|
|
51578
|
-
await this.configService.
|
|
51579
|
-
throw new
|
|
51730
|
+
await this.configService.clearCredentials();
|
|
51731
|
+
throw new BBError({
|
|
51732
|
+
code: 1002 /* AUTH_INVALID */,
|
|
51733
|
+
message: `Authentication failed: ${error instanceof Error ? error.message : String(error)}`
|
|
51734
|
+
});
|
|
51580
51735
|
}
|
|
51581
51736
|
}
|
|
51582
51737
|
}
|
|
@@ -51591,7 +51746,7 @@ class LogoutCommand extends BaseCommand {
|
|
|
51591
51746
|
this.configService = configService;
|
|
51592
51747
|
}
|
|
51593
51748
|
async execute(_options, context) {
|
|
51594
|
-
await this.configService.
|
|
51749
|
+
await this.configService.clearCredentials();
|
|
51595
51750
|
if (context.globalOptions.json) {
|
|
51596
51751
|
this.output.json({ authenticated: false, success: true });
|
|
51597
51752
|
return;
|
|
@@ -51645,7 +51800,11 @@ class StatusCommand extends BaseCommand {
|
|
|
51645
51800
|
this.output.text(` Default workspace: ${this.output.highlight(config.defaultWorkspace)}`);
|
|
51646
51801
|
}
|
|
51647
51802
|
} catch (error) {
|
|
51648
|
-
throw new
|
|
51803
|
+
throw new BBError({
|
|
51804
|
+
code: 1002 /* AUTH_INVALID */,
|
|
51805
|
+
message: `Authentication is invalid or expired. Run ${this.output.highlight("bb auth login")} to re-authenticate.`,
|
|
51806
|
+
cause: error instanceof Error ? error : undefined
|
|
51807
|
+
});
|
|
51649
51808
|
}
|
|
51650
51809
|
}
|
|
51651
51810
|
}
|
|
@@ -51662,7 +51821,10 @@ class TokenCommand extends BaseCommand {
|
|
|
51662
51821
|
async execute(_options, context) {
|
|
51663
51822
|
const credentials = await this.configService.getCredentials();
|
|
51664
51823
|
if (!credentials.username || !credentials.apiToken) {
|
|
51665
|
-
throw new
|
|
51824
|
+
throw new BBError({
|
|
51825
|
+
code: 1001 /* AUTH_REQUIRED */,
|
|
51826
|
+
message: "Not authenticated. Run 'bb auth login' first."
|
|
51827
|
+
});
|
|
51666
51828
|
}
|
|
51667
51829
|
const token = Buffer.from(`${credentials.username}:${credentials.apiToken}`).toString("base64");
|
|
51668
51830
|
if (context.globalOptions.json) {
|
|
@@ -51710,7 +51872,10 @@ class CloneCommand extends BaseCommand {
|
|
|
51710
51872
|
if (parts.length === 1) {
|
|
51711
51873
|
const config = await this.configService.getConfig();
|
|
51712
51874
|
if (!config.defaultWorkspace) {
|
|
51713
|
-
throw new
|
|
51875
|
+
throw new BBError({
|
|
51876
|
+
code: 6002 /* CONTEXT_WORKSPACE_NOT_FOUND */,
|
|
51877
|
+
message: "No workspace specified. Use workspace/repo format or set a default workspace."
|
|
51878
|
+
});
|
|
51714
51879
|
}
|
|
51715
51880
|
workspace = config.defaultWorkspace;
|
|
51716
51881
|
repoSlug = parts[0];
|
|
@@ -51718,7 +51883,11 @@ class CloneCommand extends BaseCommand {
|
|
|
51718
51883
|
workspace = parts[0];
|
|
51719
51884
|
repoSlug = parts[1];
|
|
51720
51885
|
} else {
|
|
51721
|
-
throw new
|
|
51886
|
+
throw new BBError({
|
|
51887
|
+
code: 5002 /* VALIDATION_INVALID */,
|
|
51888
|
+
message: "Invalid repository format. Use workspace/repo or a full URL.",
|
|
51889
|
+
context: { repository }
|
|
51890
|
+
});
|
|
51722
51891
|
}
|
|
51723
51892
|
return `git@bitbucket.org:${workspace}/${repoSlug}.git`;
|
|
51724
51893
|
}
|
|
@@ -51726,7 +51895,11 @@ class CloneCommand extends BaseCommand {
|
|
|
51726
51895
|
const parts = repository.split("/");
|
|
51727
51896
|
const lastPart = parts.at(-1);
|
|
51728
51897
|
if (!lastPart) {
|
|
51729
|
-
throw new
|
|
51898
|
+
throw new BBError({
|
|
51899
|
+
code: 5002 /* VALIDATION_INVALID */,
|
|
51900
|
+
message: "Invalid repository format.",
|
|
51901
|
+
context: { repository }
|
|
51902
|
+
});
|
|
51730
51903
|
}
|
|
51731
51904
|
return lastPart.replace(".git", "");
|
|
51732
51905
|
}
|
|
@@ -51782,12 +51955,61 @@ class CreateRepoCommand extends BaseCommand {
|
|
|
51782
51955
|
}
|
|
51783
51956
|
const config = await this.configService.getConfig();
|
|
51784
51957
|
if (!config.defaultWorkspace) {
|
|
51785
|
-
throw new
|
|
51958
|
+
throw new BBError({
|
|
51959
|
+
code: 6002 /* CONTEXT_WORKSPACE_NOT_FOUND */,
|
|
51960
|
+
message: "No workspace specified. Use --workspace option or set a default workspace."
|
|
51961
|
+
});
|
|
51786
51962
|
}
|
|
51787
51963
|
return config.defaultWorkspace;
|
|
51788
51964
|
}
|
|
51789
51965
|
}
|
|
51790
51966
|
|
|
51967
|
+
// src/services/pagination.ts
|
|
51968
|
+
var DEFAULT_LIMIT = 25;
|
|
51969
|
+
var MAX_PAGE_LENGTH = 50;
|
|
51970
|
+
function parseLimit(limit, fallback = DEFAULT_LIMIT) {
|
|
51971
|
+
if (!limit) {
|
|
51972
|
+
return fallback;
|
|
51973
|
+
}
|
|
51974
|
+
const parsed = Number.parseInt(limit, 10);
|
|
51975
|
+
if (Number.isNaN(parsed) || parsed <= 0) {
|
|
51976
|
+
return fallback;
|
|
51977
|
+
}
|
|
51978
|
+
return parsed;
|
|
51979
|
+
}
|
|
51980
|
+
async function collectPages(options) {
|
|
51981
|
+
const { fetchPage, shouldInclude } = options;
|
|
51982
|
+
const limit = Math.max(0, options.limit);
|
|
51983
|
+
if (limit === 0) {
|
|
51984
|
+
return [];
|
|
51985
|
+
}
|
|
51986
|
+
const requestedPageSize = options.pageSize ?? limit;
|
|
51987
|
+
const pagelen = Math.max(1, Math.min(requestedPageSize, MAX_PAGE_LENGTH));
|
|
51988
|
+
const items = [];
|
|
51989
|
+
let page = 1;
|
|
51990
|
+
while (items.length < limit) {
|
|
51991
|
+
const data = await fetchPage(page, pagelen);
|
|
51992
|
+
const pageValues = data.values ? Array.from(data.values) : [];
|
|
51993
|
+
if (pageValues.length === 0) {
|
|
51994
|
+
break;
|
|
51995
|
+
}
|
|
51996
|
+
for (const value of pageValues) {
|
|
51997
|
+
if (shouldInclude && !shouldInclude(value)) {
|
|
51998
|
+
continue;
|
|
51999
|
+
}
|
|
52000
|
+
items.push(value);
|
|
52001
|
+
if (items.length >= limit) {
|
|
52002
|
+
return items;
|
|
52003
|
+
}
|
|
52004
|
+
}
|
|
52005
|
+
if (!data.next) {
|
|
52006
|
+
break;
|
|
52007
|
+
}
|
|
52008
|
+
page += 1;
|
|
52009
|
+
}
|
|
52010
|
+
return items;
|
|
52011
|
+
}
|
|
52012
|
+
|
|
51791
52013
|
// src/commands/repo/list.command.ts
|
|
51792
52014
|
class ListReposCommand extends BaseCommand {
|
|
51793
52015
|
repositoriesApi;
|
|
@@ -51801,11 +52023,18 @@ class ListReposCommand extends BaseCommand {
|
|
|
51801
52023
|
}
|
|
51802
52024
|
async execute(options, context) {
|
|
51803
52025
|
const workspace = await this.resolveWorkspace(options.workspace ?? context.globalOptions.workspace);
|
|
51804
|
-
const limit =
|
|
51805
|
-
const
|
|
51806
|
-
|
|
52026
|
+
const limit = parseLimit(options.limit);
|
|
52027
|
+
const repos = await collectPages({
|
|
52028
|
+
limit,
|
|
52029
|
+
fetchPage: async (page, pagelen) => {
|
|
52030
|
+
const response = await this.repositoriesApi.repositoriesWorkspaceGet({
|
|
52031
|
+
workspace
|
|
52032
|
+
}, {
|
|
52033
|
+
params: { page, pagelen }
|
|
52034
|
+
});
|
|
52035
|
+
return response.data;
|
|
52036
|
+
}
|
|
51807
52037
|
});
|
|
51808
|
-
const repos = Array.from(response.data.values ?? []).slice(0, limit);
|
|
51809
52038
|
if (context.globalOptions.json) {
|
|
51810
52039
|
this.output.json({
|
|
51811
52040
|
workspace,
|
|
@@ -51831,7 +52060,10 @@ class ListReposCommand extends BaseCommand {
|
|
|
51831
52060
|
}
|
|
51832
52061
|
const config = await this.configService.getConfig();
|
|
51833
52062
|
if (!config.defaultWorkspace) {
|
|
51834
|
-
throw new
|
|
52063
|
+
throw new BBError({
|
|
52064
|
+
code: 6002 /* CONTEXT_WORKSPACE_NOT_FOUND */,
|
|
52065
|
+
message: "No workspace specified. Use --workspace option or set a default workspace."
|
|
52066
|
+
});
|
|
51835
52067
|
}
|
|
51836
52068
|
return config.defaultWorkspace;
|
|
51837
52069
|
}
|
|
@@ -51916,8 +52148,11 @@ class DeleteRepoCommand extends BaseCommand {
|
|
|
51916
52148
|
}
|
|
51917
52149
|
const repoContext = await this.contextService.requireRepoContext(contextOptions);
|
|
51918
52150
|
if (!yes) {
|
|
51919
|
-
throw new
|
|
51920
|
-
|
|
52151
|
+
throw new BBError({
|
|
52152
|
+
code: 5001 /* VALIDATION_REQUIRED */,
|
|
52153
|
+
message: `This will permanently delete ${repoContext.workspace}/${repoContext.repoSlug}.
|
|
52154
|
+
` + "Use --yes to confirm deletion."
|
|
52155
|
+
});
|
|
51921
52156
|
}
|
|
51922
52157
|
await this.repositoriesApi.repositoriesWorkspaceRepoSlugDelete({
|
|
51923
52158
|
workspace: repoContext.workspace,
|
|
@@ -51950,7 +52185,10 @@ class CreatePRCommand extends BaseCommand {
|
|
|
51950
52185
|
}
|
|
51951
52186
|
async execute(options, context) {
|
|
51952
52187
|
if (!options.title) {
|
|
51953
|
-
throw new
|
|
52188
|
+
throw new BBError({
|
|
52189
|
+
code: 5001 /* VALIDATION_REQUIRED */,
|
|
52190
|
+
message: "Pull request title is required. Use --title option."
|
|
52191
|
+
});
|
|
51954
52192
|
}
|
|
51955
52193
|
const repoContext = await this.contextService.requireRepoContext({
|
|
51956
52194
|
...context.globalOptions,
|
|
@@ -52014,13 +52252,20 @@ class ListPRsCommand extends BaseCommand {
|
|
|
52014
52252
|
...options
|
|
52015
52253
|
});
|
|
52016
52254
|
const state = options.state || "OPEN";
|
|
52017
|
-
const
|
|
52018
|
-
|
|
52019
|
-
|
|
52020
|
-
|
|
52255
|
+
const limit = parseLimit(options.limit);
|
|
52256
|
+
const values = await collectPages({
|
|
52257
|
+
limit,
|
|
52258
|
+
fetchPage: async (page, pagelen) => {
|
|
52259
|
+
const response = await this.pullrequestsApi.repositoriesWorkspaceRepoSlugPullrequestsGet({
|
|
52260
|
+
workspace: repoContext.workspace,
|
|
52261
|
+
repoSlug: repoContext.repoSlug,
|
|
52262
|
+
state
|
|
52263
|
+
}, {
|
|
52264
|
+
params: { page, pagelen }
|
|
52265
|
+
});
|
|
52266
|
+
return response.data;
|
|
52267
|
+
}
|
|
52021
52268
|
});
|
|
52022
|
-
const data = response.data;
|
|
52023
|
-
const values = data.values ? Array.from(data.values) : [];
|
|
52024
52269
|
if (context.globalOptions.json) {
|
|
52025
52270
|
this.output.json({
|
|
52026
52271
|
workspace: repoContext.workspace,
|
|
@@ -52203,18 +52448,31 @@ class EditPRCommand extends BaseCommand {
|
|
|
52203
52448
|
prId = Number.parseInt(options.id, 10);
|
|
52204
52449
|
} else {
|
|
52205
52450
|
const currentBranch = await this.gitService.getCurrentBranch();
|
|
52206
|
-
const
|
|
52207
|
-
|
|
52208
|
-
|
|
52209
|
-
|
|
52210
|
-
|
|
52211
|
-
|
|
52212
|
-
|
|
52213
|
-
|
|
52214
|
-
|
|
52451
|
+
const matches = await collectPages({
|
|
52452
|
+
limit: 1,
|
|
52453
|
+
pageSize: MAX_PAGE_LENGTH,
|
|
52454
|
+
fetchPage: async (page, pagelen) => {
|
|
52455
|
+
const response2 = await this.pullrequestsApi.repositoriesWorkspaceRepoSlugPullrequestsGet({
|
|
52456
|
+
workspace: repoContext.workspace,
|
|
52457
|
+
repoSlug: repoContext.repoSlug,
|
|
52458
|
+
state: "OPEN"
|
|
52459
|
+
}, {
|
|
52460
|
+
params: { page, pagelen }
|
|
52461
|
+
});
|
|
52462
|
+
return response2.data;
|
|
52463
|
+
},
|
|
52464
|
+
shouldInclude: (pullRequest) => {
|
|
52465
|
+
const source = pullRequest.source;
|
|
52466
|
+
return source?.branch?.name === currentBranch;
|
|
52467
|
+
}
|
|
52215
52468
|
});
|
|
52469
|
+
const matchingPR = matches[0];
|
|
52216
52470
|
if (!matchingPR) {
|
|
52217
|
-
throw new
|
|
52471
|
+
throw new BBError({
|
|
52472
|
+
code: 2002 /* API_NOT_FOUND */,
|
|
52473
|
+
message: `No open pull request found for current branch '${currentBranch}'. Specify a PR ID explicitly.`,
|
|
52474
|
+
context: { branch: currentBranch }
|
|
52475
|
+
});
|
|
52218
52476
|
}
|
|
52219
52477
|
prId = matchingPR.id;
|
|
52220
52478
|
}
|
|
@@ -52223,11 +52481,19 @@ class EditPRCommand extends BaseCommand {
|
|
|
52223
52481
|
try {
|
|
52224
52482
|
body = fs.readFileSync(options.bodyFile, "utf-8");
|
|
52225
52483
|
} catch (err) {
|
|
52226
|
-
throw new
|
|
52484
|
+
throw new BBError({
|
|
52485
|
+
code: 9999 /* UNKNOWN */,
|
|
52486
|
+
message: `Failed to read file '${options.bodyFile}': ${err instanceof Error ? err.message : "Unknown error"}`,
|
|
52487
|
+
cause: err instanceof Error ? err : undefined,
|
|
52488
|
+
context: { bodyFile: options.bodyFile }
|
|
52489
|
+
});
|
|
52227
52490
|
}
|
|
52228
52491
|
}
|
|
52229
52492
|
if (!options.title && !body) {
|
|
52230
|
-
throw new
|
|
52493
|
+
throw new BBError({
|
|
52494
|
+
code: 5001 /* VALIDATION_REQUIRED */,
|
|
52495
|
+
message: "At least one of --title or --body (or --body-file) is required."
|
|
52496
|
+
});
|
|
52231
52497
|
}
|
|
52232
52498
|
const request = {
|
|
52233
52499
|
type: "pullrequest"
|
|
@@ -52444,7 +52710,11 @@ class CheckoutPRCommand extends BaseCommand {
|
|
|
52444
52710
|
const branchName = pr.source?.branch?.name;
|
|
52445
52711
|
const localBranchName = `pr-${prId}`;
|
|
52446
52712
|
if (!branchName) {
|
|
52447
|
-
throw new
|
|
52713
|
+
throw new BBError({
|
|
52714
|
+
code: 2002 /* API_NOT_FOUND */,
|
|
52715
|
+
message: "Pull request source branch not found",
|
|
52716
|
+
context: { pullRequestId: prId }
|
|
52717
|
+
});
|
|
52448
52718
|
}
|
|
52449
52719
|
await this.gitService.fetch();
|
|
52450
52720
|
let checkedOutBranch;
|
|
@@ -52505,18 +52775,39 @@ class DiffPRCommand extends BaseCommand {
|
|
|
52505
52775
|
if (options.id) {
|
|
52506
52776
|
prId = Number.parseInt(options.id, 10);
|
|
52507
52777
|
if (Number.isNaN(prId)) {
|
|
52508
|
-
throw new
|
|
52778
|
+
throw new BBError({
|
|
52779
|
+
code: 5002 /* VALIDATION_INVALID */,
|
|
52780
|
+
message: "Invalid PR ID",
|
|
52781
|
+
context: { id: options.id }
|
|
52782
|
+
});
|
|
52509
52783
|
}
|
|
52510
52784
|
} else {
|
|
52511
52785
|
const currentBranch = await this.gitService.getCurrentBranch();
|
|
52512
|
-
const
|
|
52513
|
-
|
|
52514
|
-
|
|
52515
|
-
|
|
52786
|
+
const matches = await collectPages({
|
|
52787
|
+
limit: 1,
|
|
52788
|
+
pageSize: MAX_PAGE_LENGTH,
|
|
52789
|
+
fetchPage: async (page, pagelen) => {
|
|
52790
|
+
const response = await this.pullrequestsApi.repositoriesWorkspaceRepoSlugPullrequestsGet({
|
|
52791
|
+
workspace: repoContext.workspace,
|
|
52792
|
+
repoSlug: repoContext.repoSlug,
|
|
52793
|
+
state: "OPEN"
|
|
52794
|
+
}, {
|
|
52795
|
+
params: { page, pagelen }
|
|
52796
|
+
});
|
|
52797
|
+
return response.data;
|
|
52798
|
+
},
|
|
52799
|
+
shouldInclude: (pullRequest) => {
|
|
52800
|
+
const source = pullRequest.source;
|
|
52801
|
+
return source?.branch?.name === currentBranch;
|
|
52802
|
+
}
|
|
52516
52803
|
});
|
|
52517
|
-
const pr =
|
|
52804
|
+
const pr = matches[0];
|
|
52518
52805
|
if (!pr) {
|
|
52519
|
-
throw new
|
|
52806
|
+
throw new BBError({
|
|
52807
|
+
code: 2002 /* API_NOT_FOUND */,
|
|
52808
|
+
message: `No open pull request found for branch "${currentBranch}"`,
|
|
52809
|
+
context: { branch: currentBranch }
|
|
52810
|
+
});
|
|
52520
52811
|
}
|
|
52521
52812
|
prId = pr.id;
|
|
52522
52813
|
}
|
|
@@ -52591,11 +52882,13 @@ class DiffPRCommand extends BaseCommand {
|
|
|
52591
52882
|
repoSlug,
|
|
52592
52883
|
pullRequestId: prId
|
|
52593
52884
|
});
|
|
52594
|
-
const
|
|
52595
|
-
|
|
52596
|
-
|
|
52885
|
+
const links = prResponse.data.links;
|
|
52886
|
+
const htmlUrl = links?.html?.href;
|
|
52887
|
+
if (htmlUrl) {
|
|
52888
|
+
const normalizedHtmlUrl = htmlUrl.replace(/\/$/, "");
|
|
52889
|
+
return `${normalizedHtmlUrl}/diff`;
|
|
52597
52890
|
}
|
|
52598
|
-
return
|
|
52891
|
+
return `https://bitbucket.org/${workspace}/${repoSlug}/pull-requests/${prId}/diff`;
|
|
52599
52892
|
}
|
|
52600
52893
|
async showStat(workspace, repoSlug, prId, useJson) {
|
|
52601
52894
|
const diffstatResponse = await this.pullrequestsApi.repositoriesWorkspaceRepoSlugPullrequestsPullRequestIdDiffstatGet({
|
|
@@ -52718,15 +53011,28 @@ class ActivityPRCommand extends BaseCommand {
|
|
|
52718
53011
|
...options
|
|
52719
53012
|
});
|
|
52720
53013
|
const prId = Number.parseInt(options.id, 10);
|
|
52721
|
-
const response = await this.pullrequestsApi.repositoriesWorkspaceRepoSlugPullrequestsPullRequestIdActivityGet({
|
|
52722
|
-
workspace: repoContext.workspace,
|
|
52723
|
-
repoSlug: repoContext.repoSlug,
|
|
52724
|
-
pullRequestId: prId
|
|
52725
|
-
});
|
|
52726
|
-
const data = response.data;
|
|
52727
|
-
const values = data?.values ? Array.from(data.values) : [];
|
|
52728
53014
|
const filterTypes = this.parseTypeFilter(options.type);
|
|
52729
|
-
const
|
|
53015
|
+
const limit = parseLimit(options.limit);
|
|
53016
|
+
const activities = await collectPages({
|
|
53017
|
+
limit,
|
|
53018
|
+
fetchPage: async (page, pagelen) => {
|
|
53019
|
+
const response = await this.pullrequestsApi.repositoriesWorkspaceRepoSlugPullrequestsPullRequestIdActivityGet({
|
|
53020
|
+
workspace: repoContext.workspace,
|
|
53021
|
+
repoSlug: repoContext.repoSlug,
|
|
53022
|
+
pullRequestId: prId
|
|
53023
|
+
}, {
|
|
53024
|
+
params: { page, pagelen }
|
|
53025
|
+
});
|
|
53026
|
+
return response.data;
|
|
53027
|
+
},
|
|
53028
|
+
shouldInclude: (activity) => {
|
|
53029
|
+
if (filterTypes.length === 0) {
|
|
53030
|
+
return true;
|
|
53031
|
+
}
|
|
53032
|
+
return filterTypes.includes(this.getActivityType(activity));
|
|
53033
|
+
}
|
|
53034
|
+
});
|
|
53035
|
+
const typedActivities = activities;
|
|
52730
53036
|
if (context.globalOptions.json) {
|
|
52731
53037
|
this.output.json({
|
|
52732
53038
|
workspace: repoContext.workspace,
|
|
@@ -52735,12 +53041,12 @@ class ActivityPRCommand extends BaseCommand {
|
|
|
52735
53041
|
filters: {
|
|
52736
53042
|
types: filterTypes
|
|
52737
53043
|
},
|
|
52738
|
-
count:
|
|
52739
|
-
activities
|
|
53044
|
+
count: typedActivities.length,
|
|
53045
|
+
activities: typedActivities
|
|
52740
53046
|
});
|
|
52741
53047
|
return;
|
|
52742
53048
|
}
|
|
52743
|
-
if (
|
|
53049
|
+
if (typedActivities.length === 0) {
|
|
52744
53050
|
if (filterTypes.length > 0) {
|
|
52745
53051
|
this.output.info("No activity entries matched the requested filter");
|
|
52746
53052
|
} else {
|
|
@@ -52748,7 +53054,7 @@ class ActivityPRCommand extends BaseCommand {
|
|
|
52748
53054
|
}
|
|
52749
53055
|
return;
|
|
52750
53056
|
}
|
|
52751
|
-
const rows =
|
|
53057
|
+
const rows = typedActivities.map((activity) => {
|
|
52752
53058
|
const activityType = this.getActivityType(activity);
|
|
52753
53059
|
return [
|
|
52754
53060
|
activityType.toUpperCase(),
|
|
@@ -52866,31 +53172,79 @@ class CommentPRCommand extends BaseCommand {
|
|
|
52866
53172
|
this.contextService = contextService;
|
|
52867
53173
|
}
|
|
52868
53174
|
async execute(options, context) {
|
|
53175
|
+
if ((options.lineTo || options.lineFrom) && !options.file) {
|
|
53176
|
+
throw new BBError({
|
|
53177
|
+
code: 5001 /* VALIDATION_REQUIRED */,
|
|
53178
|
+
message: "--file is required when using --line-to or --line-from"
|
|
53179
|
+
});
|
|
53180
|
+
}
|
|
53181
|
+
if (options.file && !options.lineTo && !options.lineFrom) {
|
|
53182
|
+
throw new BBError({
|
|
53183
|
+
code: 5001 /* VALIDATION_REQUIRED */,
|
|
53184
|
+
message: "At least one of --line-to or --line-from is required when using --file"
|
|
53185
|
+
});
|
|
53186
|
+
}
|
|
53187
|
+
if (options.lineTo) {
|
|
53188
|
+
const parsed = Number.parseInt(options.lineTo, 10);
|
|
53189
|
+
if (Number.isNaN(parsed) || parsed < 1) {
|
|
53190
|
+
throw new BBError({
|
|
53191
|
+
code: 5002 /* VALIDATION_INVALID */,
|
|
53192
|
+
message: "--line-to must be a positive integer"
|
|
53193
|
+
});
|
|
53194
|
+
}
|
|
53195
|
+
}
|
|
53196
|
+
if (options.lineFrom) {
|
|
53197
|
+
const parsed = Number.parseInt(options.lineFrom, 10);
|
|
53198
|
+
if (Number.isNaN(parsed) || parsed < 1) {
|
|
53199
|
+
throw new BBError({
|
|
53200
|
+
code: 5002 /* VALIDATION_INVALID */,
|
|
53201
|
+
message: "--line-from must be a positive integer"
|
|
53202
|
+
});
|
|
53203
|
+
}
|
|
53204
|
+
}
|
|
52869
53205
|
const repoContext = await this.contextService.requireRepoContext({
|
|
52870
53206
|
...context.globalOptions,
|
|
52871
53207
|
...options
|
|
52872
53208
|
});
|
|
52873
53209
|
const prId = Number.parseInt(options.id, 10);
|
|
53210
|
+
const inline = options.file ? {
|
|
53211
|
+
path: options.file,
|
|
53212
|
+
...options.lineTo ? { to: Number.parseInt(options.lineTo, 10) } : {},
|
|
53213
|
+
...options.lineFrom ? { from: Number.parseInt(options.lineFrom, 10) } : {}
|
|
53214
|
+
} : undefined;
|
|
53215
|
+
const body = {
|
|
53216
|
+
content: {
|
|
53217
|
+
raw: options.message
|
|
53218
|
+
},
|
|
53219
|
+
...inline ? { inline } : {}
|
|
53220
|
+
};
|
|
52874
53221
|
const response = await this.pullrequestsApi.repositoriesWorkspaceRepoSlugPullrequestsPullRequestIdCommentsPost({
|
|
52875
53222
|
workspace: repoContext.workspace,
|
|
52876
53223
|
repoSlug: repoContext.repoSlug,
|
|
52877
53224
|
pullRequestId: prId,
|
|
52878
|
-
body
|
|
52879
|
-
type: "pullrequest_comment",
|
|
52880
|
-
content: {
|
|
52881
|
-
raw: options.message
|
|
52882
|
-
}
|
|
52883
|
-
}
|
|
53225
|
+
body
|
|
52884
53226
|
});
|
|
52885
53227
|
if (context.globalOptions.json) {
|
|
52886
|
-
|
|
53228
|
+
const jsonOutput = {
|
|
52887
53229
|
success: true,
|
|
52888
53230
|
pullRequestId: prId,
|
|
52889
53231
|
comment: response.data
|
|
52890
|
-
}
|
|
53232
|
+
};
|
|
53233
|
+
if (inline) {
|
|
53234
|
+
jsonOutput.inline = inline;
|
|
53235
|
+
}
|
|
53236
|
+
this.output.json(jsonOutput);
|
|
52891
53237
|
return;
|
|
52892
53238
|
}
|
|
52893
|
-
|
|
53239
|
+
if (inline) {
|
|
53240
|
+
if (inline.to) {
|
|
53241
|
+
this.output.success(`Added inline comment on ${inline.path}:${inline.to} to pull request #${prId}`);
|
|
53242
|
+
} else {
|
|
53243
|
+
this.output.success(`Added inline comment on ${inline.path} (old line ${inline.from}) to pull request #${prId}`);
|
|
53244
|
+
}
|
|
53245
|
+
} else {
|
|
53246
|
+
this.output.success(`Added comment to pull request #${prId}`);
|
|
53247
|
+
}
|
|
52894
53248
|
}
|
|
52895
53249
|
}
|
|
52896
53250
|
|
|
@@ -52911,13 +53265,20 @@ class ListCommentsPRCommand extends BaseCommand {
|
|
|
52911
53265
|
...options
|
|
52912
53266
|
});
|
|
52913
53267
|
const prId = Number.parseInt(options.id, 10);
|
|
52914
|
-
const
|
|
52915
|
-
|
|
52916
|
-
|
|
52917
|
-
|
|
53268
|
+
const limit = parseLimit(options.limit);
|
|
53269
|
+
const values = await collectPages({
|
|
53270
|
+
limit,
|
|
53271
|
+
fetchPage: async (page, pagelen) => {
|
|
53272
|
+
const response = await this.pullrequestsApi.repositoriesWorkspaceRepoSlugPullrequestsPullRequestIdCommentsGet({
|
|
53273
|
+
workspace: repoContext.workspace,
|
|
53274
|
+
repoSlug: repoContext.repoSlug,
|
|
53275
|
+
pullRequestId: prId
|
|
53276
|
+
}, {
|
|
53277
|
+
params: { page, pagelen }
|
|
53278
|
+
});
|
|
53279
|
+
return response.data;
|
|
53280
|
+
}
|
|
52918
53281
|
});
|
|
52919
|
-
const data = response.data;
|
|
52920
|
-
const values = data.values ? Array.from(data.values) : [];
|
|
52921
53282
|
if (context.globalOptions.json) {
|
|
52922
53283
|
this.output.json({
|
|
52923
53284
|
pullRequestId: prId,
|
|
@@ -53306,25 +53667,6 @@ class ChecksPRCommand extends BaseCommand {
|
|
|
53306
53667
|
}
|
|
53307
53668
|
}
|
|
53308
53669
|
|
|
53309
|
-
// src/types/config.ts
|
|
53310
|
-
var SETTABLE_CONFIG_KEYS = [
|
|
53311
|
-
"defaultWorkspace",
|
|
53312
|
-
"skipVersionCheck",
|
|
53313
|
-
"versionCheckInterval"
|
|
53314
|
-
];
|
|
53315
|
-
var READABLE_CONFIG_KEYS = [
|
|
53316
|
-
"username",
|
|
53317
|
-
"defaultWorkspace",
|
|
53318
|
-
"skipVersionCheck",
|
|
53319
|
-
"versionCheckInterval"
|
|
53320
|
-
];
|
|
53321
|
-
function isSettableConfigKey(key) {
|
|
53322
|
-
return SETTABLE_CONFIG_KEYS.includes(key);
|
|
53323
|
-
}
|
|
53324
|
-
function isReadableConfigKey(key) {
|
|
53325
|
-
return READABLE_CONFIG_KEYS.includes(key);
|
|
53326
|
-
}
|
|
53327
|
-
|
|
53328
53670
|
// src/commands/config/get.command.ts
|
|
53329
53671
|
class GetConfigCommand extends BaseCommand {
|
|
53330
53672
|
configService;
|
|
@@ -53338,12 +53680,21 @@ class GetConfigCommand extends BaseCommand {
|
|
|
53338
53680
|
async execute(options, context) {
|
|
53339
53681
|
const { key } = options;
|
|
53340
53682
|
if (GetConfigCommand.HIDDEN_KEYS.includes(key)) {
|
|
53341
|
-
throw new
|
|
53683
|
+
throw new BBError({
|
|
53684
|
+
code: 4003 /* CONFIG_INVALID_KEY */,
|
|
53685
|
+
message: `Cannot display '${key}' - use 'bb auth token' to get authentication credentials`,
|
|
53686
|
+
context: { key }
|
|
53687
|
+
});
|
|
53342
53688
|
}
|
|
53343
53689
|
if (!isReadableConfigKey(key)) {
|
|
53344
|
-
throw new
|
|
53690
|
+
throw new BBError({
|
|
53691
|
+
code: 4003 /* CONFIG_INVALID_KEY */,
|
|
53692
|
+
message: `Unknown config key '${key}'. Valid keys: ${READABLE_CONFIG_KEYS.join(", ")}`,
|
|
53693
|
+
context: { key }
|
|
53694
|
+
});
|
|
53345
53695
|
}
|
|
53346
|
-
const
|
|
53696
|
+
const rawValue = await this.configService.getValue(key);
|
|
53697
|
+
const value = normalizeReadableConfigValue(key, rawValue);
|
|
53347
53698
|
if (context.globalOptions.json) {
|
|
53348
53699
|
this.output.json({
|
|
53349
53700
|
key,
|
|
@@ -53351,7 +53702,7 @@ class GetConfigCommand extends BaseCommand {
|
|
|
53351
53702
|
});
|
|
53352
53703
|
return;
|
|
53353
53704
|
}
|
|
53354
|
-
this.output.text(String(value
|
|
53705
|
+
this.output.text(String(value ?? ""));
|
|
53355
53706
|
}
|
|
53356
53707
|
}
|
|
53357
53708
|
|
|
@@ -53368,21 +53719,30 @@ class SetConfigCommand extends BaseCommand {
|
|
|
53368
53719
|
async execute(options, context) {
|
|
53369
53720
|
const { key, value } = options;
|
|
53370
53721
|
if (SetConfigCommand.PROTECTED_KEYS.includes(key)) {
|
|
53371
|
-
throw new
|
|
53722
|
+
throw new BBError({
|
|
53723
|
+
code: 4003 /* CONFIG_INVALID_KEY */,
|
|
53724
|
+
message: `Cannot set '${key}' directly. Use 'bb auth login' to configure authentication.`,
|
|
53725
|
+
context: { key }
|
|
53726
|
+
});
|
|
53372
53727
|
}
|
|
53373
53728
|
if (!isSettableConfigKey(key)) {
|
|
53374
|
-
throw new
|
|
53729
|
+
throw new BBError({
|
|
53730
|
+
code: 4003 /* CONFIG_INVALID_KEY */,
|
|
53731
|
+
message: `Unknown config key '${key}'. Valid keys: ${SETTABLE_CONFIG_KEYS.join(", ")}`,
|
|
53732
|
+
context: { key }
|
|
53733
|
+
});
|
|
53375
53734
|
}
|
|
53376
|
-
|
|
53735
|
+
const parsedValue = parseSettableConfigValue(key, value);
|
|
53736
|
+
await this.configService.setValue(key, parsedValue);
|
|
53377
53737
|
if (context.globalOptions.json) {
|
|
53378
53738
|
this.output.json({
|
|
53379
53739
|
success: true,
|
|
53380
53740
|
key,
|
|
53381
|
-
value
|
|
53741
|
+
value: parsedValue
|
|
53382
53742
|
});
|
|
53383
53743
|
return;
|
|
53384
53744
|
}
|
|
53385
|
-
this.output.success(`Set ${key} = ${
|
|
53745
|
+
this.output.success(`Set ${key} = ${parsedValue}`);
|
|
53386
53746
|
}
|
|
53387
53747
|
}
|
|
53388
53748
|
|
|
@@ -53397,21 +53757,37 @@ class ListConfigCommand extends BaseCommand {
|
|
|
53397
53757
|
}
|
|
53398
53758
|
async execute(_options, context) {
|
|
53399
53759
|
const config = await this.configService.getConfig();
|
|
53400
|
-
const displayConfig = {
|
|
53401
|
-
|
|
53402
|
-
|
|
53403
|
-
|
|
53404
|
-
|
|
53760
|
+
const displayConfig = {};
|
|
53761
|
+
if (config.username) {
|
|
53762
|
+
displayConfig.username = config.username;
|
|
53763
|
+
}
|
|
53764
|
+
if (config.defaultWorkspace) {
|
|
53765
|
+
displayConfig.defaultWorkspace = config.defaultWorkspace;
|
|
53766
|
+
}
|
|
53767
|
+
if (config.apiToken) {
|
|
53768
|
+
displayConfig.apiToken = "********";
|
|
53769
|
+
}
|
|
53770
|
+
const skipVersionCheck = coerceSkipVersionCheckValue(config.skipVersionCheck);
|
|
53771
|
+
if (skipVersionCheck !== undefined) {
|
|
53772
|
+
displayConfig.skipVersionCheck = skipVersionCheck;
|
|
53773
|
+
}
|
|
53774
|
+
const versionCheckInterval = coerceVersionCheckIntervalValue(config.versionCheckInterval);
|
|
53775
|
+
if (versionCheckInterval !== undefined) {
|
|
53776
|
+
displayConfig.versionCheckInterval = versionCheckInterval;
|
|
53777
|
+
}
|
|
53405
53778
|
if (context.globalOptions.json) {
|
|
53406
53779
|
this.output.json({
|
|
53407
53780
|
configPath: this.configService.getConfigPath(),
|
|
53408
|
-
config:
|
|
53781
|
+
config: displayConfig
|
|
53409
53782
|
});
|
|
53410
53783
|
return;
|
|
53411
53784
|
}
|
|
53412
53785
|
this.output.text(this.output.dim(`Config file: ${this.configService.getConfigPath()}`));
|
|
53413
53786
|
this.output.text("");
|
|
53414
|
-
const rows = Object.entries(displayConfig).
|
|
53787
|
+
const rows = Object.entries(displayConfig).map(([key, value]) => [
|
|
53788
|
+
key,
|
|
53789
|
+
String(value)
|
|
53790
|
+
]);
|
|
53415
53791
|
if (rows.length === 0) {
|
|
53416
53792
|
this.output.text("No configuration set");
|
|
53417
53793
|
return;
|
|
@@ -53448,7 +53824,11 @@ class InstallCompletionCommand extends BaseCommand {
|
|
|
53448
53824
|
this.output.success("Shell completions installed successfully!");
|
|
53449
53825
|
this.output.text("Restart your shell or source your profile to enable completions.");
|
|
53450
53826
|
} catch (error) {
|
|
53451
|
-
throw new
|
|
53827
|
+
throw new BBError({
|
|
53828
|
+
code: 9999 /* UNKNOWN */,
|
|
53829
|
+
message: `Failed to install completions: ${error}`,
|
|
53830
|
+
cause: error instanceof Error ? error : undefined
|
|
53831
|
+
});
|
|
53452
53832
|
}
|
|
53453
53833
|
}
|
|
53454
53834
|
}
|
|
@@ -53479,7 +53859,11 @@ class UninstallCompletionCommand extends BaseCommand {
|
|
|
53479
53859
|
}
|
|
53480
53860
|
this.output.success("Shell completions uninstalled successfully!");
|
|
53481
53861
|
} catch (error) {
|
|
53482
|
-
throw new
|
|
53862
|
+
throw new BBError({
|
|
53863
|
+
code: 9999 /* UNKNOWN */,
|
|
53864
|
+
message: `Failed to uninstall completions: ${error}`,
|
|
53865
|
+
cause: error instanceof Error ? error : undefined
|
|
53866
|
+
});
|
|
53483
53867
|
}
|
|
53484
53868
|
}
|
|
53485
53869
|
}
|
|
@@ -53898,7 +54282,7 @@ prCmd.command("checkout <id>").description("Checkout a pull request locally").ac
|
|
|
53898
54282
|
const context = createContext(cli);
|
|
53899
54283
|
await runCommand(ServiceTokens.CheckoutPRCommand, withGlobalOptions({ id, ...options }, context), cli, context);
|
|
53900
54284
|
});
|
|
53901
|
-
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("
|
|
54285
|
+
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("--web", "Open diff in web browser").action(async (id, options) => {
|
|
53902
54286
|
const context = createContext(cli);
|
|
53903
54287
|
await runCommand(ServiceTokens.DiffPRCommand, withGlobalOptions({ id, ...options }, context), cli, context);
|
|
53904
54288
|
});
|
|
@@ -53907,9 +54291,9 @@ prCommentsCmd.command("list <id>").description("List comments on a pull request"
|
|
|
53907
54291
|
const context = createContext(cli);
|
|
53908
54292
|
await runCommand(ServiceTokens.ListCommentsPRCommand, withGlobalOptions({ id, ...options }, context), cli, context);
|
|
53909
54293
|
});
|
|
53910
|
-
prCommentsCmd.command("add <id> <message>").description("Add a comment to a pull request").action(async (id, message, options) => {
|
|
54294
|
+
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) => {
|
|
53911
54295
|
const context = createContext(cli);
|
|
53912
|
-
await runCommand(ServiceTokens.CommentPRCommand, withGlobalOptions({ id, message }, context), cli, context);
|
|
54296
|
+
await runCommand(ServiceTokens.CommentPRCommand, withGlobalOptions({ id, message, ...options }, context), cli, context);
|
|
53913
54297
|
});
|
|
53914
54298
|
prCommentsCmd.command("edit <pr-id> <comment-id> <message>").description("Edit a comment on a pull request").action(async (prId, commentId, message, options) => {
|
|
53915
54299
|
const context = createContext(cli);
|