mobbdev 0.0.143 → 0.0.148

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 +1131 -1088
  2. package/package.json +1 -1
package/dist/index.mjs CHANGED
@@ -528,16 +528,11 @@ import fetch4 from "node-fetch";
528
528
  import open2 from "open";
529
529
  import semver from "semver";
530
530
  import tmp2 from "tmp";
531
- import { z as z11 } from "zod";
531
+ import { z as z12 } from "zod";
532
532
 
533
533
  // src/features/analysis/add_fix_comments_for_pr/add_fix_comments_for_pr.ts
534
534
  import Debug4 from "debug";
535
535
 
536
- // src/features/analysis/scm/ado.ts
537
- import querystring from "node:querystring";
538
- import * as api from "azure-devops-node-api";
539
- import { z as z2 } from "zod";
540
-
541
536
  // src/features/analysis/scm/types.ts
542
537
  var ReferenceType = /* @__PURE__ */ ((ReferenceType2) => {
543
538
  ReferenceType2["BRANCH"] = "BRANCH";
@@ -566,6 +561,35 @@ var ScmType = /* @__PURE__ */ ((ScmType2) => {
566
561
  return ScmType2;
567
562
  })(ScmType || {});
568
563
 
564
+ // src/features/analysis/scm/ado/constants.ts
565
+ var DEFUALT_ADO_ORIGIN = scmCloudUrl.Ado;
566
+
567
+ // src/features/analysis/scm/ado/utils.ts
568
+ import querystring3 from "node:querystring";
569
+ import * as api from "azure-devops-node-api";
570
+ import { z as z9 } from "zod";
571
+
572
+ // src/features/analysis/scm/env.ts
573
+ import { z as z2 } from "zod";
574
+ var EnvVariablesZod = z2.object({
575
+ GITLAB_API_TOKEN: z2.string().optional(),
576
+ BROKERED_HOSTS: z2.string().toLowerCase().transform(
577
+ (x) => x.split(",").map((url) => url.trim(), []).filter(Boolean)
578
+ ).default(""),
579
+ GITHUB_API_TOKEN: z2.string().optional(),
580
+ GIT_PROXY_HOST: z2.string().default("http://tinyproxy:8888")
581
+ });
582
+ var { GITLAB_API_TOKEN, BROKERED_HOSTS, GITHUB_API_TOKEN, GIT_PROXY_HOST } = EnvVariablesZod.parse(process.env);
583
+
584
+ // src/features/analysis/scm/scm.ts
585
+ import { z as z7 } from "zod";
586
+
587
+ // src/features/analysis/scm/bitbucket/bitbucket.ts
588
+ import querystring from "node:querystring";
589
+ import bitbucketPkg from "bitbucket";
590
+ import * as bitbucketPkgNode from "bitbucket";
591
+ import { z as z3 } from "zod";
592
+
569
593
  // src/features/analysis/scm/urlParser.ts
570
594
  function detectAdoUrl(args) {
571
595
  const { pathname, hostname, scmType } = args;
@@ -588,19 +612,21 @@ function detectAdoUrl(args) {
588
612
  }
589
613
  }
590
614
  if (hostname === adoHostname || scmType === "Ado" /* Ado */) {
591
- if (pathname.length === 3 && pathname[1] === "_git") {
592
- return {
593
- organization: pathname[0],
594
- projectName: pathname[2],
595
- repoName: pathname[2]
596
- };
597
- }
598
- if (pathname.length === 4 && pathname[2] === "_git") {
599
- return {
600
- organization: pathname[0],
601
- projectName: pathname[1],
602
- repoName: pathname[3]
603
- };
615
+ if (pathname[pathname.length - 2] === "_git") {
616
+ if (pathname.length === 3) {
617
+ return {
618
+ organization: pathname[0],
619
+ projectName: pathname[2],
620
+ repoName: pathname[2]
621
+ };
622
+ }
623
+ if (pathname.length > 3) {
624
+ return {
625
+ organization: pathname[pathname.length - 4],
626
+ projectName: pathname[pathname.length - 3],
627
+ repoName: pathname[pathname.length - 1]
628
+ };
629
+ }
604
630
  }
605
631
  }
606
632
  return null;
@@ -710,509 +736,519 @@ var sanityRepoURL = (scmURL) => {
710
736
  }
711
737
  };
712
738
 
713
- // src/features/analysis/scm/ado.ts
714
- function removeTrailingSlash(str) {
715
- return str.trim().replace(/\/+$/, "");
716
- }
717
- async function _getOrgsForOauthToken({ oauthToken }) {
718
- const profileZ = z2.object({
719
- displayName: z2.string(),
720
- publicAlias: z2.string().min(1),
721
- emailAddress: z2.string(),
722
- coreRevision: z2.number(),
723
- timeStamp: z2.string(),
724
- id: z2.string(),
725
- revision: z2.number()
726
- });
727
- const accountsZ = z2.object({
728
- count: z2.number(),
729
- value: z2.array(
730
- z2.object({
731
- accountId: z2.string(),
732
- accountUri: z2.string(),
733
- accountName: z2.string()
734
- })
735
- )
736
- });
737
- const profileRes = await fetch(
738
- "https://app.vssps.visualstudio.com/_apis/profile/profiles/me?api-version=6.0",
739
- {
740
- method: "GET",
741
- headers: {
742
- Authorization: `Bearer ${oauthToken}`
743
- }
744
- }
745
- );
746
- const profileJson = await profileRes.json();
747
- const profile = profileZ.parse(profileJson);
748
- const accountsRes = await fetch(
749
- `https://app.vssps.visualstudio.com/_apis/accounts?memberId=${profile.publicAlias}&api-version=6.0`,
750
- {
751
- method: "GET",
752
- headers: {
753
- Authorization: `Bearer ${oauthToken}`
754
- }
739
+ // src/features/analysis/scm/utils/get_issue_type.ts
740
+ var getIssueType = (issueType) => {
741
+ switch (issueType) {
742
+ case "SQL_Injection" /* SqlInjection */:
743
+ return "SQL Injection";
744
+ case "CMDi_relative_path_command" /* CmDiRelativePathCommand */:
745
+ return "Relative Path Command Injection";
746
+ case "CMDi" /* CmDi */:
747
+ return "Command Injection";
748
+ case "XXE" /* Xxe */:
749
+ return "XXE";
750
+ case "XSS" /* Xss */:
751
+ return "XSS";
752
+ case "PT" /* Pt */:
753
+ return "Path Traversal";
754
+ case "ZIP_SLIP" /* ZipSlip */:
755
+ return "Zip Slip";
756
+ case "INSECURE_RANDOMNESS" /* InsecureRandomness */:
757
+ return "Insecure Randomness";
758
+ case "SSRF" /* Ssrf */:
759
+ return "Server Side Request Forgery";
760
+ case "TYPE_CONFUSION" /* TypeConfusion */:
761
+ return "Type Confusion";
762
+ case "REGEX_INJECTION" /* RegexInjection */:
763
+ return "Regular Expression Injection";
764
+ case "INCOMPLETE_URL_SANITIZATION" /* IncompleteUrlSanitization */:
765
+ return "Incomplete URL Sanitization";
766
+ case "LOCALE_DEPENDENT_COMPARISON" /* LocaleDependentComparison */:
767
+ return "Locale Dependent Comparison";
768
+ case "LOG_FORGING" /* LogForging */:
769
+ return "Log Forging";
770
+ case "MISSING_CHECK_AGAINST_NULL" /* MissingCheckAgainstNull */:
771
+ return "Missing Check against Null";
772
+ case "PASSWORD_IN_COMMENT" /* PasswordInComment */:
773
+ return "Password in Comment";
774
+ case "OVERLY_BROAD_CATCH" /* OverlyBroadCatch */:
775
+ return "Poor Error Handling: Overly Broad Catch";
776
+ case "USE_OF_SYSTEM_OUTPUT_STREAM" /* UseOfSystemOutputStream */:
777
+ return "Use of System.out/System.err";
778
+ case "DANGEROUS_FUNCTION_OVERFLOW" /* DangerousFunctionOverflow */:
779
+ return "Use of dangerous function";
780
+ case "DOS_STRING_BUILDER" /* DosStringBuilder */:
781
+ return "Denial of Service: StringBuilder";
782
+ case "OPEN_REDIRECT" /* OpenRedirect */:
783
+ return "Open Redirect";
784
+ case "WEAK_XML_SCHEMA_UNBOUNDED_OCCURRENCES" /* WeakXmlSchemaUnboundedOccurrences */:
785
+ return "Weak XML Schema: Unbounded Occurrences";
786
+ case "SYSTEM_INFORMATION_LEAK" /* SystemInformationLeak */:
787
+ return "System Information Leak";
788
+ case "SYSTEM_INFORMATION_LEAK_EXTERNAL" /* SystemInformationLeakExternal */:
789
+ return "External System Information Leak";
790
+ case "HTTP_RESPONSE_SPLITTING" /* HttpResponseSplitting */:
791
+ return "HTTP response splitting";
792
+ case "HTTP_ONLY_COOKIE" /* HttpOnlyCookie */:
793
+ return "Cookie is not HttpOnly";
794
+ case "INSECURE_COOKIE" /* InsecureCookie */:
795
+ return "Insecure Cookie";
796
+ case "TRUST_BOUNDARY_VIOLATION" /* TrustBoundaryViolation */:
797
+ return "Trust Boundary Violation";
798
+ case "NULL_DEREFERENCE" /* NullDereference */:
799
+ return "Null Dereference";
800
+ case "UNSAFE_DESERIALIZATION" /* UnsafeDeserialization */:
801
+ return "Unsafe deserialization";
802
+ case "INSECURE_BINDER_CONFIGURATION" /* InsecureBinderConfiguration */:
803
+ return "Insecure Binder Configuration";
804
+ case "UNSAFE_TARGET_BLANK" /* UnsafeTargetBlank */:
805
+ return "Unsafe use of target blank";
806
+ case "IFRAME_WITHOUT_SANDBOX" /* IframeWithoutSandbox */:
807
+ return "Client use of iframe without sandbox";
808
+ case "JQUERY_DEPRECATED_SYMBOLS" /* JqueryDeprecatedSymbols */:
809
+ return "jQuery deprecated symbols";
810
+ case "MISSING_ANTIFORGERY_VALIDATION" /* MissingAntiforgeryValidation */:
811
+ return "Missing Anti-Forgery Validation";
812
+ case "GRAPHQL_DEPTH_LIMIT" /* GraphqlDepthLimit */:
813
+ return "GraphQL Depth Limit";
814
+ case "UNCHECKED_LOOP_CONDITION" /* UncheckedLoopCondition */:
815
+ return "Unchecked Loop Condition";
816
+ case "IMPROPER_RESOURCE_SHUTDOWN_OR_RELEASE" /* ImproperResourceShutdownOrRelease */:
817
+ return "Improper Resource Shutdown or Release";
818
+ case "IMPROPER_EXCEPTION_HANDLING" /* ImproperExceptionHandling */:
819
+ return "Improper Exception Handling";
820
+ case "DEFAULT_RIGHTS_IN_OBJ_DEFINITION" /* DefaultRightsInObjDefinition */:
821
+ return "Default Definer Rights in Package or Object Definition";
822
+ case "HTML_COMMENT_IN_JSP" /* HtmlCommentInJsp */:
823
+ return "HTML Comment in JSP";
824
+ case "ERROR_CONDTION_WITHOUT_ACTION" /* ErrorCondtionWithoutAction */:
825
+ return "Error Condition Without Action";
826
+ case "DEPRECATED_FUNCTION" /* DeprecatedFunction */:
827
+ return "Deprecated Function";
828
+ case "HARDCODED_SECRETS" /* HardcodedSecrets */:
829
+ return "Hardcoded Secrets";
830
+ case "PROTOTYPE_POLLUTION" /* PrototypePollution */:
831
+ return "Prototype Pollution";
832
+ case "RACE_CONDITION_FORMAT_FLAW" /* RaceConditionFormatFlaw */:
833
+ return "Race Condition Format Flaw";
834
+ case "NON_FINAL_PUBLIC_STATIC_FIELD" /* NonFinalPublicStaticField */:
835
+ return "Non-final Public Static Field";
836
+ case "MISSING_HSTS_HEADER" /* MissingHstsHeader */:
837
+ return "Missing HSTS Header";
838
+ case "DEAD_CODE_UNUSED_FIELD" /* DeadCodeUnusedField */:
839
+ return "Dead Code: Unused Field";
840
+ case "HEADER_MANIPULATION" /* HeaderManipulation */:
841
+ return "Header Manipulation";
842
+ case "MISSING_EQUALS_OR_HASHCODE" /* MissingEqualsOrHashcode */:
843
+ return "Missing equals or hashcode method";
844
+ case "WCF_MISCONFIGURATION_INSUFFICIENT_LOGGING" /* WcfMisconfigurationInsufficientLogging */:
845
+ return "WCF Misconfiguration: Insufficient Logging";
846
+ case "WCF_MISCONFIGURATION_THROTTLING_NOT_ENABLED" /* WcfMisconfigurationThrottlingNotEnabled */:
847
+ return "WCF Misconfiguration: Throttling Not Enabled";
848
+ case "USELESS_REGEXP_CHAR_ESCAPE" /* UselessRegexpCharEscape */:
849
+ return "Useless regular-expression character escape";
850
+ case "INCOMPLETE_HOSTNAME_REGEX" /* IncompleteHostnameRegex */:
851
+ return "Incomplete Hostname Regex";
852
+ case "OVERLY_LARGE_RANGE" /* OverlyLargeRange */:
853
+ return "Regex: Overly Large Range";
854
+ case "INSUFFICIENT_LOGGING" /* InsufficientLogging */:
855
+ return "Insufficient Logging of Sensitive Operations";
856
+ case "PRIVACY_VIOLATION" /* PrivacyViolation */:
857
+ return "Privacy Violation";
858
+ case "INCOMPLETE_URL_SCHEME_CHECK" /* IncompleteUrlSchemeCheck */:
859
+ return "Incomplete URL Scheme Check";
860
+ case "VALUE_NEVER_READ" /* ValueNeverRead */:
861
+ return "Value Never Read";
862
+ case "VALUE_SHADOWING" /* ValueShadowing */:
863
+ return "Value Shadowing";
864
+ default: {
865
+ return issueType ? issueType.replaceAll("_", " ") : "Other";
755
866
  }
756
- );
757
- const accountsJson = await accountsRes.json();
758
- const accounts = accountsZ.parse(accountsJson);
759
- const orgs = accounts.value.map((account) => account.accountName).filter((value, index, array) => array.indexOf(value) === index);
760
- return orgs;
761
- }
762
- function _getPublicAdoClient({ orgName }) {
763
- const orgUrl = `https://dev.azure.com/${orgName}`;
764
- const authHandler = api.getPersonalAccessTokenHandler("");
765
- authHandler.canHandleAuthentication = () => false;
766
- authHandler.prepareRequest = (_options) => {
767
- return;
768
- };
769
- const connection = new api.WebApi(orgUrl, authHandler);
770
- return connection;
771
- }
772
- function getAdoTokenType(token) {
773
- if (token.includes(".")) {
774
- return "OAUTH" /* OAUTH */;
775
867
  }
776
- return "PAT" /* PAT */;
868
+ };
869
+
870
+ // src/features/analysis/scm/utils/index.ts
871
+ function getFixUrlWithRedirect(params) {
872
+ const {
873
+ fixId,
874
+ projectId,
875
+ organizationId,
876
+ analysisId,
877
+ redirectUrl,
878
+ appBaseUrl,
879
+ commentId
880
+ } = params;
881
+ const searchParams = new URLSearchParams();
882
+ searchParams.append("commit_redirect_url", redirectUrl);
883
+ searchParams.append("comment_id", commentId.toString());
884
+ return `${getFixUrl({
885
+ appBaseUrl,
886
+ fixId,
887
+ projectId,
888
+ organizationId,
889
+ analysisId
890
+ })}?${searchParams.toString()}`;
777
891
  }
778
- async function getAdoApiClient({
779
- accessToken,
780
- tokenOrg,
781
- orgName
892
+ function getFixUrl({
893
+ appBaseUrl,
894
+ fixId,
895
+ projectId,
896
+ organizationId,
897
+ analysisId
782
898
  }) {
783
- if (!accessToken || tokenOrg && tokenOrg !== orgName) {
784
- return _getPublicAdoClient({ orgName });
785
- }
786
- const orgUrl = `https://dev.azure.com/${orgName}`;
787
- if (getAdoTokenType(accessToken) === "OAUTH" /* OAUTH */) {
788
- const connection2 = new api.WebApi(orgUrl, api.getBearerHandler(accessToken));
789
- return connection2;
790
- }
791
- const authHandler = api.getPersonalAccessTokenHandler(accessToken);
792
- const connection = new api.WebApi(orgUrl, authHandler);
793
- return connection;
899
+ return `${appBaseUrl}/organization/${organizationId}/project/${projectId}/report/${analysisId}/fix/${fixId}`;
794
900
  }
795
- async function adoValidateParams({
796
- url,
797
- accessToken,
798
- tokenOrg
799
- }) {
800
- try {
801
- if (!url && accessToken && getAdoTokenType(accessToken) === "OAUTH" /* OAUTH */) {
802
- await _getOrgsForOauthToken({ oauthToken: accessToken });
803
- return;
804
- }
805
- let org = tokenOrg;
806
- if (url) {
807
- const { owner } = parseAdoOwnerAndRepo(url);
808
- org = owner;
809
- }
810
- if (!org) {
811
- throw new InvalidRepoUrlError(`invalid ADO ORG ${org}`);
812
- }
813
- const api2 = await getAdoApiClient({
814
- accessToken,
815
- tokenOrg,
816
- orgName: org
817
- });
818
- await api2.connect();
819
- } catch (e) {
820
- const error = e;
821
- const code = error.code || error.status || error.statusCode || error.response?.status || error.response?.statusCode || error.response?.code;
822
- const description = error.description || `${e}`;
823
- if (code === 401 || code === 403 || description.includes("401") || description.includes("403")) {
824
- throw new InvalidAccessTokenError(`invalid ADO access token`);
825
- }
826
- if (code === 404 || description.includes("404") || description.includes("Not Found")) {
827
- throw new InvalidRepoUrlError(`invalid ADO repo URL ${url}`);
828
- }
829
- throw e;
830
- }
831
- }
832
- async function getAdoIsUserCollaborator({
833
- accessToken,
834
- tokenOrg,
835
- repoUrl
836
- }) {
837
- try {
838
- const { owner, repo, projectName } = parseAdoOwnerAndRepo(repoUrl);
839
- const api2 = await getAdoApiClient({
840
- accessToken,
841
- tokenOrg,
842
- orgName: owner
843
- });
844
- const git = await api2.getGitApi();
845
- const branches = await git.getBranches(repo, projectName);
846
- if (!branches || branches.length === 0) {
847
- throw new InvalidRepoUrlError("no branches");
848
- }
849
- return true;
850
- } catch (e) {
851
- return false;
852
- }
853
- }
854
- var adoStatusNumberToEnumMap = {
855
- 1: "active" /* active */,
856
- 2: "abandoned" /* abandoned */,
857
- 3: "completed" /* completed */,
858
- 4: "all" /* all */
859
- };
860
- async function getAdoPullRequestStatus({
861
- accessToken,
862
- tokenOrg,
863
- repoUrl,
864
- prNumber
865
- }) {
866
- const { owner, repo, projectName } = parseAdoOwnerAndRepo(repoUrl);
867
- const api2 = await getAdoApiClient({
868
- accessToken,
869
- tokenOrg,
870
- orgName: owner
871
- });
872
- const git = await api2.getGitApi();
873
- const res = await git.getPullRequest(repo, prNumber, projectName);
874
- if (!res.status || res.status < 1 || res.status > 3) {
875
- throw new Error("bad pr status for ADO");
876
- }
877
- return adoStatusNumberToEnumMap[res.status];
901
+ function getCommitUrl(params) {
902
+ const {
903
+ fixId,
904
+ projectId,
905
+ organizationId,
906
+ analysisId,
907
+ redirectUrl,
908
+ appBaseUrl,
909
+ commentId
910
+ } = params;
911
+ const searchParams = new URLSearchParams();
912
+ searchParams.append("redirect_url", redirectUrl);
913
+ searchParams.append("comment_id", commentId.toString());
914
+ return `${getFixUrl({
915
+ appBaseUrl,
916
+ fixId,
917
+ projectId,
918
+ organizationId,
919
+ analysisId
920
+ })}/commit?${searchParams.toString()}`;
878
921
  }
879
- async function getAdoIsRemoteBranch({
880
- accessToken,
881
- tokenOrg,
882
- repoUrl,
883
- branch
884
- }) {
885
- const { owner, repo, projectName } = parseAdoOwnerAndRepo(repoUrl);
886
- const api2 = await getAdoApiClient({
887
- accessToken,
888
- tokenOrg,
889
- orgName: owner
890
- });
891
- const git = await api2.getGitApi();
892
- try {
893
- const branchStatus = await git.getBranch(repo, branch, projectName);
894
- if (!branchStatus || !branchStatus.commit) {
895
- throw new InvalidRepoUrlError("no branch status");
896
- }
897
- return branchStatus.name === branch;
898
- } catch (e) {
899
- return false;
922
+ var userNamePattern = /^(https?:\/\/)([^@]+@)?([^/]+\/.+)$/;
923
+ var sshPattern = /^git@([\w.-]+):([\w./-]+)$/;
924
+ function normalizeUrl(repoUrl) {
925
+ let trimmedUrl = repoUrl.trim().replace(/\/+$/, "");
926
+ if (repoUrl.endsWith(".git")) {
927
+ trimmedUrl = trimmedUrl.slice(0, -".git".length);
900
928
  }
901
- }
902
- async function getAdoRepoList({
903
- orgName,
904
- tokenOrg,
905
- accessToken
906
- }) {
907
- let orgs = [];
908
- if (getAdoTokenType(accessToken) === "OAUTH" /* OAUTH */) {
909
- orgs = await _getOrgsForOauthToken({ oauthToken: accessToken });
929
+ const usernameMatch = trimmedUrl.match(userNamePattern);
930
+ if (usernameMatch) {
931
+ const [_all, protocol, _username, repoPath] = usernameMatch;
932
+ trimmedUrl = `${protocol}${repoPath}`;
910
933
  }
911
- if (orgs.length === 0 && !orgName) {
912
- throw new Error(`no orgs for ADO`);
913
- } else if (orgs.length === 0 && orgName) {
914
- orgs = [orgName];
934
+ const sshMatch = trimmedUrl.match(sshPattern);
935
+ if (sshMatch) {
936
+ const [_all, hostname, reporPath] = sshMatch;
937
+ trimmedUrl = `https://${hostname}/${reporPath}`;
915
938
  }
916
- const repos = (await Promise.allSettled(
917
- orgs.map(async (org) => {
918
- const orgApi = await getAdoApiClient({
919
- accessToken,
920
- tokenOrg,
921
- orgName: org
922
- });
923
- const gitOrg = await orgApi.getGitApi();
924
- const orgRepos = await gitOrg.getRepositories();
925
- const repoInfoList = (await Promise.allSettled(
926
- orgRepos.map(async (repo) => {
927
- if (!repo.name || !repo.remoteUrl || !repo.defaultBranch) {
928
- throw new InvalidRepoUrlError("bad repo");
929
- }
930
- const branch = await gitOrg.getBranch(
931
- repo.name,
932
- repo.defaultBranch.replace(/^refs\/heads\//, ""),
933
- repo.project?.name
934
- );
935
- return {
936
- repoName: repo.name,
937
- repoUrl: repo.remoteUrl.replace(
938
- /^[hH][tT][tT][pP][sS]:\/\/[^/]+@/,
939
- "https://"
940
- ),
941
- repoOwner: org,
942
- repoIsPublic: repo.project?.visibility === 2,
943
- //2 is public in the ADO API
944
- repoLanguages: [],
945
- repoUpdatedAt: branch.commit?.committer?.date?.toDateString() || repo.project?.lastUpdateTime?.toDateString() || (/* @__PURE__ */ new Date()).toDateString()
946
- };
947
- })
948
- )).reduce((acc, res) => {
949
- if (res.status === "fulfilled") {
950
- acc.push(res.value);
951
- }
952
- return acc;
953
- }, []);
954
- return repoInfoList;
955
- })
956
- )).reduce((acc, res) => {
957
- if (res.status === "fulfilled") {
958
- return acc.concat(res.value);
959
- }
960
- return acc;
961
- }, []);
962
- return repos;
939
+ return trimmedUrl;
963
940
  }
964
- function getAdoPrUrl({
965
- url,
966
- prNumber
967
- }) {
968
- return `${url}/pullrequest/${prNumber}`;
941
+ var isUrlHasPath = (url) => {
942
+ return new URL(url).origin !== url;
943
+ };
944
+ function shouldValidateUrl(repoUrl) {
945
+ return repoUrl && isUrlHasPath(repoUrl);
969
946
  }
970
- function getAdoDownloadUrl({
971
- repoUrl,
972
- branch
973
- }) {
974
- const { owner, repo, projectName } = parseAdoOwnerAndRepo(repoUrl);
975
- const url = new URL(repoUrl);
976
- const origin = url.origin.toLowerCase().endsWith(".visualstudio.com") ? "https://dev.azure.com" : url.origin.toLowerCase();
977
- 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`;
947
+
948
+ // src/features/analysis/scm/bitbucket/bitbucket.ts
949
+ var BITBUCKET_HOSTNAME = "bitbucket.org";
950
+ var TokenExpiredErrorZ = z3.object({
951
+ status: z3.number(),
952
+ error: z3.object({
953
+ type: z3.string(),
954
+ error: z3.object({
955
+ message: z3.string()
956
+ })
957
+ })
958
+ });
959
+ var BITBUCKET_ACCESS_TOKEN_URL = `https://${BITBUCKET_HOSTNAME}/site/oauth2/access_token`;
960
+ var BitbucketAuthResultZ = z3.object({
961
+ access_token: z3.string(),
962
+ token_type: z3.string(),
963
+ refresh_token: z3.string()
964
+ });
965
+ var BitbucketParseResultZ = z3.object({
966
+ organization: z3.string(),
967
+ repoName: z3.string(),
968
+ hostname: z3.literal(BITBUCKET_HOSTNAME)
969
+ });
970
+ function parseBitbucketOrganizationAndRepo(bitbucketUrl) {
971
+ const parsedGitHubUrl = normalizeUrl(bitbucketUrl);
972
+ const parsingResult = parseScmURL(parsedGitHubUrl, "Bitbucket" /* Bitbucket */);
973
+ const validatedBitbucketResult = BitbucketParseResultZ.parse(parsingResult);
974
+ return {
975
+ workspace: validatedBitbucketResult.organization,
976
+ repoSlug: validatedBitbucketResult.repoName
977
+ };
978
978
  }
979
- async function getAdoBranchList({
980
- accessToken,
981
- tokenOrg,
982
- repoUrl
983
- }) {
984
- const { owner, repo, projectName } = parseAdoOwnerAndRepo(repoUrl);
985
- const api2 = await getAdoApiClient({
986
- accessToken,
987
- tokenOrg,
988
- orgName: owner
989
- });
990
- const git = await api2.getGitApi();
991
- try {
992
- const res = await git.getBranches(repo, projectName);
993
- res.sort((a, b) => {
994
- if (!a.commit?.committer?.date || !b.commit?.committer?.date) {
995
- return 0;
996
- }
997
- return b.commit?.committer?.date.getTime() - a.commit?.committer?.date.getTime();
998
- });
999
- return res.reduce((acc, branch) => {
1000
- if (!branch.name) {
1001
- return acc;
979
+ async function getBitbucketToken(params) {
980
+ const { bitbucketClientId, bitbucketClientSecret, authType } = params;
981
+ const res = await fetch(BITBUCKET_ACCESS_TOKEN_URL, {
982
+ method: "POST",
983
+ headers: {
984
+ "Content-Type": "application/x-www-form-urlencoded",
985
+ Authorization: "Basic " + btoa(`${bitbucketClientId}:${bitbucketClientSecret}`)
986
+ },
987
+ body: querystring.stringify(
988
+ authType === "refresh_token" ? {
989
+ grant_type: authType,
990
+ refresh_token: params.refreshToken
991
+ } : {
992
+ grant_type: authType,
993
+ code: params.code
1002
994
  }
1003
- acc.push(branch.name);
1004
- return acc;
1005
- }, []);
1006
- } catch (e) {
1007
- return [];
1008
- }
1009
- }
1010
- async function createAdoPullRequest(options) {
1011
- const { owner, repo, projectName } = parseAdoOwnerAndRepo(options.repoUrl);
1012
- const api2 = await getAdoApiClient({
1013
- accessToken: options.accessToken,
1014
- tokenOrg: options.tokenOrg,
1015
- orgName: owner
995
+ )
1016
996
  });
1017
- const git = await api2.getGitApi();
1018
- const res = await git.createPullRequest(
1019
- {
1020
- sourceRefName: `refs/heads/${options.sourceBranchName}`,
1021
- targetRefName: `refs/heads/${options.targetBranchName}`,
1022
- title: options.title,
1023
- description: options.body
1024
- },
1025
- repo,
1026
- projectName
1027
- );
1028
- return res.pullRequestId;
997
+ const authResult = await res.json();
998
+ return BitbucketAuthResultZ.parse(authResult);
1029
999
  }
1030
- async function getAdoRepoDefaultBranch({
1031
- repoUrl,
1032
- tokenOrg,
1033
- accessToken
1034
- }) {
1035
- const { owner, repo, projectName } = parseAdoOwnerAndRepo(repoUrl);
1036
- const api2 = await getAdoApiClient({
1037
- accessToken,
1038
- tokenOrg,
1039
- orgName: owner
1040
- });
1041
- const git = await api2.getGitApi();
1042
- const getRepositoryRes = await git.getRepository(
1043
- decodeURI(repo),
1044
- projectName ? decodeURI(projectName) : void 0
1045
- );
1046
- if (!getRepositoryRes?.defaultBranch) {
1047
- throw new InvalidRepoUrlError("no default branch");
1000
+ function getBitbucketIntance(params) {
1001
+ const BitbucketContstructor = bitbucketPkg && "Bitbucket" in bitbucketPkg ? bitbucketPkg.Bitbucket : bitbucketPkgNode.Bitbucket;
1002
+ switch (params.authType) {
1003
+ case "public":
1004
+ return new BitbucketContstructor();
1005
+ case "token":
1006
+ return new BitbucketContstructor({ auth: { token: params.token } });
1007
+ case "basic":
1008
+ return new BitbucketContstructor({
1009
+ auth: {
1010
+ password: params.password,
1011
+ username: params.username
1012
+ }
1013
+ });
1048
1014
  }
1049
- return getRepositoryRes.defaultBranch.replace("refs/heads/", "");
1050
1015
  }
1051
- async function getAdoReferenceData({
1052
- ref,
1053
- repoUrl,
1054
- accessToken,
1055
- tokenOrg
1056
- }) {
1057
- const { owner, repo, projectName } = parseAdoOwnerAndRepo(repoUrl);
1058
- const api2 = await getAdoApiClient({
1059
- accessToken,
1060
- tokenOrg,
1061
- orgName: owner
1062
- });
1063
- if (!projectName) {
1064
- throw new InvalidUrlPatternError("no project name");
1065
- }
1066
- const git = await api2.getGitApi();
1067
- const results = await Promise.allSettled([
1068
- (async () => {
1069
- const res = await git.getBranch(repo, ref, projectName);
1070
- if (!res.commit || !res.commit.commitId) {
1071
- throw new InvalidRepoUrlError("no commit on branch");
1072
- }
1073
- return {
1074
- sha: res.commit.commitId,
1075
- type: "BRANCH" /* BRANCH */,
1076
- date: res.commit.committer?.date || /* @__PURE__ */ new Date()
1077
- };
1078
- })(),
1079
- (async () => {
1080
- const res = await git.getCommits(
1081
- repo,
1082
- {
1083
- fromCommitId: ref,
1084
- toCommitId: ref,
1085
- $top: 1
1086
- },
1087
- projectName
1016
+ function getBitbucketSdk(params) {
1017
+ const bitbucketClient = getBitbucketIntance(params);
1018
+ return {
1019
+ getAuthType() {
1020
+ return params.authType;
1021
+ },
1022
+ async getRepos(params2) {
1023
+ const repoRes = params2?.workspaceSlug ? await getRepositoriesByWorkspace(bitbucketClient, {
1024
+ workspaceSlug: params2.workspaceSlug
1025
+ }) : await getllUsersrepositories(bitbucketClient);
1026
+ return repoRes.map((repo) => ({
1027
+ repoIsPublic: !repo.is_private,
1028
+ repoName: repo.name || "unknown repo name",
1029
+ repoOwner: repo.owner?.username || "unknown owner",
1030
+ // language can be empty string
1031
+ repoLanguages: repo.language ? [repo.language] : [],
1032
+ repoUpdatedAt: repo.updated_on ? repo.updated_on : (/* @__PURE__ */ new Date()).toISOString(),
1033
+ repoUrl: repo.links?.html?.href || ""
1034
+ }));
1035
+ },
1036
+ async getBranchList(params2) {
1037
+ const { workspace, repoSlug } = parseBitbucketOrganizationAndRepo(
1038
+ params2.repoUrl
1088
1039
  );
1089
- const commit = res[0];
1090
- if (!commit || !commit.commitId) {
1091
- throw new Error("no commit");
1092
- }
1093
- return {
1094
- sha: commit.commitId,
1095
- type: "COMMIT" /* COMMIT */,
1096
- date: commit.committer?.date || /* @__PURE__ */ new Date()
1097
- };
1098
- })(),
1099
- (async () => {
1100
- const res = await git.getRefs(repo, projectName, `tags/${ref}`);
1101
- if (!res[0] || !res[0].objectId) {
1102
- throw new Error("no tag ref");
1040
+ const res = await bitbucketClient.refs.listBranches({
1041
+ repo_slug: repoSlug,
1042
+ workspace
1043
+ });
1044
+ if (!res.data.values) {
1045
+ return [];
1103
1046
  }
1104
- let objectId = res[0].objectId;
1105
- try {
1106
- const tag = await git.getAnnotatedTag(projectName, repo, objectId);
1107
- if (tag.taggedObject?.objectId) {
1108
- objectId = tag.taggedObject.objectId;
1047
+ return res.data.values.filter((branch) => !!branch.name).map((branch) => z3.string().parse(branch.name));
1048
+ },
1049
+ async getIsUserCollaborator(params2) {
1050
+ const { repoUrl } = params2;
1051
+ const { repoSlug, workspace } = parseBitbucketOrganizationAndRepo(repoUrl);
1052
+ const fullRepoName = `${workspace}/${repoSlug}`;
1053
+ const res = await bitbucketClient.user.listPermissionsForRepos({
1054
+ q: `repository.full_name~"${fullRepoName}"`
1055
+ });
1056
+ return res.data.values?.some(
1057
+ (res2) => res2.repository?.full_name === fullRepoName
1058
+ ) ?? false;
1059
+ },
1060
+ async createPullRequest(params2) {
1061
+ const { repoSlug, workspace } = parseBitbucketOrganizationAndRepo(
1062
+ params2.repoUrl
1063
+ );
1064
+ const res = await bitbucketClient.pullrequests.create({
1065
+ repo_slug: repoSlug,
1066
+ workspace,
1067
+ _body: {
1068
+ type: "pullrequest",
1069
+ title: params2.title,
1070
+ summary: {
1071
+ raw: params2.body
1072
+ },
1073
+ source: {
1074
+ branch: {
1075
+ name: params2.sourceBranchName
1076
+ }
1077
+ },
1078
+ destination: {
1079
+ branch: {
1080
+ name: params2.targetBranchName
1081
+ }
1082
+ }
1109
1083
  }
1110
- } catch (e) {
1111
- }
1112
- const commitRes2 = await git.getCommits(
1113
- repo,
1114
- {
1115
- fromCommitId: objectId,
1116
- toCommitId: objectId,
1117
- $top: 1
1118
- },
1119
- projectName
1084
+ });
1085
+ return res.data;
1086
+ },
1087
+ async getDownloadlink(params2) {
1088
+ const { repoSlug, workspace } = parseBitbucketOrganizationAndRepo(
1089
+ params2.repoUrl
1120
1090
  );
1121
- const commit = commitRes2[0];
1122
- if (!commit) {
1123
- throw new Error("no commit");
1124
- }
1125
- return {
1126
- sha: objectId,
1091
+ const res = await bitbucketClient.downloads.list({
1092
+ repo_slug: repoSlug,
1093
+ workspace
1094
+ });
1095
+ return res.data;
1096
+ },
1097
+ async getBranch(params2) {
1098
+ const { repoSlug, workspace } = parseBitbucketOrganizationAndRepo(
1099
+ params2.repoUrl
1100
+ );
1101
+ const res = await bitbucketClient.refs.getBranch({
1102
+ name: params2.branchName,
1103
+ repo_slug: repoSlug,
1104
+ workspace
1105
+ });
1106
+ return res.data;
1107
+ },
1108
+ async getRepo(params2) {
1109
+ const { repoSlug, workspace } = parseBitbucketOrganizationAndRepo(
1110
+ params2.repoUrl
1111
+ );
1112
+ const res = await bitbucketClient.repositories.get({
1113
+ repo_slug: repoSlug,
1114
+ workspace
1115
+ });
1116
+ return res.data;
1117
+ },
1118
+ async getCommit(params2) {
1119
+ const { repoSlug, workspace } = parseBitbucketOrganizationAndRepo(
1120
+ params2.repoUrl
1121
+ );
1122
+ const res = await bitbucketClient.commits.get({
1123
+ commit: params2.commitSha,
1124
+ repo_slug: repoSlug,
1125
+ workspace
1126
+ });
1127
+ return res.data;
1128
+ },
1129
+ async getUser() {
1130
+ const res = await bitbucketClient.user.get({});
1131
+ return res.data;
1132
+ },
1133
+ async getReferenceData({
1134
+ ref,
1135
+ url
1136
+ }) {
1137
+ return Promise.allSettled([
1138
+ this.getTagRef({ repoUrl: url, tagName: ref }),
1139
+ this.getBranchRef({ repoUrl: url, branchName: ref }),
1140
+ this.getCommitRef({ repoUrl: url, commitSha: ref })
1141
+ ]).then((promisesResult) => {
1142
+ const [refPromise] = promisesResult.filter(
1143
+ (promise) => promise.status === "fulfilled"
1144
+ );
1145
+ if (!refPromise) {
1146
+ throw new RefNotFoundError(`Invalid reference ${ref} for ${url}`);
1147
+ }
1148
+ return refPromise.value;
1149
+ });
1150
+ },
1151
+ async getTagRef(params2) {
1152
+ const { tagName, repoUrl } = params2;
1153
+ const { repoSlug, workspace } = parseBitbucketOrganizationAndRepo(repoUrl);
1154
+ const tagRes = await bitbucketClient.refs.getTag({
1155
+ repo_slug: repoSlug,
1156
+ workspace,
1157
+ name: tagName
1158
+ });
1159
+ return GetRefererenceResultZ.parse({
1160
+ sha: tagRes.data.target?.hash,
1127
1161
  type: "TAG" /* TAG */,
1128
- date: commit.committer?.date || /* @__PURE__ */ new Date()
1129
- };
1130
- })()
1131
- ]);
1132
- const [branchRes, commitRes, tagRes] = results;
1133
- if (tagRes.status === "fulfilled") {
1134
- return tagRes.value;
1135
- }
1136
- if (branchRes.status === "fulfilled") {
1137
- return branchRes.value;
1138
- }
1139
- if (commitRes.status === "fulfilled") {
1140
- return commitRes.value;
1141
- }
1142
- throw new RefNotFoundError(`ref: ${ref} does not exist`);
1162
+ date: new Date(z3.string().parse(tagRes.data.target?.date))
1163
+ });
1164
+ },
1165
+ async getBranchRef(params2) {
1166
+ const getBranchRes = await this.getBranch(params2);
1167
+ return GetRefererenceResultZ.parse({
1168
+ sha: getBranchRes.target?.hash,
1169
+ type: "BRANCH" /* BRANCH */,
1170
+ date: new Date(z3.string().parse(getBranchRes.target?.date))
1171
+ });
1172
+ },
1173
+ async getCommitRef(params2) {
1174
+ const getCommitRes = await this.getCommit(params2);
1175
+ return GetRefererenceResultZ.parse({
1176
+ sha: getCommitRes.hash,
1177
+ type: "COMMIT" /* COMMIT */,
1178
+ date: new Date(z3.string().parse(getCommitRes.date))
1179
+ });
1180
+ },
1181
+ async getDownloadUrl({ url, sha }) {
1182
+ this.getReferenceData({ ref: sha, url });
1183
+ const repoRes = await this.getRepo({ repoUrl: url });
1184
+ const parsedRepoUrl = z3.string().url().parse(repoRes.links?.html?.href);
1185
+ return `${parsedRepoUrl}/get/${sha}.zip`;
1186
+ },
1187
+ async getPullRequest(params2) {
1188
+ const { repoSlug, workspace } = parseBitbucketOrganizationAndRepo(
1189
+ params2.url
1190
+ );
1191
+ const res = await bitbucketClient.pullrequests.get({
1192
+ pull_request_id: params2.prNumber,
1193
+ repo_slug: repoSlug,
1194
+ workspace
1195
+ });
1196
+ return res.data;
1197
+ }
1198
+ };
1143
1199
  }
1144
- function parseAdoOwnerAndRepo(adoUrl) {
1145
- adoUrl = removeTrailingSlash(adoUrl);
1146
- const parsingResult = parseScmURL(adoUrl, "Ado" /* Ado */);
1147
- if (!parsingResult || parsingResult.hostname !== "dev.azure.com" && !parsingResult.hostname.endsWith(".visualstudio.com")) {
1148
- throw new InvalidUrlPatternError(`invalid ADO repo URL: ${adoUrl}`);
1200
+ async function validateBitbucketParams(params) {
1201
+ const { bitbucketClient } = params;
1202
+ const authType = bitbucketClient.getAuthType();
1203
+ try {
1204
+ if (authType !== "public") {
1205
+ await bitbucketClient.getUser();
1206
+ }
1207
+ if (params.url && shouldValidateUrl(params.url)) {
1208
+ await bitbucketClient.getRepo({ repoUrl: params.url });
1209
+ }
1210
+ } catch (e) {
1211
+ const safeParseError = TokenExpiredErrorZ.safeParse(e);
1212
+ if (safeParseError.success) {
1213
+ switch (safeParseError.data.status) {
1214
+ case 401:
1215
+ throw new InvalidAccessTokenError(
1216
+ safeParseError.data.error.error.message
1217
+ );
1218
+ case 404:
1219
+ throw new InvalidRepoUrlError(safeParseError.data.error.error.message);
1220
+ }
1221
+ }
1222
+ throw e;
1149
1223
  }
1150
- const { organization, repoName, projectName, projectPath, pathElements } = parsingResult;
1151
- return {
1152
- owner: decodeURI(organization),
1153
- repo: decodeURI(repoName),
1154
- projectName: projectName ? decodeURI(projectName) : void 0,
1155
- projectPath,
1156
- pathElements
1157
- };
1158
1224
  }
1159
- async function getAdoBlameRanges() {
1160
- return [];
1225
+ async function getUsersworkspacesSlugs(bitbucketClient) {
1226
+ const res = await bitbucketClient.workspaces.getWorkspaces({});
1227
+ return res.data.values?.map((v) => z3.string().parse(v.slug));
1161
1228
  }
1162
- var ADO_ACCESS_TOKEN_URL = "https://app.vssps.visualstudio.com/oauth2/token";
1163
- var AdoAuthResultZ = z2.object({
1164
- access_token: z2.string().min(1),
1165
- token_type: z2.string().min(1),
1166
- refresh_token: z2.string().min(1)
1167
- });
1168
- async function getAdoToken({
1169
- token,
1170
- adoClientSecret,
1171
- tokenType,
1172
- redirectUri
1173
- }) {
1174
- const res = await fetch(ADO_ACCESS_TOKEN_URL, {
1175
- method: "POST",
1176
- headers: {
1177
- Accept: "application/json",
1178
- "Content-Type": "application/x-www-form-urlencoded"
1179
- },
1180
- body: querystring.stringify({
1181
- client_assertion_type: "urn:ietf:params:oauth:client-assertion-type:jwt-bearer",
1182
- client_assertion: adoClientSecret,
1183
- redirect_uri: redirectUri,
1184
- assertion: token,
1185
- grant_type: tokenType === "code" /* CODE */ ? "urn:ietf:params:oauth:grant-type:jwt-bearer" : "refresh_token"
1186
- })
1229
+ async function getllUsersrepositories(bitbucketClient) {
1230
+ const userWorspacesSlugs = await getUsersworkspacesSlugs(bitbucketClient);
1231
+ if (!userWorspacesSlugs) {
1232
+ return [];
1233
+ }
1234
+ const allWorkspaceRepos = [];
1235
+ for (const workspaceSlug of userWorspacesSlugs) {
1236
+ const repos = await bitbucketClient.repositories.list({
1237
+ workspace: workspaceSlug
1238
+ });
1239
+ if (!repos.data.values) {
1240
+ continue;
1241
+ }
1242
+ allWorkspaceRepos.push(...repos.data.values);
1243
+ }
1244
+ return allWorkspaceRepos;
1245
+ }
1246
+ async function getRepositoriesByWorkspace(bitbucketClient, { workspaceSlug }) {
1247
+ const res = await bitbucketClient.repositories.list({
1248
+ workspace: workspaceSlug
1187
1249
  });
1188
- const authResult = await res.json();
1189
- return AdoAuthResultZ.parse(authResult);
1190
- }
1191
- var AdoSdk = {
1192
- getAdoApiClient,
1193
- adoValidateParams,
1194
- getAdoIsUserCollaborator,
1195
- getAdoPullRequestStatus,
1196
- getAdoIsRemoteBranch,
1197
- getAdoRepoList,
1198
- getAdoDownloadUrl,
1199
- getAdoBranchList,
1200
- createAdoPullRequest,
1201
- getAdoRepoDefaultBranch,
1202
- getAdoReferenceData,
1203
- parseAdoOwnerAndRepo,
1204
- getAdoBlameRanges,
1205
- getAdoToken,
1206
- getAdoTokenType
1207
- };
1208
-
1209
- // src/features/analysis/scm/bitbucket/bitbucket.ts
1210
- import querystring3 from "node:querystring";
1211
- import * as bitbucketPkg from "bitbucket";
1212
- import { z as z8 } from "zod";
1213
-
1214
- // src/features/analysis/scm/scm.ts
1215
- import { z as z7 } from "zod";
1250
+ return res.data.values ?? [];
1251
+ }
1216
1252
 
1217
1253
  // src/features/analysis/scm/github/github.ts
1218
1254
  import { RequestError } from "@octokit/request-error";
@@ -1303,7 +1339,7 @@ function isGithubOnPrem(url) {
1303
1339
  function getFetch(url) {
1304
1340
  if (url && BROKERED_HOSTS.includes(new URL(url).origin)) {
1305
1341
  const dispatcher = new ProxyAgent({
1306
- uri: process.env["GIT_PROXY_HOST"] || "http://tinyproxy:8888",
1342
+ uri: GIT_PROXY_HOST,
1307
1343
  requestTls: {
1308
1344
  rejectUnauthorized: false
1309
1345
  }
@@ -1727,226 +1763,6 @@ import {
1727
1763
  } from "@gitbeaker/rest";
1728
1764
  import { ProxyAgent as ProxyAgent2 } from "undici";
1729
1765
 
1730
- // src/features/analysis/scm/env.ts
1731
- import { z as z3 } from "zod";
1732
- var EnvVariablesZod = z3.object({
1733
- GITLAB_API_TOKEN: z3.string().optional(),
1734
- BROKERED_HOSTS: z3.string().toLowerCase().transform(
1735
- (x) => x.split(",").map((url) => url.trim(), []).filter(Boolean)
1736
- ).default(""),
1737
- GITHUB_API_TOKEN: z3.string().optional()
1738
- });
1739
- var { GITLAB_API_TOKEN, BROKERED_HOSTS, GITHUB_API_TOKEN } = EnvVariablesZod.parse(process.env);
1740
-
1741
- // src/features/analysis/scm/utils/get_issue_type.ts
1742
- var getIssueType = (issueType) => {
1743
- switch (issueType) {
1744
- case "SQL_Injection" /* SqlInjection */:
1745
- return "SQL Injection";
1746
- case "CMDi_relative_path_command" /* CmDiRelativePathCommand */:
1747
- return "Relative Path Command Injection";
1748
- case "CMDi" /* CmDi */:
1749
- return "Command Injection";
1750
- case "XXE" /* Xxe */:
1751
- return "XXE";
1752
- case "XSS" /* Xss */:
1753
- return "XSS";
1754
- case "PT" /* Pt */:
1755
- return "Path Traversal";
1756
- case "ZIP_SLIP" /* ZipSlip */:
1757
- return "Zip Slip";
1758
- case "INSECURE_RANDOMNESS" /* InsecureRandomness */:
1759
- return "Insecure Randomness";
1760
- case "SSRF" /* Ssrf */:
1761
- return "Server Side Request Forgery";
1762
- case "TYPE_CONFUSION" /* TypeConfusion */:
1763
- return "Type Confusion";
1764
- case "REGEX_INJECTION" /* RegexInjection */:
1765
- return "Regular Expression Injection";
1766
- case "INCOMPLETE_URL_SANITIZATION" /* IncompleteUrlSanitization */:
1767
- return "Incomplete URL Sanitization";
1768
- case "LOCALE_DEPENDENT_COMPARISON" /* LocaleDependentComparison */:
1769
- return "Locale Dependent Comparison";
1770
- case "LOG_FORGING" /* LogForging */:
1771
- return "Log Forging";
1772
- case "MISSING_CHECK_AGAINST_NULL" /* MissingCheckAgainstNull */:
1773
- return "Missing Check against Null";
1774
- case "PASSWORD_IN_COMMENT" /* PasswordInComment */:
1775
- return "Password in Comment";
1776
- case "OVERLY_BROAD_CATCH" /* OverlyBroadCatch */:
1777
- return "Poor Error Handling: Overly Broad Catch";
1778
- case "USE_OF_SYSTEM_OUTPUT_STREAM" /* UseOfSystemOutputStream */:
1779
- return "Use of System.out/System.err";
1780
- case "DANGEROUS_FUNCTION_OVERFLOW" /* DangerousFunctionOverflow */:
1781
- return "Use of dangerous function";
1782
- case "DOS_STRING_BUILDER" /* DosStringBuilder */:
1783
- return "Denial of Service: StringBuilder";
1784
- case "OPEN_REDIRECT" /* OpenRedirect */:
1785
- return "Open Redirect";
1786
- case "WEAK_XML_SCHEMA_UNBOUNDED_OCCURRENCES" /* WeakXmlSchemaUnboundedOccurrences */:
1787
- return "Weak XML Schema: Unbounded Occurrences";
1788
- case "SYSTEM_INFORMATION_LEAK" /* SystemInformationLeak */:
1789
- return "System Information Leak";
1790
- case "SYSTEM_INFORMATION_LEAK_EXTERNAL" /* SystemInformationLeakExternal */:
1791
- return "External System Information Leak";
1792
- case "HTTP_RESPONSE_SPLITTING" /* HttpResponseSplitting */:
1793
- return "HTTP response splitting";
1794
- case "HTTP_ONLY_COOKIE" /* HttpOnlyCookie */:
1795
- return "Cookie is not HttpOnly";
1796
- case "INSECURE_COOKIE" /* InsecureCookie */:
1797
- return "Insecure Cookie";
1798
- case "TRUST_BOUNDARY_VIOLATION" /* TrustBoundaryViolation */:
1799
- return "Trust Boundary Violation";
1800
- case "NULL_DEREFERENCE" /* NullDereference */:
1801
- return "Null Dereference";
1802
- case "UNSAFE_DESERIALIZATION" /* UnsafeDeserialization */:
1803
- return "Unsafe deserialization";
1804
- case "INSECURE_BINDER_CONFIGURATION" /* InsecureBinderConfiguration */:
1805
- return "Insecure Binder Configuration";
1806
- case "UNSAFE_TARGET_BLANK" /* UnsafeTargetBlank */:
1807
- return "Unsafe use of target blank";
1808
- case "IFRAME_WITHOUT_SANDBOX" /* IframeWithoutSandbox */:
1809
- return "Client use of iframe without sandbox";
1810
- case "JQUERY_DEPRECATED_SYMBOLS" /* JqueryDeprecatedSymbols */:
1811
- return "jQuery deprecated symbols";
1812
- case "MISSING_ANTIFORGERY_VALIDATION" /* MissingAntiforgeryValidation */:
1813
- return "Missing Anti-Forgery Validation";
1814
- case "GRAPHQL_DEPTH_LIMIT" /* GraphqlDepthLimit */:
1815
- return "GraphQL Depth Limit";
1816
- case "UNCHECKED_LOOP_CONDITION" /* UncheckedLoopCondition */:
1817
- return "Unchecked Loop Condition";
1818
- case "IMPROPER_RESOURCE_SHUTDOWN_OR_RELEASE" /* ImproperResourceShutdownOrRelease */:
1819
- return "Improper Resource Shutdown or Release";
1820
- case "IMPROPER_EXCEPTION_HANDLING" /* ImproperExceptionHandling */:
1821
- return "Improper Exception Handling";
1822
- case "DEFAULT_RIGHTS_IN_OBJ_DEFINITION" /* DefaultRightsInObjDefinition */:
1823
- return "Default Definer Rights in Package or Object Definition";
1824
- case "HTML_COMMENT_IN_JSP" /* HtmlCommentInJsp */:
1825
- return "HTML Comment in JSP";
1826
- case "ERROR_CONDTION_WITHOUT_ACTION" /* ErrorCondtionWithoutAction */:
1827
- return "Error Condition Without Action";
1828
- case "DEPRECATED_FUNCTION" /* DeprecatedFunction */:
1829
- return "Deprecated Function";
1830
- case "HARDCODED_SECRETS" /* HardcodedSecrets */:
1831
- return "Hardcoded Secrets";
1832
- case "PROTOTYPE_POLLUTION" /* PrototypePollution */:
1833
- return "Prototype Pollution";
1834
- case "RACE_CONDITION_FORMAT_FLAW" /* RaceConditionFormatFlaw */:
1835
- return "Race Condition Format Flaw";
1836
- case "NON_FINAL_PUBLIC_STATIC_FIELD" /* NonFinalPublicStaticField */:
1837
- return "Non-final Public Static Field";
1838
- case "MISSING_HSTS_HEADER" /* MissingHstsHeader */:
1839
- return "Missing HSTS Header";
1840
- case "DEAD_CODE_UNUSED_FIELD" /* DeadCodeUnusedField */:
1841
- return "Dead Code: Unused Field";
1842
- case "HEADER_MANIPULATION" /* HeaderManipulation */:
1843
- return "Header Manipulation";
1844
- case "MISSING_EQUALS_OR_HASHCODE" /* MissingEqualsOrHashcode */:
1845
- return "Missing equals or hashcode method";
1846
- case "WCF_MISCONFIGURATION_INSUFFICIENT_LOGGING" /* WcfMisconfigurationInsufficientLogging */:
1847
- return "WCF Misconfiguration: Insufficient Logging";
1848
- case "WCF_MISCONFIGURATION_THROTTLING_NOT_ENABLED" /* WcfMisconfigurationThrottlingNotEnabled */:
1849
- return "WCF Misconfiguration: Throttling Not Enabled";
1850
- case "USELESS_REGEXP_CHAR_ESCAPE" /* UselessRegexpCharEscape */:
1851
- return "Useless regular-expression character escape";
1852
- case "INCOMPLETE_HOSTNAME_REGEX" /* IncompleteHostnameRegex */:
1853
- return "Incomplete Hostname Regex";
1854
- case "OVERLY_LARGE_RANGE" /* OverlyLargeRange */:
1855
- return "Regex: Overly Large Range";
1856
- case "INSUFFICIENT_LOGGING" /* InsufficientLogging */:
1857
- return "Insufficient Logging of Sensitive Operations";
1858
- case "PRIVACY_VIOLATION" /* PrivacyViolation */:
1859
- return "Privacy Violation";
1860
- case "INCOMPLETE_URL_SCHEME_CHECK" /* IncompleteUrlSchemeCheck */:
1861
- return "Incomplete URL Scheme Check";
1862
- case "VALUE_NEVER_READ" /* ValueNeverRead */:
1863
- return "Value Never Read";
1864
- case "VALUE_SHADOWING" /* ValueShadowing */:
1865
- return "Value Shadowing";
1866
- default: {
1867
- return issueType ? issueType.replaceAll("_", " ") : "Other";
1868
- }
1869
- }
1870
- };
1871
-
1872
- // src/features/analysis/scm/utils/index.ts
1873
- function getFixUrlWithRedirect(params) {
1874
- const {
1875
- fixId,
1876
- projectId,
1877
- organizationId,
1878
- analysisId,
1879
- redirectUrl,
1880
- appBaseUrl,
1881
- commentId
1882
- } = params;
1883
- const searchParams = new URLSearchParams();
1884
- searchParams.append("commit_redirect_url", redirectUrl);
1885
- searchParams.append("comment_id", commentId.toString());
1886
- return `${getFixUrl({
1887
- appBaseUrl,
1888
- fixId,
1889
- projectId,
1890
- organizationId,
1891
- analysisId
1892
- })}?${searchParams.toString()}`;
1893
- }
1894
- function getFixUrl({
1895
- appBaseUrl,
1896
- fixId,
1897
- projectId,
1898
- organizationId,
1899
- analysisId
1900
- }) {
1901
- return `${appBaseUrl}/organization/${organizationId}/project/${projectId}/report/${analysisId}/fix/${fixId}`;
1902
- }
1903
- function getCommitUrl(params) {
1904
- const {
1905
- fixId,
1906
- projectId,
1907
- organizationId,
1908
- analysisId,
1909
- redirectUrl,
1910
- appBaseUrl,
1911
- commentId
1912
- } = params;
1913
- const searchParams = new URLSearchParams();
1914
- searchParams.append("redirect_url", redirectUrl);
1915
- searchParams.append("comment_id", commentId.toString());
1916
- return `${getFixUrl({
1917
- appBaseUrl,
1918
- fixId,
1919
- projectId,
1920
- organizationId,
1921
- analysisId
1922
- })}/commit?${searchParams.toString()}`;
1923
- }
1924
- var userNamePattern = /^(https?:\/\/)([^@]+@)?([^/]+\/.+)$/;
1925
- var sshPattern = /^git@([\w.-]+):([\w./-]+)$/;
1926
- function normalizeUrl(repoUrl) {
1927
- let trimmedUrl = repoUrl.trim().replace(/\/+$/, "");
1928
- if (repoUrl.endsWith(".git")) {
1929
- trimmedUrl = trimmedUrl.slice(0, -".git".length);
1930
- }
1931
- const usernameMatch = trimmedUrl.match(userNamePattern);
1932
- if (usernameMatch) {
1933
- const [_all, protocol, _username, repoPath] = usernameMatch;
1934
- trimmedUrl = `${protocol}${repoPath}`;
1935
- }
1936
- const sshMatch = trimmedUrl.match(sshPattern);
1937
- if (sshMatch) {
1938
- const [_all, hostname, reporPath] = sshMatch;
1939
- trimmedUrl = `https://${hostname}/${reporPath}`;
1940
- }
1941
- return trimmedUrl;
1942
- }
1943
- var isUrlHasPath = (url) => {
1944
- return new URL(url).origin !== url;
1945
- };
1946
- function shouldValidateUrl(repoUrl) {
1947
- return repoUrl && isUrlHasPath(repoUrl);
1948
- }
1949
-
1950
1766
  // src/features/analysis/scm/gitlab/types.ts
1951
1767
  import { z as z4 } from "zod";
1952
1768
  var GitlabAuthResultZ = z4.object({
@@ -1956,7 +1772,7 @@ var GitlabAuthResultZ = z4.object({
1956
1772
  });
1957
1773
 
1958
1774
  // src/features/analysis/scm/gitlab/gitlab.ts
1959
- function removeTrailingSlash2(str) {
1775
+ function removeTrailingSlash(str) {
1960
1776
  return str.trim().replace(/\/+$/, "");
1961
1777
  }
1962
1778
  function getGitBeaker(options) {
@@ -2185,7 +2001,7 @@ async function getGitlabReferenceData({ ref, gitlabUrl }, options) {
2185
2001
  throw new RefNotFoundError(`ref: ${ref} does not exist`);
2186
2002
  }
2187
2003
  function parseGitlabOwnerAndRepo(gitlabUrl) {
2188
- gitlabUrl = removeTrailingSlash2(gitlabUrl);
2004
+ gitlabUrl = removeTrailingSlash(gitlabUrl);
2189
2005
  const parsingResult = parseScmURL(gitlabUrl, "GitLab" /* GitLab */);
2190
2006
  if (!parsingResult || !parsingResult.repoName) {
2191
2007
  throw new InvalidUrlPatternError(`invalid gitlab repo Url ${gitlabUrl}`);
@@ -2263,7 +2079,8 @@ var BaseSubmitToScmMessageZ = z5.object({
2263
2079
  })
2264
2080
  ),
2265
2081
  commitHash: z5.string(),
2266
- repoUrl: z5.string()
2082
+ repoUrl: z5.string(),
2083
+ extraHeaders: z5.record(z5.string(), z5.string()).default({})
2267
2084
  });
2268
2085
  var submitToScmMessageType = {
2269
2086
  commitToSameBranch: "commitToSameBranch",
@@ -2532,7 +2349,8 @@ var SCMLib = class {
2532
2349
  }
2533
2350
  const scmLibType = this.getScmLibType();
2534
2351
  if (scmLibType === "ADO" /* ADO */) {
2535
- return `https://${accessToken}@${trimmedUrl.toLowerCase().replace("https://", "")}`;
2352
+ const { host, protocol, pathname } = new URL(trimmedUrl);
2353
+ return `${protocol}//${accessToken}@${host}${pathname}`;
2536
2354
  }
2537
2355
  if (this instanceof BitbucketSCMLib) {
2538
2356
  const authData = this.getAuthData();
@@ -2580,7 +2398,7 @@ var SCMLib = class {
2580
2398
  }
2581
2399
  return this.url.split("/").at(-1) || "";
2582
2400
  }
2583
- _validateToken() {
2401
+ _validateAccessToken() {
2584
2402
  if (!this.accessToken) {
2585
2403
  console.error("no access token");
2586
2404
  throw new Error("no access token");
@@ -2626,14 +2444,12 @@ var SCMLib = class {
2626
2444
  scmLibScmTypeToScmType[z7.nativeEnum(ScmLibScmType).parse(scmType)]
2627
2445
  );
2628
2446
  }
2447
+ console.error(`error validating scm: ${scmType} `, e);
2629
2448
  }
2630
2449
  return new StubSCMLib(trimmedUrl, void 0, void 0);
2631
2450
  }
2632
2451
  _validateAccessTokenAndUrl() {
2633
- if (!this.accessToken) {
2634
- console.error("no access token");
2635
- throw new InvalidAccessTokenError("no access token");
2636
- }
2452
+ this._validateAccessToken();
2637
2453
  this._validateUrl();
2638
2454
  }
2639
2455
  _validateUrl() {
@@ -2643,45 +2459,65 @@ var SCMLib = class {
2643
2459
  }
2644
2460
  }
2645
2461
  };
2462
+ async function initAdoSdk(params) {
2463
+ const { url, accessToken, scmOrg } = params;
2464
+ const adoClientParams = await getAdoClientParams({
2465
+ tokenOrg: scmOrg,
2466
+ accessToken,
2467
+ url
2468
+ });
2469
+ return getAdoSdk(adoClientParams);
2470
+ }
2646
2471
  var AdoSCMLib = class extends SCMLib {
2472
+ constructor(url, accessToken, scmOrg) {
2473
+ super(url, accessToken, scmOrg);
2474
+ __publicField(this, "_adoSdkPromise");
2475
+ this._adoSdkPromise = initAdoSdk({ accessToken, url, scmOrg });
2476
+ }
2477
+ async getAdoSdk() {
2478
+ if (!this._adoSdkPromise) {
2479
+ console.error("ado sdk was not initialized");
2480
+ throw new InvalidAccessTokenError("ado sdk was not initialized");
2481
+ }
2482
+ return this._adoSdkPromise;
2483
+ }
2647
2484
  async createSubmitRequest(params) {
2648
2485
  this._validateAccessTokenAndUrl();
2649
2486
  const { targetBranchName, sourceBranchName, title, body } = params;
2650
- return String(
2651
- await AdoSdk.createAdoPullRequest({
2652
- title,
2653
- body,
2654
- targetBranchName,
2655
- sourceBranchName,
2656
- repoUrl: this.url,
2657
- accessToken: this.accessToken,
2658
- tokenOrg: this.scmOrg
2659
- })
2660
- );
2487
+ const adoSdk = await this.getAdoSdk();
2488
+ const pullRequestId = await adoSdk.createAdoPullRequest({
2489
+ title,
2490
+ body,
2491
+ targetBranchName,
2492
+ sourceBranchName,
2493
+ repoUrl: this.url
2494
+ });
2495
+ return String(pullRequestId);
2661
2496
  }
2662
2497
  async validateParams() {
2663
- return AdoSdk.adoValidateParams({
2498
+ return adoValidateParams({
2664
2499
  url: this.url,
2665
2500
  accessToken: this.accessToken,
2666
2501
  tokenOrg: this.scmOrg
2667
2502
  });
2668
2503
  }
2669
2504
  async getRepoList(scmOrg) {
2670
- if (!this.accessToken) {
2671
- console.error("no access token");
2672
- throw new Error("no access token");
2505
+ this._validateAccessToken();
2506
+ if (this.url && new URL(this.url).origin !== scmCloudUrl.Ado) {
2507
+ throw new Error(
2508
+ `Oauth token is not supported for ADO on prem - ${origin} `
2509
+ );
2673
2510
  }
2674
- return AdoSdk.getAdoRepoList({
2511
+ return getAdoRepoList({
2675
2512
  orgName: scmOrg,
2676
- tokenOrg: this.scmOrg,
2677
- accessToken: this.accessToken
2513
+ accessToken: this.accessToken,
2514
+ tokenOrg: this.scmOrg
2678
2515
  });
2679
2516
  }
2680
2517
  async getBranchList() {
2681
2518
  this._validateAccessTokenAndUrl();
2682
- return AdoSdk.getAdoBranchList({
2683
- accessToken: this.accessToken,
2684
- tokenOrg: this.scmOrg,
2519
+ const adoSdk = await this.getAdoSdk();
2520
+ return adoSdk.getAdoBranchList({
2685
2521
  repoUrl: this.url
2686
2522
  });
2687
2523
  }
@@ -2690,7 +2526,7 @@ var AdoSCMLib = class extends SCMLib {
2690
2526
  }
2691
2527
  getAuthHeaders() {
2692
2528
  if (this.accessToken) {
2693
- if (AdoSdk.getAdoTokenType(this.accessToken) === "OAUTH" /* OAUTH */) {
2529
+ if (getAdoTokenInfo(this.accessToken).type === "OAUTH") {
2694
2530
  return {
2695
2531
  authorization: `Bearer ${this.accessToken}`
2696
2532
  };
@@ -2704,29 +2540,26 @@ var AdoSCMLib = class extends SCMLib {
2704
2540
  }
2705
2541
  return {};
2706
2542
  }
2707
- getDownloadUrl(sha) {
2543
+ async getDownloadUrl(sha) {
2708
2544
  this._validateUrl();
2709
- return Promise.resolve(
2710
- AdoSdk.getAdoDownloadUrl({ repoUrl: this.url, branch: sha })
2711
- );
2545
+ const adoSdk = await this.getAdoSdk();
2546
+ return adoSdk.getAdoDownloadUrl({ repoUrl: this.url, branch: sha });
2712
2547
  }
2713
2548
  async _getUsernameForAuthUrl() {
2714
2549
  throw new Error("_getUsernameForAuthUrl() is not relevant for ADO");
2715
2550
  }
2716
2551
  async getIsRemoteBranch(branch) {
2717
2552
  this._validateAccessTokenAndUrl();
2718
- return AdoSdk.getAdoIsRemoteBranch({
2719
- accessToken: this.accessToken,
2720
- tokenOrg: this.scmOrg,
2553
+ const adoSdk = await this.getAdoSdk();
2554
+ return adoSdk.getAdoIsRemoteBranch({
2721
2555
  repoUrl: this.url,
2722
2556
  branch
2723
2557
  });
2724
2558
  }
2725
2559
  async getUserHasAccessToRepo() {
2726
2560
  this._validateAccessTokenAndUrl();
2727
- return AdoSdk.getAdoIsUserCollaborator({
2728
- accessToken: this.accessToken,
2729
- tokenOrg: this.scmOrg,
2561
+ const adoSdk = await this.getAdoSdk();
2562
+ return adoSdk.getAdoIsUserCollaborator({
2730
2563
  repoUrl: this.url
2731
2564
  });
2732
2565
  }
@@ -2735,46 +2568,48 @@ var AdoSCMLib = class extends SCMLib {
2735
2568
  }
2736
2569
  async getSubmitRequestStatus(scmSubmitRequestId) {
2737
2570
  this._validateAccessTokenAndUrl();
2738
- const state = await AdoSdk.getAdoPullRequestStatus({
2739
- accessToken: this.accessToken,
2740
- tokenOrg: this.scmOrg,
2571
+ const adoSdk = await this.getAdoSdk();
2572
+ const state = await adoSdk.getAdoPullRequestStatus({
2741
2573
  repoUrl: this.url,
2742
2574
  prNumber: Number(scmSubmitRequestId)
2743
2575
  });
2744
2576
  switch (state) {
2745
- case "completed" /* completed */:
2577
+ case 3 /* Completed */:
2746
2578
  return "merged";
2747
- case "active" /* active */:
2579
+ case 1 /* Active */:
2748
2580
  return "open";
2749
- case "abandoned" /* abandoned */:
2581
+ case 2 /* Abandoned */:
2750
2582
  return "closed";
2751
2583
  default:
2752
2584
  throw new Error(`unknown state ${state}`);
2753
2585
  }
2754
2586
  }
2755
2587
  async getRepoBlameRanges(_ref, _path) {
2756
- return await AdoSdk.getAdoBlameRanges();
2588
+ const adoSdk = await this.getAdoSdk();
2589
+ return await adoSdk.getAdoBlameRanges();
2757
2590
  }
2758
2591
  async getReferenceData(ref) {
2759
2592
  this._validateUrl();
2760
- return await AdoSdk.getAdoReferenceData({
2593
+ const adoSdk = await this.getAdoSdk();
2594
+ return await adoSdk.getAdoReferenceData({
2761
2595
  ref,
2762
- repoUrl: this.url,
2763
- accessToken: this.accessToken,
2764
- tokenOrg: this.scmOrg
2596
+ repoUrl: this.url
2765
2597
  });
2766
2598
  }
2767
2599
  async getRepoDefaultBranch() {
2768
2600
  this._validateUrl();
2769
- return await AdoSdk.getAdoRepoDefaultBranch({
2770
- repoUrl: this.url,
2771
- tokenOrg: this.scmOrg,
2772
- accessToken: this.accessToken
2601
+ const adoSdk = await this.getAdoSdk();
2602
+ return await adoSdk.getAdoRepoDefaultBranch({
2603
+ repoUrl: this.url
2773
2604
  });
2774
2605
  }
2775
- getPrUrl(prNumber) {
2776
- this._validateAccessTokenAndUrl();
2777
- return Promise.resolve(getAdoPrUrl({ prNumber, url: this.url }));
2606
+ async getPrUrl(prNumber) {
2607
+ this._validateUrl();
2608
+ const adoSdk = await this.getAdoSdk();
2609
+ return adoSdk.getAdoPrUrl({
2610
+ url: this.url,
2611
+ prNumber
2612
+ });
2778
2613
  }
2779
2614
  };
2780
2615
  var GitlabSCMLib = class extends SCMLib {
@@ -2937,7 +2772,7 @@ var GithubSCMLib = class extends SCMLib {
2937
2772
  return String(pullRequestResult.data.number);
2938
2773
  }
2939
2774
  async forkRepo(repoUrl) {
2940
- this._validateToken();
2775
+ this._validateAccessToken();
2941
2776
  return this.githubSdk.forkRepo({
2942
2777
  repoUrl
2943
2778
  });
@@ -3017,7 +2852,7 @@ var GithubSCMLib = class extends SCMLib {
3017
2852
  return z7.string().parse(prRes.data);
3018
2853
  }
3019
2854
  async getRepoList(_scmOrg) {
3020
- this._validateToken();
2855
+ this._validateAccessToken();
3021
2856
  return this.githubSdk.getGithubRepoList();
3022
2857
  }
3023
2858
  async getBranchList() {
@@ -3060,7 +2895,7 @@ var GithubSCMLib = class extends SCMLib {
3060
2895
  });
3061
2896
  }
3062
2897
  async getUsername() {
3063
- this._validateToken();
2898
+ this._validateAccessToken();
3064
2899
  return this.githubSdk.getGithubUsername();
3065
2900
  }
3066
2901
  async getSubmitRequestStatus(scmSubmitRequestId) {
@@ -3236,7 +3071,7 @@ var BitbucketSCMLib = class extends SCMLib {
3236
3071
  const authType = this.bitbucketSdk.getAuthType();
3237
3072
  switch (authType) {
3238
3073
  case "basic": {
3239
- this._validateToken();
3074
+ this._validateAccessToken();
3240
3075
  const { username, password } = getUserAndPassword(this.accessToken);
3241
3076
  return { username, password, authType };
3242
3077
  }
@@ -3262,7 +3097,7 @@ var BitbucketSCMLib = class extends SCMLib {
3262
3097
  });
3263
3098
  }
3264
3099
  async getRepoList(scmOrg) {
3265
- this._validateToken();
3100
+ this._validateAccessToken();
3266
3101
  return this.bitbucketSdk.getRepos({
3267
3102
  workspaceSlug: scmOrg
3268
3103
  });
@@ -3284,7 +3119,7 @@ var BitbucketSCMLib = class extends SCMLib {
3284
3119
  case "token":
3285
3120
  return { authorization: `Bearer ${this.accessToken}` };
3286
3121
  case "basic": {
3287
- this._validateToken();
3122
+ this._validateAccessToken();
3288
3123
  const { username, password } = getUserAndPassword(this.accessToken);
3289
3124
  return {
3290
3125
  authorization: `Basic ${Buffer.from(
@@ -3323,7 +3158,7 @@ var BitbucketSCMLib = class extends SCMLib {
3323
3158
  return this.bitbucketSdk.getIsUserCollaborator({ repoUrl: this.url });
3324
3159
  }
3325
3160
  async getUsername() {
3326
- this._validateToken();
3161
+ this._validateAccessToken();
3327
3162
  const res = await this.bitbucketSdk.getUser();
3328
3163
  return z7.string().parse(res.username);
3329
3164
  }
@@ -3375,309 +3210,516 @@ var BitbucketSCMLib = class extends SCMLib {
3375
3210
  }
3376
3211
  };
3377
3212
 
3378
- // src/features/analysis/scm/bitbucket/bitbucket.ts
3379
- var { Bitbucket } = bitbucketPkg;
3380
- var BITBUCKET_HOSTNAME = "bitbucket.org";
3381
- var TokenExpiredErrorZ = z8.object({
3382
- status: z8.number(),
3383
- error: z8.object({
3384
- type: z8.string(),
3385
- error: z8.object({
3386
- message: z8.string()
3387
- })
3388
- })
3213
+ // src/features/analysis/scm/ado/validation.ts
3214
+ import { z as z8 } from "zod";
3215
+ var ValidPullRequestStatusZ = z8.union([
3216
+ z8.literal(1 /* Active */),
3217
+ z8.literal(2 /* Abandoned */),
3218
+ z8.literal(3 /* Completed */)
3219
+ ]);
3220
+ var AdoAuthResultZ = z8.object({
3221
+ access_token: z8.string().min(1),
3222
+ token_type: z8.string().min(1),
3223
+ refresh_token: z8.string().min(1)
3389
3224
  });
3390
- var BITBUCKET_ACCESS_TOKEN_URL = `https://${BITBUCKET_HOSTNAME}/site/oauth2/access_token`;
3391
- var BitbucketAuthResultZ = z8.object({
3392
- access_token: z8.string(),
3393
- token_type: z8.string(),
3394
- refresh_token: z8.string()
3225
+ var profileZ = z8.object({
3226
+ displayName: z8.string(),
3227
+ publicAlias: z8.string().min(1),
3228
+ emailAddress: z8.string(),
3229
+ coreRevision: z8.number(),
3230
+ timeStamp: z8.string(),
3231
+ id: z8.string(),
3232
+ revision: z8.number()
3395
3233
  });
3396
- var BitbucketParseResultZ = z8.object({
3397
- organization: z8.string(),
3398
- repoName: z8.string(),
3399
- hostname: z8.literal(BITBUCKET_HOSTNAME)
3234
+ var accountsZ = z8.object({
3235
+ count: z8.number(),
3236
+ value: z8.array(
3237
+ z8.object({
3238
+ accountId: z8.string(),
3239
+ accountUri: z8.string(),
3240
+ accountName: z8.string()
3241
+ })
3242
+ )
3400
3243
  });
3401
- function parseBitbucketOrganizationAndRepo(bitbucketUrl) {
3402
- const parsedGitHubUrl = normalizeUrl(bitbucketUrl);
3403
- const parsingResult = parseScmURL(parsedGitHubUrl, "Bitbucket" /* Bitbucket */);
3404
- const validatedBitbucketResult = BitbucketParseResultZ.parse(parsingResult);
3405
- return {
3406
- workspace: validatedBitbucketResult.organization,
3407
- repoSlug: validatedBitbucketResult.repoName
3244
+
3245
+ // src/features/analysis/scm/ado/utils.ts
3246
+ function _getPublicAdoClient({
3247
+ orgName,
3248
+ origin: origin2
3249
+ }) {
3250
+ const orgUrl = `${origin2}/${orgName}`;
3251
+ const authHandler = api.getPersonalAccessTokenHandler("");
3252
+ authHandler.canHandleAuthentication = () => false;
3253
+ authHandler.prepareRequest = (_options) => {
3254
+ return;
3408
3255
  };
3256
+ const connection = new api.WebApi(orgUrl, authHandler);
3257
+ return connection;
3409
3258
  }
3410
- async function getBitbucketToken(params) {
3411
- const { bitbucketClientId, bitbucketClientSecret, authType } = params;
3412
- const res = await fetch(BITBUCKET_ACCESS_TOKEN_URL, {
3413
- method: "POST",
3414
- headers: {
3415
- "Content-Type": "application/x-www-form-urlencoded",
3416
- Authorization: "Basic " + btoa(`${bitbucketClientId}:${bitbucketClientSecret}`)
3417
- },
3418
- body: querystring3.stringify(
3419
- authType === "refresh_token" ? {
3420
- grant_type: authType,
3421
- refresh_token: params.refreshToken
3422
- } : {
3423
- grant_type: authType,
3424
- code: params.code
3425
- }
3426
- )
3427
- });
3428
- const authResult = await res.json();
3429
- return BitbucketAuthResultZ.parse(authResult);
3259
+ function removeTrailingSlash2(str) {
3260
+ return str.trim().replace(/\/+$/, "");
3430
3261
  }
3431
- function getBitbucketIntance(params) {
3432
- switch (params.authType) {
3433
- case "public":
3434
- return new Bitbucket();
3435
- case "token":
3436
- return new Bitbucket({ auth: { token: params.token } });
3437
- case "basic":
3438
- return new Bitbucket({
3439
- auth: {
3440
- password: params.password,
3441
- username: params.username
3442
- }
3443
- });
3262
+ function parseAdoOwnerAndRepo(adoUrl) {
3263
+ adoUrl = removeTrailingSlash2(adoUrl);
3264
+ const parsingResult = parseScmURL(adoUrl, "Ado" /* Ado */);
3265
+ if (!parsingResult) {
3266
+ throw new InvalidUrlPatternError(`
3267
+ : ${adoUrl}`);
3444
3268
  }
3445
- }
3446
- function getBitbucketSdk(params) {
3447
- const bitbucketClient = getBitbucketIntance(params);
3269
+ const {
3270
+ organization,
3271
+ repoName,
3272
+ projectName,
3273
+ projectPath,
3274
+ pathElements,
3275
+ hostname,
3276
+ protocol
3277
+ } = parsingResult;
3448
3278
  return {
3449
- getAuthType() {
3450
- return params.authType;
3451
- },
3452
- async getRepos(params2) {
3453
- const repoRes = params2?.workspaceSlug ? await getRepositoriesByWorkspace(bitbucketClient, {
3454
- workspaceSlug: params2.workspaceSlug
3455
- }) : await getllUsersrepositories(bitbucketClient);
3456
- return repoRes.map((repo) => ({
3457
- repoIsPublic: !repo.is_private,
3458
- repoName: repo.name || "unknown repo name",
3459
- repoOwner: repo.owner?.username || "unknown owner",
3460
- // language can be empty string
3461
- repoLanguages: repo.language ? [repo.language] : [],
3462
- repoUpdatedAt: repo.updated_on ? repo.updated_on : (/* @__PURE__ */ new Date()).toISOString(),
3463
- repoUrl: repo.links?.html?.href || ""
3464
- }));
3465
- },
3466
- async getBranchList(params2) {
3467
- const { workspace, repoSlug } = parseBitbucketOrganizationAndRepo(
3468
- params2.repoUrl
3469
- );
3470
- const res = await bitbucketClient.refs.listBranches({
3471
- repo_slug: repoSlug,
3472
- workspace
3473
- });
3474
- if (!res.data.values) {
3475
- return [];
3476
- }
3477
- return res.data.values.filter((branch) => !!branch.name).map((branch) => z8.string().parse(branch.name));
3478
- },
3479
- async getIsUserCollaborator(params2) {
3480
- const { repoUrl } = params2;
3481
- const { repoSlug, workspace } = parseBitbucketOrganizationAndRepo(repoUrl);
3482
- const fullRepoName = `${workspace}/${repoSlug}`;
3483
- const res = await bitbucketClient.user.listPermissionsForRepos({
3484
- q: `repository.full_name~"${fullRepoName}"`
3485
- });
3486
- return res.data.values?.some(
3487
- (res2) => res2.repository?.full_name === fullRepoName
3488
- ) ?? false;
3489
- },
3490
- async createPullRequest(params2) {
3491
- const { repoSlug, workspace } = parseBitbucketOrganizationAndRepo(
3492
- params2.repoUrl
3493
- );
3494
- const res = await bitbucketClient.pullrequests.create({
3495
- repo_slug: repoSlug,
3496
- workspace,
3497
- _body: {
3498
- type: "pullrequest",
3499
- title: params2.title,
3500
- summary: {
3501
- raw: params2.body
3502
- },
3503
- source: {
3504
- branch: {
3505
- name: params2.sourceBranchName
3506
- }
3507
- },
3508
- destination: {
3509
- branch: {
3510
- name: params2.targetBranchName
3511
- }
3512
- }
3513
- }
3514
- });
3515
- return res.data;
3516
- },
3517
- async getDownloadlink(params2) {
3518
- const { repoSlug, workspace } = parseBitbucketOrganizationAndRepo(
3519
- params2.repoUrl
3520
- );
3521
- const res = await bitbucketClient.downloads.list({
3522
- repo_slug: repoSlug,
3523
- workspace
3524
- });
3525
- return res.data;
3526
- },
3527
- async getBranch(params2) {
3528
- const { repoSlug, workspace } = parseBitbucketOrganizationAndRepo(
3529
- params2.repoUrl
3530
- );
3531
- const res = await bitbucketClient.refs.getBranch({
3532
- name: params2.branchName,
3533
- repo_slug: repoSlug,
3534
- workspace
3279
+ owner: decodeURI(organization),
3280
+ repo: decodeURI(repoName),
3281
+ projectName: projectName ? decodeURI(projectName) : void 0,
3282
+ projectPath,
3283
+ pathElements,
3284
+ origin: `${protocol}//${hostname}`
3285
+ };
3286
+ }
3287
+ async function getAdoConnectData({
3288
+ url,
3289
+ tokenOrg,
3290
+ adoTokenInfo
3291
+ }) {
3292
+ if (url && new URL(url).origin !== url) {
3293
+ const { owner, origin: origin2 } = parseAdoOwnerAndRepo(url);
3294
+ return {
3295
+ org: owner,
3296
+ origin: origin2
3297
+ };
3298
+ }
3299
+ if (!tokenOrg) {
3300
+ if (adoTokenInfo.type === "OAUTH" /* OAUTH */) {
3301
+ const [org] = await _getOrgsForOauthToken({
3302
+ oauthToken: adoTokenInfo.accessToken
3535
3303
  });
3536
- return res.data;
3537
- },
3538
- async getRepo(params2) {
3539
- const { repoSlug, workspace } = parseBitbucketOrganizationAndRepo(
3540
- params2.repoUrl
3304
+ return {
3305
+ org: z9.string().parse(org),
3306
+ origin: DEFUALT_ADO_ORIGIN
3307
+ };
3308
+ }
3309
+ throw new InvalidRepoUrlError("ADO URL is null");
3310
+ }
3311
+ return {
3312
+ org: tokenOrg,
3313
+ origin: DEFUALT_ADO_ORIGIN
3314
+ };
3315
+ }
3316
+ async function getAdoApiClient(params) {
3317
+ const { origin: origin2 = DEFUALT_ADO_ORIGIN, orgName } = params;
3318
+ if (params.tokenType === "NONE" /* NONE */ || // move to public client if the token is not associated with the PAT org
3319
+ params.tokenType === "PAT" /* PAT */ && params.patTokenOrg !== orgName) {
3320
+ return _getPublicAdoClient({ orgName, origin: origin2 });
3321
+ }
3322
+ const orgUrl = `${origin2}/${orgName}`;
3323
+ if (params.tokenType === "OAUTH" /* OAUTH */) {
3324
+ if (origin2 !== DEFUALT_ADO_ORIGIN) {
3325
+ throw new Error(
3326
+ `Oauth token is not supported for ADO on prem - ${origin2} `
3541
3327
  );
3542
- const res = await bitbucketClient.repositories.get({
3543
- repo_slug: repoSlug,
3544
- workspace
3545
- });
3546
- return res.data;
3328
+ }
3329
+ const connection2 = new api.WebApi(
3330
+ orgUrl,
3331
+ api.getBearerHandler(params.accessToken),
3332
+ {}
3333
+ );
3334
+ return connection2;
3335
+ }
3336
+ const authHandler = api.getPersonalAccessTokenHandler(params.accessToken);
3337
+ const isBroker = BROKERED_HOSTS.includes(new URL(orgUrl).origin);
3338
+ const connection = new api.WebApi(
3339
+ orgUrl,
3340
+ authHandler,
3341
+ isBroker ? {
3342
+ proxy: {
3343
+ proxyUrl: GIT_PROXY_HOST
3344
+ },
3345
+ ignoreSslError: true
3346
+ } : void 0
3347
+ );
3348
+ return connection;
3349
+ }
3350
+ function getAdoTokenInfo(token) {
3351
+ if (!token) {
3352
+ return { type: "NONE" /* NONE */ };
3353
+ }
3354
+ if (token.includes(".")) {
3355
+ return { type: "OAUTH" /* OAUTH */, accessToken: token };
3356
+ }
3357
+ return { type: "PAT" /* PAT */, accessToken: token };
3358
+ }
3359
+ async function getAdoClientParams(params) {
3360
+ const { url, accessToken, tokenOrg } = params;
3361
+ const adoTokenInfo = getAdoTokenInfo(accessToken);
3362
+ const { org, origin: origin2 } = await getAdoConnectData({
3363
+ url,
3364
+ tokenOrg,
3365
+ adoTokenInfo
3366
+ });
3367
+ switch (adoTokenInfo.type) {
3368
+ case "NONE" /* NONE */:
3369
+ return {
3370
+ tokenType: "NONE" /* NONE */,
3371
+ origin: origin2,
3372
+ orgName: org.toLowerCase()
3373
+ };
3374
+ case "OAUTH" /* OAUTH */: {
3375
+ return {
3376
+ tokenType: "OAUTH" /* OAUTH */,
3377
+ accessToken: adoTokenInfo.accessToken,
3378
+ origin: origin2,
3379
+ orgName: org.toLowerCase()
3380
+ };
3381
+ }
3382
+ case "PAT" /* PAT */: {
3383
+ return {
3384
+ tokenType: "PAT" /* PAT */,
3385
+ accessToken: adoTokenInfo.accessToken,
3386
+ patTokenOrg: z9.string().parse(tokenOrg).toLowerCase(),
3387
+ origin: origin2,
3388
+ orgName: org.toLowerCase()
3389
+ };
3390
+ }
3391
+ }
3392
+ }
3393
+ async function adoValidateParams({
3394
+ url,
3395
+ accessToken,
3396
+ tokenOrg
3397
+ }) {
3398
+ try {
3399
+ const api2 = await getAdoApiClient(
3400
+ await getAdoClientParams({ url, accessToken, tokenOrg })
3401
+ );
3402
+ await api2.connect();
3403
+ } catch (e) {
3404
+ console.log("adoValidateParams error", e);
3405
+ const error = e;
3406
+ const code = error.code || error.status || error.statusCode || error.response?.status || error.response?.statusCode || error.response?.code;
3407
+ const description = error.description || `${e}`;
3408
+ if (code === 401 || code === 403 || description.includes("401") || description.includes("403")) {
3409
+ throw new InvalidAccessTokenError(`invalid ADO access token`);
3410
+ }
3411
+ if (code === 404 || description.includes("404") || description.includes("Not Found")) {
3412
+ throw new InvalidRepoUrlError(`invalid ADO repo URL ${url}`);
3413
+ }
3414
+ throw e;
3415
+ }
3416
+ }
3417
+ async function _getOrgsForOauthToken({
3418
+ oauthToken
3419
+ }) {
3420
+ const profileRes = await fetch(
3421
+ "https://app.vssps.visualstudio.com/_apis/profile/profiles/me?api-version=6.0",
3422
+ {
3423
+ method: "GET",
3424
+ headers: {
3425
+ Authorization: `Bearer ${oauthToken}`
3426
+ }
3427
+ }
3428
+ );
3429
+ const profileJson = await profileRes.json();
3430
+ const profile = profileZ.parse(profileJson);
3431
+ const accountsRes = await fetch(
3432
+ `https://app.vssps.visualstudio.com/_apis/accounts?memberId=${profile.publicAlias}&api-version=6.0`,
3433
+ {
3434
+ method: "GET",
3435
+ headers: {
3436
+ Authorization: `Bearer ${oauthToken}`
3437
+ }
3438
+ }
3439
+ );
3440
+ const accountsJson = await accountsRes.json();
3441
+ const accounts = accountsZ.parse(accountsJson);
3442
+ const orgs = accounts.value.map((account) => account.accountName).filter((value, index, array) => array.indexOf(value) === index);
3443
+ return orgs;
3444
+ }
3445
+
3446
+ // src/features/analysis/scm/ado/ado.ts
3447
+ async function getAdoSdk(params) {
3448
+ const api2 = await getAdoApiClient(params);
3449
+ return {
3450
+ async getAdoIsUserCollaborator({ repoUrl }) {
3451
+ try {
3452
+ const { repo, projectName } = parseAdoOwnerAndRepo(repoUrl);
3453
+ const git = await api2.getGitApi();
3454
+ const branches = await git.getBranches(repo, projectName);
3455
+ if (!branches || branches.length === 0) {
3456
+ throw new InvalidRepoUrlError("no branches");
3457
+ }
3458
+ return true;
3459
+ } catch (e) {
3460
+ return false;
3461
+ }
3547
3462
  },
3548
- async getCommit(params2) {
3549
- const { repoSlug, workspace } = parseBitbucketOrganizationAndRepo(
3550
- params2.repoUrl
3463
+ async getAdoPullRequestStatus({
3464
+ repoUrl,
3465
+ prNumber
3466
+ }) {
3467
+ const { repo, projectName } = parseAdoOwnerAndRepo(repoUrl);
3468
+ const git = await api2.getGitApi();
3469
+ const res = await git.getPullRequest(repo, prNumber, projectName);
3470
+ const parsedPullRequestStatus = ValidPullRequestStatusZ.safeParse(
3471
+ res.status
3551
3472
  );
3552
- const res = await bitbucketClient.commits.get({
3553
- commit: params2.commitSha,
3554
- repo_slug: repoSlug,
3555
- workspace
3556
- });
3557
- return res.data;
3558
- },
3559
- async getUser() {
3560
- const res = await bitbucketClient.user.get({});
3561
- return res.data;
3473
+ if (!parsedPullRequestStatus.success) {
3474
+ throw new Error("bad pr status for ADO");
3475
+ }
3476
+ return parsedPullRequestStatus.data;
3562
3477
  },
3563
- async getReferenceData({
3564
- ref,
3565
- url
3478
+ async getAdoIsRemoteBranch({
3479
+ repoUrl,
3480
+ branch
3566
3481
  }) {
3567
- return Promise.allSettled([
3568
- this.getTagRef({ repoUrl: url, tagName: ref }),
3569
- this.getBranchRef({ repoUrl: url, branchName: ref }),
3570
- this.getCommitRef({ repoUrl: url, commitSha: ref })
3571
- ]).then((promisesResult) => {
3572
- const [refPromise] = promisesResult.filter(
3573
- (promise) => promise.status === "fulfilled"
3574
- );
3575
- if (!refPromise) {
3576
- throw new RefNotFoundError(`Invalid reference ${ref} for ${url}`);
3482
+ const { repo, projectName } = parseAdoOwnerAndRepo(repoUrl);
3483
+ const git = await api2.getGitApi();
3484
+ try {
3485
+ const branchStatus = await git.getBranch(repo, branch, projectName);
3486
+ if (!branchStatus || !branchStatus.commit) {
3487
+ throw new InvalidRepoUrlError("no branch status");
3577
3488
  }
3578
- return refPromise.value;
3579
- });
3489
+ return branchStatus.name === branch;
3490
+ } catch (e) {
3491
+ return false;
3492
+ }
3580
3493
  },
3581
- async getTagRef(params2) {
3582
- const { tagName, repoUrl } = params2;
3583
- const { repoSlug, workspace } = parseBitbucketOrganizationAndRepo(repoUrl);
3584
- const tagRes = await bitbucketClient.refs.getTag({
3585
- repo_slug: repoSlug,
3586
- workspace,
3587
- name: tagName
3588
- });
3589
- return GetRefererenceResultZ.parse({
3590
- sha: tagRes.data.target?.hash,
3591
- type: "TAG" /* TAG */,
3592
- date: new Date(z8.string().parse(tagRes.data.target?.date))
3593
- });
3494
+ async getAdoPrUrl({ url, prNumber }) {
3495
+ const { repo, projectName } = parseAdoOwnerAndRepo(url);
3496
+ const git = await api2.getGitApi();
3497
+ const getRepositoryRes = await git.getRepository(
3498
+ decodeURI(repo),
3499
+ projectName ? decodeURI(projectName) : void 0
3500
+ );
3501
+ return `${getRepositoryRes.webUrl}/pullrequest/${prNumber}`;
3594
3502
  },
3595
- async getBranchRef(params2) {
3596
- const getBranchRes = await this.getBranch(params2);
3597
- return GetRefererenceResultZ.parse({
3598
- sha: getBranchRes.target?.hash,
3599
- type: "BRANCH" /* BRANCH */,
3600
- date: new Date(z8.string().parse(getBranchRes.target?.date))
3601
- });
3503
+ getAdoDownloadUrl({
3504
+ repoUrl,
3505
+ branch
3506
+ }) {
3507
+ const { owner, repo, projectName } = parseAdoOwnerAndRepo(repoUrl);
3508
+ const url = new URL(repoUrl);
3509
+ const origin2 = url.origin.toLowerCase().endsWith(".visualstudio.com") ? DEFUALT_ADO_ORIGIN : url.origin.toLowerCase();
3510
+ return `${origin2}/${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`;
3602
3511
  },
3603
- async getCommitRef(params2) {
3604
- const getCommitRes = await this.getCommit(params2);
3605
- return GetRefererenceResultZ.parse({
3606
- sha: getCommitRes.hash,
3607
- type: "COMMIT" /* COMMIT */,
3608
- date: new Date(z8.string().parse(getCommitRes.date))
3609
- });
3512
+ async getAdoBranchList({ repoUrl }) {
3513
+ const { repo, projectName } = parseAdoOwnerAndRepo(repoUrl);
3514
+ const git = await api2.getGitApi();
3515
+ try {
3516
+ const res = await git.getBranches(repo, projectName);
3517
+ res.sort((a, b) => {
3518
+ if (!a.commit?.committer?.date || !b.commit?.committer?.date) {
3519
+ return 0;
3520
+ }
3521
+ return b.commit?.committer?.date.getTime() - a.commit?.committer?.date.getTime();
3522
+ });
3523
+ return res.reduce((acc, branch) => {
3524
+ if (!branch.name) {
3525
+ return acc;
3526
+ }
3527
+ acc.push(branch.name);
3528
+ return acc;
3529
+ }, []);
3530
+ } catch (e) {
3531
+ return [];
3532
+ }
3610
3533
  },
3611
- async getDownloadUrl({ url, sha }) {
3612
- this.getReferenceData({ ref: sha, url });
3613
- const repoRes = await this.getRepo({ repoUrl: url });
3614
- const parsedRepoUrl = z8.string().url().parse(repoRes.links?.html?.href);
3615
- return `${parsedRepoUrl}/get/${sha}.zip`;
3534
+ async createAdoPullRequest(options) {
3535
+ const { repoUrl, sourceBranchName, targetBranchName, title, body } = options;
3536
+ const { repo, projectName } = parseAdoOwnerAndRepo(repoUrl);
3537
+ const git = await api2.getGitApi();
3538
+ const res = await git.createPullRequest(
3539
+ {
3540
+ sourceRefName: `refs/heads/${sourceBranchName}`,
3541
+ targetRefName: `refs/heads/${targetBranchName}`,
3542
+ title,
3543
+ description: body
3544
+ },
3545
+ repo,
3546
+ projectName
3547
+ );
3548
+ return res.pullRequestId;
3616
3549
  },
3617
- async getPullRequest(params2) {
3618
- const { repoSlug, workspace } = parseBitbucketOrganizationAndRepo(
3619
- params2.url
3550
+ async getAdoRepoDefaultBranch({
3551
+ repoUrl
3552
+ }) {
3553
+ const { repo, projectName } = parseAdoOwnerAndRepo(repoUrl);
3554
+ const git = await api2.getGitApi();
3555
+ const getRepositoryRes = await git.getRepository(
3556
+ decodeURI(repo),
3557
+ projectName ? decodeURI(projectName) : void 0
3620
3558
  );
3621
- const res = await bitbucketClient.pullrequests.get({
3622
- pull_request_id: params2.prNumber,
3623
- repo_slug: repoSlug,
3624
- workspace
3625
- });
3626
- return res.data;
3627
- }
3628
- };
3629
- }
3630
- async function validateBitbucketParams(params) {
3631
- const { bitbucketClient } = params;
3632
- const authType = bitbucketClient.getAuthType();
3633
- try {
3634
- if (authType !== "public") {
3635
- await bitbucketClient.getUser();
3636
- }
3637
- if (params.url && shouldValidateUrl(params.url)) {
3638
- await bitbucketClient.getRepo({ repoUrl: params.url });
3639
- }
3640
- } catch (e) {
3641
- const safeParseError = TokenExpiredErrorZ.safeParse(e);
3642
- if (safeParseError.success) {
3643
- switch (safeParseError.data.status) {
3644
- case 401:
3645
- throw new InvalidAccessTokenError(
3646
- safeParseError.data.error.error.message
3559
+ if (!getRepositoryRes?.defaultBranch) {
3560
+ throw new InvalidRepoUrlError("no default branch");
3561
+ }
3562
+ return getRepositoryRes.defaultBranch.replace("refs/heads/", "");
3563
+ },
3564
+ // todo: refactor this function
3565
+ async getAdoReferenceData({
3566
+ ref,
3567
+ repoUrl
3568
+ }) {
3569
+ const { repo, projectName } = parseAdoOwnerAndRepo(repoUrl);
3570
+ if (!projectName) {
3571
+ throw new InvalidUrlPatternError("no project name");
3572
+ }
3573
+ const git = await api2.getGitApi();
3574
+ const results = await Promise.allSettled([
3575
+ (async () => {
3576
+ const res = await git.getBranch(repo, ref, projectName);
3577
+ if (!res.commit || !res.commit.commitId) {
3578
+ throw new InvalidRepoUrlError("no commit on branch");
3579
+ }
3580
+ return {
3581
+ sha: res.commit.commitId,
3582
+ type: "BRANCH" /* BRANCH */,
3583
+ date: res.commit.committer?.date || /* @__PURE__ */ new Date()
3584
+ };
3585
+ })(),
3586
+ (async () => {
3587
+ const res = await git.getCommits(
3588
+ repo,
3589
+ {
3590
+ fromCommitId: ref,
3591
+ toCommitId: ref,
3592
+ $top: 1
3593
+ },
3594
+ projectName
3647
3595
  );
3648
- case 404:
3649
- throw new InvalidRepoUrlError(safeParseError.data.error.error.message);
3596
+ const commit = res[0];
3597
+ if (!commit || !commit.commitId) {
3598
+ throw new Error("no commit");
3599
+ }
3600
+ return {
3601
+ sha: commit.commitId,
3602
+ type: "COMMIT" /* COMMIT */,
3603
+ date: commit.committer?.date || /* @__PURE__ */ new Date()
3604
+ };
3605
+ })(),
3606
+ (async () => {
3607
+ const res = await git.getRefs(repo, projectName, `tags/${ref}`);
3608
+ if (!res[0] || !res[0].objectId) {
3609
+ throw new Error("no tag ref");
3610
+ }
3611
+ let objectId = res[0].objectId;
3612
+ try {
3613
+ const tag = await git.getAnnotatedTag(projectName, repo, objectId);
3614
+ if (tag.taggedObject?.objectId) {
3615
+ objectId = tag.taggedObject.objectId;
3616
+ }
3617
+ } catch (e) {
3618
+ }
3619
+ const commitRes2 = await git.getCommits(
3620
+ repo,
3621
+ {
3622
+ fromCommitId: objectId,
3623
+ toCommitId: objectId,
3624
+ $top: 1
3625
+ },
3626
+ projectName
3627
+ );
3628
+ const commit = commitRes2[0];
3629
+ if (!commit) {
3630
+ throw new Error("no commit");
3631
+ }
3632
+ return {
3633
+ sha: objectId,
3634
+ type: "TAG" /* TAG */,
3635
+ date: commit.committer?.date || /* @__PURE__ */ new Date()
3636
+ };
3637
+ })()
3638
+ ]);
3639
+ const [branchRes, commitRes, tagRes] = results;
3640
+ if (tagRes.status === "fulfilled") {
3641
+ return tagRes.value;
3642
+ }
3643
+ if (branchRes.status === "fulfilled") {
3644
+ return branchRes.value;
3645
+ }
3646
+ if (commitRes.status === "fulfilled") {
3647
+ return commitRes.value;
3650
3648
  }
3649
+ throw new RefNotFoundError(`ref: ${ref} does not exist`);
3650
+ },
3651
+ getAdoBlameRanges() {
3652
+ return [];
3651
3653
  }
3652
- throw e;
3653
- }
3654
- }
3655
- async function getUsersworkspacesSlugs(bitbucketClient) {
3656
- const res = await bitbucketClient.workspaces.getWorkspaces({});
3657
- return res.data.values?.map((v) => z8.string().parse(v.slug));
3654
+ };
3658
3655
  }
3659
- async function getllUsersrepositories(bitbucketClient) {
3660
- const userWorspacesSlugs = await getUsersworkspacesSlugs(bitbucketClient);
3661
- if (!userWorspacesSlugs) {
3656
+ async function getAdoRepoList({
3657
+ orgName,
3658
+ tokenOrg,
3659
+ accessToken
3660
+ }) {
3661
+ let orgs = [];
3662
+ const adoTokenInfo = getAdoTokenInfo(accessToken);
3663
+ if (adoTokenInfo.type === "NONE" /* NONE */) {
3662
3664
  return [];
3663
3665
  }
3664
- const allWorkspaceRepos = [];
3665
- for (const workspaceSlug of userWorspacesSlugs) {
3666
- const repos = await bitbucketClient.repositories.list({
3667
- workspace: workspaceSlug
3668
- });
3669
- if (!repos.data.values) {
3670
- continue;
3671
- }
3672
- allWorkspaceRepos.push(...repos.data.values);
3666
+ if (adoTokenInfo.type === "OAUTH" /* OAUTH */) {
3667
+ orgs = await _getOrgsForOauthToken({ oauthToken: accessToken });
3673
3668
  }
3674
- return allWorkspaceRepos;
3675
- }
3676
- async function getRepositoriesByWorkspace(bitbucketClient, { workspaceSlug }) {
3677
- const res = await bitbucketClient.repositories.list({
3678
- workspace: workspaceSlug
3679
- });
3680
- return res.data.values ?? [];
3669
+ if (orgs.length === 0 && !orgName) {
3670
+ throw new Error(`no orgs for ADO`);
3671
+ } else if (orgs.length === 0 && orgName) {
3672
+ orgs = [orgName];
3673
+ }
3674
+ const repos = (await Promise.allSettled(
3675
+ orgs.map(async (org) => {
3676
+ const orgApi = await getAdoApiClient({
3677
+ ...await getAdoClientParams({
3678
+ accessToken,
3679
+ tokenOrg: tokenOrg || org,
3680
+ url: void 0
3681
+ }),
3682
+ orgName: org
3683
+ });
3684
+ const gitOrg = await orgApi.getGitApi();
3685
+ const orgRepos = await gitOrg.getRepositories();
3686
+ const repoInfoList = (await Promise.allSettled(
3687
+ orgRepos.map(async (repo) => {
3688
+ if (!repo.name || !repo.remoteUrl || !repo.defaultBranch) {
3689
+ throw new InvalidRepoUrlError("bad repo");
3690
+ }
3691
+ const branch = await gitOrg.getBranch(
3692
+ repo.name,
3693
+ repo.defaultBranch.replace(/^refs\/heads\//, ""),
3694
+ repo.project?.name
3695
+ );
3696
+ return {
3697
+ repoName: repo.name,
3698
+ repoUrl: repo.remoteUrl.replace(
3699
+ /^[hH][tT][tT][pP][sS]:\/\/[^/]+@/,
3700
+ "https://"
3701
+ ),
3702
+ repoOwner: org,
3703
+ repoIsPublic: repo.project?.visibility === 2 /* Public */,
3704
+ repoLanguages: [],
3705
+ repoUpdatedAt: branch.commit?.committer?.date?.toDateString() || repo.project?.lastUpdateTime?.toDateString() || (/* @__PURE__ */ new Date()).toDateString()
3706
+ };
3707
+ })
3708
+ )).reduce((acc, res) => {
3709
+ if (res.status === "fulfilled") {
3710
+ acc.push(res.value);
3711
+ }
3712
+ return acc;
3713
+ }, []);
3714
+ return repoInfoList;
3715
+ })
3716
+ )).reduce((acc, res) => {
3717
+ if (res.status === "fulfilled") {
3718
+ return acc.concat(res.value);
3719
+ }
3720
+ return acc;
3721
+ }, []);
3722
+ return repos;
3681
3723
  }
3682
3724
 
3683
3725
  // src/features/analysis/scm/constants.ts
@@ -3686,7 +3728,7 @@ var MOBB_ICON_IMG = "https://app.mobb.ai/gh-action/Logo_Rounded_Icon.svg";
3686
3728
  // src/features/analysis/add_fix_comments_for_pr/utils.ts
3687
3729
  import Debug3 from "debug";
3688
3730
  import parseDiff2 from "parse-diff";
3689
- import { z as z9 } from "zod";
3731
+ import { z as z10 } from "zod";
3690
3732
 
3691
3733
  // src/features/analysis/utils/by_key.ts
3692
3734
  function keyBy(array, keyBy2) {
@@ -3837,7 +3879,8 @@ async function postFixComment(params) {
3837
3879
  patchAndQuestions: { patch }
3838
3880
  } = fix;
3839
3881
  const commentRes = await scm.postPrComment({
3840
- body: "empty",
3882
+ body: `# ${MobbIconMarkdown} Your fix is ready!
3883
+ Refresh the page in order to see the changes.`,
3841
3884
  pull_number: pullRequest,
3842
3885
  commit_id: commitSha,
3843
3886
  path: path9,
@@ -3917,7 +3960,7 @@ async function getRelevantVulenrabilitiesFromDiff(params) {
3917
3960
  });
3918
3961
  const lineAddedRanges = calculateRanges(fileNumbers);
3919
3962
  const fileFilter = {
3920
- path: z9.string().parse(file.to),
3963
+ path: z10.string().parse(file.to),
3921
3964
  ranges: lineAddedRanges.map(([startLine, endLine]) => ({
3922
3965
  endLine,
3923
3966
  startLine
@@ -4224,30 +4267,30 @@ function subscribe(query, variables, callback, wsClientOptions) {
4224
4267
  }
4225
4268
 
4226
4269
  // src/features/analysis/graphql/types.ts
4227
- import { z as z10 } from "zod";
4228
- var VulnerabilityReportIssueCodeNodeZ = z10.object({
4229
- vulnerabilityReportIssueId: z10.string(),
4230
- path: z10.string(),
4231
- startLine: z10.number(),
4232
- vulnerabilityReportIssue: z10.object({
4233
- fixId: z10.string()
4270
+ import { z as z11 } from "zod";
4271
+ var VulnerabilityReportIssueCodeNodeZ = z11.object({
4272
+ vulnerabilityReportIssueId: z11.string(),
4273
+ path: z11.string(),
4274
+ startLine: z11.number(),
4275
+ vulnerabilityReportIssue: z11.object({
4276
+ fixId: z11.string()
4234
4277
  })
4235
4278
  });
4236
- var GetVulByNodesMetadataZ = z10.object({
4237
- vulnerabilityReportIssueCodeNodes: z10.array(VulnerabilityReportIssueCodeNodeZ),
4238
- nonFixablePrVuls: z10.object({
4239
- aggregate: z10.object({
4240
- count: z10.number()
4279
+ var GetVulByNodesMetadataZ = z11.object({
4280
+ vulnerabilityReportIssueCodeNodes: z11.array(VulnerabilityReportIssueCodeNodeZ),
4281
+ nonFixablePrVuls: z11.object({
4282
+ aggregate: z11.object({
4283
+ count: z11.number()
4241
4284
  })
4242
4285
  }),
4243
- fixablePrVuls: z10.object({
4244
- aggregate: z10.object({
4245
- count: z10.number()
4286
+ fixablePrVuls: z11.object({
4287
+ aggregate: z11.object({
4288
+ count: z11.number()
4246
4289
  })
4247
4290
  }),
4248
- totalScanVulnerabilities: z10.object({
4249
- aggregate: z10.object({
4250
- count: z10.number()
4291
+ totalScanVulnerabilities: z11.object({
4292
+ aggregate: z11.object({
4293
+ count: z11.number()
4251
4294
  })
4252
4295
  })
4253
4296
  });
@@ -5148,7 +5191,7 @@ async function _scan(params, { skipPrompts = false } = {}) {
5148
5191
  spinner: mobbSpinner,
5149
5192
  submitVulnerabilityReportVariables: {
5150
5193
  fixReportId: reportUploadInfo.fixReportId,
5151
- repoUrl: z11.string().parse(repo),
5194
+ repoUrl: z12.string().parse(repo),
5152
5195
  reference,
5153
5196
  projectId,
5154
5197
  vulnerabilityReportFileName: "report.json",
@@ -5400,9 +5443,9 @@ async function _scan(params, { skipPrompts = false } = {}) {
5400
5443
  }
5401
5444
  });
5402
5445
  if (command === "review") {
5403
- const params2 = z11.object({
5404
- repo: z11.string().url(),
5405
- githubActionToken: z11.string()
5446
+ const params2 = z12.object({
5447
+ repo: z12.string().url(),
5448
+ githubActionToken: z12.string()
5406
5449
  }).parse({ repo, githubActionToken });
5407
5450
  const scm2 = await SCMLib.init({
5408
5451
  url: params2.repo,
@@ -5419,7 +5462,7 @@ async function _scan(params, { skipPrompts = false } = {}) {
5419
5462
  analysisId,
5420
5463
  gqlClient,
5421
5464
  scm: scm2,
5422
- scanner: z11.nativeEnum(SCANNERS).parse(scanner)
5465
+ scanner: z12.nativeEnum(SCANNERS).parse(scanner)
5423
5466
  });
5424
5467
  },
5425
5468
  callbackStates: ["Finished" /* Finished */]
@@ -5632,7 +5675,7 @@ var scmTokenOption = {
5632
5675
  // src/args/validation.ts
5633
5676
  import chalk6 from "chalk";
5634
5677
  import path8 from "path";
5635
- import { z as z12 } from "zod";
5678
+ import { z as z13 } from "zod";
5636
5679
  function throwRepoUrlErrorMessage({
5637
5680
  error,
5638
5681
  repoUrl,
@@ -5649,13 +5692,13 @@ Example:
5649
5692
  )}`;
5650
5693
  throw new CliError(formattedErrorMessage);
5651
5694
  }
5652
- var UrlZ = z12.string({
5695
+ var UrlZ = z13.string({
5653
5696
  invalid_type_error: "is not a valid GitHub / GitLab / ADO URL"
5654
5697
  }).refine((data) => !!sanityRepoURL(data), {
5655
5698
  message: "is not a valid GitHub / GitLab / ADO URL"
5656
5699
  });
5657
5700
  function validateOrganizationId(organizationId) {
5658
- const orgIdValidation = z12.string().uuid().nullish().safeParse(organizationId);
5701
+ const orgIdValidation = z13.string().uuid().nullish().safeParse(organizationId);
5659
5702
  if (!orgIdValidation.success) {
5660
5703
  throw new CliError(`organizationId: ${organizationId} is not a valid UUID`);
5661
5704
  }
@@ -5812,7 +5855,7 @@ async function scanHandler(args) {
5812
5855
  }
5813
5856
 
5814
5857
  // src/args/commands/token.ts
5815
- import { z as z13 } from "zod";
5858
+ import { z as z14 } from "zod";
5816
5859
  function addScmTokenBuilder(args) {
5817
5860
  return args.option("scm-type", scmTypeOption).option("url", urlOption).option("token", scmTokenOption).option("organization", scmOrgOption).option("refresh-token", scmRefreshTokenOption).option("api-key", apiKeyOption).example(
5818
5861
  "$0 add-scm-token --scm-type Ado --url https://dev.azure.com/adoorg/test/_git/repo --token abcdef0123456 --organization myOrg",
@@ -5820,7 +5863,7 @@ function addScmTokenBuilder(args) {
5820
5863
  ).help().demandOption(["url", "token"]);
5821
5864
  }
5822
5865
  function validateAddScmTokenOptions(argv) {
5823
- if (!z13.nativeEnum(ScmType).safeParse(argv.scmType).success) {
5866
+ if (!z14.nativeEnum(ScmType).safeParse(argv.scmType).success) {
5824
5867
  throw new CliError(
5825
5868
  "\nError: --scm-type must reference a valid SCM type (GitHub, GitLab, Ado, Bitbutcket)"
5826
5869
  );