@socketsecurity/cli-with-sentry 0.14.66 → 0.14.67

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