@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.
@@ -27,6 +27,7 @@ var index = require('./index.js');
27
27
  var constants = require('./constants.js');
28
28
  var objects = require('@socketsecurity/registry/lib/objects');
29
29
  var regexps = require('@socketsecurity/registry/lib/regexps');
30
+ var commonTags = _socketInterop(require('common-tags'));
30
31
  var fs$1 = require('node:fs/promises');
31
32
  var ScreenWidget = _socketInterop(require('blessed/lib/widgets/screen'));
32
33
  var contrib = _socketInterop(require('blessed-contrib'));
@@ -41,7 +42,7 @@ var packages = require('@socketsecurity/registry/lib/packages');
41
42
  var registryConstants = require('@socketsecurity/registry/lib/constants');
42
43
  var isInteractive = require('@socketregistry/is-interactive/index.cjs');
43
44
  var terminalLink = _socketInterop(require('terminal-link'));
44
- var spawn = _socketInterop(require('@npmcli/promise-spawn'));
45
+ var spawn = require('@socketsecurity/registry/lib/spawn');
45
46
  var npa = _socketInterop(require('npm-package-arg'));
46
47
  var semver = _socketInterop(require('semver'));
47
48
  var tinyglobby = _socketInterop(require('tinyglobby'));
@@ -53,13 +54,11 @@ var sorts = require('@socketsecurity/registry/lib/sorts');
53
54
  var strings = require('@socketsecurity/registry/lib/strings');
54
55
  var yaml = _socketInterop(require('yaml'));
55
56
  var debug = require('@socketsecurity/registry/lib/debug');
56
- var npm$1 = require('./npm.js');
57
57
  var npmPaths = require('./npm-paths.js');
58
58
  var betterAjvErrors = _socketInterop(require('@apideck/better-ajv-errors'));
59
59
  var config$A = require('@socketsecurity/config');
60
60
  var assert = require('node:assert');
61
61
  var readline = require('node:readline/promises');
62
- var childProcess = require('node:child_process');
63
62
  var TableWidget = _socketInterop(require('blessed-contrib/lib/widget/table'));
64
63
  var readline$1 = require('node:readline');
65
64
 
