@pilatos/bitbucket-cli 1.7.1 → 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 (2) hide show
  1. package/dist/index.js +189 -46
  2. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -45103,6 +45103,101 @@ class OutputService {
45103
45103
  return this.format(text, source_default.underline);
45104
45104
  }
45105
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
+ }
45199
+ }
45200
+
45106
45201
  // src/services/version.service.ts
45107
45202
  var NPM_REGISTRY_URL = "https://registry.npmjs.org/@pilatos/bitbucket-cli";
45108
45203
  var PACKAGE_NAME = "@pilatos/bitbucket-cli";
@@ -45115,7 +45210,8 @@ class VersionService {
45115
45210
  this.currentVersion = currentVersion;
45116
45211
  }
45117
45212
  async checkForUpdate() {
45118
- const skipCheck = await this.configService.getValue("skipVersionCheck");
45213
+ const skipCheckRaw = await this.configService.getValue("skipVersionCheck");
45214
+ const skipCheck = coerceSkipVersionCheckValue(skipCheckRaw);
45119
45215
  if (skipCheck === true) {
45120
45216
  return null;
45121
45217
  }
@@ -45148,7 +45244,7 @@ class VersionService {
45148
45244
  const now = new Date;
45149
45245
  const timeSinceLastCheck = now.getTime() - lastCheckDate.getTime();
45150
45246
  const intervalDays = await this.configService.getValue("versionCheckInterval");
45151
- const days = typeof intervalDays === "number" ? intervalDays : 1;
45247
+ const days = coerceVersionCheckIntervalValue(intervalDays) ?? 1;
45152
45248
  const intervalMs = days * 24 * 60 * 60 * 1000;
45153
45249
  return timeSinceLastCheck >= intervalMs;
45154
45250
  }
@@ -52866,31 +52962,79 @@ class CommentPRCommand extends BaseCommand {
52866
52962
  this.contextService = contextService;
52867
52963
  }
52868
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
+ }
52869
52995
  const repoContext = await this.contextService.requireRepoContext({
52870
52996
  ...context.globalOptions,
52871
52997
  ...options
52872
52998
  });
52873
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
+ };
52874
53011
  const response = await this.pullrequestsApi.repositoriesWorkspaceRepoSlugPullrequestsPullRequestIdCommentsPost({
52875
53012
  workspace: repoContext.workspace,
52876
53013
  repoSlug: repoContext.repoSlug,
52877
53014
  pullRequestId: prId,
52878
- body: {
52879
- type: "pullrequest_comment",
52880
- content: {
52881
- raw: options.message
52882
- }
52883
- }
53015
+ body
52884
53016
  });
52885
53017
  if (context.globalOptions.json) {
52886
- this.output.json({
53018
+ const jsonOutput = {
52887
53019
  success: true,
52888
53020
  pullRequestId: prId,
52889
53021
  comment: response.data
52890
- });
53022
+ };
53023
+ if (inline) {
53024
+ jsonOutput.inline = inline;
53025
+ }
53026
+ this.output.json(jsonOutput);
52891
53027
  return;
52892
53028
  }
52893
- this.output.success(`Added comment to pull request #${prId}`);
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 {
53036
+ this.output.success(`Added comment to pull request #${prId}`);
53037
+ }
52894
53038
  }
52895
53039
  }
52896
53040
 
@@ -53306,25 +53450,6 @@ class ChecksPRCommand extends BaseCommand {
53306
53450
  }
53307
53451
  }
53308
53452
 
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
53453
  // src/commands/config/get.command.ts
53329
53454
  class GetConfigCommand extends BaseCommand {
53330
53455
  configService;
@@ -53341,9 +53466,10 @@ class GetConfigCommand extends BaseCommand {
53341
53466
  throw new Error(`Cannot display '${key}' - use 'bb auth token' to get authentication credentials`);
53342
53467
  }
53343
53468
  if (!isReadableConfigKey(key)) {
53344
- throw new Error(`Unknown config key '${key}'. Valid keys: username, defaultWorkspace`);
53469
+ throw new Error(`Unknown config key '${key}'. Valid keys: ${READABLE_CONFIG_KEYS.join(", ")}`);
53345
53470
  }
53346
- const value = await this.configService.getValue(key);
53471
+ const rawValue = await this.configService.getValue(key);
53472
+ const value = normalizeReadableConfigValue(key, rawValue);
53347
53473
  if (context.globalOptions.json) {
53348
53474
  this.output.json({
53349
53475
  key,
@@ -53351,7 +53477,7 @@ class GetConfigCommand extends BaseCommand {
53351
53477
  });
53352
53478
  return;
53353
53479
  }
53354
- this.output.text(String(value || ""));
53480
+ this.output.text(String(value ?? ""));
53355
53481
  }
53356
53482
  }
