@socketsecurity/cli-with-sentry 0.14.56 → 0.14.58

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.
Files changed (39) hide show
  1. package/bin/cli.js +10 -10
  2. package/bin/npm-cli.js +1 -1
  3. package/bin/npx-cli.js +3 -1
  4. package/dist/constants.d.ts +20 -8
  5. package/dist/constants.js +54 -25
  6. package/dist/constants.js.map +1 -1
  7. package/dist/instrument-with-sentry.js +3 -3
  8. package/dist/instrument-with-sentry.js.map +1 -1
  9. package/dist/module-sync/artifact.d.ts +75 -0
  10. package/dist/module-sync/cli.js +1372 -1062
  11. package/dist/module-sync/cli.js.map +1 -1
  12. package/dist/module-sync/edge.d.ts +1 -1
  13. package/dist/module-sync/index.d.ts +5 -173
  14. package/dist/module-sync/node.d.ts +1 -1
  15. package/dist/module-sync/override-set.d.ts +37 -0
  16. package/dist/module-sync/shadow-bin.js +10 -8
  17. package/dist/module-sync/shadow-bin.js.map +1 -1
  18. package/dist/module-sync/{index.js → shadow-npm-inject.js} +1436 -1302
  19. package/dist/module-sync/shadow-npm-inject.js.map +1 -0
  20. package/dist/module-sync/{npm-paths.js → shadow-npm-paths.js} +4 -4
  21. package/dist/module-sync/shadow-npm-paths.js.map +1 -0
  22. package/dist/module-sync/socket-package-alert.d.ts +46 -0
  23. package/dist/module-sync/types.d.ts +11 -3
  24. package/dist/require/cli.js +1372 -1062
  25. package/dist/require/cli.js.map +1 -1
  26. package/dist/require/shadow-npm-inject.js +3 -0
  27. package/dist/require/shadow-npm-paths.js +3 -0
  28. package/package.json +14 -11
  29. package/dist/module-sync/index.js.map +0 -1
  30. package/dist/module-sync/npm-injection.js +0 -26
  31. package/dist/module-sync/npm-injection.js.map +0 -1
  32. package/dist/module-sync/npm-paths.js.map +0 -1
  33. package/dist/module-sync/proc-log.d.ts +0 -3
  34. package/dist/module-sync/reify.d.ts +0 -1020
  35. package/dist/require/index.js +0 -3
  36. package/dist/require/npm-injection.js +0 -3
  37. package/dist/require/npm-paths.js +0 -3
  38. /package/dist/module-sync/{npm-injection.d.ts → shadow-npm-inject.d.ts} +0 -0
  39. /package/dist/module-sync/{npm-paths.d.ts → shadow-npm-paths.d.ts} +0 -0
@@ -23,9 +23,10 @@ var events = require('node:events');
23
23
  var fs = require('node:fs');
24
24
  var path = require('node:path');
25
25
  var ndjson = _socketInterop(require('ndjson'));
26
- var index = require('./index.js');
26
+ var shadowNpmInject = require('./shadow-npm-inject.js');
27
27
  var constants = require('./constants.js');
28
28
  var objects = require('@socketsecurity/registry/lib/objects');
29
+ var path$1 = require('@socketsecurity/registry/lib/path');
29
30
  var regexps = require('@socketsecurity/registry/lib/regexps');
30
31
  var commonTags = _socketInterop(require('common-tags'));
31
32
  var fs$1 = require('node:fs/promises');
@@ -40,26 +41,29 @@ var require$$0$1 = require('node:util');
40
41
  var registry = require('@socketsecurity/registry');
41
42
  var npm = require('@socketsecurity/registry/lib/npm');
42
43
  var packages = require('@socketsecurity/registry/lib/packages');
43
- var registryConstants = require('@socketsecurity/registry/lib/constants');
44
- var isInteractive = require('@socketregistry/is-interactive/index.cjs');
45
- var terminalLink = _socketInterop(require('terminal-link'));
44
+ var lockfileFile = _socketInterop(require('@pnpm/lockfile-file'));
45
+ var lockfile_detectDepTypes = _socketInterop(require('@pnpm/lockfile.detect-dep-types'));
46
+ var debug = require('@socketsecurity/registry/lib/debug');
46
47
  var spawn = require('@socketsecurity/registry/lib/spawn');
47
- var npa = _socketInterop(require('npm-package-arg'));
48
- var semver = _socketInterop(require('semver'));
49
- var tinyglobby = _socketInterop(require('tinyglobby'));
50
- var promises = require('@socketsecurity/registry/lib/promises');
48
+ var shadowNpmPaths = require('./shadow-npm-paths.js');
51
49
  var browserslist = _socketInterop(require('browserslist'));
50
+ var semver = _socketInterop(require('semver'));
52
51
  var which = _socketInterop(require('which'));
53
52
  var index_cjs = require('@socketregistry/hyrious__bun.lockb/index.cjs');
54
53
  var sorts = require('@socketsecurity/registry/lib/sorts');
55
54
  var strings = require('@socketsecurity/registry/lib/strings');
55
+ var registryConstants = require('@socketsecurity/registry/lib/constants');
56
+ var isInteractive = require('@socketregistry/is-interactive/index.cjs');
57
+ var terminalLink = _socketInterop(require('terminal-link'));
58
+ var npa = _socketInterop(require('npm-package-arg'));
59
+ var tinyglobby = _socketInterop(require('tinyglobby'));
60
+ var promises = require('@socketsecurity/registry/lib/promises');
56
61
  var yaml = _socketInterop(require('yaml'));
57
- var debug = require('@socketsecurity/registry/lib/debug');
58
- var npmPaths = require('./npm-paths.js');
59
62
  var betterAjvErrors = _socketInterop(require('@apideck/better-ajv-errors'));
60
63
  var config$A = require('@socketsecurity/config');
61
64
  var assert = require('node:assert');
62
65
  var readline = require('node:readline/promises');
66
+ var BoxWidget = _socketInterop(require('blessed/lib/widgets/box'));
63
67
  var TableWidget = _socketInterop(require('blessed-contrib/lib/widget/table'));
64
68
  var readline$1 = require('node:readline');
65
69
 
