@socketsecurity/cli-with-sentry 0.14.52 → 0.14.55

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.
@@ -29,6 +29,7 @@ var constants = require('./constants.js');
29
29
  var meow = _socketInterop(require('meow'));
30
30
  var objects = require('@socketsecurity/registry/lib/objects');
31
31
  var regexps = require('@socketsecurity/registry/lib/regexps');
32
+ var commonTags = _socketInterop(require('common-tags'));
32
33
  var fs$1 = require('node:fs/promises');
33
34
  var ScreenWidget = _socketInterop(require('blessed/lib/widgets/screen'));
34
35
  var contrib = _socketInterop(require('blessed-contrib'));
@@ -43,7 +44,7 @@ var packages = require('@socketsecurity/registry/lib/packages');
43
44
  var registryConstants = require('@socketsecurity/registry/lib/constants');
44
45
  var isInteractive = require('@socketregistry/is-interactive/index.cjs');
45
46
  var terminalLink = _socketInterop(require('terminal-link'));
46
- var spawn = _socketInterop(require('@npmcli/promise-spawn'));
47
+ var spawn = require('@socketsecurity/registry/lib/spawn');
47
48
  var npa = _socketInterop(require('npm-package-arg'));
48
49
  var semver = _socketInterop(require('semver'));
49
50
  var tinyglobby = _socketInterop(require('tinyglobby'));
@@ -55,14 +56,12 @@ var sorts = require('@socketsecurity/registry/lib/sorts');
55
56
  var strings = require('@socketsecurity/registry/lib/strings');
56
57
  var yaml = _socketInterop(require('yaml'));
57
58
  var debug = require('@socketsecurity/registry/lib/debug');
58
- var npm$1 = require('./npm.js');
59
59
  var npmPaths = require('./npm-paths.js');
60
60
  var betterAjvErrors = _socketInterop(require('@apideck/better-ajv-errors'));
61
61
  var config$A = require('@socketsecurity/config');
62
62
  var assert = require('node:assert');
63
63
  var readline = require('node:readline/promises');
64
64
  var open = _socketInterop(require('open'));
65
- var node_child_process = require('node:child_process');
66
65
  var TableWidget = _socketInterop(require('blessed-contrib/lib/widget/table'));
67
66
  var readline$1 = require('node:readline');
68
67
 