53357
53483
 
@@ -53371,18 +53497,19 @@ class SetConfigCommand extends BaseCommand {
53371
53497
  throw new Error(`Cannot set '${key}' directly. Use 'bb auth login' to configure authentication.`);
53372
53498
  }
53373
53499
  if (!isSettableConfigKey(key)) {
53374
- throw new Error(`Unknown config key '${key}'. Valid keys: defaultWorkspace`);
53500
+ throw new Error(`Unknown config key '${key}'. Valid keys: ${SETTABLE_CONFIG_KEYS.join(", ")}`);
53375
53501
  }
53376
- await this.configService.setValue(key, value);
53502
+ const parsedValue = parseSettableConfigValue(key, value);
53503
+ await this.configService.setValue(key, parsedValue);
53377
53504
  if (context.globalOptions.json) {
53378
53505
  this.output.json({
53379
53506
  success: true,
53380
53507
  key,
53381
- value
53508
+ value: parsedValue
53382
53509
  });
53383
53510
  return;
53384
53511
  }
53385
- this.output.success(`Set ${key} = ${value}`);
53512
+ this.output.success(`Set ${key} = ${parsedValue}`);
53386
53513
  }
53387
53514
  }
53388
53515
 
@@ -53397,21 +53524,37 @@ class ListConfigCommand extends BaseCommand {
53397
53524
  }
53398
53525
  async execute(_options, context) {
53399
53526
  const config = await this.configService.getConfig();
53400
- const displayConfig = {
53401
- username: config.username || "",
53402
- defaultWorkspace: config.defaultWorkspace || "",
53403
- apiToken: config.apiToken ? "********" : ""
53404
- };
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
+ }
53405
53545
  if (context.globalOptions.json) {
53406
53546
  this.output.json({
53407
53547
  configPath: this.configService.getConfigPath(),
53408
- config: Object.fromEntries(Object.entries(displayConfig).filter(([, value]) => value !== ""))
53548
+ config: displayConfig
53409
53549
  });
53410
53550
  return;
53411
53551
  }
53412
53552
  this.output.text(this.output.dim(`Config file: ${this.configService.getConfigPath()}`));
53413
53553
  this.output.text("");
53414
- 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
+ ]);
53415
53558
  if (rows.length === 0) {
53416
53559
  this.output.text("No configuration set");
53417
53560
  return;
@@ -53907,9 +54050,9 @@ prCommentsCmd.command("list <id>").description("List comments on a pull request"
53907
54050
  const context = createContext(cli);
53908
54051
  await runCommand(ServiceTokens.ListCommentsPRCommand, withGlobalOptions({ id, ...options }, context), cli, context);
53909
54052
  });
53910
- prCommentsCmd.command("add <id> <message>").description("Add a comment to a pull request").action(async (id, message, options) => {
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) => {
53911
54054
  const context = createContext(cli);
53912
- await runCommand(ServiceTokens.CommentPRCommand, withGlobalOptions({ id, message }, context), cli, context);
54055
+ await runCommand(ServiceTokens.CommentPRCommand, withGlobalOptions({ id, message, ...options }, context), cli, context);
53913
54056
  });
53914
54057
  prCommentsCmd.command("edit <pr-id> <comment-id> <message>").description("Edit a comment on a pull request").action(async (prId, commentId, message, options) => {
53915
54058
  const context = createContext(cli);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@pilatos/bitbucket-cli",
3
- "version": "1.7.1",
3
+ "version": "1.8.0",
4
4
  "description": "A command-line interface for Bitbucket Cloud",
5
5
  "author": "",
6
6
  "license": "MIT",