@socketsecurity/cli-with-sentry 0.14.65 → 0.14.67

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