@@ -1520,7 +1519,7 @@ function meowOrExit({
1520
1519
  }
1521
1520
  function getAsciiHeader(command) {
1522
1521
  const cliVersion = // The '@rollup/plugin-replace' will replace "process.env['SOCKET_CLI_VERSION_HASH']".
1523
- "0.14.52:709a145:a30d9dfd:pub";
1522
+ "0.14.55:51de259:b691b88f:pub";
1524
1523
  const nodeVersion = process.version;
1525
1524
  const apiToken = index.getSetting('apiToken');
1526
1525
  const shownToken = apiToken ? getLastFiveOfApiToken(apiToken) : 'no';
@@ -1594,15 +1593,87 @@ async function run$z(argv, importMeta, {
1594
1593
  await runAction(githubEventBefore, githubEventAfter);
1595
1594
  }
1596
1595
 
1596
+ async function fetchOrgAnalyticsData(time, spinner, apiToken) {
1597
+ const socketSdk = await index.setupSdk(apiToken);
1598
+ const result = await handleApiCall(socketSdk.getOrgAnalytics(time.toString()), 'fetching analytics data');
1599
+ if (result.success === false) {
1600
+ handleUnsuccessfulApiResponse('getOrgAnalytics', result, spinner);
1601
+ return undefined;
1602
+ }
1603
+ spinner.stop();
1604
+ if (!result.data.length) {
1605
+ logger.logger.log('No analytics data is available for this organization yet.');
1606
+ return undefined;
1607
+ }
1608
+ return result.data;
1609
+ }
1610
+
1611
+ async function fetchRepoAnalyticsData(repo, time, spinner, apiToken) {
1612
+ const socketSdk = await index.setupSdk(apiToken);
1613
+ const result = await handleApiCall(socketSdk.getRepoAnalytics(repo, time.toString()), 'fetching analytics data');
1614
+ if (result.success === false) {
1615
+ handleUnsuccessfulApiResponse('getRepoAnalytics', result, spinner);
1616
+ return undefined;
1617
+ }
1618
+ spinner.stop();
1619
+ if (!result.data.length) {
1620
+ logger.logger.log('No analytics data is available for this organization yet.');
1621
+ return undefined;
1622
+ }
1623
+ return result.data;
1624
+ }
1625
+
1626
+ function mdTableStringNumber(title1, title2, obj) {
1627
+ // | Date | Counts |
1628
+ // | ----------- | ------ |
1629
+ // | Header | 201464 |
1630
+ // | Paragraph | 18 |
1631
+ let mw1 = title1.length;
1632
+ let mw2 = title2.length;
1633
+ for (const [key, value] of Object.entries(obj)) {
1634
+ mw1 = Math.max(mw1, key.length);
1635
+ mw2 = Math.max(mw2, String(value ?? '').length);
1636
+ }
1637
+ const lines = [];
1638
+ lines.push(`| ${title1.padEnd(mw1, ' ')} | ${title2.padEnd(mw2)} |`);
1639
+ lines.push(`| ${'-'.repeat(mw1)} | ${'-'.repeat(mw2)} |`);
1640
+ for (const [key, value] of Object.entries(obj)) {
1641
+ lines.push(`| ${key.padEnd(mw1, ' ')} | ${String(value ?? '').padStart(mw2, ' ')} |`);
1642
+ }
1643
+ lines.push(`| ${'-'.repeat(mw1)} | ${'-'.repeat(mw2)} |`);
1644
+ return lines.join('\n');
1645
+ }
1646
+
1597
1647
  // Note: Widgets does not seem to actually work as code :'(
1598
1648
 
1649
+ const METRICS = ['total_critical_alerts', 'total_high_alerts', 'total_medium_alerts', 'total_low_alerts', 'total_critical_added', 'total_medium_added', 'total_low_added', 'total_high_added', 'total_critical_prevented', 'total_high_prevented', 'total_medium_prevented', 'total_low_prevented'];
1650
+
1599
1651
  // Note: This maps `new Date(date).getMonth()` to English three letters
1600
1652
  const Months = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'];
1601
- const METRICS = ['total_critical_alerts', 'total_high_alerts', 'total_medium_alerts', 'total_low_alerts', 'total_critical_added', 'total_medium_added', 'total_low_added', 'total_high_added', 'total_critical_prevented', 'total_high_prevented', 'total_medium_prevented', 'total_low_prevented'];
1602
1653
  async function displayAnalytics({
1654
+ filePath,
1655
+ outputKind,
1656
+ repo,
1657
+ scope,
1658
+ time
1659
+ }) {
1660
+ const apiToken = index.getDefaultToken();
1661
+ if (!apiToken) {
1662
+ 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.');
1663
+ }
1664
+ await outputAnalyticsWithToken({
1665
+ apiToken,
1666
+ filePath,
1667
+ outputKind,
1668
+ repo,
1669
+ scope,
1670
+ time
1671
+ });
1672
+ }
1673
+ async function outputAnalyticsWithToken({
1603
1674
  apiToken,
1604
1675
  filePath,
1605
- outputJson,
1676
+ outputKind,
1606
1677
  repo,
1607
1678
  scope,
1608
1679
  time
@@ -1618,22 +1689,70 @@ async function displayAnalytics({
1618
1689
  } else if (repo) {
1619
1690
  data = await fetchRepoAnalyticsData(repo, time, spinner, apiToken);
1620
1691
  }
1621
- if (data) {
1622
- if (outputJson && !filePath) {
1623
- logger.logger.log(data);
1624
- } else if (filePath) {
1692
+
1693
+ // A message should already have been printed if we have no data here
1694
+ if (!data) return;
1695
+ if (outputKind === 'json') {
1696
+ let serialized = renderJson(data);
1697
+ if (!serialized) return;
1698
+ if (filePath && filePath !== '-') {
1625
1699
  try {
1626
- await fs$1.writeFile(filePath, JSON.stringify(data), 'utf8');
1700
+ await fs$1.writeFile(filePath, serialized, 'utf8');
1627
1701
  logger.logger.log(`Data successfully written to ${filePath}`);
1628
1702
  } catch (e) {
1703
+ logger.logger.error('There was an error trying to write the json to disk');
1629
1704
  logger.logger.error(e);
1705
+ process.exitCode = 1;
1706
+ }
1707
+ } else {
1708
+ logger.logger.log(serialized);
1709
+ }
1710
+ } else {
1711
+ const fdata = scope === 'org' ? formatDataOrg(data) : formatDataRepo(data);
1712
+ if (outputKind === 'markdown') {
1713
+ const serialized = renderMarkdown(fdata, time, repo);
1714
+ if (filePath && filePath !== '-') {
1715
+ try {
1716
+ await fs$1.writeFile(filePath, serialized, 'utf8');
1717
+ logger.logger.log(`Data successfully written to ${filePath}`);
1718
+ } catch (e) {
1719
+ logger.logger.error(e);
1720
+ }
1721
+ } else {
1722
+ logger.logger.log(serialized);
1630
1723
  }
1631
1724
  } else {
1632
- const fdata = scope === 'org' ? formatData(data, 'org') : formatData(data, 'repo');
1633
1725
  displayAnalyticsScreen(fdata);
1634
1726
  }
1635
1727
  }
1636
1728
  }
1729
+ function renderJson(data) {
1730
+ try {
1731
+ return JSON.stringify(data, null, 2);
1732
+ } catch (e) {
1733
+ // This could be caused by circular references, which is an "us" problem
1734
+ logger.logger.error('There was a problem converting the data set to JSON. Please try without --json or with --markdown');
1735
+ process.exitCode = 1;
1736
+ return;
1737
+ }
1738
+ }
1739
+ function renderMarkdown(data, days, repoSlug) {
1740
+ return commonTags.stripIndents`
1741
+ # Socket Alert Analytics
1742
+
1743
+ These are the Socket.dev stats are analytics for the ${repoSlug ? `${repoSlug} repo` : 'org'} of the past ${days} days
1744
+
1745
+ ${[['Total critical alerts', mdTableStringNumber('Date', 'Counts', data['total_critical_alerts'])], ['Total high alerts', mdTableStringNumber('Date', 'Counts', data['total_high_alerts'])], ['Total critical alerts added to the main branch', mdTableStringNumber('Date', 'Counts', data['total_critical_added'])], ['Total high alerts added to the main branch', mdTableStringNumber('Date', 'Counts', data['total_high_added'])], ['Total critical alerts prevented from the main branch', mdTableStringNumber('Date', 'Counts', data['total_critical_prevented'])], ['Total high alerts prevented from the main branch', mdTableStringNumber('Date', 'Counts', data['total_high_prevented'])], ['Total medium alerts prevented from the main branch', mdTableStringNumber('Date', 'Counts', data['total_medium_prevented'])], ['Total low alerts prevented from the main branch', mdTableStringNumber('Date', 'Counts', data['total_low_prevented'])]].map(([title, table]) => commonTags.stripIndents`
1746
+ ## ${title}
1747
+
1748
+ ${table}
1749
+ `).join('\n\n')}
1750
+
1751
+ ## Top 5 alert types
1752
+
1753
+ ${mdTableStringNumber('Name', 'Counts', data['top_five_alert_types'])}
1754
+ `;
1755
+ }
1637
1756
  function displayAnalyticsScreen(data) {
1638
1757
  const screen = new ScreenWidget({});
1639
1758
  const grid = new contrib.grid({
@@ -1666,91 +1785,69 @@ function displayAnalyticsScreen(data) {
1666
1785
  screen.render();
1667
1786
  screen.key(['escape', 'q', 'C-c'], () => process.exit(0));
1668
1787
  }
1669
- async function fetchOrgAnalyticsData(time, spinner, apiToken) {
1670
- const socketSdk = await index.setupSdk(apiToken);
1671
- const result = await handleApiCall(socketSdk.getOrgAnalytics(time.toString()), 'fetching analytics data');
1672
- if (result.success === false) {
1673
- handleUnsuccessfulApiResponse('getOrgAnalytics', result, spinner);
1674
- return undefined;
1788
+ function formatDataRepo(data) {
1789
+ const sortedTopFiveAlerts = {};
1790
+ const totalTopAlerts = {};
1791
+ const formattedData = {};
1792
+ for (const metric of METRICS) {
1793
+ formattedData[metric] = {};
1675
1794
  }
1676
- spinner.stop();
1677
- if (!result.data.length) {
1678
- logger.logger.log('No analytics data is available for this organization yet.');
1679
- return undefined;
1795
+ for (const entry of data) {
1796
+ const topFiveAlertTypes = entry['top_five_alert_types'];
1797
+ for (const type of Object.keys(topFiveAlertTypes)) {
1798
+ const count = topFiveAlertTypes[type] ?? 0;
1799
+ if (!totalTopAlerts[type]) {
1800
+ totalTopAlerts[type] = count;
1801
+ } else if (count > (totalTopAlerts[type] ?? 0)) {
1802
+ totalTopAlerts[type] = count;
1803
+ }
1804
+ }
1680
1805
  }
1681
- return result.data;
1682
- }
1683
- async function fetchRepoAnalyticsData(repo, time, spinner, apiToken) {
1684
- const socketSdk = await index.setupSdk(apiToken);
1685
- const result = await handleApiCall(socketSdk.getRepoAnalytics(repo, time.toString()), 'fetching analytics data');
1686
- if (result.success === false) {
1687
- handleUnsuccessfulApiResponse('getRepoAnalytics', result, spinner);
1688
- return undefined;
1806
+ for (const entry of data) {
1807
+ for (const metric of METRICS) {
1808
+ formattedData[metric][formatDate(entry['created_at'])] = entry[metric];
1809
+ }
1689
1810
  }
1690
- spinner.stop();
1691
- if (!result.data.length) {
1692
- logger.logger.log('No analytics data is available for this organization yet.');
1693
- return undefined;
1811
+ const topFiveAlertEntries = Object.entries(totalTopAlerts).sort(([_keya, a], [_keyb, b]) => b - a).slice(0, 5);
1812
+ for (const [key, value] of topFiveAlertEntries) {
1813
+ sortedTopFiveAlerts[key] = value;
1694
1814
  }
1695
- return result.data;
1815
+ return {
1816
+ ...formattedData,
1817
+ top_five_alert_types: sortedTopFiveAlerts
1818
+ };
1696
1819
  }
1697
- function formatData(data, scope) {
1698
- const formattedData = {};
1820
+ function formatDataOrg(data) {
1699
1821
  const sortedTopFiveAlerts = {};
1700
1822
  const totalTopAlerts = {};
1823
+ const formattedData = {};
1701
1824
  for (const metric of METRICS) {
1702
1825
  formattedData[metric] = {};
1703
1826
  }
1704
- if (scope === 'org') {
1705
- for (const entry of data) {
1706
- const topFiveAlertTypes = entry['top_five_alert_types'];
1707
- for (const type of Object.keys(topFiveAlertTypes)) {
1708
- const count = topFiveAlertTypes[type] ?? 0;
1709
- if (!totalTopAlerts[type]) {
1710
- totalTopAlerts[type] = count;
1711
- } else {
1712
- totalTopAlerts[type] += count;
1713
- }
1714
- }
1715
- }
1716
- for (const metric of METRICS) {
1717
- const formatted = formattedData[metric];
1718
- for (const entry of data) {
1719
- const date = formatDate(entry['created_at']);
1720
- if (!formatted[date]) {
1721
- formatted[date] = entry[metric];
1722
- } else {
1723
- formatted[date] += entry[metric];
1724
- }
1725
- }
1726
- }
1727
- } else if (scope === 'repo') {
1728
- for (const entry of data) {
1729
- const topFiveAlertTypes = entry['top_five_alert_types'];
1730
- for (const type of Object.keys(topFiveAlertTypes)) {
1731
- const count = topFiveAlertTypes[type] ?? 0;
1732
- if (!totalTopAlerts[type]) {
1733
- totalTopAlerts[type] = count;
1734
- } else if (count > (totalTopAlerts[type] ?? 0)) {
1735
- totalTopAlerts[type] = count;
1736
- }
1827
+ for (const entry of data) {
1828
+ const topFiveAlertTypes = entry['top_five_alert_types'];
1829
+ for (const type of Object.keys(topFiveAlertTypes)) {
1830
+ const count = topFiveAlertTypes[type] ?? 0;
1831
+ if (!totalTopAlerts[type]) {
1832
+ totalTopAlerts[type] = count;
1833
+ } else {
1834
+ totalTopAlerts[type] += count;
1737
1835
  }
1738
1836
  }
1837
+ }
1838
+ for (const metric of METRICS) {
1839
+ const formatted = formattedData[metric];
1739
1840
  for (const entry of data) {
1740
- for (const metric of METRICS) {
1741
- formattedData[metric][formatDate(entry['created_at'])] = entry[metric];
1841
+ const date = formatDate(entry['created_at']);
1842
+ if (!formatted[date]) {
1843
+ formatted[date] = entry[metric];
1844
+ } else {
1845
+ formatted[date] += entry[metric];
1742
1846
  }
1743
1847
  }
1744
1848
  }
1745
- const topFiveAlertEntries = Object.entries(totalTopAlerts).sort(({
1746
- 1: a
1747
- }, {
1748
- 1: b
1749
- }) => b - a).slice(0, 5);
1750
- for (const {
1751
- 0: key,
1752
- 1: value
1753
- } of topFiveAlertEntries) {
1849
+ const topFiveAlertEntries = Object.entries(totalTopAlerts).sort(([_keya, a], [_keyb, b]) => b - a).slice(0, 5);
1850
+ for (const [key, value] of topFiveAlertEntries) {
1754
1851
  sortedTopFiveAlerts[key] = value;
1755
1852
  }
1756
1853
  return {
@@ -1795,6 +1892,18 @@ const config$y = {
1795
1892
  flags: {
1796
1893
  ...commonFlags,
1797
1894
  ...outputFlags,
1895
+ file: {
1896
+ type: 'string',
1897
+ shortFlag: 'f',
1898
+ default: '-',
1899
+ description: 'Path to a local file to save the output. Only valid with --json/--markdown. Defaults to stdout.'
1900
+ },
1901
+ repo: {
1902
+ type: 'string',
1903
+ shortFlag: 'r',
1904
+ default: '',
1905
+ description: 'Name of the repository. Only valid when scope=repo'
1906
+ },
1798
1907
  scope: {
1799
1908
  type: 'string',
1800
1909
  shortFlag: 's',
@@ -1806,18 +1915,6 @@ const config$y = {
1806
1915
  shortFlag: 't',
1807
1916
  default: 7,
1808
1917
  description: 'Time filter - either 7, 30 or 90, default: 7'
1809
- },
1810
- repo: {
1811
- type: 'string',
1812
- shortFlag: 'r',
1813
- default: '',
1814
- description: 'Name of the repository'
1815
- },
1816
- file: {
1817
- type: 'string',
1818
- shortFlag: 'f',
1819
- default: '',
1820
- description: 'Path to a local file to save the output'
1821
1918
  }
1822
1919
  },
1823
1920
  help: (command, {
@@ -1853,6 +1950,9 @@ async function run$y(argv, importMeta, {
1853
1950
  parentName
1854
1951
  });
1855
1952
  const {
1953
+ file,
1954
+ json,
1955
+ markdown,
1856
1956
  repo,
1857
1957
  scope,
1858
1958
  time
@@ -1860,66 +1960,154 @@ async function run$y(argv, importMeta, {
1860
1960
  const badScope = scope !== 'org' && scope !== 'repo';
1861
1961
  const badTime = time !== 7 && time !== 30 && time !== 90;
1862
1962
  const badRepo = scope === 'repo' && !repo;
1863
- if (badScope || badTime || badRepo) {
1963
+ const badFile = file !== '-' && !json && !markdown;
1964
+ const badFlags = json && markdown;
1965
+ if (badScope || badTime || badRepo || badFile || badFlags) {
1864
1966
  // Use exit status of 2 to indicate incorrect usage, generally invalid
1865
1967
  // options or missing arguments.
1866
1968
  // https://www.gnu.org/software/bash/manual/html_node/Exit-Status.html
1867
1969
  process.exitCode = 2;
1868
- logger.logger.error(`${colors.bgRed(colors.white('Input error'))}: Please provide the required fields:\n
1869
- - Scope must be "repo" or "org" ${badScope ? colors.red('(bad!)') : colors.green('(ok)')}\n
1870
- - The time filter must either be 7, 30 or 90 ${badTime ? colors.red('(bad!)') : colors.green('(ok)')}\n
1871
- - Repository name using --repo when scope is "repo" ${badRepo ? colors.red('(bad!)') : colors.green('(ok)')}\n`);
1970
+ logger.logger.error(commonTags.stripIndents`${colors.bgRed(colors.white('Input error'))}: Please provide the required fields:
1971
+
1972
+ - Scope must be "repo" or "org" ${badScope ? colors.red('(bad!)') : colors.green('(ok)')}
1973
+
1974
+ - The time filter must either be 7, 30 or 90 ${badTime ? colors.red('(bad!)') : colors.green('(ok)')}
1975
+
1976
+ ${scope === 'repo' ? `- Repository name using --repo when scope is "repo" ${badRepo ? colors.red('(bad!)') : colors.green('(ok)')}` : ''}
1977
+
1978
+ ${badFlags ? `- The \`--json\` and \`--markdown\` flags can not be used at the same time ${badFlags ? colors.red('(bad!)') : colors.green('(ok)')}` : ''}
1979
+
1980
+ ${badFile ? `- The \`--file\` flag is only valid when using \`--json\` or \`--markdown\` ${badFile ? colors.red('(bad!)') : colors.green('(ok)')}` : ''}
1981
+ `.split('\n').filter(s => !!s.trim()).join('\n'));
1872
1982
  return;
1873
1983
  }
1874
1984
  if (cli.flags['dryRun']) {
1875
1985
  logger.logger.log(DRY_RUN_BAIL_TEXT$x);
1876
1986
  return;
1877
1987
  }
1878
- const apiToken = index.getDefaultToken();
1879
- if (!apiToken) {
1880
- 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.');
1881
- }
1882
1988
  return await displayAnalytics({
1883
- apiToken,
1884
1989
  scope,
1885
1990
  time,
1886
1991
  repo: String(repo || ''),
1887
- outputJson: Boolean(cli.flags['json']),
1888
- filePath: String(cli.flags['file'] || '')
1992
+ outputKind: json ? 'json' : markdown ? 'markdown' : 'print',
1993
+ filePath: String(file || '')
1889
1994
  });
1890
1995
  }
1891
1996
 
1892
1997
  async function getAuditLog({
1893
- apiToken,
1998
+ logType,
1894
1999
  orgSlug,
1895
- outputJson,
1896
- outputMarkdown,
2000
+ outputKind,
1897
2001
  page,
1898
- perPage,
1899
- type
2002
+ perPage
1900
2003
  }) {
1901
- // Lazily access constants.spinner.
1902
- const {
1903
- spinner
1904
- } = constants;
1905
- spinner.start(`Looking up audit log for ${orgSlug}`);
1906
- const socketSdk = await index.setupSdk(apiToken);
1907
- const result = await handleApiCall(socketSdk.getAuditLogEvents(orgSlug, {
1908
- outputJson,
1909
- outputMarkdown,
2004
+ const apiToken = index.getDefaultToken();
2005
+ if (!apiToken) {
2006
+ 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.');
2007
+ }
2008
+ const auditLogs = await getAuditLogWithToken({
2009
+ apiToken,
1910
2010
  orgSlug,
1911
- type,
2011
+ outputKind,
1912
2012
  page,
1913
- per_page: perPage
1914
- }), `Looking up audit log for ${orgSlug}\n`);
1915
- if (!result.success) {
1916
- handleUnsuccessfulApiResponse('getAuditLogEvents', result, spinner);
2013
+ perPage,
2014
+ logType
2015
+ });
2016
+ if (!auditLogs) return;
2017
+ if (outputKind === 'json') await outputAsJson(auditLogs.results, orgSlug, logType, page, perPage);else if (outputKind === 'markdown') await outputAsMarkdown(auditLogs.results, orgSlug, logType, page, perPage);else await outputAsPrint(auditLogs.results, orgSlug, logType);
2018
+ }
2019
+ async function outputAsJson(auditLogs, orgSlug, logType, page, perPage) {
2020
+ let json;
2021
+ try {
2022
+ json = JSON.stringify({
2023
+ desc: 'Audit logs for given query',
2024
+ generated: new Date().toISOString(),
2025
+ org: orgSlug,
2026
+ logType,
2027
+ page,
2028
+ perPage,
2029
+ logs: auditLogs.map(log => {
2030
+ // Note: The subset is pretty arbitrary
2031
+ const {
2032
+ created_at,
2033
+ event_id,
2034
+ ip_address,
2035
+ type,
2036
+ user_agent,
2037
+ user_email
2038
+ } = log;
2039
+ return {
2040
+ event_id,
2041
+ created_at,
2042
+ ip_address,
2043
+ type,
2044
+ user_agent,
2045
+ user_email
2046
+ };
2047
+ })
2048
+ }, null, 2);
2049
+ } catch (e) {
2050
+ logger.logger.error('There was a problem converting the logs to JSON, please try without the `--json` flag');
2051
+ process.exitCode = 1;
1917
2052
  return;
1918
2053
  }
1919
- spinner.stop();
2054
+ logger.logger.log(json);
2055
+ }
2056
+ async function outputAsMarkdown(auditLogs, orgSlug, logType, page, perPage) {
2057
+ try {
2058
+ const table = mdTable(auditLogs, ['event_id', 'created_at', 'type', 'user_email', 'ip_address', 'user_agent']);
2059
+ logger.logger.log(commonTags.stripIndents`
2060
+ # Socket Audit Logs
2061
+
2062
+ These are the Socket.dev audit logs as per requested query.
2063
+ - org: ${orgSlug}
2064
+ - type filter: ${logType || '(none)'}
2065
+ - page: ${page}
2066
+ - per page: ${perPage}
2067
+ - generated: ${new Date().toISOString()}
2068
+
2069
+ ${table}
2070
+ `);
2071
+ } catch (e) {
2072
+ logger.logger.error('There was a problem converting the logs to JSON, please try without the `--json` flag');
2073
+ logger.logger.error(e);
2074
+ process.exitCode = 1;
2075
+ return;
2076
+ }
2077
+ }
2078
+ function mdTable(logs,
2079
+ // This is saying "an array of strings and the strings are a valid key of elements of T"
2080
+ // In turn, T is defined above as the audit log event type from our OpenAPI docs.
2081
+ cols) {
2082
+ // Max col width required to fit all data in that column
2083
+ const cws = cols.map(col => col.length);
2084
+ for (const log of logs) {
2085
+ for (let i = 0; i < cols.length; ++i) {
2086
+ // @ts-ignore
2087
+ const val = log[cols[i] ?? ''] ?? '';
2088
+ cws[i] = Math.max(cws[i] ?? 0, String(val).length);
2089
+ }
2090
+ }
2091
+ let div = '|';
2092
+ for (const cw of cws) div += ' ' + '-'.repeat(cw) + ' |';
2093
+ let header = '|';
2094
+ for (let i = 0; i < cols.length; ++i) header += ' ' + String(cols[i]).padEnd(cws[i] ?? 0, ' ') + ' |';
2095
+ let body = '';
2096
+ for (const log of logs) {
2097
+ body += '|';
2098
+ for (let i = 0; i < cols.length; ++i) {
2099
+ // @ts-ignore
2100
+ const val = log[cols[i] ?? ''] ?? '';
2101
+ body += ' ' + String(val).padEnd(cws[i] ?? 0, ' ') + ' |';
2102
+ }
2103
+ body += '\n';
2104
+ }
2105
+ return [div, header, div, body.trim(), div].filter(s => !!s.trim()).join('\n');
2106
+ }
2107
+ async function outputAsPrint(auditLogs, orgSlug, logType) {
1920
2108
  const data = [];
1921
2109
  const logDetails = {};
1922
- for (const d of result.data.results) {
2110
+ for (const d of auditLogs) {
1923
2111
  const {
1924
2112
  created_at
1925
2113
  } = d;
@@ -1936,11 +2124,42 @@ async function getAuditLog({
1936
2124
  }
1937
2125
  }
1938
2126
  logger.logger.log(logDetails[await prompts.select({
1939
- message: type ? `\n Audit log for: ${orgSlug} with type: ${type}\n` : `\n Audit log for: ${orgSlug}\n`,
2127
+ message: logType ? `\n Audit log for: ${orgSlug} with type: ${logType}\n` : `\n Audit log for: ${orgSlug}\n`,
1940
2128
  choices: data,
1941
2129
  pageSize: 30
1942
2130
  })]);
1943
2131
  }
2132
+ async function getAuditLogWithToken({
2133
+ apiToken,
2134
+ logType,
2135
+ orgSlug,
2136
+ outputKind,
2137
+ page,
2138
+ perPage
2139
+ }) {
2140
+ // Lazily access constants.spinner.
2141
+ const {
2142
+ spinner
2143
+ } = constants;
2144
+ spinner.start(`Looking up audit log for ${orgSlug}`);
2145
+ const socketSdk = await index.setupSdk(apiToken);
2146
+ const result = await handleApiCall(socketSdk.getAuditLogEvents(orgSlug, {
2147
+ outputJson: outputKind === 'json',
2148
+ // I'm not sure this is used at all
2149
+ outputMarkdown: outputKind === 'markdown',
2150
+ // I'm not sure this is used at all
2151
+ orgSlug,
2152
+ type: logType,
2153
+ page,
2154
+ per_page: perPage
2155
+ }), `Looking up audit log for ${orgSlug}\n`);
2156
+ if (!result.success) {
2157
+ handleUnsuccessfulApiResponse('getAuditLogEvents', result, spinner);
2158
+ return;
2159
+ }
2160
+ spinner.stop();
2161
+ return result.data;
2162
+ }
1944
2163
 
1945
2164
  const {
1946
2165
  DRY_RUN_BAIL_TEXT: DRY_RUN_BAIL_TEXT$w
@@ -1996,33 +2215,36 @@ async function run$x(argv, importMeta, {
1996
2215
  importMeta,
1997
2216
  parentName
1998
2217
  });
1999
- const type = String(cli.flags['type'] || '');
2218
+ const {
2219
+ json,
2220
+ markdown,
2221
+ page,
2222
+ perPage,
2223
+ type
2224
+ } = cli.flags;
2225
+ const logType = String(type || '');
2000
2226
  const [orgSlug = ''] = cli.input;
2001
2227
  if (!orgSlug) {
2002
2228
  // Use exit status of 2 to indicate incorrect usage, generally invalid
2003
2229
  // options or missing arguments.
2004
2230
  // https://www.gnu.org/software/bash/manual/html_node/Exit-Status.html
2005
2231
  process.exitCode = 2;
2006
- logger.logger.error(`${colors.bgRed(colors.white('Input error'))}: Please provide the required fields:\n
2007
- - Org name as the first argument ${!orgSlug ? colors.red('(missing!)') : colors.green('(ok)')}\n`);
2232
+ logger.logger.error(commonTags.stripIndents`
2233
+ ${colors.bgRed(colors.white('Input error'))}: Please provide the required fields:\n
2234
+ - Org name as the first argument ${!orgSlug ? colors.red('(missing!)') : colors.green('(ok)')}
2235
+ `);
2008
2236
  return;
2009
2237
  }
2010
2238
  if (cli.flags['dryRun']) {
2011
2239
  logger.logger.log(DRY_RUN_BAIL_TEXT$w);
2012
2240
  return;
2013
2241
  }
2014
- const apiToken = index.getDefaultToken();
2015
- if (!apiToken) {
2016
- 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.');
2017
- }
2018
2242
  await getAuditLog({
2019
- apiToken,
2020
2243
  orgSlug,
2021
- outputJson: Boolean(cli.flags['json']),
2022
- outputMarkdown: Boolean(cli.flags['markdown']),
2023
- page: Number(cli.flags['page'] || 0),
2024
- perPage: Number(cli.flags['perPage'] || 0),
2025
- type: type.charAt(0).toUpperCase() + type.slice(1)
2244
+ outputKind: json ? 'json' : markdown ? 'markdown' : 'print',
2245
+ page: Number(page || 0),
2246
+ perPage: Number(perPage || 0),
2247
+ logType: logType.charAt(0).toUpperCase() + logType.slice(1)
2026
2248
  });
2027
2249
  }
2028
2250
 
@@ -2209,8 +2431,11 @@ async function run$w(argv, importMeta, {
2209
2431
  //
2210
2432
  //
2211
2433
  // if (cli.input.length)
2212
- // logger.error(`${colors.bgRed(colors.white('Input error'))}: Please provide the required fields:\n
2213
- // - Unexpected arguments\n
2434
+ // logger.error(
2435
+ // stripIndents`
2436
+ // ${colors.bgRed(colors.white('Input error'))}: Please provide the required fields:
2437
+ //
2438
+ // - Unexpected arguments
2214
2439
  // `)
2215
2440
  // config.help(parentName, config)
2216
2441
  // return
@@ -2941,8 +3166,6 @@ function applyLogin(apiToken, enforcedOrgs, apiBaseUrl, apiProxy) {
2941
3166
  index.updateSetting('apiProxy', apiProxy);
2942
3167
  }
2943
3168
 
2944
- // TODO: this type should come from a general Socket REST API type doc
2945
-
2946
3169
  const {
2947
3170
  SOCKET_PUBLIC_API_TOKEN
2948
3171
  } = constants;
@@ -3154,7 +3377,7 @@ async function convertGradleToMaven(target, bin, _out, verbose, gradleOpts) {
3154
3377
  if (verbose) {
3155
3378
  spinner.log('[VERBOSE] Executing:', bin, commandArgs);
3156
3379
  }
3157
- const output = await spawn(bin, commandArgs, {
3380
+ const output = await spawn.spawn(bin, commandArgs, {
3158
3381
  cwd: target || '.'
3159
3382
  });
3160
3383
  spinner.stop();
@@ -3325,9 +3548,11 @@ async function run$p(argv, importMeta, {
3325
3548
  // options or missing arguments.
3326
3549
  // https://www.gnu.org/software/bash/manual/html_node/Exit-Status.html
3327
3550
  process.exitCode = 2;
3328
- logger.logger.error(`${colors.bgRed(colors.white('Input error'))}: Please provide the required fields:\n
3329
- - The DIR arg is required ${!target ? colors.red('(missing!)') : target === '-' ? colors.red('(stdin is not supported)') : colors.green('(ok)')}\n
3330
- - Can only accept one DIR (make sure to escape spaces!) ${cli.input.length > 1 ? colors.red(`(received ${cli.input.length}!)`) : colors.green('(ok)')}\n`);
3551
+ logger.logger.error(commonTags.stripIndents`${colors.bgRed(colors.white('Input error'))}: Please provide the required fields:
3552
+
3553
+ - The DIR arg is required ${!target ? colors.red('(missing!)') : target === '-' ? colors.red('(stdin is not supported)') : colors.green('(ok)')}
3554
+
3555
+ - Can only accept one DIR (make sure to escape spaces!) ${cli.input.length > 1 ? colors.red(`(received ${cli.input.length}!)`) : colors.green('(ok)')}`);
3331
3556
  return;
3332
3557
  }
3333
3558
  let bin;
@@ -3388,7 +3613,7 @@ async function convertSbtToMaven(target, bin, out, verbose, sbtOpts) {
3388
3613
  // we can upload them and predict them through the GitHub API. We could do a
3389
3614
  // .socket folder. We could do a socket.pom.gz with all the poms, although
3390
3615
  // I'd prefer something plain-text if it is to be committed.
3391
- const output = await spawn(bin, ['makePom'].concat(sbtOpts), {
3616
+ const output = await spawn.spawn(bin, ['makePom'].concat(sbtOpts), {
3392
3617
  cwd: target || '.'
3393
3618
  });
3394
3619
  spinner.stop();
@@ -3559,9 +3784,11 @@ async function run$o(argv, importMeta, {
3559
3784
  // options or missing arguments.
3560
3785
  // https://www.gnu.org/software/bash/manual/html_node/Exit-Status.html
3561
3786
  process.exitCode = 2;
3562
- logger.logger.error(`${colors.bgRed(colors.white('Input error'))}: Please provide the required fields:\n
3563
- - The DIR or FILE arg is required ${!target ? colors.red('(missing!)') : target === '-' ? colors.red('(stdin is not supported)') : colors.green('(ok)')}\n
3564
- - Can only accept one DIR or FILE (make sure to escape spaces!) ${cli.input.length > 1 ? colors.red(`(received ${cli.input.length}!)`) : colors.green('(ok)')}\n`);
3787
+ logger.logger.error(commonTags.stripIndents`${colors.bgRed(colors.white('Input error'))}: Please provide the required fields:
3788
+
3789
+ - The DIR or FILE arg is required ${!target ? colors.red('(missing!)') : target === '-' ? colors.red('(stdin is not supported)') : colors.green('(ok)')}
3790
+
3791
+ - Can only accept one DIR or FILE (make sure to escape spaces!) ${cli.input.length > 1 ? colors.red(`(received ${cli.input.length}!)`) : colors.green('(ok)')}`);
3565
3792
  return;
3566
3793
  }
3567
3794
  let bin = 'sbt';
@@ -3817,9 +4044,11 @@ async function run$m(argv, importMeta, {
3817
4044
  // options or missing arguments.
3818
4045
  // https://www.gnu.org/software/bash/manual/html_node/Exit-Status.html
3819
4046
  process.exitCode = 2;
3820
- logger.logger.error(`${colors.bgRed(colors.white('Input error'))}: Please provide the required fields:\n
3821
- - The DIR arg is required ${!target ? colors.red('(missing!)') : target === '-' ? colors.red('(stdin is not supported)') : colors.green('(ok)')}\n
3822
- - Can only accept one DIR (make sure to escape spaces!) ${cli.input.length > 1 ? colors.red(`(received ${cli.input.length}!)`) : colors.green('(ok)')}\n`);
4047
+ logger.logger.error(commonTags.stripIndents`${colors.bgRed(colors.white('Input error'))}: Please provide the required fields:
4048
+
4049
+ - The DIR arg is required ${!target ? colors.red('(missing!)') : target === '-' ? colors.red('(stdin is not supported)') : colors.green('(ok)')}
4050
+
4051
+ - Can only accept one DIR (make sure to escape spaces!) ${cli.input.length > 1 ? colors.red(`(received ${cli.input.length}!)`) : colors.green('(ok)')}`);
3823
4052
  return;
3824
4053
  }
3825
4054
  let bin;
@@ -4067,7 +4296,7 @@ async function getAgentVersion(agentExecPath, cwd) {
4067
4296
  try {
4068
4297
  result = semver.coerce(
4069
4298
  // All package managers support the "--version" flag.
4070
- (await spawn(agentExecPath, ['--version'], {
4299
+ (await spawn.spawn(agentExecPath, ['--version'], {
4071
4300
  cwd
4072
4301
  })).stdout) ?? undefined;
4073
4302
  } catch {}
@@ -4122,7 +4351,7 @@ const readLockFileByAgent = (() => {
4122
4351
  // To print a Yarn lockfile to your console without writing it to disk
4123
4352
  // use `bun bun.lockb`.
4124
4353
  // https://bun.sh/guides/install/yarnlock
4125
- return (await spawn(agentExecPath, [lockPath])).stdout.trim();
4354
+ return (await spawn.spawn(agentExecPath, [lockPath])).stdout.trim();
4126
4355
  }
4127
4356
  return undefined;
4128
4357
  }),
@@ -4521,7 +4750,7 @@ function parseableToQueryStdout(stdout) {
4521
4750
  async function npmQuery(npmExecPath, cwd) {
4522
4751
  let stdout = '';
4523
4752
  try {
4524
- stdout = (await spawn(npmExecPath, ['query', ':not(.dev)'], {
4753
+ stdout = (await spawn.spawn(npmExecPath, ['query', ':not(.dev)'], {
4525
4754
  cwd
4526
4755
  })).stdout;
4527
4756
  } catch {}
@@ -4531,7 +4760,7 @@ async function lsBun(agentExecPath, cwd) {
4531
4760
  try {
4532
4761
  // Bun does not support filtering by production packages yet.
4533
4762
  // https://github.com/oven-sh/bun/issues/8283
4534
- return (await spawn(agentExecPath, ['pm', 'ls', '--all'], {
4763
+ return (await spawn.spawn(agentExecPath, ['pm', 'ls', '--all'], {
4535
4764
  cwd
4536
4765
  })).stdout;
4537
4766
  } catch {}
@@ -4550,7 +4779,7 @@ async function lsPnpm(agentExecPath, cwd, options) {
4550
4779
  }
4551
4780
  let stdout = '';
4552
4781
  try {
4553
- stdout = (await spawn(agentExecPath, ['ls', '--parseable', '--prod', '--depth', 'Infinity'], {
4782
+ stdout = (await spawn.spawn(agentExecPath, ['ls', '--parseable', '--prod', '--depth', 'Infinity'], {
4554
4783
  cwd
4555
4784
  })).stdout;
4556
4785
  } catch {}
@@ -4559,7 +4788,7 @@ async function lsPnpm(agentExecPath, cwd, options) {
4559
4788
  async function lsVlt(agentExecPath, cwd) {
4560
4789
  let stdout = '';
4561
4790
  try {
4562
- stdout = (await spawn(agentExecPath, ['ls', '--view', 'human', ':not(.dev)'], {
4791
+ stdout = (await spawn.spawn(agentExecPath, ['ls', '--view', 'human', ':not(.dev)'], {
4563
4792
  cwd
4564
4793
  })).stdout;
4565
4794
  } catch {}
@@ -4570,7 +4799,7 @@ async function lsYarnBerry(agentExecPath, cwd) {
4570
4799
  return (
4571
4800
  // Yarn Berry does not support filtering by production packages yet.
4572
4801
  // https://github.com/yarnpkg/berry/issues/5117
4573
- (await spawn(agentExecPath, ['info', '--recursive', '--name-only'], {
4802
+ (await spawn.spawn(agentExecPath, ['info', '--recursive', '--name-only'], {
4574
4803
  cwd
4575
4804
  })).stdout.trim()
4576
4805
  );
@@ -4583,7 +4812,7 @@ async function lsYarnClassic(agentExecPath, cwd) {
4583
4812
  // https://github.com/yarnpkg/yarn/releases/tag/v1.0.0
4584
4813
  // > Fix: Excludes dev dependencies from the yarn list output when the
4585
4814
  // environment is production
4586
- return (await spawn(agentExecPath, ['list', '--prod'], {
4815
+ return (await spawn.spawn(agentExecPath, ['list', '--prod'], {
4587
4816
  cwd
4588
4817
  })).stdout.trim();
4589
4818
  } catch {}
@@ -4708,14 +4937,73 @@ function pnpmUpdatePkgJson(editablePkgJson, overrides) {
4708
4937
  }
4709
4938
  const updateManifestByAgent = new Map([[BUN, updateResolutions], [NPM$4, updateOverrides], [PNPM$1, pnpmUpdatePkgJson], [VLT, updateOverrides], [YARN_BERRY, updateResolutions], [YARN_CLASSIC$1, updateResolutions]]);
4710
4939
 
4940
+ const {
4941
+ SOCKET_IPC_HANDSHAKE
4942
+ } = constants;
4943
+ function safeNpmInstall(options) {
4944
+ const {
4945
+ args = [],
4946
+ ipc,
4947
+ spinner,
4948
+ ...spawnOptions
4949
+ } = {
4950
+ __proto__: null,
4951
+ ...options
4952
+ };
4953
+ const terminatorPos = args.indexOf('--');
4954
+ const npmArgs = (terminatorPos === -1 ? args : args.slice(0, terminatorPos)).filter(a => !npm.isAuditFlag(a) && !npm.isFundFlag(a) && !npm.isProgressFlag(a));
4955
+ const otherArgs = terminatorPos === -1 ? [] : args.slice(terminatorPos);
4956
+ const useIpc = objects.isObject(ipc);
4957
+ const useDebug = debug.isDebug();
4958
+ const isSilent = !useDebug && !npmArgs.some(npm.isLoglevelFlag);
4959
+ const spawnPromise = spawn.spawn(
4960
+ // Lazily access constants.execPath.
4961
+ constants.execPath, [
4962
+ // Lazily access constants.nodeNoWarningsFlags.
4963
+ ...constants.nodeNoWarningsFlags, '--require',
4964
+ // Lazily access constants.npmInjectionPath.
4965
+ constants.npmInjectionPath, npmPaths.getNpmBinPath(), 'install',
4966
+ // Even though the '--silent' flag is passed npm will still run through
4967
+ // code paths for 'audit' and 'fund' unless '--no-audit' and '--no-fund'
4968
+ // flags are passed.
4969
+ '--no-audit', '--no-fund',
4970
+ // Add `--no-progress` and `--silent` flags to fix input being swallowed
4971
+ // by the spinner when running the command with recent versions of npm.
4972
+ '--no-progress',
4973
+ // Add the '--silent' flag if a loglevel flag is not provided and the
4974
+ // SOCKET_CLI_DEBUG environment variable is not truthy.
4975
+ ...(isSilent ? ['--silent'] : []), ...npmArgs, ...otherArgs], {
4976
+ spinner,
4977
+ // Set stdio to include 'ipc'.
4978
+ // See https://github.com/nodejs/node/blob/v23.6.0/lib/child_process.js#L161-L166
4979
+ // and https://github.com/nodejs/node/blob/v23.6.0/lib/internal/child_process.js#L238.
4980
+ stdio: isSilent ?
4981
+ // 'ignore'
4982
+ useIpc ? ['ignore', 'ignore', 'ignore', 'ipc'] : 'ignore' :
4983
+ // 'inherit'
4984
+ useIpc ? [0, 1, 2, 'ipc'] : 'inherit',
4985
+ ...spawnOptions,
4986
+ env: {
4987
+ ...process$1.env,
4988
+ ...spawnOptions.env
4989
+ }
4990
+ });
4991
+ if (useIpc) {
4992
+ spawnPromise.process.send({
4993
+ [SOCKET_IPC_HANDSHAKE]: ipc
4994
+ });
4995
+ }
4996
+ return spawnPromise;
4997
+ }
4998
+
4711
4999
  const {
4712
5000
  NPM: NPM$3,
4713
- abortSignal: abortSignal$2
5001
+ abortSignal
4714
5002
  } = constants;
4715
5003
  function runAgentInstall(agent, agentExecPath, options) {
4716
5004
  // All package managers support the "install" command.
4717
5005
  if (agent === NPM$3) {
4718
- return npm$1.safeNpmInstall(options);
5006
+ return safeNpmInstall(options);
4719
5007
  }
4720
5008
  const {
4721
5009
  args = [],
@@ -4726,12 +5014,9 @@ function runAgentInstall(agent, agentExecPath, options) {
4726
5014
  ...options
4727
5015
  };
4728
5016
  const isSilent = !debug.isDebug();
4729
- const isSpinning = spinner?.isSpinning ?? false;
4730
- if (!isSilent) {
4731
- spinner?.stop();
4732
- }
4733
- let spawnPromise = spawn(agentExecPath, ['install', ...args], {
4734
- signal: abortSignal$2,
5017
+ return spawn.spawn(agentExecPath, ['install', ...args], {
5018
+ signal: abortSignal,
5019
+ spinner,
4735
5020
  stdio: isSilent ? 'ignore' : 'inherit',
4736
5021
  ...spawnOptions,
4737
5022
  env: {
@@ -4739,22 +5024,12 @@ function runAgentInstall(agent, agentExecPath, options) {
4739
5024
  ...spawnOptions.env
4740
5025
  }
4741
5026
  });
4742
- if (!isSilent && isSpinning) {
4743
- const oldSpawnPromise = spawnPromise;
4744
- spawnPromise = spawnPromise.finally(() => {
4745
- spinner?.start();
4746
- });
4747
- spawnPromise.process = oldSpawnPromise.process;
4748
- spawnPromise.stdin = spawnPromise.stdin;
4749
- }
4750
- return spawnPromise;
4751
5027
  }
4752
5028
 
4753
5029
  const {
4754
5030
  NPM: NPM$2
4755
5031
  } = constants;
4756
5032
  const COMMAND_TITLE$1 = 'Socket Optimize';
4757
- const NPM_OVERRIDE_PR_URL = 'https://github.com/npm/cli/pull/8089';
4758
5033
  async function updatePackageLockJson(pkgEnvDetails, options) {
4759
5034
  const {
4760
5035
  logger,
@@ -4770,7 +5045,7 @@ async function updatePackageLockJson(pkgEnvDetails, options) {
4770
5045
  });
4771
5046
  spinner?.stop();
4772
5047
  if (pkgEnvDetails.agent === NPM$2) {
4773
- logger?.log(`💡 Re-run ${COMMAND_TITLE$1} whenever ${pkgEnvDetails.lockName} changes.\n This can be skipped once npm ships ${NPM_OVERRIDE_PR_URL}.`);
5048
+ logger?.log(`💡 Re-run ${COMMAND_TITLE$1} whenever ${pkgEnvDetails.lockName} changes.\n This can be skipped once npm v11.2.0 is released.`);
4774
5049
  }
4775
5050
  } catch (e) {
4776
5051
  spinner?.stop();
@@ -5171,9 +5446,10 @@ async function run$g(argv, importMeta, {
5171
5446
  // options or missing arguments.
5172
5447
  // https://www.gnu.org/software/bash/manual/html_node/Exit-Status.html
5173
5448
  process.exitCode = 2;
5174
- logger.logger.error(`
5175
- ${colors.bgRed(colors.white('Input error'))}: Please provide the required fields:\n
5176
- - The json and markdown flags cannot be both set, pick one
5449
+ logger.logger.error(commonTags.stripIndents`
5450
+ ${colors.bgRed(colors.white('Input error'))}: Please provide the required fields:
5451
+
5452
+ - The json and markdown flags cannot be both set, pick one
5177
5453
  `);
5178
5454
  return;
5179
5455
  }
@@ -5184,19 +5460,12 @@ async function run$g(argv, importMeta, {
5184
5460
  await getOrganization(json ? 'json' : markdown ? 'markdown' : 'text');
5185
5461
  }
5186
5462
 
5187
- const {
5188
- abortSignal: abortSignal$1
5189
- } = constants;
5190
5463
  async function runRawNpm(argv) {
5191
- const spawnPromise = spawn(npmPaths.getNpmBinPath(), argv.slice(0), {
5192
- signal: abortSignal$1,
5464
+ const spawnPromise = spawn.spawn(npmPaths.getNpmBinPath(), argv, {
5193
5465
  stdio: 'inherit'
5194
5466
  });
5195
5467
  // See https://nodejs.org/api/all.html#all_child_process_event-exit.
5196
5468
  spawnPromise.process.on('exit', (code, signalName) => {
5197
- if (abortSignal$1.aborted) {
5198
- return;
5199
- }
5200
5469
  if (signalName) {
5201
5470
  process$1.kill(process$1.pid, signalName);
5202
5471
  } else if (code !== null) {
@@ -5248,19 +5517,12 @@ async function run$f(argv, importMeta, {
5248
5517
  await runRawNpm(argv);
5249
5518
  }
5250
5519
 
5251
- const {
5252
- abortSignal
5253
- } = constants;
5254
5520
  async function runRawNpx(argv) {
5255
- const spawnPromise = spawn(npmPaths.getNpxBinPath(), argv, {
5256
- signal: abortSignal,
5521
+ const spawnPromise = spawn.spawn(npmPaths.getNpxBinPath(), argv, {
5257
5522
  stdio: 'inherit'
5258
5523
  });
5259
5524
  // See https://nodejs.org/api/all.html#all_child_process_event-exit.
5260
5525
  spawnPromise.process.on('exit', (code, signalName) => {
5261
- if (abortSignal.aborted) {
5262
- return;
5263
- }
5264
5526
  if (signalName) {
5265
5527
  process$1.kill(process$1.pid, signalName);
5266
5528
  } else if (code !== null) {
@@ -5425,11 +5687,12 @@ function formatReportDataOutput(reportId, data, commandName, outputJson, outputM
5425
5687
  logger.logger.log(JSON.stringify(data, undefined, 2));
5426
5688
  } else {
5427
5689
  const format = new index.ColorOrMarkdown(outputMarkdown);
5428
- logger.logger.log('\nDetailed info on socket.dev: ' + format.hyperlink(reportId, data.url, {
5690
+ logger.logger.log(commonTags.stripIndents`
5691
+ Detailed info on socket.dev: ${format.hyperlink(reportId, data.url, {
5429
5692
  fallbackToUrl: true
5430
- }));
5693
+ })}`);
5431
5694
  if (!outputMarkdown) {
5432
- logger.logger.log(colors.dim(`\nOr rerun ${colors.italic(commandName)} using the ${colors.italic('--json')} flag to get full JSON output`));
5695
+ logger.logger.log(colors.dim(`Or rerun ${colors.italic(commandName)} using the ${colors.italic('--json')} flag to get full JSON output`));
5433
5696
  }
5434
5697
  }
5435
5698
  if (strict && !data.healthy) {
@@ -5598,9 +5861,11 @@ async function run$c(argv, importMeta, {
5598
5861
  // options or missing arguments.
5599
5862
  // https://www.gnu.org/software/bash/manual/html_node/Exit-Status.html
5600
5863
  process.exitCode = 2;
5601
- logger.logger.error(`${colors.bgRed(colors.white('Input error'))}: Please provide the required fields:\n
5602
- - Need at least one report ID ${!reportId ? colors.red('(missing!)') : colors.green('(ok)')}\n
5603
- - Can only handle a single report ID ${extraInput.length < 2 ? colors.red(`(received ${extraInput.length}!)`) : colors.green('(ok)')}\n`);
5864
+ logger.logger.error(commonTags.stripIndents`${colors.bgRed(colors.white('Input error'))}: Please provide the required fields:
5865
+
5866
+ - Need at least one report ID ${!reportId ? colors.red('(missing!)') : colors.green('(ok)')}
5867
+
5868
+ - Can only handle a single report ID ${extraInput.length < 2 ? colors.red(`(received ${extraInput.length}!)`) : colors.green('(ok)')}`);
5604
5869
  return;
5605
5870
  }
5606
5871
  if (cli.flags['dryRun']) {
@@ -5741,9 +6006,11 @@ async function run$b(argv, importMeta, {
5741
6006
  // options or missing arguments.
5742
6007
  // https://www.gnu.org/software/bash/manual/html_node/Exit-Status.html
5743
6008
  process.exitCode = 2;
5744
- logger.logger.error(`${colors.bgRed(colors.white('Input error'))}: Please provide the required fields:\n
5745
- - Org name as the first argument ${!orgSlug ? colors.red('(missing!)') : colors.green('(ok)')}\n
5746
- - Repository name using --repoName ${!repoName ? colors.red('(missing!)') : typeof repoName !== 'string' ? colors.red('(invalid!)') : colors.green('(ok)')}\n`);
6009
+ logger.logger.error(commonTags.stripIndents`${colors.bgRed(colors.white('Input error'))}: Please provide the required fields:
6010
+
6011
+ - Org name as the first argument ${!orgSlug ? colors.red('(missing!)') : colors.green('(ok)')}
6012
+
6013
+ - Repository name using --repoName ${!repoName ? colors.red('(missing!)') : typeof repoName !== 'string' ? colors.red('(invalid!)') : colors.green('(ok)')}`);
5747
6014
  return;
5748
6015
  }
5749
6016
  if (cli.flags['dryRun']) {
@@ -5823,10 +6090,13 @@ async function run$a(argv, importMeta, {
5823
6090
  // options or missing arguments.
5824
6091
  // https://www.gnu.org/software/bash/manual/html_node/Exit-Status.html
5825
6092
  process.exitCode = 2;
5826
- logger.logger.error(`${colors.bgRed(colors.white('Input error'))}: Please provide the required fields:\n
5827
- - Org name as the first argument ${!orgSlug ? colors.red('(missing!)') : colors.green('(ok)')}\n
5828
- - Repository name as the second argument ${!repoName ? colors.red('(missing!)') : typeof repoName !== 'string' ? colors.red('(invalid!)') : colors.green('(ok)')}\n
5829
- - At least one TARGET (e.g. \`.\` or \`./package.json\`\n`);
6093
+ logger.logger.error(commonTags.stripIndents`${colors.bgRed(colors.white('Input error'))}: Please provide the required fields:
6094
+
6095
+ - Org name as the first argument ${!orgSlug ? colors.red('(missing!)') : colors.green('(ok)')}
6096
+
6097
+ - Repository name as the second argument ${!repoName ? colors.red('(missing!)') : typeof repoName !== 'string' ? colors.red('(invalid!)') : colors.green('(ok)')}
6098
+
6099
+ - At least one TARGET (e.g. \`.\` or \`./package.json\``);
5830
6100
  return;
5831
6101
  }
5832
6102
  if (cli.flags['dryRun']) {
@@ -5968,9 +6238,11 @@ async function run$9(argv, importMeta, {
5968
6238
  // options or missing arguments.
5969
6239
  // https://www.gnu.org/software/bash/manual/html_node/Exit-Status.html
5970
6240
  process.exitCode = 2;
5971
- logger.logger.error(`${colors.bgRed(colors.white('Input error'))}: Please provide the required fields:\n
5972
- - Org name as the first argument ${!orgSlug ? colors.red('(missing!)') : colors.green('(ok)')}\n
5973
- - At least one TARGET (e.g. \`.\` or \`./package.json\`\n`);
6241
+ logger.logger.error(commonTags.stripIndents`${colors.bgRed(colors.white('Input error'))}: Please provide the required fields:
6242
+
6243
+ - Org name as the first argument ${!orgSlug ? colors.red('(missing!)') : colors.green('(ok)')}
6244
+
6245
+ - At least one TARGET (e.g. \`.\` or \`./package.json\``);
5974
6246
  return;
5975
6247
  }
5976
6248
  if (cli.flags['dryRun']) {
@@ -6100,10 +6372,13 @@ async function run$8(argv, importMeta, {
6100
6372
  // options or missing arguments.
6101
6373
  // https://www.gnu.org/software/bash/manual/html_node/Exit-Status.html
6102
6374
  process.exitCode = 2;
6103
- logger.logger.error(`${colors.bgRed(colors.white('Input error'))}: Please provide the required fields:\n
6104
- - Org name as the first argument ${!orgSlug ? colors.red('(missing!)') : colors.green('(ok)')}\n
6105
- - Repository name using --repoName ${!repoName ? colors.red('(missing!)') : typeof repoName !== 'string' ? colors.red('(invalid!)') : colors.green('(ok)')}\n
6106
- - At least one TARGET (e.g. \`.\` or \`./package.json\`\n`);
6375
+ logger.logger.error(commonTags.stripIndents`${colors.bgRed(colors.white('Input error'))}: Please provide the required fields:
6376
+
6377
+ - Org name as the first argument ${!orgSlug ? colors.red('(missing!)') : colors.green('(ok)')}
6378
+
6379
+ - Repository name using --repoName ${!repoName ? colors.red('(missing!)') : typeof repoName !== 'string' ? colors.red('(invalid!)') : colors.green('(ok)')}
6380
+
6381
+ - At least one TARGET (e.g. \`.\` or \`./package.json\``);
6107
6382
  return;
6108
6383
  }
6109
6384
  if (cli.flags['dryRun']) {
@@ -6210,9 +6485,13 @@ async function run$7(argv, importMeta, {
6210
6485
  // options or missing arguments.
6211
6486
  // https://www.gnu.org/software/bash/manual/html_node/Exit-Status.html
6212
6487
  process.exitCode = 2;
6213
- logger.logger.error(`${colors.bgRed(colors.white('Input error'))}: Please provide the required fields:\n
6214
- - Org name as the first argument ${!orgSlug ? colors.red('(missing!)') : colors.green('(ok)')}\n
6215
- - Repository name using --repoName ${!repoName ? colors.red('(missing!)') : typeof repoName !== 'string' ? colors.red('(invalid!)') : colors.green('(ok)')}\n`);
6488
+ logger.logger.error(commonTags.stripIndents`
6489
+ ${colors.bgRed(colors.white('Input error'))}: Please provide the required fields:
6490
+
6491
+ - Org name as the first argument ${!orgSlug ? colors.red('(missing!)') : colors.green('(ok)')}
6492
+
6493
+ - Repository name using --repoName ${!repoName ? colors.red('(missing!)') : typeof repoName !== 'string' ? colors.red('(invalid!)') : colors.green('(ok)')}
6494
+ `);
6216
6495
  return;
6217
6496
  }
6218
6497
  if (cli.flags['dryRun']) {
@@ -6344,7 +6623,7 @@ function dirNameToSlug(name) {
6344
6623
  }
6345
6624
 
6346
6625
  async function suggestBranchSlug(repoDefaultBranch) {
6347
- const spawnResult = node_child_process.spawnSync('git', ['branch', '--show-current']);
6626
+ const spawnResult = spawn.spawnSync('git', ['branch', '--show-current']);
6348
6627
  const currentBranch = spawnResult.stdout.toString('utf8').trim();
6349
6628
  if (currentBranch && spawnResult.status === 0) {
6350
6629
  const proceed = await prompts.select({
@@ -6468,14 +6747,19 @@ async function createFullScan({
6468
6747
  // options or missing arguments.
6469
6748
  // https://www.gnu.org/software/bash/manual/html_node/Exit-Status.html
6470
6749
  process$1.exitCode = 2;
6471
- logger.logger.error(`
6472
- ${colors.bgRed(colors.white('Input error'))}: Please provide the required fields:\n
6473
- - Org name as the first argument ${!orgSlug ? colors.red('(missing!)') : colors.green('(ok)')}\n
6474
- - Repository name using --repo ${!repoName ? colors.red('(missing!)') : colors.green('(ok)')}\n
6475
- - Branch name using --branch ${!branchName ? colors.red('(missing!)') : colors.green('(ok)')}\n
6476
- - At least one TARGET (e.g. \`.\` or \`./package.json\`) ${!packagePaths.length ? colors.red(targets.length > 0 ? '(TARGET' + (targets.length ? 's' : '') + ' contained no matching/supported files!)' : '(missing)') : colors.green('(ok)')}\n
6477
- ${!apiToken ? 'Note: was unable to make suggestions because no API Token was found; this would make command fail regardless\n' : ''}
6478
- `);
6750
+ logger.logger.error(commonTags.stripIndents`
6751
+ ${colors.bgRed(colors.white('Input error'))}: Please provide the required fields:
6752
+
6753
+ - Org name as the first argument ${!orgSlug ? colors.red('(missing!)') : colors.green('(ok)')}
6754
+
6755
+ - Repository name using --repo ${!repoName ? colors.red('(missing!)') : colors.green('(ok)')}
6756
+
6757
+ - Branch name using --branch ${!branchName ? colors.red('(missing!)') : colors.green('(ok)')}
6758
+
6759
+ - At least one TARGET (e.g. \`.\` or \`./package.json\`) ${!packagePaths.length ? colors.red(targets.length > 0 ? '(TARGET' + (targets.length ? 's' : '') + ' contained no matching/supported files!)' : '(missing)') : colors.green('(ok)')}
6760
+
6761
+ ${!apiToken ? 'Note: was unable to make suggestions because no API Token was found; this would make command fail regardless' : ''}
6762
+ `);
6479
6763
  return;
6480
6764
  }
6481
6765
  if (updatedInput) {
@@ -6637,13 +6921,18 @@ async function run$6(argv, importMeta, {
6637
6921
  // options or missing arguments.
6638
6922
  // https://www.gnu.org/software/bash/manual/html_node/Exit-Status.html
6639
6923
  process$1.exitCode = 2;
6640
- logger.logger.error(`
6641
- ${colors.bgRed(colors.white('Input error'))}: Please provide the required fields:\n
6642
- - Org name as the first argument ${!orgSlug ? colors.red('(missing!)') : colors.green('(ok)')}\n
6643
- - Repository name using --repo ${!repoName ? colors.red('(missing!)') : colors.green('(ok)')}\n
6644
- - Branch name using --branch ${!branchName ? colors.red('(missing!)') : colors.green('(ok)')}\n
6645
- - At least one TARGET (e.g. \`.\` or \`./package.json\`) ${!targets.length ? '(missing)' : colors.green('(ok)')}\n
6646
- (Additionally, no API Token was set so we cannot auto-discover these details)\n
6924
+ logger.logger.error(commonTags.stripIndents`
6925
+ ${colors.bgRed(colors.white('Input error'))}: Please provide the required fields:
6926
+
6927
+ - Org name as the first argument ${!orgSlug ? colors.red('(missing!)') : colors.green('(ok)')}
6928
+
6929
+ - Repository name using --repo ${!repoName ? colors.red('(missing!)') : colors.green('(ok)')}
6930
+
6931
+ - Branch name using --branch ${!branchName ? colors.red('(missing!)') : colors.green('(ok)')}
6932
+
6933
+ - At least one TARGET (e.g. \`.\` or \`./package.json\`) ${!targets.length ? '(missing)' : colors.green('(ok)')}
6934
+
6935
+ (Additionally, no API Token was set so we cannot auto-discover these details)
6647
6936
  `);
6648
6937
  return;
6649
6938
  }
@@ -6727,9 +7016,11 @@ async function run$5(argv, importMeta, {
6727
7016
  // options or missing arguments.
6728
7017
  // https://www.gnu.org/software/bash/manual/html_node/Exit-Status.html
6729
7018
  process.exitCode = 2;
6730
- logger.logger.error(`${colors.bgRed(colors.white('Input error'))}: Please provide the required fields:\n
6731
- - Org name as the first argument ${!orgSlug ? colors.red('(missing!)') : colors.green('(ok)')}\n
6732
- - Full Scan ID to delete as second argument ${!fullScanId ? colors.red('(missing!)') : colors.green('(ok)')}\n`);
7019
+ logger.logger.error(commonTags.stripIndents`${colors.bgRed(colors.white('Input error'))}: Please provide the required fields:
7020
+
7021
+ - Org name as the first argument ${!orgSlug ? colors.red('(missing!)') : colors.green('(ok)')}
7022
+
7023
+ - Full Scan ID to delete as second argument ${!fullScanId ? colors.red('(missing!)') : colors.green('(ok)')}`);
6733
7024
  return;
6734
7025
  }
6735
7026
  if (cli.flags['dryRun']) {
@@ -6865,8 +7156,9 @@ async function run$4(argv, importMeta, {
6865
7156
  // options or missing arguments.
6866
7157
  // https://www.gnu.org/software/bash/manual/html_node/Exit-Status.html
6867
7158
  process.exitCode = 2;
6868
- logger.logger.error(`${colors.bgRed(colors.white('Input error'))}: Please provide the required fields:\n
6869
- - Org name as the argument ${!orgSlug ? colors.red('(missing!)') : colors.green('(ok)')}\n`);
7159
+ logger.logger.error(commonTags.stripIndents`${colors.bgRed(colors.white('Input error'))}: Please provide the required fields:
7160
+
7161
+ - Org name as the argument ${!orgSlug ? colors.red('(missing!)') : colors.green('(ok)')}`);
6870
7162
  return;
6871
7163
  }
6872
7164
  if (cli.flags['dryRun']) {
@@ -6950,9 +7242,11 @@ async function run$3(argv, importMeta, {
6950
7242
  // options or missing arguments.
6951
7243
  // https://www.gnu.org/software/bash/manual/html_node/Exit-Status.html
6952
7244
  process.exitCode = 2;
6953
- logger.logger.error(`${colors.bgRed(colors.white('Input error'))}: Please provide the required fields:\n
6954
- - Org name as the first argument ${!orgSlug ? colors.red('(missing!)') : colors.green('(ok)')}\n
6955
- - Full Scan ID to inspect as second argument ${!fullScanId ? colors.red('(missing!)') : colors.green('(ok)')}\n`);
7245
+ logger.logger.error(commonTags.stripIndents`${colors.bgRed(colors.white('Input error'))}: Please provide the required fields:
7246
+
7247
+ - Org name as the first argument ${!orgSlug ? colors.red('(missing!)') : colors.green('(ok)')}
7248
+
7249
+ - Full Scan ID to inspect as second argument ${!fullScanId ? colors.red('(missing!)') : colors.green('(ok)')}`);
6956
7250
  return;
6957
7251
  }
6958
7252
  if (cli.flags['dryRun']) {
@@ -7026,9 +7320,13 @@ async function run$2(argv, importMeta, {
7026
7320
  // options or missing arguments.
7027
7321
  // https://www.gnu.org/software/bash/manual/html_node/Exit-Status.html
7028
7322
  process.exitCode = 2;
7029
- logger.logger.error(`${colors.bgRed(colors.white('Input error'))}: Please provide the required fields:\n
7030
- - Org name as the first argument ${!orgSlug ? colors.red('(missing!)') : colors.green('(ok)')}\n
7031
- - Full Scan ID to fetch as second argument ${!fullScanId ? colors.red('(missing!)') : colors.green('(ok)')}\n`);
7323
+ logger.logger.error(commonTags.stripIndents`
7324
+ ${colors.bgRed(colors.white('Input error'))}: Please provide the required fields:
7325
+
7326
+ - Org name as the first argument ${!orgSlug ? colors.red('(missing!)') : colors.green('(ok)')}
7327
+
7328
+ - Full Scan ID to fetch as second argument ${!fullScanId ? colors.red('(missing!)') : colors.green('(ok)')}
7329
+ `);
7032
7330
  return;
7033
7331
  }
7034
7332
  if (cli.flags['dryRun']) {
@@ -7227,7 +7525,7 @@ function addSocketWrapper(file) {
7227
7525
  }
7228
7526
  // TODO: pretty sure you need to source the file or restart
7229
7527
  // any terminal session before changes are reflected.
7230
- logger.logger.log(`
7528
+ logger.logger.log(commonTags.stripIndents`
7231
7529
  The alias was added to ${file}. Running 'npm install' will now be wrapped in Socket's "safe npm" 🎉
7232
7530
  If you want to disable it at any time, run \`socket wrapper --disable\`
7233
7531
  `);
@@ -7380,8 +7678,11 @@ async function run(argv, importMeta, {
7380
7678
  // options or missing arguments.
7381
7679
  // https://www.gnu.org/software/bash/manual/html_node/Exit-Status.html
7382
7680
  process.exitCode = 2;
7383
- logger.logger.error(`${colors.bgRed(colors.white('Input error'))}: Please provide the required flags:\n
7384
- - Must use --enabled or --disabled\n`);
7681
+ logger.logger.error(commonTags.stripIndents`
7682
+ ${colors.bgRed(colors.white('Input error'))}: Please provide the required flags:
7683
+
7684
+ - Must use --enabled or --disabled
7685
+ `);
7385
7686
  return;
7386
7687
  }
7387
7688
  if (cli.flags['dryRun']) {
@@ -7490,5 +7791,5 @@ void (async () => {
7490
7791
  await index.captureException(e);
7491
7792
  }
7492
7793
  })();
7493
- //# debugId=9ba118ee-ceb1-4f74-9334-3ae81bcb81f3
7794
+ //# debugId=e6a98767-74ff-4fd4-a15e-82ce65af55f8
7494
7795
  //# sourceMappingURL=cli.js.map