@socketsecurity/cli-with-sentry 0.14.65 → 0.14.67

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.
@@ -55,18 +55,18 @@ var tinyglobby = _socketInterop(require('tinyglobby'));
55
55
  var promises = require('@socketsecurity/registry/lib/promises');
56
56
  var yaml = _socketInterop(require('yaml'));
57
57
  var betterAjvErrors = _socketInterop(require('@apideck/better-ajv-errors'));
58
- var config$D = require('@socketsecurity/config');
59
- var assert = require('node:assert');
58
+ var config$H = require('@socketsecurity/config');
60
59
  var readline = require('node:readline/promises');
61
60
  var BoxWidget = _socketInterop(require('blessed/lib/widgets/box'));
62
61
  var TableWidget = _socketInterop(require('blessed-contrib/lib/widget/table'));
63
62
  var readline$1 = require('node:readline');
64
63
 
65
- function handleUnsuccessfulApiResponse(_name, result) {
66
- // SocketSdkErrorType['error'] is not typed.
67
- const resultErrorMessage = result.error?.message;
68
- const message = typeof resultErrorMessage === 'string' ? resultErrorMessage : 'No error message returned';
69
- if (result.status === 401 || result.status === 403) {
64
+ function handleUnsuccessfulApiResponse(_name, sockSdkError) {
65
+ const message = sockSdkError.error || 'No error message returned';
66
+ const {
67
+ status
68
+ } = sockSdkError;
69
+ if (status === 401 || status === 403) {
70
70
  // Lazily access constants.spinner.
71
71
  const {
72
72
  spinner
@@ -88,7 +88,7 @@ async function handleApiCall(value, description) {
88
88
  }
89
89
  return result;
90
90
  }
91
- async function handleAPIError(code) {
91
+ async function handleApiError(code) {
92
92
  if (code === 400) {
93
93
  return 'One of the options passed might be incorrect.';
94
94
  } else if (code === 403) {
@@ -102,22 +102,22 @@ function getLastFiveOfApiToken(token) {
102
102
 
103
103
  // The API server that should be used for operations.
104
104
  function getDefaultApiBaseUrl() {
105
- const baseUrl = process$1.env['SOCKET_SECURITY_API_BASE_URL'] || shadowNpmInject.getSetting('apiBaseUrl');
105
+ const baseUrl = process$1.env['SOCKET_SECURITY_API_BASE_URL'] || shadowNpmInject.getConfigValue('apiBaseUrl');
106
106
  return strings.isNonEmptyString(baseUrl) ? baseUrl : undefined;
107
107
  }
108
- async function queryAPI(path, apiToken) {
108
+ async function queryApi(path, apiToken) {
109
109
  const API_V0_URL = getDefaultApiBaseUrl();
110
110
  return await fetch(`${API_V0_URL}/${path}`, {
111
111
  method: 'GET',
112
112
  headers: {
113
- Authorization: `Basic ${btoa(`${apiToken}:${apiToken}`)}`
113
+ Authorization: `Basic ${btoa(`${apiToken}:`)}`
114
114
  }
115
115
  });
116
116
  }
117
117
 
118
118
  async function fetchOrgAnalyticsData(time, spinner, apiToken) {
119
- const socketSdk = await shadowNpmInject.setupSdk(apiToken);
120
- const result = await handleApiCall(socketSdk.getOrgAnalytics(time.toString()), 'fetching analytics data');
119
+ const sockSdk = await shadowNpmInject.setupSdk(apiToken);
120
+ const result = await handleApiCall(sockSdk.getOrgAnalytics(time.toString()), 'fetching analytics data');
121
121
  if (result.success === false) {
122
122
  handleUnsuccessfulApiResponse('getOrgAnalytics', result);
123
123
  return undefined;
@@ -131,8 +131,8 @@ async function fetchOrgAnalyticsData(time, spinner, apiToken) {
131
131
  }
132
132
 
133
133
  async function fetchRepoAnalyticsData(repo, time, spinner, apiToken) {
134
- const socketSdk = await shadowNpmInject.setupSdk(apiToken);
135
- const result = await handleApiCall(socketSdk.getRepoAnalytics(repo, time.toString()), 'fetching analytics data');
134
+ const sockSdk = await shadowNpmInject.setupSdk(apiToken);
135
+ const result = await handleApiCall(sockSdk.getRepoAnalytics(repo, time.toString()), 'fetching analytics data');
136
136
  if (result.success === false) {
137
137
  handleUnsuccessfulApiResponse('getRepoAnalytics', result);
138
138
  return undefined;
@@ -652,9 +652,9 @@ function emitBanner(name) {
652
652
  }
653
653
  function getAsciiHeader(command) {
654
654
  const cliVersion = // The '@rollup/plugin-replace' will replace "process.env['INLINED_SOCKET_CLI_VERSION_HASH']".
655
- "0.14.65:ace6cae:076379f8:pub";
655
+ "0.14.67:a2db5d2:df42d424:pub";
656
656
  const nodeVersion = process.version;
657
- const apiToken = shadowNpmInject.getSetting('apiToken');
657
+ const apiToken = shadowNpmInject.getConfigValue('apiToken');
658
658
  const shownToken = apiToken ? getLastFiveOfApiToken(apiToken) : 'no';
659
659
  const relCwd = path.normalizePath(process.cwd().replace(new RegExp(`^${regexps.escapeRegExp(constants.homePath)}(?:${path$1.sep}|$)`, 'i'), '~/'));
660
660
  const body = `
@@ -666,9 +666,9 @@ function getAsciiHeader(command) {
666
666
  }
667
667
 
668
668
  const {
669
- DRY_RUN_BAIL_TEXT: DRY_RUN_BAIL_TEXT$B
669
+ DRY_RUN_BAIL_TEXT: DRY_RUN_BAIL_TEXT$F
670
670
  } = constants;
671
- const config$C = {
671
+ const config$G = {
672
672
  commandName: 'analytics',
673
673
  description: `Look up analytics data`,
674
674
  hidden: false,
@@ -719,16 +719,16 @@ const config$C = {
719
719
  `
720
720
  };
721
721
  const cmdAnalytics = {
722
- description: config$C.description,
723
- hidden: config$C.hidden,
724
- run: run$C
722
+ description: config$G.description,
723
+ hidden: config$G.hidden,
724
+ run: run$G
725
725
  };
726
- async function run$C(argv, importMeta, {
726
+ async function run$G(argv, importMeta, {
727
727
  parentName
728
728
  }) {
729
729
  const cli = meowOrExit({
730
730
  argv,
731
- config: config$C,
731
+ config: config$G,
732
732
  importMeta,
733
733
  parentName
734
734
  });
@@ -765,7 +765,7 @@ async function run$C(argv, importMeta, {
765
765
  return;
766
766
  }
767
767
  if (cli.flags['dryRun']) {
768
- logger.logger.log(DRY_RUN_BAIL_TEXT$B);
768
+ logger.logger.log(DRY_RUN_BAIL_TEXT$F);
769
769
  return;
770
770
  }
771
771
  return await displayAnalytics({
@@ -808,8 +808,8 @@ async function fetchAuditLogWithToken(apiToken, {
808
808
  spinner
809
809
  } = constants;
810
810
  spinner.start(`Looking up audit log for ${orgSlug}`);
811
- const socketSdk = await shadowNpmInject.setupSdk(apiToken);
812
- const result = await handleApiCall(socketSdk.getAuditLogEvents(orgSlug, {
811
+ const sockSdk = await shadowNpmInject.setupSdk(apiToken);
812
+ const result = await handleApiCall(sockSdk.getAuditLogEvents(orgSlug, {
813
813
  // I'm not sure this is used at all.
814
814
  outputJson: String(outputKind === 'json'),
815
815
  // I'm not sure this is used at all.
@@ -952,9 +952,9 @@ async function handleAuditLog({
952
952
  }
953
953
 
954
954
  const {
955
- DRY_RUN_BAIL_TEXT: DRY_RUN_BAIL_TEXT$A
955
+ DRY_RUN_BAIL_TEXT: DRY_RUN_BAIL_TEXT$E
956
956
  } = constants;
957
- const config$B = {
957
+ const config$F = {
958
958
  commandName: 'audit-log',
959
959
  description: 'Look up the audit log for an organization',
960
960
  hidden: false,
@@ -995,16 +995,16 @@ const config$B = {
995
995
  `
996
996
  };
997
997
  const cmdAuditLog = {
998
- description: config$B.description,
999
- hidden: config$B.hidden,
1000
- run: run$B
998
+ description: config$F.description,
999
+ hidden: config$F.hidden,
1000
+ run: run$F
1001
1001
  };
1002
- async function run$B(argv, importMeta, {
1002
+ async function run$F(argv, importMeta, {
1003
1003
  parentName
1004
1004
  }) {
1005
1005
  const cli = meowOrExit({
1006
1006
  argv,
1007
- config: config$B,
1007
+ config: config$F,
1008
1008
  importMeta,
1009
1009
  parentName
1010
1010
  });
@@ -1029,7 +1029,7 @@ async function run$B(argv, importMeta, {
1029
1029
  return;
1030
1030
  }
1031
1031
  if (cli.flags['dryRun']) {
1032
- logger.logger.log(DRY_RUN_BAIL_TEXT$A);
1032
+ logger.logger.log(DRY_RUN_BAIL_TEXT$E);
1033
1033
  return;
1034
1034
  }
1035
1035
  await handleAuditLog({
@@ -1146,7 +1146,7 @@ function isHelpFlag(cmdArg) {
1146
1146
 
1147
1147
  // import { meowOrExit } from '../../utils/meow-with-subcommands'
1148
1148
  const {
1149
- DRY_RUN_BAIL_TEXT: DRY_RUN_BAIL_TEXT$z
1149
+ DRY_RUN_BAIL_TEXT: DRY_RUN_BAIL_TEXT$D
1150
1150
  } = constants;
1151
1151
 
1152
1152
  // TODO: convert yargs to meow. Or convert all the other things to yargs.
@@ -1223,7 +1223,7 @@ const yargsConfig = {
1223
1223
  'yes'],
1224
1224
  string: ['api-key', 'lifecycle', 'output', 'parent-project-id', 'profile', 'project-group', 'project-name', 'project-version', 'project-id', 'server-host', 'server-port', 'server-url', 'spec-version']
1225
1225
  };
1226
- const config$A = {
1226
+ const config$E = {
1227
1227
  commandName: 'cdxgen',
1228
1228
  description: 'Create an SBOM with CycloneDX generator (cdxgen)',
1229
1229
  hidden: false,
@@ -1239,18 +1239,18 @@ const config$A = {
1239
1239
  `
1240
1240
  };
1241
1241
  const cmdCdxgen = {
1242
- description: config$A.description,
1243
- hidden: config$A.hidden,
1244
- run: run$A
1242
+ description: config$E.description,
1243
+ hidden: config$E.hidden,
1244
+ run: run$E
1245
1245
  };
1246
- async function run$A(argv, importMeta, {
1246
+ async function run$E(argv, importMeta, {
1247
1247
  parentName
1248
1248
  }) {
1249
1249
  const cli = meowOrExit({
1250
1250
  allowUnknownFlags: true,
1251
1251
  // Don't let meow take over --help.
1252
1252
  argv: argv.filter(a => !isHelpFlag(a)),
1253
- config: config$A,
1253
+ config: config$E,
1254
1254
  importMeta,
1255
1255
  parentName
1256
1256
  });
@@ -1282,7 +1282,7 @@ async function run$A(argv, importMeta, {
1282
1282
  return;
1283
1283
  }
1284
1284
  if (cli.flags['dryRun']) {
1285
- logger.logger.log(DRY_RUN_BAIL_TEXT$z);
1285
+ logger.logger.log(DRY_RUN_BAIL_TEXT$D);
1286
1286
  return;
1287
1287
  }
1288
1288
  if (yargv.output === undefined) {
@@ -1291,212 +1291,611 @@ async function run$A(argv, importMeta, {
1291
1291
  await runCycloneDX(yargv);
1292
1292
  }
1293
1293
 
1294
- async function fetchDependencies({
1295
- limit,
1296
- offset
1297
- }) {
1298
- const apiToken = shadowNpmInject.getDefaultToken();
1299
- if (!apiToken) {
1300
- throw new shadowNpmInject.AuthError('User must be authenticated to run this command. To log in, run the command `socket login` and enter your API key.');
1301
- }
1302
- return await fetchDependenciesWithToken(apiToken, {
1303
- limit,
1304
- offset
1305
- });
1306
- }
1307
- async function fetchDependenciesWithToken(apiToken, {
1308
- limit,
1309
- offset
1310
- }) {
1311
- // Lazily access constants.spinner.
1312
- const {
1313
- spinner
1314
- } = constants;
1315
- spinner.start('Fetching organization dependencies...');
1316
- const socketSdk = await shadowNpmInject.setupSdk(apiToken);
1317
- const result = await handleApiCall(socketSdk.searchDependencies({
1318
- limit,
1319
- offset
1320
- }), 'Searching dependencies');
1321
- spinner?.successAndStop('Received organization dependencies response.');
1322
- if (!result.success) {
1323
- handleUnsuccessfulApiResponse('searchDependencies', result);
1324
- return;
1325
- }
1326
- return result.data;
1327
- }
1328
-
1329
- // @ts-ignore
1330
- async function outputDependencies(data, {
1331
- limit,
1332
- offset,
1333
- outputKind
1334
- }) {
1294
+ async function outputConfigGet(key, value, outputKind) {
1335
1295
  if (outputKind === 'json') {
1336
- let json;
1337
- try {
1338
- json = JSON.stringify(data, null, 2);
1339
- } catch (e) {
1340
- process.exitCode = 1;
1341
- logger.logger.fail('There was a problem converting the data to JSON, please try without the `--json` flag');
1342
- return;
1343
- }
1344
- logger.logger.log(json);
1345
- return;
1296
+ logger.logger.log(JSON.stringify({
1297
+ success: true,
1298
+ result: {
1299
+ key,
1300
+ value
1301
+ }
1302
+ }));
1303
+ } else if (outputKind === 'markdown') {
1304
+ logger.logger.log(`# Config Value`);
1305
+ logger.logger.log('');
1306
+ logger.logger.log(`Config key '${key}' has value '${value}`);
1307
+ } else {
1308
+ logger.logger.log(`${key}: ${value}`);
1346
1309
  }
1347
- logger.logger.log('Request details: Offset:', offset, ', limit:', limit, ', is there more data after this?', data.end ? 'no' : 'yes');
1348
- const options = {
1349
- columns: [{
1350
- field: 'namespace',
1351
- name: colors.cyan('Namespace')
1352
- }, {
1353
- field: 'name',
1354
- name: colors.cyan('Name')
1355
- }, {
1356
- field: 'version',
1357
- name: colors.cyan('Version')
1358
- }, {
1359
- field: 'repository',
1360
- name: colors.cyan('Repository')
1361
- }, {
1362
- field: 'branch',
1363
- name: colors.cyan('Branch')
1364
- }, {
1365
- field: 'type',
1366
- name: colors.cyan('Type')
1367
- }, {
1368
- field: 'direct',
1369
- name: colors.cyan('Direct')
1370
- }]
1371
- };
1372
- logger.logger.log(chalkTable(options, data.rows));
1373
1310
  }
1374
1311
 
1375
- async function handleDependencies({
1376
- limit,
1377
- offset,
1312
+ async function handleConfigGet({
1313
+ key,
1378
1314
  outputKind
1379
1315
  }) {
1380
- const data = await fetchDependencies({
1381
- limit,
1382
- offset
1383
- });
1384
- if (!data) return;
1385
- await outputDependencies(data, {
1386
- limit,
1387
- offset,
1388
- outputKind
1389
- });
1316
+ const value = shadowNpmInject.getConfigValue(key);
1317
+ await outputConfigGet(key, value, outputKind);
1390
1318
  }
1391
1319
 
1392
1320
  const {
1393
- DRY_RUN_BAIL_TEXT: DRY_RUN_BAIL_TEXT$y
1321
+ DRY_RUN_BAIL_TEXT: DRY_RUN_BAIL_TEXT$C
1394
1322
  } = constants;
1395
- const config$z = {
1396
- commandName: 'dependencies',
1397
- description: 'Search for any dependency that is being used in your organization',
1323
+ const config$D = {
1324
+ commandName: 'get',
1325
+ description: 'Get the value of a local CLI config item',
1398
1326
  hidden: false,
1399
1327
  flags: {
1400
1328
  ...commonFlags,
1401
- limit: {
1402
- type: 'number',
1403
- shortFlag: 'l',
1404
- default: 50,
1405
- description: 'Maximum number of dependencies returned'
1406
- },
1407
- offset: {
1408
- type: 'number',
1409
- shortFlag: 'o',
1410
- default: 0,
1411
- description: 'Page number'
1412
- },
1413
1329
  ...outputFlags
1414
1330
  },
1415
1331
  help: (command, config) => `
1416
1332
  Usage
1417
- ${command}
1333
+ $ ${command} <org slug>
1418
1334
 
1419
1335
  Options
1420
1336
  ${getFlagListOutput(config.flags, 6)}
1421
1337
 
1338
+ Keys:
1339
+
1340
+ ${Array.from(shadowNpmInject.supportedConfigKeys.entries()).map(([key, desc]) => ` - ${key} -- ${desc}`).join('\n')}
1341
+
1422
1342
  Examples
1423
- ${command} --limit 20 --offset 10
1343
+ $ ${command} FakeOrg --repoName=test-repo
1424
1344
  `
1425
1345
  };
1426
- const cmdScanCreate$1 = {
1427
- description: config$z.description,
1428
- hidden: config$z.hidden,
1429
- run: run$z
1346
+ const cmdConfigGet = {
1347
+ description: config$D.description,
1348
+ hidden: config$D.hidden,
1349
+ run: run$D
1430
1350
  };
1431
- async function run$z(argv, importMeta, {
1351
+ async function run$D(argv, importMeta, {
1432
1352
  parentName
1433
1353
  }) {
1434
1354
  const cli = meowOrExit({
1435
1355
  argv,
1436
- config: config$z,
1356
+ config: config$D,
1437
1357
  importMeta,
1438
1358
  parentName
1439
1359
  });
1440
1360
  const {
1441
1361
  json,
1442
- limit,
1443
- markdown,
1444
- offset
1362
+ markdown
1445
1363
  } = cli.flags;
1364
+ const [key = ''] = cli.input;
1365
+ if (!shadowNpmInject.supportedConfigKeys.has(key) && key !== 'test') {
1366
+ // Use exit status of 2 to indicate incorrect usage, generally invalid
1367
+ // options or missing arguments.
1368
+ // https://www.gnu.org/software/bash/manual/html_node/Exit-Status.html
1369
+ process.exitCode = 2;
1370
+ logger.logger.fail(commonTags.stripIndents`${colors.bgRed(colors.white('Input error'))}: Please provide the required fields:
1371
+
1372
+ - Config key should be the first arg ${!key ? colors.red('(missing!)') : !shadowNpmInject.supportedConfigKeys.has(key) ? colors.red('(invalid config key!)') : colors.green('(ok)')}
1373
+ `);
1374
+ return;
1375
+ }
1446
1376
  if (cli.flags['dryRun']) {
1447
- logger.logger.log(DRY_RUN_BAIL_TEXT$y);
1377
+ logger.logger.log(DRY_RUN_BAIL_TEXT$C);
1448
1378
  return;
1449
1379
  }
1450
- await handleDependencies({
1451
- limit: Number(limit || 0) || 0,
1452
- offset: Number(offset || 0) || 0,
1380
+ await handleConfigGet({
1381
+ key: key,
1453
1382
  outputKind: json ? 'json' : markdown ? 'markdown' : 'text'
1454
1383
  });
1455
1384
  }
1456
1385
 
1457
- async function fetchDiffScan({
1458
- after,
1459
- before,
1460
- orgSlug
1386
+ async function outputConfigList({
1387
+ full,
1388
+ outputKind
1461
1389
  }) {
1462
- const apiToken = shadowNpmInject.getDefaultToken();
1463
- if (!apiToken) {
1464
- throw new shadowNpmInject.AuthError('User must be authenticated to run this command. To log in, run the command `socket login` and enter your API key.');
1390
+ if (outputKind === 'json') {
1391
+ const obj = {};
1392
+ for (const key of shadowNpmInject.supportedConfigKeys.keys()) {
1393
+ let value = shadowNpmInject.getConfigValue(key);
1394
+ if (!full && shadowNpmInject.sensitiveConfigKeys.has(key)) {
1395
+ value = '********';
1396
+ }
1397
+ if (full || value !== undefined) {
1398
+ obj[key] = value ?? '<none>';
1399
+ }
1400
+ }
1401
+ logger.logger.log(JSON.stringify({
1402
+ success: true,
1403
+ full,
1404
+ config: obj
1405
+ }, null, 2));
1406
+ } else {
1407
+ const maxWidth = Array.from(shadowNpmInject.supportedConfigKeys.keys()).reduce((a, b) => Math.max(a, b.length), 0);
1408
+ logger.logger.log('# Local CLI Config');
1409
+ logger.logger.log('');
1410
+ logger.logger.log(`This is the local CLI config (full=${!!full}):`);
1411
+ logger.logger.log('');
1412
+ for (const key of shadowNpmInject.supportedConfigKeys.keys()) {
1413
+ let value = shadowNpmInject.getConfigValue(key);
1414
+ if (!full && shadowNpmInject.sensitiveConfigKeys.has(key)) {
1415
+ value = '********';
1416
+ }
1417
+ if (full || value !== undefined) {
1418
+ logger.logger.log(`- ${key}:${' '.repeat(Math.max(0, maxWidth - key.length + 3))} ${Array.isArray(value) ? value.join(', ') || '<none>' : value ?? '<none>'}`);
1419
+ }
1420
+ }
1465
1421
  }
1466
- return await fetchDiffScanWithToken(apiToken, {
1467
- after,
1468
- before,
1469
- orgSlug
1470
- });
1471
1422
  }
1472
- async function fetchDiffScanWithToken(apiToken, {
1473
- after,
1474
- before,
1475
- orgSlug
1423
+
1424
+ const {
1425
+ DRY_RUN_BAIL_TEXT: DRY_RUN_BAIL_TEXT$B
1426
+ } = constants;
1427
+ const config$C = {
1428
+ commandName: 'list',
1429
+ description: 'Show all local CLI config items and their values',
1430
+ hidden: false,
1431
+ flags: {
1432
+ ...commonFlags,
1433
+ ...outputFlags,
1434
+ full: {
1435
+ type: 'boolean',
1436
+ default: false,
1437
+ description: 'Show full tokens in plaintext (unsafe)'
1438
+ }
1439
+ },
1440
+ help: (command, config) => `
1441
+ Usage
1442
+ $ ${command} <org slug>
1443
+
1444
+ Options
1445
+ ${getFlagListOutput(config.flags, 6)}
1446
+
1447
+ Keys:
1448
+
1449
+ ${Array.from(shadowNpmInject.supportedConfigKeys.entries()).map(([key, desc]) => ` - ${key} -- ${desc}`).join('\n')}
1450
+
1451
+ Examples
1452
+ $ ${command} FakeOrg --repoName=test-repo
1453
+ `
1454
+ };
1455
+ const cmdConfigList = {
1456
+ description: config$C.description,
1457
+ hidden: config$C.hidden,
1458
+ run: run$C
1459
+ };
1460
+ async function run$C(argv, importMeta, {
1461
+ parentName
1476
1462
  }) {
1477
- // Lazily access constants.spinner.
1463
+ const cli = meowOrExit({
1464
+ argv,
1465
+ config: config$C,
1466
+ importMeta,
1467
+ parentName
1468
+ });
1478
1469
  const {
1479
- spinner
1480
- } = constants;
1481
- spinner.start('Fetching diff-scan...');
1482
- const response = await queryAPI(`orgs/${orgSlug}/full-scans/diff?before=${encodeURIComponent(before)}&after=${encodeURIComponent(after)}`, apiToken);
1483
- spinner?.successAndStop('Received diff-scan response');
1484
- if (!response.ok) {
1485
- const err = await handleAPIError(response.status);
1486
- spinner.errorAndStop(`${colors.bgRed(colors.white(response.statusText))}: ${err}`);
1470
+ full,
1471
+ json,
1472
+ markdown
1473
+ } = cli.flags;
1474
+ if (cli.flags['dryRun']) {
1475
+ logger.logger.log(DRY_RUN_BAIL_TEXT$B);
1487
1476
  return;
1488
1477
  }
1489
- const result = await handleApiCall(await response.json(), 'Deserializing json');
1490
- return result;
1478
+ await outputConfigList({
1479
+ full: !!full,
1480
+ outputKind: json ? 'json' : markdown ? 'markdown' : 'text'
1481
+ });
1491
1482
  }
1492
1483
 
1493
- async function outputDiffScan(result, {
1494
- depth,
1495
- file,
1496
- outputKind
1497
- }) {
1498
- const dashboardUrl = result.diff_report_url;
1499
- const dashboardMessage = dashboardUrl ? `\n View this diff scan in the Socket dashboard: ${colors.cyan(dashboardUrl)}` : '';
1484
+ async function outputConfigSet(key, _value, outputKind) {
1485
+ if (outputKind === 'json') {
1486
+ logger.logger.log(JSON.stringify({
1487
+ success: true,
1488
+ message: `Config key '${key}' was updated`
1489
+ }));
1490
+ } else if (outputKind === 'markdown') {
1491
+ logger.logger.log(`# Update config`);
1492
+ logger.logger.log('');
1493
+ logger.logger.log(`Config key '${key}' was updated`);
1494
+ } else {
1495
+ logger.logger.log(`OK`);
1496
+ }
1497
+ }
1498
+
1499
+ async function handleConfigSet({
1500
+ key,
1501
+ outputKind,
1502
+ value
1503
+ }) {
1504
+ shadowNpmInject.updateConfigValue(key, value);
1505
+ await outputConfigSet(key, value, outputKind);
1506
+ }
1507
+
1508
+ const {
1509
+ DRY_RUN_BAIL_TEXT: DRY_RUN_BAIL_TEXT$A
1510
+ } = constants;
1511
+ const config$B = {
1512
+ commandName: 'set',
1513
+ description: 'Update the value of a local CLI config item',
1514
+ hidden: false,
1515
+ flags: {
1516
+ ...commonFlags,
1517
+ ...outputFlags
1518
+ },
1519
+ help: (command, config) => `
1520
+ Usage
1521
+ $ ${command} <key> <value>
1522
+
1523
+ Options
1524
+ ${getFlagListOutput(config.flags, 6)}
1525
+
1526
+ This is a crude way of updating the local configuration for this CLI tool.
1527
+
1528
+ Note that updating a value here is nothing more than updating a key/value
1529
+ store entry. No validation is happening. The server may reject your config.
1530
+
1531
+ Keys:
1532
+
1533
+ ${Array.from(shadowNpmInject.supportedConfigKeys.entries()).map(([key, desc]) => ` - ${key} -- ${desc}`).join('\n')}
1534
+
1535
+ Examples
1536
+ $ ${command} apiProxy https://example.com
1537
+ `
1538
+ };
1539
+ const cmdConfigSet = {
1540
+ description: config$B.description,
1541
+ hidden: config$B.hidden,
1542
+ run: run$B
1543
+ };
1544
+ async function run$B(argv, importMeta, {
1545
+ parentName
1546
+ }) {
1547
+ const cli = meowOrExit({
1548
+ argv,
1549
+ config: config$B,
1550
+ importMeta,
1551
+ parentName
1552
+ });
1553
+ const {
1554
+ json,
1555
+ markdown
1556
+ } = cli.flags;
1557
+ const [key = '', ...rest] = cli.input;
1558
+ const value = rest.join(' ');
1559
+ if (!shadowNpmInject.supportedConfigKeys.has(key) && key !== 'test' || !value) {
1560
+ // Use exit status of 2 to indicate incorrect usage, generally invalid
1561
+ // options or missing arguments.
1562
+ // https://www.gnu.org/software/bash/manual/html_node/Exit-Status.html
1563
+ process.exitCode = 2;
1564
+ logger.logger.fail(commonTags.stripIndents`${colors.bgRed(colors.white('Input error'))}: Please provide the required fields:
1565
+
1566
+ - Config key should be the first arg ${!key ? colors.red('(missing!)') : !shadowNpmInject.supportedConfigKeys.has(key) ? colors.red('(invalid config key!)') : colors.green('(ok)')}
1567
+
1568
+ - Key value should be the remaining args (use \`del\` to unset a value) ${!value ? colors.red('(missing!)') : colors.green('(ok)')}`);
1569
+ return;
1570
+ }
1571
+ if (cli.flags['dryRun']) {
1572
+ logger.logger.log(DRY_RUN_BAIL_TEXT$A);
1573
+ return;
1574
+ }
1575
+ await handleConfigSet({
1576
+ key: key,
1577
+ outputKind: json ? 'json' : markdown ? 'markdown' : 'text',
1578
+ value
1579
+ });
1580
+ }
1581
+
1582
+ async function outputConfigUnset(key, outputKind) {
1583
+ if (outputKind === 'json') {
1584
+ logger.logger.log(JSON.stringify({
1585
+ success: true,
1586
+ message: `Config key '${key}' was unset`
1587
+ }));
1588
+ } else if (outputKind === 'markdown') {
1589
+ logger.logger.log(`# Update config`);
1590
+ logger.logger.log('');
1591
+ logger.logger.log(`Config key '${key}' was unset`);
1592
+ } else {
1593
+ logger.logger.log(`OK`);
1594
+ }
1595
+ }
1596
+
1597
+ async function handleConfigUnset({
1598
+ key,
1599
+ outputKind
1600
+ }) {
1601
+ shadowNpmInject.updateConfigValue(key, undefined);
1602
+ await outputConfigUnset(key, outputKind);
1603
+ }
1604
+
1605
+ const {
1606
+ DRY_RUN_BAIL_TEXT: DRY_RUN_BAIL_TEXT$z
1607
+ } = constants;
1608
+ const config$A = {
1609
+ commandName: 'unset',
1610
+ description: 'Clear the value of a local CLI config item',
1611
+ hidden: false,
1612
+ flags: {
1613
+ ...commonFlags,
1614
+ ...outputFlags
1615
+ },
1616
+ help: (command, config) => `
1617
+ Usage
1618
+ $ ${command} <org slug>
1619
+
1620
+ Options
1621
+ ${getFlagListOutput(config.flags, 6)}
1622
+
1623
+ Keys:
1624
+
1625
+ ${Array.from(shadowNpmInject.supportedConfigKeys.entries()).map(([key, desc]) => ` - ${key} -- ${desc}`).join('\n')}
1626
+
1627
+ Examples
1628
+ $ ${command} FakeOrg --repoName=test-repo
1629
+ `
1630
+ };
1631
+ const cmdConfigUnset = {
1632
+ description: config$A.description,
1633
+ hidden: config$A.hidden,
1634
+ run: run$A
1635
+ };
1636
+ async function run$A(argv, importMeta, {
1637
+ parentName
1638
+ }) {
1639
+ const cli = meowOrExit({
1640
+ argv,
1641
+ config: config$A,
1642
+ importMeta,
1643
+ parentName
1644
+ });
1645
+ const {
1646
+ json,
1647
+ markdown
1648
+ } = cli.flags;
1649
+ const [key = ''] = cli.input;
1650
+ if (!shadowNpmInject.supportedConfigKeys.has(key) && key !== 'test') {
1651
+ // Use exit status of 2 to indicate incorrect usage, generally invalid
1652
+ // options or missing arguments.
1653
+ // https://www.gnu.org/software/bash/manual/html_node/Exit-Status.html
1654
+ process.exitCode = 2;
1655
+ logger.logger.fail(commonTags.stripIndents`${colors.bgRed(colors.white('Input error'))}: Please provide the required fields:
1656
+
1657
+ - Config key should be the first arg ${!key ? colors.red('(missing!)') : !shadowNpmInject.supportedConfigKeys.has(key) ? colors.red('(invalid config key!)') : colors.green('(ok)')}
1658
+ `);
1659
+ return;
1660
+ }
1661
+ if (cli.flags['dryRun']) {
1662
+ logger.logger.log(DRY_RUN_BAIL_TEXT$z);
1663
+ return;
1664
+ }
1665
+ await handleConfigUnset({
1666
+ key: key,
1667
+ outputKind: json ? 'json' : markdown ? 'markdown' : 'text'
1668
+ });
1669
+ }
1670
+
1671
+ const description$7 = 'Commands related to the local CLI configuration';
1672
+ const cmdConfig = {
1673
+ description: description$7,
1674
+ hidden: true,
1675
+ // [beta]
1676
+ async run(argv, importMeta, {
1677
+ parentName
1678
+ }) {
1679
+ await meowWithSubcommands({
1680
+ unset: cmdConfigUnset,
1681
+ get: cmdConfigGet,
1682
+ list: cmdConfigList,
1683
+ set: cmdConfigSet
1684
+ }, {
1685
+ argv,
1686
+ description: description$7,
1687
+ importMeta,
1688
+ name: `${parentName} config`
1689
+ });
1690
+ }
1691
+ };
1692
+
1693
+ async function fetchDependencies({
1694
+ limit,
1695
+ offset
1696
+ }) {
1697
+ const apiToken = shadowNpmInject.getDefaultToken();
1698
+ if (!apiToken) {
1699
+ throw new shadowNpmInject.AuthError('User must be authenticated to run this command. To log in, run the command `socket login` and enter your API key.');
1700
+ }
1701
+ return await fetchDependenciesWithToken(apiToken, {
1702
+ limit,
1703
+ offset
1704
+ });
1705
+ }
1706
+ async function fetchDependenciesWithToken(apiToken, {
1707
+ limit,
1708
+ offset
1709
+ }) {
1710
+ // Lazily access constants.spinner.
1711
+ const {
1712
+ spinner
1713
+ } = constants;
1714
+ spinner.start('Fetching organization dependencies...');
1715
+ const sockSdk = await shadowNpmInject.setupSdk(apiToken);
1716
+ const result = await handleApiCall(sockSdk.searchDependencies({
1717
+ limit,
1718
+ offset
1719
+ }), 'Searching dependencies');
1720
+ spinner?.successAndStop('Received organization dependencies response.');
1721
+ if (!result.success) {
1722
+ handleUnsuccessfulApiResponse('searchDependencies', result);
1723
+ return;
1724
+ }
1725
+ return result.data;
1726
+ }
1727
+
1728
+ // @ts-ignore
1729
+ async function outputDependencies(data, {
1730
+ limit,
1731
+ offset,
1732
+ outputKind
1733
+ }) {
1734
+ if (outputKind === 'json') {
1735
+ let json;
1736
+ try {
1737
+ json = JSON.stringify(data, null, 2);
1738
+ } catch (e) {
1739
+ process.exitCode = 1;
1740
+ logger.logger.fail('There was a problem converting the data to JSON, please try without the `--json` flag');
1741
+ return;
1742
+ }
1743
+ logger.logger.log(json);
1744
+ return;
1745
+ }
1746
+ logger.logger.log('Request details: Offset:', offset, ', limit:', limit, ', is there more data after this?', data.end ? 'no' : 'yes');
1747
+ const options = {
1748
+ columns: [{
1749
+ field: 'namespace',
1750
+ name: colors.cyan('Namespace')
1751
+ }, {
1752
+ field: 'name',
1753
+ name: colors.cyan('Name')
1754
+ }, {
1755
+ field: 'version',
1756
+ name: colors.cyan('Version')
1757
+ }, {
1758
+ field: 'repository',
1759
+ name: colors.cyan('Repository')
1760
+ }, {
1761
+ field: 'branch',
1762
+ name: colors.cyan('Branch')
1763
+ }, {
1764
+ field: 'type',
1765
+ name: colors.cyan('Type')
1766
+ }, {
1767
+ field: 'direct',
1768
+ name: colors.cyan('Direct')
1769
+ }]
1770
+ };
1771
+ logger.logger.log(chalkTable(options, data.rows));
1772
+ }
1773
+
1774
+ async function handleDependencies({
1775
+ limit,
1776
+ offset,
1777
+ outputKind
1778
+ }) {
1779
+ const data = await fetchDependencies({
1780
+ limit,
1781
+ offset
1782
+ });
1783
+ if (!data) return;
1784
+ await outputDependencies(data, {
1785
+ limit,
1786
+ offset,
1787
+ outputKind
1788
+ });
1789
+ }
1790
+
1791
+ const {
1792
+ DRY_RUN_BAIL_TEXT: DRY_RUN_BAIL_TEXT$y
1793
+ } = constants;
1794
+ const config$z = {
1795
+ commandName: 'dependencies',
1796
+ description: 'Search for any dependency that is being used in your organization',
1797
+ hidden: false,
1798
+ flags: {
1799
+ ...commonFlags,
1800
+ limit: {
1801
+ type: 'number',
1802
+ shortFlag: 'l',
1803
+ default: 50,
1804
+ description: 'Maximum number of dependencies returned'
1805
+ },
1806
+ offset: {
1807
+ type: 'number',
1808
+ shortFlag: 'o',
1809
+ default: 0,
1810
+ description: 'Page number'
1811
+ },
1812
+ ...outputFlags
1813
+ },
1814
+ help: (command, config) => `
1815
+ Usage
1816
+ ${command}
1817
+
1818
+ Options
1819
+ ${getFlagListOutput(config.flags, 6)}
1820
+
1821
+ Examples
1822
+ ${command} --limit 20 --offset 10
1823
+ `
1824
+ };
1825
+ const cmdScanCreate$1 = {
1826
+ description: config$z.description,
1827
+ hidden: config$z.hidden,
1828
+ run: run$z
1829
+ };
1830
+ async function run$z(argv, importMeta, {
1831
+ parentName
1832
+ }) {
1833
+ const cli = meowOrExit({
1834
+ argv,
1835
+ config: config$z,
1836
+ importMeta,
1837
+ parentName
1838
+ });
1839
+ const {
1840
+ json,
1841
+ limit,
1842
+ markdown,
1843
+ offset
1844
+ } = cli.flags;
1845
+ if (cli.flags['dryRun']) {
1846
+ logger.logger.log(DRY_RUN_BAIL_TEXT$y);
1847
+ return;
1848
+ }
1849
+ await handleDependencies({
1850
+ limit: Number(limit || 0) || 0,
1851
+ offset: Number(offset || 0) || 0,
1852
+ outputKind: json ? 'json' : markdown ? 'markdown' : 'text'
1853
+ });
1854
+ }
1855
+
1856
+ async function fetchDiffScan({
1857
+ after,
1858
+ before,
1859
+ orgSlug
1860
+ }) {
1861
+ const apiToken = shadowNpmInject.getDefaultToken();
1862
+ if (!apiToken) {
1863
+ throw new shadowNpmInject.AuthError('User must be authenticated to run this command. To log in, run the command `socket login` and enter your API key.');
1864
+ }
1865
+ return await fetchDiffScanWithToken(apiToken, {
1866
+ after,
1867
+ before,
1868
+ orgSlug
1869
+ });
1870
+ }
1871
+ async function fetchDiffScanWithToken(apiToken, {
1872
+ after,
1873
+ before,
1874
+ orgSlug
1875
+ }) {
1876
+ // Lazily access constants.spinner.
1877
+ const {
1878
+ spinner
1879
+ } = constants;
1880
+ spinner.start('Fetching diff-scan...');
1881
+ const response = await queryApi(`orgs/${orgSlug}/full-scans/diff?before=${encodeURIComponent(before)}&after=${encodeURIComponent(after)}`, apiToken);
1882
+ spinner?.successAndStop('Received diff-scan response');
1883
+ if (!response.ok) {
1884
+ const err = await handleApiError(response.status);
1885
+ spinner.errorAndStop(`${colors.bgRed(colors.white(response.statusText))}: ${err}`);
1886
+ return;
1887
+ }
1888
+ const result = await handleApiCall(await response.json(), 'Deserializing json');
1889
+ return result;
1890
+ }
1891
+
1892
+ async function outputDiffScan(result, {
1893
+ depth,
1894
+ file,
1895
+ outputKind
1896
+ }) {
1897
+ const dashboardUrl = result.diff_report_url;
1898
+ const dashboardMessage = dashboardUrl ? `\n View this diff scan in the Socket dashboard: ${colors.cyan(dashboardUrl)}` : '';
1500
1899
 
1501
1900
  // When forcing json, or dumping to file, serialize to string such that it
1502
1901
  // won't get truncated. The only way to dump the full raw JSON to stdout is
@@ -1827,12 +2226,12 @@ async function getAlertsMapFromPnpmLockfile(lockfile, options) {
1827
2226
  }
1828
2227
  const getText = () => `Looking up data for ${remaining} packages`;
1829
2228
  spinner?.start(getText());
1830
- const socketSdk = await shadowNpmInject.setupSdk(shadowNpmInject.getPublicToken());
2229
+ const sockSdk = await shadowNpmInject.setupSdk(shadowNpmInject.getPublicToken());
1831
2230
  const toAlertsMapOptions = {
1832
2231
  overrides: lockfile.overrides,
1833
2232
  ...options
1834
2233
  };
1835
- for await (const batchPackageFetchResult of socketSdk.batchPackageStream({
2234
+ for await (const batchPackageFetchResult of sockSdk.batchPackageStream({
1836
2235
  alerts: 'true',
1837
2236
  compact: 'true',
1838
2237
  fixable: include.unfixable ? 'false' : 'true'
@@ -2433,15 +2832,15 @@ async function run$x(argv, importMeta, {
2433
2832
  }
2434
2833
 
2435
2834
  async function fetchPackageInfo(pkgName, pkgVersion, includeAllIssues) {
2436
- const socketSdk = await shadowNpmInject.setupSdk(shadowNpmInject.getPublicToken());
2835
+ const sockSdk = await shadowNpmInject.setupSdk(shadowNpmInject.getPublicToken());
2437
2836
 
2438
2837
  // Lazily access constants.spinner.
2439
2838
  const {
2440
2839
  spinner
2441
2840
  } = constants;
2442
2841
  spinner.start(pkgVersion === 'latest' ? `Looking up data for the latest version of ${pkgName}` : `Looking up data for version ${pkgVersion} of ${pkgName}`);
2443
- const result = await handleApiCall(socketSdk.getIssuesByNPMPackage(pkgName, pkgVersion), 'looking up package');
2444
- const scoreResult = await handleApiCall(socketSdk.getScoreByNPMPackage(pkgName, pkgVersion), 'looking up package score');
2842
+ const result = await handleApiCall(sockSdk.getIssuesByNPMPackage(pkgName, pkgVersion), 'looking up package');
2843
+ const scoreResult = await handleApiCall(sockSdk.getScoreByNPMPackage(pkgName, pkgVersion), 'looking up package score');
2445
2844
  spinner.successAndStop('Data fetched');
2446
2845
  if (result.success === false) {
2447
2846
  return handleUnsuccessfulApiResponse('getIssuesByNPMPackage', result);
@@ -2469,7 +2868,7 @@ function formatScore$1(score) {
2469
2868
  return colors.red(`${score}`);
2470
2869
  }
2471
2870
  function outputPackageIssuesDetails(packageData, outputMarkdown) {
2472
- const issueDetails = packageData.filter(d => d.value?.severity === shadowNpmInject.SEVERITY.critical || d.value?.severity === shadowNpmInject.SEVERITY.high);
2871
+ const issueDetails = packageData.filter(d => d.value?.severity === shadowNpmInject.ALERT_SEVERITY.critical || d.value?.severity === shadowNpmInject.ALERT_SEVERITY.high);
2473
2872
  const uniqueIssueDetails = issueDetails.reduce((acc, issue) => {
2474
2873
  const {
2475
2874
  type
@@ -2656,18 +3055,18 @@ async function run$w(argv, importMeta, {
2656
3055
  }
2657
3056
 
2658
3057
  function applyLogin(apiToken, enforcedOrgs, apiBaseUrl, apiProxy) {
2659
- shadowNpmInject.updateSetting('enforcedOrgs', enforcedOrgs);
2660
- shadowNpmInject.updateSetting('apiToken', apiToken);
2661
- shadowNpmInject.updateSetting('apiBaseUrl', apiBaseUrl);
2662
- shadowNpmInject.updateSetting('apiProxy', apiProxy);
3058
+ shadowNpmInject.updateConfigValue('enforcedOrgs', enforcedOrgs);
3059
+ shadowNpmInject.updateConfigValue('apiToken', apiToken);
3060
+ shadowNpmInject.updateConfigValue('apiBaseUrl', apiBaseUrl);
3061
+ shadowNpmInject.updateConfigValue('apiProxy', apiProxy);
2663
3062
  }
2664
3063
 
2665
3064
  const {
2666
3065
  SOCKET_PUBLIC_API_TOKEN
2667
3066
  } = constants;
2668
3067
  async function attemptLogin(apiBaseUrl, apiProxy) {
2669
- apiBaseUrl ??= shadowNpmInject.getSetting('apiBaseUrl') ?? undefined;
2670
- apiProxy ??= shadowNpmInject.getSetting('apiProxy') ?? undefined;
3068
+ apiBaseUrl ??= shadowNpmInject.getConfigValue('apiBaseUrl') ?? undefined;
3069
+ apiProxy ??= shadowNpmInject.getConfigValue('apiProxy') ?? undefined;
2671
3070
  const apiToken = (await prompts.password({
2672
3071
  message: `Enter your ${terminalLink('Socket.dev API key', 'https://docs.socket.dev/docs/api-keys')} (leave blank for a public key)`
2673
3072
  })) || SOCKET_PUBLIC_API_TOKEN;
@@ -2723,7 +3122,7 @@ async function attemptLogin(apiBaseUrl, apiProxy) {
2723
3122
  }
2724
3123
  }
2725
3124
  spinner.stop();
2726
- const oldToken = shadowNpmInject.getSetting('apiToken');
3125
+ const oldToken = shadowNpmInject.getConfigValue('apiToken');
2727
3126
  try {
2728
3127
  applyLogin(apiToken, enforcedOrgs, apiBaseUrl, apiProxy);
2729
3128
  logger.logger.success(`API credentials ${oldToken ? 'updated' : 'set'}`);
@@ -2791,10 +3190,10 @@ async function run$v(argv, importMeta, {
2791
3190
  }
2792
3191
 
2793
3192
  function applyLogout() {
2794
- shadowNpmInject.updateSetting('apiToken', null);
2795
- shadowNpmInject.updateSetting('apiBaseUrl', null);
2796
- shadowNpmInject.updateSetting('apiProxy', null);
2797
- shadowNpmInject.updateSetting('enforcedOrgs', null);
3193
+ shadowNpmInject.updateConfigValue('apiToken', null);
3194
+ shadowNpmInject.updateConfigValue('apiBaseUrl', null);
3195
+ shadowNpmInject.updateConfigValue('apiProxy', null);
3196
+ shadowNpmInject.updateConfigValue('enforcedOrgs', null);
2798
3197
  }
2799
3198
 
2800
3199
  function attemptLogout() {
@@ -4543,14 +4942,14 @@ async function fetchOrganization() {
4543
4942
  return await fetchOrganizationWithToken(apiToken);
4544
4943
  }
4545
4944
  async function fetchOrganizationWithToken(apiToken) {
4546
- const socketSdk = await shadowNpmInject.setupSdk(apiToken);
4945
+ const sockSdk = await shadowNpmInject.setupSdk(apiToken);
4547
4946
 
4548
4947
  // Lazily access constants.spinner.
4549
4948
  const {
4550
4949
  spinner
4551
4950
  } = constants;
4552
4951
  spinner.start('Fetching organization list...');
4553
- const result = await handleApiCall(socketSdk.getOrganizations(), 'looking up organizations');
4952
+ const result = await handleApiCall(sockSdk.getOrganizations(), 'looking up organizations');
4554
4953
  spinner.successAndStop('Received organization list response.');
4555
4954
  if (!result.success) {
4556
4955
  handleUnsuccessfulApiResponse('getOrganizations', result);
@@ -4680,9 +5079,9 @@ async function fetchSecurityPolicyWithToken(apiToken, orgSlug) {
4680
5079
  const {
4681
5080
  spinner
4682
5081
  } = constants;
4683
- const socketSdk = await shadowNpmInject.setupSdk(apiToken);
5082
+ const sockSdk = await shadowNpmInject.setupSdk(apiToken);
4684
5083
  spinner.start('Fetching organization quota...');
4685
- const result = await handleApiCall(socketSdk.getOrgSecurityPolicy(orgSlug), 'looking up organization quota');
5084
+ const result = await handleApiCall(sockSdk.getOrgSecurityPolicy(orgSlug), 'looking up organization quota');
4686
5085
  spinner?.successAndStop('Received organization quota response.');
4687
5086
  if (!result.success) {
4688
5087
  handleUnsuccessfulApiResponse('getOrgSecurityPolicy', result);
@@ -4825,9 +5224,9 @@ async function fetchQuotaWithToken(apiToken) {
4825
5224
  const {
4826
5225
  spinner
4827
5226
  } = constants;
4828
- const socketSdk = await shadowNpmInject.setupSdk(apiToken);
5227
+ const sockSdk = await shadowNpmInject.setupSdk(apiToken);
4829
5228
  spinner.start('Fetching organization quota...');
4830
- const result = await handleApiCall(socketSdk.getQuota(), 'looking up organization quota');
5229
+ const result = await handleApiCall(sockSdk.getQuota(), 'looking up organization quota');
4831
5230
  spinner?.successAndStop('Recieved organization quota response.');
4832
5231
  if (!result.success) {
4833
5232
  handleUnsuccessfulApiResponse('getQuota', result);
@@ -4954,8 +5353,8 @@ async function fetchPurlsShallowScore(purls) {
4954
5353
  spinner
4955
5354
  } = constants;
4956
5355
  spinner.start(`Requesting data ...`);
4957
- const socketSdk = await shadowNpmInject.setupSdk(shadowNpmInject.getPublicToken());
4958
- const result = await handleApiCall(socketSdk.batchPackageFetch({
5356
+ const sockSdk = await shadowNpmInject.setupSdk(shadowNpmInject.getPublicToken());
5357
+ const result = await handleApiCall(sockSdk.batchPackageFetch({
4959
5358
  alerts: 'true'
4960
5359
  // compact: false,
4961
5360
  // fixable: false,
@@ -5356,8 +5755,8 @@ async function createReport(socketConfig, inputPaths, {
5356
5755
  const {
5357
5756
  spinner
5358
5757
  } = constants;
5359
- const socketSdk = await shadowNpmInject.setupSdk();
5360
- const supportedFiles = await socketSdk.getReportSupportedFiles().then(res => {
5758
+ const sockSdk = await shadowNpmInject.setupSdk();
5759
+ const supportedFiles = await sockSdk.getReportSupportedFiles().then(res => {
5361
5760
  if (!res.success) handleUnsuccessfulApiResponse('getReportSupportedFiles', res);
5362
5761
  return res.data;
5363
5762
  }).catch(cause => {
@@ -5365,7 +5764,7 @@ async function createReport(socketConfig, inputPaths, {
5365
5764
  cause
5366
5765
  });
5367
5766
  });
5368
- const packagePaths = await shadowNpmPaths.getPackageFilesFullScans(cwd, inputPaths, supportedFiles, socketConfig);
5767
+ const packagePaths = await shadowNpmPaths.getPackageFilesForScan(cwd, inputPaths, supportedFiles, socketConfig);
5369
5768
  const packagePathsCount = packagePaths.length;
5370
5769
  if (packagePathsCount && debug.isDebug()) {
5371
5770
  for (const pkgPath of packagePaths) {
@@ -5377,7 +5776,7 @@ async function createReport(socketConfig, inputPaths, {
5377
5776
  return undefined;
5378
5777
  }
5379
5778
  spinner.start(`Creating report with ${packagePathsCount} package ${words.pluralize('file', packagePathsCount)}`);
5380
- const apiCall = socketSdk.createReportFromFilePaths(packagePaths, cwd, socketConfig?.issueRules);
5779
+ const apiCall = sockSdk.createReportFromFilePaths(packagePaths, cwd, socketConfig?.issueRules);
5381
5780
  const result = await handleApiCall(apiCall, 'creating report');
5382
5781
  if (!result.success) {
5383
5782
  handleUnsuccessfulApiResponse('createReport', result);
@@ -5388,8 +5787,8 @@ async function createReport(socketConfig, inputPaths, {
5388
5787
  }
5389
5788
 
5390
5789
  async function getSocketConfig(absoluteConfigPath) {
5391
- const socketConfig = await config$D.readSocketConfig(absoluteConfigPath).catch(cause => {
5392
- if (cause && typeof cause === 'object' && cause instanceof config$D.SocketValidationError) {
5790
+ const socketConfig = await config$H.readSocketConfig(absoluteConfigPath).catch(cause => {
5791
+ if (cause && typeof cause === 'object' && cause instanceof config$H.SocketValidationError) {
5393
5792
  // Inspired by workbox-build:
5394
5793
  // https://github.com/GoogleChrome/workbox/blob/95f97a207fd51efb3f8a653f6e3e58224183a778/packages/workbox-build/src/lib/validate-options.ts#L68-L71
5395
5794
  const betterErrors = betterAjvErrors.betterAjvErrors({
@@ -5417,12 +5816,12 @@ async function fetchReportData$1(reportId, includeAllIssues, strict) {
5417
5816
  } = constants;
5418
5817
  spinner.log('Fetching report with ID ${reportId} (this could take a while)');
5419
5818
  spinner.start(`Fetch started... (this could take a while)`);
5420
- const socketSdk = await shadowNpmInject.setupSdk();
5819
+ const sockSdk = await shadowNpmInject.setupSdk();
5421
5820
  let result;
5422
5821
  for (let retry = 1; !result; ++retry) {
5423
5822
  try {
5424
5823
  // eslint-disable-next-line no-await-in-loop
5425
- result = await handleApiCall(socketSdk.getReport(reportId), 'fetching report');
5824
+ result = await handleApiCall(sockSdk.getReport(reportId), 'fetching report');
5426
5825
  } catch (err) {
5427
5826
  if (retry >= MAX_TIMEOUT_RETRY || !(err instanceof Error) || err.cause?.cause?.response?.statusCode !== HTTP_CODE_TIMEOUT) {
5428
5827
  spinner.stop(`Failed to fetch report`);
@@ -5474,7 +5873,7 @@ function formatReportDataOutput(reportId, data, commandName, outputKind, strict,
5474
5873
  }
5475
5874
  }
5476
5875
 
5477
- async function getFullScan(orgSlug, fullScanId) {
5876
+ async function fetchScan(orgSlug, scanId) {
5478
5877
  // Lazily access constants.spinner.
5479
5878
  const {
5480
5879
  spinner
@@ -5484,10 +5883,10 @@ async function getFullScan(orgSlug, fullScanId) {
5484
5883
  throw new shadowNpmInject.AuthError('User must be authenticated to run this command. To log in, run the command `socket login` and enter your API key.');
5485
5884
  }
5486
5885
  spinner.start('Fetching full-scan...');
5487
- const response = await queryAPI(`orgs/${orgSlug}/full-scans/${encodeURIComponent(fullScanId)}`, apiToken);
5886
+ const response = await queryApi(`orgs/${orgSlug}/full-scans/${encodeURIComponent(scanId)}`, apiToken);
5488
5887
  spinner.stop('Fetch complete.');
5489
5888
  if (!response.ok) {
5490
- const err = await handleAPIError(response.status);
5889
+ const err = await handleApiError(response.status);
5491
5890
  logger.logger.fail(`${colors.bgRed(colors.white(response.statusText))}: Fetch error: ${err}`);
5492
5891
  return;
5493
5892
  }
@@ -5513,7 +5912,7 @@ async function viewReport(reportId, {
5513
5912
  strict
5514
5913
  }) {
5515
5914
  const result = await fetchReportData$1(reportId, all, strict);
5516
- const artifacts = await getFullScan('socketdev', reportId);
5915
+ const artifacts = await fetchScan('socketdev', reportId);
5517
5916
  if (result) {
5518
5917
  formatReportDataOutput(reportId, result, commandName, outputKind, strict, artifacts);
5519
5918
  }
@@ -5714,9 +6113,9 @@ async function fetchCreateRepoWithToken(apiToken, {
5714
6113
  const {
5715
6114
  spinner
5716
6115
  } = constants;
5717
- const socketSdk = await shadowNpmInject.setupSdk(apiToken);
6116
+ const sockSdk = await shadowNpmInject.setupSdk(apiToken);
5718
6117
  spinner.start('Sending request ot create a repository...');
5719
- const result = await handleApiCall(socketSdk.createOrgRepo(orgSlug, {
6118
+ const result = await handleApiCall(sockSdk.createOrgRepo(orgSlug, {
5720
6119
  name: repoName,
5721
6120
  description,
5722
6121
  homepage,
@@ -5861,8 +6260,8 @@ async function deleteRepoWithToken(orgSlug, repoName, apiToken) {
5861
6260
  spinner
5862
6261
  } = constants;
5863
6262
  spinner.start('Deleting repository...');
5864
- const socketSdk = await shadowNpmInject.setupSdk(apiToken);
5865
- const result = await handleApiCall(socketSdk.deleteOrgRepo(orgSlug, repoName), 'deleting repository');
6263
+ const sockSdk = await shadowNpmInject.setupSdk(apiToken);
6264
+ const result = await handleApiCall(sockSdk.deleteOrgRepo(orgSlug, repoName), 'deleting repository');
5866
6265
  if (!result.success) {
5867
6266
  handleUnsuccessfulApiResponse('deleteOrgRepo', result);
5868
6267
  return;
@@ -5957,9 +6356,9 @@ async function fetchListReposWithToken(apiToken, {
5957
6356
  const {
5958
6357
  spinner
5959
6358
  } = constants;
5960
- const socketSdk = await shadowNpmInject.setupSdk(apiToken);
6359
+ const sockSdk = await shadowNpmInject.setupSdk(apiToken);
5961
6360
  spinner.start('Fetching list of repositories...');
5962
- const result = await handleApiCall(socketSdk.getOrgRepoList(orgSlug, {
6361
+ const result = await handleApiCall(sockSdk.getOrgRepoList(orgSlug, {
5963
6362
  sort,
5964
6363
  direction,
5965
6364
  per_page: String(per_page),
@@ -6146,8 +6545,8 @@ async function fetchUpdateRepoWithToken(apiToken, {
6146
6545
  spinner
6147
6546
  } = constants;
6148
6547
  spinner.start('Sending request to update a repository...');
6149
- const socketSdk = await shadowNpmInject.setupSdk(apiToken);
6150
- const result = await handleApiCall(socketSdk.updateOrgRepo(orgSlug, repoName, {
6548
+ const sockSdk = await shadowNpmInject.setupSdk(apiToken);
6549
+ const result = await handleApiCall(sockSdk.updateOrgRepo(orgSlug, repoName, {
6151
6550
  orgSlug,
6152
6551
  name: repoName,
6153
6552
  description,
@@ -6294,9 +6693,9 @@ async function fetchViewRepoWithToken(orgSlug, repoName, apiToken) {
6294
6693
  const {
6295
6694
  spinner
6296
6695
  } = constants;
6297
- const socketSdk = await shadowNpmInject.setupSdk(apiToken);
6696
+ const sockSdk = await shadowNpmInject.setupSdk(apiToken);
6298
6697
  spinner.start('Fetching repository data...');
6299
- const result = await handleApiCall(socketSdk.getOrgRepo(orgSlug, repoName), 'fetching repository');
6698
+ const result = await handleApiCall(sockSdk.getOrgRepo(orgSlug, repoName), 'fetching repository');
6300
6699
  spinner.successAndStop('Received response while fetched repository data.');
6301
6700
  if (!result.success) {
6302
6701
  handleUnsuccessfulApiResponse('getOrgRepo', result);
@@ -6450,8 +6849,106 @@ const cmdRepos = {
6450
6849
  }
6451
6850
  };
6452
6851
 
6453
- async function suggestOrgSlug(socketSdk) {
6454
- const result = await handleApiCall(socketSdk.getOrganizations(), 'looking up organizations');
6852
+ async function fetchCreateOrgFullScan(packagePaths, orgSlug, repoName, branchName, commitMessage, defaultBranch, pendingHead, tmp, cwd) {
6853
+ const sockSdk = await shadowNpmInject.setupSdk();
6854
+
6855
+ // Lazily access constants.spinner.
6856
+ const {
6857
+ spinner
6858
+ } = constants;
6859
+ spinner.start(`Creating a scan with ${packagePaths.length} packages...`);
6860
+ const result = await handleApiCall(sockSdk.createOrgFullScan(orgSlug, {
6861
+ repo: repoName,
6862
+ branch: branchName,
6863
+ commit_message: commitMessage,
6864
+ make_default_branch: String(defaultBranch),
6865
+ set_as_pending_head: String(pendingHead),
6866
+ tmp: String(tmp)
6867
+ }, packagePaths, cwd), 'Creating scan');
6868
+ spinner.successAndStop('Scan created successfully');
6869
+ if (!result.success) {
6870
+ handleUnsuccessfulApiResponse('CreateOrgFullScan', result);
6871
+ return;
6872
+ }
6873
+ return result.data;
6874
+ }
6875
+
6876
+ async function fetchSupportedScanFileNames() {
6877
+ const sockSdk = await shadowNpmInject.setupSdk();
6878
+
6879
+ // Lazily access constants.spinner.
6880
+ const {
6881
+ spinner
6882
+ } = constants;
6883
+ spinner.start('Requesting supported scan file types from API...');
6884
+ const result = await handleApiCall(sockSdk.getReportSupportedFiles(), 'fetching supported scan file types');
6885
+ spinner.successAndStop('Received response while fetched supported scan file types.');
6886
+ if (!result.success) {
6887
+ handleUnsuccessfulApiResponse('getReportSupportedFiles', result);
6888
+ return;
6889
+ }
6890
+ return result.data;
6891
+ }
6892
+
6893
+ async function outputCreateNewScan(data) {
6894
+ const link = colors.underline(colors.cyan(`${data.html_report_url}`));
6895
+ logger.logger.log(`Available at: ${link}`);
6896
+ const rl = readline.createInterface({
6897
+ input: process$1.stdin,
6898
+ output: process$1.stdout
6899
+ });
6900
+ const answer = await rl.question('Would you like to open it in your browser? (y/n)');
6901
+ if (answer.toLowerCase() === 'y') {
6902
+ await vendor.open(`${data.html_report_url}`);
6903
+ }
6904
+ rl.close();
6905
+ }
6906
+
6907
+ async function handleCreateNewScan({
6908
+ branchName,
6909
+ commitMessage,
6910
+ cwd,
6911
+ defaultBranch,
6912
+ orgSlug,
6913
+ pendingHead,
6914
+ readOnly,
6915
+ repoName,
6916
+ targets,
6917
+ tmp
6918
+ }) {
6919
+ const apiToken = shadowNpmInject.getDefaultToken();
6920
+
6921
+ // Note: you need an apiToken to request supportedScanFileNames from the API
6922
+ if (!apiToken) {
6923
+ throw new shadowNpmInject.AuthError('User must be authenticated to create and submit new scans. To log in, run the command `socket login` and enter your API key.');
6924
+ }
6925
+ const supportedFileNames = await fetchSupportedScanFileNames();
6926
+ if (!supportedFileNames) return;
6927
+ const packagePaths = await shadowNpmPaths.getPackageFilesForScan(cwd, targets, supportedFileNames
6928
+ // socketConfig
6929
+ );
6930
+ if (!packagePaths.length) {
6931
+ // Use exit status of 2 to indicate incorrect usage, generally invalid
6932
+ // options or missing arguments.
6933
+ // https://www.gnu.org/software/bash/manual/html_node/Exit-Status.html
6934
+ process$1.exitCode = 2;
6935
+ logger.logger.fail(commonTags.stripIndents`
6936
+ ${colors.bgRed(colors.white('Input error'))}: The TARGET did not contain any matching / supported files for a scan
6937
+ `);
6938
+ return;
6939
+ }
6940
+ if (readOnly) {
6941
+ logger.logger.log('[ReadOnly] Bailing now');
6942
+ return;
6943
+ }
6944
+ const data = await fetchCreateOrgFullScan(packagePaths, orgSlug, repoName, branchName, commitMessage, defaultBranch, pendingHead, tmp, cwd);
6945
+ if (!data) return;
6946
+ await outputCreateNewScan(data);
6947
+ }
6948
+
6949
+ async function suggestOrgSlug() {
6950
+ const sockSdk = await shadowNpmInject.setupSdk();
6951
+ const result = await handleApiCall(sockSdk.getOrganizations(), 'looking up organizations');
6455
6952
  // Ignore a failed request here. It was not the primary goal of
6456
6953
  // running this command and reporting it only leads to end-user confusion.
6457
6954
  if (result.success) {
@@ -6472,13 +6969,17 @@ async function suggestOrgSlug(socketSdk) {
6472
6969
  if (proceed) {
6473
6970
  return proceed;
6474
6971
  }
6972
+ } else {
6973
+ logger.logger.fail('Failed to lookup organization list from API, unable to suggest.');
6475
6974
  }
6476
6975
  }
6477
6976
 
6478
- async function suggestRepoSlug(socketSdk, orgSlug) {
6977
+ async function suggestRepoSlug(orgSlug) {
6978
+ const sockSdk = await shadowNpmInject.setupSdk();
6979
+
6479
6980
  // Same as above, but if there's a repo with the same name as cwd then
6480
6981
  // default the selection to that name.
6481
- const result = await handleApiCall(socketSdk.getOrgRepoList(orgSlug, {
6982
+ const result = await handleApiCall(sockSdk.getOrgRepoList(orgSlug, {
6482
6983
  orgSlug,
6483
6984
  sort: 'name',
6484
6985
  direction: 'asc',
@@ -6488,6 +6989,7 @@ async function suggestRepoSlug(socketSdk, orgSlug) {
6488
6989
  perPage: '10',
6489
6990
  page: '0'
6490
6991
  }), 'looking up known repos');
6992
+
6491
6993
  // Ignore a failed request here. It was not the primary goal of
6492
6994
  // running this command and reporting it only leads to end-user confusion.
6493
6995
  if (result.success) {
@@ -6495,7 +6997,7 @@ async function suggestRepoSlug(socketSdk, orgSlug) {
6495
6997
  let cwdIsKnown = !!currentDirName && result.data.results.some(obj => obj.slug === currentDirName);
6496
6998
  if (!cwdIsKnown && currentDirName) {
6497
6999
  // Do an explicit request so we can assert that the cwd exists or not
6498
- const result = await handleApiCall(socketSdk.getOrgRepo(orgSlug, currentDirName), 'checking if current cwd is a known repo');
7000
+ const result = await handleApiCall(sockSdk.getOrgRepo(orgSlug, currentDirName), 'checking if current cwd is a known repo');
6499
7001
  if (result.success) {
6500
7002
  cwdIsKnown = true;
6501
7003
  }
@@ -6534,203 +7036,64 @@ async function suggestRepoSlug(socketSdk, orgSlug) {
6534
7036
  }
6535
7037
  });
6536
7038
  return {
6537
- slug: repoName,
6538
- defaultBranch: repoDefaultBranch
6539
- };
6540
- }
6541
- }
6542
- }
6543
- function dirNameToSlug(name) {
6544
- // Uses slug specs asserted by our servers
6545
- // Note: this can lead to collisions; eg. slug for `x--y` and `x---y` is `x-y`
6546
- return name.toLowerCase().replace(/[^[a-zA-Z0-9_.-]/g, '_').replace(/--+/g, '-').replace(/__+/g, '_').replace(/\.\.+/g, '.').replace(/[._-]+$/, '');
6547
- }
6548
-
6549
- async function suggestBranchSlug(repoDefaultBranch) {
6550
- const spawnResult = spawn.spawnSync('git', ['branch', '--show-current']);
6551
- const currentBranch = spawnResult.stdout.toString('utf8').trim();
6552
- if (currentBranch && spawnResult.status === 0) {
6553
- const proceed = await prompts.select({
6554
- message: 'Use the current git branch as target branch name?',
6555
- choices: [{
6556
- name: `Yes [${currentBranch}]`,
6557
- value: currentBranch,
6558
- description: 'Use the current git branch for branch name'
6559
- }, ...(repoDefaultBranch && repoDefaultBranch !== currentBranch ? [{
6560
- name: `No, use the default branch [${repoDefaultBranch}]`,
6561
- value: repoDefaultBranch,
6562
- description: 'Use the default branch for target repo as the target branch name'
6563
- }] : []), {
6564
- name: 'No',
6565
- value: '',
6566
- description: 'Do not use the current git branch as name (will end in a no-op)'
6567
- }].filter(Boolean)
6568
- });
6569
- if (proceed) {
6570
- return proceed;
6571
- }
6572
- }
6573
- }
6574
-
6575
- async function suggestTarget() {
6576
- // We could prefill this with sub-dirs of the current
6577
- // dir ... but is that going to be useful?
6578
- const proceed = await prompts.select({
6579
- message: 'No TARGET given. Do you want to use the current directory?',
6580
- choices: [{
6581
- name: 'Yes',
6582
- value: true,
6583
- description: 'Target the current directory'
6584
- }, {
6585
- name: 'No',
6586
- value: false,
6587
- description: 'Do not use the current directory (this will end in a no-op)'
6588
- }]
6589
- });
6590
- if (proceed) {
6591
- return ['.'];
6592
- }
6593
- }
6594
-
6595
- async function createFullScan({
6596
- branchName,
6597
- commitHash: _commitHash,
6598
- commitMessage,
6599
- committers: _committers,
6600
- cwd,
6601
- defaultBranch,
6602
- orgSlug,
6603
- pendingHead,
6604
- pullRequest: _pullRequest,
6605
- readOnly,
6606
- repoName,
6607
- targets,
6608
- tmp
6609
- }) {
6610
- // Lazily access constants.spinner.
6611
- const {
6612
- spinner
6613
- } = constants;
6614
- const socketSdk = await shadowNpmInject.setupSdk();
6615
- const supportedFiles = await socketSdk.getReportSupportedFiles().then(res => {
6616
- if (!res.success) {
6617
- handleUnsuccessfulApiResponse('getReportSupportedFiles', res);
6618
- assert(false, 'handleUnsuccessfulApiResponse should unconditionally throw');
6619
- }
6620
- return res.data;
6621
- }).catch(cause => {
6622
- throw new Error('Failed getting supported files for report', {
6623
- cause
6624
- });
6625
- });
6626
-
6627
- // If we updated any inputs then we should print the command line to repeat
6628
- // the command without requiring user input, as a suggestion.
6629
- let updatedInput = false;
6630
- if (!targets.length) {
6631
- const received = await suggestTarget();
6632
- targets = received ?? [];
6633
- updatedInput = true;
6634
- }
6635
-
6636
- // // TODO: we'll probably use socket.json or something else soon...
6637
- // const absoluteConfigPath = path.join(cwd, 'socket.yml')
6638
- // const socketConfig = await getSocketConfig(absoluteConfigPath)
6639
-
6640
- const packagePaths = await shadowNpmPaths.getPackageFilesFullScans(cwd, targets, supportedFiles
6641
- // socketConfig
6642
- );
6643
-
6644
- // We're going to need an api token to suggest data because those suggestions
6645
- // must come from data we already know. Don't error on missing api token yet.
6646
- // If the api-token is not set, ignore it for the sake of suggestions.
6647
- const apiToken = shadowNpmInject.getDefaultToken();
6648
-
6649
- // If the current cwd is unknown and is used as a repo slug anyways, we will
6650
- // first need to register the slug before we can use it.
6651
- let repoDefaultBranch = '';
6652
- if (apiToken) {
6653
- if (!orgSlug) {
6654
- const suggestion = await suggestOrgSlug(socketSdk);
6655
- if (suggestion) orgSlug = suggestion;
6656
- updatedInput = true;
6657
- }
6658
-
6659
- // (Don't bother asking for the rest if we didn't get an org slug above)
6660
- if (orgSlug && !repoName) {
6661
- const suggestion = await suggestRepoSlug(socketSdk, orgSlug);
6662
- if (suggestion) {
6663
- repoDefaultBranch = suggestion.defaultBranch;
6664
- repoName = suggestion.slug;
6665
- }
6666
- updatedInput = true;
6667
- }
6668
-
6669
- // (Don't bother asking for the rest if we didn't get an org/repo above)
6670
- if (orgSlug && repoName && !branchName) {
6671
- const suggestion = await suggestBranchSlug(repoDefaultBranch);
6672
- if (suggestion) branchName = suggestion;
6673
- updatedInput = true;
7039
+ slug: repoName,
7040
+ defaultBranch: repoDefaultBranch
7041
+ };
6674
7042
  }
7043
+ } else {
7044
+ logger.logger.fail('Failed to lookup repo list from API, unable to suggest.');
6675
7045
  }
6676
- if (!orgSlug || !repoName || !branchName || !packagePaths.length) {
6677
- // Use exit status of 2 to indicate incorrect usage, generally invalid
6678
- // options or missing arguments.
6679
- // https://www.gnu.org/software/bash/manual/html_node/Exit-Status.html
6680
- process$1.exitCode = 2;
6681
- logger.logger.fail(commonTags.stripIndents`
6682
- ${colors.bgRed(colors.white('Input error'))}: Please provide the required fields:
6683
-
6684
- - Org name as the first argument ${!orgSlug ? colors.red('(missing!)') : colors.green('(ok)')}
6685
-
6686
- - Repository name using --repo ${!repoName ? colors.red('(missing!)') : colors.green('(ok)')}
6687
-
6688
- - Branch name using --branch ${!branchName ? colors.red('(missing!)') : colors.green('(ok)')}
6689
-
6690
- - At least one TARGET (e.g. \`.\` or \`./package.json\`) ${!packagePaths.length ? colors.red(targets.length > 0 ? '(TARGET' + (targets.length ? 's' : '') + ' contained no matching/supported files!)' : '(missing)') : colors.green('(ok)')}
7046
+ }
7047
+ function dirNameToSlug(name) {
7048
+ // Uses slug specs asserted by our servers
7049
+ // Note: this can lead to collisions; eg. slug for `x--y` and `x---y` is `x-y`
7050
+ return name.toLowerCase().replace(/[^[a-zA-Z0-9_.-]/g, '_').replace(/--+/g, '-').replace(/__+/g, '_').replace(/\.\.+/g, '.').replace(/[._-]+$/, '');
7051
+ }
6691
7052
 
6692
- ${!apiToken ? 'Note: was unable to make suggestions because no API Token was found; this would make command fail regardless' : ''}
6693
- `);
6694
- return;
6695
- }
6696
- if (updatedInput) {
6697
- logger.logger.log('Note: You can invoke this command next time to skip the interactive questions:');
6698
- logger.logger.log('```');
6699
- logger.logger.log(` socket scan create [other flags...] --repo ${repoName} --branch ${branchName} ${orgSlug} ${targets.join(' ')}`);
6700
- logger.logger.log('```');
6701
- }
6702
- if (!apiToken) {
6703
- throw new shadowNpmInject.AuthError('User must be authenticated to run this command. To log in, run the command `socket login` and enter your API key.');
6704
- }
6705
- if (readOnly) {
6706
- logger.logger.log('[ReadOnly] Bailing now');
6707
- return;
6708
- }
6709
- spinner.start(`Creating a scan with ${packagePaths.length} packages...`);
6710
- const result = await handleApiCall(socketSdk.createOrgFullScan(orgSlug, {
6711
- repo: repoName,
6712
- branch: branchName,
6713
- commit_message: commitMessage,
6714
- make_default_branch: String(defaultBranch),
6715
- set_as_pending_head: String(pendingHead),
6716
- tmp: String(tmp)
6717
- }, packagePaths, cwd), 'Creating scan');
6718
- if (!result.success) {
6719
- handleUnsuccessfulApiResponse('CreateOrgFullScan', result);
6720
- return;
7053
+ async function suggestBranchSlug(repoDefaultBranch) {
7054
+ const spawnResult = spawn.spawnSync('git', ['branch', '--show-current']);
7055
+ const currentBranch = spawnResult.stdout.toString('utf8').trim();
7056
+ if (currentBranch && spawnResult.status === 0) {
7057
+ const proceed = await prompts.select({
7058
+ message: 'Use the current git branch as target branch name?',
7059
+ choices: [{
7060
+ name: `Yes [${currentBranch}]`,
7061
+ value: currentBranch,
7062
+ description: 'Use the current git branch for branch name'
7063
+ }, ...(repoDefaultBranch && repoDefaultBranch !== currentBranch ? [{
7064
+ name: `No, use the default branch [${repoDefaultBranch}]`,
7065
+ value: repoDefaultBranch,
7066
+ description: 'Use the default branch for target repo as the target branch name'
7067
+ }] : []), {
7068
+ name: 'No',
7069
+ value: '',
7070
+ description: 'Do not use the current git branch as name (will end in a no-op)'
7071
+ }].filter(Boolean)
7072
+ });
7073
+ if (proceed) {
7074
+ return proceed;
7075
+ }
6721
7076
  }
6722
- spinner.successAndStop('Scan created successfully');
6723
- const link = colors.underline(colors.cyan(`${result.data.html_report_url}`));
6724
- logger.logger.log(`Available at: ${link}`);
6725
- const rl = readline.createInterface({
6726
- input: process$1.stdin,
6727
- output: process$1.stdout
7077
+ }
7078
+
7079
+ async function suggestTarget() {
7080
+ // We could prefill this with sub-dirs of the current
7081
+ // dir ... but is that going to be useful?
7082
+ const proceed = await prompts.select({
7083
+ message: 'No TARGET given. Do you want to use the current directory?',
7084
+ choices: [{
7085
+ name: 'Yes',
7086
+ value: true,
7087
+ description: 'Target the current directory'
7088
+ }, {
7089
+ name: 'No',
7090
+ value: false,
7091
+ description: 'Do not use the current directory (this will end in a no-op)'
7092
+ }]
6728
7093
  });
6729
- const answer = await rl.question('Would you like to open it in your browser? (y/n)');
6730
- if (answer.toLowerCase() === 'y') {
6731
- await vendor.open(`${result.data.html_report_url}`);
7094
+ if (proceed) {
7095
+ return ['.'];
6732
7096
  }
6733
- rl.close();
6734
7097
  }
6735
7098
 
6736
7099
  const {
@@ -6854,18 +7217,66 @@ async function run$7(argv, importMeta, {
6854
7217
  importMeta,
6855
7218
  parentName
6856
7219
  });
6857
- const [orgSlug = '', ...targets] = cli.input;
6858
- const cwd = cli.flags['cwd'] && cli.flags['cwd'] !== 'process.cwd()' ? String(cli.flags['cwd']) : process$1.cwd();
6859
7220
  const {
7221
+ cwd: cwdOverride,
7222
+ dryRun
7223
+ } = cli.flags;
7224
+ const cwd = cwdOverride && cwdOverride !== 'process.cwd()' ? String(cwdOverride) : process$1.cwd();
7225
+ let {
6860
7226
  branch: branchName,
6861
7227
  repo: repoName
6862
7228
  } = cli.flags;
6863
- const apiToken = shadowNpmInject.getDefaultToken(); // This checks if we _can_ suggest anything
7229
+ let [orgSlug = '', ...targets] = cli.input;
6864
7230
 
6865
- if (!apiToken && (!orgSlug || !repoName || !branchName || !targets.length)) {
6866
- // Without api token we cannot recover because we can't request more info
6867
- // from the server, to match and help with the current cwd/git status.
6868
- //
7231
+ // We're going to need an api token to suggest data because those suggestions
7232
+ // must come from data we already know. Don't error on missing api token yet.
7233
+ // If the api-token is not set, ignore it for the sake of suggestions.
7234
+ const apiToken = shadowNpmInject.getDefaultToken();
7235
+
7236
+ // If we updated any inputs then we should print the command line to repeat
7237
+ // the command without requiring user input, as a suggestion.
7238
+ let updatedInput = false;
7239
+ if (!targets.length && !dryRun) {
7240
+ const received = await suggestTarget();
7241
+ targets = received ?? [];
7242
+ updatedInput = true;
7243
+ }
7244
+
7245
+ // If the current cwd is unknown and is used as a repo slug anyways, we will
7246
+ // first need to register the slug before we can use it.
7247
+ let repoDefaultBranch = '';
7248
+ // Only do suggestions with an apiToken and when not in dryRun mode
7249
+ if (apiToken && !dryRun) {
7250
+ if (!orgSlug) {
7251
+ const suggestion = await suggestOrgSlug();
7252
+ if (suggestion) orgSlug = suggestion;
7253
+ updatedInput = true;
7254
+ }
7255
+
7256
+ // (Don't bother asking for the rest if we didn't get an org slug above)
7257
+ if (orgSlug && !repoName) {
7258
+ const suggestion = await suggestRepoSlug(orgSlug);
7259
+ if (suggestion) {
7260
+ repoDefaultBranch = suggestion.defaultBranch;
7261
+ repoName = suggestion.slug;
7262
+ }
7263
+ updatedInput = true;
7264
+ }
7265
+
7266
+ // (Don't bother asking for the rest if we didn't get an org/repo above)
7267
+ if (orgSlug && repoName && !branchName) {
7268
+ const suggestion = await suggestBranchSlug(repoDefaultBranch);
7269
+ if (suggestion) branchName = suggestion;
7270
+ updatedInput = true;
7271
+ }
7272
+ }
7273
+ if (updatedInput && repoName && branchName && orgSlug && targets?.length) {
7274
+ logger.logger.error('Note: You can invoke this command next time to skip the interactive questions:');
7275
+ logger.logger.error('```');
7276
+ logger.logger.error(` socket scan create [other flags...] --repo ${repoName} --branch ${branchName} ${orgSlug} ${targets.join(' ')}`);
7277
+ logger.logger.error('```\n');
7278
+ }
7279
+ if (!orgSlug || !repoName || !branchName || !targets.length) {
6869
7280
  // Use exit status of 2 to indicate incorrect usage, generally invalid
6870
7281
  // options or missing arguments.
6871
7282
  // https://www.gnu.org/software/bash/manual/html_node/Exit-Status.html
@@ -6879,28 +7290,25 @@ async function run$7(argv, importMeta, {
6879
7290
 
6880
7291
  - Branch name using --branch ${!branchName ? colors.red('(missing!)') : colors.green('(ok)')}
6881
7292
 
6882
- - At least one TARGET (e.g. \`.\` or \`./package.json\`) ${!targets.length ? '(missing)' : colors.green('(ok)')}
7293
+ - At least one TARGET (e.g. \`.\` or \`./package.json\`) ${!targets.length ? colors.red('(missing)') : colors.green('(ok)')}
6883
7294
 
6884
- (Additionally, no API Token was set so we cannot auto-discover these details)
7295
+ ${!apiToken ? 'Note: was unable to make suggestions because no API Token was found; this would make the command fail regardless' : ''}
6885
7296
  `);
6886
7297
  return;
6887
7298
  }
6888
7299
 
6889
7300
  // Note exiting earlier to skirt a hidden auth requirement
6890
- if (cli.flags['dryRun']) {
7301
+ if (dryRun) {
6891
7302
  logger.logger.log(DRY_RUN_BAIL_TEXT$7);
6892
7303
  return;
6893
7304
  }
6894
- await createFullScan({
7305
+ await handleCreateNewScan({
6895
7306
  branchName: branchName,
6896
- commitHash: cli.flags['commitHash'] ?? '',
6897
7307
  commitMessage: cli.flags['commitMessage'] ?? '',
6898
- committers: cli.flags['committers'] ?? '',
6899
7308
  cwd,
6900
7309
  defaultBranch: Boolean(cli.flags['defaultBranch']),
6901
7310
  orgSlug,
6902
7311
  pendingHead: Boolean(cli.flags['pendingHead']),
6903
- pullRequest: cli.flags['pullRequest'] ?? undefined,
6904
7312
  readOnly: Boolean(cli.flags['readOnly']),
6905
7313
  repoName: repoName,
6906
7314
  targets,
@@ -6908,26 +7316,37 @@ async function run$7(argv, importMeta, {
6908
7316
  });
6909
7317
  }
6910
7318
 
6911
- async function deleteOrgFullScan(orgSlug, fullScanId) {
7319
+ async function fetchDeleteOrgFullScan(orgSlug, scanId) {
6912
7320
  const apiToken = shadowNpmInject.getDefaultToken();
6913
7321
  if (!apiToken) {
6914
7322
  throw new shadowNpmInject.AuthError('User must be authenticated to run this command. To log in, run the command `socket login` and enter your API key.');
6915
7323
  }
6916
- await deleteOrgFullScanWithToken(orgSlug, fullScanId, apiToken);
7324
+ await fetchDeleteOrgFullScanWithToken(apiToken, orgSlug, scanId);
6917
7325
  }
6918
- async function deleteOrgFullScanWithToken(orgSlug, fullScanId, apiToken) {
7326
+ async function fetchDeleteOrgFullScanWithToken(apiToken, orgSlug, scanId) {
6919
7327
  // Lazily access constants.spinner.
6920
7328
  const {
6921
7329
  spinner
6922
7330
  } = constants;
6923
- spinner.start('Deleting scan...');
6924
- const socketSdk = await shadowNpmInject.setupSdk(apiToken);
6925
- const result = await handleApiCall(socketSdk.deleteOrgFullScan(orgSlug, fullScanId), 'Deleting scan');
7331
+ const sockSdk = await shadowNpmInject.setupSdk(apiToken);
7332
+ spinner.start('Requesting the scan to be deleted...');
7333
+ const result = await handleApiCall(sockSdk.deleteOrgFullScan(orgSlug, scanId), 'Deleting scan');
7334
+ spinner.successAndStop('Received response for deleting a scan.');
6926
7335
  if (!result.success) {
6927
7336
  handleUnsuccessfulApiResponse('deleteOrgFullScan', result);
6928
7337
  return;
6929
7338
  }
6930
- spinner.successAndStop('Scan deleted successfully');
7339
+ return result.data;
7340
+ }
7341
+
7342
+ async function outputDeleteScan(_data) {
7343
+ logger.logger.success('Scan deleted successfully');
7344
+ }
7345
+
7346
+ async function handleDeleteScan(orgSlug, scanId) {
7347
+ const data = await fetchDeleteOrgFullScan(orgSlug, scanId);
7348
+ if (!data) return;
7349
+ await outputDeleteScan();
6931
7350
  }
6932
7351
 
6933
7352
  const {
@@ -6966,8 +7385,8 @@ async function run$6(argv, importMeta, {
6966
7385
  importMeta,
6967
7386
  parentName
6968
7387
  });
6969
- const [orgSlug = '', fullScanId = ''] = cli.input;
6970
- if (!orgSlug || !fullScanId) {
7388
+ const [orgSlug = '', scanId = ''] = cli.input;
7389
+ if (!orgSlug || !scanId) {
6971
7390
  // Use exit status of 2 to indicate incorrect usage, generally invalid
6972
7391
  // options or missing arguments.
6973
7392
  // https://www.gnu.org/software/bash/manual/html_node/Exit-Status.html
@@ -6976,22 +7395,20 @@ async function run$6(argv, importMeta, {
6976
7395
 
6977
7396
  - Org name as the first argument ${!orgSlug ? colors.red('(missing!)') : colors.green('(ok)')}
6978
7397
 
6979
- - Full Scan ID to delete as second argument ${!fullScanId ? colors.red('(missing!)') : colors.green('(ok)')}`);
7398
+ - Full Scan ID to delete as second argument ${!scanId ? colors.red('(missing!)') : colors.green('(ok)')}`);
6980
7399
  return;
6981
7400
  }
6982
7401
  if (cli.flags['dryRun']) {
6983
7402
  logger.logger.log(DRY_RUN_BAIL_TEXT$6);
6984
7403
  return;
6985
7404
  }
6986
- await deleteOrgFullScan(orgSlug, fullScanId);
7405
+ await handleDeleteScan(orgSlug, scanId);
6987
7406
  }
6988
7407
 
6989
- // @ts-ignore
6990
- async function listFullScans({
7408
+ async function fetchListScans({
6991
7409
  direction,
6992
7410
  from_time,
6993
7411
  orgSlug,
6994
- outputKind,
6995
7412
  page,
6996
7413
  per_page,
6997
7414
  sort
@@ -7000,23 +7417,19 @@ async function listFullScans({
7000
7417
  if (!apiToken) {
7001
7418
  throw new shadowNpmInject.AuthError('User must be authenticated to run this command. To log in, run the command `socket login` and enter your API key.');
7002
7419
  }
7003
- await listFullScansWithToken({
7004
- apiToken,
7420
+ await fetchListScansWithToken(apiToken, {
7005
7421
  direction,
7006
7422
  from_time,
7007
7423
  orgSlug,
7008
- outputKind,
7009
7424
  page,
7010
7425
  per_page,
7011
7426
  sort
7012
7427
  });
7013
7428
  }
7014
- async function listFullScansWithToken({
7015
- apiToken,
7429
+ async function fetchListScansWithToken(apiToken, {
7016
7430
  direction,
7017
7431
  from_time,
7018
7432
  orgSlug,
7019
- outputKind,
7020
7433
  page,
7021
7434
  per_page,
7022
7435
  sort
@@ -7025,22 +7438,27 @@ async function listFullScansWithToken({
7025
7438
  const {
7026
7439
  spinner
7027
7440
  } = constants;
7441
+ const sockSdk = await shadowNpmInject.setupSdk(apiToken);
7028
7442
  spinner.start('Fetching list of scans...');
7029
- const socketSdk = await shadowNpmInject.setupSdk(apiToken);
7030
- const result = await handleApiCall(socketSdk.getOrgFullScanList(orgSlug, {
7443
+ const result = await handleApiCall(sockSdk.getOrgFullScanList(orgSlug, {
7031
7444
  sort,
7032
7445
  direction,
7033
7446
  per_page: String(per_page),
7034
7447
  page: String(page),
7035
7448
  from: from_time
7036
7449
  }), 'Listing scans');
7450
+ spinner.successAndStop(`Received response for list of scans.`);
7037
7451
  if (!result.success) {
7038
7452
  handleUnsuccessfulApiResponse('getOrgFullScanList', result);
7039
7453
  return;
7040
7454
  }
7041
- spinner.stop(`Fetch complete`);
7455
+ return result.data;
7456
+ }
7457
+
7458
+ // @ts-ignore
7459
+ async function outputListScans(data, outputKind) {
7042
7460
  if (outputKind === 'json') {
7043
- logger.logger.log(result.data);
7461
+ logger.logger.log(data);
7044
7462
  return;
7045
7463
  }
7046
7464
  const options = {
@@ -7058,7 +7476,7 @@ async function listFullScansWithToken({
7058
7476
  name: colors.magenta('Created at')
7059
7477
  }]
7060
7478
  };
7061
- const formattedResults = result.data.results.map(d => {
7479
+ const formattedResults = data.results.map(d => {
7062
7480
  return {
7063
7481
  id: d.id,
7064
7482
  report_url: colors.underline(`${d.html_report_url}`),
@@ -7073,6 +7491,27 @@ async function listFullScansWithToken({
7073
7491
  logger.logger.log(chalkTable(options, formattedResults));
7074
7492
  }
7075
7493
 
7494
+ async function handleListScans({
7495
+ direction,
7496
+ from_time,
7497
+ orgSlug,
7498
+ outputKind,
7499
+ page,
7500
+ per_page,
7501
+ sort
7502
+ }) {
7503
+ const data = await fetchListScans({
7504
+ direction,
7505
+ from_time,
7506
+ orgSlug,
7507
+ page,
7508
+ per_page,
7509
+ sort
7510
+ });
7511
+ if (!data) return;
7512
+ await outputListScans(data, outputKind);
7513
+ }
7514
+
7076
7515
  const {
7077
7516
  DRY_RUN_BAIL_TEXT: DRY_RUN_BAIL_TEXT$5
7078
7517
  } = constants;
@@ -7160,7 +7599,7 @@ async function run$5(argv, importMeta, {
7160
7599
  logger.logger.log(DRY_RUN_BAIL_TEXT$5);
7161
7600
  return;
7162
7601
  }
7163
- await listFullScans({
7602
+ await handleListScans({
7164
7603
  direction: String(cli.flags['direction'] || ''),
7165
7604
  from_time: String(cli.flags['fromTime'] || ''),
7166
7605
  orgSlug,
@@ -7171,46 +7610,56 @@ async function run$5(argv, importMeta, {
7171
7610
  });
7172
7611
  }
7173
7612
 
7174
- async function getOrgScanMetadata(orgSlug, scanId, outputKind) {
7613
+ async function fetchScanMetadata(orgSlug, scanId) {
7175
7614
  const apiToken = shadowNpmInject.getDefaultToken();
7176
7615
  if (!apiToken) {
7177
7616
  throw new shadowNpmInject.AuthError('User must be authenticated to run this command. To log in, run the command `socket login` and enter your API key.');
7178
7617
  }
7179
- await getOrgScanMetadataWithToken(orgSlug, scanId, apiToken, outputKind);
7618
+ await fetchScanMetadataWithToken(apiToken, orgSlug, scanId);
7180
7619
  }
7181
- async function getOrgScanMetadataWithToken(orgSlug, scanId, apiToken, outputKind) {
7620
+ async function fetchScanMetadataWithToken(apiToken, orgSlug, scanId) {
7182
7621
  // Lazily access constants.spinner.
7183
7622
  const {
7184
7623
  spinner
7185
7624
  } = constants;
7625
+ const sockSdk = await shadowNpmInject.setupSdk(apiToken);
7186
7626
  spinner.start('Fetching meta data for a full scan...');
7187
- const socketSdk = await shadowNpmInject.setupSdk(apiToken);
7188
- const result = await handleApiCall(socketSdk.getOrgFullScanMetadata(orgSlug, scanId), 'Listing scans');
7627
+ const result = await handleApiCall(sockSdk.getOrgFullScanMetadata(orgSlug, scanId), 'Listing scans');
7628
+ spinner.successAndStop('Received response for scan meta data.');
7189
7629
  if (!result.success) {
7190
7630
  handleUnsuccessfulApiResponse('getOrgFullScanMetadata', result);
7191
7631
  return;
7192
7632
  }
7193
- spinner?.successAndStop('Fetched the meta data\n');
7633
+ return result.data;
7634
+ }
7635
+
7636
+ async function outputScanMetadata(data, scanId, outputKind) {
7194
7637
  if (outputKind === 'json') {
7195
- logger.logger.log(result.data);
7638
+ logger.logger.log(data);
7196
7639
  } else {
7197
7640
  // Markdown = print
7198
7641
  if (outputKind === 'markdown') {
7199
7642
  logger.logger.log('# Scan meta data\n');
7200
7643
  }
7201
7644
  logger.logger.log(`Scan ID: ${scanId}\n`);
7202
- for (const [key, value] of Object.entries(result.data)) {
7645
+ for (const [key, value] of Object.entries(data)) {
7203
7646
  if (['id', 'updated_at', 'organization_id', 'repository_id', 'commit_hash', 'html_report_url'].includes(key)) continue;
7204
7647
  logger.logger.log(`- ${key}:`, value);
7205
7648
  }
7206
7649
  if (outputKind === 'markdown') {
7207
- logger.logger.log(`\nYou can view this report at: [${result.data.html_report_url}](${result.data.html_report_url})\n`);
7650
+ logger.logger.log(`\nYou can view this report at: [${data.html_report_url}](${data.html_report_url})\n`);
7208
7651
  } else {
7209
- logger.logger.log(`\nYou can view this report at: ${result.data.html_report_url}]\n`);
7652
+ logger.logger.log(`\nYou can view this report at: ${data.html_report_url}]\n`);
7210
7653
  }
7211
7654
  }
7212
7655
  }
7213
7656
 
7657
+ async function handleOrgScanMetadata(orgSlug, scanId, outputKind) {
7658
+ const data = await fetchScanMetadata(orgSlug, scanId);
7659
+ if (!data) return;
7660
+ await outputScanMetadata(data, scanId, outputKind);
7661
+ }
7662
+
7214
7663
  const {
7215
7664
  DRY_RUN_BAIL_TEXT: DRY_RUN_BAIL_TEXT$4
7216
7665
  } = constants;
@@ -7247,8 +7696,8 @@ async function run$4(argv, importMeta, {
7247
7696
  importMeta,
7248
7697
  parentName
7249
7698
  });
7250
- const [orgSlug = '', fullScanId = ''] = cli.input;
7251
- if (!orgSlug || !fullScanId) {
7699
+ const [orgSlug = '', scanId = ''] = cli.input;
7700
+ if (!orgSlug || !scanId) {
7252
7701
  // Use exit status of 2 to indicate incorrect usage, generally invalid
7253
7702
  // options or missing arguments.
7254
7703
  // https://www.gnu.org/software/bash/manual/html_node/Exit-Status.html
@@ -7257,14 +7706,14 @@ async function run$4(argv, importMeta, {
7257
7706
 
7258
7707
  - Org name as the first argument ${!orgSlug ? colors.red('(missing!)') : colors.green('(ok)')}
7259
7708
 
7260
- - Full Scan ID to inspect as second argument ${!fullScanId ? colors.red('(missing!)') : colors.green('(ok)')}`);
7709
+ - Full Scan ID to inspect as second argument ${!scanId ? colors.red('(missing!)') : colors.green('(ok)')}`);
7261
7710
  return;
7262
7711
  }
7263
7712
  if (cli.flags['dryRun']) {
7264
7713
  logger.logger.log(DRY_RUN_BAIL_TEXT$4);
7265
7714
  return;
7266
7715
  }
7267
- await getOrgScanMetadata(orgSlug, fullScanId, cli.flags['json'] ? 'json' : cli.flags['markdown'] ? 'markdown' : 'print');
7716
+ await handleOrgScanMetadata(orgSlug, scanId, cli.flags['json'] ? 'json' : cli.flags['markdown'] ? 'markdown' : 'print');
7268
7717
  }
7269
7718
 
7270
7719
  /**
@@ -7272,7 +7721,7 @@ async function run$4(argv, importMeta, {
7272
7721
  * full scan ID.
7273
7722
  * It can optionally only fetch the security or license side of things.
7274
7723
  */
7275
- async function fetchReportData(orgSlug, fullScanId,
7724
+ async function fetchReportData(orgSlug, scanId,
7276
7725
  // includeLicensePolicy: boolean,
7277
7726
  includeSecurityPolicy) {
7278
7727
  let haveScan = false;
@@ -7309,18 +7758,18 @@ includeSecurityPolicy) {
7309
7758
  throw new shadowNpmInject.AuthError('User must be authenticated to run this command. To log in, run the command `socket login` and enter your API key.');
7310
7759
  }
7311
7760
  updateProgress();
7312
- const socketSdk = await shadowNpmInject.setupSdk(apiToken);
7761
+ const sockSdk = await shadowNpmInject.setupSdk(apiToken);
7313
7762
 
7314
7763
  // @ts-ignore
7315
7764
  const [scan,
7316
7765
  // licensePolicyMaybe,
7317
7766
  securityPolicyMaybe] = await Promise.all([(async () => {
7318
7767
  try {
7319
- const response = await queryAPI(`orgs/${orgSlug}/full-scans/${encodeURIComponent(fullScanId)}`, apiToken);
7768
+ const response = await queryApi(`orgs/${orgSlug}/full-scans/${encodeURIComponent(scanId)}`, apiToken);
7320
7769
  haveScan = true;
7321
7770
  updateProgress();
7322
7771
  if (!response.ok) {
7323
- const err = await handleAPIError(response.status);
7772
+ const err = await handleApiError(response.status);
7324
7773
  logger.logger.fail(`${colors.bgRed(colors.white(response.statusText))}: Fetch error: ${err}`);
7325
7774
  return undefined;
7326
7775
  }
@@ -7342,7 +7791,7 @@ includeSecurityPolicy) {
7342
7791
  })(),
7343
7792
  // includeLicensePolicy &&
7344
7793
  // (async () => {
7345
- // const r = await socketSdk.getOrgSecurityPolicy(orgSlug)
7794
+ // const r = await sockSdk.getOrgSecurityPolicy(orgSlug)
7346
7795
  // haveLicensePolicy = true
7347
7796
  // updateProgress()
7348
7797
  // return await handleApiCall(
@@ -7351,7 +7800,7 @@ includeSecurityPolicy) {
7351
7800
  // )
7352
7801
  // })(),
7353
7802
  includeSecurityPolicy && (async () => {
7354
- const r = await socketSdk.getOrgSecurityPolicy(orgSlug);
7803
+ const r = await sockSdk.getOrgSecurityPolicy(orgSlug);
7355
7804
  haveSecurityPolicy = true;
7356
7805
  updateProgress();
7357
7806
  return await handleApiCall(r, "looking up organization's security policy");
@@ -7597,40 +8046,31 @@ function* walkNestedMap(map, keys = []) {
7597
8046
  }
7598
8047
  }
7599
8048
 
7600
- async function reportFullScan({
8049
+ async function outputScanReport(scan,
8050
+ // licensePolicy: undefined | SocketSdkReturnType<'getOrgSecurityPolicy'>,
8051
+ securityPolicy, {
7601
8052
  filePath,
7602
8053
  fold,
7603
- fullScanId,
7604
8054
  includeLicensePolicy,
7605
8055
  includeSecurityPolicy,
7606
8056
  orgSlug,
7607
8057
  outputKind,
7608
8058
  reportLevel,
8059
+ scanId,
7609
8060
  short
7610
8061
  }) {
7611
- logger.logger.error('output:', outputKind, ', file:', filePath, ', fold:', fold, ', reportLevel:', reportLevel);
7612
8062
  if (!includeSecurityPolicy) {
8063
+ process.exitCode = 1;
7613
8064
  return; // caller should assert
7614
8065
  }
7615
- const {
7616
- // licensePolicy,
7617
- ok,
7618
- scan,
7619
- securityPolicy
7620
- } = await fetchReportData(orgSlug, fullScanId,
7621
- // includeLicensePolicy
7622
- includeSecurityPolicy);
7623
- if (!ok) {
7624
- return;
7625
- }
7626
8066
  const scanReport = generateReport(scan, undefined,
7627
8067
  // licensePolicy,
7628
8068
  securityPolicy, {
7629
8069
  orgSlug,
7630
- scanId: fullScanId,
8070
+ scanId,
7631
8071
  fold,
7632
- short,
7633
- reportLevel
8072
+ reportLevel,
8073
+ short
7634
8074
  });
7635
8075
  if (!scanReport.healthy) {
7636
8076
  process.exitCode = 1;
@@ -7717,6 +8157,43 @@ ${!report.alerts.size ? '' : mdTable(flatData, ['Policy', 'Alert Type', 'Package
7717
8157
  return md;
7718
8158
  }
7719
8159
 
8160
+ async function handleScanReport({
8161
+ filePath,
8162
+ fold,
8163
+ includeLicensePolicy,
8164
+ includeSecurityPolicy,
8165
+ orgSlug,
8166
+ outputKind,
8167
+ reportLevel,
8168
+ scanId,
8169
+ short
8170
+ }) {
8171
+ if (!includeSecurityPolicy) {
8172
+ process.exitCode = 1;
8173
+ return; // caller should assert
8174
+ }
8175
+ const {
8176
+ // licensePolicy,
8177
+ ok,
8178
+ scan,
8179
+ securityPolicy
8180
+ } = await fetchReportData(orgSlug, scanId,
8181
+ // includeLicensePolicy
8182
+ includeSecurityPolicy);
8183
+ if (!ok) return;
8184
+ await outputScanReport(scan, securityPolicy, {
8185
+ filePath,
8186
+ fold,
8187
+ scanId: scanId,
8188
+ includeLicensePolicy,
8189
+ includeSecurityPolicy,
8190
+ orgSlug,
8191
+ outputKind,
8192
+ reportLevel,
8193
+ short
8194
+ });
8195
+ }
8196
+
7720
8197
  const {
7721
8198
  DRY_RUN_BAIL_TEXT: DRY_RUN_BAIL_TEXT$3
7722
8199
  } = constants;
@@ -7803,8 +8280,8 @@ async function run$3(argv, importMeta, {
7803
8280
  reportLevel = 'warn',
7804
8281
  security
7805
8282
  } = cli.flags;
7806
- const [orgSlug = '', fullScanId = '', file = '-'] = cli.input;
7807
- if (!orgSlug || !fullScanId ||
8283
+ const [orgSlug = '', scanId = '', file = '-'] = cli.input;
8284
+ if (!orgSlug || !scanId ||
7808
8285
  // (!license && !security) ||
7809
8286
  json && markdown) {
7810
8287
  // Use exit status of 2 to indicate incorrect usage, generally invalid
@@ -7816,7 +8293,7 @@ async function run$3(argv, importMeta, {
7816
8293
 
7817
8294
  - Org name as the first argument ${!orgSlug ? colors.red('(missing!)') : colors.green('(ok)')}
7818
8295
 
7819
- - Full Scan ID to fetch as second argument ${!fullScanId ? colors.red('(missing!)') : colors.green('(ok)')}
8296
+ - Full Scan ID to fetch as second argument ${!scanId ? colors.red('(missing!)') : colors.green('(ok)')}
7820
8297
 
7821
8298
  - Not both the --json and --markdown flags ${json && markdown ? colors.red('(pick one!)') : colors.green('(ok)')}
7822
8299
  `
@@ -7828,9 +8305,9 @@ async function run$3(argv, importMeta, {
7828
8305
  logger.logger.log(DRY_RUN_BAIL_TEXT$3);
7829
8306
  return;
7830
8307
  }
7831
- await reportFullScan({
8308
+ await handleScanReport({
7832
8309
  orgSlug,
7833
- fullScanId,
8310
+ scanId: scanId,
7834
8311
  includeLicensePolicy: false,
7835
8312
  // !!license,
7836
8313
  includeSecurityPolicy: typeof security === 'boolean' ? security : true,
@@ -7842,29 +8319,7 @@ async function run$3(argv, importMeta, {
7842
8319
  });
7843
8320
  }
7844
8321
 
7845
- async function streamFullScan(orgSlug, fullScanId, file) {
7846
- // Lazily access constants.spinner.
7847
- const {
7848
- spinner
7849
- } = constants;
7850
- const apiToken = shadowNpmInject.getDefaultToken();
7851
- if (!apiToken) {
7852
- throw new shadowNpmInject.AuthError('User must be authenticated to run this command. To log in, run the command `socket login` and enter your API key.');
7853
- }
7854
- spinner.start('Fetching scan...');
7855
- const socketSdk = await shadowNpmInject.setupSdk(apiToken);
7856
- const data = await handleApiCall(socketSdk.getOrgFullScan(orgSlug, fullScanId, file === '-' ? undefined : file), 'Fetching a scan');
7857
- if (!data?.success) {
7858
- handleUnsuccessfulApiResponse('getOrgFullScan', data);
7859
- return;
7860
- }
7861
- spinner?.successAndStop(file ? `Full scan details written to ${file}` : 'stdout');
7862
- return data;
7863
- }
7864
-
7865
- async function viewFullScan(orgSlug, fullScanId, filePath) {
7866
- const artifacts = await getFullScan(orgSlug, fullScanId);
7867
- if (!artifacts) return;
8322
+ async function outputScanView(artifacts, orgSlug, scanId, filePath) {
7868
8323
  const display = artifacts.map(art => {
7869
8324
  const author = Array.isArray(art.author) ? `${art.author[0]}${art.author.length > 1 ? ' et.al.' : ''}` : art.author;
7870
8325
  return {
@@ -7881,11 +8336,11 @@ async function viewFullScan(orgSlug, fullScanId, filePath) {
7881
8336
 
7882
8337
  These are the artifacts and their scores found.
7883
8338
 
7884
- Sscan ID: ${fullScanId}
8339
+ Scan ID: ${scanId}
7885
8340
 
7886
8341
  ${md}
7887
8342
 
7888
- View this report at: https://socket.dev/dashboard/org/${orgSlug}/sbom/${fullScanId}
8343
+ View this report at: https://socket.dev/dashboard/org/${orgSlug}/sbom/${scanId}
7889
8344
  `.trim() + '\n';
7890
8345
  if (filePath && filePath !== '-') {
7891
8346
  try {
@@ -7901,6 +8356,32 @@ View this report at: https://socket.dev/dashboard/org/${orgSlug}/sbom/${fullScan
7901
8356
  }
7902
8357
  }
7903
8358
 
8359
+ async function handleScanView(orgSlug, scanId, filePath) {
8360
+ const data = await fetchScan(orgSlug, scanId);
8361
+ if (!data) return;
8362
+ await outputScanView(data, orgSlug, scanId, filePath);
8363
+ }
8364
+
8365
+ async function streamScan(orgSlug, scanId, file) {
8366
+ // Lazily access constants.spinner.
8367
+ const {
8368
+ spinner
8369
+ } = constants;
8370
+ const apiToken = shadowNpmInject.getDefaultToken();
8371
+ if (!apiToken) {
8372
+ throw new shadowNpmInject.AuthError('User must be authenticated to run this command. To log in, run the command `socket login` and enter your API key.');
8373
+ }
8374
+ const sockSdk = await shadowNpmInject.setupSdk(apiToken);
8375
+ spinner.start('Fetching scan...');
8376
+ const data = await handleApiCall(sockSdk.getOrgFullScan(orgSlug, scanId, file === '-' ? undefined : file), 'Fetching a scan');
8377
+ spinner?.successAndStop(file ? `Full scan details written to ${file}` : 'stdout');
8378
+ if (!data?.success) {
8379
+ handleUnsuccessfulApiResponse('getOrgFullScan', data);
8380
+ return;
8381
+ }
8382
+ return data;
8383
+ }
8384
+
7904
8385
  const {
7905
8386
  DRY_RUN_BAIL_TEXT: DRY_RUN_BAIL_TEXT$2
7906
8387
  } = constants;
@@ -7939,8 +8420,8 @@ async function run$2(argv, importMeta, {
7939
8420
  importMeta,
7940
8421
  parentName
7941
8422
  });
7942
- const [orgSlug = '', fullScanId = '', file = '-'] = cli.input;
7943
- if (!orgSlug || !fullScanId) {
8423
+ const [orgSlug = '', scanId = '', file = '-'] = cli.input;
8424
+ if (!orgSlug || !scanId) {
7944
8425
  // Use exit status of 2 to indicate incorrect usage, generally invalid
7945
8426
  // options or missing arguments.
7946
8427
  // https://www.gnu.org/software/bash/manual/html_node/Exit-Status.html
@@ -7950,7 +8431,7 @@ async function run$2(argv, importMeta, {
7950
8431
 
7951
8432
  - Org name as the first argument ${!orgSlug ? colors.red('(missing!)') : colors.green('(ok)')}
7952
8433
 
7953
- - Full Scan ID to fetch as second argument ${!fullScanId ? colors.red('(missing!)') : colors.green('(ok)')}
8434
+ - Full Scan ID to fetch as second argument ${!scanId ? colors.red('(missing!)') : colors.green('(ok)')}
7954
8435
  `);
7955
8436
  return;
7956
8437
  }
@@ -7959,9 +8440,9 @@ async function run$2(argv, importMeta, {
7959
8440
  return;
7960
8441
  }
7961
8442
  if (cli.flags['json']) {
7962
- await streamFullScan(orgSlug, fullScanId, file);
8443
+ await streamScan(orgSlug, scanId, file);
7963
8444
  } else {
7964
- await viewFullScan(orgSlug, fullScanId, file);
8445
+ await handleScanView(orgSlug, scanId, file);
7965
8446
  }
7966
8447
  }
7967
8448
 
@@ -8034,7 +8515,7 @@ async function getThreatFeedWithToken({
8034
8515
  } = constants;
8035
8516
  const queryParams = new URLSearchParams([['direction', direction], ['ecosystem', ecosystem], ['filter', filter], ['page', page], ['per_page', String(perPage)]]);
8036
8517
  spinner.start('Fetching Threat Feed data...');
8037
- const response = await queryAPI(`threat-feed?${queryParams}`, apiToken);
8518
+ const response = await queryApi(`threat-feed?${queryParams}`, apiToken);
8038
8519
  const data = await response.json();
8039
8520
  spinner.stop('Threat feed data fetched');
8040
8521
  if (outputKind === 'json') {
@@ -8457,12 +8938,13 @@ void (async () => {
8457
8938
  await vendor.updater({
8458
8939
  name: SOCKET_CLI_BIN_NAME,
8459
8940
  // The '@rollup/plugin-replace' will replace "process.env['INLINED_SOCKET_CLI_VERSION']".
8460
- version: "0.14.65",
8941
+ version: "0.14.67",
8461
8942
  ttl: 86_400_000 /* 24 hours in milliseconds */
8462
8943
  });
8463
8944
  try {
8464
8945
  await meowWithSubcommands({
8465
8946
  cdxgen: cmdCdxgen,
8947
+ config: cmdConfig,
8466
8948
  fix: cmdFix,
8467
8949
  info: cmdInfo,
8468
8950
  login: cmdLogin,
@@ -8524,5 +9006,5 @@ void (async () => {
8524
9006
  await shadowNpmInject.captureException(e);
8525
9007
  }
8526
9008
  })();
8527
- //# debugId=4f35ba71-7571-4877-b38b-469cb0fdda66
9009
+ //# debugId=85506a12-36b6-49a2-b249-50b4dfcf2be6
8528
9010
  //# sourceMappingURL=cli.js.map