@pilatos/bitbucket-cli 1.1.0 → 1.2.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 +1 -1
  2. package/dist/index.js +235 -7
  3. package/package.json +1 -1
package/README.md CHANGED
@@ -83,7 +83,7 @@ bb pr list
83
83
  |----------|----------|
84
84
  | **Authentication** | `login`, `logout`, `status`, `token` |
85
85
  | **Repositories** | `clone`, `create`, `list`, `view`, `delete` |
86
- | **Pull Requests** | `create`, `list`, `view`, `edit`, `merge`, `approve`, `decline`, `checkout`, `diff` |
86
+ | **Pull Requests** | `create`, `list`, `view`, `edit`, `merge`, `approve`, `decline`, `checkout`, `diff`, `comment`, `comments` |
87
87
  | **Configuration** | `get`, `set`, `list` |
88
88
  | **Shell Completion** | `install`, `uninstall` |
89
89
 
package/dist/index.js CHANGED
@@ -33264,6 +33264,10 @@ var ServiceTokens = {
33264
33264
  DeclinePRCommand: "DeclinePRCommand",
33265
33265
  CheckoutPRCommand: "CheckoutPRCommand",
33266
33266
  DiffPRCommand: "DiffPRCommand",
33267
+ CommentPRCommand: "CommentPRCommand",
33268
+ ListCommentsPRCommand: "ListCommentsPRCommand",
33269
+ EditCommentPRCommand: "EditCommentPRCommand",
33270
+ DeleteCommentPRCommand: "DeleteCommentPRCommand",
33267
33271
  GetConfigCommand: "GetConfigCommand",
33268
33272
  SetConfigCommand: "SetConfigCommand",
33269
33273
  ListConfigCommand: "ListConfigCommand",
@@ -34279,6 +34283,11 @@ class HttpClient {
34279
34283
  body: body ? JSON.stringify(body) : undefined,
34280
34284
  signal: controller.signal
34281
34285
  });
34286
+ if (process.env.DEBUG === "true") {
34287
+ console.debug(`[HTTP] ${method} ${url} - ${response.status}`);
34288
+ console.debug(`[HTTP] Response Headers:`, Object.fromEntries(response.headers.entries()));
34289
+ console.debug(`[HTTP] Response Body:`, await response.clone().text());
34290
+ }
34282
34291
  clearTimeout(timeoutId);
34283
34292
  return acceptText ? this.handleTextResponse(response) : this.handleResponse(response);
34284
34293
  } catch (error) {
@@ -34394,6 +34403,16 @@ class UserRepository {
34394
34403
  return this.httpClient.get("/user");
34395
34404
  }
34396
34405
  }
34406
+ // src/constants.ts
34407
+ var API_PAGELEN_LIMITS = {
34408
+ PULL_REQUESTS: 50,
34409
+ REPOSITORIES: 100
34410
+ };
34411
+ var DEFAULT_PAGELEN = {
34412
+ PULL_REQUESTS: 25,
34413
+ REPOSITORIES: 25
34414
+ };
34415
+
34397
34416
  // src/repositories/repo.repository.ts