@@ -321,7 +325,7 @@ class Core {
321
325
  }) {
322
326
  const introducedBy = [];
323
327
  if (pkg.direct) {
324
- let manifests = pkg.manifestFiles.map(({
328
+ const manifests = pkg.manifestFiles.map(({
325
329
  file
326
330
  }) => file).join(';');
327
331
  introducedBy.push(['direct', manifests]);
@@ -332,7 +336,7 @@ class Core {
332
336
  continue;
333
337
  }
334
338
  const topPurl = `${topPackage.type}/${topPackage.name}@${topPackage.version}`;
335
- let manifests = topPackage.manifestFiles.map(({
339
+ const manifests = topPackage.manifestFiles.map(({
336
340
  file
337
341
  }) => file).join(';');
338
342
  introducedBy.push([topPurl, manifests]);
@@ -764,7 +768,7 @@ function processSecurityComment({
764
768
  const result = [];
765
769
  let start = false;
766
770
  let ignoreAll = false;
767
- let ignoredPackages = [];
771
+ const ignoredPackages = [];
768
772
  for (const ignoreComment of ignoreComments) {
769
773
  const parsed = parseIgnoreCommand(ignoreComment.body?.split('\n').at(0) ?? '');
770
774
  if (parsed.ignoreAll) {
@@ -788,7 +792,7 @@ function processSecurityComment({
788
792
  const [_, _title, packageLink, _introducedBy, _manifest, _ci] = line.split('|');
789
793
 
790
794
  // Parsing package link [npm/pkg](url)
791
- let [_ecosystem, pkg] = packageLink.slice(1, packageLink.indexOf(']')).split('/', 2);
795
+ const [_ecosystem, pkg] = packageLink.slice(1, packageLink.indexOf(']')).split('/', 2);
792
796
  const [pkgName, pkgVersion] = pkg.split('@');
793
797
 
794
798
  // Checking if this package should be ignored
@@ -837,7 +841,7 @@ function getIgnoreOptions({
837
841
  ignoreCommands.push(data);
838
842
  }
839
843
  } catch (e) {
840
- logger.logger.error(`Unable to process ignore command for ${comment}`);
844
+ logger.logger.fail(`Unable to process ignore command for ${comment}`);
841
845
  logger.logger.error(e);
842
846
  }
843
847
  }
@@ -1111,8 +1115,8 @@ function createSources(alert) {
1111
1115
  manifests.push(addStr);
1112
1116
  }
1113
1117
  }
1114
- let manifestList = manifests.join('');
1115
- let sourceList = sources.join('');
1118
+ const manifestList = manifests.join('');
1119
+ const sourceList = sources.join('');
1116
1120
  const manifestStr = `<ul>${manifestList}</ul>`;
1117
1121
  const sourcesStr = `<ul>${sourceList}</ul>`;
1118
1122
  return [manifestStr, sourcesStr];
@@ -1223,7 +1227,7 @@ function securityCommentTemplate(diff) {
1223
1227
  // TODO: is this a github action handler?
1224
1228
  async function runAction(githubEventBefore, githubEventAfter) {
1225
1229
  //TODO
1226
- const socket = new sdk.SocketSdk(index.getDefaultToken());
1230
+ const socket = new sdk.SocketSdk(shadowNpmInject.getDefaultToken());
1227
1231
  const git = simpleGit.simpleGit();
1228
1232
  const changedFiles = (await git.diff(process.env['GITHUB_EVENT_NAME'] === 'pull_request' ? ['--name-only', 'HEAD^1', 'HEAD'] : ['--name-only', githubEventBefore, githubEventAfter])).split('\n');
1229
1233
  logger.logger.log({
@@ -1257,8 +1261,8 @@ async function runAction(githubEventBefore, githubEventAfter) {
1257
1261
  const securityComment = securityCommentTemplate(diff);
1258
1262
  let newSecurityComment = true;
1259
1263
  let newOverviewComment = true;
1260
- let updateOldSecurityComment = comments.security !== undefined;
1261
- let updateOldOverviewComment = comments.overview !== undefined;
1264
+ const updateOldSecurityComment = comments.security !== undefined;
1265
+ const updateOldOverviewComment = comments.overview !== undefined;
1262
1266
  if (diff.newAlerts.length === 0) {
1263
1267
  if (!updateOldSecurityComment) {
1264
1268
  newSecurityComment = false;
@@ -1288,15 +1292,14 @@ async function runAction(githubEventBefore, githubEventAfter) {
1288
1292
  const {
1289
1293
  API_V0_URL
1290
1294
  } = constants;
1291
- function handleUnsuccessfulApiResponse(_name, result, spinner) {
1295
+ function handleUnsuccessfulApiResponse(_name, result) {
1292
1296
  // SocketSdkErrorType['error'] is not typed.
1293
1297
  const resultErrorMessage = result.error?.message;
1294
1298
  const message = typeof resultErrorMessage === 'string' ? resultErrorMessage : 'No error message returned';
1295
1299
  if (result.status === 401 || result.status === 403) {
1296
- spinner.stop();
1297
- throw new index.AuthError(message);
1300
+ throw new shadowNpmInject.AuthError(message);
1298
1301
  }
1299
- spinner.errorAndStop(`${colors.bgRed(colors.white('API returned an error:'))} ${message}`);
1302
+ logger.logger.fail(`${colors.bgRed(colors.white('API returned an error:'))} ${message}`);
1300
1303
  process$1.exit(1);
1301
1304
  }
1302
1305
  async function handleApiCall(value, description) {
@@ -1401,8 +1404,7 @@ const validationFlags = {
1401
1404
 
1402
1405
  const {
1403
1406
  DRY_RUN_LABEL: DRY_RUN_LABEL$1,
1404
- REDACTED,
1405
- SOCKET_CLI_SHOW_BANNER
1407
+ REDACTED
1406
1408
  } = constants;
1407
1409
  async function meowWithSubcommands(subcommands, options) {
1408
1410
  const {
@@ -1436,11 +1438,7 @@ async function meowWithSubcommands(subcommands, options) {
1436
1438
  };
1437
1439
  // ...else we provide basic instructions and help.
1438
1440
 
1439
- // Temp disable until we clear the --json and --markdown usage
1440
- // Lazily access constants.ENV[SOCKET_CLI_SHOW_BANNER].
1441
- if (constants.ENV[SOCKET_CLI_SHOW_BANNER]) {
1442
- logger.logger.log(getAsciiHeader(name));
1443
- }
1441
+ emitBanner(name);
1444
1442
  const cli = vendor.meow(`
1445
1443
  Usage
1446
1444
  $ ${name} <command>
@@ -1475,8 +1473,8 @@ async function meowWithSubcommands(subcommands, options) {
1475
1473
  autoHelp: false // otherwise we can't exit(0)
1476
1474
  });
1477
1475
  if (!cli.flags['help'] && cli.flags['dryRun']) {
1478
- logger.logger.log(`${DRY_RUN_LABEL$1}: No-op, call a sub-command; ok`);
1479
1476
  process.exitCode = 0;
1477
+ logger.logger.log(`${DRY_RUN_LABEL$1}: No-op, call a sub-command; ok`);
1480
1478
  } else {
1481
1479
  cli.showHelp();
1482
1480
  }
@@ -1494,11 +1492,7 @@ function meowOrExit({
1494
1492
  parentName
1495
1493
  }) {
1496
1494
  const command = `${parentName} ${config.commandName}`;
1497
- // Temp disable until we clear the --json and --markdown usage.
1498
- // Lazily access constants.ENV[SOCKET_CLI_SHOW_BANNER].
1499
- if (constants.ENV[SOCKET_CLI_SHOW_BANNER]) {
1500
- logger.logger.log(getAsciiHeader(command));
1501
- }
1495
+ emitBanner(command);
1502
1496
 
1503
1497
  // This exits if .printHelp() is called either by meow itself or by us.
1504
1498
  const cli = vendor.meow({
@@ -1515,13 +1509,24 @@ function meowOrExit({
1515
1509
  }
1516
1510
  return cli;
1517
1511
  }
1512
+ function emitBanner(name) {
1513
+ // Print a banner at the top of each command.
1514
+ // This helps with brand recognition and marketing.
1515
+ // It also helps with debugging since it contains version and command details.
1516
+ // Note: print over stderr to preserve stdout for flags like --json and
1517
+ // --markdown. If we don't do this, you can't use --json in particular
1518
+ // and pipe the result to other tools. By emiting the banner over stderr
1519
+ // you can do something like `socket scan view xyz | jq | process`.
1520
+ // The spinner also emits over stderr for example.
1521
+ logger.logger.error(getAsciiHeader(name));
1522
+ }
1518
1523
  function getAsciiHeader(command) {
1519
1524
  const cliVersion = // The '@rollup/plugin-replace' will replace "process.env['SOCKET_CLI_VERSION_HASH']".
1520
- "0.14.56:5a261bf:186ce7ee:pub";
1525
+ "0.14.58:f270068:05655527:pub";
1521
1526
  const nodeVersion = process.version;
1522
- const apiToken = index.getSetting('apiToken');
1527
+ const apiToken = shadowNpmInject.getSetting('apiToken');
1523
1528
  const shownToken = apiToken ? getLastFiveOfApiToken(apiToken) : 'no';
1524
- const relCwd = process.cwd().replace(new RegExp(`^${regexps.escapeRegExp(constants.homePath)}`, 'i'), '~/');
1529
+ const relCwd = path$1.normalizePath(process.cwd().replace(new RegExp(`^${regexps.escapeRegExp(constants.homePath)}(?:${path.sep}|$)`, 'i'), '~/'));
1525
1530
  const body = `
1526
1531
  _____ _ _ /---------------
1527
1532
  | __|___ ___| |_ ___| |_ | Socket.dev CLI ver ${cliVersion}
@@ -1592,10 +1597,10 @@ async function run$z(argv, importMeta, {
1592
1597
  }
1593
1598
 
1594
1599
  async function fetchOrgAnalyticsData(time, spinner, apiToken) {
1595
- const socketSdk = await index.setupSdk(apiToken);
1600
+ const socketSdk = await shadowNpmInject.setupSdk(apiToken);
1596
1601
  const result = await handleApiCall(socketSdk.getOrgAnalytics(time.toString()), 'fetching analytics data');
1597
1602
  if (result.success === false) {
1598
- handleUnsuccessfulApiResponse('getOrgAnalytics', result, spinner);
1603
+ handleUnsuccessfulApiResponse('getOrgAnalytics', result);
1599
1604
  return undefined;
1600
1605
  }
1601
1606
  spinner.stop();
@@ -1607,10 +1612,10 @@ async function fetchOrgAnalyticsData(time, spinner, apiToken) {
1607
1612
  }
1608
1613
 
1609
1614
  async function fetchRepoAnalyticsData(repo, time, spinner, apiToken) {
1610
- const socketSdk = await index.setupSdk(apiToken);
1615
+ const socketSdk = await shadowNpmInject.setupSdk(apiToken);
1611
1616
  const result = await handleApiCall(socketSdk.getRepoAnalytics(repo, time.toString()), 'fetching analytics data');
1612
1617
  if (result.success === false) {
1613
- handleUnsuccessfulApiResponse('getRepoAnalytics', result, spinner);
1618
+ handleUnsuccessfulApiResponse('getRepoAnalytics', result);
1614
1619
  return undefined;
1615
1620
  }
1616
1621
  spinner.stop();
@@ -1684,9 +1689,9 @@ async function displayAnalytics({
1684
1689
  scope,
1685
1690
  time
1686
1691
  }) {
1687
- const apiToken = index.getDefaultToken();
1692
+ const apiToken = shadowNpmInject.getDefaultToken();
1688
1693
  if (!apiToken) {
1689
- throw new index.AuthError('User must be authenticated to run this command. To log in, run the command `socket login` and enter your API token.');
1694
+ throw new shadowNpmInject.AuthError('User must be authenticated to run this command. To log in, run the command `socket login` and enter your API token.');
1690
1695
  }
1691
1696
  await outputAnalyticsWithToken({
1692
1697
  apiToken,
@@ -1720,16 +1725,16 @@ async function outputAnalyticsWithToken({
1720
1725
  // A message should already have been printed if we have no data here
1721
1726
  if (!data) return;
1722
1727
  if (outputKind === 'json') {
1723
- let serialized = renderJson(data);
1728
+ const serialized = renderJson(data);
1724
1729
  if (!serialized) return;
1725
1730
  if (filePath && filePath !== '-') {
1726
1731
  try {
1727
1732
  await fs$1.writeFile(filePath, serialized, 'utf8');
1728
1733
  logger.logger.log(`Data successfully written to ${filePath}`);
1729
1734
  } catch (e) {
1730
- logger.logger.error('There was an error trying to write the json to disk');
1731
- logger.logger.error(e);
1732
1735
  process.exitCode = 1;
1736
+ logger.logger.fail('There was an error trying to write the json to disk');
1737
+ logger.logger.error(e);
1733
1738
  }
1734
1739
  } else {
1735
1740
  logger.logger.log(serialized);
@@ -1757,9 +1762,9 @@ function renderJson(data) {
1757
1762
  try {
1758
1763
  return JSON.stringify(data, null, 2);
1759
1764
  } catch (e) {
1760
- // This could be caused by circular references, which is an "us" problem
1761
- logger.logger.error('There was a problem converting the data set to JSON. Please try without --json or with --markdown');
1762
1765
  process.exitCode = 1;
1766
+ // This could be caused by circular references, which is an "us" problem
1767
+ logger.logger.fail('There was a problem converting the data set to JSON. Please try without --json or with --markdown');
1763
1768
  return;
1764
1769
  }
1765
1770
  }
@@ -1994,7 +1999,7 @@ async function run$y(argv, importMeta, {
1994
1999
  // options or missing arguments.
1995
2000
  // https://www.gnu.org/software/bash/manual/html_node/Exit-Status.html
1996
2001
  process.exitCode = 2;
1997
- logger.logger.error(commonTags.stripIndents`${colors.bgRed(colors.white('Input error'))}: Please provide the required fields:
2002
+ logger.logger.fail(commonTags.stripIndents`${colors.bgRed(colors.white('Input error'))}: Please provide the required fields:
1998
2003
 
1999
2004
  - Scope must be "repo" or "org" ${badScope ? colors.red('(bad!)') : colors.green('(ok)')}
2000
2005
 
@@ -2028,9 +2033,9 @@ async function getAuditLog({
2028
2033
  page,
2029
2034
  perPage
2030
2035
  }) {
2031
- const apiToken = index.getDefaultToken();
2036
+ const apiToken = shadowNpmInject.getDefaultToken();
2032
2037
  if (!apiToken) {
2033
- throw new index.AuthError('User must be authenticated to run this command. To log in, run the command `socket login` and enter your API key.');
2038
+ 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.');
2034
2039
  }
2035
2040
  const auditLogs = await getAuditLogWithToken({
2036
2041
  apiToken,
@@ -2074,8 +2079,8 @@ async function outputAsJson(auditLogs, orgSlug, logType, page, perPage) {
2074
2079
  })
2075
2080
  }, null, 2);
2076
2081
  } catch (e) {
2077
- logger.logger.error('There was a problem converting the logs to JSON, please try without the `--json` flag');
2078
2082
  process.exitCode = 1;
2083
+ logger.logger.fail('There was a problem converting the logs to JSON, please try without the `--json` flag');
2079
2084
  return;
2080
2085
  }
2081
2086
  logger.logger.log(json);
@@ -2096,9 +2101,9 @@ These are the Socket.dev audit logs as per requested query.
2096
2101
  ${table}
2097
2102
  `);
2098
2103
  } catch (e) {
2099
- logger.logger.error('There was a problem converting the logs to JSON, please try without the `--json` flag');
2100
- logger.logger.error(e);
2101
2104
  process.exitCode = 1;
2105
+ logger.logger.fail('There was a problem converting the logs to JSON, please try without the `--json` flag');
2106
+ logger.logger.error(e);
2102
2107
  return;
2103
2108
  }
2104
2109
  }
@@ -2140,7 +2145,7 @@ async function getAuditLogWithToken({
2140
2145
  spinner
2141
2146
  } = constants;
2142
2147
  spinner.start(`Looking up audit log for ${orgSlug}`);
2143
- const socketSdk = await index.setupSdk(apiToken);
2148
+ const socketSdk = await shadowNpmInject.setupSdk(apiToken);
2144
2149
  const result = await handleApiCall(socketSdk.getAuditLogEvents(orgSlug, {
2145
2150
  outputJson: outputKind === 'json',
2146
2151
  // I'm not sure this is used at all
@@ -2152,7 +2157,7 @@ async function getAuditLogWithToken({
2152
2157
  per_page: perPage
2153
2158
  }), `Looking up audit log for ${orgSlug}\n`);
2154
2159
  if (!result.success) {
2155
- handleUnsuccessfulApiResponse('getAuditLogEvents', result, spinner);
2160
+ handleUnsuccessfulApiResponse('getAuditLogEvents', result);
2156
2161
  return;
2157
2162
  }
2158
2163
  spinner.stop();
@@ -2192,6 +2197,9 @@ const config$x = {
2192
2197
  Usage
2193
2198
  $ ${command} <org slug>
2194
2199
 
2200
+ This feature requires an Enterprise Plan. To learn more about getting access
2201
+ to this feature and many more, please visit https://socket.dev/pricing
2202
+
2195
2203
  Options
2196
2204
  ${getFlagListOutput(config.flags, 6)}
2197
2205
 
@@ -2227,7 +2235,7 @@ async function run$x(argv, importMeta, {
2227
2235
  // options or missing arguments.
2228
2236
  // https://www.gnu.org/software/bash/manual/html_node/Exit-Status.html
2229
2237
  process.exitCode = 2;
2230
- logger.logger.error(commonTags.stripIndents`
2238
+ logger.logger.fail(commonTags.stripIndents`
2231
2239
  ${colors.bgRed(colors.white('Input error'))}: Please provide the required fields:\n
2232
2240
  - Org name as the first argument ${!orgSlug ? colors.red('(missing!)') : colors.green('(ok)')}
2233
2241
  `);
@@ -2247,22 +2255,22 @@ async function run$x(argv, importMeta, {
2247
2255
  }
2248
2256
 
2249
2257
  const {
2250
- NPM: NPM$e,
2258
+ NPM: NPM$g,
2251
2259
  NPX: NPX$3,
2252
- PNPM: PNPM$8
2260
+ PNPM: PNPM$a
2253
2261
  } = constants;
2254
- const nodejsPlatformTypes = new Set(['javascript', 'js', 'nodejs', NPM$e, PNPM$8, 'ts', 'tsx', 'typescript']);
2262
+ const nodejsPlatformTypes = new Set(['javascript', 'js', 'nodejs', NPM$g, PNPM$a, 'ts', 'tsx', 'typescript']);
2255
2263
  async function runCycloneDX(yargv) {
2256
2264
  let cleanupPackageLock = false;
2257
2265
  if (yargv.type !== 'yarn' && nodejsPlatformTypes.has(yargv.type) && fs.existsSync('./yarn.lock')) {
2258
2266
  if (fs.existsSync('./package-lock.json')) {
2259
- yargv.type = NPM$e;
2267
+ yargv.type = NPM$g;
2260
2268
  } else {
2261
2269
  // Use synp to create a package-lock.json from the yarn.lock,
2262
2270
  // based on the node_modules folder, for a more accurate SBOM.
2263
2271
  try {
2264
2272
  await shadowBin(NPX$3, ['synp@1.9.14', '--', '--source-file', './yarn.lock'], 2);
2265
- yargv.type = NPM$e;
2273
+ yargv.type = NPM$g;
2266
2274
  cleanupPackageLock = true;
2267
2275
  } catch {}
2268
2276
  }
@@ -2413,7 +2421,7 @@ async function run$w(argv, importMeta, {
2413
2421
  //
2414
2422
  //
2415
2423
  // if (cli.input.length)
2416
- // logger.error(
2424
+ // logger.fail(
2417
2425
  // stripIndents`
2418
2426
  // ${colors.bgRed(colors.white('Input error'))}: Please provide the required fields:
2419
2427
  //
@@ -2437,7 +2445,7 @@ async function run$w(argv, importMeta, {
2437
2445
  // options or missing arguments.
2438
2446
  // https://www.gnu.org/software/bash/manual/html_node/Exit-Status.html
2439
2447
  process$1.exitCode = 2;
2440
- logger.logger.error(`Unknown ${words.pluralize('argument', unknownLength)}: ${yargv._.join(', ')}`);
2448
+ logger.logger.fail(`Unknown ${words.pluralize('argument', unknownLength)}: ${yargv._.join(', ')}`);
2441
2449
  return;
2442
2450
  }
2443
2451
  if (yargv.output === undefined) {
@@ -2456,22 +2464,22 @@ async function findDependencies({
2456
2464
  offset,
2457
2465
  outputJson
2458
2466
  }) {
2459
- const apiToken = index.getDefaultToken();
2467
+ const apiToken = shadowNpmInject.getDefaultToken();
2460
2468
  if (!apiToken) {
2461
- throw new index.AuthError('User must be authenticated to run this command. To log in, run the command `socket login` and enter your API key.');
2469
+ 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.');
2462
2470
  }
2463
2471
  // Lazily access constants.spinner.
2464
2472
  const {
2465
2473
  spinner
2466
2474
  } = constants;
2467
2475
  spinner.start('Searching dependencies...');
2468
- const socketSdk = await index.setupSdk(apiToken);
2476
+ const socketSdk = await shadowNpmInject.setupSdk(apiToken);
2469
2477
  const result = await handleApiCall(socketSdk.searchDependencies({
2470
2478
  limit,
2471
2479
  offset
2472
2480
  }), 'Searching dependencies');
2473
2481
  if (!result.success) {
2474
- handleUnsuccessfulApiResponse('searchDependencies', result, spinner);
2482
+ handleUnsuccessfulApiResponse('searchDependencies', result);
2475
2483
  return;
2476
2484
  }
2477
2485
  spinner.stop('Organization dependencies:');
@@ -2576,9 +2584,9 @@ async function getDiffScan({
2576
2584
  orgSlug,
2577
2585
  outputJson
2578
2586
  }) {
2579
- const apiToken = index.getDefaultToken();
2587
+ const apiToken = shadowNpmInject.getDefaultToken();
2580
2588
  if (!apiToken) {
2581
- throw new index.AuthError('User must be authenticated to run this command. To log in, run the command `socket login` and enter your API key.');
2589
+ 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.');
2582
2590
  }
2583
2591
  await getDiffScanWithToken({
2584
2592
  after,
@@ -2623,16 +2631,17 @@ async function getDiffScanWithToken({
2623
2631
  try {
2624
2632
  json = JSON.stringify(result, null, 2);
2625
2633
  } catch (e) {
2626
- // Most likely caused by a circular reference (or OOM)
2627
- logger.logger.error('There was a problem converting the data to JSON');
2628
2634
  process.exitCode = 1;
2635
+ // Most likely caused by a circular reference (or OOM)
2636
+ logger.logger.fail('There was a problem converting the data to JSON');
2637
+ logger.logger.error(e);
2629
2638
  return;
2630
2639
  }
2631
2640
  if (file && file !== '-') {
2632
2641
  logger.logger.log(`Writing json to \`${file}\``);
2633
2642
  fs.writeFile(file, JSON.stringify(result, null, 2), err => {
2634
2643
  if (err) {
2635
- logger.logger.error(`Writing to \`${file}\` failed...`);
2644
+ logger.logger.fail(`Writing to \`${file}\` failed...`);
2636
2645
  logger.logger.error(err);
2637
2646
  } else {
2638
2647
  logger.logger.log(`Data successfully written to \`${file}\``);
@@ -2738,7 +2747,7 @@ async function run$u(argv, importMeta, {
2738
2747
  // options or missing arguments.
2739
2748
  // https://www.gnu.org/software/bash/manual/html_node/Exit-Status.html
2740
2749
  process.exitCode = 2;
2741
- logger.logger.error(`${colors.bgRed(colors.white('Input error'))}: Please provide the required fields:\n
2750
+ logger.logger.fail(`${colors.bgRed(colors.white('Input error'))}: Please provide the required fields:\n
2742
2751
  - Specify a before and after full scan ID ${!before && !after ? colors.red('(missing before and after!)') : !before ? colors.red('(missing before!)') : !after ? colors.red('(missing after!)') : colors.green('(ok)')}\n
2743
2752
  - To get full scans IDs, you can run the command "socket scan list <your org slug>".
2744
2753
  The args are expecting a full \`aaa0aa0a-aaaa-0000-0a0a-0000000a00a0\` ID.\n
@@ -2781,254 +2790,766 @@ const cmdDiffScan = {
2781
2790
  }
2782
2791
  };
2783
2792
 
2784
- // import { detect } from '../../utils/package-environment-detector'
2785
-
2786
2793
  const {
2787
- NPM: NPM$d
2794
+ NPM: NPM$f
2788
2795
  } = constants;
2789
2796
  function isTopLevel(tree, node) {
2790
2797
  return tree.children.get(node.name) === node;
2791
2798
  }
2792
- async function runFix() {
2793
- // Lazily access constants.spinner.
2799
+ async function npmFix(_pkgEnvDetails, cwd, options) {
2794
2800
  const {
2795
2801
  spinner
2796
- } = constants;
2797
- spinner.start();
2798
- const cwd = process.cwd();
2799
- const editablePkgJson = await packages.readPackageJson(cwd, {
2800
- editable: true
2801
- });
2802
- // const agentDetails = await detect()
2803
-
2804
- const arb = new index.SafeArborist({
2802
+ } = {
2803
+ __proto__: null,
2804
+ ...options
2805
+ };
2806
+ spinner?.start();
2807
+ const arb = new shadowNpmInject.SafeArborist({
2805
2808
  path: cwd,
2806
- ...index.SAFE_ARBORIST_REIFY_OPTIONS_OVERRIDES
2809
+ ...shadowNpmInject.SAFE_ARBORIST_REIFY_OPTIONS_OVERRIDES
2807
2810
  });
2808
2811
  await arb.reify();
2809
- const alerts = await index.getPackagesAlerts(arb, {
2812
+ const alertsMap = await shadowNpmInject.getAlertsMapFromArborist(arb, {
2810
2813
  consolidate: true,
2811
- includeExisting: true,
2812
- includeUnfixable: false
2814
+ include: {
2815
+ existing: true,
2816
+ unfixable: false,
2817
+ upgrade: false
2818
+ }
2813
2819
  });
2814
- const infoByPkg = index.getCveInfoByPackage(alerts);
2820
+ const infoByPkg = shadowNpmInject.getCveInfoByAlertsMap(alertsMap);
2821
+ if (!infoByPkg) {
2822
+ spinner?.stop();
2823
+ return;
2824
+ }
2815
2825
  await arb.buildIdealTree();
2816
- if (infoByPkg) {
2817
- for (const {
2818
- 0: name,
2819
- 1: infos
2820
- } of infoByPkg) {
2821
- let revertToIdealTree = arb.idealTree;
2822
- arb.idealTree = null;
2823
- // eslint-disable-next-line no-await-in-loop
2824
- await arb.buildIdealTree();
2825
- const tree = arb.idealTree;
2826
- const hasUpgrade = !!registry.getManifestData(NPM$d, name);
2827
- if (hasUpgrade) {
2828
- spinner.info(`Skipping ${name}. Socket Optimize package exists.`);
2829
- continue;
2830
- }
2831
- const nodes = index.findPackageNodes(tree, name);
2832
- const packument = nodes.length && infos.length ?
2833
- // eslint-disable-next-line no-await-in-loop
2834
- await packages.fetchPackagePackument(name) : null;
2835
- if (packument) {
2836
- for (let i = 0, {
2837
- length: nodesLength
2838
- } = nodes; i < nodesLength; i += 1) {
2839
- const node = nodes[i];
2840
- for (let j = 0, {
2841
- length: infosLength
2842
- } = infos; j < infosLength; j += 1) {
2843
- const {
2844
- firstPatchedVersionIdentifier,
2845
- vulnerableVersionRange
2846
- } = infos[j];
2847
- const {
2848
- version: oldVersion
2849
- } = node;
2850
- if (index.updateNode(node, packument, vulnerableVersionRange)) {
2851
- try {
2852
- // eslint-disable-next-line no-await-in-loop
2853
- await npm.runScript('test', [], {
2854
- spinner,
2855
- stdio: 'ignore'
2856
- });
2857
- spinner.info(`Patched ${name} ${oldVersion} -> ${node.version}`);
2858
- if (isTopLevel(tree, node)) {
2859
- for (const depField of ['dependencies', 'optionalDependencies', 'peerDependencies']) {
2860
- const oldVersion = editablePkgJson.content[depField]?.[name];
2861
- if (oldVersion) {
2862
- const decorator = /^[~^]/.exec(oldVersion)?.[0] ?? '';
2863
- editablePkgJson.content[depField][name] = `${decorator}${node.version}`;
2864
- }
2865
- }
2826
+ const editablePkgJson = await packages.readPackageJson(cwd, {
2827
+ editable: true
2828
+ });
2829
+ for (const {
2830
+ 0: name,
2831
+ 1: infos
2832
+ } of infoByPkg) {
2833
+ const revertToIdealTree = arb.idealTree;
2834
+ arb.idealTree = null;
2835
+ // eslint-disable-next-line no-await-in-loop
2836
+ await arb.buildIdealTree();
2837
+ const tree = arb.idealTree;
2838
+ const hasUpgrade = !!registry.getManifestData(NPM$f, name);
2839
+ if (hasUpgrade) {
2840
+ spinner?.info(`Skipping ${name}. Socket Optimize package exists.`);
2841
+ continue;
2842
+ }
2843
+ const nodes = shadowNpmInject.findPackageNodes(tree, name);
2844
+ const packument = nodes.length && infos.length ?
2845
+ // eslint-disable-next-line no-await-in-loop
2846
+ await packages.fetchPackagePackument(name) : null;
2847
+ if (!packument) {
2848
+ continue;
2849
+ }
2850
+ for (let i = 0, {
2851
+ length: nodesLength
2852
+ } = nodes; i < nodesLength; i += 1) {
2853
+ const node = nodes[i];
2854
+ for (let j = 0, {
2855
+ length: infosLength
2856
+ } = infos; j < infosLength; j += 1) {
2857
+ const {
2858
+ firstPatchedVersionIdentifier,
2859
+ vulnerableVersionRange
2860
+ } = infos[j];
2861
+ const {
2862
+ version: oldVersion
2863
+ } = node;
2864
+ if (shadowNpmInject.updateNode(node, packument, vulnerableVersionRange)) {
2865
+ try {
2866
+ // eslint-disable-next-line no-await-in-loop
2867
+ await npm.runScript('test', [], {
2868
+ spinner,
2869
+ stdio: 'ignore'
2870
+ });
2871
+ spinner?.info(`Patched ${name} ${oldVersion} -> ${node.version}`);
2872
+ if (isTopLevel(tree, node)) {
2873
+ for (const depField of ['dependencies', 'optionalDependencies', 'peerDependencies']) {
2874
+ const {
2875
+ content: pkgJson
2876
+ } = editablePkgJson;
2877
+ const oldVersion = pkgJson[depField]?.[name];
2878
+ if (oldVersion) {
2879
+ const decorator = /^[~^]/.exec(oldVersion)?.[0] ?? '';
2880
+ pkgJson[depField][name] = `${decorator}${node.version}`;
2866
2881
  }
2867
- // eslint-disable-next-line no-await-in-loop
2868
- await editablePkgJson.save();
2869
- } catch {
2870
- spinner.error(`Reverting ${name} to ${oldVersion}`);
2871
- arb.idealTree = revertToIdealTree;
2872
2882
  }
2873
- } else {
2874
- spinner.error(`Could not patch ${name} ${oldVersion}`);
2875
2883
  }
2884
+ // eslint-disable-next-line no-await-in-loop
2885
+ await editablePkgJson.save();
2886
+ } catch {
2887
+ spinner?.error(`Reverting ${name} to ${oldVersion}`);
2888
+ arb.idealTree = revertToIdealTree;
2876
2889
  }
2890
+ } else {
2891
+ spinner?.error(`Could not patch ${name} ${oldVersion}`);
2877
2892
  }
2878
2893
  }
2879
2894
  }
2880
2895
  }
2881
- const arb2 = new index.Arborist({
2896
+ const arb2 = new shadowNpmInject.Arborist({
2882
2897
  path: cwd
2883
2898
  });
2884
2899
  arb2.idealTree = arb.idealTree;
2885
2900
  await arb2.reify();
2886
- spinner.stop();
2901
+ spinner?.stop();
2887
2902
  }
2888
2903
 
2889
- const {
2890
- DRY_RUN_BAIL_TEXT: DRY_RUN_BAIL_TEXT$s
2891
- } = constants;
2892
- const config$t = {
2893
- commandName: 'fix',
2894
- description: 'Fix "fixable" Socket alerts',
2895
- hidden: true,
2896
- flags: {
2897
- ...commonFlags
2898
- },
2899
- help: (command, config) => `
2900
- Usage
2901
- $ ${command}
2902
-
2903
- Options
2904
- ${getFlagListOutput(config.flags, 6)}
2905
- `
2906
- };
2907
- const cmdFix = {
2908
- description: config$t.description,
2909
- hidden: config$t.hidden,
2910
- run: run$t
2911
- };
2912
- async function run$t(argv, importMeta, {
2913
- parentName
2914
- }) {
2915
- const cli = meowOrExit({
2916
- argv,
2917
- config: config$t,
2918
- importMeta,
2919
- parentName
2920
- });
2921
- if (cli.flags['dryRun']) {
2922
- logger.logger.log(DRY_RUN_BAIL_TEXT$s);
2923
- return;
2904
+ async function getAlertsMapFromPnpmLockfile(lockfile, options) {
2905
+ const {
2906
+ spinner
2907
+ } = {
2908
+ __proto__: null,
2909
+ ...options
2910
+ };
2911
+ const depTypes = lockfile_detectDepTypes.detectDepTypes(lockfile);
2912
+ const pkgIds = Object.keys(depTypes);
2913
+ let {
2914
+ length: remaining
2915
+ } = pkgIds;
2916
+ const alertsByPkgId = new Map();
2917
+ if (!remaining) {
2918
+ return alertsByPkgId;
2919
+ }
2920
+ const getText = () => `Looking up data for ${remaining} packages`;
2921
+ spinner?.start(getText());
2922
+ const toAlertsMapOptions = {
2923
+ overrides: lockfile.overrides,
2924
+ ...options
2925
+ };
2926
+ for await (const artifact of shadowNpmInject.batchScan(pkgIds)) {
2927
+ await shadowNpmInject.addArtifactToAlertsMap(artifact, alertsByPkgId, toAlertsMapOptions);
2928
+ remaining -= 1;
2929
+ if (spinner && remaining > 0) {
2930
+ spinner.start();
2931
+ spinner.setText(getText());
2932
+ }
2924
2933
  }
2925
- await runFix();
2934
+ spinner?.stop();
2935
+ return alertsByPkgId;
2926
2936
  }
2927
2937
 
2928
- function objectSome(obj) {
2929
- for (const key in obj) {
2930
- if (obj[key]) {
2931
- return true;
2938
+ function cmdFlagsToString(args) {
2939
+ const result = [];
2940
+ for (let i = 0, {
2941
+ length
2942
+ } = args; i < length; i += 1) {
2943
+ if (args[i].startsWith('--')) {
2944
+ // Check if the next item exists and is NOT another flag.
2945
+ if (i + 1 < length && !args[i + 1].startsWith('--')) {
2946
+ result.push(`${args[i]}=${args[i + 1]}`);
2947
+ i += 1;
2948
+ } else {
2949
+ result.push(args[i]);
2950
+ }
2932
2951
  }
2933
2952
  }
2934
- return false;
2953
+ return result.join(' ');
2935
2954
  }
2936
- function pick(input, keys) {
2937
- const result = {};
2938
- for (const key of keys) {
2939
- result[key] = input[key];
2955
+
2956
+ const {
2957
+ SOCKET_IPC_HANDSHAKE
2958
+ } = constants;
2959
+ function safeNpmInstall(options) {
2960
+ const {
2961
+ agentExecPath = shadowNpmPaths.getNpmBinPath(),
2962
+ args = [],
2963
+ ipc,
2964
+ spinner,
2965
+ ...spawnOptions
2966
+ } = {
2967
+ __proto__: null,
2968
+ ...options
2969
+ };
2970
+ const useIpc = objects.isObject(ipc);
2971
+ const useDebug = debug.isDebug();
2972
+ const terminatorPos = args.indexOf('--');
2973
+ const npmArgs = (terminatorPos === -1 ? args : args.slice(0, terminatorPos)).filter(a => !npm.isAuditFlag(a) && !npm.isFundFlag(a) && !npm.isProgressFlag(a));
2974
+ const otherArgs = terminatorPos === -1 ? [] : args.slice(terminatorPos);
2975
+ const isSilent = !useDebug && !npmArgs.some(npm.isLoglevelFlag);
2976
+ const logLevelArgs = isSilent ? ['--loglevel', 'error'] : [];
2977
+ const spawnPromise = spawn.spawn(
2978
+ // Lazily access constants.execPath.
2979
+ constants.execPath, [
2980
+ // Lazily access constants.nodeHardenFlags.
2981
+ ...constants.nodeHardenFlags,
2982
+ // Lazily access constants.nodeNoWarningsFlags.
2983
+ ...constants.nodeNoWarningsFlags, '--require',
2984
+ // Lazily access constants.distShadowNpmInjectPath.
2985
+ constants.distShadowNpmInjectPath, agentExecPath, 'install',
2986
+ // Avoid code paths for 'audit' and 'fund'.
2987
+ '--no-audit', '--no-fund',
2988
+ // Add `--no-progress` flag to fix input being swallowed by the spinner
2989
+ // when running the command with recent versions of npm.
2990
+ '--no-progress',
2991
+ // Add '--loglevel=error' if a loglevel flag is not provided and the
2992
+ // SOCKET_CLI_DEBUG environment variable is not truthy.
2993
+ ...logLevelArgs, ...npmArgs, ...otherArgs], {
2994
+ spinner,
2995
+ // Set stdio to include 'ipc'.
2996
+ // See https://github.com/nodejs/node/blob/v23.6.0/lib/child_process.js#L161-L166
2997
+ // and https://github.com/nodejs/node/blob/v23.6.0/lib/internal/child_process.js#L238.
2998
+ stdio: useIpc ? [0, 1, 2, 'ipc'] : 'inherit',
2999
+ ...spawnOptions,
3000
+ env: {
3001
+ ...process$1.env,
3002
+ ...spawnOptions.env
3003
+ }
3004
+ });
3005
+ if (useIpc) {
3006
+ spawnPromise.process.send({
3007
+ [SOCKET_IPC_HANDSHAKE]: ipc
3008
+ });
2940
3009
  }
2941
- return result;
3010
+ return spawnPromise;
2942
3011
  }
2943
3012
 
2944
- function stringJoinWithSeparateFinalSeparator(list, separator = ' and ') {
2945
- const values = list.filter(Boolean);
3013
+ const {
3014
+ NPM: NPM$e
3015
+ } = constants;
3016
+ function runAgentInstall(pkgEnvDetails, options) {
2946
3017
  const {
2947
- length
2948
- } = values;
2949
- if (!length) {
2950
- return '';
2951
- }
2952
- if (length === 1) {
2953
- return values[0];
3018
+ agent,
3019
+ agentExecPath
3020
+ } = pkgEnvDetails;
3021
+ // All package managers support the "install" command.
3022
+ if (agent === NPM$e) {
3023
+ return safeNpmInstall({
3024
+ agentExecPath,
3025
+ ...options
3026
+ });
2954
3027
  }
2955
- const finalValue = values.pop();
2956
- return `${values.join(', ')}${separator}${finalValue}`;
3028
+ const {
3029
+ args = [],
3030
+ spinner,
3031
+ ...spawnOptions
3032
+ } = {
3033
+ __proto__: null,
3034
+ ...options
3035
+ };
3036
+ return spawn.spawn(agentExecPath, ['install', ...args], {
3037
+ spinner,
3038
+ stdio: debug.isDebug() ? 'inherit' : 'ignore',
3039
+ ...spawnOptions,
3040
+ env: {
3041
+ ...process.env,
3042
+ NODE_OPTIONS: cmdFlagsToString([
3043
+ // Lazily access constants.nodeHardenFlags.
3044
+ ...constants.nodeHardenFlags,
3045
+ // Lazily access constants.nodeNoWarningsFlags.
3046
+ ...constants.nodeNoWarningsFlags]),
3047
+ ...spawnOptions.env
3048
+ }
3049
+ });
2957
3050
  }
2958
3051
 
2959
- // Ordered from most severe to least.
2960
- const SEVERITIES_BY_ORDER = ['critical', 'high', 'middle', 'low'];
2961
- function getDesiredSeverities(lowestToInclude) {
2962
- const result = [];
2963
- for (const severity of SEVERITIES_BY_ORDER) {
2964
- result.push(severity);
2965
- if (severity === lowestToInclude) {
2966
- break;
2967
- }
3052
+ const {
3053
+ NPM: NPM$d,
3054
+ OVERRIDES: OVERRIDES$2,
3055
+ PNPM: PNPM$9
3056
+ } = constants;
3057
+ async function pnpmFix(pkgEnvDetails, cwd, options) {
3058
+ const {
3059
+ spinner
3060
+ } = {
3061
+ __proto__: null,
3062
+ ...options
3063
+ };
3064
+ spinner?.start();
3065
+ const lockfile = await lockfileFile.readWantedLockfile(cwd, {
3066
+ ignoreIncompatible: false
3067
+ });
3068
+ if (!lockfile) {
3069
+ spinner?.stop();
3070
+ return;
2968
3071
  }
2969
- return result;
2970
- }
2971
- function formatSeverityCount(severityCount) {
2972
- const summary = [];
2973
- for (const severity of SEVERITIES_BY_ORDER) {
2974
- if (severityCount[severity]) {
2975
- summary.push(`${severityCount[severity]} ${severity}`);
3072
+ const alertsMap = await getAlertsMapFromPnpmLockfile(lockfile, {
3073
+ consolidate: true,
3074
+ include: {
3075
+ existing: true,
3076
+ unfixable: false,
3077
+ upgrade: false
2976
3078
  }
3079
+ });
3080
+ const infoByPkg = shadowNpmInject.getCveInfoByAlertsMap(alertsMap);
3081
+ if (!infoByPkg) {
3082
+ spinner?.stop();
3083
+ return;
2977
3084
  }
2978
- return stringJoinWithSeparateFinalSeparator(summary);
2979
- }
2980
- function getSeverityCount(issues, lowestToInclude) {
2981
- const severityCount = pick({
2982
- low: 0,
2983
- middle: 0,
2984
- high: 0,
2985
- critical: 0
2986
- }, getDesiredSeverities(lowestToInclude));
2987
- for (const issue of issues) {
2988
- const {
2989
- value
2990
- } = issue;
2991
- if (!value) {
3085
+ const arb = new shadowNpmInject.SafeArborist({
3086
+ path: cwd,
3087
+ ...shadowNpmInject.SAFE_ARBORIST_REIFY_OPTIONS_OVERRIDES
3088
+ });
3089
+ await arb.loadActual();
3090
+ const editablePkgJson = await packages.readPackageJson(cwd, {
3091
+ editable: true
3092
+ });
3093
+ const {
3094
+ content: pkgJson
3095
+ } = editablePkgJson;
3096
+ for (const {
3097
+ 0: name,
3098
+ 1: infos
3099
+ } of infoByPkg) {
3100
+ const tree = arb.actualTree;
3101
+ const hasUpgrade = !!registry.getManifestData(NPM$d, name);
3102
+ if (hasUpgrade) {
3103
+ spinner?.info(`Skipping ${name}. Socket Optimize package exists.`);
2992
3104
  continue;
2993
3105
  }
2994
- if (severityCount[value.severity] !== undefined) {
2995
- severityCount[value.severity] += 1;
3106
+ const nodes = shadowNpmInject.findPackageNodes(tree, name);
3107
+ const packument = nodes.length && infos.length ?
3108
+ // eslint-disable-next-line no-await-in-loop
3109
+ await packages.fetchPackagePackument(name) : null;
3110
+ if (!packument) {
3111
+ continue;
2996
3112
  }
2997
- }
2998
- return severityCount;
2999
- }
3113
+ for (let i = 0, {
3114
+ length: nodesLength
3115
+ } = nodes; i < nodesLength; i += 1) {
3116
+ const node = nodes[i];
3117
+ for (let j = 0, {
3118
+ length: infosLength
3119
+ } = infos; j < infosLength; j += 1) {
3120
+ const {
3121
+ firstPatchedVersionIdentifier,
3122
+ vulnerableVersionRange
3123
+ } = infos[j];
3124
+ const {
3125
+ version: oldVersion
3126
+ } = node;
3127
+ const availableVersions = Object.keys(packument.versions);
3128
+ // Find the highest non-vulnerable version within the same major range
3129
+ const targetVersion = shadowNpmInject.findBestPatchVersion(node, availableVersions, vulnerableVersionRange);
3130
+ const targetPackument = targetVersion ? packument.versions[targetVersion] : undefined;
3131
+ if (targetPackument) {
3132
+ const oldPnpm = pkgJson[PNPM$9];
3133
+ const oldOverrides = oldPnpm?.[OVERRIDES$2];
3134
+ try {
3135
+ editablePkgJson.update({
3136
+ [PNPM$9]: {
3137
+ ...oldPnpm,
3138
+ [OVERRIDES$2]: {
3139
+ [`${node.name}@${vulnerableVersionRange}`]: `^${targetVersion}`,
3140
+ ...oldOverrides
3141
+ }
3142
+ }
3143
+ });
3144
+ spinner?.info(`Patched ${name} ${oldVersion} -> ${node.version}`);
3000
3145
 
3001
- async function fetchPackageInfo(pkgName, pkgVersion, includeAllIssues) {
3002
- // Lazily access constants.spinner.
3003
- const {
3004
- spinner
3005
- } = constants;
3006
- spinner.start(pkgVersion === 'latest' ? `Looking up data for the latest version of ${pkgName}` : `Looking up data for version ${pkgVersion} of ${pkgName}`);
3007
- const socketSdk = await index.setupSdk(index.getPublicToken());
3008
- const result = await handleApiCall(socketSdk.getIssuesByNPMPackage(pkgName, pkgVersion), 'looking up package');
3009
- const scoreResult = await handleApiCall(socketSdk.getScoreByNPMPackage(pkgName, pkgVersion), 'looking up package score');
3010
- if (result.success === false) {
3011
- return handleUnsuccessfulApiResponse('getIssuesByNPMPackage', result, spinner);
3012
- }
3013
- if (scoreResult.success === false) {
3014
- return handleUnsuccessfulApiResponse('getScoreByNPMPackage', scoreResult, spinner);
3146
+ // eslint-disable-next-line no-await-in-loop
3147
+ await editablePkgJson.save();
3148
+ // eslint-disable-next-line no-await-in-loop
3149
+ await runAgentInstall(pkgEnvDetails, {
3150
+ spinner
3151
+ });
3152
+ } catch {
3153
+ spinner?.error(`Reverting ${name} to ${oldVersion}`);
3154
+ }
3155
+ } else {
3156
+ spinner?.error(`Could not patch ${name} ${oldVersion}`);
3157
+ }
3158
+ }
3159
+ }
3015
3160
  }
3016
- const severityCount = getSeverityCount(result.data, includeAllIssues ? undefined : 'high');
3017
- spinner?.successAndStop('Data fetched');
3018
- return {
3019
- data: result.data,
3020
- severityCount,
3021
- score: scoreResult.data
3022
- };
3161
+ spinner?.stop();
3023
3162
  }
3024
3163
 
3025
3164
  const {
3026
- NPM: NPM$c
3027
- } = registryConstants;
3028
- function formatPackageInfo({
3029
- data,
3030
- score,
3031
- severityCount
3165
+ BINARY_LOCK_EXT,
3166
+ BUN: BUN$6,
3167
+ LOCK_EXT: LOCK_EXT$1,
3168
+ NPM: NPM$c,
3169
+ PNPM: PNPM$8,
3170
+ VLT: VLT$6,
3171
+ YARN,
3172
+ YARN_BERRY: YARN_BERRY$6,
3173
+ YARN_CLASSIC: YARN_CLASSIC$6
3174
+ } = constants;
3175
+ const AGENTS = [BUN$6, NPM$c, PNPM$8, YARN_BERRY$6, YARN_CLASSIC$6, VLT$6];
3176
+ const binByAgent = {
3177
+ __proto__: null,
3178
+ [BUN$6]: BUN$6,
3179
+ [NPM$c]: NPM$c,
3180
+ [PNPM$8]: PNPM$8,
3181
+ [YARN_BERRY$6]: YARN,
3182
+ [YARN_CLASSIC$6]: YARN,
3183
+ [VLT$6]: VLT$6
3184
+ };
3185
+ async function getAgentExecPath(agent) {
3186
+ const binName = binByAgent[agent];
3187
+ return (await which(binName, {
3188
+ nothrow: true
3189
+ })) ?? binName;
3190
+ }
3191
+ async function getAgentVersion(agentExecPath, cwd) {
3192
+ let result;
3193
+ try {
3194
+ result = semver.coerce(
3195
+ // All package managers support the "--version" flag.
3196
+ (await spawn.spawn(agentExecPath, ['--version'], {
3197
+ cwd
3198
+ })).stdout) ?? undefined;
3199
+ } catch {}
3200
+ return result;
3201
+ }
3202
+
3203
+ // The order of LOCKS properties IS significant as it affects iteration order.
3204
+ const LOCKS = {
3205
+ [`bun${LOCK_EXT$1}`]: BUN$6,
3206
+ [`bun${BINARY_LOCK_EXT}`]: BUN$6,
3207
+ // If both package-lock.json and npm-shrinkwrap.json are present in the root
3208
+ // of a project, npm-shrinkwrap.json will take precedence and package-lock.json
3209
+ // will be ignored.
3210
+ // https://docs.npmjs.com/cli/v10/configuring-npm/package-lock-json#package-lockjson-vs-npm-shrinkwrapjson
3211
+ 'npm-shrinkwrap.json': NPM$c,
3212
+ 'package-lock.json': NPM$c,
3213
+ 'pnpm-lock.yaml': PNPM$8,
3214
+ 'pnpm-lock.yml': PNPM$8,
3215
+ [`yarn${LOCK_EXT$1}`]: YARN_CLASSIC$6,
3216
+ 'vlt-lock.json': VLT$6,
3217
+ // Lastly, look for a hidden lock file which is present if .npmrc has package-lock=false:
3218
+ // https://docs.npmjs.com/cli/v10/configuring-npm/package-lock-json#hidden-lockfiles
3219
+ //
3220
+ // Unlike the other LOCKS keys this key contains a directory AND filename so
3221
+ // it has to be handled differently.
3222
+ 'node_modules/.package-lock.json': NPM$c
3223
+ };
3224
+ const readLockFileByAgent = (() => {
3225
+ function wrapReader(reader) {
3226
+ return async (...args) => {
3227
+ try {
3228
+ return await reader(...args);
3229
+ } catch {}
3230
+ return undefined;
3231
+ };
3232
+ }
3233
+ const binaryReader = wrapReader(shadowNpmInject.readFileBinary);
3234
+ const defaultReader = wrapReader(async lockPath => await shadowNpmInject.readFileUtf8(lockPath));
3235
+ return {
3236
+ [BUN$6]: wrapReader(async (lockPath, agentExecPath) => {
3237
+ const ext = path.extname(lockPath);
3238
+ if (ext === LOCK_EXT$1) {
3239
+ return await defaultReader(lockPath);
3240
+ }
3241
+ if (ext === BINARY_LOCK_EXT) {
3242
+ const lockBuffer = await binaryReader(lockPath);
3243
+ if (lockBuffer) {
3244
+ try {
3245
+ return index_cjs.parse(lockBuffer);
3246
+ } catch {}
3247
+ }
3248
+ // To print a Yarn lockfile to your console without writing it to disk
3249
+ // use `bun bun.lockb`.
3250
+ // https://bun.sh/guides/install/yarnlock
3251
+ return (await spawn.spawn(agentExecPath, [lockPath])).stdout.trim();
3252
+ }
3253
+ return undefined;
3254
+ }),
3255
+ [NPM$c]: defaultReader,
3256
+ [PNPM$8]: defaultReader,
3257
+ [VLT$6]: defaultReader,
3258
+ [YARN_BERRY$6]: defaultReader,
3259
+ [YARN_CLASSIC$6]: defaultReader
3260
+ };
3261
+ })();
3262
+ async function detectPackageEnvironment({
3263
+ cwd = process$1.cwd(),
3264
+ onUnknown
3265
+ } = {}) {
3266
+ let lockPath = await shadowNpmInject.findUp(Object.keys(LOCKS), {
3267
+ cwd
3268
+ });
3269
+ let lockName = lockPath ? path.basename(lockPath) : undefined;
3270
+ const isHiddenLockFile = lockName === '.package-lock.json';
3271
+ const pkgJsonPath = lockPath ? path.resolve(lockPath, `${isHiddenLockFile ? '../' : ''}../package.json`) : await shadowNpmInject.findUp('package.json', {
3272
+ cwd
3273
+ });
3274
+ const pkgPath = pkgJsonPath && fs.existsSync(pkgJsonPath) ? path.dirname(pkgJsonPath) : undefined;
3275
+ const editablePkgJson = pkgPath ? await packages.readPackageJson(pkgPath, {
3276
+ editable: true
3277
+ }) : undefined;
3278
+ const pkgJson = editablePkgJson?.content;
3279
+ // Read Corepack `packageManager` field in package.json:
3280
+ // https://nodejs.org/api/packages.html#packagemanager
3281
+ const pkgManager = strings.isNonEmptyString(pkgJson?.packageManager) ? pkgJson.packageManager : undefined;
3282
+ let agent;
3283
+ let agentVersion;
3284
+ if (pkgManager) {
3285
+ const atSignIndex = pkgManager.lastIndexOf('@');
3286
+ if (atSignIndex !== -1) {
3287
+ const name = pkgManager.slice(0, atSignIndex);
3288
+ const version = pkgManager.slice(atSignIndex + 1);
3289
+ if (version && AGENTS.includes(name)) {
3290
+ agent = name;
3291
+ agentVersion = semver.coerce(version) ?? undefined;
3292
+ }
3293
+ }
3294
+ }
3295
+ if (agent === undefined && !isHiddenLockFile && typeof pkgJsonPath === 'string' && typeof lockName === 'string') {
3296
+ agent = LOCKS[lockName];
3297
+ }
3298
+ if (agent === undefined) {
3299
+ agent = NPM$c;
3300
+ onUnknown?.(pkgManager);
3301
+ }
3302
+ const agentExecPath = await getAgentExecPath(agent);
3303
+ const npmExecPath = agent === NPM$c ? agentExecPath : await getAgentExecPath(NPM$c);
3304
+ if (agentVersion === undefined) {
3305
+ agentVersion = await getAgentVersion(agentExecPath, cwd);
3306
+ }
3307
+ if (agent === YARN_CLASSIC$6 && (agentVersion?.major ?? 0) > 1) {
3308
+ agent = YARN_BERRY$6;
3309
+ }
3310
+ const targets = {
3311
+ browser: false,
3312
+ node: true
3313
+ };
3314
+ let lockSrc;
3315
+ // Lazily access constants.maintainedNodeVersions.
3316
+ let minimumNodeVersion = constants.maintainedNodeVersions.last;
3317
+ if (pkgJson) {
3318
+ const browserField = pkgJson.browser;
3319
+ if (strings.isNonEmptyString(browserField) || objects.isObjectObject(browserField)) {
3320
+ targets.browser = true;
3321
+ }
3322
+ const nodeRange = pkgJson.engines?.['node'];
3323
+ if (strings.isNonEmptyString(nodeRange)) {
3324
+ const coerced = semver.coerce(nodeRange);
3325
+ if (coerced && semver.lt(coerced, minimumNodeVersion)) {
3326
+ minimumNodeVersion = coerced.version;
3327
+ }
3328
+ }
3329
+ const browserslistQuery = pkgJson['browserslist'];
3330
+ if (Array.isArray(browserslistQuery)) {
3331
+ const browserslistTargets = browserslist(browserslistQuery).map(s => s.toLowerCase()).sort(sorts.naturalCompare);
3332
+ const browserslistNodeTargets = browserslistTargets.filter(v => v.startsWith('node ')).map(v => v.slice(5 /*'node '.length*/));
3333
+ if (!targets.browser && browserslistTargets.length) {
3334
+ targets.browser = browserslistTargets.length !== browserslistNodeTargets.length;
3335
+ }
3336
+ if (browserslistNodeTargets.length) {
3337
+ const coerced = semver.coerce(browserslistNodeTargets[0]);
3338
+ if (coerced && semver.lt(coerced, minimumNodeVersion)) {
3339
+ minimumNodeVersion = coerced.version;
3340
+ }
3341
+ }
3342
+ }
3343
+ // Lazily access constants.maintainedNodeVersions.
3344
+ targets.node = constants.maintainedNodeVersions.some(v => semver.satisfies(v, `>=${minimumNodeVersion}`));
3345
+ lockSrc = typeof lockPath === 'string' ? await readLockFileByAgent[agent](lockPath, agentExecPath) : undefined;
3346
+ } else {
3347
+ lockName = undefined;
3348
+ lockPath = undefined;
3349
+ }
3350
+ return {
3351
+ agent,
3352
+ agentExecPath,
3353
+ agentVersion,
3354
+ lockName,
3355
+ lockPath,
3356
+ lockSrc,
3357
+ minimumNodeVersion,
3358
+ npmExecPath,
3359
+ pkgJson: editablePkgJson,
3360
+ pkgPath,
3361
+ supported: targets.browser || targets.node,
3362
+ targets
3363
+ };
3364
+ }
3365
+
3366
+ const {
3367
+ BUN: BUN$5,
3368
+ VLT: VLT$5,
3369
+ YARN_BERRY: YARN_BERRY$5
3370
+ } = constants;
3371
+ const COMMAND_TITLE$2 = 'Socket Optimize';
3372
+ async function detectAndValidatePackageEnvironment(cwd, options) {
3373
+ const {
3374
+ logger,
3375
+ prod
3376
+ } = {
3377
+ __proto__: null,
3378
+ ...options
3379
+ };
3380
+ const details = await detectPackageEnvironment({
3381
+ cwd,
3382
+ onUnknown(pkgManager) {
3383
+ logger?.warn(`${COMMAND_TITLE$2}: Unknown package manager${pkgManager ? ` ${pkgManager}` : ''}, defaulting to npm`);
3384
+ }
3385
+ });
3386
+ if (!details.supported) {
3387
+ logger?.fail(`${COMMAND_TITLE$2}: No supported Node or browser range detected`);
3388
+ return;
3389
+ }
3390
+ if (details.agent === VLT$5) {
3391
+ logger?.fail(`${COMMAND_TITLE$2}: ${details.agent} does not support overrides. Soon, though ⚡`);
3392
+ return;
3393
+ }
3394
+ const lockName = details.lockName ?? 'lock file';
3395
+ if (details.lockName === undefined || details.lockSrc === undefined) {
3396
+ logger?.fail(`${COMMAND_TITLE$2}: No ${lockName} found`);
3397
+ return;
3398
+ }
3399
+ if (details.lockSrc.trim() === '') {
3400
+ logger?.fail(`${COMMAND_TITLE$2}: ${lockName} is empty`);
3401
+ return;
3402
+ }
3403
+ if (details.pkgPath === undefined) {
3404
+ logger?.fail(`${COMMAND_TITLE$2}: No package.json found`);
3405
+ return;
3406
+ }
3407
+ if (prod && (details.agent === BUN$5 || details.agent === YARN_BERRY$5)) {
3408
+ logger?.fail(`${COMMAND_TITLE$2}: --prod not supported for ${details.agent}${details.agentVersion ? `@${details.agentVersion.toString()}` : ''}`);
3409
+ return;
3410
+ }
3411
+ if (details.lockPath && path.relative(cwd, details.lockPath).startsWith('.')) {
3412
+ logger?.warn(`${COMMAND_TITLE$2}: Package ${lockName} found at ${details.lockPath}`);
3413
+ }
3414
+ return details;
3415
+ }
3416
+
3417
+ const {
3418
+ NPM: NPM$b,
3419
+ PNPM: PNPM$7
3420
+ } = constants;
3421
+ async function runFix() {
3422
+ // Lazily access constants.spinner.
3423
+ const {
3424
+ spinner
3425
+ } = constants;
3426
+ spinner.start();
3427
+ const cwd = process.cwd();
3428
+ const pkgEnvDetails = await detectAndValidatePackageEnvironment(cwd, {
3429
+ logger: logger.logger
3430
+ });
3431
+ if (!pkgEnvDetails) {
3432
+ spinner.stop();
3433
+ return;
3434
+ }
3435
+ switch (pkgEnvDetails.agent) {
3436
+ case NPM$b:
3437
+ {
3438
+ await npmFix(pkgEnvDetails, cwd);
3439
+ break;
3440
+ }
3441
+ case PNPM$7:
3442
+ {
3443
+ await pnpmFix(pkgEnvDetails, cwd);
3444
+ break;
3445
+ }
3446
+ }
3447
+ spinner.successAndStop('Socket.dev fix successful');
3448
+ }
3449
+
3450
+ const {
3451
+ DRY_RUN_BAIL_TEXT: DRY_RUN_BAIL_TEXT$s
3452
+ } = constants;
3453
+ const config$t = {
3454
+ commandName: 'fix',
3455
+ description: 'Fix "fixable" Socket alerts',
3456
+ hidden: true,
3457
+ flags: {
3458
+ ...commonFlags
3459
+ },
3460
+ help: (command, config) => `
3461
+ Usage
3462
+ $ ${command}
3463
+
3464
+ Options
3465
+ ${getFlagListOutput(config.flags, 6)}
3466
+ `
3467
+ };
3468
+ const cmdFix = {
3469
+ description: config$t.description,
3470
+ hidden: config$t.hidden,
3471
+ run: run$t
3472
+ };
3473
+ async function run$t(argv, importMeta, {
3474
+ parentName
3475
+ }) {
3476
+ const cli = meowOrExit({
3477
+ argv,
3478
+ config: config$t,
3479
+ importMeta,
3480
+ parentName
3481
+ });
3482
+ if (cli.flags['dryRun']) {
3483
+ logger.logger.log(DRY_RUN_BAIL_TEXT$s);
3484
+ return;
3485
+ }
3486
+ await runFix();
3487
+ }
3488
+
3489
+ async function fetchPackageInfo(pkgName, pkgVersion, includeAllIssues) {
3490
+ const socketSdk = await shadowNpmInject.setupSdk(shadowNpmInject.getPublicToken());
3491
+ const result = await handleApiCall(socketSdk.getIssuesByNPMPackage(pkgName, pkgVersion), 'looking up package');
3492
+ const scoreResult = await handleApiCall(socketSdk.getScoreByNPMPackage(pkgName, pkgVersion), 'looking up package score');
3493
+ if (result.success === false) {
3494
+ return handleUnsuccessfulApiResponse('getIssuesByNPMPackage', result);
3495
+ }
3496
+ if (scoreResult.success === false) {
3497
+ return handleUnsuccessfulApiResponse('getScoreByNPMPackage', scoreResult);
3498
+ }
3499
+ const severityCount = shadowNpmInject.getSeverityCount(result.data, includeAllIssues ? undefined : 'high');
3500
+ return {
3501
+ data: result.data,
3502
+ severityCount,
3503
+ score: scoreResult.data
3504
+ };
3505
+ }
3506
+
3507
+ const {
3508
+ NPM: NPM$a
3509
+ } = registryConstants;
3510
+ function formatScore(score) {
3511
+ if (score > 80) {
3512
+ return colors.green(`${score}`);
3513
+ } else if (score < 80 && score > 60) {
3514
+ return colors.yellow(`${score}`);
3515
+ }
3516
+ return colors.red(`${score}`);
3517
+ }
3518
+ function logPackageIssuesDetails(packageData, outputMarkdown) {
3519
+ const issueDetails = packageData.filter(d => d.value?.severity === shadowNpmInject.SEVERITY.critical || d.value?.severity === shadowNpmInject.SEVERITY.high);
3520
+ const uniqueIssueDetails = issueDetails.reduce((acc, issue) => {
3521
+ const {
3522
+ type
3523
+ } = issue;
3524
+ if (type) {
3525
+ const details = acc.get(type);
3526
+ if (details) {
3527
+ details.count += 1;
3528
+ } else {
3529
+ acc.set(type, {
3530
+ label: issue.value?.label ?? '',
3531
+ count: 1
3532
+ });
3533
+ }
3534
+ }
3535
+ return acc;
3536
+ }, new Map());
3537
+ const format = new shadowNpmInject.ColorOrMarkdown(outputMarkdown);
3538
+ for (const [type, details] of uniqueIssueDetails.entries()) {
3539
+ const issueWithLink = format.hyperlink(details.label, shadowNpmInject.getSocketDevAlertUrl(type), {
3540
+ fallbackToUrl: true
3541
+ });
3542
+ if (details.count === 1) {
3543
+ logger.logger.log(`- ${issueWithLink}`);
3544
+ } else {
3545
+ logger.logger.log(`- ${issueWithLink}: ${details.count}`);
3546
+ }
3547
+ }
3548
+ }
3549
+ function logPackageInfo({
3550
+ data,
3551
+ score,
3552
+ severityCount
3032
3553
  }, {
3033
3554
  name,
3034
3555
  outputKind,
@@ -3040,10 +3561,13 @@ function formatPackageInfo({
3040
3561
  return;
3041
3562
  }
3042
3563
  if (outputKind === 'markdown') {
3043
- logger.logger.log(`\n# Package report for ${pkgName}\n`);
3044
- logger.logger.log('Package report card:\n');
3564
+ logger.logger.log(commonTags.stripIndents`
3565
+ # Package report for ${pkgName}
3566
+
3567
+ Package report card:
3568
+ `);
3045
3569
  } else {
3046
- logger.logger.log(`\nPackage report card for ${pkgName}:\n`);
3570
+ logger.logger.log(`Package report card for ${pkgName}:`);
3047
3571
  }
3048
3572
  const scoreResult = {
3049
3573
  'Supply Chain Risk': Math.floor(score.supplyChainRisk.score * 100),
@@ -3052,19 +3576,20 @@ function formatPackageInfo({
3052
3576
  Vulnerabilities: Math.floor(score.vulnerability.score * 100),
3053
3577
  License: Math.floor(score.license.score * 100)
3054
3578
  };
3579
+ logger.logger.log('\n');
3055
3580
  Object.entries(scoreResult).map(score => logger.logger.log(`- ${score[0]}: ${formatScore(score[1])}`));
3056
3581
  logger.logger.log('\n');
3057
- if (objectSome(severityCount)) {
3582
+ if (objects.hasKeys(severityCount)) {
3058
3583
  if (outputKind === 'markdown') {
3059
3584
  logger.logger.log('# Issues\n');
3060
3585
  }
3061
- logger.logger.log(`Package has these issues: ${formatSeverityCount(severityCount)}\n`);
3062
- formatPackageIssuesDetails(data, outputKind === 'markdown');
3586
+ logger.logger.log(`Package has these issues: ${shadowNpmInject.formatSeverityCount(severityCount)}\n`);
3587
+ logPackageIssuesDetails(data, outputKind === 'markdown');
3063
3588
  } else {
3064
3589
  logger.logger.log('Package has no issues');
3065
3590
  }
3066
- const format = new index.ColorOrMarkdown(outputKind === 'markdown');
3067
- const url = index.getSocketDevPackageOverviewUrl(NPM$c, pkgName, pkgVersion);
3591
+ const format = new shadowNpmInject.ColorOrMarkdown(outputKind === 'markdown');
3592
+ const url = shadowNpmInject.getSocketDevPackageOverviewUrl(NPM$a, pkgName, pkgVersion);
3068
3593
  logger.logger.log('\n');
3069
3594
  if (pkgVersion === 'latest') {
3070
3595
  logger.logger.log(`Detailed info on socket.dev: ${format.hyperlink(`${pkgName}`, url, {
@@ -3081,44 +3606,6 @@ function formatPackageInfo({
3081
3606
  logger.logger.log('');
3082
3607
  }
3083
3608
  }
3084
- function formatPackageIssuesDetails(packageData, outputMarkdown) {
3085
- const issueDetails = packageData.filter(d => d.value?.severity === 'high' || d.value?.severity === 'critical');
3086
- const uniqueIssues = issueDetails.reduce((acc, issue) => {
3087
- const {
3088
- type
3089
- } = issue;
3090
- if (type) {
3091
- if (acc[type] === undefined) {
3092
- acc[type] = {
3093
- label: issue.value?.label,
3094
- count: 1
3095
- };
3096
- } else {
3097
- acc[type].count += 1;
3098
- }
3099
- }
3100
- return acc;
3101
- }, {});
3102
- const format = new index.ColorOrMarkdown(outputMarkdown);
3103
- for (const issue of Object.keys(uniqueIssues)) {
3104
- const issueWithLink = format.hyperlink(`${uniqueIssues[issue]?.label}`, index.getSocketDevAlertUrl(issue), {
3105
- fallbackToUrl: true
3106
- });
3107
- if (uniqueIssues[issue]?.count === 1) {
3108
- logger.logger.log(`- ${issueWithLink}`);
3109
- } else {
3110
- logger.logger.log(`- ${issueWithLink}: ${uniqueIssues[issue]?.count}`);
3111
- }
3112
- }
3113
- }
3114
- function formatScore(score) {
3115
- if (score > 80) {
3116
- return colors.green(`${score}`);
3117
- } else if (score < 80 && score > 60) {
3118
- return colors.yellow(`${score}`);
3119
- }
3120
- return colors.red(`${score}`);
3121
- }
3122
3609
 
3123
3610
  async function getPackageInfo({
3124
3611
  commandName,
@@ -3128,15 +3615,21 @@ async function getPackageInfo({
3128
3615
  pkgVersion,
3129
3616
  strict
3130
3617
  }) {
3618
+ // Lazily access constants.spinner.
3619
+ const {
3620
+ spinner
3621
+ } = constants;
3622
+ spinner.start(pkgVersion === 'latest' ? `Looking up data for the latest version of ${pkgName}` : `Looking up data for version ${pkgVersion} of ${pkgName}`);
3131
3623
  const packageData = await fetchPackageInfo(pkgName, pkgVersion, includeAllIssues);
3624
+ spinner.successAndStop('Data fetched');
3132
3625
  if (packageData) {
3133
- formatPackageInfo(packageData, {
3626
+ logPackageInfo(packageData, {
3134
3627
  name: commandName,
3135
3628
  outputKind,
3136
3629
  pkgName,
3137
3630
  pkgVersion
3138
3631
  });
3139
- if (strict && objectSome(packageData.severityCount)) {
3632
+ if (strict && objects.hasKeys(packageData.severityCount)) {
3140
3633
  // Let NodeJS exit gracefully but with exit(1)
3141
3634
  process$1.exitCode = 1;
3142
3635
  }
@@ -3193,7 +3686,7 @@ async function run$s(argv, importMeta, {
3193
3686
  // options or missing arguments.
3194
3687
  // https://www.gnu.org/software/bash/manual/html_node/Exit-Status.html
3195
3688
  process.exitCode = 2;
3196
- logger.logger.error(`${colors.bgRed(colors.white('Input error'))}: Please provide the required fields:\n
3689
+ logger.logger.fail(`${colors.bgRed(colors.white('Input error'))}: Please provide the required fields:\n
3197
3690
  - Expecting a package name ${!rawPkgName ? colors.red('(missing!)') : colors.green('(ok)')}\n
3198
3691
  - Can only accept one package at a time ${cli.input.length > 1 ? colors.red('(got ' + cli.input.length + '!)') : colors.green('(ok)')}\n`);
3199
3692
  return;
@@ -3216,18 +3709,18 @@ async function run$s(argv, importMeta, {
3216
3709
  }
3217
3710
 
3218
3711
  function applyLogin(apiToken, enforcedOrgs, apiBaseUrl, apiProxy) {
3219
- index.updateSetting('enforcedOrgs', enforcedOrgs);
3220
- index.updateSetting('apiToken', apiToken);
3221
- index.updateSetting('apiBaseUrl', apiBaseUrl);
3222
- index.updateSetting('apiProxy', apiProxy);
3712
+ shadowNpmInject.updateSetting('enforcedOrgs', enforcedOrgs);
3713
+ shadowNpmInject.updateSetting('apiToken', apiToken);
3714
+ shadowNpmInject.updateSetting('apiBaseUrl', apiBaseUrl);
3715
+ shadowNpmInject.updateSetting('apiProxy', apiProxy);
3223
3716
  }
3224
3717
 
3225
3718
  const {
3226
3719
  SOCKET_PUBLIC_API_TOKEN
3227
3720
  } = constants;
3228
3721
  async function attemptLogin(apiBaseUrl, apiProxy) {
3229
- apiBaseUrl ??= index.getSetting('apiBaseUrl') ?? undefined;
3230
- apiProxy ??= index.getSetting('apiProxy') ?? undefined;
3722
+ apiBaseUrl ??= shadowNpmInject.getSetting('apiBaseUrl') ?? undefined;
3723
+ apiProxy ??= shadowNpmInject.getSetting('apiProxy') ?? undefined;
3231
3724
  const apiToken = (await prompts.password({
3232
3725
  message: `Enter your ${terminalLink('Socket.dev API key', 'https://docs.socket.dev/docs/api-keys')} (leave blank for a public key)`
3233
3726
  })) || SOCKET_PUBLIC_API_TOKEN;
@@ -3238,13 +3731,13 @@ async function attemptLogin(apiBaseUrl, apiProxy) {
3238
3731
  spinner.start('Verifying API key...');
3239
3732
  let orgs;
3240
3733
  try {
3241
- const sdk = await index.setupSdk(apiToken, apiBaseUrl, apiProxy);
3734
+ const sdk = await shadowNpmInject.setupSdk(apiToken, apiBaseUrl, apiProxy);
3242
3735
  const result = await sdk.getOrganizations();
3243
3736
  if (!result.success) {
3244
- throw new index.AuthError();
3737
+ throw new shadowNpmInject.AuthError();
3245
3738
  }
3246
3739
  orgs = result.data;
3247
- spinner.successAndStop('API key verified');
3740
+ spinner.success('API key verified');
3248
3741
  } catch {
3249
3742
  spinner.errorAndStop('Invalid API key');
3250
3743
  return;
@@ -3282,14 +3775,13 @@ async function attemptLogin(apiBaseUrl, apiProxy) {
3282
3775
  }
3283
3776
  }
3284
3777
  }
3285
- const oldToken = index.getSetting('apiToken');
3778
+ spinner.stop();
3779
+ const oldToken = shadowNpmInject.getSetting('apiToken');
3286
3780
  try {
3287
3781
  applyLogin(apiToken, enforcedOrgs, apiBaseUrl, apiProxy);
3288
- spinner.start();
3289
- spinner.successAndStop(`API credentials ${oldToken ? 'updated' : 'set'}`);
3782
+ logger.logger.success(`API credentials ${oldToken ? 'updated' : 'set'}`);
3290
3783
  } catch {
3291
- spinner.start();
3292
- spinner.errorAndStop(`API login failed`);
3784
+ logger.logger.fail(`API login failed`);
3293
3785
  }
3294
3786
  }
3295
3787
 
@@ -3339,23 +3831,23 @@ async function run$r(argv, importMeta, {
3339
3831
  importMeta,
3340
3832
  parentName
3341
3833
  });
3342
- let apiBaseUrl = cli.flags['apiBaseUrl'];
3343
- let apiProxy = cli.flags['apiProxy'];
3834
+ const apiBaseUrl = cli.flags['apiBaseUrl'];
3835
+ const apiProxy = cli.flags['apiProxy'];
3344
3836
  if (cli.flags['dryRun']) {
3345
3837
  logger.logger.log(DRY_RUN_BAIL_TEXT$q);
3346
3838
  return;
3347
3839
  }
3348
3840
  if (!isInteractive()) {
3349
- throw new index.InputError('Cannot prompt for credentials in a non-interactive shell');
3841
+ throw new shadowNpmInject.InputError('Cannot prompt for credentials in a non-interactive shell');
3350
3842
  }
3351
3843
  await attemptLogin(apiBaseUrl, apiProxy);
3352
3844
  }
3353
3845
 
3354
3846
  function applyLogout() {
3355
- index.updateSetting('apiToken', null);
3356
- index.updateSetting('apiBaseUrl', null);
3357
- index.updateSetting('apiProxy', null);
3358
- index.updateSetting('enforcedOrgs', null);
3847
+ shadowNpmInject.updateSetting('apiToken', null);
3848
+ shadowNpmInject.updateSetting('apiBaseUrl', null);
3849
+ shadowNpmInject.updateSetting('apiProxy', null);
3850
+ shadowNpmInject.updateSetting('enforcedOrgs', null);
3359
3851
  }
3360
3852
 
3361
3853
  function attemptLogout() {
@@ -3363,7 +3855,7 @@ function attemptLogout() {
3363
3855
  applyLogout();
3364
3856
  logger.logger.success('Successfully logged out');
3365
3857
  } catch {
3366
- logger.logger.error('Failed to complete logout steps');
3858
+ logger.logger.fail('Failed to complete logout steps');
3367
3859
  }
3368
3860
  }
3369
3861
 
@@ -3445,14 +3937,14 @@ async function convertGradleToMaven(target, bin, _out, verbose, gradleOpts) {
3445
3937
  logger.logger.groupEnd();
3446
3938
  }
3447
3939
  if (output.stderr) {
3448
- logger.logger.error('There were errors while running gradle');
3940
+ process.exitCode = 1;
3941
+ logger.logger.fail('There were errors while running gradle');
3449
3942
  // (In verbose mode, stderr was printed above, no need to repeat it)
3450
3943
  if (!verbose) {
3451
3944
  logger.logger.group('[VERBOSE] stderr:');
3452
3945
  logger.logger.error(output.stderr);
3453
3946
  logger.logger.groupEnd();
3454
3947
  }
3455
- process.exitCode = 1;
3456
3948
  return;
3457
3949
  }
3458
3950
  logger.logger.success('Executed gradle successfully');
@@ -3464,7 +3956,7 @@ async function convertGradleToMaven(target, bin, _out, verbose, gradleOpts) {
3464
3956
 
3465
3957
  // const loc = output.stdout?.match(/Wrote (.*?.pom)\n/)?.[1]?.trim()
3466
3958
  // if (!loc) {
3467
- // logger.error(
3959
+ // logger.fail(
3468
3960
  // 'There were no errors from sbt but could not find the location of resulting .pom file either'
3469
3961
  // )
3470
3962
  // process.exit(1)
@@ -3490,15 +3982,14 @@ async function convertGradleToMaven(target, bin, _out, verbose, gradleOpts) {
3490
3982
  // spinner.successAndStop(`OK. File should be available in \`${out}\``)
3491
3983
  // }
3492
3984
  } catch (e) {
3493
- spinner.errorAndStop('There was an unexpected error while running this' + (verbose ? '' : ' (use --verbose for details)'));
3985
+ process.exitCode = 1;
3986
+ spinner.stop();
3987
+ logger.logger.fail('There was an unexpected error while running this' + (verbose ? '' : ' (use --verbose for details)'));
3494
3988
  if (verbose) {
3495
3989
  logger.logger.group('[VERBOSE] error:');
3496
3990
  logger.logger.log(e);
3497
3991
  logger.logger.groupEnd();
3498
3992
  }
3499
- process.exitCode = 1;
3500
- } finally {
3501
- spinner.stop();
3502
3993
  }
3503
3994
  }
3504
3995
 
@@ -3608,7 +4099,7 @@ async function run$p(argv, importMeta, {
3608
4099
  // options or missing arguments.
3609
4100
  // https://www.gnu.org/software/bash/manual/html_node/Exit-Status.html
3610
4101
  process.exitCode = 2;
3611
- logger.logger.error(commonTags.stripIndents`${colors.bgRed(colors.white('Input error'))}: Please provide the required fields:
4102
+ logger.logger.fail(commonTags.stripIndents`${colors.bgRed(colors.white('Input error'))}: Please provide the required fields:
3612
4103
 
3613
4104
  - The DIR arg is required ${!target ? colors.red('(missing!)') : target === '-' ? colors.red('(stdin is not supported)') : colors.green('(ok)')}
3614
4105
 
@@ -3684,14 +4175,14 @@ async function convertSbtToMaven(target, bin, out, verbose, sbtOpts) {
3684
4175
  logger.logger.groupEnd();
3685
4176
  }
3686
4177
  if (output.stderr) {
3687
- logger.logger.error('There were errors while running sbt');
4178
+ process.exitCode = 1;
4179
+ logger.logger.fail('There were errors while running sbt');
3688
4180
  // (In verbose mode, stderr was printed above, no need to repeat it)
3689
4181
  if (!verbose) {
3690
4182
  logger.logger.group('[VERBOSE] stderr:');
3691
4183
  logger.logger.error(output.stderr);
3692
4184
  logger.logger.groupEnd();
3693
4185
  }
3694
- process.exitCode = 1;
3695
4186
  return;
3696
4187
  }
3697
4188
  const poms = [];
@@ -3700,8 +4191,8 @@ async function convertSbtToMaven(target, bin, out, verbose, sbtOpts) {
3700
4191
  return fn;
3701
4192
  });
3702
4193
  if (!poms.length) {
3703
- logger.logger.error('There were no errors from sbt but it seems to not have generated any poms either');
3704
4194
  process.exitCode = 1;
4195
+ logger.logger.fail('There were no errors from sbt but it seems to not have generated any poms either');
3705
4196
  return;
3706
4197
  }
3707
4198
  // Move the pom file to ...? initial cwd? loc will be an absolute path, or dump to stdout
@@ -3709,14 +4200,14 @@ async function convertSbtToMaven(target, bin, out, verbose, sbtOpts) {
3709
4200
  // TODO: maybe we can add an option to target a specific file to dump to stdout
3710
4201
  if (out === '-' && poms.length === 1) {
3711
4202
  logger.logger.log('Result:\n```');
3712
- logger.logger.log(await index.safeReadFile(poms[0], 'utf8'));
4203
+ logger.logger.log(await shadowNpmInject.safeReadFile(poms[0], 'utf8'));
3713
4204
  logger.logger.log('```');
3714
4205
  logger.logger.success(`OK`);
3715
4206
  } else if (out === '-') {
3716
- logger.logger.error('Requested out target was stdout but there are multiple generated files');
4207
+ process.exitCode = 1;
4208
+ logger.logger.fail('Requested out target was stdout but there are multiple generated files');
3717
4209
  poms.forEach(fn => logger.logger.error('-', fn));
3718
4210
  logger.logger.error('Exiting now...');
3719
- process.exitCode = 1;
3720
4211
  return;
3721
4212
  } else {
3722
4213
  // if (verbose) {
@@ -3733,15 +4224,14 @@ async function convertSbtToMaven(target, bin, out, verbose, sbtOpts) {
3733
4224
  logger.logger.success(`OK`);
3734
4225
  }
3735
4226
  } catch (e) {
3736
- spinner?.errorAndStop('There was an unexpected error while running this' + (verbose ? '' : ' (use --verbose for details)'));
4227
+ process.exitCode = 1;
4228
+ spinner.stop();
4229
+ logger.logger.fail('There was an unexpected error while running this' + (verbose ? '' : ' (use --verbose for details)'));
3737
4230
  if (verbose) {
3738
4231
  logger.logger.group('[VERBOSE] error:');
3739
4232
  logger.logger.log(e);
3740
4233
  logger.logger.groupEnd();
3741
4234
  }
3742
- process.exitCode = 1;
3743
- } finally {
3744
- spinner.stop();
3745
4235
  }
3746
4236
  }
3747
4237
 
@@ -3811,6 +4301,9 @@ const config$o = {
3811
4301
 
3812
4302
  Support is beta. Please report issues or give us feedback on what's missing.
3813
4303
 
4304
+ This is only for SBT. If your Scala setup uses gradle, please see the help
4305
+ sections for \`socket manifest gradle\` or \`socket cdxgen\`.
4306
+
3814
4307
  Examples
3815
4308
 
3816
4309
  $ ${command} ./build.sbt
@@ -3849,7 +4342,7 @@ async function run$o(argv, importMeta, {
3849
4342
  // options or missing arguments.
3850
4343
  // https://www.gnu.org/software/bash/manual/html_node/Exit-Status.html
3851
4344
  process.exitCode = 2;
3852
- logger.logger.error(commonTags.stripIndents`${colors.bgRed(colors.white('Input error'))}: Please provide the required fields:
4345
+ logger.logger.fail(commonTags.stripIndents`${colors.bgRed(colors.white('Input error'))}: Please provide the required fields:
3853
4346
 
3854
4347
  - The DIR or FILE arg is required ${!target ? colors.red('(missing!)') : target === '-' ? colors.red('(stdin is not supported)') : colors.green('(ok)')}
3855
4348
 
@@ -4109,7 +4602,7 @@ async function run$m(argv, importMeta, {
4109
4602
  // options or missing arguments.
4110
4603
  // https://www.gnu.org/software/bash/manual/html_node/Exit-Status.html
4111
4604
  process.exitCode = 2;
4112
- logger.logger.error(commonTags.stripIndents`${colors.bgRed(colors.white('Input error'))}: Please provide the required fields:
4605
+ logger.logger.fail(commonTags.stripIndents`${colors.bgRed(colors.white('Input error'))}: Please provide the required fields:
4113
4606
 
4114
4607
  - The DIR arg is required ${!target ? colors.red('(missing!)') : target === '-' ? colors.red('(stdin is not supported)') : colors.green('(ok)')}
4115
4608
 
@@ -4184,22 +4677,21 @@ async function run$l(argv, importMeta, {
4184
4677
  }
4185
4678
 
4186
4679
  const {
4187
- NPM: NPM$b,
4188
- SHADOW_BIN: SHADOW_BIN$1
4680
+ NPM: NPM$9
4189
4681
  } = constants;
4190
4682
  async function wrapNpm(argv) {
4191
- // Lazily access constants.distPath.
4192
- const shadowBin = require(`${constants.distPath}/${SHADOW_BIN$1}.js`);
4193
- await shadowBin(NPM$b, argv);
4683
+ // Lazily access constants.distShadowNpmBinPath.
4684
+ const shadowBin = require(constants.distShadowNpmBinPath);
4685
+ await shadowBin(NPM$9, argv);
4194
4686
  }
4195
4687
 
4196
4688
  const {
4197
4689
  DRY_RUN_BAIL_TEXT: DRY_RUN_BAIL_TEXT$k,
4198
- NPM: NPM$a
4690
+ NPM: NPM$8
4199
4691
  } = constants;
4200
4692
  const config$k = {
4201
4693
  commandName: 'npm',
4202
- description: `${NPM$a} wrapper functionality`,
4694
+ description: `${NPM$8} wrapper functionality`,
4203
4695
  hidden: false,
4204
4696
  flags: {},
4205
4697
  help: (command, _config) => `
@@ -4230,12 +4722,11 @@ async function run$k(argv, importMeta, {
4230
4722
  }
4231
4723
 
4232
4724
  const {
4233
- NPX: NPX$2,
4234
- SHADOW_BIN
4725
+ NPX: NPX$2
4235
4726
  } = constants;
4236
4727
  async function wrapNpx(argv) {
4237
- // Lazily access constants.distPath.
4238
- const shadowBin = require(`${constants.distPath}/${SHADOW_BIN}.js`);
4728
+ // Lazily access constants.distShadowNpmBinPath.
4729
+ const shadowBin = require(constants.distShadowNpmBinPath);
4239
4730
  await shadowBin(NPX$2, argv);
4240
4731
  }
4241
4732
 
@@ -4298,289 +4789,36 @@ const cmdOops = {
4298
4789
  run: run$i
4299
4790
  };
4300
4791
  async function run$i(argv, importMeta, {
4301
- parentName
4302
- }) {
4303
- const cli = meowOrExit({
4304
- argv,
4305
- config: config$i,
4306
- importMeta,
4307
- parentName
4308
- });
4309
- if (cli.flags['dryRun']) {
4310
- logger.logger.log(DRY_RUN_BAIL_TEXT$i);
4311
- return;
4312
- }
4313
- throw new Error('This error was intentionally left blank');
4314
- }
4315
-
4316
- const {
4317
- BUN: BUN$6,
4318
- NPM: NPM$9,
4319
- PNPM: PNPM$7,
4320
- VLT: VLT$6,
4321
- YARN_BERRY: YARN_BERRY$6,
4322
- YARN_CLASSIC: YARN_CLASSIC$6
4323
- } = constants;
4324
- function matchHumanStdout(stdout, name) {
4325
- return stdout.includes(` ${name}@`);
4326
- }
4327
- function matchQueryStdout(stdout, name) {
4328
- return stdout.includes(`"${name}"`);
4329
- }
4330
- const depsIncludesByAgent = new Map([[BUN$6, matchHumanStdout], [NPM$9, matchQueryStdout], [PNPM$7, matchQueryStdout], [VLT$6, matchQueryStdout], [YARN_BERRY$6, matchHumanStdout], [YARN_CLASSIC$6, matchHumanStdout]]);
4331
-
4332
- const {
4333
- BINARY_LOCK_EXT,
4334
- BUN: BUN$5,
4335
- LOCK_EXT: LOCK_EXT$1,
4336
- NPM: NPM$8,
4337
- PNPM: PNPM$6,
4338
- VLT: VLT$5,
4339
- YARN,
4340
- YARN_BERRY: YARN_BERRY$5,
4341
- YARN_CLASSIC: YARN_CLASSIC$5
4342
- } = constants;
4343
- const AGENTS = [BUN$5, NPM$8, PNPM$6, YARN_BERRY$5, YARN_CLASSIC$5, VLT$5];
4344
- const binByAgent = {
4345
- __proto__: null,
4346
- [BUN$5]: BUN$5,
4347
- [NPM$8]: NPM$8,
4348
- [PNPM$6]: PNPM$6,
4349
- [YARN_BERRY$5]: YARN,
4350
- [YARN_CLASSIC$5]: YARN,
4351
- [VLT$5]: VLT$5
4352
- };
4353
- async function getAgentExecPath(agent) {
4354
- const binName = binByAgent[agent];
4355
- return (await which(binName, {
4356
- nothrow: true
4357
- })) ?? binName;
4358
- }
4359
- async function getAgentVersion(agentExecPath, cwd) {
4360
- let result;
4361
- try {
4362
- result = semver.coerce(
4363
- // All package managers support the "--version" flag.
4364
- (await spawn.spawn(agentExecPath, ['--version'], {
4365
- cwd
4366
- })).stdout) ?? undefined;
4367
- } catch {}
4368
- return result;
4369
- }
4370
-
4371
- // The order of LOCKS properties IS significant as it affects iteration order.
4372
- const LOCKS = {
4373
- [`bun${LOCK_EXT$1}`]: BUN$5,
4374
- [`bun${BINARY_LOCK_EXT}`]: BUN$5,
4375
- // If both package-lock.json and npm-shrinkwrap.json are present in the root
4376
- // of a project, npm-shrinkwrap.json will take precedence and package-lock.json
4377
- // will be ignored.
4378
- // https://docs.npmjs.com/cli/v10/configuring-npm/package-lock-json#package-lockjson-vs-npm-shrinkwrapjson
4379
- 'npm-shrinkwrap.json': NPM$8,
4380
- 'package-lock.json': NPM$8,
4381
- 'pnpm-lock.yaml': PNPM$6,
4382
- 'pnpm-lock.yml': PNPM$6,
4383
- [`yarn${LOCK_EXT$1}`]: YARN_CLASSIC$5,
4384
- 'vlt-lock.json': VLT$5,
4385
- // Lastly, look for a hidden lock file which is present if .npmrc has package-lock=false:
4386
- // https://docs.npmjs.com/cli/v10/configuring-npm/package-lock-json#hidden-lockfiles
4387
- //
4388
- // Unlike the other LOCKS keys this key contains a directory AND filename so
4389
- // it has to be handled differently.
4390
- 'node_modules/.package-lock.json': NPM$8
4391
- };
4392
- const readLockFileByAgent = (() => {
4393
- function wrapReader(reader) {
4394
- return async (...args) => {
4395
- try {
4396
- return await reader(...args);
4397
- } catch {}
4398
- return undefined;
4399
- };
4400
- }
4401
- const binaryReader = wrapReader(index.readFileBinary);
4402
- const defaultReader = wrapReader(async lockPath => await index.readFileUtf8(lockPath));
4403
- return {
4404
- [BUN$5]: wrapReader(async (lockPath, agentExecPath) => {
4405
- const ext = path.extname(lockPath);
4406
- if (ext === LOCK_EXT$1) {
4407
- return await defaultReader(lockPath);
4408
- }
4409
- if (ext === BINARY_LOCK_EXT) {
4410
- const lockBuffer = await binaryReader(lockPath);
4411
- if (lockBuffer) {
4412
- try {
4413
- return index_cjs.parse(lockBuffer);
4414
- } catch {}
4415
- }
4416
- // To print a Yarn lockfile to your console without writing it to disk
4417
- // use `bun bun.lockb`.
4418
- // https://bun.sh/guides/install/yarnlock
4419
- return (await spawn.spawn(agentExecPath, [lockPath])).stdout.trim();
4420
- }
4421
- return undefined;
4422
- }),
4423
- [NPM$8]: defaultReader,
4424
- [PNPM$6]: defaultReader,
4425
- [VLT$5]: defaultReader,
4426
- [YARN_BERRY$5]: defaultReader,
4427
- [YARN_CLASSIC$5]: defaultReader
4428
- };
4429
- })();
4430
- async function detectPackageEnvironment({
4431
- cwd = process$1.cwd(),
4432
- onUnknown
4433
- } = {}) {
4434
- let lockPath = await index.findUp(Object.keys(LOCKS), {
4435
- cwd
4436
- });
4437
- let lockName = lockPath ? path.basename(lockPath) : undefined;
4438
- const isHiddenLockFile = lockName === '.package-lock.json';
4439
- const pkgJsonPath = lockPath ? path.resolve(lockPath, `${isHiddenLockFile ? '../' : ''}../package.json`) : await index.findUp('package.json', {
4440
- cwd
4441
- });
4442
- const pkgPath = pkgJsonPath && fs.existsSync(pkgJsonPath) ? path.dirname(pkgJsonPath) : undefined;
4443
- const editablePkgJson = pkgPath ? await packages.readPackageJson(pkgPath, {
4444
- editable: true
4445
- }) : undefined;
4446
- const pkgJson = editablePkgJson?.content;
4447
- // Read Corepack `packageManager` field in package.json:
4448
- // https://nodejs.org/api/packages.html#packagemanager
4449
- const pkgManager = strings.isNonEmptyString(pkgJson?.packageManager) ? pkgJson.packageManager : undefined;
4450
- let agent;
4451
- let agentVersion;
4452
- if (pkgManager) {
4453
- const atSignIndex = pkgManager.lastIndexOf('@');
4454
- if (atSignIndex !== -1) {
4455
- const name = pkgManager.slice(0, atSignIndex);
4456
- const version = pkgManager.slice(atSignIndex + 1);
4457
- if (version && AGENTS.includes(name)) {
4458
- agent = name;
4459
- agentVersion = semver.coerce(version) ?? undefined;
4460
- }
4461
- }
4462
- }
4463
- if (agent === undefined && !isHiddenLockFile && typeof pkgJsonPath === 'string' && typeof lockName === 'string') {
4464
- agent = LOCKS[lockName];
4465
- }
4466
- if (agent === undefined) {
4467
- agent = NPM$8;
4468
- onUnknown?.(pkgManager);
4469
- }
4470
- const agentExecPath = await getAgentExecPath(agent);
4471
- const npmExecPath = agent === NPM$8 ? agentExecPath : await getAgentExecPath(NPM$8);
4472
- if (agentVersion === undefined) {
4473
- agentVersion = await getAgentVersion(agentExecPath, cwd);
4474
- }
4475
- if (agent === YARN_CLASSIC$5 && (agentVersion?.major ?? 0) > 1) {
4476
- agent = YARN_BERRY$5;
4477
- }
4478
- const targets = {
4479
- browser: false,
4480
- node: true
4481
- };
4482
- let lockSrc;
4483
- // Lazily access constants.maintainedNodeVersions.
4484
- let minimumNodeVersion = constants.maintainedNodeVersions.previous;
4485
- if (pkgJson) {
4486
- const browserField = pkgJson.browser;
4487
- if (strings.isNonEmptyString(browserField) || objects.isObjectObject(browserField)) {
4488
- targets.browser = true;
4489
- }
4490
- const nodeRange = pkgJson.engines?.['node'];
4491
- if (strings.isNonEmptyString(nodeRange)) {
4492
- const coerced = semver.coerce(nodeRange);
4493
- if (coerced && semver.lt(coerced, minimumNodeVersion)) {
4494
- minimumNodeVersion = coerced.version;
4495
- }
4496
- }
4497
- const browserslistQuery = pkgJson['browserslist'];
4498
- if (Array.isArray(browserslistQuery)) {
4499
- const browserslistTargets = browserslist(browserslistQuery).map(s => s.toLowerCase()).sort(sorts.naturalCompare);
4500
- const browserslistNodeTargets = browserslistTargets.filter(v => v.startsWith('node ')).map(v => v.slice(5 /*'node '.length*/));
4501
- if (!targets.browser && browserslistTargets.length) {
4502
- targets.browser = browserslistTargets.length !== browserslistNodeTargets.length;
4503
- }
4504
- if (browserslistNodeTargets.length) {
4505
- const coerced = semver.coerce(browserslistNodeTargets[0]);
4506
- if (coerced && semver.lt(coerced, minimumNodeVersion)) {
4507
- minimumNodeVersion = coerced.version;
4508
- }
4509
- }
4510
- }
4511
- // Lazily access constants.maintainedNodeVersions.
4512
- targets.node = constants.maintainedNodeVersions.some(v => semver.satisfies(v, `>=${minimumNodeVersion}`));
4513
- lockSrc = typeof lockPath === 'string' ? await readLockFileByAgent[agent](lockPath, agentExecPath) : undefined;
4514
- } else {
4515
- lockName = undefined;
4516
- lockPath = undefined;
4792
+ parentName
4793
+ }) {
4794
+ const cli = meowOrExit({
4795
+ argv,
4796
+ config: config$i,
4797
+ importMeta,
4798
+ parentName
4799
+ });
4800
+ if (cli.flags['dryRun']) {
4801
+ logger.logger.log(DRY_RUN_BAIL_TEXT$i);
4802
+ return;
4517
4803
  }
4518
- return {
4519
- agent,
4520
- agentExecPath,
4521
- agentVersion,
4522
- lockName,
4523
- lockPath,
4524
- lockSrc,
4525
- minimumNodeVersion,
4526
- npmExecPath,
4527
- pkgJson: editablePkgJson,
4528
- pkgPath,
4529
- supported: targets.browser || targets.node,
4530
- targets
4531
- };
4804
+ throw new Error('This error was intentionally left blank');
4532
4805
  }
4533
4806
 
4534
4807
  const {
4535
4808
  BUN: BUN$4,
4809
+ NPM: NPM$7,
4810
+ PNPM: PNPM$6,
4536
4811
  VLT: VLT$4,
4537
- YARN_BERRY: YARN_BERRY$4
4812
+ YARN_BERRY: YARN_BERRY$4,
4813
+ YARN_CLASSIC: YARN_CLASSIC$5
4538
4814
  } = constants;
4539
- const COMMAND_TITLE$2 = 'Socket Optimize';
4540
- async function detectAndValidatePackageEnvironment(cwd, options) {
4541
- const {
4542
- logger,
4543
- prod
4544
- } = {
4545
- __proto__: null,
4546
- ...options
4547
- };
4548
- const details = await detectPackageEnvironment({
4549
- cwd,
4550
- onUnknown(pkgManager) {
4551
- logger?.warn(`⚠️ ${COMMAND_TITLE$2}: Unknown package manager${pkgManager ? ` ${pkgManager}` : ''}, defaulting to npm`);
4552
- }
4553
- });
4554
- if (!details.supported) {
4555
- logger?.error(`✖️ ${COMMAND_TITLE$2}: No supported Node or browser range detected`);
4556
- return;
4557
- }
4558
- if (details.agent === VLT$4) {
4559
- logger?.error(`✖️ ${COMMAND_TITLE$2}: ${details.agent} does not support overrides. Soon, though ⚡`);
4560
- return;
4561
- }
4562
- const lockName = details.lockName ?? 'lock file';
4563
- if (details.lockName === undefined || details.lockSrc === undefined) {
4564
- logger?.error(`✖️ ${COMMAND_TITLE$2}: No ${lockName} found`);
4565
- return;
4566
- }
4567
- if (details.lockSrc.trim() === '') {
4568
- logger?.error(`✖️ ${COMMAND_TITLE$2}: ${lockName} is empty`);
4569
- return;
4570
- }
4571
- if (details.pkgPath === undefined) {
4572
- logger?.error(`✖️ ${COMMAND_TITLE$2}: No package.json found`);
4573
- return;
4574
- }
4575
- if (prod && (details.agent === BUN$4 || details.agent === YARN_BERRY$4)) {
4576
- logger?.error(`✖️ ${COMMAND_TITLE$2}: --prod not supported for ${details.agent}${details.agentVersion ? `@${details.agentVersion.toString()}` : ''}`);
4577
- return;
4578
- }
4579
- if (details.lockPath && path.relative(cwd, details.lockPath).startsWith('.')) {
4580
- logger?.warn(`⚠️ ${COMMAND_TITLE$2}: Package ${lockName} found at ${details.lockPath}`);
4581
- }
4582
- return details;
4815
+ function matchLsCmdViewHumanStdout(stdout, name) {
4816
+ return stdout.includes(` ${name}@`);
4583
4817
  }
4818
+ function matchQueryCmdStdout(stdout, name) {
4819
+ return stdout.includes(`"${name}"`);
4820
+ }
4821
+ const depsIncludesByAgent = new Map([[BUN$4, matchLsCmdViewHumanStdout], [NPM$7, matchQueryCmdStdout], [PNPM$6, matchQueryCmdStdout], [VLT$4, matchQueryCmdStdout], [YARN_BERRY$4, matchLsCmdViewHumanStdout], [YARN_CLASSIC$5, matchLsCmdViewHumanStdout]]);
4584
4822
 
4585
4823
  function getDependencyEntries(pkgJson) {
4586
4824
  const {
@@ -4608,7 +4846,7 @@ function getDependencyEntries(pkgJson) {
4608
4846
 
4609
4847
  const {
4610
4848
  BUN: BUN$3,
4611
- NPM: NPM$7,
4849
+ NPM: NPM$6,
4612
4850
  OVERRIDES: OVERRIDES$1,
4613
4851
  PNPM: PNPM$5,
4614
4852
  RESOLUTIONS: RESOLUTIONS$1,
@@ -4629,7 +4867,7 @@ function getOverridesDataBun(pkgJson) {
4629
4867
  function getOverridesDataNpm(pkgJson) {
4630
4868
  const overrides = pkgJson?.[OVERRIDES$1] ?? {};
4631
4869
  return {
4632
- type: NPM$7,
4870
+ type: NPM$6,
4633
4871
  overrides
4634
4872
  };
4635
4873
  }
@@ -4670,7 +4908,7 @@ function getOverridesDataClassic(pkgJson) {
4670
4908
  overrides
4671
4909
  };
4672
4910
  }
4673
- const overridesDataByAgent = new Map([[BUN$3, getOverridesDataBun], [NPM$7, getOverridesDataNpm], [PNPM$5, getOverridesDataPnpm], [VLT$3, getOverridesDataVlt], [YARN_BERRY$3, getOverridesDataYarn], [YARN_CLASSIC$4, getOverridesDataClassic]]);
4911
+ const overridesDataByAgent = new Map([[BUN$3, getOverridesDataBun], [NPM$6, getOverridesDataNpm], [PNPM$5, getOverridesDataPnpm], [VLT$3, getOverridesDataVlt], [YARN_BERRY$3, getOverridesDataYarn], [YARN_CLASSIC$4, getOverridesDataClassic]]);
4674
4912
 
4675
4913
  const {
4676
4914
  PNPM: PNPM$4
@@ -4681,7 +4919,7 @@ async function getWorkspaceGlobs(agent, pkgPath, pkgJson) {
4681
4919
  if (agent === PNPM$4) {
4682
4920
  for (const workspacePath of [path.join(pkgPath, `${PNPM_WORKSPACE}.yaml`), path.join(pkgPath, `${PNPM_WORKSPACE}.yml`)]) {
4683
4921
  // eslint-disable-next-line no-await-in-loop
4684
- const yml = await index.safeReadFile(workspacePath, 'utf8');
4922
+ const yml = await shadowNpmInject.safeReadFile(workspacePath, 'utf8');
4685
4923
  if (yml) {
4686
4924
  try {
4687
4925
  workspacePatterns = yaml.parse(yml)?.packages;
@@ -4718,26 +4956,26 @@ function workspacePatternToGlobPattern(workspace) {
4718
4956
  const {
4719
4957
  BUN: BUN$2,
4720
4958
  LOCK_EXT,
4721
- NPM: NPM$6,
4959
+ NPM: NPM$5,
4722
4960
  PNPM: PNPM$3,
4723
4961
  VLT: VLT$2,
4724
4962
  YARN_BERRY: YARN_BERRY$2,
4725
4963
  YARN_CLASSIC: YARN_CLASSIC$3
4726
4964
  } = constants;
4727
- function lockIncludesNpm(lockSrc, name) {
4965
+ function includesNpm(lockSrc, name) {
4728
4966
  // Detects the package name in the following cases:
4729
4967
  // "name":
4730
4968
  return lockSrc.includes(`"${name}":`);
4731
4969
  }
4732
- function lockIncludesBun(lockSrc, name, lockName) {
4970
+ function includesBun(lockSrc, name, lockName) {
4733
4971
  // This is a bit counterintuitive. When lockName ends with a .lockb
4734
4972
  // we treat it as a yarn.lock. When lockName ends with a .lock we
4735
4973
  // treat it as a package-lock.json. The bun.lock format is not identical
4736
4974
  // package-lock.json, however it close enough for npmLockIncludes to work.
4737
- const lockScanner = lockName?.endsWith(LOCK_EXT) ? lockIncludesNpm : lockIncludesYarn;
4738
- return lockScanner(lockSrc, name);
4975
+ const lockfileScanner = lockName?.endsWith(LOCK_EXT) ? includesNpm : includesYarn;
4976
+ return lockfileScanner(lockSrc, name);
4739
4977
  }
4740
- function lockIncludesPnpm(lockSrc, name) {
4978
+ function includesPnpm(lockSrc, name) {
4741
4979
  const escapedName = regexps.escapeRegExp(name);
4742
4980
  return new RegExp(
4743
4981
  // Detects the package name in the following cases:
@@ -4747,12 +4985,12 @@ function lockIncludesPnpm(lockSrc, name) {
4747
4985
  // name@
4748
4986
  `(?<=^\\s*)(?:(['/])${escapedName}\\1|${escapedName}(?=[:@]))`, 'm').test(lockSrc);
4749
4987
  }
4750
- function lockIncludesVlt(lockSrc, name) {
4988
+ function includesVlt(lockSrc, name) {
4751
4989
  // Detects the package name in the following cases:
4752
4990
  // "name"
4753
4991
  return lockSrc.includes(`"${name}"`);
4754
4992
  }
4755
- function lockIncludesYarn(lockSrc, name) {
4993
+ function includesYarn(lockSrc, name) {
4756
4994
  const escapedName = regexps.escapeRegExp(name);
4757
4995
  return new RegExp(
4758
4996
  // Detects the package name in the following cases:
@@ -4762,11 +5000,11 @@ function lockIncludesYarn(lockSrc, name) {
4762
5000
  // , name@
4763
5001
  `(?<=(?:^\\s*|,\\s*)"?)${escapedName}(?=@)`, 'm').test(lockSrc);
4764
5002
  }
4765
- const lockIncludesByAgent = new Map([[BUN$2, lockIncludesBun], [NPM$6, lockIncludesNpm], [PNPM$3, lockIncludesPnpm], [VLT$2, lockIncludesVlt], [YARN_BERRY$2, lockIncludesYarn], [YARN_CLASSIC$3, lockIncludesYarn]]);
5003
+ const lockfileIncludesByAgent = new Map([[BUN$2, includesBun], [NPM$5, includesNpm], [PNPM$3, includesPnpm], [VLT$2, includesVlt], [YARN_BERRY$2, includesYarn], [YARN_CLASSIC$3, includesYarn]]);
4766
5004
 
4767
5005
  const {
4768
5006
  BUN: BUN$1,
4769
- NPM: NPM$5,
5007
+ NPM: NPM$4,
4770
5008
  PNPM: PNPM$2,
4771
5009
  VLT: VLT$1,
4772
5010
  YARN_BERRY: YARN_BERRY$1,
@@ -4802,11 +5040,11 @@ function cleanupQueryStdout(stdout) {
4802
5040
  }
4803
5041
  return JSON.stringify([...names], null, 2);
4804
5042
  }
4805
- function parseableToQueryStdout(stdout) {
5043
+ function parsableToQueryStdout(stdout) {
4806
5044
  if (stdout === '') {
4807
5045
  return '';
4808
5046
  }
4809
- // Convert the parseable stdout into a json array of unique names.
5047
+ // Convert the parsable stdout into a json array of unique names.
4810
5048
  // The matchAll regexp looks for a forward (posix) or backward (win32) slash
4811
5049
  // and matches one or more non-slashes until the newline.
4812
5050
  const names = new Set(stdout.matchAll(/(?<=[/\\])[^/\\]+(?=\n)/g));
@@ -4836,7 +5074,7 @@ async function lsNpm(agentExecPath, cwd) {
4836
5074
  }
4837
5075
  async function lsPnpm(agentExecPath, cwd, options) {
4838
5076
  const npmExecPath = options?.npmExecPath;
4839
- if (npmExecPath && npmExecPath !== NPM$5) {
5077
+ if (npmExecPath && npmExecPath !== NPM$4) {
4840
5078
  const result = await npmQuery(npmExecPath, cwd);
4841
5079
  if (result) {
4842
5080
  return result;
@@ -4844,15 +5082,19 @@ async function lsPnpm(agentExecPath, cwd, options) {
4844
5082
  }
4845
5083
  let stdout = '';
4846
5084
  try {
4847
- stdout = (await spawn.spawn(agentExecPath, ['ls', '--parseable', '--prod', '--depth', 'Infinity'], {
5085
+ stdout = (await spawn.spawn(agentExecPath,
5086
+ // Pnpm uses the alternative spelling of parsable.
5087
+ // https://en.wiktionary.org/wiki/parsable
5088
+ ['ls', '--parseable', '--prod', '--depth', 'Infinity'], {
4848
5089
  cwd
4849
5090
  })).stdout;
4850
5091
  } catch {}
4851
- return parseableToQueryStdout(stdout);
5092
+ return parsableToQueryStdout(stdout);
4852
5093
  }
4853
5094
  async function lsVlt(agentExecPath, cwd) {
4854
5095
  let stdout = '';
4855
5096
  try {
5097
+ // See https://docs.vlt.sh/cli/commands/list#options.
4856
5098
  stdout = (await spawn.spawn(agentExecPath, ['ls', '--view', 'human', ':not(.dev)'], {
4857
5099
  cwd
4858
5100
  })).stdout;
@@ -4883,20 +5125,39 @@ async function lsYarnClassic(agentExecPath, cwd) {
4883
5125
  } catch {}
4884
5126
  return '';
4885
5127
  }
4886
- const lsByAgent = {
4887
- // @ts-ignore
4888
- __proto__: null,
4889
- [BUN$1]: lsBun,
4890
- [NPM$5]: lsNpm,
4891
- [PNPM$2]: lsPnpm,
4892
- [VLT$1]: lsVlt,
4893
- [YARN_BERRY$1]: lsYarnBerry,
4894
- [YARN_CLASSIC$2]: lsYarnClassic
4895
- };
5128
+ const lsByAgent = new Map([[BUN$1, lsBun], [NPM$4, lsNpm], [PNPM$2, lsPnpm], [VLT$1, lsVlt], [YARN_BERRY$1, lsYarnBerry], [YARN_CLASSIC$2, lsYarnClassic]]);
5129
+
5130
+ const {
5131
+ NPM: NPM$3
5132
+ } = constants;
5133
+ const COMMAND_TITLE$1 = 'Socket Optimize';
5134
+ async function updateLockfile(pkgEnvDetails, options) {
5135
+ const {
5136
+ logger,
5137
+ spinner
5138
+ } = {
5139
+ __proto__: null,
5140
+ ...options
5141
+ };
5142
+ spinner?.start(`Updating ${pkgEnvDetails.lockName}...`);
5143
+ try {
5144
+ await runAgentInstall(pkgEnvDetails, {
5145
+ spinner
5146
+ });
5147
+ spinner?.stop();
5148
+ if (pkgEnvDetails.agent === NPM$3) {
5149
+ logger?.log(`💡 Re-run ${COMMAND_TITLE$1} whenever ${pkgEnvDetails.lockName} changes.\n This can be skipped once npm v11.2.0 is released.`);
5150
+ }
5151
+ } catch (e) {
5152
+ spinner?.stop();
5153
+ logger?.fail(`${COMMAND_TITLE$1}: ${pkgEnvDetails.agent} install failed to update ${pkgEnvDetails.lockName}`);
5154
+ logger?.error(e);
5155
+ }
5156
+ }
4896
5157
 
4897
5158
  const {
4898
5159
  BUN,
4899
- NPM: NPM$4,
5160
+ NPM: NPM$2,
4900
5161
  OVERRIDES,
4901
5162
  PNPM: PNPM$1,
4902
5163
  RESOLUTIONS,
@@ -4916,7 +5177,9 @@ function getHighestEntryIndex(entries, keys) {
4916
5177
  return getEntryIndexes(entries, keys).at(-1) ?? -1;
4917
5178
  }
4918
5179
  function updatePkgJson(editablePkgJson, field, value) {
4919
- const pkgJson = editablePkgJson.content;
5180
+ const {
5181
+ content: pkgJson
5182
+ } = editablePkgJson;
4920
5183
  const oldValue = pkgJson[field];
4921
5184
  if (oldValue) {
4922
5185
  // The field already exists so we simply update the field value.
@@ -4972,205 +5235,43 @@ function updatePkgJson(editablePkgJson, field, value) {
4972
5235
  } else if (field === PNPM_FIELD_NAME) {
4973
5236
  insertIndex = getLowestEntryIndex(entries, [OVERRIDES, RESOLUTIONS]);
4974
5237
  if (insertIndex === -1) {
4975
- isPlacingHigher = true;
4976
- insertIndex = getHighestEntryIndex(entries, depFields);
4977
- }
4978
- }
4979
- if (insertIndex === -1) {
4980
- insertIndex = getLowestEntryIndex(entries, ['engines', 'files']);
4981
- }
4982
- if (insertIndex === -1) {
4983
- isPlacingHigher = true;
4984
- insertIndex = getHighestEntryIndex(entries, ['exports', 'imports', 'main']);
4985
- }
4986
- if (insertIndex === -1) {
4987
- insertIndex = entries.length;
4988
- } else if (isPlacingHigher) {
4989
- insertIndex += 1;
4990
- }
4991
- entries.splice(insertIndex, 0, [field, value]);
4992
- editablePkgJson.fromJSON(`${JSON.stringify(Object.fromEntries(entries), null, 2)}\n`);
4993
- }
4994
- function updateOverrides(editablePkgJson, overrides) {
4995
- updatePkgJson(editablePkgJson, OVERRIDES, overrides);
4996
- }
4997
- function updateResolutions(editablePkgJson, overrides) {
4998
- updatePkgJson(editablePkgJson, RESOLUTIONS, overrides);
4999
- }
5000
- function pnpmUpdatePkgJson(editablePkgJson, overrides) {
5001
- updatePkgJson(editablePkgJson, PNPM_FIELD_NAME, overrides);
5002
- }
5003
- const updateManifestByAgent = new Map([[BUN, updateResolutions], [NPM$4, updateOverrides], [PNPM$1, pnpmUpdatePkgJson], [VLT, updateOverrides], [YARN_BERRY, updateResolutions], [YARN_CLASSIC$1, updateResolutions]]);
5004
-
5005
- const {
5006
- SOCKET_IPC_HANDSHAKE
5007
- } = constants;
5008
- function safeNpmInstall(options) {
5009
- const {
5010
- args = [],
5011
- ipc,
5012
- spinner,
5013
- ...spawnOptions
5014
- } = {
5015
- __proto__: null,
5016
- ...options
5017
- };
5018
- const terminatorPos = args.indexOf('--');
5019
- const npmArgs = (terminatorPos === -1 ? args : args.slice(0, terminatorPos)).filter(a => !npm.isAuditFlag(a) && !npm.isFundFlag(a) && !npm.isProgressFlag(a));
5020
- const otherArgs = terminatorPos === -1 ? [] : args.slice(terminatorPos);
5021
- const useIpc = objects.isObject(ipc);
5022
- const useDebug = debug.isDebug();
5023
- const isSilent = !useDebug && !npmArgs.some(npm.isLoglevelFlag);
5024
- const spawnPromise = spawn.spawn(
5025
- // Lazily access constants.execPath.
5026
- constants.execPath, [
5027
- // Lazily access constants.nodeNoWarningsFlags.
5028
- ...constants.nodeNoWarningsFlags, '--require',
5029
- // Lazily access constants.npmInjectionPath.
5030
- constants.npmInjectionPath, npmPaths.getNpmBinPath(), 'install',
5031
- // Even though the '--silent' flag is passed npm will still run through
5032
- // code paths for 'audit' and 'fund' unless '--no-audit' and '--no-fund'
5033
- // flags are passed.
5034
- '--no-audit', '--no-fund',
5035
- // Add `--no-progress` and `--silent` flags to fix input being swallowed
5036
- // by the spinner when running the command with recent versions of npm.
5037
- '--no-progress',
5038
- // Add the '--silent' flag if a loglevel flag is not provided and the
5039
- // SOCKET_CLI_DEBUG environment variable is not truthy.
5040
- ...(isSilent ? ['--silent'] : []), ...npmArgs, ...otherArgs], {
5041
- spinner,
5042
- // Set stdio to include 'ipc'.
5043
- // See https://github.com/nodejs/node/blob/v23.6.0/lib/child_process.js#L161-L166
5044
- // and https://github.com/nodejs/node/blob/v23.6.0/lib/internal/child_process.js#L238.
5045
- stdio: isSilent ?
5046
- // 'ignore'
5047
- useIpc ? ['ignore', 'ignore', 'ignore', 'ipc'] : 'ignore' :
5048
- // 'inherit'
5049
- useIpc ? [0, 1, 2, 'ipc'] : 'inherit',
5050
- ...spawnOptions,
5051
- env: {
5052
- ...process$1.env,
5053
- ...spawnOptions.env
5054
- }
5055
- });
5056
- if (useIpc) {
5057
- spawnPromise.process.send({
5058
- [SOCKET_IPC_HANDSHAKE]: ipc
5059
- });
5060
- }
5061
- return spawnPromise;
5062
- }
5063
-
5064
- const {
5065
- NPM: NPM$3,
5066
- abortSignal
5067
- } = constants;
5068
- function runAgentInstall(agent, agentExecPath, options) {
5069
- // All package managers support the "install" command.
5070
- if (agent === NPM$3) {
5071
- return safeNpmInstall(options);
5072
- }
5073
- const {
5074
- args = [],
5075
- spinner,
5076
- ...spawnOptions
5077
- } = {
5078
- __proto__: null,
5079
- ...options
5080
- };
5081
- const isSilent = !debug.isDebug();
5082
- return spawn.spawn(agentExecPath, ['install', ...args], {
5083
- signal: abortSignal,
5084
- spinner,
5085
- stdio: isSilent ? 'ignore' : 'inherit',
5086
- ...spawnOptions,
5087
- env: {
5088
- ...process.env,
5089
- ...spawnOptions.env
5090
- }
5091
- });
5092
- }
5093
-
5094
- const {
5095
- NPM: NPM$2
5096
- } = constants;
5097
- const COMMAND_TITLE$1 = 'Socket Optimize';
5098
- async function updatePackageLockJson(pkgEnvDetails, options) {
5099
- const {
5100
- logger,
5101
- spinner
5102
- } = {
5103
- __proto__: null,
5104
- ...options
5105
- };
5106
- spinner?.start(`Updating ${pkgEnvDetails.lockName}...`);
5107
- try {
5108
- await runAgentInstall(pkgEnvDetails.agent, pkgEnvDetails.agentExecPath, {
5109
- spinner
5110
- });
5111
- spinner?.stop();
5112
- if (pkgEnvDetails.agent === NPM$2) {
5113
- logger?.log(`💡 Re-run ${COMMAND_TITLE$1} whenever ${pkgEnvDetails.lockName} changes.\n This can be skipped once npm v11.2.0 is released.`);
5114
- }
5115
- } catch (e) {
5116
- spinner?.stop();
5117
- logger?.error(`${COMMAND_TITLE$1}: ${pkgEnvDetails.agent} install failed to update ${pkgEnvDetails.lockName}`);
5118
- logger?.error(e);
5119
- }
5120
- }
5121
-
5122
- const {
5123
- NPM: NPM$1,
5124
- PNPM,
5125
- YARN_CLASSIC
5126
- } = constants;
5127
- const COMMAND_TITLE = 'Socket Optimize';
5128
- const manifestNpmOverrides = registry.getManifestData(NPM$1);
5129
- async function applyOptimization(cwd, pin, prod) {
5130
- const pkgEnvDetails = await detectAndValidatePackageEnvironment(cwd, {
5131
- logger: logger.logger,
5132
- prod
5133
- });
5134
- if (!pkgEnvDetails) {
5135
- return;
5136
- }
5137
- // Lazily access constants.spinner.
5138
- const {
5139
- spinner
5140
- } = constants;
5141
- spinner.start('Socket optimizing...');
5142
- const state = await addOverrides(pkgEnvDetails.pkgPath, pkgEnvDetails, {
5143
- logger: logger.logger,
5144
- pin,
5145
- prod,
5146
- spinner
5147
- });
5148
- spinner.stop();
5149
- const addedCount = state.added.size;
5150
- const updatedCount = state.updated.size;
5151
- const pkgJsonChanged = addedCount > 0 || updatedCount > 0;
5152
- if (pkgJsonChanged) {
5153
- if (updatedCount > 0) {
5154
- logger.logger?.log(`${createActionMessage('Updated', updatedCount, state.updatedInWorkspaces.size)}${addedCount ? '.' : '🚀'}`);
5155
- }
5156
- if (addedCount > 0) {
5157
- logger.logger?.log(`${createActionMessage('Added', addedCount, state.addedInWorkspaces.size)} 🚀`);
5238
+ isPlacingHigher = true;
5239
+ insertIndex = getHighestEntryIndex(entries, depFields);
5158
5240
  }
5159
- } else {
5160
- logger.logger?.log('Congratulations! Already Socket.dev optimized 🎉');
5161
5241
  }
5162
- if (pkgEnvDetails.agent === NPM$1 || pkgJsonChanged) {
5163
- // Always update package-lock.json until the npm overrides PR lands:
5164
- // https://github.com/npm/cli/pull/8089
5165
- await updatePackageLockJson(pkgEnvDetails, {
5166
- logger: logger.logger,
5167
- spinner
5168
- });
5242
+ if (insertIndex === -1) {
5243
+ insertIndex = getLowestEntryIndex(entries, ['engines', 'files']);
5244
+ }
5245
+ if (insertIndex === -1) {
5246
+ isPlacingHigher = true;
5247
+ insertIndex = getHighestEntryIndex(entries, ['exports', 'imports', 'main']);
5169
5248
  }
5249
+ if (insertIndex === -1) {
5250
+ insertIndex = entries.length;
5251
+ } else if (isPlacingHigher) {
5252
+ insertIndex += 1;
5253
+ }
5254
+ entries.splice(insertIndex, 0, [field, value]);
5255
+ editablePkgJson.fromJSON(`${JSON.stringify(Object.fromEntries(entries), null, 2)}\n`);
5170
5256
  }
5171
- function createActionMessage(verb, overrideCount, workspaceCount) {
5172
- return `${verb} ${overrideCount} Socket.dev optimized ${words.pluralize('override', overrideCount)}${workspaceCount ? ` in ${workspaceCount} ${words.pluralize('workspace', workspaceCount)}` : ''}`;
5257
+ function updateOverrides(editablePkgJson, overrides) {
5258
+ updatePkgJson(editablePkgJson, OVERRIDES, overrides);
5259
+ }
5260
+ function updateResolutions(editablePkgJson, overrides) {
5261
+ updatePkgJson(editablePkgJson, RESOLUTIONS, overrides);
5262
+ }
5263
+ function pnpmUpdatePkgJson(editablePkgJson, overrides) {
5264
+ updatePkgJson(editablePkgJson, PNPM_FIELD_NAME, overrides);
5173
5265
  }
5266
+ const updateManifestByAgent = new Map([[BUN, updateResolutions], [NPM$2, updateOverrides], [PNPM$1, pnpmUpdatePkgJson], [VLT, updateOverrides], [YARN_BERRY, updateResolutions], [YARN_CLASSIC$1, updateResolutions]]);
5267
+
5268
+ const {
5269
+ NPM: NPM$1,
5270
+ PNPM,
5271
+ YARN_CLASSIC
5272
+ } = constants;
5273
+ const COMMAND_TITLE = 'Socket Optimize';
5274
+ const manifestNpmOverrides = registry.getManifestData(NPM$1);
5174
5275
  async function addOverrides(pkgPath, pkgEnvDetails, options) {
5175
5276
  const {
5176
5277
  agent,
@@ -5214,16 +5315,16 @@ async function addOverrides(pkgPath, pkgEnvDetails, options) {
5214
5315
  const isWorkspace = !!workspaceGlobs;
5215
5316
  if (isWorkspace && agent === PNPM && npmExecPath === NPM$1 && !state.warnedPnpmWorkspaceRequiresNpm) {
5216
5317
  state.warnedPnpmWorkspaceRequiresNpm = true;
5217
- logger?.warn(`⚠️ ${COMMAND_TITLE}: pnpm workspace support requires \`npm ls\`, falling back to \`pnpm list\``);
5318
+ logger?.warn(`${COMMAND_TITLE}: pnpm workspace support requires \`npm ls\`, falling back to \`pnpm list\``);
5218
5319
  }
5219
- const thingToScan = isLockScanned ? lockSrc : await lsByAgent[agent](agentExecPath, pkgPath, {
5320
+ const thingToScan = isLockScanned ? lockSrc : await lsByAgent.get(agent)(agentExecPath, pkgPath, {
5220
5321
  npmExecPath
5221
5322
  });
5222
5323
  // The AgentDepsIncludesFn and AgentLockIncludesFn types overlap in their
5223
5324
  // first two parameters. AgentLockIncludesFn accepts an optional third
5224
5325
  // parameter which AgentDepsIncludesFn will ignore so we cast thingScanner
5225
5326
  // as an AgentLockIncludesFn type.
5226
- const thingScanner = isLockScanned ? lockIncludesByAgent.get(agent) : depsIncludesByAgent.get(agent);
5327
+ const thingScanner = isLockScanned ? lockfileIncludesByAgent.get(agent) : depsIncludesByAgent.get(agent);
5227
5328
  const depEntries = getDependencyEntries(pkgJson);
5228
5329
  const overridesDataObjects = [];
5229
5330
  if (pkgJson['private'] || isWorkspace) {
@@ -5349,6 +5450,51 @@ async function addOverrides(pkgPath, pkgEnvDetails, options) {
5349
5450
  }
5350
5451
  return state;
5351
5452
  }
5453
+ function createActionMessage(verb, overrideCount, workspaceCount) {
5454
+ return `${verb} ${overrideCount} Socket.dev optimized ${words.pluralize('override', overrideCount)}${workspaceCount ? ` in ${workspaceCount} ${words.pluralize('workspace', workspaceCount)}` : ''}`;
5455
+ }
5456
+ async function applyOptimization(cwd, pin, prod) {
5457
+ const pkgEnvDetails = await detectAndValidatePackageEnvironment(cwd, {
5458
+ logger: logger.logger,
5459
+ prod
5460
+ });
5461
+ if (!pkgEnvDetails) {
5462
+ return;
5463
+ }
5464
+ // Lazily access constants.spinner.
5465
+ const {
5466
+ spinner
5467
+ } = constants;
5468
+ spinner.start('Socket optimizing...');
5469
+ const state = await addOverrides(pkgEnvDetails.pkgPath, pkgEnvDetails, {
5470
+ logger: logger.logger,
5471
+ pin,
5472
+ prod,
5473
+ spinner
5474
+ });
5475
+ spinner.stop();
5476
+ const addedCount = state.added.size;
5477
+ const updatedCount = state.updated.size;
5478
+ const pkgJsonChanged = addedCount > 0 || updatedCount > 0;
5479
+ if (pkgJsonChanged) {
5480
+ if (updatedCount > 0) {
5481
+ logger.logger?.log(`${createActionMessage('Updated', updatedCount, state.updatedInWorkspaces.size)}${addedCount ? '.' : '🚀'}`);
5482
+ }
5483
+ if (addedCount > 0) {
5484
+ logger.logger?.log(`${createActionMessage('Added', addedCount, state.addedInWorkspaces.size)} 🚀`);
5485
+ }
5486
+ } else {
5487
+ logger.logger?.log('Congratulations! Already Socket.dev optimized 🎉');
5488
+ }
5489
+ if (pkgEnvDetails.agent === NPM$1 || pkgJsonChanged) {
5490
+ // Always update package-lock.json until the npm overrides PR lands:
5491
+ // https://github.com/npm/cli/pull/8089
5492
+ await updateLockfile(pkgEnvDetails, {
5493
+ logger: logger.logger,
5494
+ spinner
5495
+ });
5496
+ }
5497
+ }
5352
5498
 
5353
5499
  const {
5354
5500
  DRY_RUN_BAIL_TEXT: DRY_RUN_BAIL_TEXT$h
@@ -5405,9 +5551,9 @@ async function run$h(argv, importMeta, {
5405
5551
  }
5406
5552
 
5407
5553
  async function getOrganization(format = 'text') {
5408
- const apiToken = index.getDefaultToken();
5554
+ const apiToken = shadowNpmInject.getDefaultToken();
5409
5555
  if (!apiToken) {
5410
- throw new index.AuthError('User must be authenticated to run this command. To log in, run the command `socket login` and enter your API key.');
5556
+ 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.');
5411
5557
  }
5412
5558
  await printOrganizationsFromToken(apiToken, format);
5413
5559
  }
@@ -5417,10 +5563,10 @@ async function printOrganizationsFromToken(apiToken, format = 'text') {
5417
5563
  spinner
5418
5564
  } = constants;
5419
5565
  spinner.start('Fetching organizations...');
5420
- const socketSdk = await index.setupSdk(apiToken);
5566
+ const socketSdk = await shadowNpmInject.setupSdk(apiToken);
5421
5567
  const result = await handleApiCall(socketSdk.getOrganizations(), 'looking up organizations');
5422
5568
  if (!result.success) {
5423
- handleUnsuccessfulApiResponse('getOrganizations', result, spinner);
5569
+ handleUnsuccessfulApiResponse('getOrganizations', result);
5424
5570
  return;
5425
5571
  }
5426
5572
  spinner.stop();
@@ -5511,7 +5657,7 @@ async function run$g(argv, importMeta, {
5511
5657
  // options or missing arguments.
5512
5658
  // https://www.gnu.org/software/bash/manual/html_node/Exit-Status.html
5513
5659
  process.exitCode = 2;
5514
- logger.logger.error(commonTags.stripIndents`
5660
+ logger.logger.fail(commonTags.stripIndents`
5515
5661
  ${colors.bgRed(colors.white('Input error'))}: Please provide the required fields:
5516
5662
 
5517
5663
  - The json and markdown flags cannot be both set, pick one
@@ -5526,7 +5672,7 @@ ${colors.bgRed(colors.white('Input error'))}: Please provide the required fields
5526
5672
  }
5527
5673
 
5528
5674
  async function runRawNpm(argv) {
5529
- const spawnPromise = spawn.spawn(npmPaths.getNpmBinPath(), argv, {
5675
+ const spawnPromise = spawn.spawn(shadowNpmPaths.getNpmBinPath(), argv, {
5530
5676
  stdio: 'inherit'
5531
5677
  });
5532
5678
  // See https://nodejs.org/api/all.html#all_child_process_event-exit.
@@ -5580,7 +5726,7 @@ async function run$f(argv, importMeta, {
5580
5726
  }
5581
5727
 
5582
5728
  async function runRawNpx(argv) {
5583
- const spawnPromise = spawn.spawn(npmPaths.getNpxBinPath(), argv, {
5729
+ const spawnPromise = spawn.spawn(shadowNpmPaths.getNpxBinPath(), argv, {
5584
5730
  stdio: 'inherit'
5585
5731
  });
5586
5732
  // See https://nodejs.org/api/all.html#all_child_process_event-exit.
@@ -5644,16 +5790,16 @@ async function createReport(socketConfig, inputPaths, {
5644
5790
  const {
5645
5791
  spinner
5646
5792
  } = constants;
5647
- const socketSdk = await index.setupSdk();
5793
+ const socketSdk = await shadowNpmInject.setupSdk();
5648
5794
  const supportedFiles = await socketSdk.getReportSupportedFiles().then(res => {
5649
- if (!res.success) handleUnsuccessfulApiResponse('getReportSupportedFiles', res, spinner);
5795
+ if (!res.success) handleUnsuccessfulApiResponse('getReportSupportedFiles', res);
5650
5796
  return res.data;
5651
5797
  }).catch(cause => {
5652
5798
  throw new Error('Failed getting supported files for report', {
5653
5799
  cause
5654
5800
  });
5655
5801
  });
5656
- const packagePaths = await npmPaths.getPackageFilesFullScans(cwd, inputPaths, supportedFiles, socketConfig);
5802
+ const packagePaths = await shadowNpmPaths.getPackageFilesFullScans(cwd, inputPaths, supportedFiles, socketConfig);
5657
5803
  const packagePathsCount = packagePaths.length;
5658
5804
  if (packagePathsCount && debug.isDebug()) {
5659
5805
  for (const pkgPath of packagePaths) {
@@ -5668,7 +5814,7 @@ async function createReport(socketConfig, inputPaths, {
5668
5814
  const apiCall = socketSdk.createReportFromFilePaths(packagePaths, cwd, socketConfig?.issueRules);
5669
5815
  const result = await handleApiCall(apiCall, 'creating report');
5670
5816
  if (!result.success) {
5671
- handleUnsuccessfulApiResponse('createReport', result, spinner);
5817
+ handleUnsuccessfulApiResponse('createReport', result);
5672
5818
  return undefined;
5673
5819
  }
5674
5820
  spinner.successAndStop();
@@ -5686,7 +5832,7 @@ async function getSocketConfig(absoluteConfigPath) {
5686
5832
  errors: cause.validationErrors,
5687
5833
  schema: cause.schema
5688
5834
  });
5689
- throw new index.InputError('The socket.yml config is not valid', betterErrors.map(err => `[${err.path}] ${err.message}.${err.suggestion ? err.suggestion : ''}`).join('\n'));
5835
+ throw new shadowNpmInject.InputError('The socket.yml config is not valid', betterErrors.map(err => `[${err.path}] ${err.message}.${err.suggestion ? err.suggestion : ''}`).join('\n'));
5690
5836
  } else {
5691
5837
  throw new Error('Failed to read socket.yml config', {
5692
5838
  cause
@@ -5704,7 +5850,7 @@ async function fetchReportData(reportId, includeAllIssues, strict) {
5704
5850
  spinner
5705
5851
  } = constants;
5706
5852
  spinner.start(`Fetching report with ID ${reportId} (this could take a while)`);
5707
- const socketSdk = await index.setupSdk();
5853
+ const socketSdk = await shadowNpmInject.setupSdk();
5708
5854
  let result;
5709
5855
  for (let retry = 1; !result; ++retry) {
5710
5856
  try {
@@ -5718,7 +5864,7 @@ async function fetchReportData(reportId, includeAllIssues, strict) {
5718
5864
  }
5719
5865
  }
5720
5866
  if (!result.success) {
5721
- return handleUnsuccessfulApiResponse('getReport', result, spinner);
5867
+ return handleUnsuccessfulApiResponse('getReport', result);
5722
5868
  }
5723
5869
 
5724
5870
  // Conclude the status of the API call.
@@ -5729,8 +5875,8 @@ async function fetchReportData(reportId, includeAllIssues, strict) {
5729
5875
  spinner.error('Report result deemed unhealthy for project');
5730
5876
  }
5731
5877
  } else if (!result.data.healthy) {
5732
- const severityCount = getSeverityCount(result.data.issues, includeAllIssues ? undefined : 'high');
5733
- const issueSummary = formatSeverityCount(severityCount);
5878
+ const severityCount = shadowNpmInject.getSeverityCount(result.data.issues, includeAllIssues ? undefined : 'high');
5879
+ const issueSummary = shadowNpmInject.formatSeverityCount(severityCount);
5734
5880
  spinner.success(`Report has these issues: ${issueSummary}`);
5735
5881
  } else {
5736
5882
  spinner.success('Report has no issues');
@@ -5743,7 +5889,7 @@ function formatReportDataOutput(reportId, data, commandName, outputJson, outputM
5743
5889
  if (outputJson) {
5744
5890
  logger.logger.log(JSON.stringify(data, undefined, 2));
5745
5891
  } else {
5746
- const format = new index.ColorOrMarkdown(outputMarkdown);
5892
+ const format = new shadowNpmInject.ColorOrMarkdown(outputMarkdown);
5747
5893
  logger.logger.log(commonTags.stripIndents`
5748
5894
  Detailed info on socket.dev: ${format.hyperlink(reportId, data.url, {
5749
5895
  fallbackToUrl: true
@@ -5847,7 +5993,7 @@ async function run$d(argv, importMeta, {
5847
5993
  } else if (json) {
5848
5994
  logger.logger.log(JSON.stringify(result.data, undefined, 2));
5849
5995
  } else {
5850
- const format = new index.ColorOrMarkdown(markdown);
5996
+ const format = new shadowNpmInject.ColorOrMarkdown(markdown);
5851
5997
  logger.logger.log(`New report: ${format.hyperlink(result.data.id, result.data.url, {
5852
5998
  fallbackToUrl: true
5853
5999
  })}`);
@@ -5894,7 +6040,7 @@ async function run$c(argv, importMeta, {
5894
6040
  // options or missing arguments.
5895
6041
  // https://www.gnu.org/software/bash/manual/html_node/Exit-Status.html
5896
6042
  process.exitCode = 2;
5897
- logger.logger.error(commonTags.stripIndents`${colors.bgRed(colors.white('Input error'))}: Please provide the required fields:
6043
+ logger.logger.fail(commonTags.stripIndents`${colors.bgRed(colors.white('Input error'))}: Please provide the required fields:
5898
6044
 
5899
6045
  - Need at least one report ID ${!reportId ? colors.red('(missing!)') : colors.green('(ok)')}
5900
6046
 
@@ -5935,13 +6081,33 @@ const cmdReport = {
5935
6081
  };
5936
6082
 
5937
6083
  async function createRepo({
6084
+ default_branch,
6085
+ description,
6086
+ homepage,
6087
+ orgSlug,
6088
+ repoName,
6089
+ visibility
6090
+ }) {
6091
+ const apiToken = shadowNpmInject.getDefaultToken();
6092
+ if (!apiToken) {
6093
+ 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.');
6094
+ }
6095
+ await createRepoWithToken({
6096
+ apiToken,
6097
+ default_branch,
6098
+ description,
6099
+ homepage,
6100
+ orgSlug,
6101
+ repoName,
6102
+ visibility
6103
+ });
6104
+ }
6105
+ async function createRepoWithToken({
5938
6106
  apiToken,
5939
6107
  default_branch,
5940
6108
  description,
5941
6109
  homepage,
5942
6110
  orgSlug,
5943
- outputJson,
5944
- outputMarkdown,
5945
6111
  repoName,
5946
6112
  visibility
5947
6113
  }) {
@@ -5950,22 +6116,19 @@ async function createRepo({
5950
6116
  spinner
5951
6117
  } = constants;
5952
6118
  spinner.start('Creating repository...');
5953
- const socketSdk = await index.setupSdk(apiToken);
6119
+ const socketSdk = await shadowNpmInject.setupSdk(apiToken);
5954
6120
  const result = await handleApiCall(socketSdk.createOrgRepo(orgSlug, {
5955
- outputJson,
5956
- outputMarkdown,
5957
- orgSlug,
5958
6121
  name: repoName,
5959
6122
  description,
5960
6123
  homepage,
5961
6124
  default_branch,
5962
6125
  visibility
5963
6126
  }), 'creating repository');
5964
- if (result.success) {
5965
- spinner.successAndStop('Repository created successfully');
5966
- } else {
5967
- handleUnsuccessfulApiResponse('createOrgRepo', result, spinner);
6127
+ if (!result.success) {
6128
+ handleUnsuccessfulApiResponse('createOrgRepo', result);
6129
+ return;
5968
6130
  }
6131
+ spinner.successAndStop('Repository created successfully');
5969
6132
  }
5970
6133
 
5971
6134
  const {
@@ -5977,7 +6140,6 @@ const config$b = {
5977
6140
  hidden: false,
5978
6141
  flags: {
5979
6142
  ...commonFlags,
5980
- ...outputFlags,
5981
6143
  repoName: {
5982
6144
  type: 'string',
5983
6145
  shortFlag: 'n',
@@ -6041,7 +6203,7 @@ async function run$b(argv, importMeta, {
6041
6203
  // options or missing arguments.
6042
6204
  // https://www.gnu.org/software/bash/manual/html_node/Exit-Status.html
6043
6205
  process.exitCode = 2;
6044
- logger.logger.error(commonTags.stripIndents`${colors.bgRed(colors.white('Input error'))}: Please provide the required fields:
6206
+ logger.logger.fail(commonTags.stripIndents`${colors.bgRed(colors.white('Input error'))}: Please provide the required fields:
6045
6207
 
6046
6208
  - Org name as the first argument ${!orgSlug ? colors.red('(missing!)') : colors.green('(ok)')}
6047
6209
 
@@ -6052,36 +6214,36 @@ async function run$b(argv, importMeta, {
6052
6214
  logger.logger.log(DRY_RUN_BAIL_TEXT$b);
6053
6215
  return;
6054
6216
  }
6055
- const apiToken = index.getDefaultToken();
6056
- if (!apiToken) {
6057
- throw new index.AuthError('User must be authenticated to run this command. To log in, run the command `socket login` and enter your API key.');
6058
- }
6059
6217
  await createRepo({
6060
- outputJson: Boolean(cli.flags['json']),
6061
- outputMarkdown: Boolean(cli.flags['markdown']),
6062
6218
  orgSlug,
6063
6219
  repoName,
6064
6220
  description: String(cli.flags['repoDescription'] || ''),
6065
6221
  homepage: String(cli.flags['homepage'] || ''),
6066
6222
  default_branch: String(cli.flags['defaultBranch'] || ''),
6067
- visibility: String(cli.flags['visibility'] || 'private'),
6068
- apiToken
6223
+ visibility: String(cli.flags['visibility'] || 'private')
6069
6224
  });
6070
6225
  }
6071
6226
 
6072
- async function deleteRepo(orgSlug, repoName, apiToken) {
6227
+ async function deleteRepo(orgSlug, repoName) {
6228
+ const apiToken = shadowNpmInject.getDefaultToken();
6229
+ if (!apiToken) {
6230
+ 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.');
6231
+ }
6232
+ await deleteRepoWithToken(orgSlug, repoName, apiToken);
6233
+ }
6234
+ async function deleteRepoWithToken(orgSlug, repoName, apiToken) {
6073
6235
  // Lazily access constants.spinner.
6074
6236
  const {
6075
6237
  spinner
6076
6238
  } = constants;
6077
6239
  spinner.start('Deleting repository...');
6078
- const socketSdk = await index.setupSdk(apiToken);
6240
+ const socketSdk = await shadowNpmInject.setupSdk(apiToken);
6079
6241
  const result = await handleApiCall(socketSdk.deleteOrgRepo(orgSlug, repoName), 'deleting repository');
6080
- if (result.success) {
6081
- spinner.successAndStop('Repository deleted successfully');
6082
- } else {
6083
- handleUnsuccessfulApiResponse('deleteOrgRepo', result, spinner);
6242
+ if (!result.success) {
6243
+ handleUnsuccessfulApiResponse('deleteOrgRepo', result);
6244
+ return;
6084
6245
  }
6246
+ spinner.successAndStop('Repository deleted successfully');
6085
6247
  }
6086
6248
 
6087
6249
  const {
@@ -6125,7 +6287,7 @@ async function run$a(argv, importMeta, {
6125
6287
  // options or missing arguments.
6126
6288
  // https://www.gnu.org/software/bash/manual/html_node/Exit-Status.html
6127
6289
  process.exitCode = 2;
6128
- logger.logger.error(commonTags.stripIndents`${colors.bgRed(colors.white('Input error'))}: Please provide the required fields:
6290
+ logger.logger.fail(commonTags.stripIndents`${colors.bgRed(colors.white('Input error'))}: Please provide the required fields:
6129
6291
 
6130
6292
  - Org name as the first argument ${!orgSlug ? colors.red('(missing!)') : colors.green('(ok)')}
6131
6293
 
@@ -6138,20 +6300,37 @@ async function run$a(argv, importMeta, {
6138
6300
  logger.logger.log(DRY_RUN_BAIL_TEXT$a);
6139
6301
  return;
6140
6302
  }
6141
- const apiToken = index.getDefaultToken();
6142
- if (!apiToken) {
6143
- throw new index.AuthError('User must be authenticated to run this command. To log in, run the command `socket login` and enter your API key.');
6144
- }
6145
- await deleteRepo(orgSlug, repoName, apiToken);
6303
+ await deleteRepo(orgSlug, repoName);
6146
6304
  }
6147
6305
 
6148
6306
  // @ts-ignore
6149
6307
  async function listRepos({
6308
+ direction,
6309
+ orgSlug,
6310
+ outputKind,
6311
+ page,
6312
+ per_page,
6313
+ sort
6314
+ }) {
6315
+ const apiToken = shadowNpmInject.getDefaultToken();
6316
+ if (!apiToken) {
6317
+ 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.');
6318
+ }
6319
+ await listReposWithToken({
6320
+ apiToken,
6321
+ direction,
6322
+ orgSlug,
6323
+ outputKind,
6324
+ page,
6325
+ per_page,
6326
+ sort
6327
+ });
6328
+ }
6329
+ async function listReposWithToken({
6150
6330
  apiToken,
6151
6331
  direction,
6152
6332
  orgSlug,
6153
- outputJson,
6154
- outputMarkdown,
6333
+ outputKind,
6155
6334
  page,
6156
6335
  per_page,
6157
6336
  sort
@@ -6160,23 +6339,20 @@ async function listRepos({
6160
6339
  const {
6161
6340
  spinner
6162
6341
  } = constants;
6163
- spinner.start('Listing repositories...');
6164
- const socketSdk = await index.setupSdk(apiToken);
6342
+ spinner.start('Fetching list of repositories...');
6343
+ const socketSdk = await shadowNpmInject.setupSdk(apiToken);
6165
6344
  const result = await handleApiCall(socketSdk.getOrgRepoList(orgSlug, {
6166
- outputJson,
6167
- outputMarkdown,
6168
- orgSlug,
6169
6345
  sort,
6170
6346
  direction,
6171
6347
  per_page,
6172
6348
  page
6173
6349
  }), 'listing repositories');
6174
6350
  if (!result.success) {
6175
- handleUnsuccessfulApiResponse('getOrgRepoList', result, spinner);
6351
+ handleUnsuccessfulApiResponse('getOrgRepoList', result);
6176
6352
  return;
6177
6353
  }
6178
- spinner.stop();
6179
- if (outputJson) {
6354
+ spinner.stop('Fetch complete.');
6355
+ if (outputKind === 'json') {
6180
6356
  const data = result.data.results.map(o => ({
6181
6357
  id: o.id,
6182
6358
  name: o.name,
@@ -6273,7 +6449,7 @@ async function run$9(argv, importMeta, {
6273
6449
  // options or missing arguments.
6274
6450
  // https://www.gnu.org/software/bash/manual/html_node/Exit-Status.html
6275
6451
  process.exitCode = 2;
6276
- logger.logger.error(commonTags.stripIndents`${colors.bgRed(colors.white('Input error'))}: Please provide the required fields:
6452
+ logger.logger.fail(commonTags.stripIndents`${colors.bgRed(colors.white('Input error'))}: Please provide the required fields:
6277
6453
 
6278
6454
  - Org name as the first argument ${!orgSlug ? colors.red('(missing!)') : colors.green('(ok)')}
6279
6455
 
@@ -6284,30 +6460,44 @@ async function run$9(argv, importMeta, {
6284
6460
  logger.logger.log(DRY_RUN_BAIL_TEXT$9);
6285
6461
  return;
6286
6462
  }
6287
- const apiToken = index.getDefaultToken();
6288
- if (!apiToken) {
6289
- throw new index.AuthError('User must be authenticated to run this command. To log in, run the command `socket login` and enter your API key.');
6290
- }
6291
6463
  await listRepos({
6292
- apiToken,
6293
- outputJson: Boolean(cli.flags['json']),
6294
- outputMarkdown: Boolean(cli.flags['markdown']),
6295
- orgSlug,
6296
- sort: String(cli.flags['sort'] || 'created_at'),
6297
6464
  direction: cli.flags['direction'] === 'asc' ? 'asc' : 'desc',
6465
+ orgSlug,
6466
+ outputKind: cli.flags['json'] ? 'json' : cli.flags['markdown'] ? 'markdown' : 'print',
6298
6467
  page: Number(cli.flags['page']) || 1,
6299
- per_page: Number(cli.flags['perPage']) || 30
6468
+ per_page: Number(cli.flags['perPage']) || 30,
6469
+ sort: String(cli.flags['sort'] || 'created_at')
6300
6470
  });
6301
6471
  }
6302
6472
 
6303
6473
  async function updateRepo({
6474
+ default_branch,
6475
+ description,
6476
+ homepage,
6477
+ orgSlug,
6478
+ repoName,
6479
+ visibility
6480
+ }) {
6481
+ const apiToken = shadowNpmInject.getDefaultToken();
6482
+ if (!apiToken) {
6483
+ 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.');
6484
+ }
6485
+ await updateRepoWithToken({
6486
+ apiToken,
6487
+ default_branch,
6488
+ description,
6489
+ homepage,
6490
+ orgSlug,
6491
+ repoName,
6492
+ visibility
6493
+ });
6494
+ }
6495
+ async function updateRepoWithToken({
6304
6496
  apiToken,
6305
6497
  default_branch,
6306
6498
  description,
6307
6499
  homepage,
6308
6500
  orgSlug,
6309
- outputJson,
6310
- outputMarkdown,
6311
6501
  repoName,
6312
6502
  visibility
6313
6503
  }) {
@@ -6316,10 +6506,8 @@ async function updateRepo({
6316
6506
  spinner
6317
6507
  } = constants;
6318
6508
  spinner.start('Updating repository...');
6319
- const socketSdk = await index.setupSdk(apiToken);
6509
+ const socketSdk = await shadowNpmInject.setupSdk(apiToken);
6320
6510
  const result = await handleApiCall(socketSdk.updateOrgRepo(orgSlug, repoName, {
6321
- outputJson,
6322
- outputMarkdown,
6323
6511
  orgSlug,
6324
6512
  name: repoName,
6325
6513
  description,
@@ -6327,11 +6515,11 @@ async function updateRepo({
6327
6515
  default_branch,
6328
6516
  visibility
6329
6517
  }), 'updating repository');
6330
- if (result.success) {
6331
- spinner.successAndStop('Repository updated successfully');
6332
- } else {
6333
- handleUnsuccessfulApiResponse('updateOrgRepo', result, spinner);
6518
+ if (!result.success) {
6519
+ handleUnsuccessfulApiResponse('updateOrgRepo', result);
6520
+ return;
6334
6521
  }
6522
+ spinner.successAndStop('Repository updated successfully');
6335
6523
  }
6336
6524
 
6337
6525
  const {
@@ -6343,7 +6531,6 @@ const config$8 = {
6343
6531
  hidden: false,
6344
6532
  flags: {
6345
6533
  ...commonFlags,
6346
- ...outputFlags,
6347
6534
  repoName: {
6348
6535
  type: 'string',
6349
6536
  shortFlag: 'n',
@@ -6407,7 +6594,7 @@ async function run$8(argv, importMeta, {
6407
6594
  // options or missing arguments.
6408
6595
  // https://www.gnu.org/software/bash/manual/html_node/Exit-Status.html
6409
6596
  process.exitCode = 2;
6410
- logger.logger.error(commonTags.stripIndents`${colors.bgRed(colors.white('Input error'))}: Please provide the required fields:
6597
+ logger.logger.fail(commonTags.stripIndents`${colors.bgRed(colors.white('Input error'))}: Please provide the required fields:
6411
6598
 
6412
6599
  - Org name as the first argument ${!orgSlug ? colors.red('(missing!)') : colors.green('(ok)')}
6413
6600
 
@@ -6420,14 +6607,7 @@ async function run$8(argv, importMeta, {
6420
6607
  logger.logger.log(DRY_RUN_BAIL_TEXT$8);
6421
6608
  return;
6422
6609
  }
6423
- const apiToken = index.getDefaultToken();
6424
- if (!apiToken) {
6425
- throw new index.AuthError('User must be authenticated to run this command. To log in, run the command `socket login` and enter your API key.');
6426
- }
6427
6610
  await updateRepo({
6428
- apiToken,
6429
- outputJson: Boolean(cli.flags['json']),
6430
- outputMarkdown: Boolean(cli.flags['markdown']),
6431
6611
  orgSlug,
6432
6612
  repoName,
6433
6613
  description: String(cli.flags['repoDescription'] || ''),
@@ -6438,16 +6618,45 @@ async function run$8(argv, importMeta, {
6438
6618
  }
6439
6619
 
6440
6620
  // @ts-ignore
6441
- async function viewRepo(orgSlug, repoName, apiToken) {
6621
+ async function viewRepo(orgSlug, repoName, outputKind) {
6622
+ const apiToken = shadowNpmInject.getDefaultToken();
6623
+ if (!apiToken) {
6624
+ 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.');
6625
+ }
6626
+ await viewRepoWithToken(orgSlug, repoName, apiToken, outputKind);
6627
+ }
6628
+ async function viewRepoWithToken(orgSlug, repoName, apiToken, outputKind) {
6442
6629
  // Lazily access constants.spinner.
6443
6630
  const {
6444
6631
  spinner
6445
6632
  } = constants;
6446
- spinner.start('Fetching repository...');
6447
- const socketSdk = await index.setupSdk(apiToken);
6633
+ spinner.start('Fetching repository data...');
6634
+ const socketSdk = await shadowNpmInject.setupSdk(apiToken);
6448
6635
  const result = await handleApiCall(socketSdk.getOrgRepo(orgSlug, repoName), 'fetching repository');
6449
6636
  if (!result.success) {
6450
- handleUnsuccessfulApiResponse('getOrgRepo', result, spinner);
6637
+ handleUnsuccessfulApiResponse('getOrgRepo', result);
6638
+ return;
6639
+ }
6640
+ spinner.stop('Fetched repository data.');
6641
+ if (outputKind === 'json') {
6642
+ const {
6643
+ archived,
6644
+ created_at,
6645
+ default_branch,
6646
+ homepage,
6647
+ id,
6648
+ name,
6649
+ visibility
6650
+ } = result.data;
6651
+ logger.logger.log(JSON.stringify({
6652
+ id,
6653
+ name,
6654
+ visibility,
6655
+ default_branch,
6656
+ homepage,
6657
+ archived,
6658
+ created_at
6659
+ }, null, 2));
6451
6660
  return;
6452
6661
  }
6453
6662
  const options = {
@@ -6474,7 +6683,7 @@ async function viewRepo(orgSlug, repoName, apiToken) {
6474
6683
  name: colors.magenta('Created at')
6475
6684
  }]
6476
6685
  };
6477
- spinner.stop(chalkTable(options, [result.data]));
6686
+ logger.logger.log(chalkTable(options, [result.data]));
6478
6687
  }
6479
6688
 
6480
6689
  const {
@@ -6486,7 +6695,12 @@ const config$7 = {
6486
6695
  hidden: false,
6487
6696
  flags: {
6488
6697
  ...commonFlags,
6489
- ...outputFlags
6698
+ ...outputFlags,
6699
+ repoName: {
6700
+ description: 'The repository to check',
6701
+ default: '',
6702
+ type: 'string'
6703
+ }
6490
6704
  },
6491
6705
  help: (command, config) => `
6492
6706
  Usage
@@ -6520,7 +6734,7 @@ async function run$7(argv, importMeta, {
6520
6734
  // options or missing arguments.
6521
6735
  // https://www.gnu.org/software/bash/manual/html_node/Exit-Status.html
6522
6736
  process.exitCode = 2;
6523
- logger.logger.error(commonTags.stripIndents`
6737
+ logger.logger.fail(commonTags.stripIndents`
6524
6738
  ${colors.bgRed(colors.white('Input error'))}: Please provide the required fields:
6525
6739
 
6526
6740
  - Org name as the first argument ${!orgSlug ? colors.red('(missing!)') : colors.green('(ok)')}
@@ -6533,11 +6747,7 @@ async function run$7(argv, importMeta, {
6533
6747
  logger.logger.log(DRY_RUN_BAIL_TEXT$7);
6534
6748
  return;
6535
6749
  }
6536
- const apiToken = index.getDefaultToken();
6537
- if (!apiToken) {
6538
- throw new index.AuthError('User must be authenticated to run this command. To log in, run the command `socket login` and enter your API key.');
6539
- }
6540
- await viewRepo(orgSlug, repoName, apiToken);
6750
+ await viewRepo(orgSlug, repoName, cli.flags['json'] ? 'json' : cli.flags['markdown'] ? 'markdown' : 'print');
6541
6751
  }
6542
6752
 
6543
6753
  const description$1 = 'Repositories related commands';
@@ -6722,10 +6932,10 @@ async function createFullScan({
6722
6932
  const {
6723
6933
  spinner
6724
6934
  } = constants;
6725
- const socketSdk = await index.setupSdk();
6935
+ const socketSdk = await shadowNpmInject.setupSdk();
6726
6936
  const supportedFiles = await socketSdk.getReportSupportedFiles().then(res => {
6727
6937
  if (!res.success) {
6728
- handleUnsuccessfulApiResponse('getReportSupportedFiles', res, spinner);
6938
+ handleUnsuccessfulApiResponse('getReportSupportedFiles', res);
6729
6939
  assert(false, 'handleUnsuccessfulApiResponse should unconditionally throw');
6730
6940
  }
6731
6941
  return res.data;
@@ -6748,14 +6958,14 @@ async function createFullScan({
6748
6958
  // const absoluteConfigPath = path.join(cwd, 'socket.yml')
6749
6959
  // const socketConfig = await getSocketConfig(absoluteConfigPath)
6750
6960
 
6751
- const packagePaths = await npmPaths.getPackageFilesFullScans(cwd, targets, supportedFiles
6961
+ const packagePaths = await shadowNpmPaths.getPackageFilesFullScans(cwd, targets, supportedFiles
6752
6962
  // socketConfig
6753
6963
  );
6754
6964
 
6755
6965
  // We're going to need an api token to suggest data because those suggestions
6756
6966
  // must come from data we already know. Don't error on missing api token yet.
6757
6967
  // If the api-token is not set, ignore it for the sake of suggestions.
6758
- const apiToken = index.getDefaultToken();
6968
+ const apiToken = shadowNpmInject.getDefaultToken();
6759
6969
 
6760
6970
  // If the current cwd is unknown and is used as a repo slug anyways, we will
6761
6971
  // first need to register the slug before we can use it.
@@ -6789,7 +6999,7 @@ async function createFullScan({
6789
6999
  // options or missing arguments.
6790
7000
  // https://www.gnu.org/software/bash/manual/html_node/Exit-Status.html
6791
7001
  process$1.exitCode = 2;
6792
- logger.logger.error(commonTags.stripIndents`
7002
+ logger.logger.fail(commonTags.stripIndents`
6793
7003
  ${colors.bgRed(colors.white('Input error'))}: Please provide the required fields:
6794
7004
 
6795
7005
  - Org name as the first argument ${!orgSlug ? colors.red('(missing!)') : colors.green('(ok)')}
@@ -6811,7 +7021,7 @@ async function createFullScan({
6811
7021
  logger.logger.log('```');
6812
7022
  }
6813
7023
  if (!apiToken) {
6814
- throw new index.AuthError('User must be authenticated to run this command. To log in, run the command `socket login` and enter your API key.');
7024
+ 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.');
6815
7025
  }
6816
7026
  if (readOnly) {
6817
7027
  logger.logger.log('[ReadOnly] Bailing now');
@@ -6827,7 +7037,7 @@ async function createFullScan({
6827
7037
  tmp
6828
7038
  }, packagePaths, cwd), 'Creating scan');
6829
7039
  if (!result.success) {
6830
- handleUnsuccessfulApiResponse('CreateOrgFullScan', result, spinner);
7040
+ handleUnsuccessfulApiResponse('CreateOrgFullScan', result);
6831
7041
  return;
6832
7042
  }
6833
7043
  spinner.successAndStop('Scan created successfully');
@@ -6967,20 +7177,21 @@ async function run$6(argv, importMeta, {
6967
7177
  });
6968
7178
  const [orgSlug = '', ...targets] = cli.input;
6969
7179
  const cwd = cli.flags['cwd'] && cli.flags['cwd'] !== 'process.cwd()' ? String(cli.flags['cwd']) : process$1.cwd();
6970
- let {
7180
+ const {
6971
7181
  branch: branchName,
6972
7182
  repo: repoName
6973
7183
  } = cli.flags;
6974
- const apiToken = index.getDefaultToken(); // This checks if we _can_ suggest anything
7184
+ const apiToken = shadowNpmInject.getDefaultToken(); // This checks if we _can_ suggest anything
6975
7185
 
6976
7186
  if (!apiToken && (!orgSlug || !repoName || !branchName || !targets.length)) {
6977
7187
  // Without api token we cannot recover because we can't request more info
6978
7188
  // from the server, to match and help with the current cwd/git status.
7189
+ //
6979
7190
  // Use exit status of 2 to indicate incorrect usage, generally invalid
6980
7191
  // options or missing arguments.
6981
7192
  // https://www.gnu.org/software/bash/manual/html_node/Exit-Status.html
6982
7193
  process$1.exitCode = 2;
6983
- logger.logger.error(commonTags.stripIndents`
7194
+ logger.logger.fail(commonTags.stripIndents`
6984
7195
  ${colors.bgRed(colors.white('Input error'))}: Please provide the required fields:
6985
7196
 
6986
7197
  - Org name as the first argument ${!orgSlug ? colors.red('(missing!)') : colors.green('(ok)')}
@@ -7019,9 +7230,9 @@ async function run$6(argv, importMeta, {
7019
7230
  }
7020
7231
 
7021
7232
  async function deleteOrgFullScan(orgSlug, fullScanId) {
7022
- const apiToken = index.getDefaultToken();
7233
+ const apiToken = shadowNpmInject.getDefaultToken();
7023
7234
  if (!apiToken) {
7024
- throw new index.AuthError('User must be authenticated to run this command. To log in, run the command `socket login` and enter your API key.');
7235
+ 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.');
7025
7236
  }
7026
7237
  await deleteOrgFullScanWithToken(orgSlug, fullScanId, apiToken);
7027
7238
  }
@@ -7031,10 +7242,10 @@ async function deleteOrgFullScanWithToken(orgSlug, fullScanId, apiToken) {
7031
7242
  spinner
7032
7243
  } = constants;
7033
7244
  spinner.start('Deleting scan...');
7034
- const socketSdk = await index.setupSdk(apiToken);
7245
+ const socketSdk = await shadowNpmInject.setupSdk(apiToken);
7035
7246
  const result = await handleApiCall(socketSdk.deleteOrgFullScan(orgSlug, fullScanId), 'Deleting scan');
7036
7247
  if (!result.success) {
7037
- handleUnsuccessfulApiResponse('deleteOrgFullScan', result, spinner);
7248
+ handleUnsuccessfulApiResponse('deleteOrgFullScan', result);
7038
7249
  return;
7039
7250
  }
7040
7251
  spinner.successAndStop('Scan deleted successfully');
@@ -7082,7 +7293,7 @@ async function run$5(argv, importMeta, {
7082
7293
  // options or missing arguments.
7083
7294
  // https://www.gnu.org/software/bash/manual/html_node/Exit-Status.html
7084
7295
  process.exitCode = 2;
7085
- logger.logger.error(commonTags.stripIndents`${colors.bgRed(colors.white('Input error'))}: Please provide the required fields:
7296
+ logger.logger.fail(commonTags.stripIndents`${colors.bgRed(colors.white('Input error'))}: Please provide the required fields:
7086
7297
 
7087
7298
  - Org name as the first argument ${!orgSlug ? colors.red('(missing!)') : colors.green('(ok)')}
7088
7299
 
@@ -7106,9 +7317,9 @@ async function listFullScans({
7106
7317
  per_page,
7107
7318
  sort
7108
7319
  }) {
7109
- const apiToken = index.getDefaultToken();
7320
+ const apiToken = shadowNpmInject.getDefaultToken();
7110
7321
  if (!apiToken) {
7111
- throw new index.AuthError('User must be authenticated to run this command. To log in, run the command `socket login` and enter your API key.');
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.');
7112
7323
  }
7113
7324
  await listFullScansWithToken({
7114
7325
  apiToken,
@@ -7136,7 +7347,7 @@ async function listFullScansWithToken({
7136
7347
  spinner
7137
7348
  } = constants;
7138
7349
  spinner.start('Fetching list of scans...');
7139
- const socketSdk = await index.setupSdk(apiToken);
7350
+ const socketSdk = await shadowNpmInject.setupSdk(apiToken);
7140
7351
  const result = await handleApiCall(socketSdk.getOrgFullScanList(orgSlug, {
7141
7352
  sort,
7142
7353
  direction,
@@ -7145,7 +7356,7 @@ async function listFullScansWithToken({
7145
7356
  from: from_time
7146
7357
  }), 'Listing scans');
7147
7358
  if (!result.success) {
7148
- handleUnsuccessfulApiResponse('getOrgFullScanList', result, spinner);
7359
+ handleUnsuccessfulApiResponse('getOrgFullScanList', result);
7149
7360
  return;
7150
7361
  }
7151
7362
  spinner.stop(`Fetch complete`);
@@ -7261,7 +7472,7 @@ async function run$4(argv, importMeta, {
7261
7472
  // options or missing arguments.
7262
7473
  // https://www.gnu.org/software/bash/manual/html_node/Exit-Status.html
7263
7474
  process.exitCode = 2;
7264
- logger.logger.error(commonTags.stripIndents`${colors.bgRed(colors.white('Input error'))}: Please provide the required fields:
7475
+ logger.logger.fail(commonTags.stripIndents`${colors.bgRed(colors.white('Input error'))}: Please provide the required fields:
7265
7476
 
7266
7477
  - Org name as the argument ${!orgSlug ? colors.red('(missing!)') : colors.green('(ok)')}`);
7267
7478
  return;
@@ -7282,9 +7493,9 @@ async function run$4(argv, importMeta, {
7282
7493
  }
7283
7494
 
7284
7495
  async function getOrgScanMetadata(orgSlug, scanId, outputKind) {
7285
- const apiToken = index.getDefaultToken();
7496
+ const apiToken = shadowNpmInject.getDefaultToken();
7286
7497
  if (!apiToken) {
7287
- throw new index.AuthError('User must be authenticated to run this command. To log in, run the command `socket login` and enter your API key.');
7498
+ 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.');
7288
7499
  }
7289
7500
  await getOrgScanMetadataWithToken(orgSlug, scanId, apiToken, outputKind);
7290
7501
  }
@@ -7294,10 +7505,10 @@ async function getOrgScanMetadataWithToken(orgSlug, scanId, apiToken, outputKind
7294
7505
  spinner
7295
7506
  } = constants;
7296
7507
  spinner.start('Fetching meta data for a full scan...');
7297
- const socketSdk = await index.setupSdk(apiToken);
7508
+ const socketSdk = await shadowNpmInject.setupSdk(apiToken);
7298
7509
  const result = await handleApiCall(socketSdk.getOrgFullScanMetadata(orgSlug, scanId), 'Listing scans');
7299
7510
  if (!result.success) {
7300
- handleUnsuccessfulApiResponse('getOrgFullScanMetadata', result, spinner);
7511
+ handleUnsuccessfulApiResponse('getOrgFullScanMetadata', result);
7301
7512
  return;
7302
7513
  }
7303
7514
  spinner?.successAndStop('Fetched the meta data\n');
@@ -7363,7 +7574,7 @@ async function run$3(argv, importMeta, {
7363
7574
  // options or missing arguments.
7364
7575
  // https://www.gnu.org/software/bash/manual/html_node/Exit-Status.html
7365
7576
  process.exitCode = 2;
7366
- logger.logger.error(commonTags.stripIndents`${colors.bgRed(colors.white('Input error'))}: Please provide the required fields:
7577
+ logger.logger.fail(commonTags.stripIndents`${colors.bgRed(colors.white('Input error'))}: Please provide the required fields:
7367
7578
 
7368
7579
  - Org name as the first argument ${!orgSlug ? colors.red('(missing!)') : colors.green('(ok)')}
7369
7580
 
@@ -7382,15 +7593,15 @@ async function streamFullScan(orgSlug, fullScanId, file) {
7382
7593
  const {
7383
7594
  spinner
7384
7595
  } = constants;
7385
- const apiToken = index.getDefaultToken();
7596
+ const apiToken = shadowNpmInject.getDefaultToken();
7386
7597
  if (!apiToken) {
7387
- throw new index.AuthError('User must be authenticated to run this command. To log in, run the command `socket login` and enter your API key.');
7598
+ 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.');
7388
7599
  }
7389
7600
  spinner.start('Fetching scan...');
7390
- const socketSdk = await index.setupSdk(apiToken);
7601
+ const socketSdk = await shadowNpmInject.setupSdk(apiToken);
7391
7602
  const data = await handleApiCall(socketSdk.getOrgFullScan(orgSlug, fullScanId, file === '-' ? undefined : file), 'Fetching a scan');
7392
7603
  if (!data?.success) {
7393
- handleUnsuccessfulApiResponse('getOrgFullScan', data, spinner);
7604
+ handleUnsuccessfulApiResponse('getOrgFullScan', data);
7394
7605
  return;
7395
7606
  }
7396
7607
  spinner?.successAndStop(file ? `Full scan details written to ${file}` : 'stdout');
@@ -7402,16 +7613,16 @@ async function getFullScan(orgSlug, fullScanId) {
7402
7613
  const {
7403
7614
  spinner
7404
7615
  } = constants;
7405
- const apiToken = index.getDefaultToken();
7616
+ const apiToken = shadowNpmInject.getDefaultToken();
7406
7617
  if (!apiToken) {
7407
- throw new index.AuthError('User must be authenticated to run this command. To log in, run the command `socket login` and enter your API key.');
7618
+ throw new shadowNpmInject.AuthError('User must be authenticated to run this command. To log in, run the command `socket login` and enter your API key.');
7408
7619
  }
7409
7620
  spinner.start('Fetching full-scan...');
7410
7621
  const response = await queryAPI(`orgs/${orgSlug}/full-scans/${encodeURIComponent(fullScanId)}`, apiToken);
7411
7622
  spinner.stop('Fetch complete.');
7412
7623
  if (!response.ok) {
7413
7624
  const err = await handleAPIError(response.status);
7414
- logger.logger.error(`${colors.bgRed(colors.white(response.statusText))}: Fetch error: ${err}`);
7625
+ logger.logger.fail(`${colors.bgRed(colors.white(response.statusText))}: Fetch error: ${err}`);
7415
7626
  return;
7416
7627
  }
7417
7628
 
@@ -7459,9 +7670,9 @@ View this report at: https://socket.dev/dashboard/org/${orgSlug}/sbom/${fullScan
7459
7670
  await fs$1.writeFile(filePath, report, 'utf8');
7460
7671
  logger.logger.log(`Data successfully written to ${filePath}`);
7461
7672
  } catch (e) {
7462
- logger.logger.error('There was an error trying to write the json to disk');
7463
- logger.logger.error(e);
7464
7673
  process.exitCode = 1;
7674
+ logger.logger.fail('There was an error trying to write the json to disk');
7675
+ logger.logger.error(e);
7465
7676
  }
7466
7677
  } else {
7467
7678
  logger.logger.log(report);
@@ -7512,7 +7723,7 @@ async function run$2(argv, importMeta, {
7512
7723
  // options or missing arguments.
7513
7724
  // https://www.gnu.org/software/bash/manual/html_node/Exit-Status.html
7514
7725
  process.exitCode = 2;
7515
- logger.logger.error(commonTags.stripIndents`
7726
+ logger.logger.fail(commonTags.stripIndents`
7516
7727
  ${colors.bgRed(colors.white('Input error'))}: Please provide the required fields:
7517
7728
 
7518
7729
  - Org name as the first argument ${!orgSlug ? colors.red('(missing!)') : colors.green('(ok)')}
@@ -7561,11 +7772,36 @@ const cmdScan = {
7561
7772
  }
7562
7773
  };
7563
7774
 
7775
+ // Note: Widgets does not seem to actually work as code :'(
7776
+
7564
7777
  async function getThreatFeed({
7778
+ direction,
7779
+ ecosystem,
7780
+ filter,
7781
+ outputKind,
7782
+ page,
7783
+ perPage
7784
+ }) {
7785
+ const apiToken = shadowNpmInject.getDefaultToken();
7786
+ if (!apiToken) {
7787
+ 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.');
7788
+ }
7789
+ await getThreatFeedWithToken({
7790
+ apiToken,
7791
+ direction,
7792
+ ecosystem,
7793
+ filter,
7794
+ outputKind,
7795
+ page,
7796
+ perPage
7797
+ });
7798
+ }
7799
+ async function getThreatFeedWithToken({
7565
7800
  apiToken,
7566
7801
  direction,
7802
+ ecosystem,
7567
7803
  filter,
7568
- outputJson,
7804
+ outputKind,
7569
7805
  page,
7570
7806
  perPage
7571
7807
  }) {
@@ -7573,17 +7809,12 @@ async function getThreatFeed({
7573
7809
  const {
7574
7810
  spinner
7575
7811
  } = constants;
7576
- spinner.start('Looking up the threat feed');
7577
- const formattedQueryParams = formatQueryParams({
7578
- per_page: perPage,
7579
- page,
7580
- direction,
7581
- filter
7582
- }).join('&');
7583
- const response = await queryAPI(`threat-feed?${formattedQueryParams}`, apiToken);
7812
+ const queryParams = new URLSearchParams([['direction', direction], ['ecosystem', ecosystem], ['filter', filter], ['page', page], ['per_page', String(perPage)]]);
7813
+ spinner.start('Fetching Threat Feed data...');
7814
+ const response = await queryAPI(`threat-feed?${queryParams}`, apiToken);
7584
7815
  const data = await response.json();
7585
- spinner.stop();
7586
- if (outputJson) {
7816
+ spinner.stop('Threat feed data fetched');
7817
+ if (outputKind === 'json') {
7587
7818
  logger.logger.log(data);
7588
7819
  return;
7589
7820
  }
@@ -7596,47 +7827,98 @@ async function getThreatFeed({
7596
7827
  interactive: 'true',
7597
7828
  label: 'Threat feed',
7598
7829
  width: '100%',
7599
- height: '100%',
7830
+ height: '70%',
7831
+ // Changed from 100% to 70%
7832
+ border: {
7833
+ type: 'line',
7834
+ fg: 'cyan'
7835
+ },
7836
+ columnWidth: [10, 30, 20, 18, 15, 200],
7837
+ // TODO: the truncation doesn't seem to work too well yet but when we add
7838
+ // `pad` alignment fails, when we extend columnSpacing alignment fails
7839
+ columnSpacing: 1,
7840
+ truncate: '_'
7841
+ });
7842
+
7843
+ // Create details box at the bottom
7844
+ const detailsBox = new BoxWidget({
7845
+ bottom: 0,
7846
+ height: '30%',
7847
+ width: '100%',
7600
7848
  border: {
7601
7849
  type: 'line',
7602
7850
  fg: 'cyan'
7603
7851
  },
7604
- columnSpacing: 3,
7605
- //in chars
7606
- columnWidth: [9, 30, 10, 17, 13, 100] /*in chars*/
7852
+ label: 'Details',
7853
+ content: 'Use arrow keys to navigate. Press Enter to select a threat. Press q to exit.',
7854
+ style: {
7855
+ fg: 'white'
7856
+ }
7607
7857
  });
7608
7858
 
7609
7859
  // allow control the table with the keyboard
7610
7860
  table.focus();
7611
7861
  screen.append(table);
7862
+ screen.append(detailsBox);
7612
7863
  const formattedOutput = formatResults(data.results);
7864
+ const descriptions = data.results.map(d => d.description);
7613
7865
  table.setData({
7614
- headers: ['Ecosystem', 'Name', 'Version', 'Threat type', 'Detected at', 'Details'],
7866
+ headers: [' Ecosystem', ' Name', ' Version', ' Threat type', ' Detected at', ' Details'],
7615
7867
  data: formattedOutput
7616
7868
  });
7869
+
7870
+ // Update details box when selection changes
7871
+ table.rows.on('select item', () => {
7872
+ const selectedIndex = table.rows.selected;
7873
+ if (selectedIndex !== undefined && selectedIndex >= 0) {
7874
+ const selectedRow = formattedOutput[selectedIndex];
7875
+ if (selectedRow) {
7876
+ // Note: the spacing works around issues with the table; it refuses to pad!
7877
+ detailsBox.setContent(`Ecosystem: ${selectedRow[0]}\n` + `Name: ${selectedRow[1]}\n` + `Version:${selectedRow[2]}\n` + `Threat type:${selectedRow[3]}\n` + `Detected at:${selectedRow[4]}\n` + `Details: ${selectedRow[5]}\n` + `Description: ${descriptions[selectedIndex]}`);
7878
+ screen.render();
7879
+ }
7880
+ }
7881
+ });
7617
7882
  screen.render();
7618
7883
  screen.key(['escape', 'q', 'C-c'], () => process$1.exit(0));
7884
+ screen.key(['return'], () => {
7885
+ const selectedIndex = table.rows.selected;
7886
+ screen.destroy();
7887
+ const selectedRow = formattedOutput[selectedIndex];
7888
+ console.log(selectedRow);
7889
+ });
7619
7890
  }
7620
7891
  function formatResults(data) {
7621
7892
  return data.map(d => {
7622
7893
  const ecosystem = d.purl.split('pkg:')[1].split('/')[0];
7623
7894
  const name = d.purl.split('/')[1].split('@')[0];
7624
7895
  const version = d.purl.split('@')[1];
7625
- const timeStart = new Date(d.createdAt).getMilliseconds();
7626
- const timeEnd = Date.now();
7627
- const diff = getHourDiff(timeStart, timeEnd);
7628
- const hourDiff = diff > 0 ? `${diff} hours ago` : `${getMinDiff(timeStart, timeEnd)} minutes ago`;
7629
- return [ecosystem, decodeURIComponent(name), version, d.threatType, hourDiff, d.locationHtmlUrl];
7896
+ const timeDiff = msAtHome(d.createdAt);
7897
+
7898
+ // Note: the spacing works around issues with the table; it refuses to pad!
7899
+ return [ecosystem, decodeURIComponent(name), ` ${version}`, ` ${d.threatType}`, ` ${timeDiff}`, d.locationHtmlUrl];
7630
7900
  });
7631
7901
  }
7632
- function formatQueryParams(params) {
7633
- return Object.entries(params).map(entry => `${entry[0]}=${entry[1]}`);
7634
- }
7635
- function getHourDiff(start, end) {
7636
- return Math.floor((end - start) / 3600000);
7637
- }
7638
- function getMinDiff(start, end) {
7639
- return Math.floor((end - start) / 60000);
7902
+ function msAtHome(isoTimeStamp) {
7903
+ const timeStart = Date.parse(isoTimeStamp);
7904
+ const timeEnd = Date.now();
7905
+ const rtf = new Intl.RelativeTimeFormat('en', {
7906
+ numeric: 'always',
7907
+ style: 'short'
7908
+ });
7909
+ const delta = timeEnd - timeStart;
7910
+ if (delta < 60 * 60 * 1000) {
7911
+ return rtf.format(-Math.round(delta / (60 * 1000)), 'minute');
7912
+ // return Math.round(delta / (60 * 1000)) + ' min ago'
7913
+ } else if (delta < 24 * 60 * 60 * 1000) {
7914
+ return rtf.format(-(delta / (60 * 60 * 1000)).toFixed(1), 'hour');
7915
+ // return (delta / (60 * 60 * 1000)).toFixed(1) + ' hr ago'
7916
+ } else if (delta < 7 * 24 * 60 * 60 * 1000) {
7917
+ return rtf.format(-(delta / (24 * 60 * 60 * 1000)).toFixed(1), 'day');
7918
+ // return (delta / (24 * 60 * 60 * 1000)).toFixed(1) + ' day ago'
7919
+ } else {
7920
+ return isoTimeStamp.slice(0, 10);
7921
+ }
7640
7922
  }
7641
7923
 
7642
7924
  const {
@@ -7644,7 +7926,7 @@ const {
7644
7926
  } = constants;
7645
7927
  const config$1 = {
7646
7928
  commandName: 'threat-feed',
7647
- description: 'Look up the threat feed',
7929
+ description: '[beta] View the threat feed',
7648
7930
  hidden: false,
7649
7931
  flags: {
7650
7932
  ...commonFlags,
@@ -7667,6 +7949,12 @@ const config$1 = {
7667
7949
  default: 'desc',
7668
7950
  description: 'Order asc or desc by the createdAt attribute.'
7669
7951
  },
7952
+ eco: {
7953
+ type: 'string',
7954
+ shortFlag: 'e',
7955
+ default: '',
7956
+ description: 'Only show threats for a particular ecosystem'
7957
+ },
7670
7958
  filter: {
7671
7959
  type: 'string',
7672
7960
  shortFlag: 'f',
@@ -7678,9 +7966,35 @@ const config$1 = {
7678
7966
  Usage
7679
7967
  $ ${command}
7680
7968
 
7969
+ This feature requires a Threat Feed license. Please contact
7970
+ sales@socket.dev if you are interested in purchasing this access.
7971
+
7681
7972
  Options
7682
7973
  ${getFlagListOutput(config.flags, 6)}
7683
7974
 
7975
+ Valid filters:
7976
+
7977
+ - anom Anomaly
7978
+ - c Do not filter
7979
+ - fp False Positives
7980
+ - joke Joke / Fake
7981
+ - mal Malware and Possible Malware [default]
7982
+ - secret Secrets
7983
+ - spy Telemetry
7984
+ - tp False Positives and Unreviewed
7985
+ - typo Typo-squat
7986
+ - u Unreviewed
7987
+ - vuln Vulnerability
7988
+
7989
+ Valid ecosystems:
7990
+
7991
+ - gem
7992
+ - golang
7993
+ - maven
7994
+ - npm
7995
+ - nuget
7996
+ - pypi
7997
+
7684
7998
  Examples
7685
7999
  $ ${command}
7686
8000
  $ ${command} --perPage=5 --page=2 --direction=asc --filter=joke
@@ -7704,17 +8018,13 @@ async function run$1(argv, importMeta, {
7704
8018
  logger.logger.log(DRY_RUN_BAIL_TEXT$1);
7705
8019
  return;
7706
8020
  }
7707
- const apiToken = index.getDefaultToken();
7708
- if (!apiToken) {
7709
- throw new index.AuthError('User must be authenticated to run this command. To log in, run the command `socket login` and enter your API key.');
7710
- }
7711
8021
  await getThreatFeed({
7712
- apiToken,
7713
8022
  direction: String(cli.flags['direction'] || 'desc'),
8023
+ ecosystem: String(cli.flags['eco'] || ''),
7714
8024
  filter: String(cli.flags['filter'] || 'mal'),
7715
- outputJson: Boolean(cli.flags['json']),
7716
- page: String(cli.flags['filter'] || '1'),
7717
- perPage: Number(cli.flags['per_page'] || 0)
8025
+ outputKind: cli.flags['json'] ? 'json' : cli.flags['markdown'] ? 'markdown' : 'print',
8026
+ page: String(cli.flags['page'] || '1'),
8027
+ perPage: Number(cli.flags['perPage']) || 30
7718
8028
  });
7719
8029
  }
7720
8030
 
@@ -7801,7 +8111,7 @@ function askQuestion(rl, query) {
7801
8111
  function removeSocketWrapper(file) {
7802
8112
  return fs.readFile(file, 'utf8', function (err, data) {
7803
8113
  if (err) {
7804
- logger.logger.error('There was an error removing the alias:');
8114
+ logger.logger.fail('There was an error removing the alias:');
7805
8115
  logger.logger.error(err);
7806
8116
  return;
7807
8117
  }
@@ -7878,7 +8188,7 @@ async function run(argv, importMeta, {
7878
8188
  // options or missing arguments.
7879
8189
  // https://www.gnu.org/software/bash/manual/html_node/Exit-Status.html
7880
8190
  process.exitCode = 2;
7881
- logger.logger.error(commonTags.stripIndents`
8191
+ logger.logger.fail(commonTags.stripIndents`
7882
8192
  ${colors.bgRed(colors.white('Input error'))}: Please provide the required flags:
7883
8193
 
7884
8194
  - Must use --enabled or --disabled
@@ -7911,7 +8221,7 @@ async function run(argv, importMeta, {
7911
8221
  }
7912
8222
  }
7913
8223
  if (!fs.existsSync(bashRcPath) && !fs.existsSync(zshRcPath)) {
7914
- logger.logger.error('There was an issue setting up the alias in your bash profile');
8224
+ logger.logger.fail('There was an issue setting up the alias in your bash profile');
7915
8225
  }
7916
8226
  }
7917
8227
 
@@ -7970,10 +8280,10 @@ void (async () => {
7970
8280
  let errorBody;
7971
8281
  let errorTitle;
7972
8282
  let errorMessage = '';
7973
- if (e instanceof index.AuthError) {
8283
+ if (e instanceof shadowNpmInject.AuthError) {
7974
8284
  errorTitle = 'Authentication error';
7975
8285
  errorMessage = e.message;
7976
- } else if (e instanceof index.InputError) {
8286
+ } else if (e instanceof shadowNpmInject.InputError) {
7977
8287
  errorTitle = 'Invalid input';
7978
8288
  errorMessage = e.message;
7979
8289
  errorBody = e.body;
@@ -7984,12 +8294,12 @@ void (async () => {
7984
8294
  } else {
7985
8295
  errorTitle = 'Unexpected error with no details';
7986
8296
  }
7987
- logger.logger.error(`${colors.bgRed(colors.white(errorTitle + ':'))} ${errorMessage}`);
8297
+ logger.logger.fail(`${colors.bgRed(colors.white(errorTitle + ':'))} ${errorMessage}`);
7988
8298
  if (errorBody) {
7989
8299
  logger.logger.error(`\n${errorBody}`);
7990
8300
  }
7991
- await index.captureException(e);
8301
+ await shadowNpmInject.captureException(e);
7992
8302
  }
7993
8303
  })();
7994
- //# debugId=c0b42b8b-128e-4ec9-a7f4-e4313aab0875
8304
+ //# debugId=b5131c8e-e05e-4ce0-8d35-03afa5b09043
7995
8305
  //# sourceMappingURL=cli.js.map