@socketsecurity/cli 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:9b43c652:pub";
655
+ "0.14.67:a2db5d2:39ede5c0: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'
@@ -2431,15 +2830,15 @@ async function run$x(argv, importMeta, {
2431
2830
  }
2432
2831
 
2433
2832
  async function fetchPackageInfo(pkgName, pkgVersion, includeAllIssues) {
2434
- const socketSdk = await shadowNpmInject.setupSdk(shadowNpmInject.getPublicToken());
2833
+ const sockSdk = await shadowNpmInject.setupSdk(shadowNpmInject.getPublicToken());
2435
2834
 
2436
2835
  // Lazily access constants.spinner.
2437
2836
  const {
2438
2837
  spinner
2439
2838
  } = constants;
2440
2839
  spinner.start(pkgVersion === 'latest' ? `Looking up data for the latest version of ${pkgName}` : `Looking up data for version ${pkgVersion} of ${pkgName}`);
2441
- const result = await handleApiCall(socketSdk.getIssuesByNPMPackage(pkgName, pkgVersion), 'looking up package');
2442
- const scoreResult = await handleApiCall(socketSdk.getScoreByNPMPackage(pkgName, pkgVersion), 'looking up package score');
2840
+ const result = await handleApiCall(sockSdk.getIssuesByNPMPackage(pkgName, pkgVersion), 'looking up package');
2841
+ const scoreResult = await handleApiCall(sockSdk.getScoreByNPMPackage(pkgName, pkgVersion), 'looking up package score');
2443
2842
  spinner.successAndStop('Data fetched');
2444
2843
  if (result.success === false) {
2445
2844
  return handleUnsuccessfulApiResponse('getIssuesByNPMPackage', result);
@@ -2467,7 +2866,7 @@ function formatScore$1(score) {
2467
2866
  return colors.red(`${score}`);
2468
2867
  }
2469
2868
  function outputPackageIssuesDetails(packageData, outputMarkdown) {
2470
- const issueDetails = packageData.filter(d => d.value?.severity === shadowNpmInject.SEVERITY.critical || d.value?.severity === shadowNpmInject.SEVERITY.high);
2869
+ const issueDetails = packageData.filter(d => d.value?.severity === shadowNpmInject.ALERT_SEVERITY.critical || d.value?.severity === shadowNpmInject.ALERT_SEVERITY.high);
2471
2870
  const uniqueIssueDetails = issueDetails.reduce((acc, issue) => {
2472
2871
  const {
2473
2872
  type
@@ -2654,18 +3053,18 @@ async function run$w(argv, importMeta, {
2654
3053
  }
2655
3054
 
2656
3055
  function applyLogin(apiToken, enforcedOrgs, apiBaseUrl, apiProxy) {
2657
- shadowNpmInject.updateSetting('enforcedOrgs', enforcedOrgs);
2658
- shadowNpmInject.updateSetting('apiToken', apiToken);
2659
- shadowNpmInject.updateSetting('apiBaseUrl', apiBaseUrl);
2660
- shadowNpmInject.updateSetting('apiProxy', apiProxy);
3056
+ shadowNpmInject.updateConfigValue('enforcedOrgs', enforcedOrgs);
3057
+ shadowNpmInject.updateConfigValue('apiToken', apiToken);
3058
+ shadowNpmInject.updateConfigValue('apiBaseUrl', apiBaseUrl);
3059
+ shadowNpmInject.updateConfigValue('apiProxy', apiProxy);
2661
3060
  }
2662
3061
 
2663
3062
  const {
2664
3063
  SOCKET_PUBLIC_API_TOKEN
2665
3064
  } = constants;
2666
3065
  async function attemptLogin(apiBaseUrl, apiProxy) {
2667
- apiBaseUrl ??= shadowNpmInject.getSetting('apiBaseUrl') ?? undefined;
2668
- apiProxy ??= shadowNpmInject.getSetting('apiProxy') ?? undefined;
3066
+ apiBaseUrl ??= shadowNpmInject.getConfigValue('apiBaseUrl') ?? undefined;
3067
+ apiProxy ??= shadowNpmInject.getConfigValue('apiProxy') ?? undefined;
2669
3068
  const apiToken = (await prompts.password({
2670
3069
  message: `Enter your ${terminalLink('Socket.dev API key', 'https://docs.socket.dev/docs/api-keys')} (leave blank for a public key)`
2671
3070
  })) || SOCKET_PUBLIC_API_TOKEN;
@@ -2721,7 +3120,7 @@ async function attemptLogin(apiBaseUrl, apiProxy) {
2721
3120
  }
2722
3121
  }
2723
3122
  spinner.stop();
2724
- const oldToken = shadowNpmInject.getSetting('apiToken');
3123
+ const oldToken = shadowNpmInject.getConfigValue('apiToken');
2725
3124
  try {
2726
3125
  applyLogin(apiToken, enforcedOrgs, apiBaseUrl, apiProxy);
2727
3126
  logger.logger.success(`API credentials ${oldToken ? 'updated' : 'set'}`);
@@ -2789,10 +3188,10 @@ async function run$v(argv, importMeta, {
2789
3188
  }
2790
3189
 
2791
3190
  function applyLogout() {
2792
- shadowNpmInject.updateSetting('apiToken', null);
2793
- shadowNpmInject.updateSetting('apiBaseUrl', null);
2794
- shadowNpmInject.updateSetting('apiProxy', null);
2795
- shadowNpmInject.updateSetting('enforcedOrgs', null);
3191
+ shadowNpmInject.updateConfigValue('apiToken', null);
3192
+ shadowNpmInject.updateConfigValue('apiBaseUrl', null);
3193
+ shadowNpmInject.updateConfigValue('apiProxy', null);
3194
+ shadowNpmInject.updateConfigValue('enforcedOrgs', null);
2796
3195
  }
2797
3196
 
2798
3197
  function attemptLogout() {
@@ -4541,14 +4940,14 @@ async function fetchOrganization() {
4541
4940
  return await fetchOrganizationWithToken(apiToken);
4542
4941
  }
4543
4942
  async function fetchOrganizationWithToken(apiToken) {
4544
- const socketSdk = await shadowNpmInject.setupSdk(apiToken);
4943
+ const sockSdk = await shadowNpmInject.setupSdk(apiToken);
4545
4944
 
4546
4945
  // Lazily access constants.spinner.
4547
4946
  const {
4548
4947
  spinner
4549
4948
  } = constants;
4550
4949
  spinner.start('Fetching organization list...');
4551
- const result = await handleApiCall(socketSdk.getOrganizations(), 'looking up organizations');
4950
+ const result = await handleApiCall(sockSdk.getOrganizations(), 'looking up organizations');
4552
4951
  spinner.successAndStop('Received organization list response.');
4553
4952
  if (!result.success) {
4554
4953
  handleUnsuccessfulApiResponse('getOrganizations', result);
@@ -4678,9 +5077,9 @@ async function fetchSecurityPolicyWithToken(apiToken, orgSlug) {
4678
5077
  const {
4679
5078
  spinner
4680
5079
  } = constants;
4681
- const socketSdk = await shadowNpmInject.setupSdk(apiToken);
5080
+ const sockSdk = await shadowNpmInject.setupSdk(apiToken);
4682
5081
  spinner.start('Fetching organization quota...');
4683
- const result = await handleApiCall(socketSdk.getOrgSecurityPolicy(orgSlug), 'looking up organization quota');
5082
+ const result = await handleApiCall(sockSdk.getOrgSecurityPolicy(orgSlug), 'looking up organization quota');
4684
5083
  spinner?.successAndStop('Received organization quota response.');
4685
5084
  if (!result.success) {
4686
5085
  handleUnsuccessfulApiResponse('getOrgSecurityPolicy', result);
@@ -4823,9 +5222,9 @@ async function fetchQuotaWithToken(apiToken) {
4823
5222
  const {
4824
5223
  spinner
4825
5224
  } = constants;
4826
- const socketSdk = await shadowNpmInject.setupSdk(apiToken);
5225
+ const sockSdk = await shadowNpmInject.setupSdk(apiToken);
4827
5226
  spinner.start('Fetching organization quota...');
4828
- const result = await handleApiCall(socketSdk.getQuota(), 'looking up organization quota');
5227
+ const result = await handleApiCall(sockSdk.getQuota(), 'looking up organization quota');
4829
5228
  spinner?.successAndStop('Recieved organization quota response.');
4830
5229
  if (!result.success) {
4831
5230
  handleUnsuccessfulApiResponse('getQuota', result);
@@ -4952,8 +5351,8 @@ async function fetchPurlsShallowScore(purls) {
4952
5351
  spinner
4953
5352
  } = constants;
4954
5353
  spinner.start(`Requesting data ...`);
4955
- const socketSdk = await shadowNpmInject.setupSdk(shadowNpmInject.getPublicToken());
4956
- const result = await handleApiCall(socketSdk.batchPackageFetch({
5354
+ const sockSdk = await shadowNpmInject.setupSdk(shadowNpmInject.getPublicToken());
5355
+ const result = await handleApiCall(sockSdk.batchPackageFetch({
4957
5356
  alerts: 'true'
4958
5357
  // compact: false,
4959
5358
  // fixable: false,
@@ -5354,8 +5753,8 @@ async function createReport(socketConfig, inputPaths, {
5354
5753
  const {
5355
5754
  spinner
5356
5755
  } = constants;
5357
- const socketSdk = await shadowNpmInject.setupSdk();
5358
- const supportedFiles = await socketSdk.getReportSupportedFiles().then(res => {
5756
+ const sockSdk = await shadowNpmInject.setupSdk();
5757
+ const supportedFiles = await sockSdk.getReportSupportedFiles().then(res => {
5359
5758
  if (!res.success) handleUnsuccessfulApiResponse('getReportSupportedFiles', res);
5360
5759
  return res.data;
5361
5760
  }).catch(cause => {
@@ -5363,7 +5762,7 @@ async function createReport(socketConfig, inputPaths, {
5363
5762
  cause
5364
5763
  });
5365
5764
  });
5366
- const packagePaths = await shadowNpmPaths.getPackageFilesFullScans(cwd, inputPaths, supportedFiles, socketConfig);
5765
+ const packagePaths = await shadowNpmPaths.getPackageFilesForScan(cwd, inputPaths, supportedFiles, socketConfig);
5367
5766
  const packagePathsCount = packagePaths.length;
5368
5767
  if (packagePathsCount && debug.isDebug()) {
5369
5768
  for (const pkgPath of packagePaths) {
@@ -5375,7 +5774,7 @@ async function createReport(socketConfig, inputPaths, {
5375
5774
  return undefined;
5376
5775
  }
5377
5776
  spinner.start(`Creating report with ${packagePathsCount} package ${words.pluralize('file', packagePathsCount)}`);
5378
- const apiCall = socketSdk.createReportFromFilePaths(packagePaths, cwd, socketConfig?.issueRules);
5777
+ const apiCall = sockSdk.createReportFromFilePaths(packagePaths, cwd, socketConfig?.issueRules);
5379
5778
  const result = await handleApiCall(apiCall, 'creating report');
5380
5779
  if (!result.success) {
5381
5780
  handleUnsuccessfulApiResponse('createReport', result);
@@ -5386,8 +5785,8 @@ async function createReport(socketConfig, inputPaths, {
5386
5785
  }
5387
5786
 
5388
5787
  async function getSocketConfig(absoluteConfigPath) {
5389
- const socketConfig = await config$D.readSocketConfig(absoluteConfigPath).catch(cause => {
5390
- if (cause && typeof cause === 'object' && cause instanceof config$D.SocketValidationError) {
5788
+ const socketConfig = await config$H.readSocketConfig(absoluteConfigPath).catch(cause => {
5789
+ if (cause && typeof cause === 'object' && cause instanceof config$H.SocketValidationError) {
5391
5790
  // Inspired by workbox-build:
5392
5791
  // https://github.com/GoogleChrome/workbox/blob/95f97a207fd51efb3f8a653f6e3e58224183a778/packages/workbox-build/src/lib/validate-options.ts#L68-L71
5393
5792
  const betterErrors = betterAjvErrors.betterAjvErrors({
@@ -5415,12 +5814,12 @@ async function fetchReportData$1(reportId, includeAllIssues, strict) {
5415
5814
  } = constants;
5416
5815
  spinner.log('Fetching report with ID ${reportId} (this could take a while)');
5417
5816
  spinner.start(`Fetch started... (this could take a while)`);
5418
- const socketSdk = await shadowNpmInject.setupSdk();
5817
+ const sockSdk = await shadowNpmInject.setupSdk();
5419
5818
  let result;
5420
5819
  for (let retry = 1; !result; ++retry) {
5421
5820
  try {
5422
5821
  // eslint-disable-next-line no-await-in-loop
5423
- result = await handleApiCall(socketSdk.getReport(reportId), 'fetching report');
5822
+ result = await handleApiCall(sockSdk.getReport(reportId), 'fetching report');
5424
5823
  } catch (err) {
5425
5824
  if (retry >= MAX_TIMEOUT_RETRY || !(err instanceof Error) || err.cause?.cause?.response?.statusCode !== HTTP_CODE_TIMEOUT) {
5426
5825
  spinner.stop(`Failed to fetch report`);
@@ -5472,7 +5871,7 @@ function formatReportDataOutput(reportId, data, commandName, outputKind, strict,
5472
5871
  }
5473
5872
  }
5474
5873
 
5475
- async function getFullScan(orgSlug, fullScanId) {
5874
+ async function fetchScan(orgSlug, scanId) {
5476
5875
  // Lazily access constants.spinner.
5477
5876
  const {
5478
5877
  spinner
@@ -5482,10 +5881,10 @@ async function getFullScan(orgSlug, fullScanId) {
5482
5881
  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.');
5483
5882
  }
5484
5883
  spinner.start('Fetching full-scan...');
5485
- const response = await queryAPI(`orgs/${orgSlug}/full-scans/${encodeURIComponent(fullScanId)}`, apiToken);
5884
+ const response = await queryApi(`orgs/${orgSlug}/full-scans/${encodeURIComponent(scanId)}`, apiToken);
5486
5885
  spinner.stop('Fetch complete.');
5487
5886
  if (!response.ok) {
5488
- const err = await handleAPIError(response.status);
5887
+ const err = await handleApiError(response.status);
5489
5888
  logger.logger.fail(`${colors.bgRed(colors.white(response.statusText))}: Fetch error: ${err}`);
5490
5889
  return;
5491
5890
  }
@@ -5511,7 +5910,7 @@ async function viewReport(reportId, {
5511
5910
  strict
5512
5911
  }) {
5513
5912
  const result = await fetchReportData$1(reportId, all, strict);
5514
- const artifacts = await getFullScan('socketdev', reportId);
5913
+ const artifacts = await fetchScan('socketdev', reportId);
5515
5914
  if (result) {
5516
5915
  formatReportDataOutput(reportId, result, commandName, outputKind, strict, artifacts);
5517
5916
  }
@@ -5712,9 +6111,9 @@ async function fetchCreateRepoWithToken(apiToken, {
5712
6111
  const {
5713
6112
  spinner
5714
6113
  } = constants;
5715
- const socketSdk = await shadowNpmInject.setupSdk(apiToken);
6114
+ const sockSdk = await shadowNpmInject.setupSdk(apiToken);
5716
6115
  spinner.start('Sending request ot create a repository...');
5717
- const result = await handleApiCall(socketSdk.createOrgRepo(orgSlug, {
6116
+ const result = await handleApiCall(sockSdk.createOrgRepo(orgSlug, {
5718
6117
  name: repoName,
5719
6118
  description,
5720
6119
  homepage,
@@ -5859,8 +6258,8 @@ async function deleteRepoWithToken(orgSlug, repoName, apiToken) {
5859
6258
  spinner
5860
6259
  } = constants;
5861
6260
  spinner.start('Deleting repository...');
5862
- const socketSdk = await shadowNpmInject.setupSdk(apiToken);
5863
- const result = await handleApiCall(socketSdk.deleteOrgRepo(orgSlug, repoName), 'deleting repository');
6261
+ const sockSdk = await shadowNpmInject.setupSdk(apiToken);
6262
+ const result = await handleApiCall(sockSdk.deleteOrgRepo(orgSlug, repoName), 'deleting repository');
5864
6263
  if (!result.success) {
5865
6264
  handleUnsuccessfulApiResponse('deleteOrgRepo', result);
5866
6265
  return;
@@ -5955,9 +6354,9 @@ async function fetchListReposWithToken(apiToken, {
5955
6354
  const {
5956
6355
  spinner
5957
6356
  } = constants;
5958
- const socketSdk = await shadowNpmInject.setupSdk(apiToken);
6357
+ const sockSdk = await shadowNpmInject.setupSdk(apiToken);
5959
6358
  spinner.start('Fetching list of repositories...');
5960
- const result = await handleApiCall(socketSdk.getOrgRepoList(orgSlug, {
6359
+ const result = await handleApiCall(sockSdk.getOrgRepoList(orgSlug, {
5961
6360
  sort,
5962
6361
  direction,
5963
6362
  per_page: String(per_page),
@@ -6144,8 +6543,8 @@ async function fetchUpdateRepoWithToken(apiToken, {
6144
6543
  spinner
6145
6544
  } = constants;
6146
6545
  spinner.start('Sending request to update a repository...');
6147
- const socketSdk = await shadowNpmInject.setupSdk(apiToken);
6148
- const result = await handleApiCall(socketSdk.updateOrgRepo(orgSlug, repoName, {
6546
+ const sockSdk = await shadowNpmInject.setupSdk(apiToken);
6547
+ const result = await handleApiCall(sockSdk.updateOrgRepo(orgSlug, repoName, {
6149
6548
  orgSlug,
6150
6549
  name: repoName,
6151
6550
  description,
@@ -6292,9 +6691,9 @@ async function fetchViewRepoWithToken(orgSlug, repoName, apiToken) {
6292
6691
  const {
6293
6692
  spinner
6294
6693
  } = constants;
6295
- const socketSdk = await shadowNpmInject.setupSdk(apiToken);
6694
+ const sockSdk = await shadowNpmInject.setupSdk(apiToken);
6296
6695
  spinner.start('Fetching repository data...');
6297
- const result = await handleApiCall(socketSdk.getOrgRepo(orgSlug, repoName), 'fetching repository');
6696
+ const result = await handleApiCall(sockSdk.getOrgRepo(orgSlug, repoName), 'fetching repository');
6298
6697
  spinner.successAndStop('Received response while fetched repository data.');
6299
6698
  if (!result.success) {
6300
6699
  handleUnsuccessfulApiResponse('getOrgRepo', result);
@@ -6448,8 +6847,106 @@ const cmdRepos = {
6448
6847
  }
6449
6848
  };
6450
6849
 
6451
- async function suggestOrgSlug(socketSdk) {
6452
- const result = await handleApiCall(socketSdk.getOrganizations(), 'looking up organizations');
6850
+ async function fetchCreateOrgFullScan(packagePaths, orgSlug, repoName, branchName, commitMessage, defaultBranch, pendingHead, tmp, cwd) {
6851
+ const sockSdk = await shadowNpmInject.setupSdk();
6852
+
6853
+ // Lazily access constants.spinner.
6854
+ const {
6855
+ spinner
6856
+ } = constants;
6857
+ spinner.start(`Creating a scan with ${packagePaths.length} packages...`);
6858
+ const result = await handleApiCall(sockSdk.createOrgFullScan(orgSlug, {
6859
+ repo: repoName,
6860
+ branch: branchName,
6861
+ commit_message: commitMessage,
6862
+ make_default_branch: String(defaultBranch),
6863
+ set_as_pending_head: String(pendingHead),
6864
+ tmp: String(tmp)
6865
+ }, packagePaths, cwd), 'Creating scan');
6866
+ spinner.successAndStop('Scan created successfully');
6867
+ if (!result.success) {
6868
+ handleUnsuccessfulApiResponse('CreateOrgFullScan', result);
6869
+ return;
6870
+ }
6871
+ return result.data;
6872
+ }
6873
+
6874
+ async function fetchSupportedScanFileNames() {
6875
+ const sockSdk = await shadowNpmInject.setupSdk();
6876
+
6877
+ // Lazily access constants.spinner.
6878
+ const {
6879
+ spinner
6880
+ } = constants;
6881
+ spinner.start('Requesting supported scan file types from API...');
6882
+ const result = await handleApiCall(sockSdk.getReportSupportedFiles(), 'fetching supported scan file types');
6883
+ spinner.successAndStop('Received response while fetched supported scan file types.');
6884
+ if (!result.success) {
6885
+ handleUnsuccessfulApiResponse('getReportSupportedFiles', result);
6886
+ return;
6887
+ }
6888
+ return result.data;
6889
+ }
6890
+
6891
+ async function outputCreateNewScan(data) {
6892
+ const link = colors.underline(colors.cyan(`${data.html_report_url}`));
6893
+ logger.logger.log(`Available at: ${link}`);
6894
+ const rl = readline.createInterface({
6895
+ input: process$1.stdin,
6896
+ output: process$1.stdout
6897
+ });
6898
+ const answer = await rl.question('Would you like to open it in your browser? (y/n)');
6899
+ if (answer.toLowerCase() === 'y') {
6900
+ await vendor.open(`${data.html_report_url}`);
6901
+ }
6902
+ rl.close();
6903
+ }
6904
+
6905
+ async function handleCreateNewScan({
6906
+ branchName,
6907
+ commitMessage,
6908
+ cwd,
6909
+ defaultBranch,
6910
+ orgSlug,
6911
+ pendingHead,
6912
+ readOnly,
6913
+ repoName,
6914
+ targets,
6915
+ tmp
6916
+ }) {
6917
+ const apiToken = shadowNpmInject.getDefaultToken();
6918
+
6919
+ // Note: you need an apiToken to request supportedScanFileNames from the API
6920
+ if (!apiToken) {
6921
+ 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.');
6922
+ }
6923
+ const supportedFileNames = await fetchSupportedScanFileNames();
6924
+ if (!supportedFileNames) return;
6925
+ const packagePaths = await shadowNpmPaths.getPackageFilesForScan(cwd, targets, supportedFileNames
6926
+ // socketConfig
6927
+ );
6928
+ if (!packagePaths.length) {
6929
+ // Use exit status of 2 to indicate incorrect usage, generally invalid
6930
+ // options or missing arguments.
6931
+ // https://www.gnu.org/software/bash/manual/html_node/Exit-Status.html
6932
+ process$1.exitCode = 2;
6933
+ logger.logger.fail(commonTags.stripIndents`
6934
+ ${colors.bgRed(colors.white('Input error'))}: The TARGET did not contain any matching / supported files for a scan
6935
+ `);
6936
+ return;
6937
+ }
6938
+ if (readOnly) {
6939
+ logger.logger.log('[ReadOnly] Bailing now');
6940
+ return;
6941
+ }
6942
+ const data = await fetchCreateOrgFullScan(packagePaths, orgSlug, repoName, branchName, commitMessage, defaultBranch, pendingHead, tmp, cwd);
6943
+ if (!data) return;
6944
+ await outputCreateNewScan(data);
6945
+ }
6946
+
6947
+ async function suggestOrgSlug() {
6948
+ const sockSdk = await shadowNpmInject.setupSdk();
6949
+ const result = await handleApiCall(sockSdk.getOrganizations(), 'looking up organizations');
6453
6950
  // Ignore a failed request here. It was not the primary goal of
6454
6951
  // running this command and reporting it only leads to end-user confusion.
6455
6952
  if (result.success) {
@@ -6470,13 +6967,17 @@ async function suggestOrgSlug(socketSdk) {
6470
6967
  if (proceed) {
6471
6968
  return proceed;
6472
6969
  }
6970
+ } else {
6971
+ logger.logger.fail('Failed to lookup organization list from API, unable to suggest.');
6473
6972
  }
6474
6973
  }
6475
6974
 
6476
- async function suggestRepoSlug(socketSdk, orgSlug) {
6975
+ async function suggestRepoSlug(orgSlug) {
6976
+ const sockSdk = await shadowNpmInject.setupSdk();
6977
+
6477
6978
  // Same as above, but if there's a repo with the same name as cwd then
6478
6979
  // default the selection to that name.
6479
- const result = await handleApiCall(socketSdk.getOrgRepoList(orgSlug, {
6980
+ const result = await handleApiCall(sockSdk.getOrgRepoList(orgSlug, {
6480
6981
  orgSlug,
6481
6982
  sort: 'name',
6482
6983
  direction: 'asc',
@@ -6486,6 +6987,7 @@ async function suggestRepoSlug(socketSdk, orgSlug) {
6486
6987
  perPage: '10',
6487
6988
  page: '0'
6488
6989
  }), 'looking up known repos');
6990
+
6489
6991
  // Ignore a failed request here. It was not the primary goal of
6490
6992
  // running this command and reporting it only leads to end-user confusion.
6491
6993
  if (result.success) {
@@ -6493,7 +6995,7 @@ async function suggestRepoSlug(socketSdk, orgSlug) {
6493
6995
  let cwdIsKnown = !!currentDirName && result.data.results.some(obj => obj.slug === currentDirName);
6494
6996
  if (!cwdIsKnown && currentDirName) {
6495
6997
  // Do an explicit request so we can assert that the cwd exists or not
6496
- const result = await handleApiCall(socketSdk.getOrgRepo(orgSlug, currentDirName), 'checking if current cwd is a known repo');
6998
+ const result = await handleApiCall(sockSdk.getOrgRepo(orgSlug, currentDirName), 'checking if current cwd is a known repo');
6497
6999
  if (result.success) {
6498
7000
  cwdIsKnown = true;
6499
7001
  }
@@ -6532,203 +7034,64 @@ async function suggestRepoSlug(socketSdk, orgSlug) {
6532
7034
  }
6533
7035
  });
6534
7036
  return {
6535
- slug: repoName,
6536
- defaultBranch: repoDefaultBranch
6537
- };
6538
- }
6539
- }
6540
- }
6541
- function dirNameToSlug(name) {
6542
- // Uses slug specs asserted by our servers
6543
- // Note: this can lead to collisions; eg. slug for `x--y` and `x---y` is `x-y`
6544
- return name.toLowerCase().replace(/[^[a-zA-Z0-9_.-]/g, '_').replace(/--+/g, '-').replace(/__+/g, '_').replace(/\.\.+/g, '.').replace(/[._-]+$/, '');
6545
- }
6546
-
6547
- async function suggestBranchSlug(repoDefaultBranch) {
6548
- const spawnResult = spawn.spawnSync('git', ['branch', '--show-current']);
6549
- const currentBranch = spawnResult.stdout.toString('utf8').trim();
6550
- if (currentBranch && spawnResult.status === 0) {
6551
- const proceed = await prompts.select({
6552
- message: 'Use the current git branch as target branch name?',
6553
- choices: [{
6554
- name: `Yes [${currentBranch}]`,
6555
- value: currentBranch,
6556
- description: 'Use the current git branch for branch name'
6557
- }, ...(repoDefaultBranch && repoDefaultBranch !== currentBranch ? [{
6558
- name: `No, use the default branch [${repoDefaultBranch}]`,
6559
- value: repoDefaultBranch,
6560
- description: 'Use the default branch for target repo as the target branch name'
6561
- }] : []), {
6562
- name: 'No',
6563
- value: '',
6564
- description: 'Do not use the current git branch as name (will end in a no-op)'
6565
- }].filter(Boolean)
6566
- });
6567
- if (proceed) {
6568
- return proceed;
6569
- }
6570
- }
6571
- }
6572
-
6573
- async function suggestTarget() {
6574
- // We could prefill this with sub-dirs of the current
6575
- // dir ... but is that going to be useful?
6576
- const proceed = await prompts.select({
6577
- message: 'No TARGET given. Do you want to use the current directory?',
6578
- choices: [{
6579
- name: 'Yes',
6580
- value: true,
6581
- description: 'Target the current directory'
6582
- }, {
6583
- name: 'No',
6584
- value: false,
6585
- description: 'Do not use the current directory (this will end in a no-op)'
6586
- }]
6587
- });
6588
- if (proceed) {
6589
- return ['.'];
6590
- }
6591
- }
6592
-
6593
- async function createFullScan({
6594
- branchName,
6595
- commitHash: _commitHash,
6596
- commitMessage,
6597
- committers: _committers,
6598
- cwd,
6599
- defaultBranch,
6600
- orgSlug,
6601
- pendingHead,
6602
- pullRequest: _pullRequest,
6603
- readOnly,
6604
- repoName,
6605
- targets,
6606
- tmp
6607
- }) {
6608
- // Lazily access constants.spinner.
6609
- const {
6610
- spinner
6611
- } = constants;
6612
- const socketSdk = await shadowNpmInject.setupSdk();
6613
- const supportedFiles = await socketSdk.getReportSupportedFiles().then(res => {
6614
- if (!res.success) {
6615
- handleUnsuccessfulApiResponse('getReportSupportedFiles', res);
6616
- assert(false, 'handleUnsuccessfulApiResponse should unconditionally throw');
6617
- }
6618
- return res.data;
6619
- }).catch(cause => {
6620
- throw new Error('Failed getting supported files for report', {
6621
- cause
6622
- });
6623
- });
6624
-
6625
- // If we updated any inputs then we should print the command line to repeat
6626
- // the command without requiring user input, as a suggestion.
6627
- let updatedInput = false;
6628
- if (!targets.length) {
6629
- const received = await suggestTarget();
6630
- targets = received ?? [];
6631
- updatedInput = true;
6632
- }
6633
-
6634
- // // TODO: we'll probably use socket.json or something else soon...
6635
- // const absoluteConfigPath = path.join(cwd, 'socket.yml')
6636
- // const socketConfig = await getSocketConfig(absoluteConfigPath)
6637
-
6638
- const packagePaths = await shadowNpmPaths.getPackageFilesFullScans(cwd, targets, supportedFiles
6639
- // socketConfig
6640
- );
6641
-
6642
- // We're going to need an api token to suggest data because those suggestions
6643
- // must come from data we already know. Don't error on missing api token yet.
6644
- // If the api-token is not set, ignore it for the sake of suggestions.
6645
- const apiToken = shadowNpmInject.getDefaultToken();
6646
-
6647
- // If the current cwd is unknown and is used as a repo slug anyways, we will
6648
- // first need to register the slug before we can use it.
6649
- let repoDefaultBranch = '';
6650
- if (apiToken) {
6651
- if (!orgSlug) {
6652
- const suggestion = await suggestOrgSlug(socketSdk);
6653
- if (suggestion) orgSlug = suggestion;
6654
- updatedInput = true;
6655
- }
6656
-
6657
- // (Don't bother asking for the rest if we didn't get an org slug above)
6658
- if (orgSlug && !repoName) {
6659
- const suggestion = await suggestRepoSlug(socketSdk, orgSlug);
6660
- if (suggestion) {
6661
- repoDefaultBranch = suggestion.defaultBranch;
6662
- repoName = suggestion.slug;
6663
- }
6664
- updatedInput = true;
6665
- }
6666
-
6667
- // (Don't bother asking for the rest if we didn't get an org/repo above)
6668
- if (orgSlug && repoName && !branchName) {
6669
- const suggestion = await suggestBranchSlug(repoDefaultBranch);
6670
- if (suggestion) branchName = suggestion;
6671
- updatedInput = true;
7037
+ slug: repoName,
7038
+ defaultBranch: repoDefaultBranch
7039
+ };
6672
7040
  }
7041
+ } else {
7042
+ logger.logger.fail('Failed to lookup repo list from API, unable to suggest.');
6673
7043
  }
6674
- if (!orgSlug || !repoName || !branchName || !packagePaths.length) {
6675
- // Use exit status of 2 to indicate incorrect usage, generally invalid
6676
- // options or missing arguments.
6677
- // https://www.gnu.org/software/bash/manual/html_node/Exit-Status.html
6678
- process$1.exitCode = 2;
6679
- logger.logger.fail(commonTags.stripIndents`
6680
- ${colors.bgRed(colors.white('Input error'))}: Please provide the required fields:
6681
-
6682
- - Org name as the first argument ${!orgSlug ? colors.red('(missing!)') : colors.green('(ok)')}
6683
-
6684
- - Repository name using --repo ${!repoName ? colors.red('(missing!)') : colors.green('(ok)')}
6685
-
6686
- - Branch name using --branch ${!branchName ? colors.red('(missing!)') : colors.green('(ok)')}
6687
-
6688
- - 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)')}
7044
+ }
7045
+ function dirNameToSlug(name) {
7046
+ // Uses slug specs asserted by our servers
7047
+ // Note: this can lead to collisions; eg. slug for `x--y` and `x---y` is `x-y`
7048
+ return name.toLowerCase().replace(/[^[a-zA-Z0-9_.-]/g, '_').replace(/--+/g, '-').replace(/__+/g, '_').replace(/\.\.+/g, '.').replace(/[._-]+$/, '');
7049
+ }
6689
7050
 
6690
- ${!apiToken ? 'Note: was unable to make suggestions because no API Token was found; this would make command fail regardless' : ''}
6691
- `);
6692
- return;
6693
- }
6694
- if (updatedInput) {
6695
- logger.logger.log('Note: You can invoke this command next time to skip the interactive questions:');
6696
- logger.logger.log('```');
6697
- logger.logger.log(` socket scan create [other flags...] --repo ${repoName} --branch ${branchName} ${orgSlug} ${targets.join(' ')}`);
6698
- logger.logger.log('```');
6699
- }
6700
- if (!apiToken) {
6701
- 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.');
6702
- }
6703
- if (readOnly) {
6704
- logger.logger.log('[ReadOnly] Bailing now');
6705
- return;
6706
- }
6707
- spinner.start(`Creating a scan with ${packagePaths.length} packages...`);
6708
- const result = await handleApiCall(socketSdk.createOrgFullScan(orgSlug, {
6709
- repo: repoName,
6710
- branch: branchName,
6711
- commit_message: commitMessage,
6712
- make_default_branch: String(defaultBranch),
6713
- set_as_pending_head: String(pendingHead),
6714
- tmp: String(tmp)
6715
- }, packagePaths, cwd), 'Creating scan');
6716
- if (!result.success) {
6717
- handleUnsuccessfulApiResponse('CreateOrgFullScan', result);
6718
- return;
7051
+ async function suggestBranchSlug(repoDefaultBranch) {
7052
+ const spawnResult = spawn.spawnSync('git', ['branch', '--show-current']);
7053
+ const currentBranch = spawnResult.stdout.toString('utf8').trim();
7054
+ if (currentBranch && spawnResult.status === 0) {
7055
+ const proceed = await prompts.select({
7056
+ message: 'Use the current git branch as target branch name?',
7057
+ choices: [{
7058
+ name: `Yes [${currentBranch}]`,
7059
+ value: currentBranch,
7060
+ description: 'Use the current git branch for branch name'
7061
+ }, ...(repoDefaultBranch && repoDefaultBranch !== currentBranch ? [{
7062
+ name: `No, use the default branch [${repoDefaultBranch}]`,
7063
+ value: repoDefaultBranch,
7064
+ description: 'Use the default branch for target repo as the target branch name'
7065
+ }] : []), {
7066
+ name: 'No',
7067
+ value: '',
7068
+ description: 'Do not use the current git branch as name (will end in a no-op)'
7069
+ }].filter(Boolean)
7070
+ });
7071
+ if (proceed) {
7072
+ return proceed;
7073
+ }
6719
7074
  }
6720
- spinner.successAndStop('Scan created successfully');
6721
- const link = colors.underline(colors.cyan(`${result.data.html_report_url}`));
6722
- logger.logger.log(`Available at: ${link}`);
6723
- const rl = readline.createInterface({
6724
- input: process$1.stdin,
6725
- output: process$1.stdout
7075
+ }
7076
+
7077
+ async function suggestTarget() {
7078
+ // We could prefill this with sub-dirs of the current
7079
+ // dir ... but is that going to be useful?
7080
+ const proceed = await prompts.select({
7081
+ message: 'No TARGET given. Do you want to use the current directory?',
7082
+ choices: [{
7083
+ name: 'Yes',
7084
+ value: true,
7085
+ description: 'Target the current directory'
7086
+ }, {
7087
+ name: 'No',
7088
+ value: false,
7089
+ description: 'Do not use the current directory (this will end in a no-op)'
7090
+ }]
6726
7091
  });
6727
- const answer = await rl.question('Would you like to open it in your browser? (y/n)');
6728
- if (answer.toLowerCase() === 'y') {
6729
- await vendor.open(`${result.data.html_report_url}`);
7092
+ if (proceed) {
7093
+ return ['.'];
6730
7094
  }
6731
- rl.close();
6732
7095
  }
6733
7096
 
6734
7097
  const {
@@ -6852,18 +7215,66 @@ async function run$7(argv, importMeta, {
6852
7215
  importMeta,
6853
7216
  parentName
6854
7217
  });
6855
- const [orgSlug = '', ...targets] = cli.input;
6856
- const cwd = cli.flags['cwd'] && cli.flags['cwd'] !== 'process.cwd()' ? String(cli.flags['cwd']) : process$1.cwd();
6857
7218
  const {
7219
+ cwd: cwdOverride,
7220
+ dryRun
7221
+ } = cli.flags;
7222
+ const cwd = cwdOverride && cwdOverride !== 'process.cwd()' ? String(cwdOverride) : process$1.cwd();
7223
+ let {
6858
7224
  branch: branchName,
6859
7225
  repo: repoName
6860
7226
  } = cli.flags;
6861
- const apiToken = shadowNpmInject.getDefaultToken(); // This checks if we _can_ suggest anything
7227
+ let [orgSlug = '', ...targets] = cli.input;
6862
7228
 
6863
- if (!apiToken && (!orgSlug || !repoName || !branchName || !targets.length)) {
6864
- // Without api token we cannot recover because we can't request more info
6865
- // from the server, to match and help with the current cwd/git status.
6866
- //
7229
+ // We're going to need an api token to suggest data because those suggestions
7230
+ // must come from data we already know. Don't error on missing api token yet.
7231
+ // If the api-token is not set, ignore it for the sake of suggestions.
7232
+ const apiToken = shadowNpmInject.getDefaultToken();
7233
+
7234
+ // If we updated any inputs then we should print the command line to repeat
7235
+ // the command without requiring user input, as a suggestion.
7236
+ let updatedInput = false;
7237
+ if (!targets.length && !dryRun) {
7238
+ const received = await suggestTarget();
7239
+ targets = received ?? [];
7240
+ updatedInput = true;
7241
+ }
7242
+
7243
+ // If the current cwd is unknown and is used as a repo slug anyways, we will
7244
+ // first need to register the slug before we can use it.
7245
+ let repoDefaultBranch = '';
7246
+ // Only do suggestions with an apiToken and when not in dryRun mode
7247
+ if (apiToken && !dryRun) {
7248
+ if (!orgSlug) {
7249
+ const suggestion = await suggestOrgSlug();
7250
+ if (suggestion) orgSlug = suggestion;
7251
+ updatedInput = true;
7252
+ }
7253
+
7254
+ // (Don't bother asking for the rest if we didn't get an org slug above)
7255
+ if (orgSlug && !repoName) {
7256
+ const suggestion = await suggestRepoSlug(orgSlug);
7257
+ if (suggestion) {
7258
+ repoDefaultBranch = suggestion.defaultBranch;
7259
+ repoName = suggestion.slug;
7260
+ }
7261
+ updatedInput = true;
7262
+ }
7263
+
7264
+ // (Don't bother asking for the rest if we didn't get an org/repo above)
7265
+ if (orgSlug && repoName && !branchName) {
7266
+ const suggestion = await suggestBranchSlug(repoDefaultBranch);
7267
+ if (suggestion) branchName = suggestion;
7268
+ updatedInput = true;
7269
+ }
7270
+ }
7271
+ if (updatedInput && repoName && branchName && orgSlug && targets?.length) {
7272
+ logger.logger.error('Note: You can invoke this command next time to skip the interactive questions:');
7273
+ logger.logger.error('```');
7274
+ logger.logger.error(` socket scan create [other flags...] --repo ${repoName} --branch ${branchName} ${orgSlug} ${targets.join(' ')}`);
7275
+ logger.logger.error('```\n');
7276
+ }
7277
+ if (!orgSlug || !repoName || !branchName || !targets.length) {
6867
7278
  // Use exit status of 2 to indicate incorrect usage, generally invalid
6868
7279
  // options or missing arguments.
6869
7280
  // https://www.gnu.org/software/bash/manual/html_node/Exit-Status.html
@@ -6877,28 +7288,25 @@ async function run$7(argv, importMeta, {
6877
7288
 
6878
7289
  - Branch name using --branch ${!branchName ? colors.red('(missing!)') : colors.green('(ok)')}
6879
7290
 
6880
- - At least one TARGET (e.g. \`.\` or \`./package.json\`) ${!targets.length ? '(missing)' : colors.green('(ok)')}
7291
+ - At least one TARGET (e.g. \`.\` or \`./package.json\`) ${!targets.length ? colors.red('(missing)') : colors.green('(ok)')}
6881
7292
 
6882
- (Additionally, no API Token was set so we cannot auto-discover these details)
7293
+ ${!apiToken ? 'Note: was unable to make suggestions because no API Token was found; this would make the command fail regardless' : ''}
6883
7294
  `);
6884
7295
  return;
6885
7296
  }
6886
7297
 
6887
7298
  // Note exiting earlier to skirt a hidden auth requirement
6888
- if (cli.flags['dryRun']) {
7299
+ if (dryRun) {
6889
7300
  logger.logger.log(DRY_RUN_BAIL_TEXT$7);
6890
7301
  return;
6891
7302
  }
6892
- await createFullScan({
7303
+ await handleCreateNewScan({
6893
7304
  branchName: branchName,
6894
- commitHash: cli.flags['commitHash'] ?? '',
6895
7305
  commitMessage: cli.flags['commitMessage'] ?? '',
6896
- committers: cli.flags['committers'] ?? '',
6897
7306
  cwd,
6898
7307
  defaultBranch: Boolean(cli.flags['defaultBranch']),
6899
7308
  orgSlug,
6900
7309
  pendingHead: Boolean(cli.flags['pendingHead']),
6901
- pullRequest: cli.flags['pullRequest'] ?? undefined,
6902
7310
  readOnly: Boolean(cli.flags['readOnly']),
6903
7311
  repoName: repoName,
6904
7312
  targets,
@@ -6906,26 +7314,37 @@ async function run$7(argv, importMeta, {
6906
7314
  });
6907
7315
  }
6908
7316
 
6909
- async function deleteOrgFullScan(orgSlug, fullScanId) {
7317
+ async function fetchDeleteOrgFullScan(orgSlug, scanId) {
6910
7318
  const apiToken = shadowNpmInject.getDefaultToken();
6911
7319
  if (!apiToken) {
6912
7320
  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.');
6913
7321
  }
6914
- await deleteOrgFullScanWithToken(orgSlug, fullScanId, apiToken);
7322
+ await fetchDeleteOrgFullScanWithToken(apiToken, orgSlug, scanId);
6915
7323
  }
6916
- async function deleteOrgFullScanWithToken(orgSlug, fullScanId, apiToken) {
7324
+ async function fetchDeleteOrgFullScanWithToken(apiToken, orgSlug, scanId) {
6917
7325
  // Lazily access constants.spinner.
6918
7326
  const {
6919
7327
  spinner
6920
7328
  } = constants;
6921
- spinner.start('Deleting scan...');
6922
- const socketSdk = await shadowNpmInject.setupSdk(apiToken);
6923
- const result = await handleApiCall(socketSdk.deleteOrgFullScan(orgSlug, fullScanId), 'Deleting scan');
7329
+ const sockSdk = await shadowNpmInject.setupSdk(apiToken);
7330
+ spinner.start('Requesting the scan to be deleted...');
7331
+ const result = await handleApiCall(sockSdk.deleteOrgFullScan(orgSlug, scanId), 'Deleting scan');
7332
+ spinner.successAndStop('Received response for deleting a scan.');
6924
7333
  if (!result.success) {
6925
7334
  handleUnsuccessfulApiResponse('deleteOrgFullScan', result);
6926
7335
  return;
6927
7336
  }
6928
- spinner.successAndStop('Scan deleted successfully');
7337
+ return result.data;
7338
+ }
7339
+
7340
+ async function outputDeleteScan(_data) {
7341
+ logger.logger.success('Scan deleted successfully');
7342
+ }
7343
+
7344
+ async function handleDeleteScan(orgSlug, scanId) {
7345
+ const data = await fetchDeleteOrgFullScan(orgSlug, scanId);
7346
+ if (!data) return;
7347
+ await outputDeleteScan();
6929
7348
  }
6930
7349
 
6931
7350
  const {
@@ -6964,8 +7383,8 @@ async function run$6(argv, importMeta, {
6964
7383
  importMeta,
6965
7384
  parentName
6966
7385
  });
6967
- const [orgSlug = '', fullScanId = ''] = cli.input;
6968
- if (!orgSlug || !fullScanId) {
7386
+ const [orgSlug = '', scanId = ''] = cli.input;
7387
+ if (!orgSlug || !scanId) {
6969
7388
  // Use exit status of 2 to indicate incorrect usage, generally invalid
6970
7389
  // options or missing arguments.
6971
7390
  // https://www.gnu.org/software/bash/manual/html_node/Exit-Status.html
@@ -6974,22 +7393,20 @@ async function run$6(argv, importMeta, {
6974
7393
 
6975
7394
  - Org name as the first argument ${!orgSlug ? colors.red('(missing!)') : colors.green('(ok)')}
6976
7395
 
6977
- - Full Scan ID to delete as second argument ${!fullScanId ? colors.red('(missing!)') : colors.green('(ok)')}`);
7396
+ - Full Scan ID to delete as second argument ${!scanId ? colors.red('(missing!)') : colors.green('(ok)')}`);
6978
7397
  return;
6979
7398
  }
6980
7399
  if (cli.flags['dryRun']) {
6981
7400
  logger.logger.log(DRY_RUN_BAIL_TEXT$6);
6982
7401
  return;
6983
7402
  }
6984
- await deleteOrgFullScan(orgSlug, fullScanId);
7403
+ await handleDeleteScan(orgSlug, scanId);
6985
7404
  }
6986
7405
 
6987
- // @ts-ignore
6988
- async function listFullScans({
7406
+ async function fetchListScans({
6989
7407
  direction,
6990
7408
  from_time,
6991
7409
  orgSlug,
6992
- outputKind,
6993
7410
  page,
6994
7411
  per_page,
6995
7412
  sort
@@ -6998,23 +7415,19 @@ async function listFullScans({
6998
7415
  if (!apiToken) {
6999
7416
  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.');
7000
7417
  }
7001
- await listFullScansWithToken({
7002
- apiToken,
7418
+ await fetchListScansWithToken(apiToken, {
7003
7419
  direction,
7004
7420
  from_time,
7005
7421
  orgSlug,
7006
- outputKind,
7007
7422
  page,
7008
7423
  per_page,
7009
7424
  sort
7010
7425
  });
7011
7426
  }
7012
- async function listFullScansWithToken({
7013
- apiToken,
7427
+ async function fetchListScansWithToken(apiToken, {
7014
7428
  direction,
7015
7429
  from_time,
7016
7430
  orgSlug,
7017
- outputKind,
7018
7431
  page,
7019
7432
  per_page,
7020
7433
  sort
@@ -7023,22 +7436,27 @@ async function listFullScansWithToken({
7023
7436
  const {
7024
7437
  spinner
7025
7438
  } = constants;
7439
+ const sockSdk = await shadowNpmInject.setupSdk(apiToken);
7026
7440
  spinner.start('Fetching list of scans...');
7027
- const socketSdk = await shadowNpmInject.setupSdk(apiToken);
7028
- const result = await handleApiCall(socketSdk.getOrgFullScanList(orgSlug, {
7441
+ const result = await handleApiCall(sockSdk.getOrgFullScanList(orgSlug, {
7029
7442
  sort,
7030
7443
  direction,
7031
7444
  per_page: String(per_page),
7032
7445
  page: String(page),
7033
7446
  from: from_time
7034
7447
  }), 'Listing scans');
7448
+ spinner.successAndStop(`Received response for list of scans.`);
7035
7449
  if (!result.success) {
7036
7450
  handleUnsuccessfulApiResponse('getOrgFullScanList', result);
7037
7451
  return;
7038
7452
  }
7039
- spinner.stop(`Fetch complete`);
7453
+ return result.data;
7454
+ }
7455
+
7456
+ // @ts-ignore
7457
+ async function outputListScans(data, outputKind) {
7040
7458
  if (outputKind === 'json') {
7041
- logger.logger.log(result.data);
7459
+ logger.logger.log(data);
7042
7460
  return;
7043
7461
  }
7044
7462
  const options = {
@@ -7056,7 +7474,7 @@ async function listFullScansWithToken({
7056
7474
  name: colors.magenta('Created at')
7057
7475
  }]
7058
7476
  };
7059
- const formattedResults = result.data.results.map(d => {
7477
+ const formattedResults = data.results.map(d => {
7060
7478
  return {
7061
7479
  id: d.id,
7062
7480
  report_url: colors.underline(`${d.html_report_url}`),
@@ -7071,6 +7489,27 @@ async function listFullScansWithToken({
7071
7489
  logger.logger.log(chalkTable(options, formattedResults));
7072
7490
  }
7073
7491
 
7492
+ async function handleListScans({
7493
+ direction,
7494
+ from_time,
7495
+ orgSlug,
7496
+ outputKind,
7497
+ page,
7498
+ per_page,
7499
+ sort
7500
+ }) {
7501
+ const data = await fetchListScans({
7502
+ direction,
7503
+ from_time,
7504
+ orgSlug,
7505
+ page,
7506
+ per_page,
7507
+ sort
7508
+ });
7509
+ if (!data) return;
7510
+ await outputListScans(data, outputKind);
7511
+ }
7512
+
7074
7513
  const {
7075
7514
  DRY_RUN_BAIL_TEXT: DRY_RUN_BAIL_TEXT$5
7076
7515
  } = constants;
@@ -7158,7 +7597,7 @@ async function run$5(argv, importMeta, {
7158
7597
  logger.logger.log(DRY_RUN_BAIL_TEXT$5);
7159
7598
  return;
7160
7599
  }
7161
- await listFullScans({
7600
+ await handleListScans({
7162
7601
  direction: String(cli.flags['direction'] || ''),
7163
7602
  from_time: String(cli.flags['fromTime'] || ''),
7164
7603
  orgSlug,
@@ -7169,46 +7608,56 @@ async function run$5(argv, importMeta, {
7169
7608
  });
7170
7609
  }
7171
7610
 
7172
- async function getOrgScanMetadata(orgSlug, scanId, outputKind) {
7611
+ async function fetchScanMetadata(orgSlug, scanId) {
7173
7612
  const apiToken = shadowNpmInject.getDefaultToken();
7174
7613
  if (!apiToken) {
7175
7614
  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.');
7176
7615
  }
7177
- await getOrgScanMetadataWithToken(orgSlug, scanId, apiToken, outputKind);
7616
+ await fetchScanMetadataWithToken(apiToken, orgSlug, scanId);
7178
7617
  }
7179
- async function getOrgScanMetadataWithToken(orgSlug, scanId, apiToken, outputKind) {
7618
+ async function fetchScanMetadataWithToken(apiToken, orgSlug, scanId) {
7180
7619
  // Lazily access constants.spinner.
7181
7620
  const {
7182
7621
  spinner
7183
7622
  } = constants;
7623
+ const sockSdk = await shadowNpmInject.setupSdk(apiToken);
7184
7624
  spinner.start('Fetching meta data for a full scan...');
7185
- const socketSdk = await shadowNpmInject.setupSdk(apiToken);
7186
- const result = await handleApiCall(socketSdk.getOrgFullScanMetadata(orgSlug, scanId), 'Listing scans');
7625
+ const result = await handleApiCall(sockSdk.getOrgFullScanMetadata(orgSlug, scanId), 'Listing scans');
7626
+ spinner.successAndStop('Received response for scan meta data.');
7187
7627
  if (!result.success) {
7188
7628
  handleUnsuccessfulApiResponse('getOrgFullScanMetadata', result);
7189
7629
  return;
7190
7630
  }
7191
- spinner?.successAndStop('Fetched the meta data\n');
7631
+ return result.data;
7632
+ }
7633
+
7634
+ async function outputScanMetadata(data, scanId, outputKind) {
7192
7635
  if (outputKind === 'json') {
7193
- logger.logger.log(result.data);
7636
+ logger.logger.log(data);
7194
7637
  } else {
7195
7638
  // Markdown = print
7196
7639
  if (outputKind === 'markdown') {
7197
7640
  logger.logger.log('# Scan meta data\n');
7198
7641
  }
7199
7642
  logger.logger.log(`Scan ID: ${scanId}\n`);
7200
- for (const [key, value] of Object.entries(result.data)) {
7643
+ for (const [key, value] of Object.entries(data)) {
7201
7644
  if (['id', 'updated_at', 'organization_id', 'repository_id', 'commit_hash', 'html_report_url'].includes(key)) continue;
7202
7645
  logger.logger.log(`- ${key}:`, value);
7203
7646
  }
7204
7647
  if (outputKind === 'markdown') {
7205
- logger.logger.log(`\nYou can view this report at: [${result.data.html_report_url}](${result.data.html_report_url})\n`);
7648
+ logger.logger.log(`\nYou can view this report at: [${data.html_report_url}](${data.html_report_url})\n`);
7206
7649
  } else {
7207
- logger.logger.log(`\nYou can view this report at: ${result.data.html_report_url}]\n`);
7650
+ logger.logger.log(`\nYou can view this report at: ${data.html_report_url}]\n`);
7208
7651
  }
7209
7652
  }
7210
7653
  }
7211
7654
 
7655
+ async function handleOrgScanMetadata(orgSlug, scanId, outputKind) {
7656
+ const data = await fetchScanMetadata(orgSlug, scanId);
7657
+ if (!data) return;
7658
+ await outputScanMetadata(data, scanId, outputKind);
7659
+ }
7660
+
7212
7661
  const {
7213
7662
  DRY_RUN_BAIL_TEXT: DRY_RUN_BAIL_TEXT$4
7214
7663
  } = constants;
@@ -7245,8 +7694,8 @@ async function run$4(argv, importMeta, {
7245
7694
  importMeta,
7246
7695
  parentName
7247
7696
  });
7248
- const [orgSlug = '', fullScanId = ''] = cli.input;
7249
- if (!orgSlug || !fullScanId) {
7697
+ const [orgSlug = '', scanId = ''] = cli.input;
7698
+ if (!orgSlug || !scanId) {
7250
7699
  // Use exit status of 2 to indicate incorrect usage, generally invalid
7251
7700
  // options or missing arguments.
7252
7701
  // https://www.gnu.org/software/bash/manual/html_node/Exit-Status.html
@@ -7255,14 +7704,14 @@ async function run$4(argv, importMeta, {
7255
7704
 
7256
7705
  - Org name as the first argument ${!orgSlug ? colors.red('(missing!)') : colors.green('(ok)')}
7257
7706
 
7258
- - Full Scan ID to inspect as second argument ${!fullScanId ? colors.red('(missing!)') : colors.green('(ok)')}`);
7707
+ - Full Scan ID to inspect as second argument ${!scanId ? colors.red('(missing!)') : colors.green('(ok)')}`);
7259
7708
  return;
7260
7709
  }
7261
7710
  if (cli.flags['dryRun']) {
7262
7711
  logger.logger.log(DRY_RUN_BAIL_TEXT$4);
7263
7712
  return;
7264
7713
  }
7265
- await getOrgScanMetadata(orgSlug, fullScanId, cli.flags['json'] ? 'json' : cli.flags['markdown'] ? 'markdown' : 'print');
7714
+ await handleOrgScanMetadata(orgSlug, scanId, cli.flags['json'] ? 'json' : cli.flags['markdown'] ? 'markdown' : 'print');
7266
7715
  }
7267
7716
 
7268
7717
  /**
@@ -7270,7 +7719,7 @@ async function run$4(argv, importMeta, {
7270
7719
  * full scan ID.
7271
7720
  * It can optionally only fetch the security or license side of things.
7272
7721
  */
7273
- async function fetchReportData(orgSlug, fullScanId,
7722
+ async function fetchReportData(orgSlug, scanId,
7274
7723
  // includeLicensePolicy: boolean,
7275
7724
  includeSecurityPolicy) {
7276
7725
  let haveScan = false;
@@ -7307,18 +7756,18 @@ includeSecurityPolicy) {
7307
7756
  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.');
7308
7757
  }
7309
7758
  updateProgress();
7310
- const socketSdk = await shadowNpmInject.setupSdk(apiToken);
7759
+ const sockSdk = await shadowNpmInject.setupSdk(apiToken);
7311
7760
 
7312
7761
  // @ts-ignore
7313
7762
  const [scan,
7314
7763
  // licensePolicyMaybe,
7315
7764
  securityPolicyMaybe] = await Promise.all([(async () => {
7316
7765
  try {
7317
- const response = await queryAPI(`orgs/${orgSlug}/full-scans/${encodeURIComponent(fullScanId)}`, apiToken);
7766
+ const response = await queryApi(`orgs/${orgSlug}/full-scans/${encodeURIComponent(scanId)}`, apiToken);
7318
7767
  haveScan = true;
7319
7768
  updateProgress();
7320
7769
  if (!response.ok) {
7321
- const err = await handleAPIError(response.status);
7770
+ const err = await handleApiError(response.status);
7322
7771
  logger.logger.fail(`${colors.bgRed(colors.white(response.statusText))}: Fetch error: ${err}`);
7323
7772
  return undefined;
7324
7773
  }
@@ -7340,7 +7789,7 @@ includeSecurityPolicy) {
7340
7789
  })(),
7341
7790
  // includeLicensePolicy &&
7342
7791
  // (async () => {
7343
- // const r = await socketSdk.getOrgSecurityPolicy(orgSlug)
7792
+ // const r = await sockSdk.getOrgSecurityPolicy(orgSlug)
7344
7793
  // haveLicensePolicy = true
7345
7794
  // updateProgress()
7346
7795
  // return await handleApiCall(
@@ -7349,7 +7798,7 @@ includeSecurityPolicy) {
7349
7798
  // )
7350
7799
  // })(),
7351
7800
  includeSecurityPolicy && (async () => {
7352
- const r = await socketSdk.getOrgSecurityPolicy(orgSlug);
7801
+ const r = await sockSdk.getOrgSecurityPolicy(orgSlug);
7353
7802
  haveSecurityPolicy = true;
7354
7803
  updateProgress();
7355
7804
  return await handleApiCall(r, "looking up organization's security policy");
@@ -7595,40 +8044,31 @@ function* walkNestedMap(map, keys = []) {
7595
8044
  }
7596
8045
  }
7597
8046
 
7598
- async function reportFullScan({
8047
+ async function outputScanReport(scan,
8048
+ // licensePolicy: undefined | SocketSdkReturnType<'getOrgSecurityPolicy'>,
8049
+ securityPolicy, {
7599
8050
  filePath,
7600
8051
  fold,
7601
- fullScanId,
7602
8052
  includeLicensePolicy,
7603
8053
  includeSecurityPolicy,
7604
8054
  orgSlug,
7605
8055
  outputKind,
7606
8056
  reportLevel,
8057
+ scanId,
7607
8058
  short
7608
8059
  }) {
7609
- logger.logger.error('output:', outputKind, ', file:', filePath, ', fold:', fold, ', reportLevel:', reportLevel);
7610
8060
  if (!includeSecurityPolicy) {
8061
+ process.exitCode = 1;
7611
8062
  return; // caller should assert
7612
8063
  }
7613
- const {
7614
- // licensePolicy,
7615
- ok,
7616
- scan,
7617
- securityPolicy
7618
- } = await fetchReportData(orgSlug, fullScanId,
7619
- // includeLicensePolicy
7620
- includeSecurityPolicy);
7621
- if (!ok) {
7622
- return;
7623
- }
7624
8064
  const scanReport = generateReport(scan, undefined,
7625
8065
  // licensePolicy,
7626
8066
  securityPolicy, {
7627
8067
  orgSlug,
7628
- scanId: fullScanId,
8068
+ scanId,
7629
8069
  fold,
7630
- short,
7631
- reportLevel
8070
+ reportLevel,
8071
+ short
7632
8072
  });
7633
8073
  if (!scanReport.healthy) {
7634
8074
  process.exitCode = 1;
@@ -7715,6 +8155,43 @@ ${!report.alerts.size ? '' : mdTable(flatData, ['Policy', 'Alert Type', 'Package
7715
8155
  return md;
7716
8156
  }
7717
8157
 
8158
+ async function handleScanReport({
8159
+ filePath,
8160
+ fold,
8161
+ includeLicensePolicy,
8162
+ includeSecurityPolicy,
8163
+ orgSlug,
8164
+ outputKind,
8165
+ reportLevel,
8166
+ scanId,
8167
+ short
8168
+ }) {
8169
+ if (!includeSecurityPolicy) {
8170
+ process.exitCode = 1;
8171
+ return; // caller should assert
8172
+ }
8173
+ const {
8174
+ // licensePolicy,
8175
+ ok,
8176
+ scan,
8177
+ securityPolicy
8178
+ } = await fetchReportData(orgSlug, scanId,
8179
+ // includeLicensePolicy
8180
+ includeSecurityPolicy);
8181
+ if (!ok) return;
8182
+ await outputScanReport(scan, securityPolicy, {
8183
+ filePath,
8184
+ fold,
8185
+ scanId: scanId,
8186
+ includeLicensePolicy,
8187
+ includeSecurityPolicy,
8188
+ orgSlug,
8189
+ outputKind,
8190
+ reportLevel,
8191
+ short
8192
+ });
8193
+ }
8194
+
7718
8195
  const {
7719
8196
  DRY_RUN_BAIL_TEXT: DRY_RUN_BAIL_TEXT$3
7720
8197
  } = constants;
@@ -7801,8 +8278,8 @@ async function run$3(argv, importMeta, {
7801
8278
  reportLevel = 'warn',
7802
8279
  security
7803
8280
  } = cli.flags;
7804
- const [orgSlug = '', fullScanId = '', file = '-'] = cli.input;
7805
- if (!orgSlug || !fullScanId ||
8281
+ const [orgSlug = '', scanId = '', file = '-'] = cli.input;
8282
+ if (!orgSlug || !scanId ||
7806
8283
  // (!license && !security) ||
7807
8284
  json && markdown) {
7808
8285
  // Use exit status of 2 to indicate incorrect usage, generally invalid
@@ -7814,7 +8291,7 @@ async function run$3(argv, importMeta, {
7814
8291
 
7815
8292
  - Org name as the first argument ${!orgSlug ? colors.red('(missing!)') : colors.green('(ok)')}
7816
8293
 
7817
- - Full Scan ID to fetch as second argument ${!fullScanId ? colors.red('(missing!)') : colors.green('(ok)')}
8294
+ - Full Scan ID to fetch as second argument ${!scanId ? colors.red('(missing!)') : colors.green('(ok)')}
7818
8295
 
7819
8296
  - Not both the --json and --markdown flags ${json && markdown ? colors.red('(pick one!)') : colors.green('(ok)')}
7820
8297
  `
@@ -7826,9 +8303,9 @@ async function run$3(argv, importMeta, {
7826
8303
  logger.logger.log(DRY_RUN_BAIL_TEXT$3);
7827
8304
  return;
7828
8305
  }
7829
- await reportFullScan({
8306
+ await handleScanReport({
7830
8307
  orgSlug,
7831
- fullScanId,
8308
+ scanId: scanId,
7832
8309
  includeLicensePolicy: false,
7833
8310
  // !!license,
7834
8311
  includeSecurityPolicy: typeof security === 'boolean' ? security : true,
@@ -7840,29 +8317,7 @@ async function run$3(argv, importMeta, {
7840
8317
  });
7841
8318
  }
7842
8319
 
7843
- async function streamFullScan(orgSlug, fullScanId, file) {
7844
- // Lazily access constants.spinner.
7845
- const {
7846
- spinner
7847
- } = constants;
7848
- const apiToken = shadowNpmInject.getDefaultToken();
7849
- if (!apiToken) {
7850
- 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.');
7851
- }
7852
- spinner.start('Fetching scan...');
7853
- const socketSdk = await shadowNpmInject.setupSdk(apiToken);
7854
- const data = await handleApiCall(socketSdk.getOrgFullScan(orgSlug, fullScanId, file === '-' ? undefined : file), 'Fetching a scan');
7855
- if (!data?.success) {
7856
- handleUnsuccessfulApiResponse('getOrgFullScan', data);
7857
- return;
7858
- }
7859
- spinner?.successAndStop(file ? `Full scan details written to ${file}` : 'stdout');
7860
- return data;
7861
- }
7862
-
7863
- async function viewFullScan(orgSlug, fullScanId, filePath) {
7864
- const artifacts = await getFullScan(orgSlug, fullScanId);
7865
- if (!artifacts) return;
8320
+ async function outputScanView(artifacts, orgSlug, scanId, filePath) {
7866
8321
  const display = artifacts.map(art => {
7867
8322
  const author = Array.isArray(art.author) ? `${art.author[0]}${art.author.length > 1 ? ' et.al.' : ''}` : art.author;
7868
8323
  return {
@@ -7879,11 +8334,11 @@ async function viewFullScan(orgSlug, fullScanId, filePath) {
7879
8334
 
7880
8335
  These are the artifacts and their scores found.
7881
8336
 
7882
- Sscan ID: ${fullScanId}
8337
+ Scan ID: ${scanId}
7883
8338
 
7884
8339
  ${md}
7885
8340
 
7886
- View this report at: https://socket.dev/dashboard/org/${orgSlug}/sbom/${fullScanId}
8341
+ View this report at: https://socket.dev/dashboard/org/${orgSlug}/sbom/${scanId}
7887
8342
  `.trim() + '\n';
7888
8343
  if (filePath && filePath !== '-') {
7889
8344
  try {
@@ -7899,6 +8354,32 @@ View this report at: https://socket.dev/dashboard/org/${orgSlug}/sbom/${fullScan
7899
8354
  }
7900
8355
  }
7901
8356
 
8357
+ async function handleScanView(orgSlug, scanId, filePath) {
8358
+ const data = await fetchScan(orgSlug, scanId);
8359
+ if (!data) return;
8360
+ await outputScanView(data, orgSlug, scanId, filePath);
8361
+ }
8362
+
8363
+ async function streamScan(orgSlug, scanId, file) {
8364
+ // Lazily access constants.spinner.
8365
+ const {
8366
+ spinner
8367
+ } = constants;
8368
+ const apiToken = shadowNpmInject.getDefaultToken();
8369
+ if (!apiToken) {
8370
+ 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.');
8371
+ }
8372
+ const sockSdk = await shadowNpmInject.setupSdk(apiToken);
8373
+ spinner.start('Fetching scan...');
8374
+ const data = await handleApiCall(sockSdk.getOrgFullScan(orgSlug, scanId, file === '-' ? undefined : file), 'Fetching a scan');
8375
+ spinner?.successAndStop(file ? `Full scan details written to ${file}` : 'stdout');
8376
+ if (!data?.success) {
8377
+ handleUnsuccessfulApiResponse('getOrgFullScan', data);
8378
+ return;
8379
+ }
8380
+ return data;
8381
+ }
8382
+
7902
8383
  const {
7903
8384
  DRY_RUN_BAIL_TEXT: DRY_RUN_BAIL_TEXT$2
7904
8385
  } = constants;
@@ -7937,8 +8418,8 @@ async function run$2(argv, importMeta, {
7937
8418
  importMeta,
7938
8419
  parentName
7939
8420
  });
7940
- const [orgSlug = '', fullScanId = '', file = '-'] = cli.input;
7941
- if (!orgSlug || !fullScanId) {
8421
+ const [orgSlug = '', scanId = '', file = '-'] = cli.input;
8422
+ if (!orgSlug || !scanId) {
7942
8423
  // Use exit status of 2 to indicate incorrect usage, generally invalid
7943
8424
  // options or missing arguments.
7944
8425
  // https://www.gnu.org/software/bash/manual/html_node/Exit-Status.html
@@ -7948,7 +8429,7 @@ async function run$2(argv, importMeta, {
7948
8429
 
7949
8430
  - Org name as the first argument ${!orgSlug ? colors.red('(missing!)') : colors.green('(ok)')}
7950
8431
 
7951
- - Full Scan ID to fetch as second argument ${!fullScanId ? colors.red('(missing!)') : colors.green('(ok)')}
8432
+ - Full Scan ID to fetch as second argument ${!scanId ? colors.red('(missing!)') : colors.green('(ok)')}
7952
8433
  `);
7953
8434
  return;
7954
8435
  }
@@ -7957,9 +8438,9 @@ async function run$2(argv, importMeta, {
7957
8438
  return;
7958
8439
  }
7959
8440
  if (cli.flags['json']) {
7960
- await streamFullScan(orgSlug, fullScanId, file);
8441
+ await streamScan(orgSlug, scanId, file);
7961
8442
  } else {
7962
- await viewFullScan(orgSlug, fullScanId, file);
8443
+ await handleScanView(orgSlug, scanId, file);
7963
8444
  }
7964
8445
  }
7965
8446
 
@@ -8032,7 +8513,7 @@ async function getThreatFeedWithToken({
8032
8513
  } = constants;
8033
8514
  const queryParams = new URLSearchParams([['direction', direction], ['ecosystem', ecosystem], ['filter', filter], ['page', page], ['per_page', String(perPage)]]);
8034
8515
  spinner.start('Fetching Threat Feed data...');
8035
- const response = await queryAPI(`threat-feed?${queryParams}`, apiToken);
8516
+ const response = await queryApi(`threat-feed?${queryParams}`, apiToken);
8036
8517
  const data = await response.json();
8037
8518
  spinner.stop('Threat feed data fetched');
8038
8519
  if (outputKind === 'json') {
@@ -8455,12 +8936,13 @@ void (async () => {
8455
8936
  await vendor.updater({
8456
8937
  name: SOCKET_CLI_BIN_NAME,
8457
8938
  // The '@rollup/plugin-replace' will replace "process.env['INLINED_SOCKET_CLI_VERSION']".
8458
- version: "0.14.65",
8939
+ version: "0.14.67",
8459
8940
  ttl: 86_400_000 /* 24 hours in milliseconds */
8460
8941
  });
8461
8942
  try {
8462
8943
  await meowWithSubcommands({
8463
8944
  cdxgen: cmdCdxgen,
8945
+ config: cmdConfig,
8464
8946
  fix: cmdFix,
8465
8947
  info: cmdInfo,
8466
8948
  login: cmdLogin,
@@ -8522,5 +9004,5 @@ void (async () => {
8522
9004
  await shadowNpmInject.captureException(e);
8523
9005
  }
8524
9006
  })();
8525
- //# debugId=765ca9f4-3784-4e50-beb4-36197117fbea
9007
+ //# debugId=199d20b5-2692-44b6-b880-34650eeaae46
8526
9008
  //# sourceMappingURL=cli.js.map