34398
34417
  class RepoRepository {
34399
34418
  httpClient;
@@ -34404,7 +34423,8 @@ class RepoRepository {
34404
34423
  return this.httpClient.get(`/repositories/${encodeURIComponent(workspace)}/${encodeURIComponent(repoSlug)}`);
34405
34424
  }
34406
34425
  async list(workspace, limit = 25) {
34407
- return this.httpClient.get(`/repositories/${encodeURIComponent(workspace)}?pagelen=${limit}`);
34426
+ const safeLimit = Math.min(limit, API_PAGELEN_LIMITS.REPOSITORIES);
34427
+ return this.httpClient.get(`/repositories/${encodeURIComponent(workspace)}?pagelen=${safeLimit}`);
34408
34428
  }
34409
34429
  async create(workspace, request) {
34410
34430
  const repoSlug = request.name.toLowerCase().replace(/\s+/g, "-");
@@ -34428,7 +34448,8 @@ class PullRequestRepository {
34428
34448
  return this.httpClient.get(this.buildPath(workspace, repoSlug, `/${id}`));
34429
34449
  }
34430
34450
  async list(workspace, repoSlug, state = "OPEN", limit = 25) {
34431
- return this.httpClient.get(this.buildPath(workspace, repoSlug, `?state=${state}&pagelen=${limit}`));
34451
+ const safeLimit = Math.min(limit, API_PAGELEN_LIMITS.PULL_REQUESTS);
34452
+ return this.httpClient.get(this.buildPath(workspace, repoSlug, `?state=${state}&pagelen=${safeLimit}`));
34432
34453
  }
34433
34454
  async create(workspace, repoSlug, request) {
34434
34455
  return this.httpClient.post(this.buildPath(workspace, repoSlug), request);
@@ -34440,10 +34461,10 @@ class PullRequestRepository {
34440
34461
  return this.httpClient.post(this.buildPath(workspace, repoSlug, `/${id}/merge`), request);
34441
34462
  }
34442
34463
  async approve(workspace, repoSlug, id) {
34443
- return this.httpClient.post(this.buildPath(workspace, repoSlug, `/${id}/approve`));
34464
+ return this.httpClient.post(this.buildPath(workspace, repoSlug, `/${id}/approve`), {});
34444
34465
  }
34445
34466
  async decline(workspace, repoSlug, id) {
34446
- return this.httpClient.post(this.buildPath(workspace, repoSlug, `/${id}/decline`));
34467
+ return this.httpClient.post(this.buildPath(workspace, repoSlug, `/${id}/decline`), {});
34447
34468
  }
34448
34469
  async getDiff(workspace, repoSlug, id) {
34449
34470
  return this.httpClient.getText(this.buildPath(workspace, repoSlug, `/${id}/diff`));
@@ -34451,6 +34472,22 @@ class PullRequestRepository {
34451
34472
  async getDiffstat(workspace, repoSlug, id) {
34452
34473
  return this.httpClient.get(this.buildPath(workspace, repoSlug, `/${id}/diffstat`));
34453
34474
  }
34475
+ async listComments(workspace, repoSlug, prId, limit = 25) {
34476
+ const safeLimit = Math.min(limit, API_PAGELEN_LIMITS.PULL_REQUESTS);
34477
+ return this.httpClient.get(`/repositories/${encodeURIComponent(workspace)}/${encodeURIComponent(repoSlug)}/pullrequests/${prId}/comments?pagelen=${safeLimit}`);
34478
+ }
34479
+ async getComment(workspace, repoSlug, prId, commentId) {
34480
+ return this.httpClient.get(`/repositories/${encodeURIComponent(workspace)}/${encodeURIComponent(repoSlug)}/pullrequests/${prId}/comments/${commentId}`);
34481
+ }
34482
+ async createComment(workspace, repoSlug, prId, content) {
34483
+ return this.httpClient.post(`/repositories/${encodeURIComponent(workspace)}/${encodeURIComponent(repoSlug)}/pullrequests/${prId}/comments`, { content: { raw: content } });
34484
+ }
34485
+ async updateComment(workspace, repoSlug, prId, commentId, content) {
34486
+ return this.httpClient.put(`/repositories/${encodeURIComponent(workspace)}/${encodeURIComponent(repoSlug)}/pullrequests/${prId}/comments/${commentId}`, { content: { raw: content } });
34487
+ }
34488
+ async deleteComment(workspace, repoSlug, prId, commentId) {
34489
+ return this.httpClient.delete(`/repositories/${encodeURIComponent(workspace)}/${encodeURIComponent(repoSlug)}/pullrequests/${prId}/comments/${commentId}`);
34490
+ }
34454
34491
  }
34455
34492
  // src/core/base-command.ts
34456
34493
  class BaseCommand {
@@ -35109,7 +35146,7 @@ class EditPRCommand extends BaseCommand {
35109
35146
  return branchResult;
35110
35147
  }
35111
35148
  const currentBranch = branchResult.value;
35112
- const prsResult = await this.prRepository.list(workspace, repoSlug, "OPEN");
35149
+ const prsResult = await this.prRepository.list(workspace, repoSlug, "OPEN", DEFAULT_PAGELEN.PULL_REQUESTS);
35113
35150
  if (!prsResult.success) {
35114
35151
  this.handleResult(prsResult, context);
35115
35152
  return prsResult;
@@ -35377,7 +35414,7 @@ class DiffPRCommand extends BaseCommand {
35377
35414
  return Result.err(error);
35378
35415
  }
35379
35416
  const currentBranch = currentBranchResult.value;
35380
- const prsResult = await this.prRepository.list(workspace, repoSlug, "OPEN", 100);
35417
+ const prsResult = await this.prRepository.list(workspace, repoSlug, "OPEN", DEFAULT_PAGELEN.PULL_REQUESTS);
35381
35418
  if (!prsResult.success) {
35382
35419
  this.handleResult(prsResult, context);
35383
35420
  return prsResult;
@@ -35543,6 +35580,139 @@ class DiffPRCommand extends BaseCommand {
35543
35580
  }
35544
35581
  }
35545
35582
 
35583
+ // src/commands/pr/comment.command.ts
35584
+ class CommentPRCommand extends BaseCommand {
35585
+ prRepository;
35586
+ contextService;
35587
+ name = "comment";
35588
+ description = "Add a comment to a pull request";
35589
+ constructor(prRepository, contextService, output) {
35590
+ super(output);
35591
+ this.prRepository = prRepository;
35592
+ this.contextService = contextService;
35593
+ }
35594
+ async execute(options, context) {
35595
+ const repoContextResult = await this.contextService.requireRepoContext({
35596
+ ...context.globalOptions,
35597
+ ...options
35598
+ });
35599
+ if (!repoContextResult.success) {
35600
+ this.handleResult(repoContextResult, context);
35601
+ return repoContextResult;
35602
+ }
35603
+ const { workspace, repoSlug } = repoContextResult.value;
35604
+ const prId = parseInt(options.id, 10);
35605
+ const result = await this.prRepository.createComment(workspace, repoSlug, prId, options.message);
35606
+ this.handleResult(result, context, () => {
35607
+ this.output.success(`Added comment to pull request #${prId}`);
35608
+ });
35609
+ return result;
35610
+ }
35611
+ }
35612
+
35613
+ // src/commands/pr/comments.list.command.ts
35614
+ class ListCommentsPRCommand extends BaseCommand {
35615
+ prRepository;
35616
+ contextService;
35617
+ name = "comments";
35618
+ description = "List comments on a pull request";
35619
+ constructor(prRepository, contextService, output) {
35620
+ super(output);
35621
+ this.prRepository = prRepository;
35622
+ this.contextService = contextService;
35623
+ }
35624
+ async execute(options, context) {
35625
+ const repoContextResult = await this.contextService.requireRepoContext({
35626
+ ...context.globalOptions,
35627
+ ...options
35628
+ });
35629
+ if (!repoContextResult.success) {
35630
+ this.handleResult(repoContextResult, context);
35631
+ return repoContextResult;
35632
+ }
35633
+ const { workspace, repoSlug } = repoContextResult.value;
35634
+ const prId = parseInt(options.id, 10);
35635
+ const limit = options.limit ? parseInt(options.limit, 10) : 25;
35636
+ const result = await this.prRepository.listComments(workspace, repoSlug, prId, limit);
35637
+ this.handleResult(result, context, (data) => {
35638
+ if (data.values.length === 0) {
35639
+ this.output.info("No comments found on this pull request");
35640
+ return;
35641
+ }
35642
+ const rows = data.values.map((comment) => [
35643
+ comment.id.toString(),
35644
+ comment.author?.username ?? comment.author?.display_name ?? "Unknown",
35645
+ comment.content.raw.slice(0, 60) + (comment.content.raw.length > 60 ? "..." : ""),
35646
+ this.output.formatDate(comment.created_on)
35647
+ ]);
35648
+ this.output.table(["ID", "Author", "Content", "Date"], rows);
35649
+ });
35650
+ return result;
35651
+ }
35652
+ }
35653
+
35654
+ // src/commands/pr/comments.edit.command.ts
35655
+ class EditCommentPRCommand extends BaseCommand {
35656
+ prRepository;
35657
+ contextService;
35658
+ name = "edit";
35659
+ description = "Edit a comment on a pull request";
35660
+ constructor(prRepository, contextService, output) {
35661
+ super(output);
35662
+ this.prRepository = prRepository;
35663
+ this.contextService = contextService;
35664
+ }
35665
+ async execute(options, context) {
35666
+ const repoContextResult = await this.contextService.requireRepoContext({
35667
+ ...context.globalOptions,
35668
+ ...options
35669
+ });
35670
+ if (!repoContextResult.success) {
35671
+ this.handleResult(repoContextResult, context);
35672
+ return repoContextResult;
35673
+ }
35674
+ const { workspace, repoSlug } = repoContextResult.value;
35675
+ const prId = parseInt(options.prId, 10);
35676
+ const commentId = parseInt(options.commentId, 10);
35677
+ const result = await this.prRepository.updateComment(workspace, repoSlug, prId, commentId, options.message);
35678
+ this.handleResult(result, context, () => {
35679
+ this.output.success(`Updated comment #${commentId}`);
35680
+ });
35681
+ return result;
35682
+ }
35683
+ }
35684
+
35685
+ // src/commands/pr/comments.delete.command.ts
35686
+ class DeleteCommentPRCommand extends BaseCommand {
35687
+ prRepository;
35688
+ contextService;
35689
+ name = "delete";
35690
+ description = "Delete a comment on a pull request";
35691
+ constructor(prRepository, contextService, output) {
35692
+ super(output);
35693
+ this.prRepository = prRepository;
35694
+ this.contextService = contextService;
35695
+ }
35696
+ async execute(options, context) {
35697
+ const repoContextResult = await this.contextService.requireRepoContext({
35698
+ ...context.globalOptions,
35699
+ ...options
35700
+ });
35701
+ if (!repoContextResult.success) {
35702
+ this.handleResult(repoContextResult, context);
35703
+ return repoContextResult;
35704
+ }
35705
+ const { workspace, repoSlug } = repoContextResult.value;
35706
+ const prId = parseInt(options.prId, 10);
35707
+ const commentId = parseInt(options.commentId, 10);
35708
+ const result = await this.prRepository.deleteComment(workspace, repoSlug, prId, commentId);
35709
+ this.handleResult(result, context, () => {
35710
+ this.output.success(`Deleted comment #${commentId} from PR #${prId}`);
35711
+ });
35712
+ return result;
35713
+ }
35714
+ }
35715
+
35546
35716
  // src/types/config.ts
35547
35717
  var SETTABLE_CONFIG_KEYS = ["defaultWorkspace"];
35548
35718
  var READABLE_CONFIG_KEYS = ["username", "defaultWorkspace"];
@@ -35859,6 +36029,30 @@ function bootstrap() {
35859
36029
  const output = container.resolve(ServiceTokens.OutputService);
35860
36030
  return new DiffPRCommand(prRepo, contextService, gitService, output);
35861
36031
  });
36032
+ container.register(ServiceTokens.CommentPRCommand, () => {
36033
+ const prRepo = container.resolve(ServiceTokens.PullRequestRepository);
36034
+ const contextService = container.resolve(ServiceTokens.ContextService);
36035
+ const output = container.resolve(ServiceTokens.OutputService);
36036
+ return new CommentPRCommand(prRepo, contextService, output);
36037
+ });
36038
+ container.register(ServiceTokens.ListCommentsPRCommand, () => {
36039
+ const prRepo = container.resolve(ServiceTokens.PullRequestRepository);
36040
+ const contextService = container.resolve(ServiceTokens.ContextService);
36041
+ const output = container.resolve(ServiceTokens.OutputService);
36042
+ return new ListCommentsPRCommand(prRepo, contextService, output);
36043
+ });
36044
+ container.register(ServiceTokens.EditCommentPRCommand, () => {
36045
+ const prRepo = container.resolve(ServiceTokens.PullRequestRepository);
36046
+ const contextService = container.resolve(ServiceTokens.ContextService);
36047
+ const output = container.resolve(ServiceTokens.OutputService);
36048
+ return new EditCommentPRCommand(prRepo, contextService, output);
36049
+ });
36050
+ container.register(ServiceTokens.DeleteCommentPRCommand, () => {
36051
+ const prRepo = container.resolve(ServiceTokens.PullRequestRepository);
36052
+ const contextService = container.resolve(ServiceTokens.ContextService);
36053
+ const output = container.resolve(ServiceTokens.OutputService);
36054
+ return new DeleteCommentPRCommand(prRepo, contextService, output);
36055
+ });
35862
36056
  container.register(ServiceTokens.GetConfigCommand, () => {
35863
36057
  const configService = container.resolve(ServiceTokens.ConfigService);
35864
36058
  const output = container.resolve(ServiceTokens.OutputService);
@@ -35909,7 +36103,7 @@ if (process.argv.includes("--get-yargs-completions") || process.env.COMP_LINE) {
35909
36103
  } else if (env2.prev === "repo") {
35910
36104
  completions.push("clone", "create", "list", "view", "delete");
35911
36105
  } else if (env2.prev === "pr") {
35912
- completions.push("create", "list", "view", "edit", "merge", "approve", "decline", "checkout", "diff");
36106
+ completions.push("create", "list", "view", "edit", "merge", "approve", "decline", "checkout", "diff", "comments");
35913
36107
  } else if (env2.prev === "config") {
35914
36108
  completions.push("get", "set", "list");
35915
36109
  } else if (env2.prev === "completion") {
@@ -36083,7 +36277,41 @@ prCmd.command("diff [id]").description("View pull request diff").option("--color
36083
36277
  process.exit(1);
36084
36278
  }
36085
36279
  });
36280
+ var prCommentsCmd = new Command("comments").description("Manage pull request comments");
36281
+ prCommentsCmd.command("list <id>").description("List comments on a pull request").option("--limit <number>", "Maximum number of comments (default: 25)").action(async (id, options) => {
36282
+ const cmd = container.resolve(ServiceTokens.ListCommentsPRCommand);
36283
+ const context = createContext(cli);
36284
+ const result = await cmd.execute(withGlobalOptions({ id, ...options }, context), context);
36285
+ if (!result.success) {
36286
+ process.exit(1);
36287
+ }
36288
+ });
36289
+ prCommentsCmd.command("add <id> <message>").description("Add a comment to a pull request").action(async (id, message, options) => {
36290
+ const cmd = container.resolve(ServiceTokens.CommentPRCommand);
36291
+ const context = createContext(cli);
36292
+ const result = await cmd.execute(withGlobalOptions({ id, message }, context), context);
36293
+ if (!result.success) {
36294
+ process.exit(1);
36295
+ }
36296
+ });
36297
+ prCommentsCmd.command("edit <pr-id> <comment-id> <message>").description("Edit a comment on a pull request").action(async (prId, commentId, message, options) => {
36298
+ const cmd = container.resolve(ServiceTokens.EditCommentPRCommand);
36299
+ const context = createContext(cli);
36300
+ const result = await cmd.execute(withGlobalOptions({ prId, commentId, message }, context), context);
36301
+ if (!result.success) {
36302
+ process.exit(1);
36303
+ }
36304
+ });
36305
+ prCommentsCmd.command("delete <pr-id> <comment-id>").description("Delete a comment on a pull request").action(async (prId, commentId, options) => {
36306
+ const cmd = container.resolve(ServiceTokens.DeleteCommentPRCommand);
36307
+ const context = createContext(cli);
36308
+ const result = await cmd.execute(withGlobalOptions({ prId, commentId }, context), context);
36309
+ if (!result.success) {
36310
+ process.exit(1);
36311
+ }
36312
+ });
36086
36313
  cli.addCommand(prCmd);
36314
+ prCmd.addCommand(prCommentsCmd);
36087
36315
  var configCmd = new Command("config").description("Manage configuration");
36088
36316
  configCmd.command("get <key>").description("Get a configuration value").action(async (key) => {
36089
36317
  const cmd = container.resolve(ServiceTokens.GetConfigCommand);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@pilatos/bitbucket-cli",
3
- "version": "1.1.0",
3
+ "version": "1.2.0",
4
4
  "description": "A command-line interface for Bitbucket Cloud",
5
5
  "author": "",
6
6
  "license": "MIT",