mobbdev 0.0.145 → 0.0.152

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 +1642 -1512
  2. package/package.json +1 -1
package/dist/index.mjs CHANGED
@@ -32,661 +32,174 @@ import fs4 from "node:fs";
32
32
  import path7 from "node:path";
33
33
 
34
34
  // src/constants.ts
35
- import path from "node:path";
35
+ import path2 from "node:path";
36
36
  import { fileURLToPath } from "node:url";
37
37
  import chalk from "chalk";
38
38
  import Debug from "debug";
39
39
  import * as dotenv from "dotenv";
40
- import { z } from "zod";
41
- var debug = Debug("mobbdev:constants");
42
- var __dirname = path.dirname(fileURLToPath(import.meta.url));
43
- dotenv.config({ path: path.join(__dirname, "../.env") });
44
- var ScmTypes = {
45
- Github: "GitHub",
46
- Gitlab: "GitLab",
47
- AzureDevOps: "Ado"
48
- };
49
- var SCANNERS = {
50
- Checkmarx: "checkmarx",
51
- Codeql: "codeql",
52
- Fortify: "fortify",
53
- Snyk: "snyk",
54
- Sonarqube: "sonarqube"
55
- };
56
- var SupportedScannersZ = z.enum([SCANNERS.Checkmarx, SCANNERS.Snyk]);
57
- var envVariablesSchema = z.object({
58
- WEB_APP_URL: z.string(),
59
- API_URL: z.string(),
60
- HASURA_ACCESS_KEY: z.string(),
61
- LOCAL_GRAPHQL_ENDPOINT: z.string()
62
- }).required();
63
- var envVariables = envVariablesSchema.parse(process.env);
64
- debug("config %o", envVariables);
65
- var mobbAscii = `
66
- ..
67
- ..........
68
- .................
69
- ...........................
70
- ..............................
71
- ................................
72
- ..................................
73
- ....................................
74
- .....................................
75
- .............................................
76
- .................................................
77
- ............................... .................
78
- .................................. ............
79
- .................. ............. ..........
80
- ......... ........ ......... ......
81
- ............... ....
82
- .... ..
83
-
84
- . ...
85
- ..............
86
- ......................
87
- ...........................
88
- ................................
89
- ......................................
90
- ...............................
91
- .................
92
- `;
93
- var PROJECT_DEFAULT_NAME = "My first project";
94
- var WEB_APP_URL = envVariables.WEB_APP_URL;
95
- var API_URL = envVariables.API_URL;
96
- var HASURA_ACCESS_KEY = envVariables.HASURA_ACCESS_KEY;
97
- var LOCAL_GRAPHQL_ENDPOINT = envVariables.LOCAL_GRAPHQL_ENDPOINT;
98
- var errorMessages = {
99
- missingCxProjectName: `project name ${chalk.bold(
100
- "(--cx-project-name)"
101
- )} is needed if you're using checkmarx`,
102
- missingUrl: `url ${chalk.bold(
103
- "(--url)"
104
- )} is needed if you're adding an SCM token`,
105
- invalidScmType: `SCM type ${chalk.bold(
106
- "(--scm-type)"
107
- )} is invalid, please use one of: ${Object.values(ScmTypes).join(", ")}`,
108
- missingToken: `SCM token ${chalk.bold(
109
- "(--token)"
110
- )} is needed if you're adding an SCM token`
111
- };
112
- var progressMassages = {
113
- processingVulnerabilityReportSuccess: "\u2699\uFE0F Vulnerability report proccessed successfully",
114
- processingVulnerabilityReport: "\u2699\uFE0F Proccessing vulnerability report",
115
- processingVulnerabilityReportFailed: "\u2699\uFE0F Error Proccessing vulnerability report"
40
+ import { z as z10 } from "zod";
41
+
42
+ // src/features/analysis/scm/shared/src/types.ts
43
+ var scmCloudUrl = {
44
+ GitLab: "https://gitlab.com",
45
+ GitHub: "https://github.com",
46
+ Ado: "https://dev.azure.com",
47
+ Bitbucket: "https://bitbucket.org"
116
48
  };
117
- var VUL_REPORT_DIGEST_TIMEOUT_MS = 1e3 * 60 * 20;
49
+ var ScmType = /* @__PURE__ */ ((ScmType2) => {
50
+ ScmType2["GitHub"] = "GitHub";
51
+ ScmType2["GitLab"] = "GitLab";
52
+ ScmType2["Ado"] = "Ado";
53
+ ScmType2["Bitbucket"] = "Bitbucket";
54
+ return ScmType2;
55
+ })(ScmType || {});
118
56
 
119
- // src/features/analysis/index.ts
120
- import crypto from "node:crypto";
121
- import fs3 from "node:fs";
122
- import os from "node:os";
123
- import path6 from "node:path";
124
- import { pipeline } from "node:stream/promises";
57
+ // src/features/analysis/scm/ado/constants.ts
58
+ var DEFUALT_ADO_ORIGIN = scmCloudUrl.Ado;
125
59
 
126
- // src/generates/client_generates.ts
127
- var MeDocument = `
128
- query Me {
129
- me {
130
- id
131
- email
132
- scmConfigs {
133
- id
134
- orgId
135
- refreshToken
136
- scmType
137
- scmUrl
138
- scmUsername
139
- token
140
- tokenLastUpdate
141
- userId
142
- scmOrg
143
- isTokenAvailable
60
+ // src/features/analysis/scm/ado/utils.ts
61
+ import querystring3 from "node:querystring";
62
+ import * as api from "azure-devops-node-api";
63
+ import { z as z9 } from "zod";
64
+
65
+ // src/features/analysis/scm/env.ts
66
+ import { z } from "zod";
67
+ var EnvVariablesZod = z.object({
68
+ GITLAB_API_TOKEN: z.string().optional(),
69
+ BROKERED_HOSTS: z.string().toLowerCase().transform(
70
+ (x) => x.split(",").map((url) => url.trim(), []).filter(Boolean)
71
+ ).default(""),
72
+ GITHUB_API_TOKEN: z.string().optional(),
73
+ GIT_PROXY_HOST: z.string().default("http://tinyproxy:8888")
74
+ });
75
+ var { GITLAB_API_TOKEN, BROKERED_HOSTS, GITHUB_API_TOKEN, GIT_PROXY_HOST } = EnvVariablesZod.parse(process.env);
76
+
77
+ // src/features/analysis/scm/scm.ts
78
+ import { z as z7 } from "zod";
79
+
80
+ // src/features/analysis/scm/bitbucket/bitbucket.ts
81
+ import querystring from "node:querystring";
82
+ import bitbucketPkg from "bitbucket";
83
+ import * as bitbucketPkgNode from "bitbucket";
84
+ import { z as z3 } from "zod";
85
+
86
+ // src/features/analysis/scm/shared/src/urlParser/urlParser.ts
87
+ import { z as z2 } from "zod";
88
+ function detectAdoUrl(args) {
89
+ const { pathname, hostname, scmType } = args;
90
+ const hostnameParts = hostname.split(".");
91
+ const adoCloudHostname = new URL(scmCloudUrl.Ado).hostname;
92
+ const prefixPath = pathname.at(0)?.toLowerCase() === ADO_PREFIX_PATH ? ADO_PREFIX_PATH : "";
93
+ const normilizedPath = prefixPath ? pathname.slice(1) : pathname;
94
+ if (hostnameParts.length === 3 && hostnameParts[1] === "visualstudio" && hostnameParts[2] === "com") {
95
+ if (normilizedPath.length === 2 && normilizedPath[0] === "_git") {
96
+ const [_git, projectName] = normilizedPath;
97
+ const [organization] = hostnameParts;
98
+ return {
99
+ scmType: "Ado" /* Ado */,
100
+ organization,
101
+ // project has single repo - repoName === projectName
102
+ projectName: z2.string().parse(projectName),
103
+ repoName: projectName,
104
+ prefixPath
105
+ };
106
+ }
107
+ if (normilizedPath.length === 3 && normilizedPath[1] === "_git") {
108
+ const [projectName, _git, repoName] = normilizedPath;
109
+ const [organization] = hostnameParts;
110
+ return {
111
+ scmType: "Ado" /* Ado */,
112
+ organization,
113
+ projectName: z2.string().parse(projectName),
114
+ repoName,
115
+ prefixPath
116
+ };
144
117
  }
145
118
  }
146
- }
147
- `;
148
- var GetOrgAndProjectIdDocument = `
149
- query getOrgAndProjectId($filters: organization_to_organization_role_bool_exp, $limit: Int) {
150
- organization_to_organization_role(
151
- where: $filters
152
- order_by: {organization: {createdOn: desc}}
153
- limit: $limit
154
- ) {
155
- organization {
156
- id
157
- projects(order_by: {updatedAt: desc}) {
158
- id
159
- name
119
+ if (hostname === adoCloudHostname || scmType === "Ado" /* Ado */) {
120
+ if (normilizedPath[normilizedPath.length - 2] === "_git") {
121
+ if (normilizedPath.length === 3) {
122
+ const [organization, _git, repoName] = normilizedPath;
123
+ return {
124
+ scmType: "Ado" /* Ado */,
125
+ organization,
126
+ // project has only one repo - repoName === projectName
127
+ projectName: z2.string().parse(repoName),
128
+ repoName,
129
+ prefixPath
130
+ };
131
+ }
132
+ if (normilizedPath.length === 4) {
133
+ const [organization, projectName, _git, repoName] = normilizedPath;
134
+ return {
135
+ scmType: "Ado" /* Ado */,
136
+ organization,
137
+ projectName: z2.string().parse(projectName),
138
+ repoName,
139
+ prefixPath
140
+ };
160
141
  }
161
142
  }
162
143
  }
144
+ return null;
163
145
  }
164
- `;
165
- var GetEncryptedApiTokenDocument = `
166
- query GetEncryptedApiToken($loginId: uuid!) {
167
- cli_login_by_pk(id: $loginId) {
168
- encryptedApiToken
169
- }
170
- }
171
- `;
172
- var FixReportStateDocument = `
173
- query FixReportState($id: uuid!) {
174
- fixReport_by_pk(id: $id) {
175
- state
146
+ function detectGithubUrl(args) {
147
+ const { pathname, hostname, scmType } = args;
148
+ const githubHostname = new URL(scmCloudUrl.GitHub).hostname;
149
+ if (hostname === githubHostname || scmType === "GitHub" /* GitHub */) {
150
+ if (pathname.length === 2) {
151
+ return {
152
+ scmType: "GitHub" /* GitHub */,
153
+ organization: pathname[0],
154
+ repoName: pathname[1]
155
+ };
156
+ }
176
157
  }
158
+ return null;
177
159
  }
178
- `;
179
- var GetVulnerabilityReportPathsDocument = `
180
- query GetVulnerabilityReportPaths($vulnerabilityReportId: uuid!) {
181
- vulnerability_report_path(
182
- where: {vulnerabilityReportId: {_eq: $vulnerabilityReportId}}
183
- ) {
184
- path
160
+ function detectGitlabUrl(args) {
161
+ const { pathname, hostname, scmType } = args;
162
+ const gitlabHostname = new URL(scmCloudUrl.GitLab).hostname;
163
+ if (hostname === gitlabHostname || scmType === "GitLab" /* GitLab */) {
164
+ if (pathname.length >= 2) {
165
+ return {
166
+ scmType: "GitLab" /* GitLab */,
167
+ organization: pathname[0],
168
+ repoName: pathname[pathname.length - 1]
169
+ };
170
+ }
185
171
  }
172
+ return null;
186
173
  }
187
- `;
188
- var GetAnalysisDocument = `
189
- subscription getAnalysis($analysisId: uuid!) {
190
- analysis: fixReport_by_pk(id: $analysisId) {
191
- id
192
- state
174
+ function detectBitbucketUrl(args) {
175
+ const { pathname, hostname, scmType } = args;
176
+ const bitbucketHostname = new URL(scmCloudUrl.Bitbucket).hostname;
177
+ if (hostname === bitbucketHostname || scmType === "Bitbucket" /* Bitbucket */) {
178
+ if (pathname.length === 2) {
179
+ return {
180
+ scmType: "Bitbucket" /* Bitbucket */,
181
+ organization: pathname[0],
182
+ repoName: pathname[1]
183
+ };
184
+ }
193
185
  }
186
+ return null;
194
187
  }
195
- `;
196
- var GetAnalsyisDocument = `
197
- query getAnalsyis($analysisId: uuid!) {
198
- analysis: fixReport_by_pk(id: $analysisId) {
199
- id
200
- state
201
- repo {
202
- commitSha
203
- pullRequest
204
- }
205
- vulnerabilityReportId
206
- vulnerabilityReport {
207
- projectId
208
- project {
209
- organizationId
210
- }
211
- file {
212
- signedFile {
213
- url
214
- }
215
- }
188
+ var getRepoUrlFunctionMap = {
189
+ ["GitLab" /* GitLab */]: detectGitlabUrl,
190
+ ["GitHub" /* GitHub */]: detectGithubUrl,
191
+ ["Ado" /* Ado */]: detectAdoUrl,
192
+ ["Bitbucket" /* Bitbucket */]: detectBitbucketUrl
193
+ };
194
+ function getRepoInfo(args) {
195
+ for (const detectUrl of Object.values(getRepoUrlFunctionMap)) {
196
+ const detectUrlRes = detectUrl(args);
197
+ if (detectUrlRes) {
198
+ return detectUrlRes;
216
199
  }
217
200
  }
201
+ return null;
218
202
  }
219
- `;
220
- var GetFixesDocument = `
221
- query getFixes($filters: fix_bool_exp!) {
222
- fixes: fix(where: $filters) {
223
- issueType
224
- id
225
- patchAndQuestions {
226
- __typename
227
- ... on FixData {
228
- patch
229
- }
230
- }
231
- }
232
- }
233
- `;
234
- var GetVulByNodesMetadataDocument = `
235
- query getVulByNodesMetadata($filters: [vulnerability_report_issue_code_node_bool_exp!], $vulnerabilityReportId: uuid!) {
236
- vulnerabilityReportIssueCodeNodes: vulnerability_report_issue_code_node(
237
- order_by: {index: desc}
238
- where: {_or: $filters, vulnerabilityReportIssue: {fixId: {_is_null: false}, vulnerabilityReportId: {_eq: $vulnerabilityReportId}}}
239
- ) {
240
- vulnerabilityReportIssueId
241
- path
242
- startLine
243
- vulnerabilityReportIssue {
244
- issueType
245
- fixId
246
- }
247
- }
248
- fixablePrVuls: vulnerability_report_issue_aggregate(
249
- where: {fixId: {_is_null: false}, vulnerabilityReportId: {_eq: $vulnerabilityReportId}, codeNodes: {_or: $filters}}
250
- ) {
251
- aggregate {
252
- count
253
- }
254
- }
255
- nonFixablePrVuls: vulnerability_report_issue_aggregate(
256
- where: {fixId: {_is_null: true}, vulnerabilityReportId: {_eq: $vulnerabilityReportId}, codeNodes: {_or: $filters}}
257
- ) {
258
- aggregate {
259
- count
260
- }
261
- }
262
- totalScanVulnerabilities: vulnerability_report_issue_aggregate(
263
- where: {vulnerabilityReportId: {_eq: $vulnerabilityReportId}}
264
- ) {
265
- aggregate {
266
- count
267
- }
268
- }
269
- }
270
- `;
271
- var UpdateScmTokenDocument = `
272
- mutation updateScmToken($scmType: String!, $url: String!, $token: String!, $org: String, $refreshToken: String) {
273
- updateScmToken(
274
- scmType: $scmType
275
- url: $url
276
- token: $token
277
- org: $org
278
- refreshToken: $refreshToken
279
- ) {
280
- __typename
281
- ... on ScmAccessTokenUpdateSuccess {
282
- token
283
- }
284
- ... on InvalidScmTypeError {
285
- status
286
- error
287
- }
288
- ... on BadScmCredentials {
289
- status
290
- error
291
- }
292
- }
293
- }
294
- `;
295
- var UploadS3BucketInfoDocument = `
296
- mutation uploadS3BucketInfo($fileName: String!) {
297
- uploadS3BucketInfo(fileName: $fileName) {
298
- status
299
- error
300
- reportUploadInfo: uploadInfo {
301
- url
302
- fixReportId
303
- uploadFieldsJSON
304
- uploadKey
305
- }
306
- repoUploadInfo {
307
- url
308
- fixReportId
309
- uploadFieldsJSON
310
- uploadKey
311
- }
312
- }
313
- }
314
- `;
315
- var DigestVulnerabilityReportDocument = `
316
- mutation DigestVulnerabilityReport($vulnerabilityReportFileName: String!, $fixReportId: String!, $projectId: String!, $scanSource: String!) {
317
- digestVulnerabilityReport(
318
- fixReportId: $fixReportId
319
- vulnerabilityReportFileName: $vulnerabilityReportFileName
320
- projectId: $projectId
321
- scanSource: $scanSource
322
- ) {
323
- __typename
324
- ... on VulnerabilityReport {
325
- vulnerabilityReportId
326
- fixReportId
327
- }
328
- ... on RabbitSendError {
329
- status
330
- error
331
- }
332
- ... on ReportValidationError {
333
- status
334
- error
335
- }
336
- ... on ReferenceNotFoundError {
337
- status
338
- error
339
- }
340
- }
341
- }
342
- `;
343
- var SubmitVulnerabilityReportDocument = `
344
- mutation SubmitVulnerabilityReport($fixReportId: String!, $repoUrl: String!, $reference: String!, $projectId: String!, $scanSource: String!, $sha: String, $experimentalEnabled: Boolean, $vulnerabilityReportFileName: String, $pullRequest: Int) {
345
- submitVulnerabilityReport(
346
- fixReportId: $fixReportId
347
- repoUrl: $repoUrl
348
- reference: $reference
349
- sha: $sha
350
- experimentalEnabled: $experimentalEnabled
351
- pullRequest: $pullRequest
352
- projectId: $projectId
353
- vulnerabilityReportFileName: $vulnerabilityReportFileName
354
- scanSource: $scanSource
355
- ) {
356
- __typename
357
- ... on VulnerabilityReport {
358
- vulnerabilityReportId
359
- fixReportId
360
- }
361
- }
362
- }
363
- `;
364
- var CreateCommunityUserDocument = `
365
- mutation CreateCommunityUser {
366
- initOrganizationAndProject {
367
- __typename
368
- ... on InitOrganizationAndProjectGoodResponse {
369
- projectId
370
- userId
371
- organizationId
372
- }
373
- ... on UserAlreadyInProjectError {
374
- error
375
- status
376
- }
377
- }
378
- }
379
- `;
380
- var CreateCliLoginDocument = `
381
- mutation CreateCliLogin($publicKey: String!) {
382
- insert_cli_login_one(object: {publicKey: $publicKey}) {
383
- id
384
- }
385
- }
386
- `;
387
- var PerformCliLoginDocument = `
388
- mutation performCliLogin($loginId: String!) {
389
- performCliLogin(loginId: $loginId) {
390
- status
391
- }
392
- }
393
- `;
394
- var CreateProjectDocument = `
395
- mutation CreateProject($organizationId: String!, $projectName: String!) {
396
- createProject(organizationId: $organizationId, projectName: $projectName) {
397
- projectId
398
- }
399
- }
400
- `;
401
- var defaultWrapper = (action, _operationName, _operationType, _variables) => action();
402
- function getSdk(client, withWrapper = defaultWrapper) {
403
- return {
404
- Me(variables, requestHeaders) {
405
- return withWrapper((wrappedRequestHeaders) => client.request(MeDocument, variables, { ...requestHeaders, ...wrappedRequestHeaders }), "Me", "query", variables);
406
- },
407
- getOrgAndProjectId(variables, requestHeaders) {
408
- return withWrapper((wrappedRequestHeaders) => client.request(GetOrgAndProjectIdDocument, variables, { ...requestHeaders, ...wrappedRequestHeaders }), "getOrgAndProjectId", "query", variables);
409
- },
410
- GetEncryptedApiToken(variables, requestHeaders) {
411
- return withWrapper((wrappedRequestHeaders) => client.request(GetEncryptedApiTokenDocument, variables, { ...requestHeaders, ...wrappedRequestHeaders }), "GetEncryptedApiToken", "query", variables);
412
- },
413
- FixReportState(variables, requestHeaders) {
414
- return withWrapper((wrappedRequestHeaders) => client.request(FixReportStateDocument, variables, { ...requestHeaders, ...wrappedRequestHeaders }), "FixReportState", "query", variables);
415
- },
416
- GetVulnerabilityReportPaths(variables, requestHeaders) {
417
- return withWrapper((wrappedRequestHeaders) => client.request(GetVulnerabilityReportPathsDocument, variables, { ...requestHeaders, ...wrappedRequestHeaders }), "GetVulnerabilityReportPaths", "query", variables);
418
- },
419
- getAnalysis(variables, requestHeaders) {
420
- return withWrapper((wrappedRequestHeaders) => client.request(GetAnalysisDocument, variables, { ...requestHeaders, ...wrappedRequestHeaders }), "getAnalysis", "subscription", variables);
421
- },
422
- getAnalsyis(variables, requestHeaders) {
423
- return withWrapper((wrappedRequestHeaders) => client.request(GetAnalsyisDocument, variables, { ...requestHeaders, ...wrappedRequestHeaders }), "getAnalsyis", "query", variables);
424
- },
425
- getFixes(variables, requestHeaders) {
426
- return withWrapper((wrappedRequestHeaders) => client.request(GetFixesDocument, variables, { ...requestHeaders, ...wrappedRequestHeaders }), "getFixes", "query", variables);
427
- },
428
- getVulByNodesMetadata(variables, requestHeaders) {
429
- return withWrapper((wrappedRequestHeaders) => client.request(GetVulByNodesMetadataDocument, variables, { ...requestHeaders, ...wrappedRequestHeaders }), "getVulByNodesMetadata", "query", variables);
430
- },
431
- updateScmToken(variables, requestHeaders) {
432
- return withWrapper((wrappedRequestHeaders) => client.request(UpdateScmTokenDocument, variables, { ...requestHeaders, ...wrappedRequestHeaders }), "updateScmToken", "mutation", variables);
433
- },
434
- uploadS3BucketInfo(variables, requestHeaders) {
435
- return withWrapper((wrappedRequestHeaders) => client.request(UploadS3BucketInfoDocument, variables, { ...requestHeaders, ...wrappedRequestHeaders }), "uploadS3BucketInfo", "mutation", variables);
436
- },
437
- DigestVulnerabilityReport(variables, requestHeaders) {
438
- return withWrapper((wrappedRequestHeaders) => client.request(DigestVulnerabilityReportDocument, variables, { ...requestHeaders, ...wrappedRequestHeaders }), "DigestVulnerabilityReport", "mutation", variables);
439
- },
440
- SubmitVulnerabilityReport(variables, requestHeaders) {
441
- return withWrapper((wrappedRequestHeaders) => client.request(SubmitVulnerabilityReportDocument, variables, { ...requestHeaders, ...wrappedRequestHeaders }), "SubmitVulnerabilityReport", "mutation", variables);
442
- },
443
- CreateCommunityUser(variables, requestHeaders) {
444
- return withWrapper((wrappedRequestHeaders) => client.request(CreateCommunityUserDocument, variables, { ...requestHeaders, ...wrappedRequestHeaders }), "CreateCommunityUser", "mutation", variables);
445
- },
446
- CreateCliLogin(variables, requestHeaders) {
447
- return withWrapper((wrappedRequestHeaders) => client.request(CreateCliLoginDocument, variables, { ...requestHeaders, ...wrappedRequestHeaders }), "CreateCliLogin", "mutation", variables);
448
- },
449
- performCliLogin(variables, requestHeaders) {
450
- return withWrapper((wrappedRequestHeaders) => client.request(PerformCliLoginDocument, variables, { ...requestHeaders, ...wrappedRequestHeaders }), "performCliLogin", "mutation", variables);
451
- },
452
- CreateProject(variables, requestHeaders) {
453
- return withWrapper((wrappedRequestHeaders) => client.request(CreateProjectDocument, variables, { ...requestHeaders, ...wrappedRequestHeaders }), "CreateProject", "mutation", variables);
454
- }
455
- };
456
- }
457
-
458
- // src/utils/index.ts
459
- var utils_exports = {};
460
- __export(utils_exports, {
461
- CliError: () => CliError,
462
- Spinner: () => Spinner,
463
- getDirName: () => getDirName,
464
- getTopLevelDirName: () => getTopLevelDirName,
465
- keypress: () => keypress,
466
- sleep: () => sleep
467
- });
468
-
469
- // src/utils/dirname.ts
470
- import path2 from "node:path";
471
- import { fileURLToPath as fileURLToPath2 } from "node:url";
472
- function getDirName() {
473
- return path2.dirname(fileURLToPath2(import.meta.url));
474
- }
475
- function getTopLevelDirName(fullPath) {
476
- return path2.parse(fullPath).name;
477
- }
478
-
479
- // src/utils/keypress.ts
480
- import readline from "node:readline";
481
- async function keypress() {
482
- const rl = readline.createInterface({
483
- input: process.stdin,
484
- output: process.stdout
485
- });
486
- return new Promise((resolve) => {
487
- rl.question("", (answer) => {
488
- rl.close();
489
- process.stderr.moveCursor(0, -1);
490
- process.stderr.clearLine(1);
491
- resolve(answer);
492
- });
493
- });
494
- }
495
-
496
- // src/utils/spinner.ts
497
- import {
498
- createSpinner as _createSpinner
499
- } from "nanospinner";
500
- var mockSpinner = {
501
- success: () => mockSpinner,
502
- error: () => mockSpinner,
503
- warn: () => mockSpinner,
504
- stop: () => mockSpinner,
505
- start: () => mockSpinner,
506
- update: () => mockSpinner,
507
- reset: () => mockSpinner,
508
- clear: () => mockSpinner,
509
- spin: () => mockSpinner
510
- };
511
- function Spinner({ ci = false } = {}) {
512
- return {
513
- createSpinner: (text, options) => ci ? mockSpinner : _createSpinner(text, options)
514
- };
515
- }
516
-
517
- // src/utils/index.ts
518
- var sleep = (ms = 2e3) => new Promise((r) => setTimeout(r, ms));
519
- var CliError = class extends Error {
520
- };
521
-
522
- // src/features/analysis/index.ts
523
- import chalk4 from "chalk";
524
- import Configstore from "configstore";
525
- import Debug12 from "debug";
526
- import extract from "extract-zip";
527
- import fetch4 from "node-fetch";
528
- import open2 from "open";
529
- import semver from "semver";
530
- import tmp2 from "tmp";
531
- import { z as z12 } from "zod";
532
-
533
- // src/features/analysis/add_fix_comments_for_pr/add_fix_comments_for_pr.ts
534
- import Debug4 from "debug";
535
-
536
- // src/features/analysis/scm/types.ts
537
- var ReferenceType = /* @__PURE__ */ ((ReferenceType2) => {
538
- ReferenceType2["BRANCH"] = "BRANCH";
539
- ReferenceType2["COMMIT"] = "COMMIT";
540
- ReferenceType2["TAG"] = "TAG";
541
- return ReferenceType2;
542
- })(ReferenceType || {});
543
- var ScmLibScmType = /* @__PURE__ */ ((ScmLibScmType2) => {
544
- ScmLibScmType2["GITHUB"] = "GITHUB";
545
- ScmLibScmType2["GITLAB"] = "GITLAB";
546
- ScmLibScmType2["ADO"] = "ADO";
547
- ScmLibScmType2["BITBUCKET"] = "BITBUCKET";
548
- return ScmLibScmType2;
549
- })(ScmLibScmType || {});
550
- var scmCloudUrl = {
551
- GitLab: "https://gitlab.com",
552
- GitHub: "https://github.com",
553
- Ado: "https://dev.azure.com",
554
- Bitbucket: "https://bitbucket.org"
555
- };
556
- var ScmType = /* @__PURE__ */ ((ScmType2) => {
557
- ScmType2["GitHub"] = "GitHub";
558
- ScmType2["GitLab"] = "GitLab";
559
- ScmType2["Ado"] = "Ado";
560
- ScmType2["Bitbucket"] = "Bitbucket";
561
- return ScmType2;
562
- })(ScmType || {});
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
-
593
- // src/features/analysis/scm/urlParser.ts
594
- function detectAdoUrl(args) {
595
- const { pathname, hostname, scmType } = args;
596
- const hostnameParts = hostname.split(".");
597
- const adoHostname = new URL(scmCloudUrl.Ado).hostname;
598
- if (hostnameParts.length === 3 && hostnameParts[1] === "visualstudio" && hostnameParts[2] === "com") {
599
- if (pathname.length === 2 && pathname[0] === "_git") {
600
- return {
601
- organization: hostnameParts[0],
602
- projectName: pathname[1],
603
- repoName: pathname[1]
604
- };
605
- }
606
- if (pathname.length === 3 && pathname[1] === "_git") {
607
- return {
608
- organization: hostnameParts[0],
609
- projectName: pathname[0],
610
- repoName: pathname[2]
611
- };
612
- }
613
- }
614
- if (hostname === adoHostname || scmType === "Ado" /* Ado */) {
615
- if (pathname.length === 3 && pathname[1] === "_git") {
616
- return {
617
- organization: pathname[0],
618
- projectName: pathname[2],
619
- repoName: pathname[2]
620
- };
621
- }
622
- if (pathname.length === 4 && pathname[2] === "_git") {
623
- return {
624
- organization: pathname[0],
625
- projectName: pathname[1],
626
- repoName: pathname[3]
627
- };
628
- }
629
- }
630
- return null;
631
- }
632
- function detectGithubUrl(args) {
633
- const { pathname, hostname, scmType } = args;
634
- const githubHostname = new URL(scmCloudUrl.GitHub).hostname;
635
- if (hostname === githubHostname || scmType === "GitHub" /* GitHub */) {
636
- if (pathname.length === 2) {
637
- return {
638
- organization: pathname[0],
639
- projectName: void 0,
640
- repoName: pathname[1]
641
- };
642
- }
643
- }
644
- return null;
645
- }
646
- function detectGitlabUrl(args) {
647
- const { pathname, hostname, scmType } = args;
648
- const gitlabHostname = new URL(scmCloudUrl.GitLab).hostname;
649
- if (hostname === gitlabHostname || scmType === "GitLab" /* GitLab */) {
650
- if (pathname.length >= 2) {
651
- return {
652
- organization: pathname[0],
653
- projectName: void 0,
654
- repoName: pathname[pathname.length - 1]
655
- };
656
- }
657
- }
658
- return null;
659
- }
660
- function detectBitbucketUrl(args) {
661
- const { pathname, hostname, scmType } = args;
662
- const bitbucketHostname = new URL(scmCloudUrl.Bitbucket).hostname;
663
- if (hostname === bitbucketHostname || scmType === "Bitbucket" /* Bitbucket */) {
664
- if (pathname.length === 2) {
665
- return {
666
- organization: pathname[0],
667
- projectName: void 0,
668
- repoName: pathname[1]
669
- };
670
- }
671
- }
672
- return null;
673
- }
674
- var getRepoUrlFunctionMap = {
675
- ["GitLab" /* GitLab */]: detectGitlabUrl,
676
- ["GitHub" /* GitHub */]: detectGithubUrl,
677
- ["Ado" /* Ado */]: detectAdoUrl,
678
- ["Bitbucket" /* Bitbucket */]: detectBitbucketUrl
679
- };
680
- function getRepoInfo(args) {
681
- for (const detectUrl of Object.values(getRepoUrlFunctionMap)) {
682
- const detectUrlRes = detectUrl(args);
683
- if (detectUrlRes) {
684
- return detectUrlRes;
685
- }
686
- }
687
- return null;
688
- }
689
- var NAME_REGEX = /[a-z0-9\-_.+]+/i;
690
203
  var parseScmURL = (scmURL, scmType) => {
691
204
  try {
692
205
  const url = new URL(scmURL);
@@ -699,41 +212,55 @@ var parseScmURL = (scmURL, scmType) => {
699
212
  });
700
213
  if (!repo)
701
214
  return null;
702
- const { organization, repoName, projectName } = repo;
215
+ const { organization, repoName } = repo;
703
216
  if (!organization || !repoName)
704
217
  return null;
705
218
  if (!organization.match(NAME_REGEX) || !repoName.match(NAME_REGEX))
706
- return null;
707
- return {
708
- hostname,
709
- organization,
710
- projectPath,
711
- repoName,
712
- projectName,
713
- protocol: url.protocol,
714
- pathElements: projectPath.split("/")
715
- };
716
- } catch (e) {
717
- return null;
718
- }
719
- };
720
- var sanityRepoURL = (scmURL) => {
721
- try {
722
- const url = new URL(scmURL);
723
- const projectPath = url.pathname.substring(1).replace(/.git$/i, "");
724
- const pathParts = projectPath.split("/");
725
- if (pathParts.length < 2)
726
- return false;
727
- if (pathParts.length > 4)
728
- return false;
729
- if (pathParts.some((part) => !part.match(NAME_REGEX)))
730
- return false;
731
- return true;
219
+ return null;
220
+ const res = {
221
+ hostname,
222
+ organization,
223
+ projectPath,
224
+ repoName,
225
+ protocol: url.protocol,
226
+ pathElements: projectPath.split("/")
227
+ };
228
+ if (repo.scmType === "Ado" /* Ado */) {
229
+ return {
230
+ projectName: repo.projectName,
231
+ prefixPath: repo.prefixPath,
232
+ scmType: repo.scmType,
233
+ ...res
234
+ };
235
+ }
236
+ return {
237
+ scmType: repo.scmType,
238
+ ...res
239
+ };
732
240
  } catch (e) {
733
241
  return null;
734
242
  }
735
243
  };
