mobbdev 0.0.110 → 0.0.113

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.mjs +1647 -1143
  2. package/package.json +7 -6
package/dist/index.mjs CHANGED
@@ -524,7 +524,7 @@ import fetch3 from "node-fetch";
524
524
  import open2 from "open";
525
525
  import semver from "semver";
526
526
  import tmp2 from "tmp";
527
- import { z as z11 } from "zod";
527
+ import { z as z12 } from "zod";
528
528
 
529
529
  // src/features/analysis/git.ts
530
530
  import Debug2 from "debug";
@@ -952,35 +952,46 @@ var GQLClient = class {
952
952
  import { Octokit as Octokit3 } from "@octokit/core";
953
953
  import Debug5 from "debug";
954
954
  import parseDiff2 from "parse-diff";
955
- import { z as z10 } from "zod";
955
+ import { z as z11 } from "zod";
956
956
 
957
957
  // src/features/analysis/scm/ado.ts
958
- import querystring2 from "node:querystring";
958
+ import querystring from "node:querystring";
959
959
  import * as api from "azure-devops-node-api";
960
- import { z as z9 } from "zod";
961
-
962
- // src/features/analysis/scm/scm.ts
963
- import { Octokit as Octokit2 } from "@octokit/core";
964
- import { z as z8 } from "zod";
965
-
966
- // src/features/analysis/scm/github/encryptSecret.ts
967
- import sodium from "libsodium-wrappers";
968
- async function encryptSecret(secret, key) {
969
- await sodium.ready;
970
- const binkey = sodium.from_base64(key, sodium.base64_variants.ORIGINAL);
971
- const binsec = sodium.from_string(secret);
972
- const encBytes = sodium.crypto_box_seal(binsec, binkey);
973
- return sodium.to_base64(encBytes, sodium.base64_variants.ORIGINAL);
974
- }
975
-
976
- // src/features/analysis/scm/github/github.ts
977
- import { RequestError } from "@octokit/request-error";
978
- import { Octokit } from "octokit";
979
960
  import { z as z3 } from "zod";
980
961
 
962
+ // src/features/analysis/scm/types.ts
963
+ var ReferenceType = /* @__PURE__ */ ((ReferenceType2) => {
964
+ ReferenceType2["BRANCH"] = "BRANCH";
965
+ ReferenceType2["COMMIT"] = "COMMIT";
966
+ ReferenceType2["TAG"] = "TAG";
967
+ return ReferenceType2;
968
+ })(ReferenceType || {});
969
+ var ScmLibScmType = /* @__PURE__ */ ((ScmLibScmType2) => {
970
+ ScmLibScmType2["GITHUB"] = "GITHUB";
971
+ ScmLibScmType2["GITLAB"] = "GITLAB";
972
+ ScmLibScmType2["ADO"] = "ADO";
973
+ ScmLibScmType2["BITBUCKET"] = "BITBUCKET";
974
+ return ScmLibScmType2;
975
+ })(ScmLibScmType || {});
976
+ var scmCloudUrl = {
977
+ GitLab: "https://gitlab.com",
978
+ GitHub: "https://github.com",
979
+ Ado: "https://dev.azure.com",
980
+ Bitbucket: "https://bitbucket.org"
981
+ };
982
+ var ScmType = /* @__PURE__ */ ((ScmType2) => {
983
+ ScmType2["GitHub"] = "GitHub";
984
+ ScmType2["GitLab"] = "GitLab";
985
+ ScmType2["Ado"] = "Ado";
986
+ ScmType2["Bitbucket"] = "Bitbucket";
987
+ return ScmType2;
988
+ })(ScmType || {});
989
+
981
990
  // src/features/analysis/scm/urlParser.ts
982
- function getRepoInfo(pathname, hostname, scmType) {
991
+ function detectAdoUrl(args) {
992
+ const { pathname, hostname, scmType } = args;
983
993
  const hostnameParts = hostname.split(".");
994
+ const adoHostname = new URL(scmCloudUrl.Ado).hostname;
984
995
  if (hostnameParts.length === 3 && hostnameParts[1] === "visualstudio" && hostnameParts[2] === "com") {
985
996
  if (pathname.length === 2 && pathname[0] === "_git") {
986
997
  return {
@@ -997,7 +1008,7 @@ function getRepoInfo(pathname, hostname, scmType) {
997
1008
  };
998
1009
  }
999
1010
  }
1000
- if (hostname === "dev.azure.com" || scmType === "Ado" /* Ado */) {
1011
+ if (hostname === adoHostname || scmType === "Ado" /* Ado */) {
1001
1012
  if (pathname.length === 3 && pathname[1] === "_git") {
1002
1013
  return {
1003
1014
  organization: pathname[0],
@@ -1013,7 +1024,12 @@ function getRepoInfo(pathname, hostname, scmType) {
1013
1024
  };
1014
1025
  }
1015
1026
  }
1016
- if (hostname === "github.com" || scmType === "GitHub" /* GitHub */) {
1027
+ return null;
1028
+ }
1029
+ function detectGithubUrl(args) {
1030
+ const { pathname, hostname, scmType } = args;
1031
+ const githubHostname = new URL(scmCloudUrl.GitHub).hostname;
1032
+ if (hostname === githubHostname || scmType === "GitHub" /* GitHub */) {
1017
1033
  if (pathname.length === 2) {
1018
1034
  return {
1019
1035
  organization: pathname[0],
@@ -1022,7 +1038,12 @@ function getRepoInfo(pathname, hostname, scmType) {
1022
1038
  };
1023
1039
  }
1024
1040
  }
1025
- if (hostname === "gitlab.com" || scmType === "GitLab" /* GitLab */) {
1041
+ return null;
1042
+ }
1043
+ function detectGitlabUrl(args) {
1044
+ const { pathname, hostname, scmType } = args;
1045
+ const gitlabHostname = new URL(scmCloudUrl.GitLab).hostname;
1046
+ if (hostname === gitlabHostname || scmType === "GitLab" /* GitLab */) {
1026
1047
  if (pathname.length >= 2) {
1027
1048
  return {
1028
1049
  organization: pathname[0],
@@ -1033,13 +1054,46 @@ function getRepoInfo(pathname, hostname, scmType) {
1033
1054
  }
1034
1055
  return null;
1035
1056
  }
1057
+ function detectBitbucketUrl(args) {
1058
+ const { pathname, hostname, scmType } = args;
1059
+ const bitbucketHostname = new URL(scmCloudUrl.Bitbucket).hostname;
1060
+ if (hostname === bitbucketHostname || scmType === "Bitbucket" /* Bitbucket */) {
1061
+ if (pathname.length === 2) {
1062
+ return {
1063
+ organization: pathname[0],
1064
+ projectName: void 0,
1065
+ repoName: pathname[1]
1066
+ };
1067
+ }
1068
+ }
1069
+ return null;
1070
+ }
1071
+ var getRepoUrlFunctionMap = {
1072
+ ["GitLab" /* GitLab */]: detectGitlabUrl,
1073
+ ["GitHub" /* GitHub */]: detectGithubUrl,
1074
+ ["Ado" /* Ado */]: detectAdoUrl,
1075
+ ["Bitbucket" /* Bitbucket */]: detectBitbucketUrl
1076
+ };
1077
+ function getRepoInfo(args) {
1078
+ for (const detectUrl of Object.values(getRepoUrlFunctionMap)) {
1079
+ const detectUrlRes = detectUrl(args);
1080
+ if (detectUrlRes) {
1081
+ return detectUrlRes;
1082
+ }
1083
+ }
1084
+ return null;
1085
+ }
1036
1086
  var NAME_REGEX = /[a-z0-9\-_.+]+/i;
1037
1087
  var parseScmURL = (scmURL, scmType) => {
1038
1088
  try {
1039
1089
  const url = new URL(scmURL);
1040
1090
  const hostname = url.hostname.toLowerCase();
1041
1091
  const projectPath = url.pathname.substring(1).replace(/.git$/i, "");
1042
- const repo = getRepoInfo(projectPath.split("/"), hostname, scmType);
1092
+ const repo = getRepoInfo({
1093
+ pathname: projectPath.split("/"),
1094
+ hostname,
1095
+ scmType
1096
+ });
1043
1097
  if (!repo)
1044
1098
  return null;
1045
1099
  const { organization, repoName, projectName } = repo;
@@ -1076,255 +1130,894 @@ var sanityRepoURL = (scmURL) => {
1076
1130
  }
1077
1131
  };
1078
1132
 
1079
- // src/features/analysis/scm/github/github.ts
1133
+ // src/features/analysis/scm/ado.ts
1080
1134
  function removeTrailingSlash(str) {
1081
1135
  return str.trim().replace(/\/+$/, "");
1082
1136
  }
1083
- var EnvVariablesZod = z3.object({
1084
- GITHUB_API_TOKEN: z3.string().optional()
1085
- });
1086
- var { GITHUB_API_TOKEN } = EnvVariablesZod.parse(process.env);
1087
- var GetBlameDocument = `
1088
- query GetBlame(
1089
- $owner: String!
1090
- $repo: String!
1091
- $ref: String!
1092
- $path: String!
1093
- ) {
1094
- repository(name: $repo, owner: $owner) {
1095
- # branch name
1096
- object(expression: $ref) {
1097
- # cast Target to a Commit
1098
- ... on Commit {
1099
- # full repo-relative path to blame file
1100
- blame(path: $path) {
1101
- ranges {
1102
- commit {
1103
- author {
1104
- user {
1105
- name
1106
- login
1107
- }
1108
- }
1109
- authoredDate
1110
- }
1111
- startingLine
1112
- endingLine
1113
- age
1114
- }
1115
- }
1116
- }
1117
-
1118
- }
1119
- }
1137
+ async function _getOrgsForOauthToken({ oauthToken }) {
1138
+ const profileZ = z3.object({
1139
+ displayName: z3.string(),
1140
+ publicAlias: z3.string().min(1),
1141
+ emailAddress: z3.string(),
1142
+ coreRevision: z3.number(),
1143
+ timeStamp: z3.string(),
1144
+ id: z3.string(),
1145
+ revision: z3.number()
1146
+ });
1147
+ const accountsZ = z3.object({
1148
+ count: z3.number(),
1149
+ value: z3.array(
1150
+ z3.object({
1151
+ accountId: z3.string(),
1152
+ accountUri: z3.string(),
1153
+ accountName: z3.string()
1154
+ })
1155
+ )
1156
+ });
1157
+ const profileRes = await fetch(
1158
+ "https://app.vssps.visualstudio.com/_apis/profile/profiles/me?api-version=6.0",
1159
+ {
1160
+ method: "GET",
1161
+ headers: {
1162
+ Authorization: `Bearer ${oauthToken}`
1120
1163
  }
1121
- `;
1122
- function getOktoKit(options) {
1123
- const token = options?.githubAuthToken ?? GITHUB_API_TOKEN ?? "";
1124
- return new Octokit({ auth: token });
1164
+ }
1165
+ );
1166
+ const profileJson = await profileRes.json();
1167
+ const profile = profileZ.parse(profileJson);
1168
+ const accountsRes = await fetch(
1169
+ `https://app.vssps.visualstudio.com/_apis/accounts?memberId=${profile.publicAlias}&api-version=6.0`,
1170
+ {
1171
+ method: "GET",
1172
+ headers: {
1173
+ Authorization: `Bearer ${oauthToken}`
1174
+ }
1175
+ }
1176
+ );
1177
+ const accountsJson = await accountsRes.json();
1178
+ const accounts = accountsZ.parse(accountsJson);
1179
+ const orgs = accounts.value.map((account) => account.accountName).filter((value, index, array) => array.indexOf(value) === index);
1180
+ return orgs;
1125
1181
  }
1126
- async function githubValidateParams(url, accessToken) {
1182
+ function _getPublicAdoClient({ orgName }) {
1183
+ const orgUrl = `https://dev.azure.com/${orgName}`;
1184
+ const authHandler = api.getPersonalAccessTokenHandler("");
1185
+ authHandler.canHandleAuthentication = () => false;
1186
+ authHandler.prepareRequest = (_options) => {
1187
+ return;
1188
+ };
1189
+ const connection = new api.WebApi(orgUrl, authHandler);
1190
+ return connection;
1191
+ }
1192
+ function getAdoTokenType(token) {
1193
+ if (token.includes(".")) {
1194
+ return "OAUTH" /* OAUTH */;
1195
+ }
1196
+ return "PAT" /* PAT */;
1197
+ }
1198
+ async function getAdoApiClient({
1199
+ accessToken,
1200
+ tokenOrg,
1201
+ orgName
1202
+ }) {
1203
+ if (!accessToken || tokenOrg && tokenOrg !== orgName) {
1204
+ return _getPublicAdoClient({ orgName });
1205
+ }
1206
+ const orgUrl = `https://dev.azure.com/${orgName}`;
1207
+ if (getAdoTokenType(accessToken) === "OAUTH" /* OAUTH */) {
1208
+ const connection2 = new api.WebApi(orgUrl, api.getBearerHandler(accessToken));
1209
+ return connection2;
1210
+ }
1211
+ const authHandler = api.getPersonalAccessTokenHandler(accessToken);
1212
+ const connection = new api.WebApi(orgUrl, authHandler);
1213
+ return connection;
1214
+ }
1215
+ async function adoValidateParams({
1216
+ url,
1217
+ accessToken,
1218
+ tokenOrg
1219
+ }) {
1127
1220
  try {
1128
- const oktoKit = getOktoKit({ githubAuthToken: accessToken });
1129
- if (accessToken) {
1130
- await oktoKit.rest.users.getAuthenticated();
1221
+ if (!url && accessToken && getAdoTokenType(accessToken) === "OAUTH" /* OAUTH */) {
1222
+ await _getOrgsForOauthToken({ oauthToken: accessToken });
1223
+ return;
1131
1224
  }
1225
+ let org = tokenOrg;
1132
1226
  if (url) {
1133
- const { owner, repo } = parseGithubOwnerAndRepo(url);
1134
- await oktoKit.rest.repos.get({ repo, owner });
1227
+ const { owner } = parseAdoOwnerAndRepo(url);
1228
+ org = owner;
1135
1229
  }
1230
+ if (!org) {
1231
+ throw new InvalidRepoUrlError(`invalid ADO ORG ${org}`);
1232
+ }
1233
+ const api2 = await getAdoApiClient({
1234
+ accessToken,
1235
+ tokenOrg,
1236
+ orgName: org
1237
+ });
1238
+ await api2.connect();
1136
1239
  } catch (e) {
1137
1240
  const error = e;
1138
- const code = error.status || error.statusCode || error.response?.status || error.response?.statusCode || error.response?.code;
1139
- if (code === 401 || code === 403) {
1140
- throw new InvalidAccessTokenError(`invalid github access token`);
1241
+ const code = error.code || error.status || error.statusCode || error.response?.status || error.response?.statusCode || error.response?.code;
1242
+ const description = error.description || `${e}`;
1243
+ if (code === 401 || code === 403 || description.includes("401") || description.includes("403")) {
1244
+ throw new InvalidAccessTokenError(`invalid ADO access token`);
1141
1245
  }
1142
- if (code === 404) {
1143
- throw new InvalidRepoUrlError(`invalid github repo Url ${url}`);
1246
+ if (code === 404 || description.includes("404") || description.includes("Not Found")) {
1247
+ throw new InvalidRepoUrlError(`invalid ADO repo URL ${url}`);
1144
1248
  }
1145
1249
  throw e;
1146
1250
  }
1147
1251
  }
1148
- async function getGithubUsername(accessToken) {
1149
- const oktoKit = getOktoKit({ githubAuthToken: accessToken });
1150
- const res = await oktoKit.rest.users.getAuthenticated();
1151
- return res.data.login;
1152
- }
1153
- async function getGithubIsUserCollaborator(username, accessToken, repoUrl) {
1252
+ async function getAdoIsUserCollaborator({
1253
+ accessToken,
1254
+ tokenOrg,
1255
+ repoUrl
1256
+ }) {
1154
1257
  try {
1155
- const { owner, repo } = parseGithubOwnerAndRepo(repoUrl);
1156
- const oktoKit = getOktoKit({ githubAuthToken: accessToken });
1157
- const res = await oktoKit.rest.repos.checkCollaborator({
1158
- owner,
1159
- repo,
1160
- username
1258
+ const { owner, repo, projectName } = parseAdoOwnerAndRepo(repoUrl);
1259
+ const api2 = await getAdoApiClient({
1260
+ accessToken,
1261
+ tokenOrg,
1262
+ orgName: owner
1161
1263
  });
1162
- if (res.status === 204) {
1163
- return true;
1264
+ const git = await api2.getGitApi();
1265
+ const branches = await git.getBranches(repo, projectName);
1266
+ if (!branches || branches.length === 0) {
1267
+ throw new InvalidRepoUrlError("no branches");
1164
1268
  }
1269
+ return true;
1165
1270
  } catch (e) {
1166
1271
  return false;
1167
1272
  }
1168
- return false;
1169
1273
  }
1170
- async function getGithubPullRequestStatus(accessToken, repoUrl, prNumber) {
1171
- const { owner, repo } = parseGithubOwnerAndRepo(repoUrl);
1172
- const oktoKit = getOktoKit({ githubAuthToken: accessToken });
1173
- const res = await oktoKit.rest.pulls.get({
1174
- owner,
1175
- repo,
1176
- pull_number: prNumber
1274
+ var adoStatusNumberToEnumMap = {
1275
+ 1: "active" /* active */,
1276
+ 2: "abandoned" /* abandoned */,
1277
+ 3: "completed" /* completed */,
1278
+ 4: "all" /* all */
1279
+ };
1280
+ async function getAdoPullRequestStatus({
1281
+ accessToken,
1282
+ tokenOrg,
1283
+ repoUrl,
1284
+ prNumber
1285
+ }) {
1286
+ const { owner, repo, projectName } = parseAdoOwnerAndRepo(repoUrl);
1287
+ const api2 = await getAdoApiClient({
1288
+ accessToken,
1289
+ tokenOrg,
1290
+ orgName: owner
1177
1291
  });
1178
- if (res.data.merged) {
1179
- return "merged";
1180
- }
1181
- if (res.data.draft) {
1182
- return "draft";
1292
+ const git = await api2.getGitApi();
1293
+ const res = await git.getPullRequest(repo, prNumber, projectName);
1294
+ if (!res.status || res.status < 1 || res.status > 3) {
1295
+ throw new Error("bad pr status for ADO");
1183
1296
  }
1184
- return res.data.state;
1297
+ return adoStatusNumberToEnumMap[res.status];
1185
1298
  }
1186
- async function getGithubIsRemoteBranch(accessToken, repoUrl, branch) {
1187
- const { owner, repo } = parseGithubOwnerAndRepo(repoUrl);
1188
- const oktoKit = getOktoKit({ githubAuthToken: accessToken });
1299
+ async function getAdoIsRemoteBranch({
1300
+ accessToken,
1301
+ tokenOrg,
1302
+ repoUrl,
1303
+ branch
1304
+ }) {
1305
+ const { owner, repo, projectName } = parseAdoOwnerAndRepo(repoUrl);
1306
+ const api2 = await getAdoApiClient({
1307
+ accessToken,
1308
+ tokenOrg,
1309
+ orgName: owner
1310
+ });
1311
+ const git = await api2.getGitApi();
1189
1312
  try {
1190
- const res = await oktoKit.rest.repos.getBranch({
1191
- owner,
1192
- repo,
1193
- branch
1194
- });
1195
- return branch === res.data.name;
1313
+ const branchStatus = await git.getBranch(repo, branch, projectName);
1314
+ if (!branchStatus || !branchStatus.commit) {
1315
+ throw new InvalidRepoUrlError("no branch status");
1316
+ }
1317
+ return branchStatus.name === branch;
1196
1318
  } catch (e) {
1197
1319
  return false;
1198
1320
  }
1199
1321
  }
1200
- async function getGithubRepoList(accessToken) {
1201
- const oktoKit = getOktoKit({ githubAuthToken: accessToken });
1202
- try {
1203
- const githubRepos = await getRepos(oktoKit);
1204
- return githubRepos.map(
1205
- (repo) => {
1206
- const repoLanguages = [];
1207
- if (repo.language) {
1208
- repoLanguages.push(repo.language);
1322
+ async function getAdoRepoList({
1323
+ orgName,
1324
+ tokenOrg,
1325
+ accessToken
1326
+ }) {
1327
+ let orgs = [];
1328
+ if (getAdoTokenType(accessToken) === "OAUTH" /* OAUTH */) {
1329
+ orgs = await _getOrgsForOauthToken({ oauthToken: accessToken });
1330
+ }
1331
+ if (orgs.length === 0 && !orgName) {
1332
+ throw new Error(`no orgs for ADO`);
1333
+ } else if (orgs.length === 0 && orgName) {
1334
+ orgs = [orgName];
1335
+ }
1336
+ const repos = (await Promise.allSettled(
1337
+ orgs.map(async (org) => {
1338
+ const orgApi = await getAdoApiClient({
1339
+ accessToken,
1340
+ tokenOrg,
1341
+ orgName: org
1342
+ });
1343
+ const gitOrg = await orgApi.getGitApi();
1344
+ const orgRepos = await gitOrg.getRepositories();
1345
+ const repoInfoList = (await Promise.allSettled(
1346
+ orgRepos.map(async (repo) => {
1347
+ if (!repo.name || !repo.remoteUrl || !repo.defaultBranch) {
1348
+ throw new InvalidRepoUrlError("bad repo");
1349
+ }
1350
+ const branch = await gitOrg.getBranch(
1351
+ repo.name,
1352
+ repo.defaultBranch.replace(/^refs\/heads\//, ""),
1353
+ repo.project?.name
1354
+ );
1355
+ return {
1356
+ repoName: repo.name,
1357
+ repoUrl: repo.remoteUrl.replace(
1358
+ /^[hH][tT][tT][pP][sS]:\/\/[^/]+@/,
1359
+ "https://"
1360
+ ),
1361
+ repoOwner: org,
1362
+ repoIsPublic: repo.project?.visibility === 2,
1363
+ //2 is public in the ADO API
1364
+ repoLanguages: [],
1365
+ repoUpdatedAt: branch.commit?.committer?.date?.toDateString() || repo.project?.lastUpdateTime?.toDateString() || (/* @__PURE__ */ new Date()).toDateString()
1366
+ };
1367
+ })
1368
+ )).reduce((acc, res) => {
1369
+ if (res.status === "fulfilled") {
1370
+ acc.push(res.value);
1209
1371
  }
1210
- return {
1211
- repoName: repo.name,
1212
- repoUrl: repo.html_url,
1213
- repoOwner: repo.owner.login,
1214
- repoLanguages,
1215
- repoIsPublic: !repo.private,
1216
- repoUpdatedAt: repo.updated_at
1217
- };
1218
- }
1219
- );
1220
- } catch (e) {
1221
- if (e instanceof RequestError && e.status === 401) {
1222
- return [];
1223
- }
1224
- if (e instanceof RequestError && e.status === 404) {
1225
- return [];
1372
+ return acc;
1373
+ }, []);
1374
+ return repoInfoList;
1375
+ })
1376
+ )).reduce((acc, res) => {
1377
+ if (res.status === "fulfilled") {
1378
+ return acc.concat(res.value);
1226
1379
  }
1227
- throw e;
1228
- }
1229
- }
1230
- async function getGithubBranchList(accessToken, repoUrl) {
1231
- const { owner, repo } = parseGithubOwnerAndRepo(repoUrl);
1232
- const oktoKit = getOktoKit({ githubAuthToken: accessToken });
1233
- const res = await oktoKit.rest.repos.listBranches({
1234
- owner,
1235
- repo,
1236
- per_page: 1e3,
1237
- page: 1
1238
- });
1239
- return res.data.map((branch) => branch.name);
1380
+ return acc;
1381
+ }, []);
1382
+ return repos;
1240
1383
  }
1241
- async function createPullRequest(options) {
1242
- const { owner, repo } = parseGithubOwnerAndRepo(options.repoUrl);
1243
- const oktoKit = getOktoKit({ githubAuthToken: options.accessToken });
1244
- const res = await oktoKit.rest.pulls.create({
1245
- owner,
1246
- repo,
1247
- title: options.title,
1248
- body: options.body,
1249
- head: options.sourceBranchName,
1250
- base: options.targetBranchName,
1251
- draft: false,
1252
- maintainer_can_modify: true
1253
- });
1254
- return res.data.number;
1384
+ function getAdoPrUrl({
1385
+ url,
1386
+ prNumber
1387
+ }) {
1388
+ return `${url}/pullrequest/${prNumber}`;
1255
1389
  }
1256
- async function forkRepo(options) {
1257
- const { owner, repo } = parseGithubOwnerAndRepo(options.repoUrl);
1258
- const oktoKit = getOktoKit({ githubAuthToken: options.accessToken });
1259
- const res = await oktoKit.rest.repos.createFork({
1260
- owner,
1261
- repo,
1262
- default_branch_only: false
1263
- });
1264
- return { url: res.data.html_url ? String(res.data.html_url) : null };
1390
+ function getAdoDownloadUrl({
1391
+ repoUrl,
1392
+ branch
1393
+ }) {
1394
+ const { owner, repo, projectName } = parseAdoOwnerAndRepo(repoUrl);
1395
+ const url = new URL(repoUrl);
1396
+ const origin = url.origin.toLowerCase().endsWith(".visualstudio.com") ? "https://dev.azure.com" : url.origin.toLowerCase();
1397
+ return `${origin}/${owner}/${projectName}/_apis/git/repositories/${repo}/items/items?path=/&versionDescriptor[versionOptions]=0&versionDescriptor[versionType]=commit&versionDescriptor[version]=${branch}&resolveLfs=true&$format=zip&api-version=5.0&download=true`;
1265
1398
  }
1266
- async function getRepos(oktoKit) {
1267
- const res = await oktoKit.request("GET /user/repos?sort=updated", {
1268
- headers: {
1269
- "X-GitHub-Api-Version": "2022-11-28",
1270
- per_page: 100
1271
- }
1399
+ async function getAdoBranchList({
1400
+ accessToken,
1401
+ tokenOrg,
1402
+ repoUrl
1403
+ }) {
1404
+ const { owner, repo, projectName } = parseAdoOwnerAndRepo(repoUrl);
1405
+ const api2 = await getAdoApiClient({
1406
+ accessToken,
1407
+ tokenOrg,
1408
+ orgName: owner
1272
1409
  });
1273
- return res.data;
1274
- }
1275
- async function getGithubRepoDefaultBranch(repoUrl, options) {
1276
- const oktoKit = getOktoKit(options);
1277
- const { owner, repo } = parseGithubOwnerAndRepo(repoUrl);
1278
- return (await oktoKit.rest.repos.get({ repo, owner })).data.default_branch;
1279
- }
1280
- async function getGithubReferenceData({ ref, gitHubUrl }, options) {
1281
- const { owner, repo } = parseGithubOwnerAndRepo(gitHubUrl);
1282
- let res;
1410
+ const git = await api2.getGitApi();
1283
1411
  try {
1284
- const oktoKit = getOktoKit(options);
1285
- res = await Promise.any([
1286
- getBranch({ owner, repo, branch: ref }, oktoKit).then((result) => ({
1287
- date: result.data.commit.commit.committer?.date ? new Date(result.data.commit.commit.committer?.date) : void 0,
1288
- type: "BRANCH" /* BRANCH */,
1289
- sha: result.data.commit.sha
1290
- })),
1291
- getCommit({ commitSha: ref, repo, owner }, oktoKit).then((commit) => ({
1292
- date: new Date(commit.data.committer.date),
1293
- type: "COMMIT" /* COMMIT */,
1294
- sha: commit.data.sha
1295
- })),
1296
- getTagDate({ owner, repo, tag: ref }, oktoKit).then((data) => ({
1297
- date: new Date(data.date),
1298
- type: "TAG" /* TAG */,
1299
- sha: data.sha
1300
- }))
1301
- ]);
1302
- return res;
1412
+ const res = await git.getBranches(repo, projectName);
1413
+ res.sort((a, b) => {
1414
+ if (!a.commit?.committer?.date || !b.commit?.committer?.date) {
1415
+ return 0;
1416
+ }
1417
+ return b.commit?.committer?.date.getTime() - a.commit?.committer?.date.getTime();
1418
+ });
1419
+ return res.reduce((acc, branch) => {
1420
+ if (!branch.name) {
1421
+ return acc;
1422
+ }
1423
+ acc.push(branch.name);
1424
+ return acc;
1425
+ }, []);
1303
1426
  } catch (e) {
1304
- if (e instanceof AggregateError) {
1305
- throw new RefNotFoundError(`ref: ${ref} does not exist`);
1306
- }
1307
- throw e;
1427
+ return [];
1308
1428
  }
1309
1429
  }
1310
- async function getBranch({ branch, owner, repo }, oktoKit) {
1311
- return oktoKit.rest.repos.getBranch({
1312
- branch,
1313
- owner,
1314
- repo
1430
+ async function createAdoPullRequest(options) {
1431
+ const { owner, repo, projectName } = parseAdoOwnerAndRepo(options.repoUrl);
1432
+ const api2 = await getAdoApiClient({
1433
+ accessToken: options.accessToken,
1434
+ tokenOrg: options.tokenOrg,
1435
+ orgName: owner
1315
1436
  });
1437
+ const git = await api2.getGitApi();
1438
+ const res = await git.createPullRequest(
1439
+ {
1440
+ sourceRefName: `refs/heads/${options.sourceBranchName}`,
1441
+ targetRefName: `refs/heads/${options.targetBranchName}`,
1442
+ title: options.title,
1443
+ description: options.body
1444
+ },
1445
+ repo,
1446
+ projectName
1447
+ );
1448
+ return res.pullRequestId;
1316
1449
  }
1317
- async function getTagDate({ tag, owner, repo }, oktoKit) {
1318
- const refResponse = await oktoKit.rest.git.getRef({
1319
- ref: `tags/${tag}`,
1320
- owner,
1321
- repo
1322
- });
1323
- const tagSha = refResponse.data.object.sha;
1324
- if (refResponse.data.object.type === "commit") {
1325
- const res2 = await oktoKit.rest.git.getCommit({
1326
- commit_sha: tagSha,
1327
- owner,
1450
+ async function getAdoRepoDefaultBranch({
1451
+ repoUrl,
1452
+ tokenOrg,
1453
+ accessToken
1454
+ }) {
1455
+ const { owner, repo, projectName } = parseAdoOwnerAndRepo(repoUrl);
1456
+ const api2 = await getAdoApiClient({
1457
+ accessToken,
1458
+ tokenOrg,
1459
+ orgName: owner
1460
+ });
1461
+ const git = await api2.getGitApi();
1462
+ const branches = await git.getBranches(repo, projectName);
1463
+ if (!branches || branches.length === 0) {
1464
+ throw new InvalidRepoUrlError("no branches");
1465
+ }
1466
+ const res = branches.find((branch) => branch.isBaseVersion);
1467
+ if (!res || !res.name) {
1468
+ throw new InvalidRepoUrlError("no default branch");
1469
+ }
1470
+ return res.name;
1471
+ }
1472
+ async function getAdoReferenceData({
1473
+ ref,
1474
+ repoUrl,
1475
+ accessToken,
1476
+ tokenOrg
1477
+ }) {
1478
+ const { owner, repo, projectName } = parseAdoOwnerAndRepo(repoUrl);
1479
+ const api2 = await getAdoApiClient({
1480
+ accessToken,
1481
+ tokenOrg,
1482
+ orgName: owner
1483
+ });
1484
+ if (!projectName) {
1485
+ throw new InvalidUrlPatternError("no project name");
1486
+ }
1487
+ const git = await api2.getGitApi();
1488
+ const results = await Promise.allSettled([
1489
+ (async () => {
1490
+ const res = await git.getBranch(repo, ref, projectName);
1491
+ if (!res.commit || !res.commit.commitId) {
1492
+ throw new InvalidRepoUrlError("no commit on branch");
1493
+ }
1494
+ return {
1495
+ sha: res.commit.commitId,
1496
+ type: "BRANCH" /* BRANCH */,
1497
+ date: res.commit.committer?.date || /* @__PURE__ */ new Date()
1498
+ };
1499
+ })(),
1500
+ (async () => {
1501
+ const res = await git.getCommits(
1502
+ repo,
1503
+ {
1504
+ fromCommitId: ref,
1505
+ toCommitId: ref,
1506
+ $top: 1
1507
+ },
1508
+ projectName
1509
+ );
1510
+ const commit = res[0];
1511
+ if (!commit || !commit.commitId) {
1512
+ throw new Error("no commit");
1513
+ }
1514
+ return {
1515
+ sha: commit.commitId,
1516
+ type: "COMMIT" /* COMMIT */,
1517
+ date: commit.committer?.date || /* @__PURE__ */ new Date()
1518
+ };
1519
+ })(),
1520
+ (async () => {
1521
+ const res = await git.getRefs(repo, projectName, `tags/${ref}`);
1522
+ if (!res[0] || !res[0].objectId) {
1523
+ throw new Error("no tag ref");
1524
+ }
1525
+ let objectId = res[0].objectId;
1526
+ try {
1527
+ const tag = await git.getAnnotatedTag(projectName, repo, objectId);
1528
+ if (tag.taggedObject?.objectId) {
1529
+ objectId = tag.taggedObject.objectId;
1530
+ }
1531
+ } catch (e) {
1532
+ }
1533
+ const commitRes2 = await git.getCommits(
1534
+ repo,
1535
+ {
1536
+ fromCommitId: objectId,
1537
+ toCommitId: objectId,
1538
+ $top: 1
1539
+ },
1540
+ projectName
1541
+ );
1542
+ const commit = commitRes2[0];
1543
+ if (!commit) {
1544
+ throw new Error("no commit");
1545
+ }
1546
+ return {
1547
+ sha: objectId,
1548
+ type: "TAG" /* TAG */,
1549
+ date: commit.committer?.date || /* @__PURE__ */ new Date()
1550
+ };
1551
+ })()
1552
+ ]);
1553
+ const [branchRes, commitRes, tagRes] = results;
1554
+ if (tagRes.status === "fulfilled") {
1555
+ return tagRes.value;
1556
+ }
1557
+ if (branchRes.status === "fulfilled") {
1558
+ return branchRes.value;
1559
+ }
1560
+ if (commitRes.status === "fulfilled") {
1561
+ return commitRes.value;
1562
+ }
1563
+ throw new RefNotFoundError(`ref: ${ref} does not exist`);
1564
+ }
1565
+ function parseAdoOwnerAndRepo(adoUrl) {
1566
+ adoUrl = removeTrailingSlash(adoUrl);
1567
+ const parsingResult = parseScmURL(adoUrl, "Ado" /* Ado */);
1568
+ if (!parsingResult || parsingResult.hostname !== "dev.azure.com" && !parsingResult.hostname.endsWith(".visualstudio.com")) {
1569
+ throw new InvalidUrlPatternError(`invalid ADO repo URL: ${adoUrl}`);
1570
+ }
1571
+ const { organization, repoName, projectName, projectPath, pathElements } = parsingResult;
1572
+ return {
1573
+ owner: organization,
1574
+ repo: repoName,
1575
+ projectName,
1576
+ projectPath,
1577
+ pathElements
1578
+ };
1579
+ }
1580
+ async function getAdoBlameRanges() {
1581
+ return [];
1582
+ }
1583
+ var ADO_ACCESS_TOKEN_URL = "https://app.vssps.visualstudio.com/oauth2/token";
1584
+ var AdoAuthResultZ = z3.object({
1585
+ access_token: z3.string().min(1),
1586
+ token_type: z3.string().min(1),
1587
+ refresh_token: z3.string().min(1)
1588
+ });
1589
+ async function getAdoToken({
1590
+ token,
1591
+ adoClientSecret,
1592
+ tokenType,
1593
+ redirectUri
1594
+ }) {
1595
+ const res = await fetch(ADO_ACCESS_TOKEN_URL, {
1596
+ method: "POST",
1597
+ headers: {
1598
+ Accept: "application/json",
1599
+ "Content-Type": "application/x-www-form-urlencoded"
1600
+ },
1601
+ body: querystring.stringify({
1602
+ client_assertion_type: "urn:ietf:params:oauth:client-assertion-type:jwt-bearer",
1603
+ client_assertion: adoClientSecret,
1604
+ redirect_uri: redirectUri,
1605
+ assertion: token,
1606
+ grant_type: tokenType === "code" /* CODE */ ? "urn:ietf:params:oauth:grant-type:jwt-bearer" : "refresh_token"
1607
+ })
1608
+ });
1609
+ const authResult = await res.json();
1610
+ return AdoAuthResultZ.parse(authResult);
1611
+ }
1612
+ var AdoSdk = {
1613
+ getAdoApiClient,
1614
+ adoValidateParams,
1615
+ getAdoIsUserCollaborator,
1616
+ getAdoPullRequestStatus,
1617
+ getAdoIsRemoteBranch,
1618
+ getAdoRepoList,
1619
+ getAdoDownloadUrl,
1620
+ getAdoBranchList,
1621
+ createAdoPullRequest,
1622
+ getAdoRepoDefaultBranch,
1623
+ getAdoReferenceData,
1624
+ parseAdoOwnerAndRepo,
1625
+ getAdoBlameRanges,
1626
+ getAdoToken,
1627
+ getAdoTokenType
1628
+ };
1629
+
1630
+ // src/features/analysis/scm/bitbucket/bitbucket.ts
1631
+ import querystring3 from "node:querystring";
1632
+ import * as bitbucketPkg from "bitbucket";
1633
+ import { z as z10 } from "zod";
1634
+
1635
+ // src/features/analysis/scm/scm.ts
1636
+ import { Octokit as Octokit2 } from "@octokit/core";
1637
+ import { z as z9 } from "zod";
1638
+
1639
+ // src/features/analysis/scm/github/encryptSecret.ts
1640
+ import sodium from "libsodium-wrappers";
1641
+ async function encryptSecret(secret, key) {
1642
+ await sodium.ready;
1643
+ const binkey = sodium.from_base64(key, sodium.base64_variants.ORIGINAL);
1644
+ const binsec = sodium.from_string(secret);
1645
+ const encBytes = sodium.crypto_box_seal(binsec, binkey);
1646
+ return sodium.to_base64(encBytes, sodium.base64_variants.ORIGINAL);
1647
+ }
1648
+
1649
+ // src/features/analysis/scm/github/github.ts
1650
+ import { RequestError } from "@octokit/request-error";
1651
+ import { Octokit } from "octokit";
1652
+ import { z as z4 } from "zod";
1653
+
1654
+ // src/features/analysis/scm/utils/get_issue_type.ts
1655
+ var getIssueType = (issueType) => {
1656
+ switch (issueType) {
1657
+ case "SQL_Injection" /* SqlInjection */:
1658
+ return "SQL Injection";
1659
+ case "CMDi_relative_path_command" /* CmDiRelativePathCommand */:
1660
+ return "Relative Path Command Injection";
1661
+ case "CMDi" /* CmDi */:
1662
+ return "Command Injection";
1663
+ case "XXE" /* Xxe */:
1664
+ return "XXE";
1665
+ case "XSS" /* Xss */:
1666
+ return "XSS";
1667
+ case "PT" /* Pt */:
1668
+ return "Path Traversal";
1669
+ case "ZIP_SLIP" /* ZipSlip */:
1670
+ return "Zip Slip";
1671
+ case "INSECURE_RANDOMNESS" /* InsecureRandomness */:
1672
+ return "Insecure Randomness";
1673
+ case "SSRF" /* Ssrf */:
1674
+ return "Server Side Request Forgery";
1675
+ case "TYPE_CONFUSION" /* TypeConfusion */:
1676
+ return "Type Confusion";
1677
+ case "REGEX_INJECTION" /* RegexInjection */:
1678
+ return "Regular Expression Injection";
1679
+ case "INCOMPLETE_URL_SANITIZATION" /* IncompleteUrlSanitization */:
1680
+ return "Incomplete URL Sanitization";
1681
+ case "LOG_FORGING" /* LogForging */:
1682
+ return "Log Forging";
1683
+ case "LOCALE_DEPENDENT_COMPARISON" /* LocaleDependentComparison */:
1684
+ return "Locale Dependent Comparison";
1685
+ case "MISSING_CHECK_AGAINST_NULL" /* MissingCheckAgainstNull */:
1686
+ return "Missing Check against Null";
1687
+ case "PASSWORD_IN_COMMENT" /* PasswordInComment */:
1688
+ return "Password in Comment";
1689
+ case "OVERLY_BROAD_CATCH" /* OverlyBroadCatch */:
1690
+ return "Poor Error Handling: Overly Broad Catch";
1691
+ case "USE_OF_SYSTEM_OUTPUT_STREAM" /* UseOfSystemOutputStream */:
1692
+ return "Use of System.out/System.err";
1693
+ case "DANGEROUS_FUNCTION_OVERFLOW" /* DangerousFunctionOverflow */:
1694
+ return "Use of dangerous function";
1695
+ case "DOS_STRING_BUILDER" /* DosStringBuilder */:
1696
+ return "Denial of Service: StringBuilder";
1697
+ case "OPEN_REDIRECT" /* OpenRedirect */:
1698
+ return "Open Redirect";
1699
+ case "WEAK_XML_SCHEMA_UNBOUNDED_OCCURRENCES" /* WeakXmlSchemaUnboundedOccurrences */:
1700
+ return "Weak XML Schema: Unbounded Occurrences";
1701
+ case "SYSTEM_INFORMATION_LEAK" /* SystemInformationLeak */:
1702
+ return "System Information Leak";
1703
+ case "HTTP_RESPONSE_SPLITTING" /* HttpResponseSplitting */:
1704
+ return "HTTP response splitting";
1705
+ case "HTTP_ONLY_COOKIE" /* HttpOnlyCookie */:
1706
+ return "Cookie is not HttpOnly";
1707
+ case "INSECURE_COOKIE" /* InsecureCookie */:
1708
+ return "Insecure Cookie";
1709
+ case "TRUST_BOUNDARY_VIOLATION" /* TrustBoundaryViolation */:
1710
+ return "Trust Boundary Violation";
1711
+ case "MISSING_EQUALS_OR_HASHCODE" /* MissingEqualsOrHashcode */:
1712
+ return "Missing equals or hashcode method";
1713
+ default: {
1714
+ return issueType ? issueType.replaceAll("_", " ") : "Other";
1715
+ }
1716
+ }
1717
+ };
1718
+
1719
+ // src/features/analysis/scm/utils/index.ts
1720
+ function getFixUrlWithRedirect(params) {
1721
+ const {
1722
+ fixId,
1723
+ projectId,
1724
+ organizationId,
1725
+ analysisId,
1726
+ redirectUrl,
1727
+ appBaseUrl,
1728
+ commentId
1729
+ } = params;
1730
+ const searchParams = new URLSearchParams();
1731
+ searchParams.append("commit_redirect_url", redirectUrl);
1732
+ searchParams.append("comment_id", commentId.toString());
1733
+ return `${getFixUrl({
1734
+ appBaseUrl,
1735
+ fixId,
1736
+ projectId,
1737
+ organizationId,
1738
+ analysisId
1739
+ })}?${searchParams.toString()}`;
1740
+ }
1741
+ function getFixUrl({
1742
+ appBaseUrl,
1743
+ fixId,
1744
+ projectId,
1745
+ organizationId,
1746
+ analysisId
1747
+ }) {
1748
+ return `${appBaseUrl}/organization/${organizationId}/project/${projectId}/report/${analysisId}/fix/${fixId}`;
1749
+ }
1750
+ function getCommitUrl(params) {
1751
+ const {
1752
+ fixId,
1753
+ projectId,
1754
+ organizationId,
1755
+ analysisId,
1756
+ redirectUrl,
1757
+ appBaseUrl,
1758
+ commentId
1759
+ } = params;
1760
+ const searchParams = new URLSearchParams();
1761
+ searchParams.append("redirect_url", redirectUrl);
1762
+ searchParams.append("comment_id", commentId.toString());
1763
+ return `${getFixUrl({
1764
+ appBaseUrl,
1765
+ fixId,
1766
+ projectId,
1767
+ organizationId,
1768
+ analysisId
1769
+ })}/commit?${searchParams.toString()}`;
1770
+ }
1771
+ function removeTrailingSlash2(str) {
1772
+ return str.trim().replace(/\/+$/, "");
1773
+ }
1774
+
1775
+ // src/features/analysis/scm/github/github.ts
1776
+ var EnvVariablesZod = z4.object({
1777
+ GITHUB_API_TOKEN: z4.string().optional()
1778
+ });
1779
+ var { GITHUB_API_TOKEN } = EnvVariablesZod.parse(process.env);
1780
+ var GetBlameDocument = `
1781
+ query GetBlame(
1782
+ $owner: String!
1783
+ $repo: String!
1784
+ $ref: String!
1785
+ $path: String!
1786
+ ) {
1787
+ repository(name: $repo, owner: $owner) {
1788
+ # branch name
1789
+ object(expression: $ref) {
1790
+ # cast Target to a Commit
1791
+ ... on Commit {
1792
+ # full repo-relative path to blame file
1793
+ blame(path: $path) {
1794
+ ranges {
1795
+ commit {
1796
+ author {
1797
+ user {
1798
+ name
1799
+ login
1800
+ }
1801
+ }
1802
+ authoredDate
1803
+ }
1804
+ startingLine
1805
+ endingLine
1806
+ age
1807
+ }
1808
+ }
1809
+ }
1810
+
1811
+ }
1812
+ }
1813
+ }
1814
+ `;
1815
+ function getOktoKit(options) {
1816
+ const token = options?.githubAuthToken ?? GITHUB_API_TOKEN ?? "";
1817
+ return new Octokit({ auth: token });
1818
+ }
1819
+ async function githubValidateParams(url, accessToken) {
1820
+ try {
1821
+ const oktoKit = getOktoKit({ githubAuthToken: accessToken });
1822
+ if (accessToken) {
1823
+ await oktoKit.rest.users.getAuthenticated();
1824
+ }
1825
+ if (url) {
1826
+ const { owner, repo } = parseGithubOwnerAndRepo(url);
1827
+ await oktoKit.rest.repos.get({ repo, owner });
1828
+ }
1829
+ } catch (e) {
1830
+ const error = e;
1831
+ const code = error.status || error.statusCode || error.response?.status || error.response?.statusCode || error.response?.code;
1832
+ if (code === 401 || code === 403) {
1833
+ throw new InvalidAccessTokenError(`invalid github access token`);
1834
+ }
1835
+ if (code === 404) {
1836
+ throw new InvalidRepoUrlError(`invalid github repo Url ${url}`);
1837
+ }
1838
+ throw e;
1839
+ }
1840
+ }
1841
+ async function getGithubUsername(accessToken) {
1842
+ const oktoKit = getOktoKit({ githubAuthToken: accessToken });
1843
+ const res = await oktoKit.rest.users.getAuthenticated();
1844
+ return res.data.login;
1845
+ }
1846
+ async function getGithubIsUserCollaborator(username, accessToken, repoUrl) {
1847
+ try {
1848
+ const { owner, repo } = parseGithubOwnerAndRepo(repoUrl);
1849
+ const oktoKit = getOktoKit({ githubAuthToken: accessToken });
1850
+ const res = await oktoKit.rest.repos.checkCollaborator({
1851
+ owner,
1852
+ repo,
1853
+ username
1854
+ });
1855
+ if (res.status === 204) {
1856
+ return true;
1857
+ }
1858
+ } catch (e) {
1859
+ return false;
1860
+ }
1861
+ return false;
1862
+ }
1863
+ async function getGithubPullRequestStatus(accessToken, repoUrl, prNumber) {
1864
+ const { owner, repo } = parseGithubOwnerAndRepo(repoUrl);
1865
+ const oktoKit = getOktoKit({ githubAuthToken: accessToken });
1866
+ const res = await oktoKit.rest.pulls.get({
1867
+ owner,
1868
+ repo,
1869
+ pull_number: prNumber
1870
+ });
1871
+ if (res.data.merged) {
1872
+ return "merged";
1873
+ }
1874
+ if (res.data.draft) {
1875
+ return "draft";
1876
+ }
1877
+ return res.data.state;
1878
+ }
1879
+ async function getGithubIsRemoteBranch(accessToken, repoUrl, branch) {
1880
+ const { owner, repo } = parseGithubOwnerAndRepo(repoUrl);
1881
+ const oktoKit = getOktoKit({ githubAuthToken: accessToken });
1882
+ try {
1883
+ const res = await oktoKit.rest.repos.getBranch({
1884
+ owner,
1885
+ repo,
1886
+ branch
1887
+ });
1888
+ return branch === res.data.name;
1889
+ } catch (e) {
1890
+ return false;
1891
+ }
1892
+ }
1893
+ async function getGithubRepoList(accessToken) {
1894
+ const oktoKit = getOktoKit({ githubAuthToken: accessToken });
1895
+ try {
1896
+ const githubRepos = await getRepos(oktoKit);
1897
+ return githubRepos.map(
1898
+ (repo) => {
1899
+ const repoLanguages = [];
1900
+ if (repo.language) {
1901
+ repoLanguages.push(repo.language);
1902
+ }
1903
+ return {
1904
+ repoName: repo.name,
1905
+ repoUrl: repo.html_url,
1906
+ repoOwner: repo.owner.login,
1907
+ repoLanguages,
1908
+ repoIsPublic: !repo.private,
1909
+ repoUpdatedAt: repo.updated_at
1910
+ };
1911
+ }
1912
+ );
1913
+ } catch (e) {
1914
+ if (e instanceof RequestError && e.status === 401) {
1915
+ return [];
1916
+ }
1917
+ if (e instanceof RequestError && e.status === 404) {
1918
+ return [];
1919
+ }
1920
+ throw e;
1921
+ }
1922
+ }
1923
+ async function getGithubBranchList(accessToken, repoUrl) {
1924
+ const { owner, repo } = parseGithubOwnerAndRepo(repoUrl);
1925
+ const oktoKit = getOktoKit({ githubAuthToken: accessToken });
1926
+ const res = await oktoKit.rest.repos.listBranches({
1927
+ owner,
1928
+ repo,
1929
+ per_page: 1e3,
1930
+ page: 1
1931
+ });
1932
+ return res.data.map((branch) => branch.name);
1933
+ }
1934
+ async function createPullRequest(options) {
1935
+ const { owner, repo } = parseGithubOwnerAndRepo(options.repoUrl);
1936
+ const oktoKit = getOktoKit({ githubAuthToken: options.accessToken });
1937
+ const res = await oktoKit.rest.pulls.create({
1938
+ owner,
1939
+ repo,
1940
+ title: options.title,
1941
+ body: options.body,
1942
+ head: options.sourceBranchName,
1943
+ base: options.targetBranchName,
1944
+ draft: false,
1945
+ maintainer_can_modify: true
1946
+ });
1947
+ return res.data.number;
1948
+ }
1949
+ async function forkRepo(options) {
1950
+ const { owner, repo } = parseGithubOwnerAndRepo(options.repoUrl);
1951
+ const oktoKit = getOktoKit({ githubAuthToken: options.accessToken });
1952
+ const res = await oktoKit.rest.repos.createFork({
1953
+ owner,
1954
+ repo,
1955
+ default_branch_only: false
1956
+ });
1957
+ return { url: res.data.html_url ? String(res.data.html_url) : null };
1958
+ }
1959
+ async function getRepos(oktoKit) {
1960
+ const res = await oktoKit.request("GET /user/repos?sort=updated", {
1961
+ headers: {
1962
+ "X-GitHub-Api-Version": "2022-11-28",
1963
+ per_page: 100
1964
+ }
1965
+ });
1966
+ return res.data;
1967
+ }
1968
+ async function getGithubRepoDefaultBranch(repoUrl, options) {
1969
+ const oktoKit = getOktoKit(options);
1970
+ const { owner, repo } = parseGithubOwnerAndRepo(repoUrl);
1971
+ return (await oktoKit.rest.repos.get({ repo, owner })).data.default_branch;
1972
+ }
1973
+ async function getGithubReferenceData({ ref, gitHubUrl }, options) {
1974
+ const { owner, repo } = parseGithubOwnerAndRepo(gitHubUrl);
1975
+ let res;
1976
+ try {
1977
+ const oktoKit = getOktoKit(options);
1978
+ res = await Promise.any([
1979
+ getBranch({ owner, repo, branch: ref }, oktoKit).then((result) => ({
1980
+ date: result.data.commit.commit.committer?.date ? new Date(result.data.commit.commit.committer?.date) : void 0,
1981
+ type: "BRANCH" /* BRANCH */,
1982
+ sha: result.data.commit.sha
1983
+ })),
1984
+ getCommit({ commitSha: ref, repo, owner }, oktoKit).then((commit) => ({
1985
+ date: new Date(commit.data.committer.date),
1986
+ type: "COMMIT" /* COMMIT */,
1987
+ sha: commit.data.sha
1988
+ })),
1989
+ getTagDate({ owner, repo, tag: ref }, oktoKit).then((data) => ({
1990
+ date: new Date(data.date),
1991
+ type: "TAG" /* TAG */,
1992
+ sha: data.sha
1993
+ }))
1994
+ ]);
1995
+ return res;
1996
+ } catch (e) {
1997
+ if (e instanceof AggregateError) {
1998
+ throw new RefNotFoundError(`ref: ${ref} does not exist`);
1999
+ }
2000
+ throw e;
2001
+ }
2002
+ }
2003
+ async function getBranch({ branch, owner, repo }, oktoKit) {
2004
+ return oktoKit.rest.repos.getBranch({
2005
+ branch,
2006
+ owner,
2007
+ repo
2008
+ });
2009
+ }
2010
+ async function getTagDate({ tag, owner, repo }, oktoKit) {
2011
+ const refResponse = await oktoKit.rest.git.getRef({
2012
+ ref: `tags/${tag}`,
2013
+ owner,
2014
+ repo
2015
+ });
2016
+ const tagSha = refResponse.data.object.sha;
2017
+ if (refResponse.data.object.type === "commit") {
2018
+ const res2 = await oktoKit.rest.git.getCommit({
2019
+ commit_sha: tagSha,
2020
+ owner,
1328
2021
  repo
1329
2022
  });
1330
2023
  return {
@@ -1354,7 +2047,7 @@ async function getCommit({
1354
2047
  });
1355
2048
  }
1356
2049
  function parseGithubOwnerAndRepo(gitHubUrl) {
1357
- gitHubUrl = removeTrailingSlash(gitHubUrl);
2050
+ gitHubUrl = removeTrailingSlash2(gitHubUrl);
1358
2051
  const parsingResult = parseScmURL(gitHubUrl, "GitHub" /* GitHub */);
1359
2052
  if (!parsingResult || parsingResult.hostname !== "github.com") {
1360
2053
  throw new InvalidUrlPatternError(`invalid github repo Url ${gitHubUrl}`);
@@ -1558,30 +2251,30 @@ function deleteGeneralPrComment(client, params) {
1558
2251
  }
1559
2252
 
1560
2253
  // src/features/analysis/scm/gitlab/gitlab.ts
1561
- import querystring from "node:querystring";
2254
+ import querystring2 from "node:querystring";
1562
2255
  import {
1563
2256
  Gitlab
1564
2257
  } from "@gitbeaker/rest";
1565
2258
  import { ProxyAgent } from "undici";
1566
- import { z as z5 } from "zod";
2259
+ import { z as z6 } from "zod";
1567
2260
 
1568
2261
  // src/features/analysis/scm/gitlab/types.ts
1569
- import { z as z4 } from "zod";
1570
- var GitlabAuthResultZ = z4.object({
1571
- access_token: z4.string(),
1572
- token_type: z4.string(),
1573
- refresh_token: z4.string()
2262
+ import { z as z5 } from "zod";
2263
+ var GitlabAuthResultZ = z5.object({
2264
+ access_token: z5.string(),
2265
+ token_type: z5.string(),
2266
+ refresh_token: z5.string()
1574
2267
  });
1575
2268
 
1576
2269
  // src/features/analysis/scm/gitlab/gitlab.ts
1577
- var EnvVariablesZod2 = z5.object({
1578
- GITLAB_API_TOKEN: z5.string().optional(),
1579
- BROKERED_HOSTS: z5.string().toLowerCase().transform(
2270
+ var EnvVariablesZod2 = z6.object({
2271
+ GITLAB_API_TOKEN: z6.string().optional(),
2272
+ BROKERED_HOSTS: z6.string().toLowerCase().transform(
1580
2273
  (x) => x.split(",").map((url) => url.trim(), []).filter(Boolean)
1581
2274
  ).default("")
1582
2275
  });
1583
2276
  var { GITLAB_API_TOKEN, BROKERED_HOSTS } = EnvVariablesZod2.parse(process.env);
1584
- function removeTrailingSlash2(str) {
2277
+ function removeTrailingSlash3(str) {
1585
2278
  return str.trim().replace(/\/+$/, "");
1586
2279
  }
1587
2280
  function getGitBeaker(options) {
@@ -1641,6 +2334,11 @@ async function getGitlabIsUserCollaborator({
1641
2334
  return false;
1642
2335
  }
1643
2336
  }
2337
+ var gitlabMergeRequestStatus = {
2338
+ merged: "merged",
2339
+ opened: "opened",
2340
+ closed: "closed"
2341
+ };
1644
2342
  async function getGitlabMergeRequestStatus({
1645
2343
  accessToken,
1646
2344
  repoUrl,
@@ -1650,9 +2348,9 @@ async function getGitlabMergeRequestStatus({
1650
2348
  const api2 = getGitBeaker({ url: repoUrl, gitlabAuthToken: accessToken });
1651
2349
  const res = await api2.MergeRequests.show(projectPath, mrNumber);
1652
2350
  switch (res.state) {
1653
- case "merged" /* merged */:
1654
- case "opened" /* opened */:
1655
- case "closed" /* closed */:
2351
+ case gitlabMergeRequestStatus.merged:
2352
+ case gitlabMergeRequestStatus.opened:
2353
+ case gitlabMergeRequestStatus.closed:
1656
2354
  return res.state;
1657
2355
  default:
1658
2356
  throw new Error(`unknown merge request state ${res.state}`);
@@ -1805,7 +2503,7 @@ async function getGitlabReferenceData({ ref, gitlabUrl }, options) {
1805
2503
  throw new RefNotFoundError(`ref: ${ref} does not exist`);
1806
2504
  }
1807
2505
  function parseGitlabOwnerAndRepo(gitlabUrl) {
1808
- gitlabUrl = removeTrailingSlash2(gitlabUrl);
2506
+ gitlabUrl = removeTrailingSlash3(gitlabUrl);
1809
2507
  const parsingResult = parseScmURL(gitlabUrl, "GitLab" /* GitLab */);
1810
2508
  if (!parsingResult || !parsingResult.repoName) {
1811
2509
  throw new InvalidUrlPatternError(`invalid gitlab repo Url ${gitlabUrl}`);
@@ -1871,84 +2569,84 @@ import parseDiff from "parse-diff";
1871
2569
  import path3 from "path";
1872
2570
  import { simpleGit as simpleGit2 } from "simple-git";
1873
2571
  import tmp from "tmp";
1874
- import { z as z7 } from "zod";
2572
+ import { z as z8 } from "zod";
1875
2573
 
1876
2574
  // src/features/analysis/scm/scmSubmit/types.ts
1877
- import { z as z6 } from "zod";
1878
- var BaseSubmitToScmMessageZ = z6.object({
1879
- submitFixRequestId: z6.string().uuid(),
1880
- fixes: z6.array(
1881
- z6.object({
1882
- fixId: z6.string().uuid(),
1883
- diff: z6.string()
2575
+ import { z as z7 } from "zod";
2576
+ var BaseSubmitToScmMessageZ = z7.object({
2577
+ submitFixRequestId: z7.string().uuid(),
2578
+ fixes: z7.array(
2579
+ z7.object({
2580
+ fixId: z7.string().uuid(),
2581
+ diff: z7.string()
1884
2582
  })
1885
2583
  ),
1886
- commitHash: z6.string(),
1887
- repoUrl: z6.string()
2584
+ commitHash: z7.string(),
2585
+ repoUrl: z7.string()
1888
2586
  });
1889
2587
  var submitToScmMessageType = {
1890
2588
  commitToSameBranch: "commitToSameBranch",
1891
2589
  submitFixesForDifferentBranch: "submitFixesForDifferentBranch"
1892
2590
  };
1893
2591
  var CommitToSameBranchParamsZ = BaseSubmitToScmMessageZ.merge(
1894
- z6.object({
1895
- type: z6.literal(submitToScmMessageType.commitToSameBranch),
1896
- branch: z6.string(),
1897
- commitMessage: z6.string(),
1898
- commitDescription: z6.string().nullish(),
1899
- githubCommentId: z6.number().nullish()
2592
+ z7.object({
2593
+ type: z7.literal(submitToScmMessageType.commitToSameBranch),
2594
+ branch: z7.string(),
2595
+ commitMessage: z7.string(),
2596
+ commitDescription: z7.string().nullish(),
2597
+ githubCommentId: z7.number().nullish()
1900
2598
  })
1901
2599
  );
1902
- var SubmitFixesToDifferentBranchParamsZ = z6.object({
1903
- type: z6.literal(submitToScmMessageType.submitFixesForDifferentBranch),
1904
- submitBranch: z6.string(),
1905
- baseBranch: z6.string()
2600
+ var SubmitFixesToDifferentBranchParamsZ = z7.object({
2601
+ type: z7.literal(submitToScmMessageType.submitFixesForDifferentBranch),
2602
+ submitBranch: z7.string(),
2603
+ baseBranch: z7.string()
1906
2604
  }).merge(BaseSubmitToScmMessageZ);
1907
- var SubmitFixesMessageZ = z6.union([
2605
+ var SubmitFixesMessageZ = z7.union([
1908
2606
  CommitToSameBranchParamsZ,
1909
2607
  SubmitFixesToDifferentBranchParamsZ
1910
2608
  ]);
1911
- var FixResponseArrayZ = z6.array(
1912
- z6.object({
1913
- fixId: z6.string().uuid()
2609
+ var FixResponseArrayZ = z7.array(
2610
+ z7.object({
2611
+ fixId: z7.string().uuid()
1914
2612
  })
1915
2613
  );
1916
- var SubmitFixesBaseResponseMessageZ = z6.object({
1917
- submitFixRequestId: z6.string().uuid(),
1918
- submitBranches: z6.array(
1919
- z6.object({
1920
- branchName: z6.string(),
2614
+ var SubmitFixesBaseResponseMessageZ = z7.object({
2615
+ submitFixRequestId: z7.string().uuid(),
2616
+ submitBranches: z7.array(
2617
+ z7.object({
2618
+ branchName: z7.string(),
1921
2619
  fixes: FixResponseArrayZ
1922
2620
  })
1923
2621
  ),
1924
- error: z6.object({
1925
- type: z6.enum([
2622
+ error: z7.object({
2623
+ type: z7.enum([
1926
2624
  "InitialRepoAccessError",
1927
2625
  "PushBranchError",
1928
2626
  "UnknownError"
1929
2627
  ]),
1930
- info: z6.object({
1931
- message: z6.string(),
1932
- pushBranchName: z6.string().optional()
2628
+ info: z7.object({
2629
+ message: z7.string(),
2630
+ pushBranchName: z7.string().optional()
1933
2631
  })
1934
2632
  }).optional()
1935
2633
  });
1936
- var SubmitFixesToSameBranchResponseMessageZ = z6.object({
1937
- type: z6.literal(submitToScmMessageType.commitToSameBranch),
1938
- githubCommentId: z6.number().nullish()
2634
+ var SubmitFixesToSameBranchResponseMessageZ = z7.object({
2635
+ type: z7.literal(submitToScmMessageType.commitToSameBranch),
2636
+ githubCommentId: z7.number().nullish()
1939
2637
  }).merge(SubmitFixesBaseResponseMessageZ);
1940
- var SubmitFixesToDifferentBranchResponseMessageZ = z6.object({
1941
- type: z6.literal(submitToScmMessageType.submitFixesForDifferentBranch),
1942
- githubCommentId: z6.number().optional()
2638
+ var SubmitFixesToDifferentBranchResponseMessageZ = z7.object({
2639
+ type: z7.literal(submitToScmMessageType.submitFixesForDifferentBranch),
2640
+ githubCommentId: z7.number().optional()
1943
2641
  }).merge(SubmitFixesBaseResponseMessageZ);
1944
- var SubmitFixesResponseMessageZ = z6.discriminatedUnion("type", [
2642
+ var SubmitFixesResponseMessageZ = z7.discriminatedUnion("type", [
1945
2643
  SubmitFixesToSameBranchResponseMessageZ,
1946
2644
  SubmitFixesToDifferentBranchResponseMessageZ
1947
2645
  ]);
1948
2646
 
1949
2647
  // src/features/analysis/scm/scmSubmit/index.ts
1950
- var EnvVariablesZod3 = z7.object({
1951
- BROKERED_HOSTS: z7.string().toLowerCase().transform(
2648
+ var EnvVariablesZod3 = z8.object({
2649
+ BROKERED_HOSTS: z8.string().toLowerCase().transform(
1952
2650
  (x) => x.split(",").map((url) => url.trim(), []).filter(Boolean)
1953
2651
  ).default("")
1954
2652
  });
@@ -1965,49 +2663,59 @@ var isValidBranchName = async (branchName) => {
1965
2663
  return false;
1966
2664
  }
1967
2665
  };
1968
- var FixesZ = z7.array(z7.object({ fixId: z7.string(), diff: z7.string() })).nonempty();
2666
+ var FixesZ = z8.array(z8.object({ fixId: z8.string(), diff: z8.string() })).nonempty();
1969
2667
 
1970
2668
  // src/features/analysis/scm/scm.ts
2669
+ var GetRefererenceResultZ = z9.object({
2670
+ date: z9.date().optional(),
2671
+ sha: z9.string(),
2672
+ type: z9.nativeEnum(ReferenceType)
2673
+ });
1971
2674
  function getCloudScmLibTypeFromUrl(url) {
1972
2675
  if (!url) {
1973
2676
  return void 0;
1974
2677
  }
1975
2678
  const urlObject = new URL(url);
1976
2679
  const hostname = urlObject.hostname.toLowerCase();
1977
- if (hostname === "gitlab.com") {
2680
+ if (hostname === scmCloudHostname.GitLab) {
1978
2681
  return "GITLAB" /* GITLAB */;
1979
2682
  }
1980
- if (hostname === "github.com") {
2683
+ if (hostname === scmCloudHostname.GitHub) {
1981
2684
  return "GITHUB" /* GITHUB */;
1982
2685
  }
1983
- if (hostname === "dev.azure.com" || hostname.endsWith(".visualstudio.com")) {
2686
+ if (hostname === scmCloudHostname.Ado || hostname.endsWith(".visualstudio.com")) {
1984
2687
  return "ADO" /* ADO */;
1985
2688
  }
2689
+ if (hostname === scmCloudHostname.Bitbucket) {
2690
+ return "BITBUCKET" /* BITBUCKET */;
2691
+ }
1986
2692
  return void 0;
1987
2693
  }
2694
+ var scmCloudHostname = {
2695
+ GitLab: new URL(scmCloudUrl.GitLab).hostname,
2696
+ GitHub: new URL(scmCloudUrl.GitHub).hostname,
2697
+ Ado: new URL(scmCloudUrl.Ado).hostname,
2698
+ Bitbucket: new URL(scmCloudUrl.Bitbucket).hostname
2699
+ };
2700
+ var scmLibScmTypeToScmType = {
2701
+ ["GITLAB" /* GITLAB */]: "GitLab" /* GitLab */,
2702
+ ["GITHUB" /* GITHUB */]: "GitHub" /* GitHub */,
2703
+ ["ADO" /* ADO */]: "Ado" /* Ado */,
2704
+ ["BITBUCKET" /* BITBUCKET */]: "Bitbucket" /* Bitbucket */
2705
+ };
2706
+ var scmTypeToScmLibScmType = {
2707
+ ["GitLab" /* GitLab */]: "GITLAB" /* GITLAB */,
2708
+ ["GitHub" /* GitHub */]: "GITHUB" /* GITHUB */,
2709
+ ["Ado" /* Ado */]: "ADO" /* ADO */,
2710
+ ["Bitbucket" /* Bitbucket */]: "BITBUCKET" /* BITBUCKET */
2711
+ };
1988
2712
  function getScmTypeFromScmLibType(scmLibType) {
1989
- if (scmLibType === "GITLAB" /* GITLAB */) {
1990
- return "GitLab" /* GitLab */;
1991
- }
1992
- if (scmLibType === "GITHUB" /* GITHUB */) {
1993
- return "GitHub" /* GitHub */;
1994
- }
1995
- if (scmLibType === "ADO" /* ADO */) {
1996
- return "Ado" /* Ado */;
1997
- }
1998
- throw new Error(`unknown scm lib type: ${scmLibType}`);
2713
+ const parsedScmLibType = z9.nativeEnum(ScmLibScmType).parse(scmLibType);
2714
+ return scmLibScmTypeToScmType[parsedScmLibType];
1999
2715
  }
2000
2716
  function getScmLibTypeFromScmType(scmType) {
2001
- if (scmType === "GitLab" /* GitLab */) {
2002
- return "GITLAB" /* GITLAB */;
2003
- }
2004
- if (scmType === "GitHub" /* GitHub */) {
2005
- return "GITHUB" /* GITHUB */;
2006
- }
2007
- if (scmType === "Ado" /* Ado */) {
2008
- return "ADO" /* ADO */;
2009
- }
2010
- throw new Error(`unknown scm type: ${scmType}`);
2717
+ const parsedScmType = z9.nativeEnum(ScmType).parse(scmType);
2718
+ return scmTypeToScmLibScmType[parsedScmType];
2011
2719
  }
2012
2720
  function getScmConfig({
2013
2721
  url,
@@ -2103,6 +2811,19 @@ var RepoNoTokenAccessError = class extends Error {
2103
2811
  super(m);
2104
2812
  }
2105
2813
  };
2814
+ function buildAuthrizedRepoUrl(args) {
2815
+ const { url, username, password } = args;
2816
+ const is_http = url.toLowerCase().startsWith("http://");
2817
+ const is_https = url.toLowerCase().startsWith("https://");
2818
+ if (is_http) {
2819
+ return `http://${username}:${password}@${url.toLowerCase().replace("http://", "")}`;
2820
+ } else if (is_https) {
2821
+ return `https://${username}:${password}@${url.toLowerCase().replace("https://", "")}`;
2822
+ } else {
2823
+ console.error(`invalid scm url ${url}`);
2824
+ throw new Error(`invalid scm url ${url}`);
2825
+ }
2826
+ }
2106
2827
  var SCMLib = class {
2107
2828
  constructor(url, accessToken, scmOrg) {
2108
2829
  __publicField(this, "url");
@@ -2118,24 +2839,45 @@ var SCMLib = class {
2118
2839
  throw new Error("no url");
2119
2840
  }
2120
2841
  const trimmedUrl = this.url.trim().replace(/\/$/, "");
2121
- if (!this.accessToken) {
2842
+ const accessToken = this.getAccessToken();
2843
+ if (!accessToken) {
2122
2844
  return trimmedUrl;
2123
2845
  }
2846
+ console.log(
2847
+ "this instanceof BitbucketSCMLib",
2848
+ this instanceof BitbucketSCMLib
2849
+ );
2124
2850
  const scmLibType = this.getScmLibType();
2125
2851
  if (scmLibType === "ADO" /* ADO */) {
2126
- return `https://${this.accessToken}@${trimmedUrl.toLowerCase().replace("https://", "")}`;
2852
+ return `https://${accessToken}@${trimmedUrl.toLowerCase().replace("https://", "")}`;
2127
2853
  }
2128
- const is_http = trimmedUrl.toLowerCase().startsWith("http://");
2129
- const is_https = trimmedUrl.toLowerCase().startsWith("https://");
2130
- const username = await this._getUsernameForAuthUrl();
2131
- if (is_http) {
2132
- return `http://${username}:${this.accessToken}@${trimmedUrl.toLowerCase().replace("http://", "")}`;
2133
- } else if (is_https) {
2134
- return `https://${username}:${this.accessToken}@${trimmedUrl.toLowerCase().replace("https://", "")}`;
2135
- } else {
2136
- console.error(`invalid scm url ${trimmedUrl}`);
2137
- throw new Error(`invalid scm url ${trimmedUrl}`);
2854
+ if (this instanceof BitbucketSCMLib) {
2855
+ const authData = this.getAuthData();
2856
+ switch (authData.authType) {
2857
+ case "public": {
2858
+ return trimmedUrl;
2859
+ }
2860
+ case "token": {
2861
+ const { token } = authData;
2862
+ const username2 = await this._getUsernameForAuthUrl();
2863
+ return buildAuthrizedRepoUrl({
2864
+ url: trimmedUrl,
2865
+ username: username2,
2866
+ password: token
2867
+ });
2868
+ }
2869
+ case "basic": {
2870
+ const { username: username2, password } = authData;
2871
+ return buildAuthrizedRepoUrl({ url: trimmedUrl, username: username2, password });
2872
+ }
2873
+ }
2138
2874
  }
2875
+ const username = await this._getUsernameForAuthUrl();
2876
+ return buildAuthrizedRepoUrl({
2877
+ url: trimmedUrl,
2878
+ username,
2879
+ password: accessToken
2880
+ });
2139
2881
  }
2140
2882
  getAccessToken() {
2141
2883
  return this.accessToken || "";
@@ -2149,6 +2891,12 @@ var SCMLib = class {
2149
2891
  }
2150
2892
  return this.url.split("/").at(-1) || "";
2151
2893
  }
2894
+ _validateToken() {
2895
+ if (!this.accessToken) {
2896
+ console.error("no access token");
2897
+ throw new Error("no access token");
2898
+ }
2899
+ }
2152
2900
  static async getIsValidBranchName(branchName) {
2153
2901
  return isValidBranchName(branchName);
2154
2902
  }
@@ -2163,20 +2911,27 @@ var SCMLib = class {
2163
2911
  trimmedUrl = url.trim().replace(/\/$/, "").replace(/.git$/i, "");
2164
2912
  }
2165
2913
  try {
2166
- if ("GITHUB" /* GITHUB */ === scmType) {
2167
- const scm = new GithubSCMLib(trimmedUrl, accessToken, scmOrg);
2168
- await scm.validateParams();
2169
- return scm;
2170
- }
2171
- if ("GITLAB" /* GITLAB */ === scmType) {
2172
- const scm = new GitlabSCMLib(trimmedUrl, accessToken, scmOrg);
2173
- await scm.validateParams();
2174
- return scm;
2175
- }
2176
- if ("ADO" /* ADO */ === scmType) {
2177
- const scm = new AdoSCMLib(trimmedUrl, accessToken, scmOrg);
2178
- await scm.validateParams();
2179
- return scm;
2914
+ switch (scmType) {
2915
+ case "GITHUB" /* GITHUB */: {
2916
+ const scm = new GithubSCMLib(trimmedUrl, accessToken, scmOrg);
2917
+ await scm.validateParams();
2918
+ return scm;
2919
+ }
2920
+ case "GITLAB" /* GITLAB */: {
2921
+ const scm = new GitlabSCMLib(trimmedUrl, accessToken, scmOrg);
2922
+ await scm.validateParams();
2923
+ return scm;
2924
+ }
2925
+ case "ADO" /* ADO */: {
2926
+ const scm = new AdoSCMLib(trimmedUrl, accessToken, scmOrg);
2927
+ await scm.validateParams();
2928
+ return scm;
2929
+ }
2930
+ case "BITBUCKET" /* BITBUCKET */: {
2931
+ const scm = new BitbucketSCMLib(trimmedUrl, accessToken, scmOrg);
2932
+ await scm.validateParams();
2933
+ return scm;
2934
+ }
2180
2935
  }
2181
2936
  } catch (e) {
2182
2937
  if (e instanceof InvalidRepoUrlError && url) {
@@ -2187,36 +2942,24 @@ var SCMLib = class {
2187
2942
  }
2188
2943
  _validateAccessTokenAndUrl() {
2189
2944
  if (!this.accessToken) {
2945
+ console.error("no access token");
2190
2946
  throw new InvalidAccessTokenError("no access token");
2191
2947
  }
2948
+ this._validateUrl();
2949
+ }
2950
+ _validateUrl() {
2192
2951
  if (!this.url) {
2952
+ console.error("no url");
2193
2953
  throw new InvalidRepoUrlError("no url");
2194
2954
  }
2195
2955
  }
2196
2956
  };
2197
2957
  var AdoSCMLib = class extends SCMLib {
2198
- updatePrComment(_params, _oktokit) {
2199
- throw new Error("updatePrComment not implemented.");
2200
- }
2201
- getPrComment(_commentId) {
2202
- throw new Error("getPrComment not implemented.");
2203
- }
2204
- async forkRepo() {
2205
- throw new Error("forkRepo not supported yet");
2206
- }
2207
- async createOrUpdateRepositorySecret() {
2208
- throw new Error("createOrUpdateRepositorySecret not supported yet");
2209
- }
2210
- async createPullRequestWithNewFile(_sourceRepoUrl, _filesPaths, _userRepoUrl, _title, _body) {
2211
- throw new Error("createPullRequestWithNewFile not supported yet");
2212
- }
2213
- async createSubmitRequest(targetBranchName, sourceBranchName, title, body) {
2214
- if (!this.accessToken || !this.url) {
2215
- console.error("no access token or no url");
2216
- throw new Error("no access token or no url");
2217
- }
2958
+ async createSubmitRequest(params) {
2959
+ this._validateAccessTokenAndUrl();
2960
+ const { targetBranchName, sourceBranchName, title, body } = params;
2218
2961
  return String(
2219
- await createAdoPullRequest({
2962
+ await AdoSdk.createAdoPullRequest({
2220
2963
  title,
2221
2964
  body,
2222
2965
  targetBranchName,
@@ -2228,7 +2971,7 @@ var AdoSCMLib = class extends SCMLib {
2228
2971
  );
2229
2972
  }
2230
2973
  async validateParams() {
2231
- return adoValidateParams({
2974
+ return AdoSdk.adoValidateParams({
2232
2975
  url: this.url,
2233
2976
  accessToken: this.accessToken,
2234
2977
  tokenOrg: this.scmOrg
@@ -2239,18 +2982,15 @@ var AdoSCMLib = class extends SCMLib {
2239
2982
  console.error("no access token");
2240
2983
  throw new Error("no access token");
2241
2984
  }
2242
- return getAdoRepoList({
2985
+ return AdoSdk.getAdoRepoList({
2243
2986
  orgName: scmOrg,
2244
2987
  tokenOrg: this.scmOrg,
2245
2988
  accessToken: this.accessToken
2246
2989
  });
2247
2990
  }
2248
2991
  async getBranchList() {
2249
- if (!this.accessToken || !this.url) {
2250
- console.error("no access token or no url");
2251
- throw new Error("no access token or no url");
2252
- }
2253
- return getAdoBranchList({
2992
+ this._validateAccessTokenAndUrl();
2993
+ return AdoSdk.getAdoBranchList({
2254
2994
  accessToken: this.accessToken,
2255
2995
  tokenOrg: this.scmOrg,
2256
2996
  repoUrl: this.url
@@ -2261,7 +3001,7 @@ var AdoSCMLib = class extends SCMLib {
2261
3001
  }
2262
3002
  getAuthHeaders() {
2263
3003
  if (this.accessToken) {
2264
- if (getAdoTokenType(this.accessToken) === "OAUTH" /* OAUTH */) {
3004
+ if (AdoSdk.getAdoTokenType(this.accessToken) === "OAUTH" /* OAUTH */) {
2265
3005
  return {
2266
3006
  authorization: `Bearer ${this.accessToken}`
2267
3007
  };
@@ -2276,21 +3016,17 @@ var AdoSCMLib = class extends SCMLib {
2276
3016
  return {};
2277
3017
  }
2278
3018
  getDownloadUrl(sha) {
2279
- if (!this.url) {
2280
- console.error("no url");
2281
- throw new Error("no url");
2282
- }
2283
- return getAdoDownloadUrl({ repoUrl: this.url, branch: sha });
3019
+ this._validateUrl();
3020
+ return Promise.resolve(
3021
+ AdoSdk.getAdoDownloadUrl({ repoUrl: this.url, branch: sha })
3022
+ );
2284
3023
  }
2285
3024
  async _getUsernameForAuthUrl() {
2286
3025
  throw new Error("_getUsernameForAuthUrl() is not relevant for ADO");
2287
3026
  }
2288
3027
  async getIsRemoteBranch(branch) {
2289
- if (!this.accessToken || !this.url) {
2290
- console.error("no access token or no url");
2291
- throw new Error("no access token or no url");
2292
- }
2293
- return getAdoIsRemoteBranch({
3028
+ this._validateAccessTokenAndUrl();
3029
+ return AdoSdk.getAdoIsRemoteBranch({
2294
3030
  accessToken: this.accessToken,
2295
3031
  tokenOrg: this.scmOrg,
2296
3032
  repoUrl: this.url,
@@ -2298,11 +3034,8 @@ var AdoSCMLib = class extends SCMLib {
2298
3034
  });
2299
3035
  }
2300
3036
  async getUserHasAccessToRepo() {
2301
- if (!this.accessToken || !this.url) {
2302
- console.error("no access token or no url");
2303
- throw new Error("no access token or no url");
2304
- }
2305
- return getAdoIsUserCollaborator({
3037
+ this._validateAccessTokenAndUrl();
3038
+ return AdoSdk.getAdoIsUserCollaborator({
2306
3039
  accessToken: this.accessToken,
2307
3040
  tokenOrg: this.scmOrg,
2308
3041
  repoUrl: this.url
@@ -2312,11 +3045,8 @@ var AdoSCMLib = class extends SCMLib {
2312
3045
  throw new Error("getUsername() is not relevant for ADO");
2313
3046
  }
2314
3047
  async getSubmitRequestStatus(scmSubmitRequestId) {
2315
- if (!this.accessToken || !this.url) {
2316
- console.error("no access token or no url");
2317
- throw new Error("no access token or no url");
2318
- }
2319
- const state = await getAdoPullRequestStatus({
3048
+ this._validateAccessTokenAndUrl();
3049
+ const state = await AdoSdk.getAdoPullRequestStatus({
2320
3050
  accessToken: this.accessToken,
2321
3051
  tokenOrg: this.scmOrg,
2322
3052
  repoUrl: this.url,
@@ -2324,24 +3054,21 @@ var AdoSCMLib = class extends SCMLib {
2324
3054
  });
2325
3055
  switch (state) {
2326
3056
  case "completed" /* completed */:
2327
- return "MERGED" /* MERGED */;
3057
+ return "merged";
2328
3058
  case "active" /* active */:
2329
- return "OPEN" /* OPEN */;
3059
+ return "open";
2330
3060
  case "abandoned" /* abandoned */:
2331
- return "CLOSED" /* CLOSED */;
3061
+ return "closed";
2332
3062
  default:
2333
3063
  throw new Error(`unknown state ${state}`);
2334
3064
  }
2335
3065
  }
2336
3066
  async getRepoBlameRanges(_ref, _path) {
2337
- return await getAdoBlameRanges();
3067
+ return await AdoSdk.getAdoBlameRanges();
2338
3068
  }
2339
3069
  async getReferenceData(ref) {
2340
- if (!this.url) {
2341
- console.error("no url");
2342
- throw new Error("no url");
2343
- }
2344
- return await getAdoReferenceData({
3070
+ this._validateUrl();
3071
+ return await AdoSdk.getAdoReferenceData({
2345
3072
  ref,
2346
3073
  repoUrl: this.url,
2347
3074
  accessToken: this.accessToken,
@@ -2349,11 +3076,8 @@ var AdoSCMLib = class extends SCMLib {
2349
3076
  });
2350
3077
  }
2351
3078
  async getRepoDefaultBranch() {
2352
- if (!this.url) {
2353
- console.error("no url");
2354
- throw new Error("no url");
2355
- }
2356
- return await getAdoRepoDefaultBranch({
3079
+ this._validateUrl();
3080
+ return await AdoSdk.getAdoRepoDefaultBranch({
2357
3081
  repoUrl: this.url,
2358
3082
  tokenOrg: this.scmOrg,
2359
3083
  accessToken: this.accessToken
@@ -2363,22 +3087,11 @@ var AdoSCMLib = class extends SCMLib {
2363
3087
  this._validateAccessTokenAndUrl();
2364
3088
  return Promise.resolve(getAdoPrUrl({ prNumber, url: this.url }));
2365
3089
  }
2366
- postGeneralPrComment() {
2367
- throw new Error("Method not implemented.");
2368
- }
2369
- getGeneralPrComments() {
2370
- throw new Error("Method not implemented.");
2371
- }
2372
- deleteGeneralPrComment() {
2373
- throw new Error("Method not implemented.");
2374
- }
2375
3090
  };
2376
3091
  var GitlabSCMLib = class extends SCMLib {
2377
- async createSubmitRequest(targetBranchName, sourceBranchName, title, body) {
2378
- if (!this.accessToken || !this.url) {
2379
- console.error("no access token or no url");
2380
- throw new Error("no access token or no url");
2381
- }
3092
+ async createSubmitRequest(params) {
3093
+ this._validateAccessTokenAndUrl();
3094
+ const { targetBranchName, sourceBranchName, title, body } = params;
2382
3095
  return String(
2383
3096
  await createMergeRequest({
2384
3097
  title,
@@ -2396,23 +3109,6 @@ var GitlabSCMLib = class extends SCMLib {
2396
3109
  accessToken: this.accessToken
2397
3110
  });
2398
3111
  }
2399
- async forkRepo() {
2400
- if (!this.accessToken) {
2401
- console.error("no access token");
2402
- throw new Error("no access token");
2403
- }
2404
- throw new Error("not supported yet");
2405
- }
2406
- async createOrUpdateRepositorySecret() {
2407
- if (!this.accessToken) {
2408
- console.error("no access token");
2409
- throw new Error("no access token");
2410
- }
2411
- throw new Error("not supported yet");
2412
- }
2413
- async createPullRequestWithNewFile(_sourceRepoUrl, _filesPaths, _userRepoUrl, _title, _body) {
2414
- throw new Error("not implemented");
2415
- }
2416
3112
  async getRepoList(_scmOrg) {
2417
3113
  if (!this.accessToken) {
2418
3114
  console.error("no access token");
@@ -2421,10 +3117,7 @@ var GitlabSCMLib = class extends SCMLib {
2421
3117
  return getGitlabRepoList(this.url, this.accessToken);
2422
3118
  }
2423
3119
  async getBranchList() {
2424
- if (!this.accessToken || !this.url) {
2425
- console.error("no access token or no url");
2426
- throw new Error("no access token or no url");
2427
- }
3120
+ this._validateAccessTokenAndUrl();
2428
3121
  return getGitlabBranchList({
2429
3122
  accessToken: this.accessToken,
2430
3123
  repoUrl: this.url
@@ -2445,7 +3138,9 @@ var GitlabSCMLib = class extends SCMLib {
2445
3138
  getDownloadUrl(sha) {
2446
3139
  const urlSplit = this.url?.split("/") || [];
2447
3140
  const repoName = urlSplit[urlSplit?.length - 1];
2448
- return `${this.url}/-/archive/${sha}/${repoName}-${sha}.zip`;
3141
+ return Promise.resolve(
3142
+ `${this.url}/-/archive/${sha}/${repoName}-${sha}.zip`
3143
+ );
2449
3144
  }
2450
3145
  async _getUsernameForAuthUrl() {
2451
3146
  if (this?.accessToken?.startsWith("glpat-")) {
@@ -2455,10 +3150,7 @@ var GitlabSCMLib = class extends SCMLib {
2455
3150
  }
2456
3151
  }
2457
3152
  async getIsRemoteBranch(branch) {
2458
- if (!this.accessToken || !this.url) {
2459
- console.error("no access token or no url");
2460
- throw new Error("no access token or no url");
2461
- }
3153
+ this._validateAccessTokenAndUrl();
2462
3154
  return getGitlabIsRemoteBranch({
2463
3155
  accessToken: this.accessToken,
2464
3156
  repoUrl: this.url,
@@ -2466,10 +3158,7 @@ var GitlabSCMLib = class extends SCMLib {
2466
3158
  });
2467
3159
  }
2468
3160
  async getUserHasAccessToRepo() {
2469
- if (!this.accessToken || !this.url) {
2470
- console.error("no access token or no url");
2471
- throw new Error("no access token or no url");
2472
- }
3161
+ this._validateAccessTokenAndUrl();
2473
3162
  const username = await this.getUsername();
2474
3163
  return getGitlabIsUserCollaborator({
2475
3164
  username,
@@ -2478,38 +3167,29 @@ var GitlabSCMLib = class extends SCMLib {
2478
3167
  });
2479
3168
  }
2480
3169
  async getUsername() {
2481
- if (!this.accessToken) {
2482
- console.error("no access token");
2483
- throw new Error("no access token");
2484
- }
3170
+ this._validateAccessTokenAndUrl();
2485
3171
  return getGitlabUsername(this.url, this.accessToken);
2486
3172
  }
2487
3173
  async getSubmitRequestStatus(scmSubmitRequestId) {
2488
- if (!this.accessToken || !this.url) {
2489
- console.error("no access token or no url");
2490
- throw new Error("no access token or no url");
2491
- }
3174
+ this._validateAccessTokenAndUrl();
2492
3175
  const state = await getGitlabMergeRequestStatus({
2493
3176
  accessToken: this.accessToken,
2494
3177
  repoUrl: this.url,
2495
3178
  mrNumber: Number(scmSubmitRequestId)
2496
3179
  });
2497
3180
  switch (state) {
2498
- case "merged" /* merged */:
2499
- return "MERGED" /* MERGED */;
2500
- case "opened" /* opened */:
2501
- return "OPEN" /* OPEN */;
2502
- case "closed" /* closed */:
2503
- return "CLOSED" /* CLOSED */;
3181
+ case gitlabMergeRequestStatus.merged:
3182
+ return "merged";
3183
+ case gitlabMergeRequestStatus.opened:
3184
+ return "open";
3185
+ case gitlabMergeRequestStatus.closed:
3186
+ return "closed";
2504
3187
  default:
2505
3188
  throw new Error(`unknown state ${state}`);
2506
3189
  }
2507
3190
  }
2508
3191
  async getRepoBlameRanges(ref, path9) {
2509
- if (!this.url) {
2510
- console.error("no url");
2511
- throw new Error("no url");
2512
- }
3192
+ this._validateUrl();
2513
3193
  return await getGitlabBlameRanges(
2514
3194
  { ref, path: path9, gitlabUrl: this.url },
2515
3195
  {
@@ -2519,10 +3199,7 @@ var GitlabSCMLib = class extends SCMLib {
2519
3199
  );
2520
3200
  }
2521
3201
  async getReferenceData(ref) {
2522
- if (!this.url) {
2523
- console.error("no url");
2524
- throw new Error("no url");
2525
- }
3202
+ this._validateUrl();
2526
3203
  return await getGitlabReferenceData(
2527
3204
  { ref, gitlabUrl: this.url },
2528
3205
  {
@@ -2532,21 +3209,12 @@ var GitlabSCMLib = class extends SCMLib {
2532
3209
  );
2533
3210
  }
2534
3211
  async getRepoDefaultBranch() {
2535
- if (!this.url) {
2536
- console.error("no url");
2537
- throw new Error("no url");
2538
- }
3212
+ this._validateUrl();
2539
3213
  return await getGitlabRepoDefaultBranch(this.url, {
2540
3214
  url: this.url,
2541
3215
  gitlabAuthToken: this.accessToken
2542
3216
  });
2543
3217
  }
2544
- getPrComment(_commentId) {
2545
- throw new Error("getPrComment not implemented.");
2546
- }
2547
- updatePrComment(_params, _oktokit) {
2548
- throw new Error("updatePrComment not implemented.");
2549
- }
2550
3218
  async getPrUrl(prNumber) {
2551
3219
  this._validateAccessTokenAndUrl();
2552
3220
  const res = await getGitlabMergeRequest({
@@ -2556,15 +3224,6 @@ var GitlabSCMLib = class extends SCMLib {
2556
3224
  });
2557
3225
  return res.web_url;
2558
3226
  }
2559
- postGeneralPrComment() {
2560
- throw new Error("Method not implemented.");
2561
- }
2562
- getGeneralPrComments() {
2563
- throw new Error("Method not implemented.");
2564
- }
2565
- deleteGeneralPrComment() {
2566
- throw new Error("Method not implemented.");
2567
- }
2568
3227
  };
2569
3228
  var GithubSCMLib = class extends SCMLib {
2570
3229
  // we don't always need a url, what's important is that we have an access token
@@ -2573,11 +3232,9 @@ var GithubSCMLib = class extends SCMLib {
2573
3232
  __publicField(this, "oktokit");
2574
3233
  this.oktokit = new Octokit2({ auth: accessToken });
2575
3234
  }
2576
- async createSubmitRequest(targetBranchName, sourceBranchName, title, body) {
2577
- if (!this.accessToken || !this.url) {
2578
- console.error("no access token or no url");
2579
- throw new Error("no access token or no url");
2580
- }
3235
+ async createSubmitRequest(params) {
3236
+ this._validateAccessTokenAndUrl();
3237
+ const { targetBranchName, sourceBranchName, title, body } = params;
2581
3238
  return String(
2582
3239
  await createPullRequest({
2583
3240
  title,
@@ -2590,10 +3247,7 @@ var GithubSCMLib = class extends SCMLib {
2590
3247
  );
2591
3248
  }
2592
3249
  async forkRepo(repoUrl) {
2593
- if (!this.accessToken) {
2594
- console.error("no access token");
2595
- throw new Error("no access token");
2596
- }
3250
+ this._validateToken();
2597
3251
  return forkRepo({
2598
3252
  repoUrl,
2599
3253
  accessToken: this.accessToken
@@ -2699,7 +3353,7 @@ var GithubSCMLib = class extends SCMLib {
2699
3353
  owner,
2700
3354
  repo
2701
3355
  });
2702
- return z8.string().parse(prRes.data);
3356
+ return z9.string().parse(prRes.data);
2703
3357
  }
2704
3358
  async getRepoList(_scmOrg) {
2705
3359
  if (!this.accessToken) {
@@ -2709,10 +3363,7 @@ var GithubSCMLib = class extends SCMLib {
2709
3363
  return getGithubRepoList(this.accessToken);
2710
3364
  }
2711
3365
  async getBranchList() {
2712
- if (!this.accessToken || !this.url) {
2713
- console.error("no access token or no url");
2714
- throw new Error("no access token or no url");
2715
- }
3366
+ this._validateAccessTokenAndUrl();
2716
3367
  return getGithubBranchList(this.accessToken, this.url);
2717
3368
  }
2718
3369
  getScmLibType() {
@@ -2725,16 +3376,13 @@ var GithubSCMLib = class extends SCMLib {
2725
3376
  return {};
2726
3377
  }
2727
3378
  getDownloadUrl(sha) {
2728
- return `${this.url}/zipball/${sha}`;
3379
+ return Promise.resolve(`${this.url}/zipball/${sha}`);
2729
3380
  }
2730
3381
  async _getUsernameForAuthUrl() {
2731
3382
  return this.getUsername();
2732
3383
  }
2733
3384
  async getIsRemoteBranch(branch) {
2734
- if (!this.accessToken || !this.url) {
2735
- console.error("no access token or no url");
2736
- throw new Error("no access token or no url");
2737
- }
3385
+ this._validateAccessTokenAndUrl();
2738
3386
  return getGithubIsRemoteBranch(this.accessToken, this.url, branch);
2739
3387
  }
2740
3388
  async getUserHasAccessToRepo() {
@@ -2762,25 +3410,10 @@ var GithubSCMLib = class extends SCMLib {
2762
3410
  this.url,
2763
3411
  Number(scmSubmitRequestId)
2764
3412
  );
2765
- if (state === "merged") {
2766
- return "MERGED" /* MERGED */;
2767
- }
2768
- if (state === "open") {
2769
- return "OPEN" /* OPEN */;
2770
- }
2771
- if (state === "draft") {
2772
- return "DRAFT" /* DRAFT */;
2773
- }
2774
- if (state === "closed") {
2775
- return "CLOSED" /* CLOSED */;
2776
- }
2777
- throw new Error(`unknown state ${state}`);
3413
+ return state;
2778
3414
  }
2779
3415
  async getRepoBlameRanges(ref, path9) {
2780
- if (!this.url) {
2781
- console.error("no url");
2782
- throw new Error("no url");
2783
- }
3416
+ this._validateUrl();
2784
3417
  return await getGithubBlameRanges(
2785
3418
  { ref, path: path9, gitHubUrl: this.url },
2786
3419
  {
@@ -2789,10 +3422,7 @@ var GithubSCMLib = class extends SCMLib {
2789
3422
  );
2790
3423
  }
2791
3424
  async getReferenceData(ref) {
2792
- if (!this.url) {
2793
- console.error("no url");
2794
- throw new Error("no url");
2795
- }
3425
+ this._validateUrl();
2796
3426
  return await getGithubReferenceData(
2797
3427
  { ref, gitHubUrl: this.url },
2798
3428
  {
@@ -2801,10 +3431,7 @@ var GithubSCMLib = class extends SCMLib {
2801
3431
  );
2802
3432
  }
2803
3433
  async getPrComment(commentId) {
2804
- if (!this.url) {
2805
- console.error("no url");
2806
- throw new Error("no url");
2807
- }
3434
+ this._validateUrl();
2808
3435
  const { owner, repo } = parseGithubOwnerAndRepo(this.url);
2809
3436
  return await getPrComment(this.oktokit, {
2810
3437
  repo,
@@ -2813,10 +3440,7 @@ var GithubSCMLib = class extends SCMLib {
2813
3440
  });
2814
3441
  }
2815
3442
  async getRepoDefaultBranch() {
2816
- if (!this.url) {
2817
- console.error("no url");
2818
- throw new Error("no url");
2819
- }
3443
+ this._validateUrl();
2820
3444
  return await getGithubRepoDefaultBranch(this.url, {
2821
3445
  githubAuthToken: this.accessToken
2822
3446
  });
@@ -2836,10 +3460,7 @@ var GithubSCMLib = class extends SCMLib {
2836
3460
  }
2837
3461
  async postGeneralPrComment(params, auth) {
2838
3462
  const { prNumber, body } = params;
2839
- if (!this.url) {
2840
- console.error("no url");
2841
- throw new Error("no url");
2842
- }
3463
+ this._validateUrl();
2843
3464
  const oktoKit = auth ? new Octokit2({ auth: auth.authToken }) : this.oktokit;
2844
3465
  const { owner, repo } = parseGithubOwnerAndRepo(this.url);
2845
3466
  return await postGeneralPrComment(oktoKit, {
@@ -2851,10 +3472,7 @@ var GithubSCMLib = class extends SCMLib {
2851
3472
  }
2852
3473
  async getGeneralPrComments(params, auth) {
2853
3474
  const { prNumber } = params;
2854
- if (!this.url) {
2855
- console.error("no url");
2856
- throw new Error("no url");
2857
- }
3475
+ this._validateUrl();
2858
3476
  const oktoKit = auth ? new Octokit2({ auth: auth.authToken }) : this.oktokit;
2859
3477
  const { owner, repo } = parseGithubOwnerAndRepo(this.url);
2860
3478
  return await getGeneralPrComments(oktoKit, {
@@ -2864,10 +3482,7 @@ var GithubSCMLib = class extends SCMLib {
2864
3482
  });
2865
3483
  }
2866
3484
  async deleteGeneralPrComment({ commentId }, auth) {
2867
- if (!this.url) {
2868
- console.error("no url");
2869
- throw new Error("no url");
2870
- }
3485
+ this._validateUrl();
2871
3486
  const oktoKit = auth ? new Octokit2({ auth: auth.authToken }) : this.oktokit;
2872
3487
  const { owner, repo } = parseGithubOwnerAndRepo(this.url);
2873
3488
  return deleteGeneralPrComment(oktoKit, {
@@ -2878,7 +3493,7 @@ var GithubSCMLib = class extends SCMLib {
2878
3493
  }
2879
3494
  };
2880
3495
  var StubSCMLib = class extends SCMLib {
2881
- async createSubmitRequest(_targetBranchName, _sourceBranchName, _title, _body) {
3496
+ async createSubmitRequest(_params) {
2882
3497
  console.error("createSubmitRequest() not implemented");
2883
3498
  throw new Error("createSubmitRequest() not implemented");
2884
3499
  }
@@ -2894,10 +3509,6 @@ var StubSCMLib = class extends SCMLib {
2894
3509
  console.error("getDownloadUrl() not implemented");
2895
3510
  throw new Error("getDownloadUrl() not implemented");
2896
3511
  }
2897
- async _getUsernameForAuthUrl() {
2898
- console.error("_getUsernameForAuthUrl() not implemented");
2899
- throw new Error("_getUsernameForAuthUrl() not implemented");
2900
- }
2901
3512
  async getIsRemoteBranch(_branch) {
2902
3513
  console.error("getIsRemoteBranch() not implemented");
2903
3514
  throw new Error("getIsRemoteBranch() not implemented");
@@ -2906,18 +3517,6 @@ var StubSCMLib = class extends SCMLib {
2906
3517
  console.error("validateParams() not implemented");
2907
3518
  throw new Error("validateParams() not implemented");
2908
3519
  }
2909
- async forkRepo() {
2910
- console.error("forkRepo() not implemented");
2911
- throw new Error("forkRepo() not implemented");
2912
- }
2913
- async createOrUpdateRepositorySecret() {
2914
- console.error("forkRepo() not implemented");
2915
- throw new Error("forkRepo() not implemented");
2916
- }
2917
- async createPullRequestWithNewFile(_sourceRepoUrl, _filesPaths, _userRepoUrl, _title, _body) {
2918
- console.error("createPullRequestWithNewFile() not implemented");
2919
- throw new Error("createPullRequestWithNewFile() not implemented");
2920
- }
2921
3520
  async getRepoList(_scmOrg) {
2922
3521
  console.error("getRepoList() not implemented");
2923
3522
  throw new Error("getRepoList() not implemented");
@@ -2950,607 +3549,496 @@ var StubSCMLib = class extends SCMLib {
2950
3549
  console.error("getRepoDefaultBranch() not implemented");
2951
3550
  throw new Error("getRepoDefaultBranch() not implemented");
2952
3551
  }
2953
- async getPrComment(_commentId) {
2954
- console.error("getPrComment() not implemented");
2955
- throw new Error("getPrComment() not implemented");
2956
- }
2957
- async updatePrComment() {
2958
- console.error("updatePrComment() not implemented");
2959
- throw new Error("updatePrComment() not implemented");
2960
- }
2961
3552
  async getPrUrl(_prNumber) {
2962
3553
  console.error("getPr() not implemented");
2963
3554
  throw new Error("getPr() not implemented");
2964
3555
  }
2965
- postGeneralPrComment() {
3556
+ _getUsernameForAuthUrl() {
2966
3557
  throw new Error("Method not implemented.");
2967
3558
  }
2968
- getGeneralPrComments() {
2969
- throw new Error("Method not implemented.");
3559
+ };
3560
+ function getUserAndPassword(token) {
3561
+ const [username, password] = token.split(":");
3562
+ const safePasswordAndUsername = z9.object({ username: z9.string(), password: z9.string() }).parse({ username, password });
3563
+ return {
3564
+ username: safePasswordAndUsername.username,
3565
+ password: safePasswordAndUsername.password
3566
+ };
3567
+ }
3568
+ function createBitbucketSdk(token) {
3569
+ if (!token) {
3570
+ return getBitbucketSdk({ authType: "public" });
2970
3571
  }
2971
- deleteGeneralPrComment() {
2972
- throw new Error("Method not implemented.");
3572
+ if (token.includes(":")) {
3573
+ const { password, username } = getUserAndPassword(token);
3574
+ return getBitbucketSdk({
3575
+ authType: "basic",
3576
+ username,
3577
+ password
3578
+ });
2973
3579
  }
2974
- };
2975
-
2976
- // src/features/analysis/scm/ado.ts
2977
- function removeTrailingSlash3(str) {
2978
- return str.trim().replace(/\/+$/, "");
3580
+ return getBitbucketSdk({ authType: "token", token });
2979
3581
  }
2980
- async function _getOrgsForOauthToken({ oauthToken }) {
2981
- const profileZ = z9.object({
2982
- displayName: z9.string(),
2983
- publicAlias: z9.string().min(1),
2984
- emailAddress: z9.string(),
2985
- coreRevision: z9.number(),
2986
- timeStamp: z9.string(),
2987
- id: z9.string(),
2988
- revision: z9.number()
2989
- });
2990
- const accountsZ = z9.object({
2991
- count: z9.number(),
2992
- value: z9.array(
2993
- z9.object({
2994
- accountId: z9.string(),
2995
- accountUri: z9.string(),
2996
- accountName: z9.string()
2997
- })
2998
- )
2999
- });
3000
- const profileRes = await fetch(
3001
- "https://app.vssps.visualstudio.com/_apis/profile/profiles/me?api-version=6.0",
3002
- {
3003
- method: "GET",
3004
- headers: {
3005
- Authorization: `Bearer ${oauthToken}`
3582
+ var BitbucketSCMLib = class extends SCMLib {
3583
+ constructor(url, accessToken, scmOrg) {
3584
+ super(url, accessToken, scmOrg);
3585
+ __publicField(this, "bitbucketSdk");
3586
+ const bitbucketSdk = createBitbucketSdk(accessToken);
3587
+ this.bitbucketSdk = bitbucketSdk;
3588
+ }
3589
+ getAuthData() {
3590
+ const authType = this.bitbucketSdk.getAuthType();
3591
+ switch (authType) {
3592
+ case "basic": {
3593
+ this._validateToken();
3594
+ const { username, password } = getUserAndPassword(this.accessToken);
3595
+ return { username, password, authType };
3006
3596
  }
3007
- }
3008
- );
3009
- const profileJson = await profileRes.json();
3010
- const profile = profileZ.parse(profileJson);
3011
- const accountsRes = await fetch(
3012
- `https://app.vssps.visualstudio.com/_apis/accounts?memberId=${profile.publicAlias}&api-version=6.0`,
3013
- {
3014
- method: "GET",
3015
- headers: {
3016
- Authorization: `Bearer ${oauthToken}`
3597
+ case "token": {
3598
+ return { authType, token: z9.string().parse(this.accessToken) };
3017
3599
  }
3600
+ case "public":
3601
+ return { authType };
3018
3602
  }
3019
- );
3020
- const accountsJson = await accountsRes.json();
3021
- const accounts = accountsZ.parse(accountsJson);
3022
- const orgs = accounts.value.map((account) => account.accountName).filter((value, index, array) => array.indexOf(value) === index);
3023
- return orgs;
3024
- }
3025
- function _getPublicAdoClient({ orgName }) {
3026
- const orgUrl = `https://dev.azure.com/${orgName}`;
3027
- const authHandler = api.getPersonalAccessTokenHandler("");
3028
- authHandler.canHandleAuthentication = () => false;
3029
- authHandler.prepareRequest = (_options) => {
3030
- return;
3031
- };
3032
- const connection = new api.WebApi(orgUrl, authHandler);
3033
- return connection;
3034
- }
3035
- function getAdoTokenType(token) {
3036
- if (token.includes(".")) {
3037
- return "OAUTH" /* OAUTH */;
3038
- }
3039
- return "PAT" /* PAT */;
3040
- }
3041
- async function getAdoApiClient({
3042
- accessToken,
3043
- tokenOrg,
3044
- orgName
3045
- }) {
3046
- if (!accessToken || tokenOrg && tokenOrg !== orgName) {
3047
- return _getPublicAdoClient({ orgName });
3048
3603
  }
3049
- const orgUrl = `https://dev.azure.com/${orgName}`;
3050
- if (getAdoTokenType(accessToken) === "OAUTH" /* OAUTH */) {
3051
- const connection2 = new api.WebApi(orgUrl, api.getBearerHandler(accessToken));
3052
- return connection2;
3604
+ async createSubmitRequest(params) {
3605
+ this._validateAccessTokenAndUrl();
3606
+ const pullRequestRes = await this.bitbucketSdk.createPullRequest({
3607
+ ...params,
3608
+ repoUrl: this.url
3609
+ });
3610
+ return String(z9.number().parse(pullRequestRes.id));
3053
3611
  }
3054
- const authHandler = api.getPersonalAccessTokenHandler(accessToken);
3055
- const connection = new api.WebApi(orgUrl, authHandler);
3056
- return connection;
3057
- }
3058
- async function adoValidateParams({
3059
- url,
3060
- accessToken,
3061
- tokenOrg
3062
- }) {
3063
- try {
3064
- if (!url && accessToken && getAdoTokenType(accessToken) === "OAUTH" /* OAUTH */) {
3065
- await _getOrgsForOauthToken({ oauthToken: accessToken });
3066
- return;
3067
- }
3068
- let org = tokenOrg;
3069
- if (url) {
3070
- const { owner } = parseAdoOwnerAndRepo(url);
3071
- org = owner;
3072
- }
3073
- if (!org) {
3074
- throw new InvalidRepoUrlError(`invalid ADO ORG ${org}`);
3075
- }
3076
- const api2 = await getAdoApiClient({
3077
- accessToken,
3078
- tokenOrg,
3079
- orgName: org
3612
+ async validateParams() {
3613
+ return validateBitbucketParams({
3614
+ bitbucketClient: this.bitbucketSdk,
3615
+ url: this.url
3080
3616
  });
3081
- await api2.connect();
3082
- } catch (e) {
3083
- const error = e;
3084
- const code = error.code || error.status || error.statusCode || error.response?.status || error.response?.statusCode || error.response?.code;
3085
- const description = error.description || `${e}`;
3086
- if (code === 401 || code === 403 || description.includes("401") || description.includes("403")) {
3087
- throw new InvalidAccessTokenError(`invalid ADO access token`);
3088
- }
3089
- if (code === 404 || description.includes("404") || description.includes("Not Found")) {
3090
- throw new InvalidRepoUrlError(`invalid ADO repo URL ${url}`);
3091
- }
3092
- throw e;
3093
3617
  }
3094
- }
3095
- async function getAdoIsUserCollaborator({
3096
- accessToken,
3097
- tokenOrg,
3098
- repoUrl
3099
- }) {
3100
- try {
3101
- const { owner, repo, projectName } = parseAdoOwnerAndRepo(repoUrl);
3102
- const api2 = await getAdoApiClient({
3103
- accessToken,
3104
- tokenOrg,
3105
- orgName: owner
3618
+ async getRepoList(scmOrg) {
3619
+ this._validateToken();
3620
+ return this.bitbucketSdk.getRepos({
3621
+ workspaceSlug: scmOrg
3106
3622
  });
3107
- const git = await api2.getGitApi();
3108
- const branches = await git.getBranches(repo, projectName);
3109
- if (!branches || branches.length === 0) {
3110
- throw new InvalidRepoUrlError("no branches");
3111
- }
3112
- return true;
3113
- } catch (e) {
3114
- return false;
3115
3623
  }
3116
- }
3117
- var adoStatusNumberToEnumMap = {
3118
- 1: "active" /* active */,
3119
- 2: "abandoned" /* abandoned */,
3120
- 3: "completed" /* completed */,
3121
- 4: "all" /* all */
3122
- };
3123
- async function getAdoPullRequestStatus({
3124
- accessToken,
3125
- tokenOrg,
3126
- repoUrl,
3127
- prNumber
3128
- }) {
3129
- const { owner, repo, projectName } = parseAdoOwnerAndRepo(repoUrl);
3130
- const api2 = await getAdoApiClient({
3131
- accessToken,
3132
- tokenOrg,
3133
- orgName: owner
3134
- });
3135
- const git = await api2.getGitApi();
3136
- const res = await git.getPullRequest(repo, prNumber, projectName);
3137
- if (!res.status || res.status < 1 || res.status > 3) {
3138
- throw new Error("bad pr status for ADO");
3624
+ async getBranchList() {
3625
+ this._validateAccessTokenAndUrl();
3626
+ return this.bitbucketSdk.getBranchList({
3627
+ repoUrl: this.url
3628
+ });
3139
3629
  }
3140
- return adoStatusNumberToEnumMap[res.status];
3141
- }
3142
- async function getAdoIsRemoteBranch({
3143
- accessToken,
3144
- tokenOrg,
3145
- repoUrl,
3146
- branch
3147
- }) {
3148
- const { owner, repo, projectName } = parseAdoOwnerAndRepo(repoUrl);
3149
- const api2 = await getAdoApiClient({
3150
- accessToken,
3151
- tokenOrg,
3152
- orgName: owner
3153
- });
3154
- const git = await api2.getGitApi();
3155
- try {
3156
- const branchStatus = await git.getBranch(repo, branch, projectName);
3157
- if (!branchStatus || !branchStatus.commit) {
3158
- throw new InvalidRepoUrlError("no branch status");
3630
+ getScmLibType() {
3631
+ return "BITBUCKET" /* BITBUCKET */;
3632
+ }
3633
+ getAuthHeaders() {
3634
+ const authType = this.bitbucketSdk.getAuthType();
3635
+ switch (authType) {
3636
+ case "public":
3637
+ return {};
3638
+ case "token":
3639
+ return { authorization: `Bearer ${this.accessToken}` };
3640
+ case "basic": {
3641
+ this._validateToken();
3642
+ const { username, password } = getUserAndPassword(this.accessToken);
3643
+ return {
3644
+ authorization: `Basic ${Buffer.from(
3645
+ username + ":" + password
3646
+ ).toString("base64")}`
3647
+ };
3648
+ }
3159
3649
  }
3160
- return branchStatus.name === branch;
3161
- } catch (e) {
3162
- return false;
3163
3650
  }
3164
- }
3165
- async function getAdoRepoList({
3166
- orgName,
3167
- tokenOrg,
3168
- accessToken
3169
- }) {
3170
- let orgs = [];
3171
- if (getAdoTokenType(accessToken) === "OAUTH" /* OAUTH */) {
3172
- orgs = await _getOrgsForOauthToken({ oauthToken: accessToken });
3651
+ async getDownloadUrl(sha) {
3652
+ this._validateUrl();
3653
+ return this.bitbucketSdk.getDownloadUrl({ url: this.url, sha });
3173
3654
  }
3174
- if (orgs.length === 0 && !orgName) {
3175
- throw new Error(`no orgs for ADO`);
3176
- } else if (orgs.length === 0 && orgName) {
3177
- orgs = [orgName];
3655
+ async _getUsernameForAuthUrl() {
3656
+ this._validateAccessTokenAndUrl();
3657
+ const user = await this.bitbucketSdk.getUser();
3658
+ if (!user.username) {
3659
+ throw new Error("no username found");
3660
+ }
3661
+ return user.username;
3178
3662
  }
3179
- const repos = (await Promise.allSettled(
3180
- orgs.map(async (org) => {
3181
- const orgApi = await getAdoApiClient({
3182
- accessToken,
3183
- tokenOrg,
3184
- orgName: org
3663
+ async getIsRemoteBranch(branch) {
3664
+ this._validateAccessTokenAndUrl();
3665
+ try {
3666
+ const res = await this.bitbucketSdk.getBranch({
3667
+ branchName: branch,
3668
+ repoUrl: this.url
3185
3669
  });
3186
- const gitOrg = await orgApi.getGitApi();
3187
- const orgRepos = await gitOrg.getRepositories();
3188
- const repoInfoList = (await Promise.allSettled(
3189
- orgRepos.map(async (repo) => {
3190
- if (!repo.name || !repo.remoteUrl || !repo.defaultBranch) {
3191
- throw new InvalidRepoUrlError("bad repo");
3192
- }
3193
- const branch = await gitOrg.getBranch(
3194
- repo.name,
3195
- repo.defaultBranch.replace(/^refs\/heads\//, ""),
3196
- repo.project?.name
3197
- );
3198
- return {
3199
- repoName: repo.name,
3200
- repoUrl: repo.remoteUrl.replace(
3201
- /^[hH][tT][tT][pP][sS]:\/\/[^/]+@/,
3202
- "https://"
3203
- ),
3204
- repoOwner: org,
3205
- repoIsPublic: repo.project?.visibility === 2,
3206
- //2 is public in the ADO API
3207
- repoLanguages: [],
3208
- repoUpdatedAt: branch.commit?.committer?.date?.toDateString() || repo.project?.lastUpdateTime?.toDateString() || (/* @__PURE__ */ new Date()).toDateString()
3209
- };
3210
- })
3211
- )).reduce((acc, res) => {
3212
- if (res.status === "fulfilled") {
3213
- acc.push(res.value);
3214
- }
3215
- return acc;
3216
- }, []);
3217
- return repoInfoList;
3218
- })
3219
- )).reduce((acc, res) => {
3220
- if (res.status === "fulfilled") {
3221
- return acc.concat(res.value);
3670
+ return res.name === branch;
3671
+ } catch (e) {
3672
+ return false;
3222
3673
  }
3223
- return acc;
3224
- }, []);
3225
- return repos;
3226
- }
3227
- function getAdoPrUrl({
3228
- url,
3229
- prNumber
3230
- }) {
3231
- return `${url}/pullrequest/${prNumber}`;
3232
- }
3233
- function getAdoDownloadUrl({
3234
- repoUrl,
3235
- branch
3236
- }) {
3237
- const { owner, repo, projectName } = parseAdoOwnerAndRepo(repoUrl);
3238
- const url = new URL(repoUrl);
3239
- const origin = url.origin.toLowerCase().endsWith(".visualstudio.com") ? "https://dev.azure.com" : url.origin.toLowerCase();
3240
- return `${origin}/${owner}/${projectName}/_apis/git/repositories/${repo}/items/items?path=/&versionDescriptor[versionOptions]=0&versionDescriptor[versionType]=commit&versionDescriptor[version]=${branch}&resolveLfs=true&$format=zip&api-version=5.0&download=true`;
3241
- }
3242
- async function getAdoBranchList({
3243
- accessToken,
3244
- tokenOrg,
3245
- repoUrl
3246
- }) {
3247
- const { owner, repo, projectName } = parseAdoOwnerAndRepo(repoUrl);
3248
- const api2 = await getAdoApiClient({
3249
- accessToken,
3250
- tokenOrg,
3251
- orgName: owner
3252
- });
3253
- const git = await api2.getGitApi();
3254
- try {
3255
- const res = await git.getBranches(repo, projectName);
3256
- res.sort((a, b) => {
3257
- if (!a.commit?.committer?.date || !b.commit?.committer?.date) {
3258
- return 0;
3259
- }
3260
- return b.commit?.committer?.date.getTime() - a.commit?.committer?.date.getTime();
3674
+ }
3675
+ async getUserHasAccessToRepo() {
3676
+ this._validateAccessTokenAndUrl();
3677
+ return this.bitbucketSdk.getIsUserCollaborator({ repoUrl: this.url });
3678
+ }
3679
+ async getUsername() {
3680
+ this._validateToken();
3681
+ const res = await this.bitbucketSdk.getUser();
3682
+ return z9.string().parse(res.username);
3683
+ }
3684
+ async getSubmitRequestStatus(_scmSubmitRequestId) {
3685
+ this._validateAccessTokenAndUrl();
3686
+ const pullRequestRes = await this.bitbucketSdk.getPullRequest({
3687
+ prNumber: Number(_scmSubmitRequestId),
3688
+ url: this.url
3261
3689
  });
3262
- return res.reduce((acc, branch) => {
3263
- if (!branch.name) {
3264
- return acc;
3265
- }
3266
- acc.push(branch.name);
3267
- return acc;
3268
- }, []);
3269
- } catch (e) {
3690
+ switch (pullRequestRes.state) {
3691
+ case "OPEN":
3692
+ return "open";
3693
+ case "MERGED":
3694
+ return "merged";
3695
+ case "DECLINED":
3696
+ return "closed";
3697
+ default:
3698
+ throw new Error(`unknown state ${pullRequestRes.state} `);
3699
+ }
3700
+ }
3701
+ async getRepoBlameRanges(_ref, _path) {
3270
3702
  return [];
3271
3703
  }
3272
- }
3273
- async function createAdoPullRequest(options) {
3274
- const { owner, repo, projectName } = parseAdoOwnerAndRepo(options.repoUrl);
3275
- const api2 = await getAdoApiClient({
3276
- accessToken: options.accessToken,
3277
- tokenOrg: options.tokenOrg,
3278
- orgName: owner
3279
- });
3280
- const git = await api2.getGitApi();
3281
- const res = await git.createPullRequest(
3282
- {
3283
- sourceRefName: `refs/heads/${options.sourceBranchName}`,
3284
- targetRefName: `refs/heads/${options.targetBranchName}`,
3285
- title: options.title,
3286
- description: options.body
3287
- },
3288
- repo,
3289
- projectName
3290
- );
3291
- return res.pullRequestId;
3292
- }
3293
- async function getAdoRepoDefaultBranch({
3294
- repoUrl,
3295
- tokenOrg,
3296
- accessToken
3297
- }) {
3298
- const { owner, repo, projectName } = parseAdoOwnerAndRepo(repoUrl);
3299
- const api2 = await getAdoApiClient({
3300
- accessToken,
3301
- tokenOrg,
3302
- orgName: owner
3303
- });
3304
- const git = await api2.getGitApi();
3305
- const branches = await git.getBranches(repo, projectName);
3306
- if (!branches || branches.length === 0) {
3307
- throw new InvalidRepoUrlError("no branches");
3704
+ async getReferenceData(ref) {
3705
+ this._validateUrl();
3706
+ return this.bitbucketSdk.getReferenceData({ url: this.url, ref });
3308
3707
  }
3309
- const res = branches.find((branch) => branch.isBaseVersion);
3310
- if (!res || !res.name) {
3311
- throw new InvalidRepoUrlError("no default branch");
3708
+ async getRepoDefaultBranch() {
3709
+ this._validateUrl();
3710
+ const repoRes = await this.bitbucketSdk.getRepo({ repoUrl: this.url });
3711
+ return z9.string().parse(repoRes.mainbranch?.name);
3312
3712
  }
3313
- return res.name;
3713
+ getPrUrl(prNumber) {
3714
+ this._validateUrl();
3715
+ const { repoSlug, workspace } = parseBitbucketOrganizationAndRepo(this.url);
3716
+ return Promise.resolve(
3717
+ `https://bitbucket.org/${workspace}/${repoSlug}/pull-requests/${prNumber}`
3718
+ );
3719
+ }
3720
+ async refreshToken(params) {
3721
+ const getBitbucketTokenResponse = await getBitbucketToken({
3722
+ authType: "refresh_token",
3723
+ ...params
3724
+ });
3725
+ return {
3726
+ accessToken: getBitbucketTokenResponse.access_token,
3727
+ refreshToken: getBitbucketTokenResponse.refresh_token
3728
+ };
3729
+ }
3730
+ };
3731
+
3732
+ // src/features/analysis/scm/bitbucket/bitbucket.ts
3733
+ var { Bitbucket } = bitbucketPkg;
3734
+ var BITBUCKET_HOSTNAME = "bitbucket.org";
3735
+ var TokenExpiredErrorZ = z10.object({
3736
+ status: z10.number(),
3737
+ error: z10.object({
3738
+ type: z10.string(),
3739
+ error: z10.object({
3740
+ message: z10.string()
3741
+ })
3742
+ })
3743
+ });
3744
+ var BITBUCKET_ACCESS_TOKEN_URL = `https://${BITBUCKET_HOSTNAME}/site/oauth2/access_token`;
3745
+ var BitbucketAuthResultZ = z10.object({
3746
+ access_token: z10.string(),
3747
+ token_type: z10.string(),
3748
+ refresh_token: z10.string()
3749
+ });
3750
+ var BitbucketParseResultZ = z10.object({
3751
+ organization: z10.string(),
3752
+ repoName: z10.string(),
3753
+ hostname: z10.literal(BITBUCKET_HOSTNAME)
3754
+ });
3755
+ function parseBitbucketOrganizationAndRepo(bitbucketUrl) {
3756
+ const parsedGitHubUrl = removeTrailingSlash2(bitbucketUrl);
3757
+ const parsingResult = parseScmURL(parsedGitHubUrl, "Bitbucket" /* Bitbucket */);
3758
+ const validatedBitbucketResult = BitbucketParseResultZ.parse(parsingResult);
3759
+ return {
3760
+ workspace: validatedBitbucketResult.organization,
3761
+ repoSlug: validatedBitbucketResult.repoName
3762
+ };
3314
3763
  }
3315
- async function getAdoReferenceData({
3316
- ref,
3317
- repoUrl,
3318
- accessToken,
3319
- tokenOrg
3320
- }) {
3321
- const { owner, repo, projectName } = parseAdoOwnerAndRepo(repoUrl);
3322
- const api2 = await getAdoApiClient({
3323
- accessToken,
3324
- tokenOrg,
3325
- orgName: owner
3764
+ async function getBitbucketToken(params) {
3765
+ const { bitbucketClientId, bitbucketClientSecret, authType } = params;
3766
+ const res = await fetch(BITBUCKET_ACCESS_TOKEN_URL, {
3767
+ method: "POST",
3768
+ headers: {
3769
+ "Content-Type": "application/x-www-form-urlencoded",
3770
+ Authorization: "Basic " + btoa(`${bitbucketClientId}:${bitbucketClientSecret}`)
3771
+ },
3772
+ body: querystring3.stringify(
3773
+ authType === "refresh_token" ? {
3774
+ grant_type: authType,
3775
+ refresh_token: params.refreshToken
3776
+ } : {
3777
+ grant_type: authType,
3778
+ code: params.code
3779
+ }
3780
+ )
3326
3781
  });
3327
- if (!projectName) {
3328
- throw new InvalidUrlPatternError("no project name");
3782
+ const authResult = await res.json();
3783
+ return BitbucketAuthResultZ.parse(authResult);
3784
+ }
3785
+ function getBitbucketIntance(params) {
3786
+ switch (params.authType) {
3787
+ case "public":
3788
+ return new Bitbucket();
3789
+ case "token":
3790
+ return new Bitbucket({ auth: { token: params.token } });
3791
+ case "basic":
3792
+ return new Bitbucket({
3793
+ auth: {
3794
+ password: params.password,
3795
+ username: params.username
3796
+ }
3797
+ });
3329
3798
  }
3330
- const git = await api2.getGitApi();
3331
- const results = await Promise.allSettled([
3332
- (async () => {
3333
- const res = await git.getBranch(repo, ref, projectName);
3334
- if (!res.commit || !res.commit.commitId) {
3335
- throw new InvalidRepoUrlError("no commit on branch");
3336
- }
3337
- return {
3338
- sha: res.commit.commitId,
3339
- type: "BRANCH" /* BRANCH */,
3340
- date: res.commit.committer?.date || /* @__PURE__ */ new Date()
3341
- };
3342
- })(),
3343
- (async () => {
3344
- const res = await git.getCommits(
3345
- repo,
3346
- {
3347
- fromCommitId: ref,
3348
- toCommitId: ref,
3349
- $top: 1
3350
- },
3351
- projectName
3799
+ }
3800
+ function getBitbucketSdk(params) {
3801
+ const bitbucketClient = getBitbucketIntance(params);
3802
+ return {
3803
+ getAuthType() {
3804
+ return params.authType;
3805
+ },
3806
+ async getRepos(params2) {
3807
+ const repoRes = params2?.workspaceSlug ? await getRepositoriesByWorkspace(bitbucketClient, {
3808
+ workspaceSlug: params2.workspaceSlug
3809
+ }) : await getllUsersrepositories(bitbucketClient);
3810
+ return repoRes.map((repo) => ({
3811
+ repoIsPublic: !repo.is_private,
3812
+ repoName: repo.name || "unknown repo name",
3813
+ repoOwner: repo.owner?.username || "unknown owner",
3814
+ // language can be empty string
3815
+ repoLanguages: repo.language ? [repo.language] : [],
3816
+ repoUpdatedAt: repo.updated_on ? repo.updated_on : (/* @__PURE__ */ new Date()).toISOString(),
3817
+ repoUrl: repo.links?.html?.href || ""
3818
+ }));
3819
+ },
3820
+ async getBranchList(params2) {
3821
+ const { workspace, repoSlug } = parseBitbucketOrganizationAndRepo(
3822
+ params2.repoUrl
3352
3823
  );
3353
- const commit = res[0];
3354
- if (!commit || !commit.commitId) {
3355
- throw new Error("no commit");
3356
- }
3357
- return {
3358
- sha: commit.commitId,
3359
- type: "COMMIT" /* COMMIT */,
3360
- date: commit.committer?.date || /* @__PURE__ */ new Date()
3361
- };
3362
- })(),
3363
- (async () => {
3364
- const res = await git.getRefs(repo, projectName, `tags/${ref}`);
3365
- if (!res[0] || !res[0].objectId) {
3366
- throw new Error("no tag ref");
3824
+ const res = await bitbucketClient.refs.listBranches({
3825
+ repo_slug: repoSlug,
3826
+ workspace
3827
+ });
3828
+ if (!res.data.values) {
3829
+ return [];
3367
3830
  }
3368
- let objectId = res[0].objectId;
3369
- try {
3370
- const tag = await git.getAnnotatedTag(projectName, repo, objectId);
3371
- if (tag.taggedObject?.objectId) {
3372
- objectId = tag.taggedObject.objectId;
3831
+ return res.data.values.filter((branch) => !!branch.name).map((branch) => z10.string().parse(branch.name));
3832
+ },
3833
+ async getIsUserCollaborator(params2) {
3834
+ const { repoUrl } = params2;
3835
+ const { repoSlug, workspace } = parseBitbucketOrganizationAndRepo(repoUrl);
3836
+ const fullRepoName = `${workspace}/${repoSlug}`;
3837
+ const res = await bitbucketClient.user.listPermissionsForRepos({
3838
+ q: `repository.full_name~"${fullRepoName}"`
3839
+ });
3840
+ return res.data.values?.some(
3841
+ (res2) => res2.repository?.full_name === fullRepoName
3842
+ ) ?? false;
3843
+ },
3844
+ async createPullRequest(params2) {
3845
+ const { repoSlug, workspace } = parseBitbucketOrganizationAndRepo(
3846
+ params2.repoUrl
3847
+ );
3848
+ const res = await bitbucketClient.pullrequests.create({
3849
+ repo_slug: repoSlug,
3850
+ workspace,
3851
+ _body: {
3852
+ type: "pullrequest",
3853
+ title: params2.title,
3854
+ summary: {
3855
+ raw: params2.body
3856
+ },
3857
+ source: {
3858
+ branch: {
3859
+ name: params2.sourceBranchName
3860
+ }
3861
+ },
3862
+ destination: {
3863
+ branch: {
3864
+ name: params2.targetBranchName
3865
+ }
3866
+ }
3373
3867
  }
3868
+ });
3869
+ return res.data;
3870
+ },
3871
+ async getDownloadlink(params2) {
3872
+ const { repoSlug, workspace } = parseBitbucketOrganizationAndRepo(
3873
+ params2.repoUrl
3874
+ );
3875
+ const res = await bitbucketClient.downloads.list({
3876
+ repo_slug: repoSlug,
3877
+ workspace
3878
+ });
3879
+ return res.data;
3880
+ },
3881
+ async getBranch(params2) {
3882
+ const { repoSlug, workspace } = parseBitbucketOrganizationAndRepo(
3883
+ params2.repoUrl
3884
+ );
3885
+ const res = await bitbucketClient.refs.getBranch({
3886
+ name: params2.branchName,
3887
+ repo_slug: repoSlug,
3888
+ workspace
3889
+ });
3890
+ return res.data;
3891
+ },
3892
+ async getRepo(params2) {
3893
+ const { repoSlug, workspace } = parseBitbucketOrganizationAndRepo(
3894
+ params2.repoUrl
3895
+ );
3896
+ const res = await bitbucketClient.repositories.get({
3897
+ repo_slug: repoSlug,
3898
+ workspace
3899
+ });
3900
+ return res.data;
3901
+ },
3902
+ async getCommit(params2) {
3903
+ const { repoSlug, workspace } = parseBitbucketOrganizationAndRepo(
3904
+ params2.repoUrl
3905
+ );
3906
+ const res = await bitbucketClient.commits.get({
3907
+ commit: params2.commitSha,
3908
+ repo_slug: repoSlug,
3909
+ workspace
3910
+ });
3911
+ return res.data;
3912
+ },
3913
+ async getUser() {
3914
+ const res = await bitbucketClient.user.get({});
3915
+ return res.data;
3916
+ },
3917
+ async getReferenceData({
3918
+ ref,
3919
+ url
3920
+ }) {
3921
+ try {
3922
+ return await Promise.any([
3923
+ this.getBranchRef({ repoUrl: url, branchName: ref }),
3924
+ this.getTagRef({ repoUrl: url, tagName: ref }),
3925
+ this.getCommitRef({ repoUrl: url, commitSha: ref })
3926
+ ]);
3374
3927
  } catch (e) {
3928
+ console.log("e", e);
3929
+ if (e instanceof AggregateError) {
3930
+ throw new RefNotFoundError(`Invalid reference ${ref} for ${url}`);
3931
+ }
3932
+ throw e;
3375
3933
  }
3376
- const commitRes2 = await git.getCommits(
3377
- repo,
3378
- {
3379
- fromCommitId: objectId,
3380
- toCommitId: objectId,
3381
- $top: 1
3382
- },
3383
- projectName
3934
+ },
3935
+ async getTagRef(params2) {
3936
+ const { tagName, repoUrl } = params2;
3937
+ const { repoSlug, workspace } = parseBitbucketOrganizationAndRepo(repoUrl);
3938
+ const tagRes = await bitbucketClient.refs.getTag({
3939
+ repo_slug: repoSlug,
3940
+ workspace,
3941
+ name: tagName
3942
+ });
3943
+ return GetRefererenceResultZ.parse({
3944
+ sha: tagRes.data.target?.hash,
3945
+ type: "TAG" /* TAG */,
3946
+ date: new Date(z10.string().parse(tagRes.data.target?.date))
3947
+ });
3948
+ },
3949
+ async getBranchRef(params2) {
3950
+ const getBranchRes = await this.getBranch(params2);
3951
+ return GetRefererenceResultZ.parse({
3952
+ sha: getBranchRes.target?.hash,
3953
+ type: "BRANCH" /* BRANCH */,
3954
+ date: new Date(z10.string().parse(getBranchRes.target?.date))
3955
+ });
3956
+ },
3957
+ async getCommitRef(params2) {
3958
+ const getCommitRes = await this.getCommit(params2);
3959
+ return GetRefererenceResultZ.parse({
3960
+ sha: getCommitRes.hash,
3961
+ type: "COMMIT" /* COMMIT */,
3962
+ date: new Date(z10.string().parse(getCommitRes.date))
3963
+ });
3964
+ },
3965
+ async getDownloadUrl({ url, sha }) {
3966
+ this.getReferenceData({ ref: sha, url });
3967
+ const repoRes = await this.getRepo({ repoUrl: url });
3968
+ const parsedRepoUrl = z10.string().url().parse(repoRes.links?.html?.href);
3969
+ return `${parsedRepoUrl}/get/${sha}.zip`;
3970
+ },
3971
+ async getPullRequest(params2) {
3972
+ const { repoSlug, workspace } = parseBitbucketOrganizationAndRepo(
3973
+ params2.url
3384
3974
  );
3385
- const commit = commitRes2[0];
3386
- if (!commit) {
3387
- throw new Error("no commit");
3975
+ const res = await bitbucketClient.pullrequests.get({
3976
+ pull_request_id: params2.prNumber,
3977
+ repo_slug: repoSlug,
3978
+ workspace
3979
+ });
3980
+ return res.data;
3981
+ }
3982
+ };
3983
+ }
3984
+ async function validateBitbucketParams(params) {
3985
+ const { bitbucketClient } = params;
3986
+ const authType = bitbucketClient.getAuthType();
3987
+ console.log("authType", authType, params.url);
3988
+ try {
3989
+ if (authType !== "public") {
3990
+ await bitbucketClient.getUser();
3991
+ }
3992
+ if (params.url) {
3993
+ await bitbucketClient.getRepo({ repoUrl: params.url });
3994
+ }
3995
+ } catch (e) {
3996
+ const safeParseError = TokenExpiredErrorZ.safeParse(e);
3997
+ if (safeParseError.success) {
3998
+ switch (safeParseError.data.status) {
3999
+ case 401:
4000
+ throw new InvalidAccessTokenError(
4001
+ safeParseError.data.error.error.message
4002
+ );
4003
+ case 404:
4004
+ throw new InvalidRepoUrlError(safeParseError.data.error.error.message);
3388
4005
  }
3389
- return {
3390
- sha: objectId,
3391
- type: "TAG" /* TAG */,
3392
- date: commit.committer?.date || /* @__PURE__ */ new Date()
3393
- };
3394
- })()
3395
- ]);
3396
- const [branchRes, commitRes, tagRes] = results;
3397
- if (tagRes.status === "fulfilled") {
3398
- return tagRes.value;
3399
- }
3400
- if (branchRes.status === "fulfilled") {
3401
- return branchRes.value;
3402
- }
3403
- if (commitRes.status === "fulfilled") {
3404
- return commitRes.value;
4006
+ }
4007
+ throw e;
3405
4008
  }
3406
- throw new RefNotFoundError(`ref: ${ref} does not exist`);
3407
4009
  }
3408
- function parseAdoOwnerAndRepo(adoUrl) {
3409
- adoUrl = removeTrailingSlash3(adoUrl);
3410
- const parsingResult = parseScmURL(adoUrl, "Ado" /* Ado */);
3411
- if (!parsingResult || parsingResult.hostname !== "dev.azure.com" && !parsingResult.hostname.endsWith(".visualstudio.com")) {
3412
- throw new InvalidUrlPatternError(`invalid ADO repo URL: ${adoUrl}`);
4010
+ async function getUsersworkspacesSlugs(bitbucketClient) {
4011
+ const res = await bitbucketClient.workspaces.getWorkspaces({});
4012
+ return res.data.values?.map((v) => z10.string().parse(v.slug));
4013
+ }
4014
+ async function getllUsersrepositories(bitbucketClient) {
4015
+ const userWorspacesSlugs = await getUsersworkspacesSlugs(bitbucketClient);
4016
+ if (!userWorspacesSlugs) {
4017
+ return [];
3413
4018
  }
3414
- const { organization, repoName, projectName, projectPath, pathElements } = parsingResult;
3415
- return {
3416
- owner: organization,
3417
- repo: repoName,
3418
- projectName,
3419
- projectPath,
3420
- pathElements
3421
- };
4019
+ const allWorkspaceRepos = [];
4020
+ for (const workspaceSlug of userWorspacesSlugs) {
4021
+ const repos = await bitbucketClient.repositories.list({
4022
+ workspace: workspaceSlug
4023
+ });
4024
+ if (!repos.data.values) {
4025
+ continue;
4026
+ }
4027
+ allWorkspaceRepos.push(...repos.data.values);
4028
+ }
4029
+ return allWorkspaceRepos;
3422
4030
  }
3423
- async function getAdoBlameRanges() {
3424
- return [];
4031
+ async function getRepositoriesByWorkspace(bitbucketClient, { workspaceSlug }) {
4032
+ const res = await bitbucketClient.repositories.list({
4033
+ workspace: workspaceSlug
4034
+ });
4035
+ return res.data.values ?? [];
3425
4036
  }
3426
- var AdoAuthResultZ = z9.object({
3427
- access_token: z9.string().min(1),
3428
- token_type: z9.string().min(1),
3429
- refresh_token: z9.string().min(1)
3430
- });
3431
4037
 
3432
4038
  // src/features/analysis/scm/constants.ts
3433
4039
  var MOBB_ICON_IMG = "https://app.mobb.ai/gh-action/Logo_Rounded_Icon.svg";
3434
4040
  var COMMIT_FIX_SVG = `https://app.mobb.ai/gh-action/commit-button.svg`;
3435
4041
 
3436
- // src/features/analysis/scm/utils/get_issue_type.ts
3437
- var getIssueType = (issueType) => {
3438
- switch (issueType) {
3439
- case "SQL_Injection" /* SqlInjection */:
3440
- return "SQL Injection";
3441
- case "CMDi_relative_path_command" /* CmDiRelativePathCommand */:
3442
- return "Relative Path Command Injection";
3443
- case "CMDi" /* CmDi */:
3444
- return "Command Injection";
3445
- case "XXE" /* Xxe */:
3446
- return "XXE";
3447
- case "XSS" /* Xss */:
3448
- return "XSS";
3449
- case "PT" /* Pt */:
3450
- return "Path Traversal";
3451
- case "ZIP_SLIP" /* ZipSlip */:
3452
- return "Zip Slip";
3453
- case "INSECURE_RANDOMNESS" /* InsecureRandomness */:
3454
- return "Insecure Randomness";
3455
- case "SSRF" /* Ssrf */:
3456
- return "Server Side Request Forgery";
3457
- case "TYPE_CONFUSION" /* TypeConfusion */:
3458
- return "Type Confusion";
3459
- case "REGEX_INJECTION" /* RegexInjection */:
3460
- return "Regular Expression Injection";
3461
- case "INCOMPLETE_URL_SANITIZATION" /* IncompleteUrlSanitization */:
3462
- return "Incomplete URL Sanitization";
3463
- case "LOG_FORGING" /* LogForging */:
3464
- return "Log Forging";
3465
- case "LOCALE_DEPENDENT_COMPARISON" /* LocaleDependentComparison */:
3466
- return "Locale Dependent Comparison";
3467
- case "MISSING_CHECK_AGAINST_NULL" /* MissingCheckAgainstNull */:
3468
- return "Missing Check against Null";
3469
- case "PASSWORD_IN_COMMENT" /* PasswordInComment */:
3470
- return "Password in Comment";
3471
- case "OVERLY_BROAD_CATCH" /* OverlyBroadCatch */:
3472
- return "Poor Error Handling: Overly Broad Catch";
3473
- case "USE_OF_SYSTEM_OUTPUT_STREAM" /* UseOfSystemOutputStream */:
3474
- return "Use of System.out/System.err";
3475
- case "DANGEROUS_FUNCTION_OVERFLOW" /* DangerousFunctionOverflow */:
3476
- return "Use of dangerous function";
3477
- case "DOS_STRING_BUILDER" /* DosStringBuilder */:
3478
- return "Denial of Service: StringBuilder";
3479
- case "OPEN_REDIRECT" /* OpenRedirect */:
3480
- return "Open Redirect";
3481
- case "WEAK_XML_SCHEMA_UNBOUNDED_OCCURRENCES" /* WeakXmlSchemaUnboundedOccurrences */:
3482
- return "Weak XML Schema: Unbounded Occurrences";
3483
- case "SYSTEM_INFORMATION_LEAK" /* SystemInformationLeak */:
3484
- return "System Information Leak";
3485
- case "HTTP_RESPONSE_SPLITTING" /* HttpResponseSplitting */:
3486
- return "HTTP response splitting";
3487
- case "HTTP_ONLY_COOKIE" /* HttpOnlyCookie */:
3488
- return "Cookie is not HttpOnly";
3489
- case "INSECURE_COOKIE" /* InsecureCookie */:
3490
- return "Insecure Cookie";
3491
- case "TRUST_BOUNDARY_VIOLATION" /* TrustBoundaryViolation */:
3492
- return "Trust Boundary Violation";
3493
- case "MISSING_EQUALS_OR_HASHCODE" /* MissingEqualsOrHashcode */:
3494
- return "Missing equals or hashcode method";
3495
- default: {
3496
- return issueType ? issueType.replaceAll("_", " ") : "Other";
3497
- }
3498
- }
3499
- };
3500
-
3501
- // src/features/analysis/scm/utils/index.ts
3502
- function getFixUrlWithRedirect(params) {
3503
- const {
3504
- fixId,
3505
- projectId,
3506
- organizationId,
3507
- analysisId,
3508
- redirectUrl,
3509
- appBaseUrl,
3510
- commentId
3511
- } = params;
3512
- const searchParams = new URLSearchParams();
3513
- searchParams.append("commit_redirect_url", redirectUrl);
3514
- searchParams.append("comment_id", commentId.toString());
3515
- return `${getFixUrl({
3516
- appBaseUrl,
3517
- fixId,
3518
- projectId,
3519
- organizationId,
3520
- analysisId
3521
- })}?${searchParams.toString()}`;
3522
- }
3523
- function getFixUrl({
3524
- appBaseUrl,
3525
- fixId,
3526
- projectId,
3527
- organizationId,
3528
- analysisId
3529
- }) {
3530
- return `${appBaseUrl}/organization/${organizationId}/project/${projectId}/report/${analysisId}/fix/${fixId}`;
3531
- }
3532
- function getCommitUrl(params) {
3533
- const {
3534
- fixId,
3535
- projectId,
3536
- organizationId,
3537
- analysisId,
3538
- redirectUrl,
3539
- appBaseUrl,
3540
- commentId
3541
- } = params;
3542
- const searchParams = new URLSearchParams();
3543
- searchParams.append("redirect_url", redirectUrl);
3544
- searchParams.append("comment_id", commentId.toString());
3545
- return `${getFixUrl({
3546
- appBaseUrl,
3547
- fixId,
3548
- projectId,
3549
- organizationId,
3550
- analysisId
3551
- })}/commit?${searchParams.toString()}`;
3552
- }
3553
-
3554
4042
  // src/features/analysis/utils/by_key.ts
3555
4043
  function keyBy(array, keyBy2) {
3556
4044
  return array.reduce((acc, item) => {
@@ -3658,7 +4146,7 @@ async function getRelevantVulenrabilitiesFromDiff(params) {
3658
4146
  });
3659
4147
  const lineAddedRanges = calculateRanges(fileNumbers);
3660
4148
  const fileFilter = {
3661
- path: z10.string().parse(file.to),
4149
+ path: z11.string().parse(file.to),
3662
4150
  ranges: lineAddedRanges.map(([startLine, endLine]) => ({
3663
4151
  endLine,
3664
4152
  startLine
@@ -4456,9 +4944,7 @@ async function _scan(params, { skipPrompts = false } = {}) {
4456
4944
  apiKey: apiKey || config2.get("apiToken")
4457
4945
  });
4458
4946
  await handleMobbLogin();
4459
- const { projectId, organizationId } = await gqlClient.getOrgAndProjectId(
4460
- mobbProjectName
4461
- );
4947
+ const { projectId, organizationId } = await gqlClient.getOrgAndProjectId(mobbProjectName);
4462
4948
  const {
4463
4949
  uploadS3BucketInfo: { repoUploadInfo, reportUploadInfo }
4464
4950
  } = await gqlClient.uploadS3BucketInfo();
@@ -4521,6 +5007,7 @@ async function _scan(params, { skipPrompts = false } = {}) {
4521
5007
  });
4522
5008
  const reference = ref ?? await scm.getRepoDefaultBranch();
4523
5009
  const { sha } = await scm.getReferenceData(reference);
5010
+ const downloadUrl = await scm.getDownloadUrl(sha);
4524
5011
  debug10("org id %s", organizationId);
4525
5012
  debug10("project id %s", projectId);
4526
5013
  debug10("default branch %s", reference);
@@ -4529,7 +5016,7 @@ async function _scan(params, { skipPrompts = false } = {}) {
4529
5016
  dirname,
4530
5017
  ci,
4531
5018
  authHeaders: scm.getAuthHeaders(),
4532
- downloadUrl: scm.getDownloadUrl(sha)
5019
+ downloadUrl
4533
5020
  });
4534
5021
  if (command === "scan") {
4535
5022
  reportPath = await getReport(SupportedScannersZ.parse(scanner));
@@ -4556,7 +5043,7 @@ async function _scan(params, { skipPrompts = false } = {}) {
4556
5043
  spinner: mobbSpinner,
4557
5044
  submitVulnerabilityReportVariables: {
4558
5045
  fixReportId: reportUploadInfo.fixReportId,
4559
- repoUrl: z11.string().parse(repo),
5046
+ repoUrl: z12.string().parse(repo),
4560
5047
  reference,
4561
5048
  projectId,
4562
5049
  vulnerabilityReportFileName: "report.json",
@@ -4578,8 +5065,8 @@ async function _scan(params, { skipPrompts = false } = {}) {
4578
5065
  analysisId,
4579
5066
  gqlClient,
4580
5067
  scm,
4581
- githubActionToken: z11.string().parse(githubActionToken),
4582
- scanner: z11.nativeEnum(SCANNERS).parse(scanner)
5068
+ githubActionToken: z12.string().parse(githubActionToken),
5069
+ scanner: z12.nativeEnum(SCANNERS).parse(scanner)
4583
5070
  }),
4584
5071
  callbackStates: ["Finished" /* Finished */]
4585
5072
  });
@@ -4987,21 +5474,22 @@ var commitHashOption = {
4987
5474
  };
4988
5475
  var scmTypeOption = {
4989
5476
  demandOption: true,
4990
- describe: chalk5.bold("SCM type (GitHub, GitLab, Ado)"),
5477
+ describe: chalk5.bold("SCM type (GitHub, GitLab, Ado, Bitbucket)"),
4991
5478
  type: "string"
4992
5479
  };
4993
5480
  var urlOption = {
4994
5481
  describe: chalk5.bold(
4995
- "URL of the repository (used in GitHub, GitLab, Azure DevOps)"
5482
+ "URL of the repository (used in GitHub, GitLab, Azure DevOps, Bitbucket)"
4996
5483
  ),
4997
- type: "string"
5484
+ type: "string",
5485
+ demandOption: true
4998
5486
  };
4999
5487
  var scmOrgOption = {
5000
5488
  describe: chalk5.bold("Organization name in SCM (used in Azure DevOps)"),
5001
5489
  type: "string"
5002
5490
  };
5003
5491
  var scmUsernameOption = {
5004
- describe: chalk5.bold("Username in SCM (used in GitHub)"),
5492
+ describe: chalk5.bold("Username in SCM (used in GitHub, Bitbucket)"),
5005
5493
  type: "string"
5006
5494
  };
5007
5495
  var scmRefreshTokenOption = {
@@ -5010,13 +5498,14 @@ var scmRefreshTokenOption = {
5010
5498
  };
5011
5499
  var scmTokenOption = {
5012
5500
  describe: chalk5.bold("SCM API token"),
5013
- type: "string"
5501
+ type: "string",
5502
+ demandOption: true
5014
5503
  };
5015
5504
 
5016
5505
  // src/args/validation.ts
5017
5506
  import chalk6 from "chalk";
5018
5507
  import path8 from "path";
5019
- import { z as z12 } from "zod";
5508
+ import { z as z13 } from "zod";
5020
5509
  function throwRepoUrlErrorMessage({
5021
5510
  error,
5022
5511
  repoUrl,
@@ -5033,7 +5522,7 @@ Example:
5033
5522
  )}`;
5034
5523
  throw new CliError(formattedErrorMessage);
5035
5524
  }
5036
- var UrlZ = z12.string({
5525
+ var UrlZ = z13.string({
5037
5526
  invalid_type_error: "is not a valid GitHub / GitLab / ADO URL"
5038
5527
  }).refine((data) => !!sanityRepoURL(data), {
5039
5528
  message: "is not a valid GitHub / GitLab / ADO URL"
@@ -5181,6 +5670,7 @@ async function scanHandler(args) {
5181
5670
  }
5182
5671
 
5183
5672
  // src/args/commands/token.ts
5673
+ import { z as z14 } from "zod";
5184
5674
  function addScmTokenBuilder(args) {
5185
5675
  return args.option("scm-type", scmTypeOption).option("url", urlOption).option("token", scmTokenOption).option("organization", scmOrgOption).option("username", scmUsernameOption).option("refresh-token", scmRefreshTokenOption).option("api-key", apiKeyOption).example(
5186
5676
  "$0 add-scm-token --scm-type Ado --url https://dev.azure.com/adoorg/test/_git/repo --token abcdef0123456 --organization myOrg",
@@ -5188,22 +5678,36 @@ function addScmTokenBuilder(args) {
5188
5678
  ).help().demandOption(["url", "token"]);
5189
5679
  }
5190
5680
  function validateAddScmTokenOptions(argv) {
5191
- if (!argv.url) {
5192
- throw new CliError(errorMessages.missingUrl);
5193
- }
5194
- if (!argv.token) {
5195
- throw new CliError(errorMessages.missingToken);
5196
- }
5197
- if ("GitHub" /* GitHub */ !== argv.scmType && "Ado" /* Ado */ !== argv.scmType && "GitLab" /* GitLab */ !== argv.scmType) {
5681
+ if (!z14.nativeEnum(ScmType).safeParse(argv.scmType).success) {
5198
5682
  throw new CliError(
5199
- "\nError: --scm-type must reference a valid SCM type (GitHub, GitLab, Ado)"
5683
+ "\nError: --scm-type must reference a valid SCM type (GitHub, GitLab, Ado, Bitbutcket)"
5200
5684
  );
5201
5685
  }
5686
+ Object.values(scmValidationMap).forEach((validate) => validate(argv));
5687
+ }
5688
+ var scmValidationMap = {
5689
+ ["GitHub" /* GitHub */]: validateGithub,
5690
+ ["GitLab" /* GitLab */]: () => {
5691
+ return;
5692
+ },
5693
+ ["Ado" /* Ado */]: validateAdo,
5694
+ ["Bitbucket" /* Bitbucket */]: validateBitbucket
5695
+ };
5696
+ function validateBitbucket(argv) {
5697
+ const urlObj = new URL(argv.url);
5698
+ if (urlObj.hostname.toLowerCase() === scmCloudHostname.Bitbucket && !argv.username) {
5699
+ throw new CliError("\nError: --username flag is required for Bitbucket");
5700
+ }
5701
+ }
5702
+ function validateGithub(argv) {
5202
5703
  const urlObj = new URL(argv.url);
5203
- if (urlObj.hostname.toLowerCase() === "github.com" && !argv.username) {
5704
+ if (urlObj.hostname.toLowerCase() === scmCloudHostname.GitHub && !argv.username) {
5204
5705
  throw new CliError("\nError: --username flag is required for GitHub");
5205
5706
  }
5206
- if ((urlObj.hostname.toLowerCase() === "dev.azure.com" || urlObj.hostname.toLowerCase().endsWith(".visualstudio.com")) && !argv.organization) {
5707
+ }
5708
+ function validateAdo(argv) {
5709
+ const urlObj = new URL(argv.url);
5710
+ if ((urlObj.hostname.toLowerCase() === scmCloudHostname.Ado || urlObj.hostname.toLowerCase().endsWith(".visualstudio.com")) && !argv.organization) {
5207
5711
  throw new CliError(
5208
5712
  "\nError: --organization flag is required for Azure DevOps"
5209
5713
  );