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