mobbdev 1.2.22 → 1.2.27

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.
@@ -237,6 +237,7 @@ var init_client_generates = __esm({
237
237
  IssueType_Enum2["DuplicatedStrings"] = "DUPLICATED_STRINGS";
238
238
  IssueType_Enum2["ErroneousStringCompare"] = "ERRONEOUS_STRING_COMPARE";
239
239
  IssueType_Enum2["ErrorCondtionWithoutAction"] = "ERROR_CONDTION_WITHOUT_ACTION";
240
+ IssueType_Enum2["ExcessiveSecretsExposure"] = "EXCESSIVE_SECRETS_EXPOSURE";
240
241
  IssueType_Enum2["FrameableLoginPage"] = "FRAMEABLE_LOGIN_PAGE";
241
242
  IssueType_Enum2["FunctionCallWithoutParentheses"] = "FUNCTION_CALL_WITHOUT_PARENTHESES";
242
243
  IssueType_Enum2["GhActionsShellInjection"] = "GH_ACTIONS_SHELL_INJECTION";
@@ -881,6 +882,7 @@ var init_client_generates = __esm({
881
882
  ... on ProcessAIBlameRequestedResult {
882
883
  status
883
884
  requestIds
885
+ commitBlameRequestIds
884
886
  }
885
887
  }
886
888
  }
@@ -1711,7 +1713,8 @@ var init_getIssueType = __esm({
1711
1713
  ["ACTION_NOT_PINNED_TO_COMMIT_SHA" /* ActionNotPinnedToCommitSha */]: "Action Not Pinned to Commit Sha",
1712
1714
  ["DJANGO_BLANK_FIELD_NEEDS_NULL_OR_DEFAULT" /* DjangoBlankFieldNeedsNullOrDefault */]: "Django Blank Field Needs Null or Default",
1713
1715
  ["REDUNDANT_NIL_ERROR_CHECK" /* RedundantNilErrorCheck */]: "Redundant Nil Error Check",
1714
- ["MISSING_WORKFLOW_PERMISSIONS" /* MissingWorkflowPermissions */]: "Missing Workflow Permissions"
1716
+ ["MISSING_WORKFLOW_PERMISSIONS" /* MissingWorkflowPermissions */]: "Missing Workflow Permissions",
1717
+ ["EXCESSIVE_SECRETS_EXPOSURE" /* ExcessiveSecretsExposure */]: "Excessive Secrets Exposure"
1715
1718
  };
1716
1719
  issueTypeZ = z5.nativeEnum(IssueType_Enum);
1717
1720
  getIssueTypeFriendlyString = (issueType) => {
@@ -2571,11 +2574,20 @@ var init_urlParser = __esm({
2571
2574
  }
2572
2575
  });
2573
2576
 
2577
+ // src/features/analysis/scm/shared/src/urlParser/repoSlug.ts
2578
+ var init_repoSlug = __esm({
2579
+ "src/features/analysis/scm/shared/src/urlParser/repoSlug.ts"() {
2580
+ "use strict";
2581
+ init_urlParser();
2582
+ }
2583
+ });
2584
+
2574
2585
  // src/features/analysis/scm/shared/src/urlParser/index.ts
2575
2586
  var init_urlParser2 = __esm({
2576
2587
  "src/features/analysis/scm/shared/src/urlParser/index.ts"() {
2577
2588
  "use strict";
2578
2589
  init_types2();
2590
+ init_repoSlug();
2579
2591
  init_urlParser();
2580
2592
  }
2581
2593
  });
@@ -4210,7 +4222,9 @@ function subscribeStream(query, variables, handlers, wsClientOptions) {
4210
4222
  finalizeError(error);
4211
4223
  },
4212
4224
  complete: () => {
4213
- return;
4225
+ finalizeError(
4226
+ new Error("Subscription completed by server before resolving")
4227
+ );
4214
4228
  }
4215
4229
  }
4216
4230
  );
@@ -4544,7 +4558,8 @@ var fixDetailsData = {
4544
4558
  ["ACTION_NOT_PINNED_TO_COMMIT_SHA" /* ActionNotPinnedToCommitSha */]: void 0,
4545
4559
  ["DJANGO_BLANK_FIELD_NEEDS_NULL_OR_DEFAULT" /* DjangoBlankFieldNeedsNullOrDefault */]: void 0,
4546
4560
  ["REDUNDANT_NIL_ERROR_CHECK" /* RedundantNilErrorCheck */]: void 0,
4547
- ["MISSING_WORKFLOW_PERMISSIONS" /* MissingWorkflowPermissions */]: void 0
4561
+ ["MISSING_WORKFLOW_PERMISSIONS" /* MissingWorkflowPermissions */]: void 0,
4562
+ ["EXCESSIVE_SECRETS_EXPOSURE" /* ExcessiveSecretsExposure */]: void 0
4548
4563
  };
4549
4564
 
4550
4565
  // src/features/analysis/scm/shared/src/commitDescriptionMarkup.ts
@@ -6146,9 +6161,6 @@ var GetReferenceResultZ = z14.object({
6146
6161
  type: z14.nativeEnum(ReferenceType)
6147
6162
  });
6148
6163
 
6149
- // src/features/analysis/scm/utils/diffUtils.ts
6150
- import parseDiff from "parse-diff";
6151
-
6152
6164
  // src/features/analysis/scm/ado/constants.ts
6153
6165
  init_types2();
6154
6166
  var DEFUALT_ADO_ORIGIN = scmCloudUrl.Ado;
@@ -6249,8 +6261,6 @@ var REPORT_DEFAULT_FILE_NAME = "report.json";
6249
6261
  init_env();
6250
6262
 
6251
6263
  // src/features/analysis/scm/github/GithubSCMLib.ts
6252
- init_env();
6253
- import pLimit from "p-limit";
6254
6264
  import { z as z22 } from "zod";
6255
6265
  init_client_generates();
6256
6266
 
@@ -6274,7 +6284,7 @@ import {
6274
6284
  Gitlab
6275
6285
  } from "@gitbeaker/rest";
6276
6286
  import Debug4 from "debug";
6277
- import pLimit2 from "p-limit";
6287
+ import pLimit from "p-limit";
6278
6288
  import {
6279
6289
  Agent,
6280
6290
  fetch as undiciFetch,
package/dist/index.mjs CHANGED
@@ -237,6 +237,7 @@ var init_client_generates = __esm({
237
237
  IssueType_Enum2["DuplicatedStrings"] = "DUPLICATED_STRINGS";
238
238
  IssueType_Enum2["ErroneousStringCompare"] = "ERRONEOUS_STRING_COMPARE";
239
239
  IssueType_Enum2["ErrorCondtionWithoutAction"] = "ERROR_CONDTION_WITHOUT_ACTION";
240
+ IssueType_Enum2["ExcessiveSecretsExposure"] = "EXCESSIVE_SECRETS_EXPOSURE";
240
241
  IssueType_Enum2["FrameableLoginPage"] = "FRAMEABLE_LOGIN_PAGE";
241
242
  IssueType_Enum2["FunctionCallWithoutParentheses"] = "FUNCTION_CALL_WITHOUT_PARENTHESES";
242
243
  IssueType_Enum2["GhActionsShellInjection"] = "GH_ACTIONS_SHELL_INJECTION";
@@ -881,6 +882,7 @@ var init_client_generates = __esm({
881
882
  ... on ProcessAIBlameRequestedResult {
882
883
  status
883
884
  requestIds
885
+ commitBlameRequestIds
884
886
  }
885
887
  }
886
888
  }
@@ -1411,7 +1413,8 @@ var init_getIssueType = __esm({
1411
1413
  ["ACTION_NOT_PINNED_TO_COMMIT_SHA" /* ActionNotPinnedToCommitSha */]: "Action Not Pinned to Commit Sha",
1412
1414
  ["DJANGO_BLANK_FIELD_NEEDS_NULL_OR_DEFAULT" /* DjangoBlankFieldNeedsNullOrDefault */]: "Django Blank Field Needs Null or Default",
1413
1415
  ["REDUNDANT_NIL_ERROR_CHECK" /* RedundantNilErrorCheck */]: "Redundant Nil Error Check",
1414
- ["MISSING_WORKFLOW_PERMISSIONS" /* MissingWorkflowPermissions */]: "Missing Workflow Permissions"
1416
+ ["MISSING_WORKFLOW_PERMISSIONS" /* MissingWorkflowPermissions */]: "Missing Workflow Permissions",
1417
+ ["EXCESSIVE_SECRETS_EXPOSURE" /* ExcessiveSecretsExposure */]: "Excessive Secrets Exposure"
1415
1418
  };
1416
1419
  issueTypeZ = z.nativeEnum(IssueType_Enum);
1417
1420
  getIssueTypeFriendlyString = (issueType) => {
@@ -2620,11 +2623,20 @@ var init_urlParser = __esm({
2620
2623
  }
2621
2624
  });
2622
2625
 
2626
+ // src/features/analysis/scm/shared/src/urlParser/repoSlug.ts
2627
+ var init_repoSlug = __esm({
2628
+ "src/features/analysis/scm/shared/src/urlParser/repoSlug.ts"() {
2629
+ "use strict";
2630
+ init_urlParser();
2631
+ }
2632
+ });
2633
+
2623
2634
  // src/features/analysis/scm/shared/src/urlParser/index.ts
2624
2635
  var init_urlParser2 = __esm({
2625
2636
  "src/features/analysis/scm/shared/src/urlParser/index.ts"() {
2626
2637
  "use strict";
2627
2638
  init_types2();
2639
+ init_repoSlug();
2628
2640
  init_urlParser();
2629
2641
  }
2630
2642
  });
@@ -4274,7 +4286,8 @@ var fixDetailsData = {
4274
4286
  ["ACTION_NOT_PINNED_TO_COMMIT_SHA" /* ActionNotPinnedToCommitSha */]: void 0,
4275
4287
  ["DJANGO_BLANK_FIELD_NEEDS_NULL_OR_DEFAULT" /* DjangoBlankFieldNeedsNullOrDefault */]: void 0,
4276
4288
  ["REDUNDANT_NIL_ERROR_CHECK" /* RedundantNilErrorCheck */]: void 0,
4277
- ["MISSING_WORKFLOW_PERMISSIONS" /* MissingWorkflowPermissions */]: void 0
4289
+ ["MISSING_WORKFLOW_PERMISSIONS" /* MissingWorkflowPermissions */]: void 0,
4290
+ ["EXCESSIVE_SECRETS_EXPOSURE" /* ExcessiveSecretsExposure */]: void 0
4278
4291
  };
4279
4292
 
4280
4293
  // src/features/analysis/scm/shared/src/commitDescriptionMarkup.ts
@@ -6109,34 +6122,6 @@ var GetReferenceResultZ = z13.object({
6109
6122
  type: z13.nativeEnum(ReferenceType)
6110
6123
  });
6111
6124
 
6112
- // src/features/analysis/scm/utils/diffUtils.ts
6113
- import parseDiff from "parse-diff";
6114
- function parseAddedLinesByFile(diff) {
6115
- const result = /* @__PURE__ */ new Map();
6116
- const parsedDiff = parseDiff(diff);
6117
- for (const file of parsedDiff) {
6118
- if (!file.to || file.to === "/dev/null") {
6119
- continue;
6120
- }
6121
- const filePath = file.to;
6122
- const addedLines = [];
6123
- if (file.chunks) {
6124
- for (const chunk of file.chunks) {
6125
- for (const change of chunk.changes) {
6126
- if (change.type === "add") {
6127
- const addChange = change;
6128
- addedLines.push(addChange.ln);
6129
- }
6130
- }
6131
- }
6132
- }
6133
- if (addedLines.length > 0) {
6134
- result.set(filePath, addedLines);
6135
- }
6136
- }
6137
- return result;
6138
- }
6139
-
6140
6125
  // src/features/analysis/scm/utils/scm.ts
6141
6126
  var safeBody = (body, maxBodyLength) => {
6142
6127
  const truncationNotice = "\n\n... Message was cut here because it is too long";
@@ -7101,28 +7086,16 @@ var SCMLib = class {
7101
7086
  *
7102
7087
  * @param repoUrl - Repository URL
7103
7088
  * @param prNumbers - Array of PR numbers to fetch commits for
7104
- * @returns Map of PR number to array of commit SHAs
7089
+ * @returns Map of PR number to array of commit SHAs in chronological order
7090
+ * (oldest first, HEAD commit last)
7105
7091
  */
7106
7092
  async getPrCommitsBatch(_repoUrl, _prNumbers) {
7107
7093
  throw new Error("getPrCommitsBatch not implemented for this SCM provider");
7108
7094
  }
7109
- /**
7110
- * Fetches additions and deletions counts for multiple PRs in batch.
7111
- * More efficient than fetching individual PR details.
7112
- *
7113
- * @param repoUrl - Repository URL
7114
- * @param prNumbers - Array of PR numbers to fetch metrics for
7115
- * @returns Map of PR number to additions/deletions count
7116
- */
7117
- async getPrAdditionsDeletionsBatch(_repoUrl, _prNumbers) {
7118
- throw new Error(
7119
- "getPrAdditionsDeletionsBatch not implemented for this SCM provider"
7120
- );
7121
- }
7122
7095
  /**
7123
7096
  * Batch fetch PR data (additions/deletions + comments) for multiple PRs.
7124
7097
  * Only implemented for GitHub (via GraphQL). Other providers should override if supported.
7125
- * This is more efficient than calling getPrAdditionsDeletionsBatch separately.
7098
+ * This is more efficient than calling separate batch methods.
7126
7099
  *
7127
7100
  * @param _repoUrl - Repository URL
7128
7101
  * @param _prNumbers - Array of PR numbers to fetch data for
@@ -7364,11 +7337,8 @@ var AdoSCMLib = class extends SCMLib {
7364
7337
  markdownComment: comment
7365
7338
  });
7366
7339
  }
7367
- async getCommitDiff(_commitSha) {
7368
- throw new Error("getCommitDiff not implemented for ADO");
7369
- }
7370
- async getSubmitRequestDiff(_submitRequestId) {
7371
- throw new Error("getSubmitRequestDiff not implemented for ADO");
7340
+ async getSubmitRequestMetadata(_submitRequestId) {
7341
+ throw new Error("getSubmitRequestMetadata not implemented for ADO");
7372
7342
  }
7373
7343
  async searchSubmitRequests(_params) {
7374
7344
  throw new Error("searchSubmitRequests not implemented for ADO");
@@ -7946,11 +7916,8 @@ var BitbucketSCMLib = class extends SCMLib {
7946
7916
  markdownComment: comment
7947
7917
  });
7948
7918
  }
7949
- async getCommitDiff(_commitSha) {
7950
- throw new Error("getCommitDiff not implemented for Bitbucket");
7951
- }
7952
- async getSubmitRequestDiff(_submitRequestId) {
7953
- throw new Error("getSubmitRequestDiff not implemented for Bitbucket");
7919
+ async getSubmitRequestMetadata(_submitRequestId) {
7920
+ throw new Error("getSubmitRequestMetadata not implemented for Bitbucket");
7954
7921
  }
7955
7922
  async searchSubmitRequests(_params) {
7956
7923
  throw new Error("searchSubmitRequests not implemented for Bitbucket");
@@ -7980,8 +7947,6 @@ var REPORT_DEFAULT_FILE_NAME = "report.json";
7980
7947
  init_env();
7981
7948
 
7982
7949
  // src/features/analysis/scm/github/GithubSCMLib.ts
7983
- init_env();
7984
- import pLimit from "p-limit";
7985
7950
  import { z as z21 } from "zod";
7986
7951
  init_client_generates();
7987
7952
 
@@ -8054,18 +8019,6 @@ var GET_PR_METRICS_QUERY = `
8054
8019
  mergedAt
8055
8020
  additions
8056
8021
  deletions
8057
- commits(first: 100) {
8058
- totalCount
8059
- nodes {
8060
- commit {
8061
- oid
8062
- committedDate
8063
- author {
8064
- date
8065
- }
8066
- }
8067
- }
8068
- }
8069
8022
  comments(first: 100) {
8070
8023
  totalCount
8071
8024
  nodes {
@@ -8506,33 +8459,6 @@ function getGithubSdk(params = {}) {
8506
8459
  commit_sha: commitSha
8507
8460
  });
8508
8461
  },
8509
- async getCommitWithDiff({
8510
- commitSha,
8511
- owner,
8512
- repo
8513
- }) {
8514
- const [commitData, diffData] = await Promise.all([
8515
- // Get commit metadata
8516
- octokit.rest.repos.getCommit({
8517
- repo,
8518
- owner,
8519
- ref: commitSha
8520
- }),
8521
- // Get commit diff
8522
- octokit.request("GET /repos/{owner}/{repo}/commits/{ref}", {
8523
- owner,
8524
- repo,
8525
- ref: commitSha,
8526
- headers: {
8527
- Accept: "application/vnd.github.v3.diff"
8528
- }
8529
- })
8530
- ]);
8531
- return {
8532
- commit: commitData.data,
8533
- diff: diffData.data
8534
- };
8535
- },
8536
8462
  async getTagDate({
8537
8463
  tag,
8538
8464
  owner,
@@ -8716,14 +8642,6 @@ function getGithubSdk(params = {}) {
8716
8642
  async getUserInfo() {
8717
8643
  return octokit.request(GET_USER);
8718
8644
  },
8719
- async getPrCommits(params2) {
8720
- const data = await octokit.paginate(octokit.rest.pulls.listCommits, {
8721
- owner: params2.owner,
8722
- repo: params2.repo,
8723
- pull_number: params2.pull_number
8724
- });
8725
- return { data };
8726
- },
8727
8645
  async getUserRepos() {
8728
8646
  return octokit.rest.repos.listForAuthenticatedUser({
8729
8647
  visibility: "all",
@@ -8767,30 +8685,6 @@ function getGithubSdk(params = {}) {
8767
8685
  });
8768
8686
  return { data };
8769
8687
  },
8770
- /**
8771
- * Batch fetch additions/deletions for multiple PRs via GraphQL.
8772
- * Uses GITHUB_GRAPHQL_FRAGMENTS.PR_CHANGES for the field selection.
8773
- */
8774
- async getPrAdditionsDeletionsBatch(params2) {
8775
- return executeBatchGraphQL(octokit, params2.owner, params2.repo, {
8776
- items: params2.prNumbers,
8777
- aliasPrefix: "pr",
8778
- buildFragment: (prNumber, index) => `
8779
- pr${index}: pullRequest(number: ${prNumber}) {
8780
- ${GITHUB_GRAPHQL_FRAGMENTS.PR_CHANGES}
8781
- }`,
8782
- extractResult: (data) => {
8783
- const prData = data;
8784
- if (prData.additions !== void 0 && prData.deletions !== void 0) {
8785
- return {
8786
- additions: prData.additions,
8787
- deletions: prData.deletions
8788
- };
8789
- }
8790
- return void 0;
8791
- }
8792
- });
8793
- },
8794
8688
  /**
8795
8689
  * Batch fetch comments for multiple PRs via GraphQL.
8796
8690
  * Uses GITHUB_GRAPHQL_FRAGMENTS.PR_COMMENTS for the field selection.
@@ -8818,7 +8712,7 @@ function getGithubSdk(params = {}) {
8818
8712
  /**
8819
8713
  * Batch fetch PR data (additions/deletions + comments) for multiple PRs via GraphQL.
8820
8714
  * Combines PR_CHANGES and PR_COMMENTS fragments into a single API call for efficiency.
8821
- * This is more efficient than calling getPrAdditionsDeletionsBatch and getPrCommentsBatch separately.
8715
+ * This is more efficient than calling separate batch methods.
8822
8716
  */
8823
8717
  async getPrDataBatch(params2) {
8824
8718
  return executeBatchGraphQL(octokit, params2.owner, params2.repo, {
@@ -9209,82 +9103,21 @@ var GithubSCMLib = class _GithubSCMLib extends SCMLib {
9209
9103
  comment_id: commentId
9210
9104
  });
9211
9105
  }
9212
- async getCommitDiff(commitSha, options) {
9106
+ async getSubmitRequestMetadata(submitRequestId) {
9213
9107
  this._validateAccessTokenAndUrl();
9214
9108
  const { owner, repo } = parseGithubOwnerAndRepo(this.url);
9215
- const { commit, diff } = await this.githubSdk.getCommitWithDiff({
9109
+ const prNumber = Number(submitRequestId);
9110
+ const prRes = await this.githubSdk.getPr({
9216
9111
  owner,
9217
9112
  repo,
9218
- commitSha
9113
+ pull_number: prNumber
9219
9114
  });
9220
- const commitTimestamp = commit.commit.committer?.date ? new Date(commit.commit.committer.date) : new Date(commit.commit.author?.date || Date.now());
9221
- let repositoryCreatedAt = options?.repositoryCreatedAt;
9222
- if (repositoryCreatedAt === void 0) {
9223
- try {
9224
- const repoData = await this.githubSdk.getRepository({ owner, repo });
9225
- repositoryCreatedAt = repoData.data.created_at ? new Date(repoData.data.created_at) : void 0;
9226
- } catch (error) {
9227
- console.error("Failed to fetch repository creation date", {
9228
- error,
9229
- owner,
9230
- repo
9231
- });
9232
- repositoryCreatedAt = void 0;
9233
- }
9234
- }
9235
- return {
9236
- diff,
9237
- commitTimestamp,
9238
- commitSha: commit.sha,
9239
- authorName: commit.commit.author?.name,
9240
- authorEmail: commit.commit.author?.email,
9241
- message: commit.commit.message,
9242
- repositoryCreatedAt
9243
- };
9244
- }
9245
- async getSubmitRequestDiff(submitRequestId) {
9246
- this._validateAccessTokenAndUrl();
9247
- const { owner, repo } = parseGithubOwnerAndRepo(this.url);
9248
- const prNumber = Number(submitRequestId);
9249
- const [prRes, commitsRes, repoData, prDiff] = await Promise.all([
9250
- this.githubSdk.getPr({ owner, repo, pull_number: prNumber }),
9251
- this.githubSdk.getPrCommits({ owner, repo, pull_number: prNumber }),
9252
- this.githubSdk.getRepository({ owner, repo }),
9253
- this.getPrDiff({ pull_number: prNumber })
9254
- ]);
9255
9115
  const pr = prRes.data;
9256
- const repositoryCreatedAt = repoData.data.created_at ? new Date(repoData.data.created_at) : void 0;
9257
- const limit = pLimit(GITHUB_API_CONCURRENCY);
9258
- const commits = await Promise.all(
9259
- commitsRes.data.map(
9260
- (commit) => limit(
9261
- () => this.getCommitDiff(commit.sha, {
9262
- repositoryCreatedAt
9263
- })
9264
- )
9265
- )
9266
- );
9267
- const addedLinesByFile = parseAddedLinesByFile(prDiff);
9268
- const diffLines = [];
9269
- for (const [file, lines] of addedLinesByFile) {
9270
- for (const line of lines) {
9271
- diffLines.push({ file, line });
9272
- }
9273
- }
9274
9116
  return {
9275
- diff: prDiff,
9276
- createdAt: new Date(pr.created_at),
9277
- updatedAt: new Date(pr.updated_at),
9278
- submitRequestId,
9279
- submitRequestNumber: prNumber,
9280
- sourceBranch: pr.head.ref,
9281
- targetBranch: pr.base.ref,
9282
- authorName: pr.user?.name || pr.user?.login,
9283
- authorEmail: pr.user?.email || void 0,
9284
9117
  title: pr.title,
9285
- description: pr.body || void 0,
9286
- commits,
9287
- diffLines
9118
+ targetBranch: pr.base.ref,
9119
+ sourceBranch: pr.head.ref,
9120
+ headCommitSha: pr.head.sha
9288
9121
  };
9289
9122
  }
9290
9123
  /**
@@ -9342,7 +9175,7 @@ var GithubSCMLib = class _GithubSCMLib extends SCMLib {
9342
9175
  }
9343
9176
  /**
9344
9177
  * Fetches commits for multiple PRs in a single GraphQL request.
9345
- * Much more efficient than calling getSubmitRequestDiff for each PR.
9178
+ * Much more efficient than fetching commits for each PR individually.
9346
9179
  *
9347
9180
  * @param repoUrl - Repository URL
9348
9181
  * @param prNumbers - Array of PR numbers to fetch commits for
@@ -9353,23 +9186,6 @@ var GithubSCMLib = class _GithubSCMLib extends SCMLib {
9353
9186
  const { owner, repo } = parseGithubOwnerAndRepo(repoUrl);
9354
9187
  return this.githubSdk.getPrCommitsBatch({ owner, repo, prNumbers });
9355
9188
  }
9356
- /**
9357
- * Fetches additions and deletions counts for multiple PRs in a single GraphQL request.
9358
- * Used to enrich search results with changed lines data.
9359
- *
9360
- * @param repoUrl - Repository URL
9361
- * @param prNumbers - Array of PR numbers to fetch metrics for
9362
- * @returns Map of PR number to additions/deletions count
9363
- */
9364
- async getPrAdditionsDeletionsBatch(repoUrl, prNumbers) {
9365
- this._validateAccessToken();
9366
- const { owner, repo } = parseGithubOwnerAndRepo(repoUrl);
9367
- return this.githubSdk.getPrAdditionsDeletionsBatch({
9368
- owner,
9369
- repo,
9370
- prNumbers
9371
- });
9372
- }
9373
9189
  /**
9374
9190
  * Batch fetch PR data (additions/deletions + comments) for multiple PRs.
9375
9191
  * Combines both metrics into a single GraphQL call for efficiency.
@@ -9469,19 +9285,6 @@ var GithubSCMLib = class _GithubSCMLib extends SCMLib {
9469
9285
  throw new Error(`Pull request #${prNumber} not found`);
9470
9286
  }
9471
9287
  const prStatus = determinePrStatus(pr.state, pr.isDraft);
9472
- const firstCommit = pr.commits.nodes[0];
9473
- const firstCommitDate = firstCommit ? new Date(
9474
- firstCommit.commit.author?.date || firstCommit.commit.committedDate || pr.createdAt
9475
- ) : null;
9476
- let commitShas = pr.commits.nodes.map((node) => node.commit.oid);
9477
- if (pr.commits.totalCount > 100) {
9478
- const commitsRes = await this.githubSdk.getPrCommits({
9479
- owner,
9480
- repo,
9481
- pull_number: prNumber
9482
- });
9483
- commitShas = commitsRes.data.map((c) => c.sha);
9484
- }
9485
9288
  let commentIds = pr.comments.nodes.map((node) => node.id);
9486
9289
  if (pr.comments.totalCount > 100) {
9487
9290
  const commentsRes = await this.githubSdk.getGeneralPrComments({
@@ -9496,10 +9299,7 @@ var GithubSCMLib = class _GithubSCMLib extends SCMLib {
9496
9299
  repositoryUrl: this.url,
9497
9300
  prCreatedAt: new Date(pr.createdAt),
9498
9301
  prMergedAt: pr.mergedAt ? new Date(pr.mergedAt) : null,
9499
- firstCommitDate,
9500
9302
  linesAdded: pr.additions,
9501
- commitsCount: pr.commits.totalCount,
9502
- commitShas,
9503
9303
  prStatus,
9504
9304
  commentIds
9505
9305
  };
@@ -9537,7 +9337,7 @@ import {
9537
9337
  Gitlab
9538
9338
  } from "@gitbeaker/rest";
9539
9339
  import Debug3 from "debug";
9540
- import pLimit2 from "p-limit";
9340
+ import pLimit from "p-limit";
9541
9341
  import {
9542
9342
  Agent,
9543
9343
  fetch as undiciFetch,
@@ -9619,14 +9419,6 @@ function removeTrailingSlash2(str) {
9619
9419
  return str.trim().replace(/\/+$/, "");
9620
9420
  }
9621
9421
  var MAX_GITLAB_PR_BODY_LENGTH = 1048576;
9622
- function buildUnifiedDiff(diffs) {
9623
- return diffs.filter((d) => d.diff).map((d) => {
9624
- const oldPath = d.old_path || d.new_path || "";
9625
- const newPath = d.new_path || d.old_path || "";
9626
- return `diff --git a/${oldPath} b/${newPath}
9627
- ${d.diff}`;
9628
- }).join("\n");
9629
- }
9630
9422
  function getRandomGitlabCloudAnonToken() {
9631
9423
  if (!GITLAB_API_TOKEN || typeof GITLAB_API_TOKEN !== "string") {
9632
9424
  return void 0;
@@ -9776,34 +9568,74 @@ async function getGitlabIsRemoteBranch({
9776
9568
  return false;
9777
9569
  }
9778
9570
  }
9779
- async function getGitlabRepoList(url, accessToken) {
9571
+ async function searchGitlabProjects({
9572
+ url,
9573
+ accessToken,
9574
+ perPage = 20,
9575
+ page = 1
9576
+ }) {
9577
+ if (perPage > GITLAB_MAX_PER_PAGE) {
9578
+ throw new Error(
9579
+ `perPage ${perPage} exceeds GitLab maximum of ${GITLAB_MAX_PER_PAGE}`
9580
+ );
9581
+ }
9780
9582
  const api2 = getGitBeaker({ url, gitlabAuthToken: accessToken });
9781
- const res = await api2.Projects.all({
9782
- membership: true,
9783
- //TODO: a bug in the sorting mechanism of this api call
9784
- //disallows us to sort by updated_at in descending order
9785
- //so we have to sort by updated_at in ascending order.
9786
- //We can wait for the bug to be fixed or call the api
9787
- //directly with fetch()
9788
- sort: "asc",
9789
- orderBy: "updated_at",
9790
- perPage: 100
9791
- });
9792
- return Promise.all(
9793
- res.map(async (project) => {
9794
- const proj = await api2.Projects.show(project.id);
9795
- const owner = proj.namespace.name;
9796
- const repoLanguages = await api2.Projects.showLanguages(project.id);
9797
- return {
9798
- repoName: project.path,
9799
- repoUrl: project.web_url,
9800
- repoOwner: owner,
9801
- repoLanguages: Object.keys(repoLanguages),
9802
- repoIsPublic: project.visibility === "public",
9803
- repoUpdatedAt: project.last_activity_at
9804
- };
9805
- })
9806
- );
9583
+ let response;
9584
+ try {
9585
+ response = await api2.Projects.all({
9586
+ membership: true,
9587
+ orderBy: "last_activity_at",
9588
+ sort: "desc",
9589
+ pagination: "offset",
9590
+ perPage,
9591
+ page,
9592
+ showExpanded: true
9593
+ });
9594
+ } catch (e) {
9595
+ debug4(
9596
+ "[searchGitlabProjects] order_by=last_activity_at failed, falling back to created_at: %s",
9597
+ e instanceof Error ? e.message : String(e)
9598
+ );
9599
+ response = await api2.Projects.all({
9600
+ membership: true,
9601
+ orderBy: "created_at",
9602
+ sort: "desc",
9603
+ pagination: "offset",
9604
+ perPage,
9605
+ page,
9606
+ showExpanded: true
9607
+ });
9608
+ }
9609
+ const projects = response.data.map((p) => ({
9610
+ id: p.id,
9611
+ path: p.path,
9612
+ web_url: p.web_url,
9613
+ namespace_name: p.namespace?.name ?? "",
9614
+ visibility: p.visibility,
9615
+ last_activity_at: p.last_activity_at
9616
+ }));
9617
+ return {
9618
+ projects,
9619
+ hasMore: response.paginationInfo.next !== null
9620
+ };
9621
+ }
9622
+ async function getGitlabProjectLanguages({
9623
+ url,
9624
+ accessToken,
9625
+ projectId
9626
+ }) {
9627
+ try {
9628
+ const api2 = getGitBeaker({ url, gitlabAuthToken: accessToken });
9629
+ const languages3 = await api2.Projects.showLanguages(projectId);
9630
+ return Object.keys(languages3);
9631
+ } catch (e) {
9632
+ debug4(
9633
+ "[getGitlabProjectLanguages] Failed for project %d: %s",
9634
+ projectId,
9635
+ e instanceof Error ? e.message : String(e)
9636
+ );
9637
+ return [];
9638
+ }
9807
9639
  }
9808
9640
  async function getGitlabBranchList({
9809
9641
  accessToken,
@@ -9873,6 +9705,11 @@ async function searchGitlabMergeRequests({
9873
9705
  perPage = GITLAB_PER_PAGE,
9874
9706
  page = 1
9875
9707
  }) {
9708
+ if (perPage > GITLAB_MAX_PER_PAGE) {
9709
+ throw new Error(
9710
+ `perPage ${perPage} exceeds GitLab maximum of ${GITLAB_MAX_PER_PAGE}`
9711
+ );
9712
+ }
9876
9713
  const { projectPath } = parseGitlabOwnerAndRepo(repoUrl);
9877
9714
  debug4(
9878
9715
  "[searchGitlabMergeRequests] Fetching MRs for %s (page=%d, perPage=%d)",
@@ -9884,16 +9721,17 @@ async function searchGitlabMergeRequests({
9884
9721
  url: repoUrl,
9885
9722
  gitlabAuthToken: accessToken
9886
9723
  });
9887
- const mergeRequests = await api2.MergeRequests.all({
9724
+ const response = await api2.MergeRequests.all({
9888
9725
  projectId: projectPath,
9889
9726
  state: state === "all" ? void 0 : state,
9890
9727
  updatedAfter: updatedAfter?.toISOString(),
9891
9728
  orderBy,
9892
9729
  sort,
9893
9730
  perPage,
9894
- page
9731
+ page,
9732
+ showExpanded: true
9895
9733
  });
9896
- const items = mergeRequests.map((mr) => ({
9734
+ const items = response.data.map((mr) => ({
9897
9735
  iid: mr.iid,
9898
9736
  title: mr.title,
9899
9737
  state: mr.state,
@@ -9911,7 +9749,7 @@ async function searchGitlabMergeRequests({
9911
9749
  );
9912
9750
  return {
9913
9751
  items,
9914
- hasMore: mergeRequests.length === perPage
9752
+ hasMore: response.paginationInfo.next !== null
9915
9753
  };
9916
9754
  }
9917
9755
  var GITLAB_API_CONCURRENCY = 5;
@@ -9928,7 +9766,7 @@ async function getGitlabMrCommitsBatch({
9928
9766
  url: repoUrl,
9929
9767
  gitlabAuthToken: accessToken
9930
9768
  });
9931
- const limit = pLimit2(GITLAB_API_CONCURRENCY);
9769
+ const limit = pLimit(GITLAB_API_CONCURRENCY);
9932
9770
  const results = await Promise.all(
9933
9771
  mrNumbers.map(
9934
9772
  (mrNumber) => limit(async () => {
@@ -9937,7 +9775,7 @@ async function getGitlabMrCommitsBatch({
9937
9775
  projectPath,
9938
9776
  mrNumber
9939
9777
  );
9940
- return [mrNumber, commits.map((c) => c.id)];
9778
+ return [mrNumber, commits.map((c) => c.id).reverse()];
9941
9779
  } catch (error) {
9942
9780
  contextLogger.warn(
9943
9781
  "[getGitlabMrCommitsBatch] Failed to fetch commits for MR",
@@ -9967,28 +9805,12 @@ async function getGitlabMrDataBatch({
9967
9805
  url: repoUrl,
9968
9806
  gitlabAuthToken: accessToken
9969
9807
  });
9970
- const limit = pLimit2(GITLAB_API_CONCURRENCY);
9808
+ const limit = pLimit(GITLAB_API_CONCURRENCY);
9971
9809
  const results = await Promise.all(
9972
9810
  mrNumbers.map(
9973
9811
  (mrNumber) => limit(async () => {
9974
9812
  try {
9975
- const [diffs, notes] = await Promise.all([
9976
- api2.MergeRequests.allDiffs(projectPath, mrNumber),
9977
- api2.MergeRequestNotes.all(projectPath, mrNumber)
9978
- ]);
9979
- let additions = 0;
9980
- let deletions = 0;
9981
- for (const diff of diffs) {
9982
- if (diff.diff) {
9983
- for (const line of diff.diff.split("\n")) {
9984
- if (line.startsWith("+") && !line.startsWith("+++")) {
9985
- additions++;
9986
- } else if (line.startsWith("-") && !line.startsWith("---")) {
9987
- deletions++;
9988
- }
9989
- }
9990
- }
9991
- }
9813
+ const notes = await api2.MergeRequestNotes.all(projectPath, mrNumber);
9992
9814
  const comments = notes.map((note) => ({
9993
9815
  author: note.author ? {
9994
9816
  login: note.author.username,
@@ -9998,7 +9820,7 @@ async function getGitlabMrDataBatch({
9998
9820
  }));
9999
9821
  return [
10000
9822
  mrNumber,
10001
- { changedLines: { additions, deletions }, comments }
9823
+ { changedLines: { additions: 0, deletions: 0 }, comments }
10002
9824
  ];
10003
9825
  } catch (error) {
10004
9826
  contextLogger.warn(
@@ -10022,39 +9844,6 @@ async function getGitlabMrDataBatch({
10022
9844
  );
10023
9845
  return new Map(results);
10024
9846
  }
10025
- async function getGitlabMergeRequestLinesAdded({
10026
- url,
10027
- prNumber,
10028
- accessToken
10029
- }) {
10030
- try {
10031
- const { projectPath } = parseGitlabOwnerAndRepo(url);
10032
- const api2 = getGitBeaker({
10033
- url,
10034
- gitlabAuthToken: accessToken
10035
- });
10036
- const diffs = await api2.MergeRequests.allDiffs(projectPath, prNumber);
10037
- let linesAdded = 0;
10038
- for (const diff of diffs) {
10039
- if (diff.diff) {
10040
- const addedLines = diff.diff.split("\n").filter(
10041
- (line) => line.startsWith("+") && !line.startsWith("+++")
10042
- ).length;
10043
- linesAdded += addedLines;
10044
- }
10045
- }
10046
- return linesAdded;
10047
- } catch (error) {
10048
- contextLogger.warn(
10049
- "[getGitlabMergeRequestLinesAdded] Failed to fetch diffs for MR",
10050
- {
10051
- prNumber,
10052
- error
10053
- }
10054
- );
10055
- return 0;
10056
- }
10057
- }
10058
9847
  async function getGitlabMergeRequestMetrics({
10059
9848
  url,
10060
9849
  prNumber,
@@ -10065,26 +9854,17 @@ async function getGitlabMergeRequestMetrics({
10065
9854
  url,
10066
9855
  gitlabAuthToken: accessToken
10067
9856
  });
10068
- const [mr, commits, linesAdded, notes] = await Promise.all([
9857
+ const [mr, notes] = await Promise.all([
10069
9858
  api2.MergeRequests.show(projectPath, prNumber),
10070
- api2.MergeRequests.allCommits(projectPath, prNumber),
10071
- getGitlabMergeRequestLinesAdded({ url, prNumber, accessToken }),
10072
9859
  api2.MergeRequestNotes.all(projectPath, prNumber)
10073
9860
  ]);
10074
- const sortedCommits = [...commits].sort(
10075
- (a, b) => new Date(a.created_at).getTime() - new Date(b.created_at).getTime()
10076
- );
10077
- const firstCommitDate = sortedCommits[0]?.created_at ?? null;
10078
9861
  const commentIds = notes.filter((note) => !note.system).map((note) => String(note.id));
10079
9862
  return {
10080
9863
  state: mr.state,
10081
9864
  isDraft: mr.draft ?? false,
10082
9865
  createdAt: mr.created_at,
10083
9866
  mergedAt: mr.merged_at ?? null,
10084
- linesAdded,
10085
- commitsCount: commits.length,
10086
- commitShas: commits.map((c) => c.id),
10087
- firstCommitDate,
9867
+ linesAdded: 0,
10088
9868
  commentIds
10089
9869
  };
10090
9870
  }
@@ -10166,7 +9946,8 @@ function parseGitlabOwnerAndRepo(gitlabUrl) {
10166
9946
  return { owner: organization, repo: repoName, projectPath };
10167
9947
  }
10168
9948
  var GITLAB_MAX_RESULTS_LIMIT = 1024;
10169
- var GITLAB_PER_PAGE = 128;
9949
+ var GITLAB_MAX_PER_PAGE = 100;
9950
+ var GITLAB_PER_PAGE = GITLAB_MAX_PER_PAGE;
10170
9951
  async function getGitlabRecentCommits({
10171
9952
  repoUrl,
10172
9953
  accessToken,
@@ -10175,14 +9956,17 @@ async function getGitlabRecentCommits({
10175
9956
  const { projectPath } = parseGitlabOwnerAndRepo(repoUrl);
10176
9957
  const api2 = getGitBeaker({ url: repoUrl, gitlabAuthToken: accessToken });
10177
9958
  const allCommits = [];
9959
+ const perPage = GITLAB_PER_PAGE;
10178
9960
  let page = 1;
10179
9961
  let hasMore = true;
10180
9962
  while (hasMore && allCommits.length < GITLAB_MAX_RESULTS_LIMIT) {
10181
- const commits = await api2.Commits.all(projectPath, {
9963
+ const response = await api2.Commits.all(projectPath, {
10182
9964
  since,
10183
- perPage: GITLAB_PER_PAGE,
10184
- page
9965
+ perPage,
9966
+ page,
9967
+ showExpanded: true
10185
9968
  });
9969
+ const commits = response.data;
10186
9970
  if (commits.length === 0) {
10187
9971
  hasMore = false;
10188
9972
  break;
@@ -10204,11 +9988,8 @@ async function getGitlabRecentCommits({
10204
9988
  parents: commit.parent_ids?.map((sha) => ({ sha })) || []
10205
9989
  });
10206
9990
  }
10207
- if (commits.length < GITLAB_PER_PAGE) {
10208
- hasMore = false;
10209
- } else {
10210
- page++;
10211
- }
9991
+ hasMore = response.paginationInfo.next !== null;
9992
+ page++;
10212
9993
  }
10213
9994
  if (allCommits.length >= GITLAB_MAX_RESULTS_LIMIT) {
10214
9995
  contextLogger.warn("[getGitlabRecentCommits] Hit commit pagination limit", {
@@ -10220,29 +10001,6 @@ async function getGitlabRecentCommits({
10220
10001
  }
10221
10002
  return allCommits;
10222
10003
  }
10223
- async function getGitlabCommitDiff({
10224
- repoUrl,
10225
- accessToken,
10226
- commitSha
10227
- }) {
10228
- const { projectPath } = parseGitlabOwnerAndRepo(repoUrl);
10229
- const api2 = getGitBeaker({ url: repoUrl, gitlabAuthToken: accessToken });
10230
- const [commit, diffs] = await Promise.all([
10231
- api2.Commits.show(projectPath, commitSha),
10232
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
10233
- api2.Commits.showDiff(projectPath, commitSha, { unidiff: true })
10234
- ]);
10235
- const diffString = buildUnifiedDiff(diffs);
10236
- const commitTimestamp = commit.committed_date ? new Date(commit.committed_date) : /* @__PURE__ */ new Date();
10237
- return {
10238
- diff: diffString,
10239
- commitTimestamp,
10240
- commitSha: commit.id,
10241
- authorName: commit.author_name,
10242
- authorEmail: commit.author_email,
10243
- message: commit.message
10244
- };
10245
- }
10246
10004
  async function getGitlabRateLimitStatus({
10247
10005
  repoUrl,
10248
10006
  accessToken
@@ -10324,88 +10082,6 @@ async function brokerRequestHandler(endpoint, options) {
10324
10082
  };
10325
10083
  throw new Error(`gitbeaker: ${response.statusText}`);
10326
10084
  }
10327
- async function getGitlabMergeRequestDiff({
10328
- repoUrl,
10329
- accessToken,
10330
- mrNumber
10331
- }) {
10332
- debug4("[getGitlabMergeRequestDiff] Starting for MR #%d", mrNumber);
10333
- const { projectPath } = parseGitlabOwnerAndRepo(repoUrl);
10334
- const api2 = getGitBeaker({ url: repoUrl, gitlabAuthToken: accessToken });
10335
- debug4(
10336
- "[getGitlabMergeRequestDiff] Fetching MR details, diffs, and commits..."
10337
- );
10338
- const startMrFetch = Date.now();
10339
- const [mr, mrDiffs, mrCommitsRaw] = await Promise.all([
10340
- api2.MergeRequests.show(projectPath, mrNumber),
10341
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
10342
- api2.MergeRequests.allDiffs(projectPath, mrNumber, { unidiff: true }),
10343
- api2.MergeRequests.allCommits(projectPath, mrNumber)
10344
- ]);
10345
- debug4(
10346
- "[getGitlabMergeRequestDiff] MR fetch took %dms. Diffs: %d, Commits: %d",
10347
- Date.now() - startMrFetch,
10348
- mrDiffs.length,
10349
- mrCommitsRaw.length
10350
- );
10351
- const diffString = buildUnifiedDiff(mrDiffs);
10352
- debug4(
10353
- "[getGitlabMergeRequestDiff] Fetching commit diffs for %d commits...",
10354
- mrCommitsRaw.length
10355
- );
10356
- const startCommitFetch = Date.now();
10357
- const commitDiffLimit = pLimit2(GITLAB_API_CONCURRENCY);
10358
- const commits = await Promise.all(
10359
- mrCommitsRaw.map(
10360
- (commit) => commitDiffLimit(async () => {
10361
- const commitDiff = await getGitlabCommitDiff({
10362
- repoUrl,
10363
- accessToken,
10364
- commitSha: commit.id
10365
- });
10366
- return {
10367
- diff: commitDiff.diff,
10368
- commitTimestamp: commitDiff.commitTimestamp,
10369
- commitSha: commitDiff.commitSha,
10370
- authorName: commitDiff.authorName,
10371
- authorEmail: commitDiff.authorEmail,
10372
- message: commitDiff.message
10373
- };
10374
- })
10375
- )
10376
- );
10377
- commits.sort(
10378
- (a, b) => new Date(a.commitTimestamp).getTime() - new Date(b.commitTimestamp).getTime()
10379
- );
10380
- debug4(
10381
- "[getGitlabMergeRequestDiff] Commit diffs fetch took %dms",
10382
- Date.now() - startCommitFetch
10383
- );
10384
- const addedLinesByFile = parseAddedLinesByFile(diffString);
10385
- const diffLines = [];
10386
- for (const [file, lines] of addedLinesByFile) {
10387
- for (const line of lines) {
10388
- diffLines.push({ file, line });
10389
- }
10390
- }
10391
- return {
10392
- diff: diffString,
10393
- createdAt: new Date(mr.created_at),
10394
- updatedAt: new Date(mr.updated_at),
10395
- submitRequestId: String(mrNumber),
10396
- submitRequestNumber: mrNumber,
10397
- sourceBranch: mr.source_branch,
10398
- targetBranch: mr.target_branch,
10399
- authorName: mr.author?.name || mr.author?.username,
10400
- authorEmail: void 0,
10401
- // GitLab MR API doesn't expose author email directly
10402
- title: mr.title,
10403
- description: mr.description || void 0,
10404
- commits,
10405
- headCommitSha: mr.sha,
10406
- diffLines
10407
- };
10408
- }
10409
10085
 
10410
10086
  // src/features/analysis/scm/gitlab/GitlabSCMLib.ts
10411
10087
  init_client_generates();
@@ -10438,7 +10114,20 @@ var GitlabSCMLib = class extends SCMLib {
10438
10114
  contextLogger.warn("[GitlabSCMLib.getRepoList] No access token provided");
10439
10115
  throw new Error("no access token");
10440
10116
  }
10441
- return getGitlabRepoList(this.url, this.accessToken);
10117
+ const allRepos = [];
10118
+ let cursor;
10119
+ let hasMore = true;
10120
+ while (hasMore) {
10121
+ const page = await this.searchRepos({
10122
+ scmOrg: _scmOrg,
10123
+ limit: 100,
10124
+ cursor
10125
+ });
10126
+ allRepos.push(...page.results);
10127
+ hasMore = page.hasMore;
10128
+ cursor = page.nextCursor;
10129
+ }
10130
+ return allRepos;
10442
10131
  }
10443
10132
  async getBranchList() {
10444
10133
  this._validateAccessTokenAndUrl();
@@ -10570,33 +10259,23 @@ var GitlabSCMLib = class extends SCMLib {
10570
10259
  this._validateAccessTokenAndUrl();
10571
10260
  return `${this.url}/-/commits/${branchName}`;
10572
10261
  }
10573
- async getCommitDiff(commitSha) {
10574
- this._validateAccessTokenAndUrl();
10575
- const result = await getGitlabCommitDiff({
10576
- repoUrl: this.url,
10577
- accessToken: this.accessToken,
10578
- commitSha
10579
- });
10580
- return {
10581
- diff: result.diff,
10582
- commitTimestamp: result.commitTimestamp,
10583
- commitSha: result.commitSha,
10584
- authorName: result.authorName,
10585
- authorEmail: result.authorEmail,
10586
- message: result.message
10587
- };
10588
- }
10589
- async getSubmitRequestDiff(submitRequestId) {
10262
+ async getSubmitRequestMetadata(submitRequestId) {
10590
10263
  this._validateAccessTokenAndUrl();
10591
10264
  const mrNumber = parseInt(submitRequestId, 10);
10592
10265
  if (isNaN(mrNumber) || mrNumber <= 0) {
10593
10266
  throw new Error(`Invalid merge request ID: ${submitRequestId}`);
10594
10267
  }
10595
- return getGitlabMergeRequestDiff({
10596
- repoUrl: this.url,
10597
- accessToken: this.accessToken,
10598
- mrNumber
10268
+ const mr = await getGitlabMergeRequest({
10269
+ url: this.url,
10270
+ prNumber: mrNumber,
10271
+ accessToken: this.accessToken
10599
10272
  });
10273
+ return {
10274
+ title: mr.title,
10275
+ targetBranch: mr.target_branch,
10276
+ sourceBranch: mr.source_branch,
10277
+ headCommitSha: mr.sha
10278
+ };
10600
10279
  }
10601
10280
  async searchSubmitRequests(params) {
10602
10281
  this._validateAccessTokenAndUrl();
@@ -10678,8 +10357,47 @@ var GitlabSCMLib = class extends SCMLib {
10678
10357
  mrNumbers: prNumbers
10679
10358
  });
10680
10359
  }
10681
- async searchRepos(_params) {
10682
- throw new Error("searchRepos not implemented for GitLab");
10360
+ async searchRepos(params) {
10361
+ if (!this.accessToken) {
10362
+ throw new Error("no access token");
10363
+ }
10364
+ const page = parseCursorSafe(params.cursor, 1);
10365
+ const perPage = params.limit || 10;
10366
+ const { projects, hasMore } = await searchGitlabProjects({
10367
+ url: this.url,
10368
+ accessToken: this.accessToken,
10369
+ perPage,
10370
+ page
10371
+ });
10372
+ const includeLanguages = params.includeLanguages !== false;
10373
+ const languageMap = /* @__PURE__ */ new Map();
10374
+ if (includeLanguages && projects.length > 0) {
10375
+ const languageResults = await Promise.all(
10376
+ projects.map(
10377
+ (p) => getGitlabProjectLanguages({
10378
+ url: this.url,
10379
+ accessToken: this.accessToken,
10380
+ projectId: p.id
10381
+ }).then((langs) => [p.id, langs])
10382
+ )
10383
+ );
10384
+ for (const [id, langs] of languageResults) {
10385
+ languageMap.set(id, langs);
10386
+ }
10387
+ }
10388
+ const results = projects.map((p) => ({
10389
+ repoName: p.path,
10390
+ repoUrl: p.web_url,
10391
+ repoOwner: p.namespace_name,
10392
+ repoLanguages: languageMap.get(p.id) || [],
10393
+ repoIsPublic: p.visibility === "public",
10394
+ repoUpdatedAt: p.last_activity_at
10395
+ }));
10396
+ return {
10397
+ results,
10398
+ nextCursor: hasMore ? String(page + 1) : void 0,
10399
+ hasMore
10400
+ };
10683
10401
  }
10684
10402
  async getPullRequestMetrics(prNumber) {
10685
10403
  this._validateAccessTokenAndUrl();
@@ -10704,10 +10422,7 @@ var GitlabSCMLib = class extends SCMLib {
10704
10422
  repositoryUrl: this.url,
10705
10423
  prCreatedAt: new Date(metrics.createdAt),
10706
10424
  prMergedAt: metrics.mergedAt ? new Date(metrics.mergedAt) : null,
10707
- firstCommitDate: metrics.firstCommitDate ? new Date(metrics.firstCommitDate) : null,
10708
10425
  linesAdded: metrics.linesAdded,
10709
- commitsCount: metrics.commitsCount,
10710
- commitShas: metrics.commitShas,
10711
10426
  prStatus,
10712
10427
  commentIds: metrics.commentIds
10713
10428
  };
@@ -10837,34 +10552,8 @@ var StubSCMLib = class extends SCMLib {
10837
10552
  async addCommentToSubmitRequest(_submitRequestId, _comment) {
10838
10553
  console.warn("addCommentToSubmitRequest() no-op");
10839
10554
  }
10840
- async getCommitDiff(_commitSha) {
10841
- console.warn("getCommitDiff() returning stub diff");
10842
- return {
10843
- diff: "",
10844
- commitTimestamp: /* @__PURE__ */ new Date(),
10845
- commitSha: _commitSha,
10846
- authorName: void 0,
10847
- authorEmail: void 0,
10848
- message: void 0
10849
- };
10850
- }
10851
- async getSubmitRequestDiff(_submitRequestId) {
10852
- console.warn("getSubmitRequestDiff() returning stub diff");
10853
- return {
10854
- diff: "",
10855
- createdAt: /* @__PURE__ */ new Date(),
10856
- updatedAt: /* @__PURE__ */ new Date(),
10857
- submitRequestId: _submitRequestId,
10858
- submitRequestNumber: parseInt(_submitRequestId) || 0,
10859
- sourceBranch: "",
10860
- targetBranch: "",
10861
- authorName: void 0,
10862
- authorEmail: void 0,
10863
- title: void 0,
10864
- description: void 0,
10865
- commits: [],
10866
- diffLines: []
10867
- };
10555
+ async getSubmitRequestMetadata(_submitRequestId) {
10556
+ throw new Error("getSubmitRequestMetadata() not implemented");
10868
10557
  }
10869
10558
  async getPullRequestMetrics(_prNumber) {
10870
10559
  console.warn("getPullRequestMetrics() returning empty object");
@@ -12001,7 +11690,9 @@ function subscribeStream(query, variables, handlers, wsClientOptions) {
12001
11690
  finalizeError(error);
12002
11691
  },
12003
11692
  complete: () => {
12004
- return;
11693
+ finalizeError(
11694
+ new Error("Subscription completed by server before resolving")
11695
+ );
12005
11696
  }
12006
11697
  }
12007
11698
  );
@@ -12903,7 +12594,7 @@ import Debug10 from "debug";
12903
12594
 
12904
12595
  // src/features/analysis/add_fix_comments_for_pr/utils/utils.ts
12905
12596
  import Debug9 from "debug";
12906
- import parseDiff2 from "parse-diff";
12597
+ import parseDiff from "parse-diff";
12907
12598
  import { z as z27 } from "zod";
12908
12599
 
12909
12600
  // src/features/analysis/utils/by_key.ts
@@ -13276,7 +12967,7 @@ Refresh the page in order to see the changes.`,
13276
12967
  }
13277
12968
  async function getRelevantVulenrabilitiesFromDiff(params) {
13278
12969
  const { gqlClient, diff, vulnerabilityReportId } = params;
13279
- const parsedDiff = parseDiff2(diff);
12970
+ const parsedDiff = parseDiff(diff);
13280
12971
  const fileHunks = parsedDiff.map((file) => {
13281
12972
  const fileNumbers = file.chunks.flatMap((chunk) => chunk.changes).filter((change) => change.type === "add").map((_change) => {
13282
12973
  const change = _change;
@@ -21710,7 +21401,7 @@ import {
21710
21401
  writeFileSync
21711
21402
  } from "fs";
21712
21403
  import fs22 from "fs/promises";
21713
- import parseDiff3 from "parse-diff";
21404
+ import parseDiff2 from "parse-diff";
21714
21405
  import path21 from "path";
21715
21406
  var PatchApplicationService = class {
21716
21407
  /**
@@ -22394,7 +22085,7 @@ var PatchApplicationService = class {
22394
22085
  fixId,
22395
22086
  scanContext
22396
22087
  }) {
22397
- const parsedPatch = parseDiff3(patch);
22088
+ const parsedPatch = parseDiff2(patch);
22398
22089
  if (!parsedPatch || parsedPatch.length === 0) {
22399
22090
  throw new Error("Failed to parse patch - no changes found");
22400
22091
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "mobbdev",
3
- "version": "1.2.22",
3
+ "version": "1.2.27",
4
4
  "description": "Automated secure code remediation tool",
5
5
  "repository": "git+https://github.com/mobb-dev/bugsy.git",
6
6
  "main": "dist/index.mjs",