@@ -1517,7 +1516,7 @@ function meowOrExit({
1517
1516
  }
1518
1517
  function getAsciiHeader(command) {
1519
1518
  const cliVersion = // The '@rollup/plugin-replace' will replace "process.env['SOCKET_CLI_VERSION_HASH']".
1520
- "0.14.52:709a145:a30d9dfd:pub";
1519
+ "0.14.55:51de259:b691b88f:pub";
1521
1520
  const nodeVersion = process.version;
1522
1521
  const apiToken = index.getSetting('apiToken');
1523
1522
  const shownToken = apiToken ? getLastFiveOfApiToken(apiToken) : 'no';
@@ -1591,15 +1590,87 @@ async function run$z(argv, importMeta, {
1591
1590
  await runAction(githubEventBefore, githubEventAfter);
1592
1591
  }
1593
1592
 
1593
+ async function fetchOrgAnalyticsData(time, spinner, apiToken) {
1594
+ const socketSdk = await index.setupSdk(apiToken);
1595
+ const result = await handleApiCall(socketSdk.getOrgAnalytics(time.toString()), 'fetching analytics data');
1596
+ if (result.success === false) {
1597
+ handleUnsuccessfulApiResponse('getOrgAnalytics', result, spinner);
1598
+ return undefined;
1599
+ }
1600
+ spinner.stop();
1601
+ if (!result.data.length) {
1602
+ logger.logger.log('No analytics data is available for this organization yet.');
1603
+ return undefined;
1604
+ }
1605
+ return result.data;
1606
+ }
1607
+
1608
+ async function fetchRepoAnalyticsData(repo, time, spinner, apiToken) {
1609
+ const socketSdk = await index.setupSdk(apiToken);
1610
+ const result = await handleApiCall(socketSdk.getRepoAnalytics(repo, time.toString()), 'fetching analytics data');
1611
+ if (result.success === false) {
1612
+ handleUnsuccessfulApiResponse('getRepoAnalytics', result, spinner);
1613
+ return undefined;
1614
+ }
1615
+ spinner.stop();
1616
+ if (!result.data.length) {
1617
+ logger.logger.log('No analytics data is available for this organization yet.');
1618
+ return undefined;
1619
+ }
1620
+ return result.data;
1621
+ }
1622
+
1623
+ function mdTableStringNumber(title1, title2, obj) {
1624
+ // | Date | Counts |
1625
+ // | ----------- | ------ |
1626
+ // | Header | 201464 |
1627
+ // | Paragraph | 18 |
1628
+ let mw1 = title1.length;
1629
+ let mw2 = title2.length;
1630
+ for (const [key, value] of Object.entries(obj)) {
1631
+ mw1 = Math.max(mw1, key.length);
1632
+ mw2 = Math.max(mw2, String(value ?? '').length);
1633
+ }
1634
+ const lines = [];
1635
+ lines.push(`| ${title1.padEnd(mw1, ' ')} | ${title2.padEnd(mw2)} |`);
1636
+ lines.push(`| ${'-'.repeat(mw1)} | ${'-'.repeat(mw2)} |`);
1637
+ for (const [key, value] of Object.entries(obj)) {
1638
+ lines.push(`| ${key.padEnd(mw1, ' ')} | ${String(value ?? '').padStart(mw2, ' ')} |`);
1639
+ }
1640
+ lines.push(`| ${'-'.repeat(mw1)} | ${'-'.repeat(mw2)} |`);
1641
+ return lines.join('\n');
1642
+ }
1643
+
1594
1644
  // Note: Widgets does not seem to actually work as code :'(
1595
1645
 
1646
+ 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'];
1647
+
1596
1648
  // Note: This maps `new Date(date).getMonth()` to English three letters
1597
1649
  const Months = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'];
1598
- 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'];
1599
1650
  async function displayAnalytics({
1651
+ filePath,
1652
+ outputKind,
1653
+ repo,
1654
+ scope,
1655
+ time
1656
+ }) {
1657
+ const apiToken = index.getDefaultToken();
1658
+ if (!apiToken) {
1659
+ 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.');
1660
+ }
1661
+ await outputAnalyticsWithToken({
1662
+ apiToken,
1663
+ filePath,
1664
+ outputKind,
1665
+ repo,
1666
+ scope,
1667
+ time
1668
+ });
1669
+ }
1670
+ async function outputAnalyticsWithToken({
1600
1671
  apiToken,
1601
1672
  filePath,
1602
- outputJson,
1673
+ outputKind,
1603
1674
  repo,
1604
1675
  scope,
1605
1676
  time
@@ -1615,22 +1686,70 @@ async function displayAnalytics({
1615
1686
  } else if (repo) {
1616
1687
  data = await fetchRepoAnalyticsData(repo, time, spinner, apiToken);
1617
1688
  }
1618
- if (data) {
1619
- if (outputJson && !filePath) {
1620
- logger.logger.log(data);
1621
- } else if (filePath) {
1689
+
1690
+ // A message should already have been printed if we have no data here
1691
+ if (!data) return;
1692
+ if (outputKind === 'json') {
1693
+ let serialized = renderJson(data);
1694
+ if (!serialized) return;
1695
+ if (filePath && filePath !== '-') {
1622
1696
  try {
1623
- await fs$1.writeFile(filePath, JSON.stringify(data), 'utf8');
1697
+ await fs$1.writeFile(filePath, serialized, 'utf8');
1624
1698
  logger.logger.log(`Data successfully written to ${filePath}`);
1625
1699
  } catch (e) {
1700
+ logger.logger.error('There was an error trying to write the json to disk');
1626
1701
  logger.logger.error(e);
1702
+ process.exitCode = 1;
1703
+ }
1704
+ } else {
1705
+ logger.logger.log(serialized);
1706
+ }
1707
+ } else {
1708
+ const fdata = scope === 'org' ? formatDataOrg(data) : formatDataRepo(data);
1709
+ if (outputKind === 'markdown') {
1710
+ const serialized = renderMarkdown(fdata, time, repo);
1711
+ if (filePath && filePath !== '-') {
1712
+ try {
1713
+ await fs$1.writeFile(filePath, serialized, 'utf8');
1714
+ logger.logger.log(`Data successfully written to ${filePath}`);
1715
+ } catch (e) {
1716
+ logger.logger.error(e);
1717
+ }
1718
+ } else {
1719
+ logger.logger.log(serialized);
1627
1720
  }
1628
1721
  } else {
1629
- const fdata = scope === 'org' ? formatData(data, 'org') : formatData(data, 'repo');
1630
1722
  displayAnalyticsScreen(fdata);
1631
1723
  }
1632
1724
  }
1633
1725
  }
1726
+ function renderJson(data) {
1727
+ try {
1728
+ return JSON.stringify(data, null, 2);
1729
+ } catch (e) {
1730
+ // This could be caused by circular references, which is an "us" problem
1731
+ logger.logger.error('There was a problem converting the data set to JSON. Please try without --json or with --markdown');
1732
+ process.exitCode = 1;
1733
+ return;
1734
+ }
1735
+ }
1736
+ function renderMarkdown(data, days, repoSlug) {
1737
+ return commonTags.stripIndents`
1738
+ # Socket Alert Analytics
1739
+
1740
+ These are the Socket.dev stats are analytics for the ${repoSlug ? `${repoSlug} repo` : 'org'} of the past ${days} days
1741
+
1742
+ ${[['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`
1743
+ ## ${title}
1744
+
1745
+ ${table}
1746
+ `).join('\n\n')}
1747
+
1748
+ ## Top 5 alert types
1749
+
1750
+ ${mdTableStringNumber('Name', 'Counts', data['top_five_alert_types'])}
1751
+ `;
1752
+ }
1634
1753
  function displayAnalyticsScreen(data) {
1635
1754
  const screen = new ScreenWidget({});
1636
1755
  const grid = new contrib.grid({
@@ -1663,91 +1782,69 @@ function displayAnalyticsScreen(data) {
1663
1782
  screen.render();
1664
1783
  screen.key(['escape', 'q', 'C-c'], () => process.exit(0));
1665
1784
  }
1666
- async function fetchOrgAnalyticsData(time, spinner, apiToken) {
1667
- const socketSdk = await index.setupSdk(apiToken);
1668
- const result = await handleApiCall(socketSdk.getOrgAnalytics(time.toString()), 'fetching analytics data');
1669
- if (result.success === false) {
1670
- handleUnsuccessfulApiResponse('getOrgAnalytics', result, spinner);
1671
- return undefined;
1785
+ function formatDataRepo(data) {
1786
+ const sortedTopFiveAlerts = {};
1787
+ const totalTopAlerts = {};
1788
+ const formattedData = {};
1789
+ for (const metric of METRICS) {
1790
+ formattedData[metric] = {};
1672
1791
  }
1673
- spinner.stop();
1674
- if (!result.data.length) {
1675
- logger.logger.log('No analytics data is available for this organization yet.');
1676
- return undefined;
1792
+ for (const entry of data) {
1793
+ const topFiveAlertTypes = entry['top_five_alert_types'];
1794
+ for (const type of Object.keys(topFiveAlertTypes)) {
1795
+ const count = topFiveAlertTypes[type] ?? 0;
1796
+ if (!totalTopAlerts[type]) {
1797
+ totalTopAlerts[type] = count;
1798
+ } else if (count > (totalTopAlerts[type] ?? 0)) {
1799
+ totalTopAlerts[type] = count;
1800
+ }
1801
+ }
1677
1802
  }
1678
- return result.data;
1679
- }
1680
- async function fetchRepoAnalyticsData(repo, time, spinner, apiToken) {
1681
- const socketSdk = await index.setupSdk(apiToken);
1682
- const result = await handleApiCall(socketSdk.getRepoAnalytics(repo, time.toString()), 'fetching analytics data');
1683
- if (result.success === false) {
1684
- handleUnsuccessfulApiResponse('getRepoAnalytics', result, spinner);
1685
- return undefined;
1803
+ for (const entry of data) {
1804
+ for (const metric of METRICS) {
1805
+ formattedData[metric][formatDate(entry['created_at'])] = entry[metric];
1806
+ }
1686
1807
  }
1687
- spinner.stop();
1688
- if (!result.data.length) {
1689
- logger.logger.log('No analytics data is available for this organization yet.');
1690
- return undefined;
1808
+ const topFiveAlertEntries = Object.entries(totalTopAlerts).sort(([_keya, a], [_keyb, b]) => b - a).slice(0, 5);
1809
+ for (const [key, value] of topFiveAlertEntries) {
1810
+ sortedTopFiveAlerts[key] = value;
1691
1811
  }
1692
- return result.data;
1812
+ return {
1813
+ ...formattedData,
1814
+ top_five_alert_types: sortedTopFiveAlerts
1815
+ };
1693
1816
  }
1694
- function formatData(data, scope) {
1695
- const formattedData = {};
1817
+ function formatDataOrg(data) {
1696
1818
  const sortedTopFiveAlerts = {};
1697
1819
  const totalTopAlerts = {};
1820
+ const formattedData = {};
1698
1821
  for (const metric of METRICS) {
1699
1822
  formattedData[metric] = {};
1700
1823
  }
1701
- if (scope === 'org') {
1702
- for (const entry of data) {
1703
- const topFiveAlertTypes = entry['top_five_alert_types'];
1704
- for (const type of Object.keys(topFiveAlertTypes)) {
1705
- const count = topFiveAlertTypes[type] ?? 0;
1706
- if (!totalTopAlerts[type]) {
1707
- totalTopAlerts[type] = count;
1708
- } else {
1709
- totalTopAlerts[type] += count;
1710
- }
1711
- }
1712
- }
1713
- for (const metric of METRICS) {
1714
- const formatted = formattedData[metric];
1715
- for (const entry of data) {
1716
- const date = formatDate(entry['created_at']);
1717
- if (!formatted[date]) {
1718
- formatted[date] = entry[metric];
1719
- } else {
1720
- formatted[date] += entry[metric];
1721
- }
1722
- }
1723
- }
1724
- } else if (scope === 'repo') {
1725
- for (const entry of data) {
1726
- const topFiveAlertTypes = entry['top_five_alert_types'];
1727
- for (const type of Object.keys(topFiveAlertTypes)) {
1728
- const count = topFiveAlertTypes[type] ?? 0;
1729
- if (!totalTopAlerts[type]) {
1730
- totalTopAlerts[type] = count;
1731
- } else if (count > (totalTopAlerts[type] ?? 0)) {
1732
- totalTopAlerts[type] = count;
1733
- }
1824
+ for (const entry of data) {
1825
+ const topFiveAlertTypes = entry['top_five_alert_types'];
1826
+ for (const type of Object.keys(topFiveAlertTypes)) {
1827
+ const count = topFiveAlertTypes[type] ?? 0;
1828
+ if (!totalTopAlerts[type]) {
1829
+ totalTopAlerts[type] = count;
1830
+ } else {
1831
+ totalTopAlerts[type] += count;
1734
1832
  }
1735
1833
  }
1834
+ }
1835
+ for (const metric of METRICS) {
1836
+ const formatted = formattedData[metric];
1736
1837
  for (const entry of data) {
1737
- for (const metric of METRICS) {
1738
- formattedData[metric][formatDate(entry['created_at'])] = entry[metric];
1838
+ const date = formatDate(entry['created_at']);
1839
+ if (!formatted[date]) {
1840
+ formatted[date] = entry[metric];
1841
+ } else {
1842
+ formatted[date] += entry[metric];
1739
1843
  }
1740
1844
  }
1741
1845
  }
1742
- const topFiveAlertEntries = Object.entries(totalTopAlerts).sort(({
1743
- 1: a
1744
- }, {
1745
- 1: b
1746
- }) => b - a).slice(0, 5);
1747
- for (const {
1748
- 0: key,
1749
- 1: value
1750
- } of topFiveAlertEntries) {
1846
+ const topFiveAlertEntries = Object.entries(totalTopAlerts).sort(([_keya, a], [_keyb, b]) => b - a).slice(0, 5);
1847
+ for (const [key, value] of topFiveAlertEntries) {
1751
1848
  sortedTopFiveAlerts[key] = value;
1752
1849
  }
1753
1850
  return {
@@ -1792,6 +1889,18 @@ const config$y = {
1792
1889
  flags: {
1793
1890
  ...commonFlags,
1794
1891
  ...outputFlags,
1892
+ file: {
1893
+ type: 'string',
1894
+ shortFlag: 'f',
1895
+ default: '-',
1896
+ description: 'Path to a local file to save the output. Only valid with --json/--markdown. Defaults to stdout.'
1897
+ },
1898
+ repo: {
1899
+ type: 'string',
1900
+ shortFlag: 'r',
1901
+ default: '',
1902
+ description: 'Name of the repository. Only valid when scope=repo'
1903
+ },
1795
1904
  scope: {
1796
1905
  type: 'string',
1797
1906
  shortFlag: 's',
@@ -1803,18 +1912,6 @@ const config$y = {
1803
1912
  shortFlag: 't',
1804
1913
  default: 7,
1805
1914
  description: 'Time filter - either 7, 30 or 90, default: 7'
1806
- },
1807
- repo: {
1808
- type: 'string',
1809
- shortFlag: 'r',
1810
- default: '',
1811
- description: 'Name of the repository'
1812
- },
1813
- file: {
1814
- type: 'string',
1815
- shortFlag: 'f',
1816
- default: '',
1817
- description: 'Path to a local file to save the output'
1818
1915
  }
1819
1916
  },
1820
1917
  help: (command, {
@@ -1850,6 +1947,9 @@ async function run$y(argv, importMeta, {
1850
1947
  parentName
1851
1948
  });
1852
1949
  const {
1950
+ file,
1951
+ json,
1952
+ markdown,
1853
1953
  repo,
1854
1954
  scope,
1855
1955
  time
@@ -1857,66 +1957,154 @@ async function run$y(argv, importMeta, {
1857
1957
  const badScope = scope !== 'org' && scope !== 'repo';
1858
1958
  const badTime = time !== 7 && time !== 30 && time !== 90;
1859
1959
  const badRepo = scope === 'repo' && !repo;
1860
- if (badScope || badTime || badRepo) {
1960
+ const badFile = file !== '-' && !json && !markdown;
1961
+ const badFlags = json && markdown;
1962
+ if (badScope || badTime || badRepo || badFile || badFlags) {
1861
1963
  // Use exit status of 2 to indicate incorrect usage, generally invalid
1862
1964
  // options or missing arguments.
1863
1965
  // https://www.gnu.org/software/bash/manual/html_node/Exit-Status.html
1864
1966
  process.exitCode = 2;
1865
- logger.logger.error(`${colors.bgRed(colors.white('Input error'))}: Please provide the required fields:\n
1866
- - Scope must be "repo" or "org" ${badScope ? colors.red('(bad!)') : colors.green('(ok)')}\n
1867
- - The time filter must either be 7, 30 or 90 ${badTime ? colors.red('(bad!)') : colors.green('(ok)')}\n
1868
- - Repository name using --repo when scope is "repo" ${badRepo ? colors.red('(bad!)') : colors.green('(ok)')}\n`);
1967
+ logger.logger.error(commonTags.stripIndents`${colors.bgRed(colors.white('Input error'))}: Please provide the required fields:
1968
+
1969
+ - Scope must be "repo" or "org" ${badScope ? colors.red('(bad!)') : colors.green('(ok)')}
1970
+
1971
+ - The time filter must either be 7, 30 or 90 ${badTime ? colors.red('(bad!)') : colors.green('(ok)')}
1972
+
1973
+ ${scope === 'repo' ? `- Repository name using --repo when scope is "repo" ${badRepo ? colors.red('(bad!)') : colors.green('(ok)')}` : ''}
1974
+
1975
+ ${badFlags ? `- The \`--json\` and \`--markdown\` flags can not be used at the same time ${badFlags ? colors.red('(bad!)') : colors.green('(ok)')}` : ''}
1976
+
1977
+ ${badFile ? `- The \`--file\` flag is only valid when using \`--json\` or \`--markdown\` ${badFile ? colors.red('(bad!)') : colors.green('(ok)')}` : ''}
1978
+ `.split('\n').filter(s => !!s.trim()).join('\n'));
1869
1979
  return;
1870
1980
  }
1871
1981
  if (cli.flags['dryRun']) {
1872
1982
  logger.logger.log(DRY_RUN_BAIL_TEXT$x);
1873
1983
  return;
1874
1984
  }
1875
- const apiToken = index.getDefaultToken();
1876
- if (!apiToken) {
1877
- 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.');
1878
- }
1879
1985
  return await displayAnalytics({
1880
- apiToken,
1881
1986
  scope,
1882
1987
  time,
1883
1988
  repo: String(repo || ''),
1884
- outputJson: Boolean(cli.flags['json']),
1885
- filePath: String(cli.flags['file'] || '')
1989
+ outputKind: json ? 'json' : markdown ? 'markdown' : 'print',
1990
+ filePath: String(file || '')
1886
1991
  });
1887
1992
  }
1888
1993
 
1889
1994
  async function getAuditLog({
1890
- apiToken,
1995
+ logType,
1891
1996
  orgSlug,
1892
- outputJson,
1893
- outputMarkdown,
1997
+ outputKind,
1894
1998
  page,
1895
- perPage,
1896
- type
1999
+ perPage
1897
2000
  }) {
1898
- // Lazily access constants.spinner.
1899
- const {
1900
- spinner
1901
- } = constants;
1902
- spinner.start(`Looking up audit log for ${orgSlug}`);
1903
- const socketSdk = await index.setupSdk(apiToken);
1904
- const result = await handleApiCall(socketSdk.getAuditLogEvents(orgSlug, {
1905
- outputJson,
1906
- outputMarkdown,
2001
+ const apiToken = index.getDefaultToken();
2002
+ if (!apiToken) {
2003
+ 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.');
2004
+ }
2005
+ const auditLogs = await getAuditLogWithToken({
2006
+ apiToken,
1907
2007
  orgSlug,
1908
- type,
2008
+ outputKind,
1909
2009
  page,
1910
- per_page: perPage
1911
- }), `Looking up audit log for ${orgSlug}\n`);
1912
- if (!result.success) {
1913
- handleUnsuccessfulApiResponse('getAuditLogEvents', result, spinner);
2010
+ perPage,
2011
+ logType
2012
+ });
2013
+ if (!auditLogs) return;
2014
+ 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);
2015
+ }
2016
+ async function outputAsJson(auditLogs, orgSlug, logType, page, perPage) {
2017
+ let json;
2018
+ try {
2019
+ json = JSON.stringify({
2020
+ desc: 'Audit logs for given query',
2021
+ generated: new Date().toISOString(),
2022
+ org: orgSlug,
2023
+ logType,
2024
+ page,
2025
+ perPage,
2026
+ logs: auditLogs.map(log => {
2027
+ // Note: The subset is pretty arbitrary
2028
+ const {
2029
+ created_at,
2030
+ event_id,
2031
+ ip_address,
2032
+ type,
2033
+ user_agent,
2034
+ user_email
2035
+ } = log;
2036
+ return {
2037
+ event_id,
2038
+ created_at,
2039
+ ip_address,
2040
+ type,
2041
+ user_agent,
2042
+ user_email
2043
+ };
2044
+ })
2045
+ }, null, 2);
2046
+ } catch (e) {
2047
+ logger.logger.error('There was a problem converting the logs to JSON, please try without the `--json` flag');
2048
+ process.exitCode = 1;
1914
2049
  return;
1915
2050
  }
1916
- spinner.stop();
2051
+ logger.logger.log(json);
2052
+ }
2053
+ async function outputAsMarkdown(auditLogs, orgSlug, logType, page, perPage) {
2054
+ try {
2055
+ const table = mdTable(auditLogs, ['event_id', 'created_at', 'type', 'user_email', 'ip_address', 'user_agent']);
2056
+ logger.logger.log(commonTags.stripIndents`
2057
+ # Socket Audit Logs
2058
+
2059
+ These are the Socket.dev audit logs as per requested query.
2060
+ - org: ${orgSlug}
2061
+ - type filter: ${logType || '(none)'}
2062
+ - page: ${page}
2063
+ - per page: ${perPage}
2064
+ - generated: ${new Date().toISOString()}
2065
+
2066
+ ${table}
2067
+ `);
2068
+ } catch (e) {
2069
+ logger.logger.error('There was a problem converting the logs to JSON, please try without the `--json` flag');
2070
+ logger.logger.error(e);
2071
+ process.exitCode = 1;
2072
+ return;
2073
+ }
2074
+ }
2075
+ function mdTable(logs,
2076
+ // This is saying "an array of strings and the strings are a valid key of elements of T"
2077
+ // In turn, T is defined above as the audit log event type from our OpenAPI docs.
2078
+ cols) {
2079
+ // Max col width required to fit all data in that column
2080
+ const cws = cols.map(col => col.length);
2081
+ for (const log of logs) {
2082
+ for (let i = 0; i < cols.length; ++i) {
2083
+ // @ts-ignore
2084
+ const val = log[cols[i] ?? ''] ?? '';
2085
+ cws[i] = Math.max(cws[i] ?? 0, String(val).length);
2086
+ }
2087
+ }
2088
+ let div = '|';
2089
+ for (const cw of cws) div += ' ' + '-'.repeat(cw) + ' |';
2090
+ let header = '|';
2091
+ for (let i = 0; i < cols.length; ++i) header += ' ' + String(cols[i]).padEnd(cws[i] ?? 0, ' ') + ' |';
2092
+ let body = '';
2093
+ for (const log of logs) {
2094
+ body += '|';
2095
+ for (let i = 0; i < cols.length; ++i) {
2096
+ // @ts-ignore
2097
+ const val = log[cols[i] ?? ''] ?? '';
2098
+ body += ' ' + String(val).padEnd(cws[i] ?? 0, ' ') + ' |';
2099
+ }
2100
+ body += '\n';
2101
+ }
2102
+ return [div, header, div, body.trim(), div].filter(s => !!s.trim()).join('\n');
2103
+ }
2104
+ async function outputAsPrint(auditLogs, orgSlug, logType) {
1917
2105
  const data = [];
1918
2106
  const logDetails = {};
1919
- for (const d of result.data.results) {
2107
+ for (const d of auditLogs) {
1920
2108
  const {
1921
2109
  created_at
1922
2110
  } = d;
@@ -1933,11 +2121,42 @@ async function getAuditLog({
1933
2121
  }
1934
2122
  }
1935
2123
  logger.logger.log(logDetails[await prompts.select({
1936
- message: type ? `\n Audit log for: ${orgSlug} with type: ${type}\n` : `\n Audit log for: ${orgSlug}\n`,
2124
+ message: logType ? `\n Audit log for: ${orgSlug} with type: ${logType}\n` : `\n Audit log for: ${orgSlug}\n`,
1937
2125
  choices: data,
1938
2126
  pageSize: 30
1939
2127
  })]);
1940
2128
  }
2129
+ async function getAuditLogWithToken({
2130
+ apiToken,
2131
+ logType,
2132
+ orgSlug,
2133
+ outputKind,
2134
+ page,
2135
+ perPage
2136
+ }) {
2137
+ // Lazily access constants.spinner.
2138
+ const {
2139
+ spinner
2140
+ } = constants;
2141
+ spinner.start(`Looking up audit log for ${orgSlug}`);
2142
+ const socketSdk = await index.setupSdk(apiToken);
2143
+ const result = await handleApiCall(socketSdk.getAuditLogEvents(orgSlug, {
2144
+ outputJson: outputKind === 'json',
2145
+ // I'm not sure this is used at all
2146
+ outputMarkdown: outputKind === 'markdown',
2147
+ // I'm not sure this is used at all
2148
+ orgSlug,
2149
+ type: logType,
2150
+ page,
2151
+ per_page: perPage
2152
+ }), `Looking up audit log for ${orgSlug}\n`);
2153
+ if (!result.success) {
2154
+ handleUnsuccessfulApiResponse('getAuditLogEvents', result, spinner);
2155
+ return;
2156
+ }
2157
+ spinner.stop();
2158
+ return result.data;
2159
+ }
1941
2160
 
1942
2161
  const {
1943
2162
  DRY_RUN_BAIL_TEXT: DRY_RUN_BAIL_TEXT$w
@@ -1993,33 +2212,36 @@ async function run$x(argv, importMeta, {
1993
2212
  importMeta,
1994
2213
  parentName
1995
2214
  });
1996
- const type = String(cli.flags['type'] || '');
2215
+ const {
2216
+ json,
2217
+ markdown,
2218
+ page,
2219
+ perPage,
2220
+ type
2221
+ } = cli.flags;
2222
+ const logType = String(type || '');
1997
2223
  const [orgSlug = ''] = cli.input;
1998
2224
  if (!orgSlug) {
1999
2225
  // Use exit status of 2 to indicate incorrect usage, generally invalid
2000
2226
  // options or missing arguments.
2001
2227
  // https://www.gnu.org/software/bash/manual/html_node/Exit-Status.html
2002
2228
  process.exitCode = 2;
2003
- logger.logger.error(`${colors.bgRed(colors.white('Input error'))}: Please provide the required fields:\n
2004
- - Org name as the first argument ${!orgSlug ? colors.red('(missing!)') : colors.green('(ok)')}\n`);
2229
+ logger.logger.error(commonTags.stripIndents`
2230
+ ${colors.bgRed(colors.white('Input error'))}: Please provide the required fields:\n
2231
+ - Org name as the first argument ${!orgSlug ? colors.red('(missing!)') : colors.green('(ok)')}
2232
+ `);
2005
2233
  return;
2006
2234
  }
2007
2235
  if (cli.flags['dryRun']) {
2008
2236
  logger.logger.log(DRY_RUN_BAIL_TEXT$w);
2009
2237
  return;
2010
2238
  }
2011
- const apiToken = index.getDefaultToken();
2012
- if (!apiToken) {
2013
- 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.');
2014
- }
2015
2239
  await getAuditLog({
2016
- apiToken,
2017
2240
  orgSlug,
2018
- outputJson: Boolean(cli.flags['json']),
2019
- outputMarkdown: Boolean(cli.flags['markdown']),
2020
- page: Number(cli.flags['page'] || 0),
2021
- perPage: Number(cli.flags['perPage'] || 0),
2022
- type: type.charAt(0).toUpperCase() + type.slice(1)
2241
+ outputKind: json ? 'json' : markdown ? 'markdown' : 'print',
2242
+ page: Number(page || 0),
2243
+ perPage: Number(perPage || 0),
2244
+ logType: logType.charAt(0).toUpperCase() + logType.slice(1)
2023
2245
  });
2024
2246
  }
2025
2247
 
@@ -2206,8 +2428,11 @@ async function run$w(argv, importMeta, {
2206
2428
  //
2207
2429
  //
2208
2430
  // if (cli.input.length)
2209
- // logger.error(`${colors.bgRed(colors.white('Input error'))}: Please provide the required fields:\n
2210
- // - Unexpected arguments\n
2431
+ // logger.error(
2432
+ // stripIndents`
2433
+ // ${colors.bgRed(colors.white('Input error'))}: Please provide the required fields:
2434
+ //
2435
+ // - Unexpected arguments
2211
2436
  // `)
2212
2437
  // config.help(parentName, config)
2213
2438
  // return
@@ -2938,8 +3163,6 @@ function applyLogin(apiToken, enforcedOrgs, apiBaseUrl, apiProxy) {
2938
3163
  index.updateSetting('apiProxy', apiProxy);
2939
3164
  }
2940
3165
 
2941
- // TODO: this type should come from a general Socket REST API type doc
2942
-
2943
3166
  const {
2944
3167
  SOCKET_PUBLIC_API_TOKEN
2945
3168
  } = constants;
@@ -3151,7 +3374,7 @@ async function convertGradleToMaven(target, bin, _out, verbose, gradleOpts) {
3151
3374
  if (verbose) {
3152
3375
  spinner.log('[VERBOSE] Executing:', bin, commandArgs);
3153
3376
  }
3154
- const output = await spawn(bin, commandArgs, {
3377
+ const output = await spawn.spawn(bin, commandArgs, {
3155
3378
  cwd: target || '.'
3156
3379
  });
3157
3380
  spinner.stop();
@@ -3322,9 +3545,11 @@ async function run$p(argv, importMeta, {
3322
3545
  // options or missing arguments.
3323
3546
  // https://www.gnu.org/software/bash/manual/html_node/Exit-Status.html
3324
3547
  process.exitCode = 2;
3325
- logger.logger.error(`${colors.bgRed(colors.white('Input error'))}: Please provide the required fields:\n
3326
- - The DIR arg is required ${!target ? colors.red('(missing!)') : target === '-' ? colors.red('(stdin is not supported)') : colors.green('(ok)')}\n
3327
- - Can only accept one DIR (make sure to escape spaces!) ${cli.input.length > 1 ? colors.red(`(received ${cli.input.length}!)`) : colors.green('(ok)')}\n`);
3548
+ logger.logger.error(commonTags.stripIndents`${colors.bgRed(colors.white('Input error'))}: Please provide the required fields:
3549
+
3550
+ - The DIR arg is required ${!target ? colors.red('(missing!)') : target === '-' ? colors.red('(stdin is not supported)') : colors.green('(ok)')}
3551
+
3552
+ - Can only accept one DIR (make sure to escape spaces!) ${cli.input.length > 1 ? colors.red(`(received ${cli.input.length}!)`) : colors.green('(ok)')}`);
3328
3553
  return;
3329
3554
  }
3330
3555
  let bin;
@@ -3385,7 +3610,7 @@ async function convertSbtToMaven(target, bin, out, verbose, sbtOpts) {
3385
3610
  // we can upload them and predict them through the GitHub API. We could do a
3386
3611
  // .socket folder. We could do a socket.pom.gz with all the poms, although
3387
3612
  // I'd prefer something plain-text if it is to be committed.
3388
- const output = await spawn(bin, ['makePom'].concat(sbtOpts), {
3613
+ const output = await spawn.spawn(bin, ['makePom'].concat(sbtOpts), {
3389
3614
  cwd: target || '.'
3390
3615
  });
3391
3616
  spinner.stop();
@@ -3556,9 +3781,11 @@ async function run$o(argv, importMeta, {
3556
3781
  // options or missing arguments.
3557
3782
  // https://www.gnu.org/software/bash/manual/html_node/Exit-Status.html
3558
3783
  process.exitCode = 2;
3559
- logger.logger.error(`${colors.bgRed(colors.white('Input error'))}: Please provide the required fields:\n
3560
- - The DIR or FILE arg is required ${!target ? colors.red('(missing!)') : target === '-' ? colors.red('(stdin is not supported)') : colors.green('(ok)')}\n
3561
- - 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`);
3784
+ logger.logger.error(commonTags.stripIndents`${colors.bgRed(colors.white('Input error'))}: Please provide the required fields:
3785
+
3786
+ - The DIR or FILE arg is required ${!target ? colors.red('(missing!)') : target === '-' ? colors.red('(stdin is not supported)') : colors.green('(ok)')}
3787
+
3788
+ - 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)')}`);
3562
3789
  return;
3563
3790
  }
3564
3791
  let bin = 'sbt';
@@ -3814,9 +4041,11 @@ async function run$m(argv, importMeta, {
3814
4041
  // options or missing arguments.
3815
4042
  // https://www.gnu.org/software/bash/manual/html_node/Exit-Status.html
3816
4043
  process.exitCode = 2;
3817
- logger.logger.error(`${colors.bgRed(colors.white('Input error'))}: Please provide the required fields:\n
3818
- - The DIR arg is required ${!target ? colors.red('(missing!)') : target === '-' ? colors.red('(stdin is not supported)') : colors.green('(ok)')}\n
3819
- - Can only accept one DIR (make sure to escape spaces!) ${cli.input.length > 1 ? colors.red(`(received ${cli.input.length}!)`) : colors.green('(ok)')}\n`);
4044
+ logger.logger.error(commonTags.stripIndents`${colors.bgRed(colors.white('Input error'))}: Please provide the required fields:
4045
+
4046
+ - The DIR arg is required ${!target ? colors.red('(missing!)') : target === '-' ? colors.red('(stdin is not supported)') : colors.green('(ok)')}
4047
+
4048
+ - Can only accept one DIR (make sure to escape spaces!) ${cli.input.length > 1 ? colors.red(`(received ${cli.input.length}!)`) : colors.green('(ok)')}`);
3820
4049
  return;
3821
4050
  }
3822
4051
  let bin;
@@ -4064,7 +4293,7 @@ async function getAgentVersion(agentExecPath, cwd) {
4064
4293
  try {
4065
4294
  result = semver.coerce(
4066
4295
  // All package managers support the "--version" flag.
4067
- (await spawn(agentExecPath, ['--version'], {
4296
+ (await spawn.spawn(agentExecPath, ['--version'], {
4068
4297
  cwd
4069
4298
  })).stdout) ?? undefined;
4070
4299
  } catch {}
@@ -4119,7 +4348,7 @@ const readLockFileByAgent = (() => {
4119
4348
  // To print a Yarn lockfile to your console without writing it to disk
4120
4349
  // use `bun bun.lockb`.
4121
4350
  // https://bun.sh/guides/install/yarnlock
4122
- return (await spawn(agentExecPath, [lockPath])).stdout.trim();
4351
+ return (await spawn.spawn(agentExecPath, [lockPath])).stdout.trim();
4123
4352
  }
4124
4353
  return undefined;
4125
4354
  }),
@@ -4518,7 +4747,7 @@ function parseableToQueryStdout(stdout) {
4518
4747
  async function npmQuery(npmExecPath, cwd) {
4519
4748
  let stdout = '';
4520
4749
  try {
4521
- stdout = (await spawn(npmExecPath, ['query', ':not(.dev)'], {
4750
+ stdout = (await spawn.spawn(npmExecPath, ['query', ':not(.dev)'], {
4522
4751
  cwd
4523
4752
  })).stdout;
4524
4753
  } catch {}
@@ -4528,7 +4757,7 @@ async function lsBun(agentExecPath, cwd) {
4528
4757
  try {
4529
4758
  // Bun does not support filtering by production packages yet.
4530
4759
  // https://github.com/oven-sh/bun/issues/8283
4531
- return (await spawn(agentExecPath, ['pm', 'ls', '--all'], {
4760
+ return (await spawn.spawn(agentExecPath, ['pm', 'ls', '--all'], {
4532
4761
  cwd
4533
4762
  })).stdout;
4534
4763
  } catch {}
@@ -4547,7 +4776,7 @@ async function lsPnpm(agentExecPath, cwd, options) {
4547
4776
  }
4548
4777
  let stdout = '';
4549
4778
  try {
4550
- stdout = (await spawn(agentExecPath, ['ls', '--parseable', '--prod', '--depth', 'Infinity'], {
4779
+ stdout = (await spawn.spawn(agentExecPath, ['ls', '--parseable', '--prod', '--depth', 'Infinity'], {
4551
4780
  cwd
4552
4781
  })).stdout;
4553
4782
  } catch {}
@@ -4556,7 +4785,7 @@ async function lsPnpm(agentExecPath, cwd, options) {
4556
4785
  async function lsVlt(agentExecPath, cwd) {
4557
4786
  let stdout = '';
4558
4787
  try {
4559
- stdout = (await spawn(agentExecPath, ['ls', '--view', 'human', ':not(.dev)'], {
4788
+ stdout = (await spawn.spawn(agentExecPath, ['ls', '--view', 'human', ':not(.dev)'], {
4560
4789
  cwd
4561
4790
  })).stdout;
4562
4791
  } catch {}
@@ -4567,7 +4796,7 @@ async function lsYarnBerry(agentExecPath, cwd) {
4567
4796
  return (
4568
4797
  // Yarn Berry does not support filtering by production packages yet.
4569
4798
  // https://github.com/yarnpkg/berry/issues/5117
4570
- (await spawn(agentExecPath, ['info', '--recursive', '--name-only'], {
4799
+ (await spawn.spawn(agentExecPath, ['info', '--recursive', '--name-only'], {
4571
4800
  cwd
4572
4801
  })).stdout.trim()
4573
4802
  );
@@ -4580,7 +4809,7 @@ async function lsYarnClassic(agentExecPath, cwd) {
4580
4809
  // https://github.com/yarnpkg/yarn/releases/tag/v1.0.0
4581
4810
  // > Fix: Excludes dev dependencies from the yarn list output when the
4582
4811
  // environment is production
4583
- return (await spawn(agentExecPath, ['list', '--prod'], {
4812
+ return (await spawn.spawn(agentExecPath, ['list', '--prod'], {
4584
4813
  cwd
4585
4814
  })).stdout.trim();
4586
4815
  } catch {}
@@ -4705,14 +4934,73 @@ function pnpmUpdatePkgJson(editablePkgJson, overrides) {
4705
4934
  }
4706
4935
  const updateManifestByAgent = new Map([[BUN, updateResolutions], [NPM$4, updateOverrides], [PNPM$1, pnpmUpdatePkgJson], [VLT, updateOverrides], [YARN_BERRY, updateResolutions], [YARN_CLASSIC$1, updateResolutions]]);
4707
4936
 
4937
+ const {
4938
+ SOCKET_IPC_HANDSHAKE
4939
+ } = constants;
4940
+ function safeNpmInstall(options) {
4941
+ const {
4942
+ args = [],
4943
+ ipc,
4944
+ spinner,
4945
+ ...spawnOptions
4946
+ } = {
4947
+ __proto__: null,
4948
+ ...options
4949
+ };
4950
+ const terminatorPos = args.indexOf('--');
4951
+ const npmArgs = (terminatorPos === -1 ? args : args.slice(0, terminatorPos)).filter(a => !npm.isAuditFlag(a) && !npm.isFundFlag(a) && !npm.isProgressFlag(a));
4952
+ const otherArgs = terminatorPos === -1 ? [] : args.slice(terminatorPos);
4953
+ const useIpc = objects.isObject(ipc);
4954
+ const useDebug = debug.isDebug();
4955
+ const isSilent = !useDebug && !npmArgs.some(npm.isLoglevelFlag);
4956
+ const spawnPromise = spawn.spawn(
4957
+ // Lazily access constants.execPath.
4958
+ constants.execPath, [
4959
+ // Lazily access constants.nodeNoWarningsFlags.
4960
+ ...constants.nodeNoWarningsFlags, '--require',
4961
+ // Lazily access constants.npmInjectionPath.
4962
+ constants.npmInjectionPath, npmPaths.getNpmBinPath(), 'install',
4963
+ // Even though the '--silent' flag is passed npm will still run through
4964
+ // code paths for 'audit' and 'fund' unless '--no-audit' and '--no-fund'
4965
+ // flags are passed.
4966
+ '--no-audit', '--no-fund',
4967
+ // Add `--no-progress` and `--silent` flags to fix input being swallowed
4968
+ // by the spinner when running the command with recent versions of npm.
4969
+ '--no-progress',
4970
+ // Add the '--silent' flag if a loglevel flag is not provided and the
4971
+ // SOCKET_CLI_DEBUG environment variable is not truthy.
4972
+ ...(isSilent ? ['--silent'] : []), ...npmArgs, ...otherArgs], {
4973
+ spinner,
4974
+ // Set stdio to include 'ipc'.
4975
+ // See https://github.com/nodejs/node/blob/v23.6.0/lib/child_process.js#L161-L166
4976
+ // and https://github.com/nodejs/node/blob/v23.6.0/lib/internal/child_process.js#L238.
4977
+ stdio: isSilent ?
4978
+ // 'ignore'
4979
+ useIpc ? ['ignore', 'ignore', 'ignore', 'ipc'] : 'ignore' :
4980
+ // 'inherit'
4981
+ useIpc ? [0, 1, 2, 'ipc'] : 'inherit',
4982
+ ...spawnOptions,
4983
+ env: {
4984
+ ...process$1.env,
4985
+ ...spawnOptions.env
4986
+ }
4987
+ });
4988
+ if (useIpc) {
4989
+ spawnPromise.process.send({
4990
+ [SOCKET_IPC_HANDSHAKE]: ipc
4991
+ });
4992
+ }
4993
+ return spawnPromise;
4994
+ }
4995
+
4708
4996
  const {
4709
4997
  NPM: NPM$3,
4710
- abortSignal: abortSignal$2
4998
+ abortSignal
4711
4999
  } = constants;
4712
5000
  function runAgentInstall(agent, agentExecPath, options) {
4713
5001
  // All package managers support the "install" command.
4714
5002
  if (agent === NPM$3) {
4715
- return npm$1.safeNpmInstall(options);
5003
+ return safeNpmInstall(options);
4716
5004
  }
4717
5005
  const {
4718
5006
  args = [],
@@ -4723,12 +5011,9 @@ function runAgentInstall(agent, agentExecPath, options) {
4723
5011
  ...options
4724
5012
  };
4725
5013
  const isSilent = !debug.isDebug();
4726
- const isSpinning = spinner?.isSpinning ?? false;
4727
- if (!isSilent) {
4728
- spinner?.stop();
4729
- }
4730
- let spawnPromise = spawn(agentExecPath, ['install', ...args], {
4731
- signal: abortSignal$2,
5014
+ return spawn.spawn(agentExecPath, ['install', ...args], {
5015
+ signal: abortSignal,
5016
+ spinner,
4732
5017
  stdio: isSilent ? 'ignore' : 'inherit',
4733
5018
  ...spawnOptions,
4734
5019
  env: {
@@ -4736,22 +5021,12 @@ function runAgentInstall(agent, agentExecPath, options) {
4736
5021
  ...spawnOptions.env
4737
5022
  }
4738
5023
  });
4739
- if (!isSilent && isSpinning) {
4740
- const oldSpawnPromise = spawnPromise;
4741
- spawnPromise = spawnPromise.finally(() => {
4742
- spinner?.start();
4743
- });
4744
- spawnPromise.process = oldSpawnPromise.process;
4745
- spawnPromise.stdin = spawnPromise.stdin;
4746
- }
4747
- return spawnPromise;
4748
5024
  }
4749
5025
 
4750
5026
  const {
4751
5027
  NPM: NPM$2
4752
5028
  } = constants;
4753
5029
  const COMMAND_TITLE$1 = 'Socket Optimize';
4754
- const NPM_OVERRIDE_PR_URL = 'https://github.com/npm/cli/pull/8089';
4755
5030
  async function updatePackageLockJson(pkgEnvDetails, options) {
4756
5031
  const {
4757
5032
  logger,
@@ -4767,7 +5042,7 @@ async function updatePackageLockJson(pkgEnvDetails, options) {
4767
5042
  });
4768
5043
  spinner?.stop();
4769
5044
  if (pkgEnvDetails.agent === NPM$2) {
4770
- logger?.log(`💡 Re-run ${COMMAND_TITLE$1} whenever ${pkgEnvDetails.lockName} changes.\n This can be skipped once npm ships ${NPM_OVERRIDE_PR_URL}.`);
5045
+ logger?.log(`💡 Re-run ${COMMAND_TITLE$1} whenever ${pkgEnvDetails.lockName} changes.\n This can be skipped once npm v11.2.0 is released.`);
4771
5046
  }
4772
5047
  } catch (e) {
4773
5048
  spinner?.stop();
@@ -5168,9 +5443,10 @@ async function run$g(argv, importMeta, {
5168
5443
  // options or missing arguments.
5169
5444
  // https://www.gnu.org/software/bash/manual/html_node/Exit-Status.html
5170
5445
  process.exitCode = 2;
5171
- logger.logger.error(`
5172
- ${colors.bgRed(colors.white('Input error'))}: Please provide the required fields:\n
5173
- - The json and markdown flags cannot be both set, pick one
5446
+ logger.logger.error(commonTags.stripIndents`
5447
+ ${colors.bgRed(colors.white('Input error'))}: Please provide the required fields:
5448
+
5449
+ - The json and markdown flags cannot be both set, pick one
5174
5450
  `);
5175
5451
  return;
5176
5452
  }
@@ -5181,19 +5457,12 @@ async function run$g(argv, importMeta, {
5181
5457
  await getOrganization(json ? 'json' : markdown ? 'markdown' : 'text');
5182
5458
  }
5183
5459
 
5184
- const {
5185
- abortSignal: abortSignal$1
5186
- } = constants;
5187
5460
  async function runRawNpm(argv) {
5188
- const spawnPromise = spawn(npmPaths.getNpmBinPath(), argv.slice(0), {
5189
- signal: abortSignal$1,
5461
+ const spawnPromise = spawn.spawn(npmPaths.getNpmBinPath(), argv, {
5190
5462
  stdio: 'inherit'
5191
5463
  });
5192
5464
  // See https://nodejs.org/api/all.html#all_child_process_event-exit.
5193
5465
  spawnPromise.process.on('exit', (code, signalName) => {
5194
- if (abortSignal$1.aborted) {
5195
- return;
5196
- }
5197
5466
  if (signalName) {
5198
5467
  process$1.kill(process$1.pid, signalName);
5199
5468
  } else if (code !== null) {
@@ -5245,19 +5514,12 @@ async function run$f(argv, importMeta, {
5245
5514
  await runRawNpm(argv);
5246
5515
  }
5247
5516
 
5248
- const {
5249
- abortSignal
5250
- } = constants;
5251
5517
  async function runRawNpx(argv) {
5252
- const spawnPromise = spawn(npmPaths.getNpxBinPath(), argv, {
5253
- signal: abortSignal,
5518
+ const spawnPromise = spawn.spawn(npmPaths.getNpxBinPath(), argv, {
5254
5519
  stdio: 'inherit'
5255
5520
  });
5256
5521
  // See https://nodejs.org/api/all.html#all_child_process_event-exit.
5257
5522
  spawnPromise.process.on('exit', (code, signalName) => {
5258
- if (abortSignal.aborted) {
5259
- return;
5260
- }
5261
5523
  if (signalName) {
5262
5524
  process$1.kill(process$1.pid, signalName);
5263
5525
  } else if (code !== null) {
@@ -5422,11 +5684,12 @@ function formatReportDataOutput(reportId, data, commandName, outputJson, outputM
5422
5684
  logger.logger.log(JSON.stringify(data, undefined, 2));
5423
5685
  } else {
5424
5686
  const format = new index.ColorOrMarkdown(outputMarkdown);
5425
- logger.logger.log('\nDetailed info on socket.dev: ' + format.hyperlink(reportId, data.url, {
5687
+ logger.logger.log(commonTags.stripIndents`
5688
+ Detailed info on socket.dev: ${format.hyperlink(reportId, data.url, {
5426
5689
  fallbackToUrl: true
5427
- }));
5690
+ })}`);
5428
5691
  if (!outputMarkdown) {
5429
- logger.logger.log(colors.dim(`\nOr rerun ${colors.italic(commandName)} using the ${colors.italic('--json')} flag to get full JSON output`));
5692
+ logger.logger.log(colors.dim(`Or rerun ${colors.italic(commandName)} using the ${colors.italic('--json')} flag to get full JSON output`));
5430
5693
  }
5431
5694
  }
5432
5695
  if (strict && !data.healthy) {
@@ -5595,9 +5858,11 @@ async function run$c(argv, importMeta, {
5595
5858
  // options or missing arguments.
5596
5859
  // https://www.gnu.org/software/bash/manual/html_node/Exit-Status.html
5597
5860
  process.exitCode = 2;
5598
- logger.logger.error(`${colors.bgRed(colors.white('Input error'))}: Please provide the required fields:\n
5599
- - Need at least one report ID ${!reportId ? colors.red('(missing!)') : colors.green('(ok)')}\n
5600
- - Can only handle a single report ID ${extraInput.length < 2 ? colors.red(`(received ${extraInput.length}!)`) : colors.green('(ok)')}\n`);
5861
+ logger.logger.error(commonTags.stripIndents`${colors.bgRed(colors.white('Input error'))}: Please provide the required fields:
5862
+
5863
+ - Need at least one report ID ${!reportId ? colors.red('(missing!)') : colors.green('(ok)')}
5864
+
5865
+ - Can only handle a single report ID ${extraInput.length < 2 ? colors.red(`(received ${extraInput.length}!)`) : colors.green('(ok)')}`);
5601
5866
  return;
5602
5867
  }
5603
5868
  if (cli.flags['dryRun']) {
@@ -5738,9 +6003,11 @@ async function run$b(argv, importMeta, {
5738
6003
  // options or missing arguments.
5739
6004
  // https://www.gnu.org/software/bash/manual/html_node/Exit-Status.html
5740
6005
  process.exitCode = 2;
5741
- logger.logger.error(`${colors.bgRed(colors.white('Input error'))}: Please provide the required fields:\n
5742
- - Org name as the first argument ${!orgSlug ? colors.red('(missing!)') : colors.green('(ok)')}\n
5743
- - Repository name using --repoName ${!repoName ? colors.red('(missing!)') : typeof repoName !== 'string' ? colors.red('(invalid!)') : colors.green('(ok)')}\n`);
6006
+ logger.logger.error(commonTags.stripIndents`${colors.bgRed(colors.white('Input error'))}: Please provide the required fields:
6007
+
6008
+ - Org name as the first argument ${!orgSlug ? colors.red('(missing!)') : colors.green('(ok)')}
6009
+
6010
+ - Repository name using --repoName ${!repoName ? colors.red('(missing!)') : typeof repoName !== 'string' ? colors.red('(invalid!)') : colors.green('(ok)')}`);
5744
6011
  return;
5745
6012
  }
5746
6013
  if (cli.flags['dryRun']) {
@@ -5820,10 +6087,13 @@ async function run$a(argv, importMeta, {
5820
6087
  // options or missing arguments.
5821
6088
  // https://www.gnu.org/software/bash/manual/html_node/Exit-Status.html
5822
6089
  process.exitCode = 2;
5823
- logger.logger.error(`${colors.bgRed(colors.white('Input error'))}: Please provide the required fields:\n
5824
- - Org name as the first argument ${!orgSlug ? colors.red('(missing!)') : colors.green('(ok)')}\n
5825
- - Repository name as the second argument ${!repoName ? colors.red('(missing!)') : typeof repoName !== 'string' ? colors.red('(invalid!)') : colors.green('(ok)')}\n
5826
- - At least one TARGET (e.g. \`.\` or \`./package.json\`\n`);
6090
+ logger.logger.error(commonTags.stripIndents`${colors.bgRed(colors.white('Input error'))}: Please provide the required fields:
6091
+
6092
+ - Org name as the first argument ${!orgSlug ? colors.red('(missing!)') : colors.green('(ok)')}
6093
+
6094
+ - Repository name as the second argument ${!repoName ? colors.red('(missing!)') : typeof repoName !== 'string' ? colors.red('(invalid!)') : colors.green('(ok)')}
6095
+
6096
+ - At least one TARGET (e.g. \`.\` or \`./package.json\``);
5827
6097
  return;
5828
6098
  }
5829
6099
  if (cli.flags['dryRun']) {
@@ -5965,9 +6235,11 @@ async function run$9(argv, importMeta, {
5965
6235
  // options or missing arguments.
5966
6236
  // https://www.gnu.org/software/bash/manual/html_node/Exit-Status.html
5967
6237
  process.exitCode = 2;
5968
- logger.logger.error(`${colors.bgRed(colors.white('Input error'))}: Please provide the required fields:\n
5969
- - Org name as the first argument ${!orgSlug ? colors.red('(missing!)') : colors.green('(ok)')}\n
5970
- - At least one TARGET (e.g. \`.\` or \`./package.json\`\n`);
6238
+ logger.logger.error(commonTags.stripIndents`${colors.bgRed(colors.white('Input error'))}: Please provide the required fields:
6239
+
6240
+ - Org name as the first argument ${!orgSlug ? colors.red('(missing!)') : colors.green('(ok)')}
6241
+
6242
+ - At least one TARGET (e.g. \`.\` or \`./package.json\``);
5971
6243
  return;
5972
6244
  }
5973
6245
  if (cli.flags['dryRun']) {
@@ -6097,10 +6369,13 @@ async function run$8(argv, importMeta, {
6097
6369
  // options or missing arguments.
6098
6370
  // https://www.gnu.org/software/bash/manual/html_node/Exit-Status.html
6099
6371
  process.exitCode = 2;
6100
- logger.logger.error(`${colors.bgRed(colors.white('Input error'))}: Please provide the required fields:\n
6101
- - Org name as the first argument ${!orgSlug ? colors.red('(missing!)') : colors.green('(ok)')}\n
6102
- - Repository name using --repoName ${!repoName ? colors.red('(missing!)') : typeof repoName !== 'string' ? colors.red('(invalid!)') : colors.green('(ok)')}\n
6103
- - At least one TARGET (e.g. \`.\` or \`./package.json\`\n`);
6372
+ logger.logger.error(commonTags.stripIndents`${colors.bgRed(colors.white('Input error'))}: Please provide the required fields:
6373
+
6374
+ - Org name as the first argument ${!orgSlug ? colors.red('(missing!)') : colors.green('(ok)')}
6375
+
6376
+ - Repository name using --repoName ${!repoName ? colors.red('(missing!)') : typeof repoName !== 'string' ? colors.red('(invalid!)') : colors.green('(ok)')}
6377
+
6378
+ - At least one TARGET (e.g. \`.\` or \`./package.json\``);
6104
6379
  return;
6105
6380
  }
6106
6381
  if (cli.flags['dryRun']) {
@@ -6207,9 +6482,13 @@ async function run$7(argv, importMeta, {
6207
6482
  // options or missing arguments.
6208
6483
  // https://www.gnu.org/software/bash/manual/html_node/Exit-Status.html
6209
6484
  process.exitCode = 2;
6210
- logger.logger.error(`${colors.bgRed(colors.white('Input error'))}: Please provide the required fields:\n
6211
- - Org name as the first argument ${!orgSlug ? colors.red('(missing!)') : colors.green('(ok)')}\n
6212
- - Repository name using --repoName ${!repoName ? colors.red('(missing!)') : typeof repoName !== 'string' ? colors.red('(invalid!)') : colors.green('(ok)')}\n`);
6485
+ logger.logger.error(commonTags.stripIndents`
6486
+ ${colors.bgRed(colors.white('Input error'))}: Please provide the required fields:
6487
+
6488
+ - Org name as the first argument ${!orgSlug ? colors.red('(missing!)') : colors.green('(ok)')}
6489
+
6490
+ - Repository name using --repoName ${!repoName ? colors.red('(missing!)') : typeof repoName !== 'string' ? colors.red('(invalid!)') : colors.green('(ok)')}
6491
+ `);
6213
6492
  return;
6214
6493
  }
6215
6494
  if (cli.flags['dryRun']) {
@@ -6341,7 +6620,7 @@ function dirNameToSlug(name) {
6341
6620
  }
6342
6621
 
6343
6622
  async function suggestBranchSlug(repoDefaultBranch) {
6344
- const spawnResult = childProcess.spawnSync('git', ['branch', '--show-current']);
6623
+ const spawnResult = spawn.spawnSync('git', ['branch', '--show-current']);
6345
6624
  const currentBranch = spawnResult.stdout.toString('utf8').trim();
6346
6625
  if (currentBranch && spawnResult.status === 0) {
6347
6626
  const proceed = await prompts.select({
@@ -6465,14 +6744,19 @@ async function createFullScan({
6465
6744
  // options or missing arguments.
6466
6745
  // https://www.gnu.org/software/bash/manual/html_node/Exit-Status.html
6467
6746
  process$1.exitCode = 2;
6468
- logger.logger.error(`
6469
- ${colors.bgRed(colors.white('Input error'))}: Please provide the required fields:\n
6470
- - Org name as the first argument ${!orgSlug ? colors.red('(missing!)') : colors.green('(ok)')}\n
6471
- - Repository name using --repo ${!repoName ? colors.red('(missing!)') : colors.green('(ok)')}\n
6472
- - Branch name using --branch ${!branchName ? colors.red('(missing!)') : colors.green('(ok)')}\n
6473
- - 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
6474
- ${!apiToken ? 'Note: was unable to make suggestions because no API Token was found; this would make command fail regardless\n' : ''}
6475
- `);
6747
+ logger.logger.error(commonTags.stripIndents`
6748
+ ${colors.bgRed(colors.white('Input error'))}: Please provide the required fields:
6749
+
6750
+ - Org name as the first argument ${!orgSlug ? colors.red('(missing!)') : colors.green('(ok)')}
6751
+
6752
+ - Repository name using --repo ${!repoName ? colors.red('(missing!)') : colors.green('(ok)')}
6753
+
6754
+ - Branch name using --branch ${!branchName ? colors.red('(missing!)') : colors.green('(ok)')}
6755
+
6756
+ - 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)')}
6757
+
6758
+ ${!apiToken ? 'Note: was unable to make suggestions because no API Token was found; this would make command fail regardless' : ''}
6759
+ `);
6476
6760
  return;
6477
6761
  }
6478
6762
  if (updatedInput) {
@@ -6634,13 +6918,18 @@ async function run$6(argv, importMeta, {
6634
6918
  // options or missing arguments.
6635
6919
  // https://www.gnu.org/software/bash/manual/html_node/Exit-Status.html
6636
6920
  process$1.exitCode = 2;
6637
- logger.logger.error(`
6638
- ${colors.bgRed(colors.white('Input error'))}: Please provide the required fields:\n
6639
- - Org name as the first argument ${!orgSlug ? colors.red('(missing!)') : colors.green('(ok)')}\n
6640
- - Repository name using --repo ${!repoName ? colors.red('(missing!)') : colors.green('(ok)')}\n
6641
- - Branch name using --branch ${!branchName ? colors.red('(missing!)') : colors.green('(ok)')}\n
6642
- - At least one TARGET (e.g. \`.\` or \`./package.json\`) ${!targets.length ? '(missing)' : colors.green('(ok)')}\n
6643
- (Additionally, no API Token was set so we cannot auto-discover these details)\n
6921
+ logger.logger.error(commonTags.stripIndents`
6922
+ ${colors.bgRed(colors.white('Input error'))}: Please provide the required fields:
6923
+
6924
+ - Org name as the first argument ${!orgSlug ? colors.red('(missing!)') : colors.green('(ok)')}
6925
+
6926
+ - Repository name using --repo ${!repoName ? colors.red('(missing!)') : colors.green('(ok)')}
6927
+
6928
+ - Branch name using --branch ${!branchName ? colors.red('(missing!)') : colors.green('(ok)')}
6929
+
6930
+ - At least one TARGET (e.g. \`.\` or \`./package.json\`) ${!targets.length ? '(missing)' : colors.green('(ok)')}
6931
+
6932
+ (Additionally, no API Token was set so we cannot auto-discover these details)
6644
6933
  `);
6645
6934
  return;
6646
6935
  }
@@ -6724,9 +7013,11 @@ async function run$5(argv, importMeta, {
6724
7013
  // options or missing arguments.
6725
7014
  // https://www.gnu.org/software/bash/manual/html_node/Exit-Status.html
6726
7015
  process.exitCode = 2;
6727
- logger.logger.error(`${colors.bgRed(colors.white('Input error'))}: Please provide the required fields:\n
6728
- - Org name as the first argument ${!orgSlug ? colors.red('(missing!)') : colors.green('(ok)')}\n
6729
- - Full Scan ID to delete as second argument ${!fullScanId ? colors.red('(missing!)') : colors.green('(ok)')}\n`);
7016
+ logger.logger.error(commonTags.stripIndents`${colors.bgRed(colors.white('Input error'))}: Please provide the required fields:
7017
+
7018
+ - Org name as the first argument ${!orgSlug ? colors.red('(missing!)') : colors.green('(ok)')}
7019
+
7020
+ - Full Scan ID to delete as second argument ${!fullScanId ? colors.red('(missing!)') : colors.green('(ok)')}`);
6730
7021
  return;
6731
7022
  }
6732
7023
  if (cli.flags['dryRun']) {
@@ -6862,8 +7153,9 @@ async function run$4(argv, importMeta, {
6862
7153
  // options or missing arguments.
6863
7154
  // https://www.gnu.org/software/bash/manual/html_node/Exit-Status.html
6864
7155
  process.exitCode = 2;
6865
- logger.logger.error(`${colors.bgRed(colors.white('Input error'))}: Please provide the required fields:\n
6866
- - Org name as the argument ${!orgSlug ? colors.red('(missing!)') : colors.green('(ok)')}\n`);
7156
+ logger.logger.error(commonTags.stripIndents`${colors.bgRed(colors.white('Input error'))}: Please provide the required fields:
7157
+
7158
+ - Org name as the argument ${!orgSlug ? colors.red('(missing!)') : colors.green('(ok)')}`);
6867
7159
  return;
6868
7160
  }
6869
7161
  if (cli.flags['dryRun']) {
@@ -6947,9 +7239,11 @@ async function run$3(argv, importMeta, {
6947
7239
  // options or missing arguments.
6948
7240
  // https://www.gnu.org/software/bash/manual/html_node/Exit-Status.html
6949
7241
  process.exitCode = 2;
6950
- logger.logger.error(`${colors.bgRed(colors.white('Input error'))}: Please provide the required fields:\n
6951
- - Org name as the first argument ${!orgSlug ? colors.red('(missing!)') : colors.green('(ok)')}\n
6952
- - Full Scan ID to inspect as second argument ${!fullScanId ? colors.red('(missing!)') : colors.green('(ok)')}\n`);
7242
+ logger.logger.error(commonTags.stripIndents`${colors.bgRed(colors.white('Input error'))}: Please provide the required fields:
7243
+
7244
+ - Org name as the first argument ${!orgSlug ? colors.red('(missing!)') : colors.green('(ok)')}
7245
+
7246
+ - Full Scan ID to inspect as second argument ${!fullScanId ? colors.red('(missing!)') : colors.green('(ok)')}`);
6953
7247
  return;
6954
7248
  }
6955
7249
  if (cli.flags['dryRun']) {
@@ -7023,9 +7317,13 @@ async function run$2(argv, importMeta, {
7023
7317
  // options or missing arguments.
7024
7318
  // https://www.gnu.org/software/bash/manual/html_node/Exit-Status.html
7025
7319
  process.exitCode = 2;
7026
- logger.logger.error(`${colors.bgRed(colors.white('Input error'))}: Please provide the required fields:\n
7027
- - Org name as the first argument ${!orgSlug ? colors.red('(missing!)') : colors.green('(ok)')}\n
7028
- - Full Scan ID to fetch as second argument ${!fullScanId ? colors.red('(missing!)') : colors.green('(ok)')}\n`);
7320
+ logger.logger.error(commonTags.stripIndents`
7321
+ ${colors.bgRed(colors.white('Input error'))}: Please provide the required fields:
7322
+
7323
+ - Org name as the first argument ${!orgSlug ? colors.red('(missing!)') : colors.green('(ok)')}
7324
+
7325
+ - Full Scan ID to fetch as second argument ${!fullScanId ? colors.red('(missing!)') : colors.green('(ok)')}
7326
+ `);
7029
7327
  return;
7030
7328
  }
7031
7329
  if (cli.flags['dryRun']) {
@@ -7224,7 +7522,7 @@ function addSocketWrapper(file) {
7224
7522
  }
7225
7523
  // TODO: pretty sure you need to source the file or restart
7226
7524
  // any terminal session before changes are reflected.
7227
- logger.logger.log(`
7525
+ logger.logger.log(commonTags.stripIndents`
7228
7526
  The alias was added to ${file}. Running 'npm install' will now be wrapped in Socket's "safe npm" 🎉
7229
7527
  If you want to disable it at any time, run \`socket wrapper --disable\`
7230
7528
  `);
@@ -7377,8 +7675,11 @@ async function run(argv, importMeta, {
7377
7675
  // options or missing arguments.
7378
7676
  // https://www.gnu.org/software/bash/manual/html_node/Exit-Status.html
7379
7677
  process.exitCode = 2;
7380
- logger.logger.error(`${colors.bgRed(colors.white('Input error'))}: Please provide the required flags:\n
7381
- - Must use --enabled or --disabled\n`);
7678
+ logger.logger.error(commonTags.stripIndents`
7679
+ ${colors.bgRed(colors.white('Input error'))}: Please provide the required flags:
7680
+
7681
+ - Must use --enabled or --disabled
7682
+ `);
7382
7683
  return;
7383
7684
  }
7384
7685
  if (cli.flags['dryRun']) {
@@ -7487,5 +7788,5 @@ void (async () => {
7487
7788
  await index.captureException(e);
7488
7789
  }
7489
7790
  })();
7490
- //# debugId=58e6ceed-07a5-4b32-b0e9-9fef0ceef6d7
7791
+ //# debugId=b11caea8-68eb-4110-977e-c8cc2d1f4464
7491
7792
  //# sourceMappingURL=cli.js.map