736
244
 
245
+ // src/features/analysis/scm/shared/src/index.ts
246
+ var NAME_REGEX = /[a-z0-9\-_.+]+/i;
247
+ var ADO_PREFIX_PATH = "tfs";
248
+
249
+ // src/features/analysis/scm/types.ts
250
+ var ReferenceType = /* @__PURE__ */ ((ReferenceType2) => {
251
+ ReferenceType2["BRANCH"] = "BRANCH";
252
+ ReferenceType2["COMMIT"] = "COMMIT";
253
+ ReferenceType2["TAG"] = "TAG";
254
+ return ReferenceType2;
255
+ })(ReferenceType || {});
256
+ var ScmLibScmType = /* @__PURE__ */ ((ScmLibScmType2) => {
257
+ ScmLibScmType2["GITHUB"] = "GITHUB";
258
+ ScmLibScmType2["GITLAB"] = "GITLAB";
259
+ ScmLibScmType2["ADO"] = "ADO";
260
+ ScmLibScmType2["BITBUCKET"] = "BITBUCKET";
261
+ return ScmLibScmType2;
262
+ })(ScmLibScmType || {});
263
+
737
264
  // src/features/analysis/scm/utils/get_issue_type.ts
738
265
  var getIssueType = (issueType) => {
739
266
  switch (issueType) {
@@ -942,6 +469,22 @@ var isUrlHasPath = (url) => {
942
469
  function shouldValidateUrl(repoUrl) {
943
470
  return repoUrl && isUrlHasPath(repoUrl);
944
471
  }
472
+ var sanityRepoURL = (scmURL) => {
473
+ try {
474
+ const url = new URL(scmURL);
475
+ const projectPath = url.pathname.substring(1).replace(/.git$/i, "");
476
+ const pathParts = projectPath.split("/");
477
+ if (pathParts.length < 2)
478
+ return false;
479
+ if (pathParts.length > 4 && pathParts.at(0) !== ADO_PREFIX_PATH)
480
+ return false;
481
+ if (pathParts.some((part) => !part.match(NAME_REGEX)))
482
+ return false;
483
+ return true;
484
+ } catch (e) {
485
+ return null;
486
+ }
487
+ };
945
488
 
946
489
  // src/features/analysis/scm/bitbucket/bitbucket.ts
947
490
  var BITBUCKET_HOSTNAME = "bitbucket.org";
@@ -2061,7 +1604,7 @@ initGitlabFetchMock();
2061
1604
  // src/features/analysis/scm/scmSubmit/index.ts
2062
1605
  import fs from "node:fs/promises";
2063
1606
  import parseDiff from "parse-diff";
2064
- import path3 from "path";
1607
+ import path from "path";
2065
1608
  import { simpleGit } from "simple-git";
2066
1609
  import tmp from "tmp";
2067
1610
  import { z as z6 } from "zod";
@@ -2193,10 +1736,10 @@ function getCloudScmLibTypeFromUrl(url) {
2193
1736
  return void 0;
2194
1737
  }
2195
1738
  var scmCloudHostname = {
2196
- GitLab: new URL(scmCloudUrl.GitLab).hostname,
2197
- GitHub: new URL(scmCloudUrl.GitHub).hostname,
2198
- Ado: new URL(scmCloudUrl.Ado).hostname,
2199
- Bitbucket: new URL(scmCloudUrl.Bitbucket).hostname
1739
+ ["GitLab" /* GitLab */]: new URL(scmCloudUrl.GitLab).hostname,
1740
+ ["GitHub" /* GitHub */]: new URL(scmCloudUrl.GitHub).hostname,
1741
+ ["Ado" /* Ado */]: new URL(scmCloudUrl.Ado).hostname,
1742
+ ["Bitbucket" /* Bitbucket */]: new URL(scmCloudUrl.Bitbucket).hostname
2200
1743
  };
2201
1744
  var scmLibScmTypeToScmType = {
2202
1745
  ["GITLAB" /* GITLAB */]: "GitLab" /* GitLab */,
@@ -2210,10 +1753,6 @@ var scmTypeToScmLibScmType = {
2210
1753
  ["Ado" /* Ado */]: "ADO" /* ADO */,
2211
1754
  ["Bitbucket" /* Bitbucket */]: "BITBUCKET" /* BITBUCKET */
2212
1755
  };
2213
- function getScmTypeFromScmLibType(scmLibType) {
2214
- const parsedScmLibType = z7.nativeEnum(ScmLibScmType).parse(scmLibType);
2215
- return scmLibScmTypeToScmType[parsedScmLibType];
2216
- }
2217
1756
  function getScmLibTypeFromScmType(scmType) {
2218
1757
  const parsedScmType = z7.nativeEnum(ScmType).parse(scmType);
2219
1758
  return scmTypeToScmLibScmType[parsedScmType];
@@ -2269,24 +1808,6 @@ function getScmConfig({
2269
1808
  scmOrg: void 0
2270
1809
  };
2271
1810
  }
2272
- async function scmCanReachRepo({
2273
- repoUrl,
2274
- scmType,
2275
- accessToken,
2276
- scmOrg
2277
- }) {
2278
- try {
2279
- await SCMLib.init({
2280
- url: repoUrl,
2281
- accessToken,
2282
- scmType: getScmLibTypeFromScmType(scmType),
2283
- scmOrg
2284
- });
2285
- return true;
2286
- } catch (e) {
2287
- return false;
2288
- }
2289
- }
2290
1811
  var InvalidRepoUrlError = class extends Error {
2291
1812
  constructor(m) {
2292
1813
  super(m);
@@ -2405,12 +1926,7 @@ var SCMLib = class {
2405
1926
  static async getIsValidBranchName(branchName) {
2406
1927
  return isValidBranchName(branchName);
2407
1928
  }
2408
- static async init({
2409
- url,
2410
- accessToken,
2411
- scmType,
2412
- scmOrg
2413
- }) {
1929
+ static async init({ url, accessToken, scmType, scmOrg }, { propagateExceptions = false } = {}) {
2414
1930
  const trimmedUrl = url ? url.trim().replace(/\/$/, "").replace(/.git$/i, "") : void 0;
2415
1931
  try {
2416
1932
  switch (scmType) {
@@ -2443,6 +1959,9 @@ var SCMLib = class {
2443
1959
  );
2444
1960
  }
2445
1961
  console.error(`error validating scm: ${scmType} `, e);
1962
+ if (propagateExceptions) {
1963
+ throw e;
1964
+ }
2446
1965
  }
2447
1966
  return new StubSCMLib(trimmedUrl, void 0, void 0);
2448
1967
  }
@@ -2941,792 +2460,1360 @@ var GithubSCMLib = class extends SCMLib {
2941
2460
  async postGeneralPrComment(params) {
2942
2461
  const { prNumber, body } = params;
2943
2462
  this._validateAccessTokenAndUrl();
2944
- const { owner, repo } = parseGithubOwnerAndRepo(this.url);
2945
- return await this.githubSdk.postGeneralPrComment({
2946
- issue_number: prNumber,
2947
- owner,
2948
- repo,
2949
- body
2950
- });
2463
+ const { owner, repo } = parseGithubOwnerAndRepo(this.url);
2464
+ return await this.githubSdk.postGeneralPrComment({
2465
+ issue_number: prNumber,
2466
+ owner,
2467
+ repo,
2468
+ body
2469
+ });
2470
+ }
2471
+ async getGeneralPrComments(params) {
2472
+ const { prNumber } = params;
2473
+ this._validateAccessTokenAndUrl();
2474
+ const { owner, repo } = parseGithubOwnerAndRepo(this.url);
2475
+ return await this.githubSdk.getGeneralPrComments({
2476
+ issue_number: prNumber,
2477
+ owner,
2478
+ repo
2479
+ });
2480
+ }
2481
+ async deleteGeneralPrComment({
2482
+ commentId
2483
+ }) {
2484
+ this._validateAccessTokenAndUrl();
2485
+ const { owner, repo } = parseGithubOwnerAndRepo(this.url);
2486
+ return this.githubSdk.deleteGeneralPrComment({
2487
+ owner,
2488
+ repo,
2489
+ comment_id: commentId
2490
+ });
2491
+ }
2492
+ };
2493
+ var StubSCMLib = class extends SCMLib {
2494
+ async createSubmitRequest(_params) {
2495
+ console.error("createSubmitRequest() not implemented");
2496
+ throw new Error("createSubmitRequest() not implemented");
2497
+ }
2498
+ getScmLibType() {
2499
+ console.error("getScmLibType() not implemented");
2500
+ throw new Error("getScmLibType() not implemented");
2501
+ }
2502
+ getAuthHeaders() {
2503
+ console.error("getAuthHeaders() not implemented");
2504
+ throw new Error("getAuthHeaders() not implemented");
2505
+ }
2506
+ getDownloadUrl(_sha) {
2507
+ console.error("getDownloadUrl() not implemented");
2508
+ throw new Error("getDownloadUrl() not implemented");
2509
+ }
2510
+ async getIsRemoteBranch(_branch) {
2511
+ console.error("getIsRemoteBranch() not implemented");
2512
+ throw new Error("getIsRemoteBranch() not implemented");
2513
+ }
2514
+ async validateParams() {
2515
+ console.error("validateParams() not implemented");
2516
+ throw new Error("validateParams() not implemented");
2517
+ }
2518
+ async getRepoList(_scmOrg) {
2519
+ console.error("getRepoList() not implemented");
2520
+ throw new Error("getRepoList() not implemented");
2521
+ }
2522
+ async getBranchList() {
2523
+ console.error("getBranchList() not implemented");
2524
+ throw new Error("getBranchList() not implemented");
2525
+ }
2526
+ async getUsername() {
2527
+ console.error("getUsername() not implemented");
2528
+ throw new Error("getUsername() not implemented");
2529
+ }
2530
+ async getSubmitRequestStatus(_scmSubmitRequestId) {
2531
+ console.error("getSubmitRequestStatus() not implemented");
2532
+ throw new Error("getSubmitRequestStatus() not implemented");
2533
+ }
2534
+ async getUserHasAccessToRepo() {
2535
+ console.error("getUserHasAccessToRepo() not implemented");
2536
+ throw new Error("getUserHasAccessToRepo() not implemented");
2537
+ }
2538
+ async getRepoBlameRanges(_ref, _path) {
2539
+ console.error("getRepoBlameRanges() not implemented");
2540
+ throw new Error("getRepoBlameRanges() not implemented");
2541
+ }
2542
+ async getReferenceData(_ref) {
2543
+ console.error("getReferenceData() not implemented");
2544
+ throw new Error("getReferenceData() not implemented");
2545
+ }
2546
+ async getRepoDefaultBranch() {
2547
+ console.error("getRepoDefaultBranch() not implemented");
2548
+ throw new Error("getRepoDefaultBranch() not implemented");
2549
+ }
2550
+ async getPrUrl(_prNumber) {
2551
+ console.error("getPr() not implemented");
2552
+ throw new Error("getPr() not implemented");
2553
+ }
2554
+ _getUsernameForAuthUrl() {
2555
+ throw new Error("Method not implemented.");
2556
+ }
2557
+ };
2558
+ function getUserAndPassword(token) {
2559
+ const [username, password] = token.split(":");
2560
+ const safePasswordAndUsername = z7.object({ username: z7.string(), password: z7.string() }).parse({ username, password });
2561
+ return {
2562
+ username: safePasswordAndUsername.username,
2563
+ password: safePasswordAndUsername.password
2564
+ };
2565
+ }
2566
+ function createBitbucketSdk(token) {
2567
+ if (!token) {
2568
+ return getBitbucketSdk({ authType: "public" });
2569
+ }
2570
+ if (token.includes(":")) {
2571
+ const { password, username } = getUserAndPassword(token);
2572
+ return getBitbucketSdk({
2573
+ authType: "basic",
2574
+ username,
2575
+ password
2576
+ });
2577
+ }
2578
+ return getBitbucketSdk({ authType: "token", token });
2579
+ }
2580
+ var BitbucketSCMLib = class extends SCMLib {
2581
+ constructor(url, accessToken, scmOrg) {
2582
+ super(url, accessToken, scmOrg);
2583
+ __publicField(this, "bitbucketSdk");
2584
+ const bitbucketSdk = createBitbucketSdk(accessToken);
2585
+ this.bitbucketSdk = bitbucketSdk;
2586
+ }
2587
+ getAuthData() {
2588
+ const authType = this.bitbucketSdk.getAuthType();
2589
+ switch (authType) {
2590
+ case "basic": {
2591
+ this._validateAccessToken();
2592
+ const { username, password } = getUserAndPassword(this.accessToken);
2593
+ return { username, password, authType };
2594
+ }
2595
+ case "token": {
2596
+ return { authType, token: z7.string().parse(this.accessToken) };
2597
+ }
2598
+ case "public":
2599
+ return { authType };
2600
+ }
2601
+ }
2602
+ async createSubmitRequest(params) {
2603
+ this._validateAccessTokenAndUrl();
2604
+ const pullRequestRes = await this.bitbucketSdk.createPullRequest({
2605
+ ...params,
2606
+ repoUrl: this.url
2607
+ });
2608
+ return String(z7.number().parse(pullRequestRes.id));
2609
+ }
2610
+ async validateParams() {
2611
+ return validateBitbucketParams({
2612
+ bitbucketClient: this.bitbucketSdk,
2613
+ url: this.url
2614
+ });
2615
+ }
2616
+ async getRepoList(scmOrg) {
2617
+ this._validateAccessToken();
2618
+ return this.bitbucketSdk.getRepos({
2619
+ workspaceSlug: scmOrg
2620
+ });
2621
+ }
2622
+ async getBranchList() {
2623
+ this._validateAccessTokenAndUrl();
2624
+ return this.bitbucketSdk.getBranchList({
2625
+ repoUrl: this.url
2626
+ });
2627
+ }
2628
+ getScmLibType() {
2629
+ return "BITBUCKET" /* BITBUCKET */;
2630
+ }
2631
+ getAuthHeaders() {
2632
+ const authType = this.bitbucketSdk.getAuthType();
2633
+ switch (authType) {
2634
+ case "public":
2635
+ return {};
2636
+ case "token":
2637
+ return { authorization: `Bearer ${this.accessToken}` };
2638
+ case "basic": {
2639
+ this._validateAccessToken();
2640
+ const { username, password } = getUserAndPassword(this.accessToken);
2641
+ return {
2642
+ authorization: `Basic ${Buffer.from(
2643
+ username + ":" + password
2644
+ ).toString("base64")}`
2645
+ };
2646
+ }
2647
+ }
2648
+ }
2649
+ async getDownloadUrl(sha) {
2650
+ this._validateUrl();
2651
+ return this.bitbucketSdk.getDownloadUrl({ url: this.url, sha });
2652
+ }
2653
+ async _getUsernameForAuthUrl() {
2654
+ this._validateAccessTokenAndUrl();
2655
+ const user = await this.bitbucketSdk.getUser();
2656
+ if (!user.username) {
2657
+ throw new Error("no username found");
2658
+ }
2659
+ return user.username;
2951
2660
  }
2952
- async getGeneralPrComments(params) {
2953
- const { prNumber } = params;
2661
+ async getIsRemoteBranch(branch) {
2954
2662
  this._validateAccessTokenAndUrl();
2955
- const { owner, repo } = parseGithubOwnerAndRepo(this.url);
2956
- return await this.githubSdk.getGeneralPrComments({
2957
- issue_number: prNumber,
2958
- owner,
2959
- repo
2960
- });
2663
+ try {
2664
+ const res = await this.bitbucketSdk.getBranch({
2665
+ branchName: branch,
2666
+ repoUrl: this.url
2667
+ });
2668
+ return res.name === branch;
2669
+ } catch (e) {
2670
+ return false;
2671
+ }
2961
2672
  }
2962
- async deleteGeneralPrComment({
2963
- commentId
2964
- }) {
2673
+ async getUserHasAccessToRepo() {
2965
2674
  this._validateAccessTokenAndUrl();
2966
- const { owner, repo } = parseGithubOwnerAndRepo(this.url);
2967
- return this.githubSdk.deleteGeneralPrComment({
2968
- owner,
2969
- repo,
2970
- comment_id: commentId
2971
- });
2675
+ return this.bitbucketSdk.getIsUserCollaborator({ repoUrl: this.url });
2972
2676
  }
2973
- };
2974
- var StubSCMLib = class extends SCMLib {
2975
- async createSubmitRequest(_params) {
2976
- console.error("createSubmitRequest() not implemented");
2977
- throw new Error("createSubmitRequest() not implemented");
2677
+ async getUsername() {
2678
+ this._validateAccessToken();
2679
+ const res = await this.bitbucketSdk.getUser();
2680
+ return z7.string().parse(res.username);
2978
2681
  }
2979
- getScmLibType() {
2980
- console.error("getScmLibType() not implemented");
2981
- throw new Error("getScmLibType() not implemented");
2682
+ async getSubmitRequestStatus(_scmSubmitRequestId) {
2683
+ this._validateAccessTokenAndUrl();
2684
+ const pullRequestRes = await this.bitbucketSdk.getPullRequest({
2685
+ prNumber: Number(_scmSubmitRequestId),
2686
+ url: this.url
2687
+ });
2688
+ switch (pullRequestRes.state) {
2689
+ case "OPEN":
2690
+ return "open";
2691
+ case "MERGED":
2692
+ return "merged";
2693
+ case "DECLINED":
2694
+ return "closed";
2695
+ default:
2696
+ throw new Error(`unknown state ${pullRequestRes.state} `);
2697
+ }
2982
2698
  }
2983
- getAuthHeaders() {
2984
- console.error("getAuthHeaders() not implemented");
2985
- throw new Error("getAuthHeaders() not implemented");
2699
+ async getRepoBlameRanges(_ref, _path) {
2700
+ return [];
2986
2701
  }
2987
- getDownloadUrl(_sha) {
2988
- console.error("getDownloadUrl() not implemented");
2989
- throw new Error("getDownloadUrl() not implemented");
2702
+ async getReferenceData(ref) {
2703
+ this._validateUrl();
2704
+ return this.bitbucketSdk.getReferenceData({ url: this.url, ref });
2990
2705
  }
2991
- async getIsRemoteBranch(_branch) {
2992
- console.error("getIsRemoteBranch() not implemented");
2993
- throw new Error("getIsRemoteBranch() not implemented");
2706
+ async getRepoDefaultBranch() {
2707
+ this._validateUrl();
2708
+ const repoRes = await this.bitbucketSdk.getRepo({ repoUrl: this.url });
2709
+ return z7.string().parse(repoRes.mainbranch?.name);
2994
2710
  }
2995
- async validateParams() {
2996
- console.error("validateParams() not implemented");
2997
- throw new Error("validateParams() not implemented");
2711
+ getPrUrl(prNumber) {
2712
+ this._validateUrl();
2713
+ const { repoSlug, workspace } = parseBitbucketOrganizationAndRepo(this.url);
2714
+ return Promise.resolve(
2715
+ `https://bitbucket.org/${workspace}/${repoSlug}/pull-requests/${prNumber}`
2716
+ );
2998
2717
  }
2999
- async getRepoList(_scmOrg) {
3000
- console.error("getRepoList() not implemented");
3001
- throw new Error("getRepoList() not implemented");
2718
+ async refreshToken(params) {
2719
+ const getBitbucketTokenResponse = await getBitbucketToken({
2720
+ authType: "refresh_token",
2721
+ ...params
2722
+ });
2723
+ return {
2724
+ accessToken: getBitbucketTokenResponse.access_token,
2725
+ refreshToken: getBitbucketTokenResponse.refresh_token
2726
+ };
3002
2727
  }
3003
- async getBranchList() {
3004
- console.error("getBranchList() not implemented");
3005
- throw new Error("getBranchList() not implemented");
2728
+ };
2729
+
2730
+ // src/features/analysis/scm/ado/validation.ts
2731
+ import { z as z8 } from "zod";
2732
+ var ValidPullRequestStatusZ = z8.union([
2733
+ z8.literal(1 /* Active */),
2734
+ z8.literal(2 /* Abandoned */),
2735
+ z8.literal(3 /* Completed */)
2736
+ ]);
2737
+ var AdoAuthResultZ = z8.object({
2738
+ access_token: z8.string().min(1),
2739
+ token_type: z8.string().min(1),
2740
+ refresh_token: z8.string().min(1)
2741
+ });
2742
+ var profileZ = z8.object({
2743
+ displayName: z8.string(),
2744
+ publicAlias: z8.string().min(1),
2745
+ emailAddress: z8.string(),
2746
+ coreRevision: z8.number(),
2747
+ timeStamp: z8.string(),
2748
+ id: z8.string(),
2749
+ revision: z8.number()
2750
+ });
2751
+ var accountsZ = z8.object({
2752
+ count: z8.number(),
2753
+ value: z8.array(
2754
+ z8.object({
2755
+ accountId: z8.string(),
2756
+ accountUri: z8.string(),
2757
+ accountName: z8.string()
2758
+ })
2759
+ )
2760
+ });
2761
+
2762
+ // src/features/analysis/scm/ado/utils.ts
2763
+ function _getPublicAdoClient({
2764
+ orgName,
2765
+ origin: origin2
2766
+ }) {
2767
+ const orgUrl = `${origin2}/${orgName}`;
2768
+ const authHandler = api.getPersonalAccessTokenHandler("");
2769
+ authHandler.canHandleAuthentication = () => false;
2770
+ authHandler.prepareRequest = (_options) => {
2771
+ return;
2772
+ };
2773
+ const connection = new api.WebApi(orgUrl, authHandler);
2774
+ return connection;
2775
+ }
2776
+ function removeTrailingSlash2(str) {
2777
+ return str.trim().replace(/\/+$/, "");
2778
+ }
2779
+ function parseAdoOwnerAndRepo(adoUrl) {
2780
+ adoUrl = removeTrailingSlash2(adoUrl);
2781
+ const parsingResult = parseScmURL(adoUrl, "Ado" /* Ado */);
2782
+ if (!parsingResult || parsingResult.scmType !== "Ado" /* Ado */) {
2783
+ throw new InvalidUrlPatternError(`
2784
+ : ${adoUrl}`);
3006
2785
  }
3007
- async getUsername() {
3008
- console.error("getUsername() not implemented");
3009
- throw new Error("getUsername() not implemented");
2786
+ const {
2787
+ organization,
2788
+ repoName,
2789
+ projectName,
2790
+ projectPath,
2791
+ pathElements,
2792
+ hostname,
2793
+ protocol
2794
+ } = parsingResult;
2795
+ return {
2796
+ owner: decodeURI(organization),
2797
+ repo: decodeURI(repoName),
2798
+ projectName: projectName ? decodeURI(projectName) : void 0,
2799
+ projectPath,
2800
+ pathElements,
2801
+ prefixPath: parsingResult.prefixPath,
2802
+ origin: `${protocol}//${hostname}`
2803
+ };
2804
+ }
2805
+ async function getAdoConnectData({
2806
+ url,
2807
+ tokenOrg,
2808
+ adoTokenInfo
2809
+ }) {
2810
+ if (url) {
2811
+ const urlObject = new URL(url);
2812
+ if (tokenOrg && (urlObject.origin === url || `${urlObject.origin}/tfs` === url)) {
2813
+ return {
2814
+ origin: url,
2815
+ org: tokenOrg
2816
+ };
2817
+ }
2818
+ const { owner, origin: origin2, prefixPath } = parseAdoOwnerAndRepo(url);
2819
+ return {
2820
+ org: owner,
2821
+ origin: prefixPath ? `${origin2}/${prefixPath}` : origin2
2822
+ };
3010
2823
  }
3011
- async getSubmitRequestStatus(_scmSubmitRequestId) {
3012
- console.error("getSubmitRequestStatus() not implemented");
3013
- throw new Error("getSubmitRequestStatus() not implemented");
2824
+ if (!tokenOrg) {
2825
+ if (adoTokenInfo.type === "OAUTH" /* OAUTH */) {
2826
+ const [org] = await _getOrgsForOauthToken({
2827
+ oauthToken: adoTokenInfo.accessToken
2828
+ });
2829
+ return {
2830
+ org: z9.string().parse(org),
2831
+ origin: DEFUALT_ADO_ORIGIN
2832
+ };
2833
+ }
2834
+ throw new InvalidRepoUrlError("ADO URL is null");
3014
2835
  }
3015
- async getUserHasAccessToRepo() {
3016
- console.error("getUserHasAccessToRepo() not implemented");
3017
- throw new Error("getUserHasAccessToRepo() not implemented");
2836
+ return {
2837
+ org: tokenOrg,
2838
+ origin: DEFUALT_ADO_ORIGIN
2839
+ };
2840
+ }
2841
+ function isAdoOnCloud(url) {
2842
+ const urlObj = new URL(url);
2843
+ return urlObj.origin.toLowerCase() === DEFUALT_ADO_ORIGIN || urlObj.hostname.toLowerCase().endsWith(".visualstudio.com");
2844
+ }
2845
+ async function getAdoApiClient(params) {
2846
+ const { origin: origin2 = DEFUALT_ADO_ORIGIN, orgName } = params;
2847
+ if (params.tokenType === "NONE" /* NONE */ || // note: move to public client if the token is not associated with the PAT org
2848
+ // we're only doing it the ado on the cloud
2849
+ params.tokenType === "PAT" /* PAT */ && params.patTokenOrg !== orgName && isAdoOnCloud(origin2)) {
2850
+ return _getPublicAdoClient({ orgName, origin: origin2 });
3018
2851
  }
3019
- async getRepoBlameRanges(_ref, _path) {
3020
- console.error("getRepoBlameRanges() not implemented");
3021
- throw new Error("getRepoBlameRanges() not implemented");
2852
+ const orgUrl = `${origin2}/${orgName}`;
2853
+ if (params.tokenType === "OAUTH" /* OAUTH */) {
2854
+ if (isAdoOnCloud(origin2)) {
2855
+ throw new Error(
2856
+ `Oauth token is not supported for ADO on prem - ${origin2} `
2857
+ );
2858
+ }
2859
+ const connection2 = new api.WebApi(
2860
+ orgUrl,
2861
+ api.getBearerHandler(params.accessToken),
2862
+ {}
2863
+ );
2864
+ return connection2;
3022
2865
  }
3023
- async getReferenceData(_ref) {
3024
- console.error("getReferenceData() not implemented");
3025
- throw new Error("getReferenceData() not implemented");
2866
+ const authHandler = api.getPersonalAccessTokenHandler(params.accessToken);
2867
+ const isBroker = BROKERED_HOSTS.includes(new URL(orgUrl).origin);
2868
+ const connection = new api.WebApi(
2869
+ orgUrl,
2870
+ authHandler,
2871
+ isBroker ? {
2872
+ proxy: {
2873
+ proxyUrl: GIT_PROXY_HOST
2874
+ },
2875
+ ignoreSslError: true
2876
+ } : void 0
2877
+ );
2878
+ return connection;
2879
+ }
2880
+ function getAdoTokenInfo(token) {
2881
+ if (!token) {
2882
+ return { type: "NONE" /* NONE */ };
3026
2883
  }
3027
- async getRepoDefaultBranch() {
3028
- console.error("getRepoDefaultBranch() not implemented");
3029
- throw new Error("getRepoDefaultBranch() not implemented");
2884
+ if (token.includes(".")) {
2885
+ return { type: "OAUTH" /* OAUTH */, accessToken: token };
3030
2886
  }
3031
- async getPrUrl(_prNumber) {
3032
- console.error("getPr() not implemented");
3033
- throw new Error("getPr() not implemented");
2887
+ return { type: "PAT" /* PAT */, accessToken: token };
2888
+ }
2889
+ async function getAdoClientParams(params) {
2890
+ const { url, accessToken, tokenOrg } = params;
2891
+ const adoTokenInfo = getAdoTokenInfo(accessToken);
2892
+ const { org, origin: origin2 } = await getAdoConnectData({
2893
+ url,
2894
+ tokenOrg,
2895
+ adoTokenInfo
2896
+ });
2897
+ switch (adoTokenInfo.type) {
2898
+ case "NONE" /* NONE */:
2899
+ return {
2900
+ tokenType: "NONE" /* NONE */,
2901
+ origin: origin2,
2902
+ orgName: org.toLowerCase()
2903
+ };
2904
+ case "OAUTH" /* OAUTH */: {
2905
+ return {
2906
+ tokenType: "OAUTH" /* OAUTH */,
2907
+ accessToken: adoTokenInfo.accessToken,
2908
+ origin: origin2,
2909
+ orgName: org.toLowerCase()
2910
+ };
2911
+ }
2912
+ case "PAT" /* PAT */: {
2913
+ return {
2914
+ tokenType: "PAT" /* PAT */,
2915
+ accessToken: adoTokenInfo.accessToken,
2916
+ patTokenOrg: z9.string().parse(tokenOrg).toLowerCase(),
2917
+ origin: origin2,
2918
+ orgName: org.toLowerCase()
2919
+ };
2920
+ }
3034
2921
  }
3035
- _getUsernameForAuthUrl() {
3036
- throw new Error("Method not implemented.");
2922
+ }
2923
+ async function adoValidateParams({
2924
+ url,
2925
+ accessToken,
2926
+ tokenOrg
2927
+ }) {
2928
+ try {
2929
+ const api2 = await getAdoApiClient(
2930
+ await getAdoClientParams({ url, accessToken, tokenOrg })
2931
+ );
2932
+ await api2.connect();
2933
+ } catch (e) {
2934
+ console.log("adoValidateParams error", e);
2935
+ const error = e;
2936
+ const code = error.code || error.status || error.statusCode || error.response?.status || error.response?.statusCode || error.response?.code;
2937
+ const description = error.description || `${e}`;
2938
+ if (code === 401 || code === 403 || description.includes("401") || description.includes("403")) {
2939
+ throw new InvalidAccessTokenError(`invalid ADO access token`);
2940
+ }
2941
+ if (code === 404 || description.includes("404") || description.includes("Not Found")) {
2942
+ throw new InvalidRepoUrlError(`invalid ADO repo URL ${url}`);
2943
+ }
2944
+ throw e;
3037
2945
  }
3038
- };
3039
- function getUserAndPassword(token) {
3040
- const [username, password] = token.split(":");
3041
- const safePasswordAndUsername = z7.object({ username: z7.string(), password: z7.string() }).parse({ username, password });
2946
+ }
2947
+ async function _getOrgsForOauthToken({
2948
+ oauthToken
2949
+ }) {
2950
+ const profileRes = await fetch(
2951
+ "https://app.vssps.visualstudio.com/_apis/profile/profiles/me?api-version=6.0",
2952
+ {
2953
+ method: "GET",
2954
+ headers: {
2955
+ Authorization: `Bearer ${oauthToken}`
2956
+ }
2957
+ }
2958
+ );
2959
+ const profileJson = await profileRes.json();
2960
+ const profile = profileZ.parse(profileJson);
2961
+ const accountsRes = await fetch(
2962
+ `https://app.vssps.visualstudio.com/_apis/accounts?memberId=${profile.publicAlias}&api-version=6.0`,
2963
+ {
2964
+ method: "GET",
2965
+ headers: {
2966
+ Authorization: `Bearer ${oauthToken}`
2967
+ }
2968
+ }
2969
+ );
2970
+ const accountsJson = await accountsRes.json();
2971
+ const accounts = accountsZ.parse(accountsJson);
2972
+ const orgs = accounts.value.map((account) => account.accountName).filter((value, index, array) => array.indexOf(value) === index);
2973
+ return orgs;
2974
+ }
2975
+
2976
+ // src/features/analysis/scm/ado/ado.ts
2977
+ async function getAdoSdk(params) {
2978
+ const api2 = await getAdoApiClient(params);
3042
2979
  return {
3043
- username: safePasswordAndUsername.username,
3044
- password: safePasswordAndUsername.password
2980
+ async getAdoIsUserCollaborator({ repoUrl }) {
2981
+ try {
2982
+ const { repo, projectName } = parseAdoOwnerAndRepo(repoUrl);
2983
+ const git = await api2.getGitApi();
2984
+ const branches = await git.getBranches(repo, projectName);
2985
+ if (!branches || branches.length === 0) {
2986
+ throw new InvalidRepoUrlError("no branches");
2987
+ }
2988
+ return true;
2989
+ } catch (e) {
2990
+ return false;
2991
+ }
2992
+ },
2993
+ async getAdoPullRequestStatus({
2994
+ repoUrl,
2995
+ prNumber
2996
+ }) {
2997
+ const { repo, projectName } = parseAdoOwnerAndRepo(repoUrl);
2998
+ const git = await api2.getGitApi();
2999
+ const res = await git.getPullRequest(repo, prNumber, projectName);
3000
+ const parsedPullRequestStatus = ValidPullRequestStatusZ.safeParse(
3001
+ res.status
3002
+ );
3003
+ if (!parsedPullRequestStatus.success) {
3004
+ throw new Error("bad pr status for ADO");
3005
+ }
3006
+ return parsedPullRequestStatus.data;
3007
+ },
3008
+ async getAdoIsRemoteBranch({
3009
+ repoUrl,
3010
+ branch
3011
+ }) {
3012
+ const { repo, projectName } = parseAdoOwnerAndRepo(repoUrl);
3013
+ const git = await api2.getGitApi();
3014
+ try {
3015
+ const branchStatus = await git.getBranch(repo, branch, projectName);
3016
+ if (!branchStatus || !branchStatus.commit) {
3017
+ throw new InvalidRepoUrlError("no branch status");
3018
+ }
3019
+ return branchStatus.name === branch;
3020
+ } catch (e) {
3021
+ return false;
3022
+ }
3023
+ },
3024
+ async getAdoPrUrl({ url, prNumber }) {
3025
+ const { repo, projectName } = parseAdoOwnerAndRepo(url);
3026
+ const git = await api2.getGitApi();
3027
+ const getRepositoryRes = await git.getRepository(
3028
+ decodeURI(repo),
3029
+ projectName ? decodeURI(projectName) : void 0
3030
+ );
3031
+ return `${getRepositoryRes.webUrl}/pullrequest/${prNumber}`;
3032
+ },
3033
+ getAdoDownloadUrl({
3034
+ repoUrl,
3035
+ branch
3036
+ }) {
3037
+ const { owner, repo, projectName, prefixPath } = parseAdoOwnerAndRepo(repoUrl);
3038
+ const url = new URL(repoUrl);
3039
+ const origin2 = url.origin.toLowerCase().endsWith(".visualstudio.com") ? DEFUALT_ADO_ORIGIN : url.origin.toLowerCase();
3040
+ const params2 = `path=/&versionDescriptor[versionOptions]=0&versionDescriptor[versionType]=commit&versionDescriptor[version]=${branch}&resolveLfs=true&$format=zip&api-version=5.0&download=true`;
3041
+ const path9 = [
3042
+ prefixPath,
3043
+ owner,
3044
+ projectName,
3045
+ "_apis",
3046
+ "git",
3047
+ "repositories",
3048
+ repo,
3049
+ "items",
3050
+ "items"
3051
+ ].filter(Boolean).join("/");
3052
+ return new URL(`${path9}?${params2}`, origin2).toString();
3053
+ },
3054
+ async getAdoBranchList({ repoUrl }) {
3055
+ const { repo, projectName } = parseAdoOwnerAndRepo(repoUrl);
3056
+ const git = await api2.getGitApi();
3057
+ try {
3058
+ const res = await git.getBranches(repo, projectName);
3059
+ res.sort((a, b) => {
3060
+ if (!a.commit?.committer?.date || !b.commit?.committer?.date) {
3061
+ return 0;
3062
+ }
3063
+ return b.commit?.committer?.date.getTime() - a.commit?.committer?.date.getTime();
3064
+ });
3065
+ return res.reduce((acc, branch) => {
3066
+ if (!branch.name) {
3067
+ return acc;
3068
+ }
3069
+ acc.push(branch.name);
3070
+ return acc;
3071
+ }, []);
3072
+ } catch (e) {
3073
+ return [];
3074
+ }
3075
+ },
3076
+ async createAdoPullRequest(options) {
3077
+ const { repoUrl, sourceBranchName, targetBranchName, title, body } = options;
3078
+ const { repo, projectName } = parseAdoOwnerAndRepo(repoUrl);
3079
+ const git = await api2.getGitApi();
3080
+ const res = await git.createPullRequest(
3081
+ {
3082
+ sourceRefName: `refs/heads/${sourceBranchName}`,
3083
+ targetRefName: `refs/heads/${targetBranchName}`,
3084
+ title,
3085
+ description: body
3086
+ },
3087
+ repo,
3088
+ projectName
3089
+ );
3090
+ return res.pullRequestId;
3091
+ },
3092
+ async getAdoRepoDefaultBranch({
3093
+ repoUrl
3094
+ }) {
3095
+ const { repo, projectName } = parseAdoOwnerAndRepo(repoUrl);
3096
+ const git = await api2.getGitApi();
3097
+ const getRepositoryRes = await git.getRepository(
3098
+ decodeURI(repo),
3099
+ projectName ? decodeURI(projectName) : void 0
3100
+ );
3101
+ if (!getRepositoryRes?.defaultBranch) {
3102
+ throw new InvalidRepoUrlError("no default branch");
3103
+ }
3104
+ return getRepositoryRes.defaultBranch.replace("refs/heads/", "");
3105
+ },
3106
+ // todo: refactor this function
3107
+ async getAdoReferenceData({
3108
+ ref,
3109
+ repoUrl
3110
+ }) {
3111
+ const { repo, projectName } = parseAdoOwnerAndRepo(repoUrl);
3112
+ if (!projectName) {
3113
+ throw new InvalidUrlPatternError("no project name");
3114
+ }
3115
+ const git = await api2.getGitApi();
3116
+ const results = await Promise.allSettled([
3117
+ (async () => {
3118
+ const res = await git.getBranch(repo, ref, projectName);
3119
+ if (!res.commit || !res.commit.commitId) {
3120
+ throw new InvalidRepoUrlError("no commit on branch");
3121
+ }
3122
+ return {
3123
+ sha: res.commit.commitId,
3124
+ type: "BRANCH" /* BRANCH */,
3125
+ date: res.commit.committer?.date || /* @__PURE__ */ new Date()
3126
+ };
3127
+ })(),
3128
+ (async () => {
3129
+ const res = await git.getCommits(
3130
+ repo,
3131
+ {
3132
+ fromCommitId: ref,
3133
+ toCommitId: ref,
3134
+ $top: 1
3135
+ },
3136
+ projectName
3137
+ );
3138
+ const commit = res[0];
3139
+ if (!commit || !commit.commitId) {
3140
+ throw new Error("no commit");
3141
+ }
3142
+ return {
3143
+ sha: commit.commitId,
3144
+ type: "COMMIT" /* COMMIT */,
3145
+ date: commit.committer?.date || /* @__PURE__ */ new Date()
3146
+ };
3147
+ })(),
3148
+ (async () => {
3149
+ const res = await git.getRefs(repo, projectName, `tags/${ref}`);
3150
+ if (!res[0] || !res[0].objectId) {
3151
+ throw new Error("no tag ref");
3152
+ }
3153
+ let objectId = res[0].objectId;
3154
+ try {
3155
+ const tag = await git.getAnnotatedTag(projectName, repo, objectId);
3156
+ if (tag.taggedObject?.objectId) {
3157
+ objectId = tag.taggedObject.objectId;
3158
+ }
3159
+ } catch (e) {
3160
+ }
3161
+ const commitRes2 = await git.getCommits(
3162
+ repo,
3163
+ {
3164
+ fromCommitId: objectId,
3165
+ toCommitId: objectId,
3166
+ $top: 1
3167
+ },
3168
+ projectName
3169
+ );
3170
+ const commit = commitRes2[0];
3171
+ if (!commit) {
3172
+ throw new Error("no commit");
3173
+ }
3174
+ return {
3175
+ sha: objectId,
3176
+ type: "TAG" /* TAG */,
3177
+ date: commit.committer?.date || /* @__PURE__ */ new Date()
3178
+ };
3179
+ })()
3180
+ ]);
3181
+ const [branchRes, commitRes, tagRes] = results;
3182
+ if (tagRes.status === "fulfilled") {
3183
+ return tagRes.value;
3184
+ }
3185
+ if (branchRes.status === "fulfilled") {
3186
+ return branchRes.value;
3187
+ }
3188
+ if (commitRes.status === "fulfilled") {
3189
+ return commitRes.value;
3190
+ }
3191
+ throw new RefNotFoundError(`ref: ${ref} does not exist`);
3192
+ },
3193
+ getAdoBlameRanges() {
3194
+ return [];
3195
+ }
3045
3196
  };
3046
3197
  }
3047
- function createBitbucketSdk(token) {
3048
- if (!token) {
3049
- return getBitbucketSdk({ authType: "public" });
3198
+ async function getAdoRepoList({
3199
+ orgName,
3200
+ tokenOrg,
3201
+ accessToken
3202
+ }) {
3203
+ let orgs = [];
3204
+ const adoTokenInfo = getAdoTokenInfo(accessToken);
3205
+ if (adoTokenInfo.type === "NONE" /* NONE */) {
3206
+ return [];
3050
3207
  }
3051
- if (token.includes(":")) {
3052
- const { password, username } = getUserAndPassword(token);
3053
- return getBitbucketSdk({
3054
- authType: "basic",
3055
- username,
3056
- password
3057
- });
3208
+ if (adoTokenInfo.type === "OAUTH" /* OAUTH */) {
3209
+ orgs = await _getOrgsForOauthToken({ oauthToken: accessToken });
3058
3210
  }
3059
- return getBitbucketSdk({ authType: "token", token });
3211
+ if (orgs.length === 0 && !orgName) {
3212
+ throw new Error(`no orgs for ADO`);
3213
+ } else if (orgs.length === 0 && orgName) {
3214
+ orgs = [orgName];
3215
+ }
3216
+ const repos = (await Promise.allSettled(
3217
+ orgs.map(async (org) => {
3218
+ const orgApi = await getAdoApiClient({
3219
+ ...await getAdoClientParams({
3220
+ accessToken,
3221
+ tokenOrg: tokenOrg || org,
3222
+ url: void 0
3223
+ }),
3224
+ orgName: org
3225
+ });
3226
+ const gitOrg = await orgApi.getGitApi();
3227
+ const orgRepos = await gitOrg.getRepositories();
3228
+ const repoInfoList = (await Promise.allSettled(
3229
+ orgRepos.map(async (repo) => {
3230
+ if (!repo.name || !repo.remoteUrl || !repo.defaultBranch) {
3231
+ throw new InvalidRepoUrlError("bad repo");
3232
+ }
3233
+ const branch = await gitOrg.getBranch(
3234
+ repo.name,
3235
+ repo.defaultBranch.replace(/^refs\/heads\//, ""),
3236
+ repo.project?.name
3237
+ );
3238
+ return {
3239
+ repoName: repo.name,
3240
+ repoUrl: repo.remoteUrl.replace(
3241
+ /^[hH][tT][tT][pP][sS]:\/\/[^/]+@/,
3242
+ "https://"
3243
+ ),
3244
+ repoOwner: org,
3245
+ repoIsPublic: repo.project?.visibility === 2 /* Public */,
3246
+ repoLanguages: [],
3247
+ repoUpdatedAt: branch.commit?.committer?.date?.toDateString() || repo.project?.lastUpdateTime?.toDateString() || (/* @__PURE__ */ new Date()).toDateString()
3248
+ };
3249
+ })
3250
+ )).reduce((acc, res) => {
3251
+ if (res.status === "fulfilled") {
3252
+ acc.push(res.value);
3253
+ }
3254
+ return acc;
3255
+ }, []);
3256
+ return repoInfoList;
3257
+ })
3258
+ )).reduce((acc, res) => {
3259
+ if (res.status === "fulfilled") {
3260
+ return acc.concat(res.value);
3261
+ }
3262
+ return acc;
3263
+ }, []);
3264
+ return repos;
3060
3265
  }
3061
- var BitbucketSCMLib = class extends SCMLib {
3062
- constructor(url, accessToken, scmOrg) {
3063
- super(url, accessToken, scmOrg);
3064
- __publicField(this, "bitbucketSdk");
3065
- const bitbucketSdk = createBitbucketSdk(accessToken);
3066
- this.bitbucketSdk = bitbucketSdk;
3266
+
3267
+ // src/features/analysis/scm/constants.ts
3268
+ var MOBB_ICON_IMG = "https://app.mobb.ai/gh-action/Logo_Rounded_Icon.svg";
3269
+
3270
+ // src/constants.ts
3271
+ var debug = Debug("mobbdev:constants");
3272
+ var __dirname = path2.dirname(fileURLToPath(import.meta.url));
3273
+ dotenv.config({ path: path2.join(__dirname, "../.env") });
3274
+ var scmFriendlyText = {
3275
+ ["Ado" /* Ado */]: "Azure DevOps",
3276
+ ["Bitbucket" /* Bitbucket */]: "Bitbucket",
3277
+ ["GitHub" /* GitHub */]: "GitGub",
3278
+ ["GitLab" /* GitLab */]: "GitLab"
3279
+ };
3280
+ var SCANNERS = {
3281
+ Checkmarx: "checkmarx",
3282
+ Codeql: "codeql",
3283
+ Fortify: "fortify",
3284
+ Snyk: "snyk",
3285
+ Sonarqube: "sonarqube"
3286
+ };
3287
+ var SupportedScannersZ = z10.enum([SCANNERS.Checkmarx, SCANNERS.Snyk]);
3288
+ var envVariablesSchema = z10.object({
3289
+ WEB_APP_URL: z10.string(),
3290
+ API_URL: z10.string(),
3291
+ HASURA_ACCESS_KEY: z10.string(),
3292
+ LOCAL_GRAPHQL_ENDPOINT: z10.string()
3293
+ }).required();
3294
+ var envVariables = envVariablesSchema.parse(process.env);
3295
+ debug("config %o", envVariables);
3296
+ var mobbAscii = `
3297
+ ..
3298
+ ..........
3299
+ .................
3300
+ ...........................
3301
+ ..............................
3302
+ ................................
3303
+ ..................................
3304
+ ....................................
3305
+ .....................................
3306
+ .............................................
3307
+ .................................................
3308
+ ............................... .................
3309
+ .................................. ............
3310
+ .................. ............. ..........
3311
+ ......... ........ ......... ......
3312
+ ............... ....
3313
+ .... ..
3314
+
3315
+ . ...
3316
+ ..............
3317
+ ......................
3318
+ ...........................
3319
+ ................................
3320
+ ......................................
3321
+ ...............................
3322
+ .................
3323
+ `;
3324
+ var PROJECT_DEFAULT_NAME = "My first project";
3325
+ var WEB_APP_URL = envVariables.WEB_APP_URL;
3326
+ var API_URL = envVariables.API_URL;
3327
+ var HASURA_ACCESS_KEY = envVariables.HASURA_ACCESS_KEY;
3328
+ var LOCAL_GRAPHQL_ENDPOINT = envVariables.LOCAL_GRAPHQL_ENDPOINT;
3329
+ var errorMessages = {
3330
+ missingCxProjectName: `project name ${chalk.bold(
3331
+ "(--cx-project-name)"
3332
+ )} is needed if you're using checkmarx`,
3333
+ missingUrl: `url ${chalk.bold(
3334
+ "(--url)"
3335
+ )} is needed if you're adding an SCM token`,
3336
+ invalidScmType: `SCM type ${chalk.bold(
3337
+ "(--scm-type)"
3338
+ )} is invalid, please use one of: ${Object.values(ScmType).join(", ")}`,
3339
+ missingToken: `SCM token ${chalk.bold(
3340
+ "(--token)"
3341
+ )} is needed if you're adding an SCM token`
3342
+ };
3343
+ var progressMassages = {
3344
+ processingVulnerabilityReportSuccess: "\u2699\uFE0F Vulnerability report proccessed successfully",
3345
+ processingVulnerabilityReport: "\u2699\uFE0F Proccessing vulnerability report",
3346
+ processingVulnerabilityReportFailed: "\u2699\uFE0F Error Proccessing vulnerability report"
3347
+ };
3348
+ var VUL_REPORT_DIGEST_TIMEOUT_MS = 1e3 * 60 * 20;
3349
+
3350
+ // src/features/analysis/index.ts
3351
+ import crypto from "node:crypto";
3352
+ import fs3 from "node:fs";
3353
+ import os from "node:os";
3354
+ import path6 from "node:path";
3355
+ import { pipeline } from "node:stream/promises";
3356
+
3357
+ // src/generates/client_generates.ts
3358
+ var MeDocument = `
3359
+ query Me {
3360
+ me {
3361
+ id
3362
+ email
3363
+ scmConfigs {
3364
+ id
3365
+ orgId
3366
+ refreshToken
3367
+ scmType
3368
+ scmUrl
3369
+ scmUsername
3370
+ token
3371
+ tokenLastUpdate
3372
+ userId
3373
+ scmOrg
3374
+ isTokenAvailable
3375
+ }
3067
3376
  }
3068
- getAuthData() {
3069
- const authType = this.bitbucketSdk.getAuthType();
3070
- switch (authType) {
3071
- case "basic": {
3072
- this._validateAccessToken();
3073
- const { username, password } = getUserAndPassword(this.accessToken);
3074
- return { username, password, authType };
3075
- }
3076
- case "token": {
3077
- return { authType, token: z7.string().parse(this.accessToken) };
3377
+ }
3378
+ `;
3379
+ var GetOrgAndProjectIdDocument = `
3380
+ query getOrgAndProjectId($filters: organization_to_organization_role_bool_exp, $limit: Int) {
3381
+ organization_to_organization_role(
3382
+ where: $filters
3383
+ order_by: {organization: {createdOn: desc}}
3384
+ limit: $limit
3385
+ ) {
3386
+ organization {
3387
+ id
3388
+ projects(order_by: {updatedAt: desc}) {
3389
+ id
3390
+ name
3078
3391
  }
3079
- case "public":
3080
- return { authType };
3081
3392
  }
3082
3393
  }
3083
- async createSubmitRequest(params) {
3084
- this._validateAccessTokenAndUrl();
3085
- const pullRequestRes = await this.bitbucketSdk.createPullRequest({
3086
- ...params,
3087
- repoUrl: this.url
3088
- });
3089
- return String(z7.number().parse(pullRequestRes.id));
3090
- }
3091
- async validateParams() {
3092
- return validateBitbucketParams({
3093
- bitbucketClient: this.bitbucketSdk,
3094
- url: this.url
3095
- });
3394
+ }
3395
+ `;
3396
+ var GetEncryptedApiTokenDocument = `
3397
+ query GetEncryptedApiToken($loginId: uuid!) {
3398
+ cli_login_by_pk(id: $loginId) {
3399
+ encryptedApiToken
3096
3400
  }
3097
- async getRepoList(scmOrg) {
3098
- this._validateAccessToken();
3099
- return this.bitbucketSdk.getRepos({
3100
- workspaceSlug: scmOrg
3101
- });
3401
+ }
3402
+ `;
3403
+ var FixReportStateDocument = `
3404
+ query FixReportState($id: uuid!) {
3405
+ fixReport_by_pk(id: $id) {
3406
+ state
3102
3407
  }
3103
- async getBranchList() {
3104
- this._validateAccessTokenAndUrl();
3105
- return this.bitbucketSdk.getBranchList({
3106
- repoUrl: this.url
3107
- });
3408
+ }
3409
+ `;
3410
+ var GetVulnerabilityReportPathsDocument = `
3411
+ query GetVulnerabilityReportPaths($vulnerabilityReportId: uuid!) {
3412
+ vulnerability_report_path(
3413
+ where: {vulnerabilityReportId: {_eq: $vulnerabilityReportId}}
3414
+ ) {
3415
+ path
3108
3416
  }
3109
- getScmLibType() {
3110
- return "BITBUCKET" /* BITBUCKET */;
3417
+ }
3418
+ `;
3419
+ var GetAnalysisDocument = `
3420
+ subscription getAnalysis($analysisId: uuid!) {
3421
+ analysis: fixReport_by_pk(id: $analysisId) {
3422
+ id
3423
+ state
3111
3424
  }
3112
- getAuthHeaders() {
3113
- const authType = this.bitbucketSdk.getAuthType();
3114
- switch (authType) {
3115
- case "public":
3116
- return {};
3117
- case "token":
3118
- return { authorization: `Bearer ${this.accessToken}` };
3119
- case "basic": {
3120
- this._validateAccessToken();
3121
- const { username, password } = getUserAndPassword(this.accessToken);
3122
- return {
3123
- authorization: `Basic ${Buffer.from(
3124
- username + ":" + password
3125
- ).toString("base64")}`
3126
- };
3425
+ }
3426
+ `;
3427
+ var GetAnalsyisDocument = `
3428
+ query getAnalsyis($analysisId: uuid!) {
3429
+ analysis: fixReport_by_pk(id: $analysisId) {
3430
+ id
3431
+ state
3432
+ repo {
3433
+ commitSha
3434
+ pullRequest
3435
+ }
3436
+ vulnerabilityReportId
3437
+ vulnerabilityReport {
3438
+ projectId
3439
+ project {
3440
+ organizationId
3441
+ }
3442
+ file {
3443
+ signedFile {
3444
+ url
3445
+ }
3127
3446
  }
3128
3447
  }
3129
3448
  }
3130
- async getDownloadUrl(sha) {
3131
- this._validateUrl();
3132
- return this.bitbucketSdk.getDownloadUrl({ url: this.url, sha });
3133
- }
3134
- async _getUsernameForAuthUrl() {
3135
- this._validateAccessTokenAndUrl();
3136
- const user = await this.bitbucketSdk.getUser();
3137
- if (!user.username) {
3138
- throw new Error("no username found");
3449
+ }
3450
+ `;
3451
+ var GetFixesDocument = `
3452
+ query getFixes($filters: fix_bool_exp!) {
3453
+ fixes: fix(where: $filters) {
3454
+ issueType
3455
+ id
3456
+ patchAndQuestions {
3457
+ __typename
3458
+ ... on FixData {
3459
+ patch
3460
+ }
3139
3461
  }
3140
- return user.username;
3141
3462
  }
3142
- async getIsRemoteBranch(branch) {
3143
- this._validateAccessTokenAndUrl();
3144
- try {
3145
- const res = await this.bitbucketSdk.getBranch({
3146
- branchName: branch,
3147
- repoUrl: this.url
3148
- });
3149
- return res.name === branch;
3150
- } catch (e) {
3151
- return false;
3463
+ }
3464
+ `;
3465
+ var GetVulByNodesMetadataDocument = `
3466
+ query getVulByNodesMetadata($filters: [vulnerability_report_issue_code_node_bool_exp!], $vulnerabilityReportId: uuid!) {
3467
+ vulnerabilityReportIssueCodeNodes: vulnerability_report_issue_code_node(
3468
+ order_by: {index: desc}
3469
+ where: {_or: $filters, vulnerabilityReportIssue: {fixId: {_is_null: false}, vulnerabilityReportId: {_eq: $vulnerabilityReportId}}}
3470
+ ) {
3471
+ vulnerabilityReportIssueId
3472
+ path
3473
+ startLine
3474
+ vulnerabilityReportIssue {
3475
+ issueType
3476
+ fixId
3152
3477
  }
3153
3478
  }
3154
- async getUserHasAccessToRepo() {
3155
- this._validateAccessTokenAndUrl();
3156
- return this.bitbucketSdk.getIsUserCollaborator({ repoUrl: this.url });
3157
- }
3158
- async getUsername() {
3159
- this._validateAccessToken();
3160
- const res = await this.bitbucketSdk.getUser();
3161
- return z7.string().parse(res.username);
3162
- }
3163
- async getSubmitRequestStatus(_scmSubmitRequestId) {
3164
- this._validateAccessTokenAndUrl();
3165
- const pullRequestRes = await this.bitbucketSdk.getPullRequest({
3166
- prNumber: Number(_scmSubmitRequestId),
3167
- url: this.url
3168
- });
3169
- switch (pullRequestRes.state) {
3170
- case "OPEN":
3171
- return "open";
3172
- case "MERGED":
3173
- return "merged";
3174
- case "DECLINED":
3175
- return "closed";
3176
- default:
3177
- throw new Error(`unknown state ${pullRequestRes.state} `);
3479
+ fixablePrVuls: vulnerability_report_issue_aggregate(
3480
+ where: {fixId: {_is_null: false}, vulnerabilityReportId: {_eq: $vulnerabilityReportId}, codeNodes: {_or: $filters}}
3481
+ ) {
3482
+ aggregate {
3483
+ count
3178
3484
  }
3179
3485
  }
3180
- async getRepoBlameRanges(_ref, _path) {
3181
- return [];
3182
- }
3183
- async getReferenceData(ref) {
3184
- this._validateUrl();
3185
- return this.bitbucketSdk.getReferenceData({ url: this.url, ref });
3186
- }
3187
- async getRepoDefaultBranch() {
3188
- this._validateUrl();
3189
- const repoRes = await this.bitbucketSdk.getRepo({ repoUrl: this.url });
3190
- return z7.string().parse(repoRes.mainbranch?.name);
3191
- }
3192
- getPrUrl(prNumber) {
3193
- this._validateUrl();
3194
- const { repoSlug, workspace } = parseBitbucketOrganizationAndRepo(this.url);
3195
- return Promise.resolve(
3196
- `https://bitbucket.org/${workspace}/${repoSlug}/pull-requests/${prNumber}`
3197
- );
3198
- }
3199
- async refreshToken(params) {
3200
- const getBitbucketTokenResponse = await getBitbucketToken({
3201
- authType: "refresh_token",
3202
- ...params
3203
- });
3204
- return {
3205
- accessToken: getBitbucketTokenResponse.access_token,
3206
- refreshToken: getBitbucketTokenResponse.refresh_token
3207
- };
3486
+ nonFixablePrVuls: vulnerability_report_issue_aggregate(
3487
+ where: {fixId: {_is_null: true}, vulnerabilityReportId: {_eq: $vulnerabilityReportId}, codeNodes: {_or: $filters}}
3488
+ ) {
3489
+ aggregate {
3490
+ count
3491
+ }
3492
+ }
3493
+ totalScanVulnerabilities: vulnerability_report_issue_aggregate(
3494
+ where: {vulnerabilityReportId: {_eq: $vulnerabilityReportId}}
3495
+ ) {
3496
+ aggregate {
3497
+ count
3498
+ }
3208
3499
  }
3209
- };
3210
-
3211
- // src/features/analysis/scm/ado/validation.ts
3212
- import { z as z8 } from "zod";
3213
- var ValidPullRequestStatusZ = z8.union([
3214
- z8.literal(1 /* Active */),
3215
- z8.literal(2 /* Abandoned */),
3216
- z8.literal(3 /* Completed */)
3217
- ]);
3218
- var AdoAuthResultZ = z8.object({
3219
- access_token: z8.string().min(1),
3220
- token_type: z8.string().min(1),
3221
- refresh_token: z8.string().min(1)
3222
- });
3223
- var profileZ = z8.object({
3224
- displayName: z8.string(),
3225
- publicAlias: z8.string().min(1),
3226
- emailAddress: z8.string(),
3227
- coreRevision: z8.number(),
3228
- timeStamp: z8.string(),
3229
- id: z8.string(),
3230
- revision: z8.number()
3231
- });
3232
- var accountsZ = z8.object({
3233
- count: z8.number(),
3234
- value: z8.array(
3235
- z8.object({
3236
- accountId: z8.string(),
3237
- accountUri: z8.string(),
3238
- accountName: z8.string()
3239
- })
3240
- )
3241
- });
3242
-
3243
- // src/features/analysis/scm/ado/utils.ts
3244
- function _getPublicAdoClient({
3245
- orgName,
3246
- origin: origin2
3247
- }) {
3248
- const orgUrl = `${origin2}/${orgName}`;
3249
- const authHandler = api.getPersonalAccessTokenHandler("");
3250
- authHandler.canHandleAuthentication = () => false;
3251
- authHandler.prepareRequest = (_options) => {
3252
- return;
3253
- };
3254
- const connection = new api.WebApi(orgUrl, authHandler);
3255
- return connection;
3256
- }
3257
- function removeTrailingSlash2(str) {
3258
- return str.trim().replace(/\/+$/, "");
3259
3500
  }
3260
- function parseAdoOwnerAndRepo(adoUrl) {
3261
- adoUrl = removeTrailingSlash2(adoUrl);
3262
- const parsingResult = parseScmURL(adoUrl, "Ado" /* Ado */);
3263
- if (!parsingResult) {
3264
- throw new InvalidUrlPatternError(`
3265
- : ${adoUrl}`);
3501
+ `;
3502
+ var UpdateScmTokenDocument = `
3503
+ mutation updateScmToken($scmType: String!, $url: String!, $token: String!, $org: String, $refreshToken: String) {
3504
+ updateScmToken(
3505
+ scmType: $scmType
3506
+ url: $url
3507
+ token: $token
3508
+ org: $org
3509
+ refreshToken: $refreshToken
3510
+ ) {
3511
+ __typename
3512
+ ... on ScmAccessTokenUpdateSuccess {
3513
+ token
3514
+ }
3515
+ ... on InvalidScmTypeError {
3516
+ status
3517
+ error
3518
+ }
3519
+ ... on BadScmCredentials {
3520
+ status
3521
+ error
3522
+ }
3266
3523
  }
3267
- const {
3268
- organization,
3269
- repoName,
3270
- projectName,
3271
- projectPath,
3272
- pathElements,
3273
- hostname,
3274
- protocol
3275
- } = parsingResult;
3276
- return {
3277
- owner: decodeURI(organization),
3278
- repo: decodeURI(repoName),
3279
- projectName: projectName ? decodeURI(projectName) : void 0,
3280
- projectPath,
3281
- pathElements,
3282
- origin: `${protocol}//${hostname}`
3283
- };
3284
3524
  }
3285
- async function getAdoConnectData({
3286
- url,
3287
- tokenOrg,
3288
- adoTokenInfo
3289
- }) {
3290
- if (url && new URL(url).origin !== url) {
3291
- const { owner, origin: origin2 } = parseAdoOwnerAndRepo(url);
3292
- return {
3293
- org: owner,
3294
- origin: origin2
3295
- };
3525
+ `;
3526
+ var UploadS3BucketInfoDocument = `
3527
+ mutation uploadS3BucketInfo($fileName: String!) {
3528
+ uploadS3BucketInfo(fileName: $fileName) {
3529
+ status
3530
+ error
3531
+ reportUploadInfo: uploadInfo {
3532
+ url
3533
+ fixReportId
3534
+ uploadFieldsJSON
3535
+ uploadKey
3536
+ }
3537
+ repoUploadInfo {
3538
+ url
3539
+ fixReportId
3540
+ uploadFieldsJSON
3541
+ uploadKey
3542
+ }
3296
3543
  }
3297
- if (!tokenOrg) {
3298
- if (adoTokenInfo.type === "OAUTH" /* OAUTH */) {
3299
- const [org] = await _getOrgsForOauthToken({
3300
- oauthToken: adoTokenInfo.accessToken
3301
- });
3302
- return {
3303
- org: z9.string().parse(org),
3304
- origin: DEFUALT_ADO_ORIGIN
3305
- };
3544
+ }
3545
+ `;
3546
+ var DigestVulnerabilityReportDocument = `
3547
+ mutation DigestVulnerabilityReport($vulnerabilityReportFileName: String!, $fixReportId: String!, $projectId: String!, $scanSource: String!) {
3548
+ digestVulnerabilityReport(
3549
+ fixReportId: $fixReportId
3550
+ vulnerabilityReportFileName: $vulnerabilityReportFileName
3551
+ projectId: $projectId
3552
+ scanSource: $scanSource
3553
+ ) {
3554
+ __typename
3555
+ ... on VulnerabilityReport {
3556
+ vulnerabilityReportId
3557
+ fixReportId
3558
+ }
3559
+ ... on RabbitSendError {
3560
+ status
3561
+ error
3562
+ }
3563
+ ... on ReportValidationError {
3564
+ status
3565
+ error
3566
+ }
3567
+ ... on ReferenceNotFoundError {
3568
+ status
3569
+ error
3306
3570
  }
3307
- throw new InvalidRepoUrlError("ADO URL is null");
3308
3571
  }
3309
- return {
3310
- org: tokenOrg,
3311
- origin: DEFUALT_ADO_ORIGIN
3312
- };
3313
3572
  }
3314
- async function getAdoApiClient(params) {
3315
- const { origin: origin2 = DEFUALT_ADO_ORIGIN, orgName } = params;
3316
- if (params.tokenType === "NONE" /* NONE */ || // move to public client if the token is not associated with the PAT org
3317
- params.tokenType === "PAT" /* PAT */ && params.patTokenOrg !== orgName) {
3318
- return _getPublicAdoClient({ orgName, origin: origin2 });
3573
+ `;
3574
+ var SubmitVulnerabilityReportDocument = `
3575
+ mutation SubmitVulnerabilityReport($fixReportId: String!, $repoUrl: String!, $reference: String!, $projectId: String!, $scanSource: String!, $sha: String, $experimentalEnabled: Boolean, $vulnerabilityReportFileName: String, $pullRequest: Int) {
3576
+ submitVulnerabilityReport(
3577
+ fixReportId: $fixReportId
3578
+ repoUrl: $repoUrl
3579
+ reference: $reference
3580
+ sha: $sha
3581
+ experimentalEnabled: $experimentalEnabled
3582
+ pullRequest: $pullRequest
3583
+ projectId: $projectId
3584
+ vulnerabilityReportFileName: $vulnerabilityReportFileName
3585
+ scanSource: $scanSource
3586
+ ) {
3587
+ __typename
3588
+ ... on VulnerabilityReport {
3589
+ vulnerabilityReportId
3590
+ fixReportId
3591
+ }
3319
3592
  }
3320
- const orgUrl = `${origin2}/${orgName}`;
3321
- if (params.tokenType === "OAUTH" /* OAUTH */) {
3322
- if (origin2 !== DEFUALT_ADO_ORIGIN) {
3323
- throw new Error(
3324
- `Oauth token is not supported for ADO on prem - ${origin2} `
3325
- );
3593
+ }
3594
+ `;
3595
+ var CreateCommunityUserDocument = `
3596
+ mutation CreateCommunityUser {
3597
+ initOrganizationAndProject {
3598
+ __typename
3599
+ ... on InitOrganizationAndProjectGoodResponse {
3600
+ projectId
3601
+ userId
3602
+ organizationId
3603
+ }
3604
+ ... on UserAlreadyInProjectError {
3605
+ error
3606
+ status
3326
3607
  }
3327
- const connection2 = new api.WebApi(
3328
- orgUrl,
3329
- api.getBearerHandler(params.accessToken),
3330
- {}
3331
- );
3332
- return connection2;
3333
3608
  }
3334
- const authHandler = api.getPersonalAccessTokenHandler(params.accessToken);
3335
- const isBroker = BROKERED_HOSTS.includes(new URL(orgUrl).origin);
3336
- const connection = new api.WebApi(
3337
- orgUrl,
3338
- authHandler,
3339
- isBroker ? {
3340
- proxy: {
3341
- proxyUrl: GIT_PROXY_HOST
3342
- },
3343
- ignoreSslError: true
3344
- } : void 0
3345
- );
3346
- return connection;
3347
3609
  }
3348
- function getAdoTokenInfo(token) {
3349
- if (!token) {
3350
- return { type: "NONE" /* NONE */ };
3610
+ `;
3611
+ var CreateCliLoginDocument = `
3612
+ mutation CreateCliLogin($publicKey: String!) {
3613
+ insert_cli_login_one(object: {publicKey: $publicKey}) {
3614
+ id
3351
3615
  }
3352
- if (token.includes(".")) {
3353
- return { type: "OAUTH" /* OAUTH */, accessToken: token };
3616
+ }
3617
+ `;
3618
+ var PerformCliLoginDocument = `
3619
+ mutation performCliLogin($loginId: String!) {
3620
+ performCliLogin(loginId: $loginId) {
3621
+ status
3354
3622
  }
3355
- return { type: "PAT" /* PAT */, accessToken: token };
3356
3623
  }
3357
- async function getAdoClientParams(params) {
3358
- const { url, accessToken, tokenOrg } = params;
3359
- const adoTokenInfo = getAdoTokenInfo(accessToken);
3360
- const { org, origin: origin2 } = await getAdoConnectData({
3361
- url,
3362
- tokenOrg,
3363
- adoTokenInfo
3364
- });
3365
- switch (adoTokenInfo.type) {
3366
- case "NONE" /* NONE */:
3367
- return {
3368
- tokenType: "NONE" /* NONE */,
3369
- origin: origin2,
3370
- orgName: org.toLowerCase()
3371
- };
3372
- case "OAUTH" /* OAUTH */: {
3373
- return {
3374
- tokenType: "OAUTH" /* OAUTH */,
3375
- accessToken: adoTokenInfo.accessToken,
3376
- origin: origin2,
3377
- orgName: org.toLowerCase()
3378
- };
3379
- }
3380
- case "PAT" /* PAT */: {
3381
- return {
3382
- tokenType: "PAT" /* PAT */,
3383
- accessToken: adoTokenInfo.accessToken,
3384
- patTokenOrg: z9.string().parse(tokenOrg).toLowerCase(),
3385
- origin: origin2,
3386
- orgName: org.toLowerCase()
3387
- };
3388
- }
3624
+ `;
3625
+ var CreateProjectDocument = `
3626
+ mutation CreateProject($organizationId: String!, $projectName: String!) {
3627
+ createProject(organizationId: $organizationId, projectName: $projectName) {
3628
+ projectId
3389
3629
  }
3390
3630
  }
3391
- async function adoValidateParams({
3392
- url,
3393
- accessToken,
3394
- tokenOrg
3395
- }) {
3396
- try {
3397
- const api2 = await getAdoApiClient(
3398
- await getAdoClientParams({ url, accessToken, tokenOrg })
3399
- );
3400
- await api2.connect();
3401
- } catch (e) {
3402
- console.log("adoValidateParams error", e);
3403
- const error = e;
3404
- const code = error.code || error.status || error.statusCode || error.response?.status || error.response?.statusCode || error.response?.code;
3405
- const description = error.description || `${e}`;
3406
- if (code === 401 || code === 403 || description.includes("401") || description.includes("403")) {
3407
- throw new InvalidAccessTokenError(`invalid ADO access token`);
3631
+ `;
3632
+ var ValidateRepoUrlDocument = `
3633
+ query validateRepoUrl($repoUrl: String!) {
3634
+ validateRepoUrl(repoUrl: $repoUrl) {
3635
+ __typename
3636
+ ... on RepoValidationSuccess {
3637
+ status
3638
+ defaultBranch
3639
+ defaultBranchLastModified
3640
+ defaultBranchSha
3641
+ scmType
3408
3642
  }
3409
- if (code === 404 || description.includes("404") || description.includes("Not Found")) {
3410
- throw new InvalidRepoUrlError(`invalid ADO repo URL ${url}`);
3643
+ ... on RepoUnreachableError {
3644
+ status
3645
+ error
3646
+ scmType
3647
+ }
3648
+ ... on BadScmCredentials {
3649
+ status
3650
+ error
3651
+ scmType
3411
3652
  }
3412
- throw e;
3413
3653
  }
3414
3654
  }
3415
- async function _getOrgsForOauthToken({
3416
- oauthToken
3417
- }) {
3418
- const profileRes = await fetch(
3419
- "https://app.vssps.visualstudio.com/_apis/profile/profiles/me?api-version=6.0",
3420
- {
3421
- method: "GET",
3422
- headers: {
3423
- Authorization: `Bearer ${oauthToken}`
3424
- }
3655
+ `;
3656
+ var GitReferenceDocument = `
3657
+ query gitReference($repoUrl: String!, $reference: String!) {
3658
+ gitReference(repoUrl: $repoUrl, reference: $reference) {
3659
+ __typename
3660
+ ... on GitReferenceData {
3661
+ status
3662
+ sha
3663
+ date
3425
3664
  }
3426
- );
3427
- const profileJson = await profileRes.json();
3428
- const profile = profileZ.parse(profileJson);
3429
- const accountsRes = await fetch(
3430
- `https://app.vssps.visualstudio.com/_apis/accounts?memberId=${profile.publicAlias}&api-version=6.0`,
3431
- {
3432
- method: "GET",
3433
- headers: {
3434
- Authorization: `Bearer ${oauthToken}`
3435
- }
3665
+ ... on ReferenceNotFoundError {
3666
+ status
3667
+ error
3436
3668
  }
3437
- );
3438
- const accountsJson = await accountsRes.json();
3439
- const accounts = accountsZ.parse(accountsJson);
3440
- const orgs = accounts.value.map((account) => account.accountName).filter((value, index, array) => array.indexOf(value) === index);
3441
- return orgs;
3669
+ }
3442
3670
  }
3443
-
3444
- // src/features/analysis/scm/ado/ado.ts
3445
- async function getAdoSdk(params) {
3446
- const api2 = await getAdoApiClient(params);
3671
+ `;
3672
+ var defaultWrapper = (action, _operationName, _operationType, _variables) => action();
3673
+ function getSdk(client, withWrapper = defaultWrapper) {
3447
3674
  return {
3448
- async getAdoIsUserCollaborator({ repoUrl }) {
3449
- try {
3450
- const { repo, projectName } = parseAdoOwnerAndRepo(repoUrl);
3451
- const git = await api2.getGitApi();
3452
- const branches = await git.getBranches(repo, projectName);
3453
- if (!branches || branches.length === 0) {
3454
- throw new InvalidRepoUrlError("no branches");
3455
- }
3456
- return true;
3457
- } catch (e) {
3458
- return false;
3459
- }
3675
+ Me(variables, requestHeaders) {
3676
+ return withWrapper((wrappedRequestHeaders) => client.request(MeDocument, variables, { ...requestHeaders, ...wrappedRequestHeaders }), "Me", "query", variables);
3460
3677
  },
3461
- async getAdoPullRequestStatus({
3462
- repoUrl,
3463
- prNumber
3464
- }) {
3465
- const { repo, projectName } = parseAdoOwnerAndRepo(repoUrl);
3466
- const git = await api2.getGitApi();
3467
- const res = await git.getPullRequest(repo, prNumber, projectName);
3468
- const parsedPullRequestStatus = ValidPullRequestStatusZ.safeParse(
3469
- res.status
3470
- );
3471
- if (!parsedPullRequestStatus.success) {
3472
- throw new Error("bad pr status for ADO");
3473
- }
3474
- return parsedPullRequestStatus.data;
3678
+ getOrgAndProjectId(variables, requestHeaders) {
3679
+ return withWrapper((wrappedRequestHeaders) => client.request(GetOrgAndProjectIdDocument, variables, { ...requestHeaders, ...wrappedRequestHeaders }), "getOrgAndProjectId", "query", variables);
3475
3680
  },
3476
- async getAdoIsRemoteBranch({
3477
- repoUrl,
3478
- branch
3479
- }) {
3480
- const { repo, projectName } = parseAdoOwnerAndRepo(repoUrl);
3481
- const git = await api2.getGitApi();
3482
- try {
3483
- const branchStatus = await git.getBranch(repo, branch, projectName);
3484
- if (!branchStatus || !branchStatus.commit) {
3485
- throw new InvalidRepoUrlError("no branch status");
3486
- }
3487
- return branchStatus.name === branch;
3488
- } catch (e) {
3489
- return false;
3490
- }
3681
+ GetEncryptedApiToken(variables, requestHeaders) {
3682
+ return withWrapper((wrappedRequestHeaders) => client.request(GetEncryptedApiTokenDocument, variables, { ...requestHeaders, ...wrappedRequestHeaders }), "GetEncryptedApiToken", "query", variables);
3491
3683
  },
3492
- async getAdoPrUrl({ url, prNumber }) {
3493
- const { repo, projectName } = parseAdoOwnerAndRepo(url);
3494
- const git = await api2.getGitApi();
3495
- const getRepositoryRes = await git.getRepository(
3496
- decodeURI(repo),
3497
- projectName ? decodeURI(projectName) : void 0
3498
- );
3499
- return `${getRepositoryRes.webUrl}/pullrequest/${prNumber}`;
3684
+ FixReportState(variables, requestHeaders) {
3685
+ return withWrapper((wrappedRequestHeaders) => client.request(FixReportStateDocument, variables, { ...requestHeaders, ...wrappedRequestHeaders }), "FixReportState", "query", variables);
3500
3686
  },
3501
- getAdoDownloadUrl({
3502
- repoUrl,
3503
- branch
3504
- }) {
3505
- const { owner, repo, projectName } = parseAdoOwnerAndRepo(repoUrl);
3506
- const url = new URL(repoUrl);
3507
- const origin2 = url.origin.toLowerCase().endsWith(".visualstudio.com") ? DEFUALT_ADO_ORIGIN : url.origin.toLowerCase();
3508
- 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`;
3687
+ GetVulnerabilityReportPaths(variables, requestHeaders) {
3688
+ return withWrapper((wrappedRequestHeaders) => client.request(GetVulnerabilityReportPathsDocument, variables, { ...requestHeaders, ...wrappedRequestHeaders }), "GetVulnerabilityReportPaths", "query", variables);
3509
3689
  },
3510
- async getAdoBranchList({ repoUrl }) {
3511
- const { repo, projectName } = parseAdoOwnerAndRepo(repoUrl);
3512
- const git = await api2.getGitApi();
3513
- try {
3514
- const res = await git.getBranches(repo, projectName);
3515
- res.sort((a, b) => {
3516
- if (!a.commit?.committer?.date || !b.commit?.committer?.date) {
3517
- return 0;
3518
- }
3519
- return b.commit?.committer?.date.getTime() - a.commit?.committer?.date.getTime();
3520
- });
3521
- return res.reduce((acc, branch) => {
3522
- if (!branch.name) {
3523
- return acc;
3524
- }
3525
- acc.push(branch.name);
3526
- return acc;
3527
- }, []);
3528
- } catch (e) {
3529
- return [];
3530
- }
3690
+ getAnalysis(variables, requestHeaders) {
3691
+ return withWrapper((wrappedRequestHeaders) => client.request(GetAnalysisDocument, variables, { ...requestHeaders, ...wrappedRequestHeaders }), "getAnalysis", "subscription", variables);
3531
3692
  },
3532
- async createAdoPullRequest(options) {
3533
- const { repoUrl, sourceBranchName, targetBranchName, title, body } = options;
3534
- const { repo, projectName } = parseAdoOwnerAndRepo(repoUrl);
3535
- const git = await api2.getGitApi();
3536
- const res = await git.createPullRequest(
3537
- {
3538
- sourceRefName: `refs/heads/${sourceBranchName}`,
3539
- targetRefName: `refs/heads/${targetBranchName}`,
3540
- title,
3541
- description: body
3542
- },
3543
- repo,
3544
- projectName
3545
- );
3546
- return res.pullRequestId;
3693
+ getAnalsyis(variables, requestHeaders) {
3694
+ return withWrapper((wrappedRequestHeaders) => client.request(GetAnalsyisDocument, variables, { ...requestHeaders, ...wrappedRequestHeaders }), "getAnalsyis", "query", variables);
3547
3695
  },
3548
- async getAdoRepoDefaultBranch({
3549
- repoUrl
3550
- }) {
3551
- const { repo, projectName } = parseAdoOwnerAndRepo(repoUrl);
3552
- const git = await api2.getGitApi();
3553
- const getRepositoryRes = await git.getRepository(
3554
- decodeURI(repo),
3555
- projectName ? decodeURI(projectName) : void 0
3556
- );
3557
- if (!getRepositoryRes?.defaultBranch) {
3558
- throw new InvalidRepoUrlError("no default branch");
3559
- }
3560
- return getRepositoryRes.defaultBranch.replace("refs/heads/", "");
3696
+ getFixes(variables, requestHeaders) {
3697
+ return withWrapper((wrappedRequestHeaders) => client.request(GetFixesDocument, variables, { ...requestHeaders, ...wrappedRequestHeaders }), "getFixes", "query", variables);
3561
3698
  },
3562
- // todo: refactor this function
3563
- async getAdoReferenceData({
3564
- ref,
3565
- repoUrl
3566
- }) {
3567
- const { repo, projectName } = parseAdoOwnerAndRepo(repoUrl);
3568
- if (!projectName) {
3569
- throw new InvalidUrlPatternError("no project name");
3570
- }
3571
- const git = await api2.getGitApi();
3572
- const results = await Promise.allSettled([
3573
- (async () => {
3574
- const res = await git.getBranch(repo, ref, projectName);
3575
- if (!res.commit || !res.commit.commitId) {
3576
- throw new InvalidRepoUrlError("no commit on branch");
3577
- }
3578
- return {
3579
- sha: res.commit.commitId,
3580
- type: "BRANCH" /* BRANCH */,
3581
- date: res.commit.committer?.date || /* @__PURE__ */ new Date()
3582
- };
3583
- })(),
3584
- (async () => {
3585
- const res = await git.getCommits(
3586
- repo,
3587
- {
3588
- fromCommitId: ref,
3589
- toCommitId: ref,
3590
- $top: 1
3591
- },
3592
- projectName
3593
- );
3594
- const commit = res[0];
3595
- if (!commit || !commit.commitId) {
3596
- throw new Error("no commit");
3597
- }
3598
- return {
3599
- sha: commit.commitId,
3600
- type: "COMMIT" /* COMMIT */,
3601
- date: commit.committer?.date || /* @__PURE__ */ new Date()
3602
- };
3603
- })(),
3604
- (async () => {
3605
- const res = await git.getRefs(repo, projectName, `tags/${ref}`);
3606
- if (!res[0] || !res[0].objectId) {
3607
- throw new Error("no tag ref");
3608
- }
3609
- let objectId = res[0].objectId;
3610
- try {
3611
- const tag = await git.getAnnotatedTag(projectName, repo, objectId);
3612
- if (tag.taggedObject?.objectId) {
3613
- objectId = tag.taggedObject.objectId;
3614
- }
3615
- } catch (e) {
3616
- }
3617
- const commitRes2 = await git.getCommits(
3618
- repo,
3619
- {
3620
- fromCommitId: objectId,
3621
- toCommitId: objectId,
3622
- $top: 1
3623
- },
3624
- projectName
3625
- );
3626
- const commit = commitRes2[0];
3627
- if (!commit) {
3628
- throw new Error("no commit");
3629
- }
3630
- return {
3631
- sha: objectId,
3632
- type: "TAG" /* TAG */,
3633
- date: commit.committer?.date || /* @__PURE__ */ new Date()
3634
- };
3635
- })()
3636
- ]);
3637
- const [branchRes, commitRes, tagRes] = results;
3638
- if (tagRes.status === "fulfilled") {
3639
- return tagRes.value;
3640
- }
3641
- if (branchRes.status === "fulfilled") {
3642
- return branchRes.value;
3643
- }
3644
- if (commitRes.status === "fulfilled") {
3645
- return commitRes.value;
3646
- }
3647
- throw new RefNotFoundError(`ref: ${ref} does not exist`);
3699
+ getVulByNodesMetadata(variables, requestHeaders) {
3700
+ return withWrapper((wrappedRequestHeaders) => client.request(GetVulByNodesMetadataDocument, variables, { ...requestHeaders, ...wrappedRequestHeaders }), "getVulByNodesMetadata", "query", variables);
3701
+ },
3702
+ updateScmToken(variables, requestHeaders) {
3703
+ return withWrapper((wrappedRequestHeaders) => client.request(UpdateScmTokenDocument, variables, { ...requestHeaders, ...wrappedRequestHeaders }), "updateScmToken", "mutation", variables);
3648
3704
  },
3649
- getAdoBlameRanges() {
3650
- return [];
3705
+ uploadS3BucketInfo(variables, requestHeaders) {
3706
+ return withWrapper((wrappedRequestHeaders) => client.request(UploadS3BucketInfoDocument, variables, { ...requestHeaders, ...wrappedRequestHeaders }), "uploadS3BucketInfo", "mutation", variables);
3707
+ },
3708
+ DigestVulnerabilityReport(variables, requestHeaders) {
3709
+ return withWrapper((wrappedRequestHeaders) => client.request(DigestVulnerabilityReportDocument, variables, { ...requestHeaders, ...wrappedRequestHeaders }), "DigestVulnerabilityReport", "mutation", variables);
3710
+ },
3711
+ SubmitVulnerabilityReport(variables, requestHeaders) {
3712
+ return withWrapper((wrappedRequestHeaders) => client.request(SubmitVulnerabilityReportDocument, variables, { ...requestHeaders, ...wrappedRequestHeaders }), "SubmitVulnerabilityReport", "mutation", variables);
3713
+ },
3714
+ CreateCommunityUser(variables, requestHeaders) {
3715
+ return withWrapper((wrappedRequestHeaders) => client.request(CreateCommunityUserDocument, variables, { ...requestHeaders, ...wrappedRequestHeaders }), "CreateCommunityUser", "mutation", variables);
3716
+ },
3717
+ CreateCliLogin(variables, requestHeaders) {
3718
+ return withWrapper((wrappedRequestHeaders) => client.request(CreateCliLoginDocument, variables, { ...requestHeaders, ...wrappedRequestHeaders }), "CreateCliLogin", "mutation", variables);
3719
+ },
3720
+ performCliLogin(variables, requestHeaders) {
3721
+ return withWrapper((wrappedRequestHeaders) => client.request(PerformCliLoginDocument, variables, { ...requestHeaders, ...wrappedRequestHeaders }), "performCliLogin", "mutation", variables);
3722
+ },
3723
+ CreateProject(variables, requestHeaders) {
3724
+ return withWrapper((wrappedRequestHeaders) => client.request(CreateProjectDocument, variables, { ...requestHeaders, ...wrappedRequestHeaders }), "CreateProject", "mutation", variables);
3725
+ },
3726
+ validateRepoUrl(variables, requestHeaders) {
3727
+ return withWrapper((wrappedRequestHeaders) => client.request(ValidateRepoUrlDocument, variables, { ...requestHeaders, ...wrappedRequestHeaders }), "validateRepoUrl", "query", variables);
3728
+ },
3729
+ gitReference(variables, requestHeaders) {
3730
+ return withWrapper((wrappedRequestHeaders) => client.request(GitReferenceDocument, variables, { ...requestHeaders, ...wrappedRequestHeaders }), "gitReference", "query", variables);
3651
3731
  }
3652
3732
  };
3653
3733
  }
3654
- async function getAdoRepoList({
3655
- orgName,
3656
- tokenOrg,
3657
- accessToken
3658
- }) {
3659
- let orgs = [];
3660
- const adoTokenInfo = getAdoTokenInfo(accessToken);
3661
- if (adoTokenInfo.type === "NONE" /* NONE */) {
3662
- return [];
3663
- }
3664
- if (adoTokenInfo.type === "OAUTH" /* OAUTH */) {
3665
- orgs = await _getOrgsForOauthToken({ oauthToken: accessToken });
3666
- }
3667
- if (orgs.length === 0 && !orgName) {
3668
- throw new Error(`no orgs for ADO`);
3669
- } else if (orgs.length === 0 && orgName) {
3670
- orgs = [orgName];
3671
- }
3672
- const repos = (await Promise.allSettled(
3673
- orgs.map(async (org) => {
3674
- const orgApi = await getAdoApiClient({
3675
- ...await getAdoClientParams({
3676
- accessToken,
3677
- tokenOrg: tokenOrg || org,
3678
- url: void 0
3679
- }),
3680
- orgName: org
3681
- });
3682
- const gitOrg = await orgApi.getGitApi();
3683
- const orgRepos = await gitOrg.getRepositories();
3684
- const repoInfoList = (await Promise.allSettled(
3685
- orgRepos.map(async (repo) => {
3686
- if (!repo.name || !repo.remoteUrl || !repo.defaultBranch) {
3687
- throw new InvalidRepoUrlError("bad repo");
3688
- }
3689
- const branch = await gitOrg.getBranch(
3690
- repo.name,
3691
- repo.defaultBranch.replace(/^refs\/heads\//, ""),
3692
- repo.project?.name
3693
- );
3694
- return {
3695
- repoName: repo.name,
3696
- repoUrl: repo.remoteUrl.replace(
3697
- /^[hH][tT][tT][pP][sS]:\/\/[^/]+@/,
3698
- "https://"
3699
- ),
3700
- repoOwner: org,
3701
- repoIsPublic: repo.project?.visibility === 2 /* Public */,
3702
- repoLanguages: [],
3703
- repoUpdatedAt: branch.commit?.committer?.date?.toDateString() || repo.project?.lastUpdateTime?.toDateString() || (/* @__PURE__ */ new Date()).toDateString()
3704
- };
3705
- })
3706
- )).reduce((acc, res) => {
3707
- if (res.status === "fulfilled") {
3708
- acc.push(res.value);
3709
- }
3710
- return acc;
3711
- }, []);
3712
- return repoInfoList;
3713
- })
3714
- )).reduce((acc, res) => {
3715
- if (res.status === "fulfilled") {
3716
- return acc.concat(res.value);
3717
- }
3718
- return acc;
3719
- }, []);
3720
- return repos;
3734
+
3735
+ // src/utils/index.ts
3736
+ var utils_exports = {};
3737
+ __export(utils_exports, {
3738
+ CliError: () => CliError,
3739
+ Spinner: () => Spinner,
3740
+ getDirName: () => getDirName,
3741
+ getTopLevelDirName: () => getTopLevelDirName,
3742
+ keypress: () => keypress,
3743
+ sleep: () => sleep
3744
+ });
3745
+
3746
+ // src/utils/dirname.ts
3747
+ import path3 from "node:path";
3748
+ import { fileURLToPath as fileURLToPath2 } from "node:url";
3749
+ function getDirName() {
3750
+ return path3.dirname(fileURLToPath2(import.meta.url));
3751
+ }
3752
+ function getTopLevelDirName(fullPath) {
3753
+ return path3.parse(fullPath).name;
3721
3754
  }
3722
3755
 
3723
- // src/features/analysis/scm/constants.ts
3724
- var MOBB_ICON_IMG = "https://app.mobb.ai/gh-action/Logo_Rounded_Icon.svg";
3756
+ // src/utils/keypress.ts
3757
+ import readline from "node:readline";
3758
+ async function keypress() {
3759
+ const rl = readline.createInterface({
3760
+ input: process.stdin,
3761
+ output: process.stdout
3762
+ });
3763
+ return new Promise((resolve) => {
3764
+ rl.question("", (answer) => {
3765
+ rl.close();
3766
+ process.stderr.moveCursor(0, -1);
3767
+ process.stderr.clearLine(1);
3768
+ resolve(answer);
3769
+ });
3770
+ });
3771
+ }
3772
+
3773
+ // src/utils/spinner.ts
3774
+ import {
3775
+ createSpinner as _createSpinner
3776
+ } from "nanospinner";
3777
+ var mockSpinner = {
3778
+ success: () => mockSpinner,
3779
+ error: () => mockSpinner,
3780
+ warn: () => mockSpinner,
3781
+ stop: () => mockSpinner,
3782
+ start: () => mockSpinner,
3783
+ update: () => mockSpinner,
3784
+ reset: () => mockSpinner,
3785
+ clear: () => mockSpinner,
3786
+ spin: () => mockSpinner
3787
+ };
3788
+ function Spinner({ ci = false } = {}) {
3789
+ return {
3790
+ createSpinner: (text, options) => ci ? mockSpinner : _createSpinner(text, options)
3791
+ };
3792
+ }
3793
+
3794
+ // src/utils/index.ts
3795
+ var sleep = (ms = 2e3) => new Promise((r) => setTimeout(r, ms));
3796
+ var CliError = class extends Error {
3797
+ };
3798
+
3799
+ // src/features/analysis/index.ts
3800
+ import chalk4 from "chalk";
3801
+ import Configstore from "configstore";
3802
+ import Debug12 from "debug";
3803
+ import extract from "extract-zip";
3804
+ import fetch4 from "node-fetch";
3805
+ import open2 from "open";
3806
+ import semver from "semver";
3807
+ import tmp2 from "tmp";
3808
+ import { z as z13 } from "zod";
3809
+
3810
+ // src/features/analysis/add_fix_comments_for_pr/add_fix_comments_for_pr.ts
3811
+ import Debug4 from "debug";
3725
3812
 
3726
3813
  // src/features/analysis/add_fix_comments_for_pr/utils.ts
3727
3814
  import Debug3 from "debug";
3728
3815
  import parseDiff2 from "parse-diff";
3729
- import { z as z10 } from "zod";
3816
+ import { z as z11 } from "zod";
3730
3817
 
3731
3818
  // src/features/analysis/utils/by_key.ts
3732
3819
  function keyBy(array, keyBy2) {
@@ -3877,7 +3964,8 @@ async function postFixComment(params) {
3877
3964
  patchAndQuestions: { patch }
3878
3965
  } = fix;
3879
3966
  const commentRes = await scm.postPrComment({
3880
- body: "empty",
3967
+ body: `# ${MobbIconMarkdown} Your fix is ready!
3968
+ Refresh the page in order to see the changes.`,
3881
3969
  pull_number: pullRequest,
3882
3970
  commit_id: commitSha,
3883
3971
  path: path9,
@@ -3957,7 +4045,7 @@ async function getRelevantVulenrabilitiesFromDiff(params) {
3957
4045
  });
3958
4046
  const lineAddedRanges = calculateRanges(fileNumbers);
3959
4047
  const fileFilter = {
3960
- path: z10.string().parse(file.to),
4048
+ path: z11.string().parse(file.to),
3961
4049
  ranges: lineAddedRanges.map(([startLine, endLine]) => ({
3962
4050
  endLine,
3963
4051
  startLine
@@ -4264,30 +4352,30 @@ function subscribe(query, variables, callback, wsClientOptions) {
4264
4352
  }
4265
4353
 
4266
4354
  // src/features/analysis/graphql/types.ts
4267
- import { z as z11 } from "zod";
4268
- var VulnerabilityReportIssueCodeNodeZ = z11.object({
4269
- vulnerabilityReportIssueId: z11.string(),
4270
- path: z11.string(),
4271
- startLine: z11.number(),
4272
- vulnerabilityReportIssue: z11.object({
4273
- fixId: z11.string()
4355
+ import { z as z12 } from "zod";
4356
+ var VulnerabilityReportIssueCodeNodeZ = z12.object({
4357
+ vulnerabilityReportIssueId: z12.string(),
4358
+ path: z12.string(),
4359
+ startLine: z12.number(),
4360
+ vulnerabilityReportIssue: z12.object({
4361
+ fixId: z12.string()
4274
4362
  })
4275
4363
  });
4276
- var GetVulByNodesMetadataZ = z11.object({
4277
- vulnerabilityReportIssueCodeNodes: z11.array(VulnerabilityReportIssueCodeNodeZ),
4278
- nonFixablePrVuls: z11.object({
4279
- aggregate: z11.object({
4280
- count: z11.number()
4364
+ var GetVulByNodesMetadataZ = z12.object({
4365
+ vulnerabilityReportIssueCodeNodes: z12.array(VulnerabilityReportIssueCodeNodeZ),
4366
+ nonFixablePrVuls: z12.object({
4367
+ aggregate: z12.object({
4368
+ count: z12.number()
4281
4369
  })
4282
4370
  }),
4283
- fixablePrVuls: z11.object({
4284
- aggregate: z11.object({
4285
- count: z11.number()
4371
+ fixablePrVuls: z12.object({
4372
+ aggregate: z12.object({
4373
+ count: z12.number()
4286
4374
  })
4287
4375
  }),
4288
- totalScanVulnerabilities: z11.object({
4289
- aggregate: z11.object({
4290
- count: z11.number()
4376
+ totalScanVulnerabilities: z12.object({
4377
+ aggregate: z12.object({
4378
+ count: z12.number()
4291
4379
  })
4292
4380
  })
4293
4381
  });
@@ -4560,6 +4648,12 @@ var GQLClient = class {
4560
4648
  });
4561
4649
  return res;
4562
4650
  }
4651
+ async validateRepoUrl(args) {
4652
+ return this._clientSdk.validateRepoUrl(args);
4653
+ }
4654
+ async getReferenceData(args) {
4655
+ return this._clientSdk.gitReference(args);
4656
+ }
4563
4657
  };
4564
4658
 
4565
4659
  // src/features/analysis/pack.ts
@@ -5060,6 +5154,70 @@ function _getUrlForScmType({
5060
5154
  };
5061
5155
  }
5062
5156
  }
5157
+ async function getScmTokenInfo(params) {
5158
+ const { gqlClient, repo } = params;
5159
+ const userInfo = await gqlClient.getUserInfo();
5160
+ if (!userInfo) {
5161
+ throw new Error("userInfo is null");
5162
+ }
5163
+ const scmConfigs = getFromArraySafe(userInfo.scmConfigs);
5164
+ return getScmConfig({
5165
+ url: repo,
5166
+ scmConfigs,
5167
+ includeOrgTokens: false
5168
+ });
5169
+ }
5170
+ async function getReport(params, { skipPrompts }) {
5171
+ const {
5172
+ scanner,
5173
+ repoUrl,
5174
+ gqlClient,
5175
+ sha,
5176
+ dirname,
5177
+ reference,
5178
+ cxProjectName,
5179
+ ci
5180
+ } = params;
5181
+ const tokenInfo = await getScmTokenInfo({ gqlClient, repo: repoUrl });
5182
+ const scm = await SCMLib.init(
5183
+ {
5184
+ url: repoUrl,
5185
+ accessToken: tokenInfo.accessToken,
5186
+ scmOrg: tokenInfo.scmOrg,
5187
+ scmType: tokenInfo.scmLibType
5188
+ },
5189
+ { propagateExceptions: true }
5190
+ );
5191
+ const downloadUrl = await scm.getDownloadUrl(sha);
5192
+ const repositoryRoot = await downloadRepo({
5193
+ repoUrl,
5194
+ dirname,
5195
+ ci,
5196
+ authHeaders: scm.getAuthHeaders(),
5197
+ downloadUrl
5198
+ });
5199
+ const reportPath = path6.join(dirname, "report.json");
5200
+ switch (scanner) {
5201
+ case "snyk":
5202
+ await getSnykReport(reportPath, repositoryRoot, { skipPrompts });
5203
+ break;
5204
+ case "checkmarx":
5205
+ if (!cxProjectName) {
5206
+ throw new Error("cxProjectName is required for checkmarx scanner");
5207
+ }
5208
+ await getCheckmarxReport(
5209
+ {
5210
+ reportPath,
5211
+ repositoryRoot,
5212
+ branch: reference,
5213
+ projectName: cxProjectName
5214
+ },
5215
+ { skipPrompts }
5216
+ );
5217
+ break;
5218
+ }
5219
+ return reportPath;
5220
+ }
5063
5221
  async function _scan(params, { skipPrompts = false } = {}) {
5064
5222
  const {
5065
5223
  dirname,
@@ -5103,68 +5261,64 @@ async function _scan(params, { skipPrompts = false } = {}) {
5103
5261
  if (!repo) {
5104
5262
  throw new Error("repo is required in case srcPath is not provided");
5105
5263
  }
5106
- const userInfo = await gqlClient.getUserInfo();
5107
- if (!userInfo) {
5108
- throw new Error("userInfo is null");
5109
- }
5110
- const scmConfigs = getFromArraySafe(userInfo.scmConfigs);
5111
- const tokenInfo = getScmConfig({
5112
- url: repo,
5113
- scmConfigs,
5114
- includeOrgTokens: false
5115
- });
5116
- const isRepoAvailable = await scmCanReachRepo({
5117
- repoUrl: repo,
5118
- accessToken: tokenInfo.accessToken,
5119
- scmOrg: tokenInfo.scmOrg,
5120
- scmType: getScmTypeFromScmLibType(tokenInfo.scmLibType)
5121
- });
5264
+ const tokenInfo = await getScmTokenInfo({ gqlClient, repo });
5265
+ const validateRes = await gqlClient.validateRepoUrl({ repoUrl: repo });
5266
+ const isRepoAvailable = validateRes.validateRepoUrl?.__typename === "RepoValidationSuccess";
5122
5267
  const cloudScmLibType = getCloudScmLibTypeFromUrl(repo);
5123
5268
  const { authUrl: scmAuthUrl } = _getUrlForScmType({
5124
5269
  scmLibType: cloudScmLibType
5125
5270
  });
5126
- let myToken = tokenInfo.accessToken;
5127
5271
  if (!isRepoAvailable) {
5128
5272
  if (ci || !cloudScmLibType || !scmAuthUrl) {
5129
5273
  const errorMessage = scmAuthUrl ? `Cannot access repo ${repo}` : `Cannot access repo ${repo} with the provided token, please visit ${scmAuthUrl} to refresh your source control management system token`;
5130
5274
  throw new Error(errorMessage);
5131
5275
  }
5132
5276
  if (cloudScmLibType && scmAuthUrl) {
5133
- myToken = await handleScmIntegration(tokenInfo.accessToken, scmAuthUrl, repo) || "";
5134
- const isRepoAvailable2 = await scmCanReachRepo({
5135
- repoUrl: repo,
5136
- accessToken: myToken,
5137
- scmOrg: tokenInfo.scmOrg,
5138
- scmType: getScmTypeFromScmLibType(tokenInfo.scmLibType)
5277
+ await handleScmIntegration(tokenInfo.accessToken, scmAuthUrl, repo);
5278
+ const repoValidationResponse = await gqlClient.validateRepoUrl({
5279
+ repoUrl: repo
5139
5280
  });
5281
+ const isRepoAvailable2 = repoValidationResponse.validateRepoUrl?.__typename === "RepoValidationSuccess";
5140
5282
  if (!isRepoAvailable2) {
5141
5283
  throw new Error(
5142
- `Cannot access repo ${repo} with the provided credentials`
5284
+ `Cannot access repo ${repo} with the provided credentials: ${repoValidationResponse.validateRepoUrl?.__typename}`
5143
5285
  );
5144
5286
  }
5145
5287
  }
5146
5288
  }
5147
- const scm = await SCMLib.init({
5148
- url: repo,
5149
- accessToken: myToken,
5150
- scmOrg: tokenInfo.scmOrg,
5151
- scmType: tokenInfo.scmLibType
5289
+ const revalidateRes = await gqlClient.validateRepoUrl({ repoUrl: repo });
5290
+ if (revalidateRes.validateRepoUrl?.__typename !== "RepoValidationSuccess") {
5291
+ throw new Error(
5292
+ `could not reach repo ${repo}: ${revalidateRes.validateRepoUrl?.__typename}`
5293
+ );
5294
+ }
5295
+ const reference = ref ?? revalidateRes.validateRepoUrl.defaultBranch;
5296
+ const getReferenceDataRes = await gqlClient.getReferenceData({
5297
+ reference,
5298
+ repoUrl: repo
5152
5299
  });
5153
- const reference = ref ?? await scm.getRepoDefaultBranch();
5154
- const { sha } = await scm.getReferenceData(reference);
5155
- const downloadUrl = await scm.getDownloadUrl(sha);
5156
- debug11("org id %s", organizationId);
5300
+ if (getReferenceDataRes.gitReference?.__typename !== "GitReferenceData") {
5301
+ throw new Error(
5302
+ `Could not get reference data for ${reference}: ${getReferenceDataRes.gitReference?.__typename}`
5303
+ );
5304
+ }
5305
+ const { sha } = getReferenceDataRes.gitReference;
5157
5306
  debug11("project id %s", projectId);
5158
5307
  debug11("default branch %s", reference);
5159
- const repositoryRoot = await downloadRepo({
5160
- repoUrl: repo,
5161
- dirname,
5162
- ci,
5163
- authHeaders: scm.getAuthHeaders(),
5164
- downloadUrl
5165
- });
5166
5308
  if (command === "scan") {
5167
- reportPath = await getReport(SupportedScannersZ.parse(scanner));
5309
+ reportPath = await getReport(
5310
+ {
5311
+ scanner: SupportedScannersZ.parse(scanner),
5312
+ repoUrl: repo,
5313
+ sha,
5314
+ gqlClient,
5315
+ cxProjectName,
5316
+ dirname,
5317
+ reference,
5318
+ ci
5319
+ },
5320
+ { skipPrompts }
5321
+ );
5168
5322
  }
5169
5323
  if (!reportPath) {
5170
5324
  throw new Error("reportPath is null");
@@ -5188,7 +5342,7 @@ async function _scan(params, { skipPrompts = false } = {}) {
5188
5342
  spinner: mobbSpinner,
5189
5343
  submitVulnerabilityReportVariables: {
5190
5344
  fixReportId: reportUploadInfo.fixReportId,
5191
- repoUrl: z12.string().parse(repo),
5345
+ repoUrl: z13.string().parse(repo),
5192
5346
  reference,
5193
5347
  projectId,
5194
5348
  vulnerabilityReportFileName: "report.json",
@@ -5207,29 +5361,6 @@ async function _scan(params, { skipPrompts = false } = {}) {
5207
5361
  });
5208
5362
  await askToOpenAnalysis();
5209
5363
  return reportUploadInfo.fixReportId;
5210
- async function getReport(scanner2) {
5211
- const reportPath2 = path6.join(dirname, "report.json");
5212
- switch (scanner2) {
5213
- case "snyk":
5214
- await getSnykReport(reportPath2, repositoryRoot, { skipPrompts });
5215
- break;
5216
- case "checkmarx":
5217
- if (!cxProjectName) {
5218
- throw new Error("cxProjectName is required for checkmarx scanner");
5219
- }
5220
- await getCheckmarxReport(
5221
- {
5222
- reportPath: reportPath2,
5223
- repositoryRoot,
5224
- branch: reference,
5225
- projectName: cxProjectName
5226
- },
5227
- { skipPrompts }
5228
- );
5229
- break;
5230
- }
5231
- return reportPath2;
5232
- }
5233
5364
  async function askToOpenAnalysis() {
5234
5365
  if (!repoUploadInfo || !reportUploadInfo) {
5235
5366
  throw new Error("uploadS3BucketInfo is null");
@@ -5326,14 +5457,14 @@ async function _scan(params, { skipPrompts = false } = {}) {
5326
5457
  );
5327
5458
  await open2(scmAuthUrl2);
5328
5459
  for (let i = 0; i < LOGIN_MAX_WAIT / LOGIN_CHECK_DELAY; i++) {
5329
- const userInfo2 = await gqlClient.getUserInfo();
5330
- if (!userInfo2) {
5460
+ const userInfo = await gqlClient.getUserInfo();
5461
+ if (!userInfo) {
5331
5462
  throw new CliError2("User info not found");
5332
5463
  }
5333
- const scmConfigs2 = getFromArraySafe(userInfo2.scmConfigs);
5464
+ const scmConfigs = getFromArraySafe(userInfo.scmConfigs);
5334
5465
  const tokenInfo2 = getScmConfig({
5335
5466
  url: repoUrl,
5336
- scmConfigs: scmConfigs2,
5467
+ scmConfigs,
5337
5468
  includeOrgTokens: false
5338
5469
  });
5339
5470
  if (tokenInfo2.accessToken && tokenInfo2.accessToken !== oldToken) {
@@ -5440,16 +5571,21 @@ async function _scan(params, { skipPrompts = false } = {}) {
5440
5571
  }
5441
5572
  });
5442
5573
  if (command === "review") {
5443
- const params2 = z12.object({
5444
- repo: z12.string().url(),
5445
- githubActionToken: z12.string()
5574
+ const params2 = z13.object({
5575
+ repo: z13.string().url(),
5576
+ githubActionToken: z13.string()
5446
5577
  }).parse({ repo, githubActionToken });
5447
- const scm2 = await SCMLib.init({
5448
- url: params2.repo,
5449
- accessToken: params2.githubActionToken,
5450
- scmOrg: "",
5451
- scmType: "GITHUB" /* GITHUB */
5452
- });
5578
+ const scm = await SCMLib.init(
5579
+ {
5580
+ url: params2.repo,
5581
+ accessToken: params2.githubActionToken,
5582
+ scmOrg: "",
5583
+ scmType: "GITHUB" /* GITHUB */
5584
+ },
5585
+ {
5586
+ propagateExceptions: true
5587
+ }
5588
+ );
5453
5589
  await gqlClient.subscribeToAnalysis({
5454
5590
  subscribeToAnalysisParams: {
5455
5591
  analysisId: reportUploadInfo.fixReportId
@@ -5458,8 +5594,8 @@ async function _scan(params, { skipPrompts = false } = {}) {
5458
5594
  return addFixCommentsForPr({
5459
5595
  analysisId,
5460
5596
  gqlClient,
5461
- scm: scm2,
5462
- scanner: z12.nativeEnum(SCANNERS).parse(scanner)
5597
+ scm,
5598
+ scanner: z13.nativeEnum(SCANNERS).parse(scanner)
5463
5599
  });
5464
5600
  },
5465
5601
  callbackStates: ["Finished" /* Finished */]
@@ -5645,12 +5781,12 @@ var commitHashOption = {
5645
5781
  };
5646
5782
  var scmTypeOption = {
5647
5783
  demandOption: true,
5648
- describe: chalk5.bold("SCM type (GitHub, GitLab, Ado, Bitbucket)"),
5649
- type: "string"
5784
+ describe: chalk5.bold("SCM type"),
5785
+ choices: Object.values(ScmType)
5650
5786
  };
5651
5787
  var urlOption = {
5652
5788
  describe: chalk5.bold(
5653
- "URL of the repository (used in GitHub, GitLab, Azure DevOps, Bitbucket)"
5789
+ `URL of the repository (used in ${Object.values(ScmType).join(", ")})`
5654
5790
  ),
5655
5791
  type: "string",
5656
5792
  demandOption: true
@@ -5672,7 +5808,7 @@ var scmTokenOption = {
5672
5808
  // src/args/validation.ts
5673
5809
  import chalk6 from "chalk";
5674
5810
  import path8 from "path";
5675
- import { z as z13 } from "zod";
5811
+ import { z as z14 } from "zod";
5676
5812
  function throwRepoUrlErrorMessage({
5677
5813
  error,
5678
5814
  repoUrl,
@@ -5689,13 +5825,13 @@ Example:
5689
5825
  )}`;
5690
5826
  throw new CliError(formattedErrorMessage);
5691
5827
  }
5692
- var UrlZ = z13.string({
5693
- invalid_type_error: "is not a valid GitHub / GitLab / ADO URL"
5828
+ var UrlZ = z14.string({
5829
+ invalid_type_error: `is not a valid ${Object.values(ScmType).join("/ ")} URL`
5694
5830
  }).refine((data) => !!sanityRepoURL(data), {
5695
- message: "is not a valid GitHub / GitLab / ADO URL"
5831
+ message: `is not a valid ${Object.values(ScmType).join(" / ")} URL`
5696
5832
  });
5697
5833
  function validateOrganizationId(organizationId) {
5698
- const orgIdValidation = z13.string().uuid().nullish().safeParse(organizationId);
5834
+ const orgIdValidation = z14.string().uuid().nullish().safeParse(organizationId);
5699
5835
  if (!orgIdValidation.success) {
5700
5836
  throw new CliError(`organizationId: ${organizationId} is not a valid UUID`);
5701
5837
  }
@@ -5852,20 +5988,15 @@ async function scanHandler(args) {
5852
5988
  }
5853
5989
 
5854
5990
  // src/args/commands/token.ts
5855
- import { z as z14 } from "zod";
5856
5991
  function addScmTokenBuilder(args) {
5857
5992
  return args.option("scm-type", scmTypeOption).option("url", urlOption).option("token", scmTokenOption).option("organization", scmOrgOption).option("refresh-token", scmRefreshTokenOption).option("api-key", apiKeyOption).example(
5858
5993
  "$0 add-scm-token --scm-type Ado --url https://dev.azure.com/adoorg/test/_git/repo --token abcdef0123456 --organization myOrg",
5859
- "Add your SCM (Github, Gitlab, Azure DevOps) token to Mobb to enable automated fixes."
5994
+ `Add your SCM (${Object.values(scmFriendlyText).join(", ")}) token to Mobb to enable automated fixes.`
5860
5995
  ).help().demandOption(["url", "token"]);
5861
5996
  }
5862
- function validateAddScmTokenOptions(argv) {
5863
- if (!z14.nativeEnum(ScmType).safeParse(argv.scmType).success) {
5864
- throw new CliError(
5865
- "\nError: --scm-type must reference a valid SCM type (GitHub, GitLab, Ado, Bitbutcket)"
5866
- );
5867
- }
5868
- Object.values(scmValidationMap).forEach((validate) => validate(argv));
5997
+ async function validateAddScmTokenOptions(argv) {
5998
+ const scmType = argv["scm-type"];
5999
+ scmValidationMap[scmType];
5869
6000
  }
5870
6001
  var scmValidationMap = {
5871
6002
  ["GitHub" /* GitHub */]: () => {
@@ -5880,15 +6011,14 @@ var scmValidationMap = {
5880
6011
  }
5881
6012
  };
5882
6013
  function validateAdo(argv) {
5883
- const urlObj = new URL(argv.url);
5884
- if ((urlObj.hostname.toLowerCase() === scmCloudHostname.Ado || urlObj.hostname.toLowerCase().endsWith(".visualstudio.com")) && !argv.organization) {
6014
+ if (!argv.organization) {
5885
6015
  throw new CliError(
5886
6016
  "\nError: --organization flag is required for Azure DevOps"
5887
6017
  );
5888
6018
  }
5889
6019
  }
5890
6020
  async function addScmTokenHandler(args) {
5891
- validateAddScmTokenOptions(args);
6021
+ await validateAddScmTokenOptions(args);
5892
6022
  await addScmToken(args);
5893
6023
  }
5894
6024