@socketsecurity/cli-with-sentry 0.14.49 → 0.14.50

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.
@@ -56,7 +56,9 @@ var npmPaths = require('./npm-paths.js');
56
56
  var npm$1 = require('./npm.js');
57
57
  var betterAjvErrors = _socketInterop(require('@apideck/better-ajv-errors'));
58
58
  var config$A = require('@socketsecurity/config');
59
+ var assert = require('node:assert');
59
60
  var readline = require('node:readline/promises');
61
+ var childProcess = require('node:child_process');
60
62
  var TableWidget = _socketInterop(require('blessed-contrib/lib/widget/table'));
61
63
  var readline$1 = require('node:readline');
62
64
 
@@ -1293,7 +1295,7 @@ function handleUnsuccessfulApiResponse(_name, result, spinner) {
1293
1295
  spinner.stop();
1294
1296
  throw new index.AuthError(message);
1295
1297
  }
1296
- spinner.error(`${colors.bgRed(colors.white('API returned an error:'))} ${message}`);
1298
+ spinner.errorAndStop(`${colors.bgRed(colors.white('API returned an error:'))} ${message}`);
1297
1299
  process$1.exit(1);
1298
1300
  }
1299
1301
  async function handleApiCall(value, description) {
@@ -1512,7 +1514,7 @@ function meowOrExit({
1512
1514
  }
1513
1515
  function getAsciiHeader(command) {
1514
1516
  const cliVersion = // The '@rollup/plugin-replace' will replace "process.env['SOCKET_CLI_VERSION_HASH']".
1515
- "0.14.49:216163f:34d3aac1:pub";
1517
+ "0.14.50:c8e152a:9126d091:pub";
1516
1518
  const nodeVersion = process.version;
1517
1519
  const apiToken = index.getSetting('apiToken');
1518
1520
  const shownToken = apiToken ? getLastFiveOfApiToken(apiToken) : 'no';
@@ -2340,7 +2342,7 @@ async function getDiffScan({
2340
2342
  const data = await response.json();
2341
2343
  if (!response.ok) {
2342
2344
  const err = await handleAPIError(response.status);
2343
- spinner$1.error(`${colors.bgRed(colors.white(response.statusText))}: ${err}`);
2345
+ spinner$1.errorAndStop(`${colors.bgRed(colors.white(response.statusText))}: ${err}`);
2344
2346
  return;
2345
2347
  }
2346
2348
  spinner$1.stop();
@@ -2556,7 +2558,7 @@ async function runFix() {
2556
2558
  // eslint-disable-next-line no-await-in-loop
2557
2559
  await editablePkgJson.save();
2558
2560
  } catch {
2559
- spinner$1.error(`Reverting ${name} to ${oldVersion}`);
2561
+ spinner$1.errorAndStop(`Reverting ${name} to ${oldVersion}`);
2560
2562
  spinner$1.start();
2561
2563
  arb.idealTree = revertToIdealTree;
2562
2564
  }
@@ -2736,7 +2738,7 @@ function formatPackageInfo({
2736
2738
  spinner[strict ? 'error' : 'success'](`Package has these issues: ${formatSeverityCount(severityCount)}`);
2737
2739
  formatPackageIssuesDetails(data, outputMarkdown);
2738
2740
  } else {
2739
- spinner.success('Package has no issues');
2741
+ spinner.successAndStop('Package has no issues');
2740
2742
  }
2741
2743
  const format = new index.ColorOrMarkdown(!!outputMarkdown);
2742
2744
  const url = index.getSocketDevPackageOverviewUrl(NPM$c, pkgName, pkgVersion);
@@ -2917,7 +2919,7 @@ async function attemptLogin(apiBaseUrl, apiProxy) {
2917
2919
  orgs = result.data;
2918
2920
  spinner$1.success('API key verified');
2919
2921
  } catch {
2920
- spinner$1.error('Invalid API key');
2922
+ spinner$1.errorAndStop('Invalid API key');
2921
2923
  return;
2922
2924
  }
2923
2925
  const enforcedChoices = Object.values(orgs.organizations).filter(org => org?.plan === 'enterprise').map(org => ({
@@ -2952,9 +2954,9 @@ async function attemptLogin(apiBaseUrl, apiProxy) {
2952
2954
  const oldToken = index.getSetting('apiToken');
2953
2955
  try {
2954
2956
  applyLogin(apiToken, enforcedOrgs, apiBaseUrl, apiProxy);
2955
- spinner$1.success(`API credentials ${oldToken ? 'updated' : 'set'}`);
2957
+ spinner$1.successAndStop(`API credentials ${oldToken ? 'updated' : 'set'}`);
2956
2958
  } catch {
2957
- spinner$1.error(`API login failed`);
2959
+ spinner$1.errorAndStop(`API login failed`);
2958
2960
  }
2959
2961
  }
2960
2962
 
@@ -3096,14 +3098,14 @@ async function convertGradleToMaven(target, bin, _out, verbose, gradleOpts) {
3096
3098
  const output = await spawn(bin, commandArgs, {
3097
3099
  cwd: target || '.'
3098
3100
  });
3099
- spinner$1.success();
3101
+ spinner$1.stop();
3100
3102
  if (verbose) {
3101
3103
  console.group('[VERBOSE] gradle stdout:');
3102
3104
  console.log(output);
3103
3105
  console.groupEnd();
3104
3106
  }
3105
3107
  if (output.stderr) {
3106
- spinner$1.error('There were errors while running gradle');
3108
+ spinner$1.errorAndStop('There were errors while running gradle');
3107
3109
  // (In verbose mode, stderr was printed above, no need to repeat it)
3108
3110
  if (!verbose) {
3109
3111
  console.group('[VERBOSE] stderr:');
@@ -3112,6 +3114,8 @@ async function convertGradleToMaven(target, bin, _out, verbose, gradleOpts) {
3112
3114
  }
3113
3115
  process.exit(1);
3114
3116
  }
3117
+ spinner$1.start();
3118
+ spinner$1.successAndStop('Executed gradle successfully');
3115
3119
  console.log('Reported exports:');
3116
3120
  output.stdout.replace(/^POM file copied to: (.*)/gm, (_all, fn) => {
3117
3121
  console.log('- ', fn);
@@ -3120,7 +3124,7 @@ async function convertGradleToMaven(target, bin, _out, verbose, gradleOpts) {
3120
3124
 
3121
3125
  // const loc = output.stdout?.match(/Wrote (.*?.pom)\n/)?.[1]?.trim()
3122
3126
  // if (!loc) {
3123
- // spinner.error(
3127
+ // spinner.errorAndStop(
3124
3128
  // 'There were no errors from sbt but could not find the location of resulting .pom file either'
3125
3129
  // )
3126
3130
  // process.exit(1)
@@ -3142,11 +3146,11 @@ async function convertGradleToMaven(target, bin, _out, verbose, gradleOpts) {
3142
3146
  // }
3143
3147
  // // TODO: do we prefer fs-extra? renaming can be gnarly on windows and fs-extra's version is better
3144
3148
  // await renamep(loc, out)
3145
- // spinner.success()
3149
+ // spinner.successAndStop()
3146
3150
  // spinner.start().success(`OK. File should be available in \`${out}\``)
3147
3151
  // }
3148
3152
  } catch (e) {
3149
- spinner$1.error('There was an unexpected error while running this' + (verbose ? '' : ' (use --verbose for details)'));
3153
+ spinner$1.errorAndStop('There was an unexpected error while running this' + (verbose ? '' : ' (use --verbose for details)'));
3150
3154
  if (verbose) {
3151
3155
  console.group('[VERBOSE] error:');
3152
3156
  console.log(e);
@@ -3321,14 +3325,15 @@ async function convertSbtToMaven(target, bin, out, verbose, sbtOpts) {
3321
3325
  const output = await spawn(bin, ['makePom'].concat(sbtOpts), {
3322
3326
  cwd: target || '.'
3323
3327
  });
3324
- spinner$1.success();
3328
+ spinner$1.successAndStop();
3325
3329
  if (verbose) {
3326
3330
  console.group('[VERBOSE] sbt stdout:');
3327
3331
  console.log(output);
3328
3332
  console.groupEnd();
3329
3333
  }
3330
3334
  if (output.stderr) {
3331
- spinner$1.error('There were errors while running sbt');
3335
+ spinner$1.start();
3336
+ spinner$1.errorAndStop('There were errors while running sbt');
3332
3337
  // (In verbose mode, stderr was printed above, no need to repeat it)
3333
3338
  if (!verbose) {
3334
3339
  console.group('[VERBOSE] stderr:');
@@ -3343,7 +3348,7 @@ async function convertSbtToMaven(target, bin, out, verbose, sbtOpts) {
3343
3348
  return fn;
3344
3349
  });
3345
3350
  if (!poms.length) {
3346
- spinner$1.error('There were no errors from sbt but it seems to not have generated any poms either');
3351
+ spinner$1.errorAndStop('There were no errors from sbt but it seems to not have generated any poms either');
3347
3352
  process.exit(1);
3348
3353
  }
3349
3354
 
@@ -3375,7 +3380,7 @@ async function convertSbtToMaven(target, bin, out, verbose, sbtOpts) {
3375
3380
  spinner$1.start().success(`OK`);
3376
3381
  }
3377
3382
  } catch (e) {
3378
- spinner$1.error('There was an unexpected error while running this' + (verbose ? '' : ' (use --verbose for details)'));
3383
+ spinner$1.errorAndStop('There was an unexpected error while running this' + (verbose ? '' : ' (use --verbose for details)'));
3379
3384
  if (verbose) {
3380
3385
  console.group('[VERBOSE] error:');
3381
3386
  console.log(e);
@@ -5235,7 +5240,7 @@ async function createReport(socketConfig, inputPaths, {
5235
5240
  handleUnsuccessfulApiResponse('createReport', result, spinner$1);
5236
5241
  return undefined;
5237
5242
  }
5238
- spinner$1.success();
5243
+ spinner$1.successAndStop();
5239
5244
  return result;
5240
5245
  }
5241
5246
  }
@@ -5287,16 +5292,16 @@ async function fetchReportData(reportId, includeAllIssues, strict) {
5287
5292
 
5288
5293
  if (strict) {
5289
5294
  if (result.data.healthy) {
5290
- spinner$1.success('Report result is healthy and great!');
5295
+ spinner$1.successAndStop('Report result is healthy and great!');
5291
5296
  } else {
5292
- spinner$1.error('Report result deemed unhealthy for project');
5297
+ spinner$1.errorAndStop('Report result deemed unhealthy for project');
5293
5298
  }
5294
5299
  } else if (!result.data.healthy) {
5295
5300
  const severityCount = getSeverityCount(result.data.issues, includeAllIssues ? undefined : 'high');
5296
5301
  const issueSummary = formatSeverityCount(severityCount);
5297
- spinner$1.success(`Report has these issues: ${issueSummary}`);
5302
+ spinner$1.successAndStop(`Report has these issues: ${issueSummary}`);
5298
5303
  } else {
5299
- spinner$1.success('Report has no issues');
5304
+ spinner$1.successAndStop('Report has no issues');
5300
5305
  }
5301
5306
  return result.data;
5302
5307
  }
@@ -5535,7 +5540,7 @@ async function createRepo({
5535
5540
  visibility
5536
5541
  }), 'creating repository');
5537
5542
  if (result.success) {
5538
- spinner$1.success('Repository created successfully');
5543
+ spinner$1.successAndStop('Repository created successfully');
5539
5544
  } else {
5540
5545
  handleUnsuccessfulApiResponse('createOrgRepo', result, spinner$1);
5541
5546
  }
@@ -5644,7 +5649,7 @@ async function deleteRepo(orgSlug, repoName, apiToken) {
5644
5649
  const socketSdk = await index.setupSdk(apiToken);
5645
5650
  const result = await handleApiCall(socketSdk.deleteOrgRepo(orgSlug, repoName), 'deleting repository');
5646
5651
  if (result.success) {
5647
- spinner$1.success('Repository deleted successfully');
5652
+ spinner$1.successAndStop('Repository deleted successfully');
5648
5653
  } else {
5649
5654
  handleUnsuccessfulApiResponse('deleteOrgRepo', result, spinner$1);
5650
5655
  }
@@ -5733,6 +5738,18 @@ async function listRepos({
5733
5738
  handleUnsuccessfulApiResponse('getOrgRepoList', result, spinner$1);
5734
5739
  return;
5735
5740
  }
5741
+ spinner$1.stop();
5742
+ if (outputJson) {
5743
+ const data = result.data.results.map(o => ({
5744
+ id: o.id,
5745
+ name: o.name,
5746
+ visibility: o.visibility,
5747
+ defaultBranch: o.default_branch,
5748
+ archived: o.archived
5749
+ }));
5750
+ console.log(JSON.stringify(data, null, 2));
5751
+ return;
5752
+ }
5736
5753
  const options = {
5737
5754
  columns: [{
5738
5755
  field: 'id',
@@ -5751,7 +5768,7 @@ async function listRepos({
5751
5768
  name: colors.magenta('Archived')
5752
5769
  }]
5753
5770
  };
5754
- spinner$1.stop(chalkTable(options, result.data.results));
5771
+ console.log(chalkTable(options, result.data.results));
5755
5772
  }
5756
5773
 
5757
5774
  const config$9 = {
@@ -5867,7 +5884,7 @@ async function updateRepo({
5867
5884
  visibility
5868
5885
  }), 'updating repository');
5869
5886
  if (result.success) {
5870
- spinner$1.success('Repository updated successfully');
5887
+ spinner$1.successAndStop('Repository updated successfully');
5871
5888
  } else {
5872
5889
  handleUnsuccessfulApiResponse('updateOrgRepo', result, spinner$1);
5873
5890
  }
@@ -6084,8 +6101,149 @@ const cmdRepos = {
6084
6101
  }
6085
6102
  };
6086
6103
 
6104
+ async function suggestOrgSlug(socketSdk) {
6105
+ const result = await handleApiCall(socketSdk.getOrganizations(), 'looking up organizations');
6106
+ // Ignore a failed request here. It was not the primary goal of
6107
+ // running this command and reporting it only leads to end-user confusion.
6108
+ if (result.success) {
6109
+ const proceed = await prompts.select({
6110
+ message: 'Missing org name; do you want to use any of these orgs for this scan?',
6111
+ choices: Array.from(Object.values(result.data.organizations)).map(({
6112
+ name: slug
6113
+ }) => ({
6114
+ name: 'Yes [' + slug + ']',
6115
+ value: slug,
6116
+ description: `Use "${slug}" as the organization`
6117
+ })).concat({
6118
+ name: 'No',
6119
+ value: '',
6120
+ description: 'Do not use any of these organizations (will end in a no-op)'
6121
+ })
6122
+ });
6123
+ if (proceed) {
6124
+ return proceed;
6125
+ }
6126
+ }
6127
+ }
6128
+
6129
+ async function suggestRepoSlug(socketSdk, orgSlug) {
6130
+ // Same as above, but if there's a repo with the same name as cwd then
6131
+ // default the selection to that name.
6132
+ const result = await handleApiCall(socketSdk.getOrgRepoList(orgSlug, {
6133
+ orgSlug,
6134
+ sort: 'name',
6135
+ direction: 'asc',
6136
+ // There's no guarantee that the cwd is part of this page. If it's not
6137
+ // then do an additional request and specific search for it instead.
6138
+ // This way we can offer the tip of "do you want to create [cwd]?".
6139
+ perPage: 10,
6140
+ page: 0
6141
+ }), 'looking up known repos');
6142
+ // Ignore a failed request here. It was not the primary goal of
6143
+ // running this command and reporting it only leads to end-user confusion.
6144
+ if (result.success) {
6145
+ const currentDirName = dirNameToSlug(path.basename(process$1.cwd()));
6146
+ let cwdIsKnown = !!currentDirName && result.data.results.some(obj => obj.slug === currentDirName);
6147
+ if (!cwdIsKnown && currentDirName) {
6148
+ // Do an explicit request so we can assert that the cwd exists or not
6149
+ const result = await handleApiCall(socketSdk.getOrgRepo(orgSlug, currentDirName), 'checking if current cwd is a known repo');
6150
+ if (result.success) {
6151
+ cwdIsKnown = true;
6152
+ }
6153
+ }
6154
+ const proceed = await prompts.select({
6155
+ message: 'Missing repo name; do you want to use any of these known repo names for this scan?',
6156
+ choices:
6157
+ // Put the CWD suggestion at the top, whether it exists or not
6158
+ (currentDirName ? [{
6159
+ name: `Yes, current dir [${cwdIsKnown ? currentDirName : `create repo for ${currentDirName}`}]`,
6160
+ value: currentDirName,
6161
+ description: cwdIsKnown ? 'Register a new repo name under the given org and use it' : 'Use current dir as repo'
6162
+ }] : []).concat(result.data.results.filter(({
6163
+ slug
6164
+ }) => !!slug && slug !== currentDirName).map(({
6165
+ slug
6166
+ }) => ({
6167
+ name: 'Yes [' + slug + ']',
6168
+ value: slug || '',
6169
+ // Filtered above but TS is like nah.
6170
+ description: `Use "${slug}" as the repo name`
6171
+ })), {
6172
+ name: 'No',
6173
+ value: '',
6174
+ description: 'Do not use any of these repos (will end in a no-op)'
6175
+ })
6176
+ });
6177
+ if (proceed) {
6178
+ const repoName = proceed;
6179
+ let repoDefaultBranch = '';
6180
+ // Store the default branch to help with the branch name question next
6181
+ result.data.results.some(obj => {
6182
+ if (obj.slug === proceed && obj.default_branch) {
6183
+ repoDefaultBranch = obj.default_branch;
6184
+ return;
6185
+ }
6186
+ });
6187
+ return {
6188
+ slug: repoName,
6189
+ defaultBranch: repoDefaultBranch
6190
+ };
6191
+ }
6192
+ }
6193
+ }
6194
+ function dirNameToSlug(name) {
6195
+ // Uses slug specs asserted by our servers
6196
+ // Note: this can lead to collisions; eg. slug for `x--y` and `x---y` is `x-y`
6197
+ return name.toLowerCase().replace(/[^[a-zA-Z0-9_.-]/g, '_').replace(/--+/g, '-').replace(/__+/g, '_').replace(/\.\.+/g, '.').replace(/[._-]+$/, '');
6198
+ }
6199
+
6200
+ async function suggestBranchSlug(repoDefaultBranch) {
6201
+ const spawnResult = childProcess.spawnSync('git', ['branch', '--show-current']);
6202
+ const currentBranch = spawnResult.stdout.toString('utf8').trim();
6203
+ if (spawnResult.status === 0 && currentBranch) {
6204
+ const proceed = await prompts.select({
6205
+ message: 'Use the current git branch as target branch name?',
6206
+ choices: [{
6207
+ name: `Yes [${currentBranch}]`,
6208
+ value: currentBranch,
6209
+ description: 'Use the current git branch for branch name'
6210
+ }, ...(repoDefaultBranch && repoDefaultBranch !== currentBranch ? [{
6211
+ name: `No, use the default branch [${repoDefaultBranch}]`,
6212
+ value: repoDefaultBranch,
6213
+ description: 'Use the default branch for target repo as the target branch name'
6214
+ }] : []), {
6215
+ name: 'No',
6216
+ value: '',
6217
+ description: 'Do not use the current git branch as name (will end in a no-op)'
6218
+ }].filter(Boolean)
6219
+ });
6220
+ if (proceed) {
6221
+ return proceed;
6222
+ }
6223
+ }
6224
+ }
6225
+
6226
+ async function suggestTarget() {
6227
+ // We could prefill this with sub-dirs of the current
6228
+ // dir ... but is that going to be useful?
6229
+ const proceed = await prompts.select({
6230
+ message: 'No TARGET given. Do you want to use the current directory?',
6231
+ choices: [{
6232
+ name: 'Yes',
6233
+ value: true,
6234
+ description: 'Target the current directory'
6235
+ }, {
6236
+ name: 'No',
6237
+ value: false,
6238
+ description: 'Do not use the current directory (this will end in a no-op)'
6239
+ }]
6240
+ });
6241
+ if (proceed) {
6242
+ return ['.'];
6243
+ }
6244
+ }
6245
+
6087
6246
  async function createFullScan({
6088
- apiToken,
6089
6247
  branchName,
6090
6248
  commitHash: _commitHash,
6091
6249
  commitMessage,
@@ -6093,17 +6251,100 @@ async function createFullScan({
6093
6251
  cwd,
6094
6252
  defaultBranch,
6095
6253
  orgSlug,
6096
- packagePaths,
6097
6254
  pendingHead,
6098
6255
  pullRequest: _pullRequest,
6256
+ readOnly,
6099
6257
  repoName,
6258
+ targets,
6100
6259
  tmp
6101
6260
  }) {
6261
+ const socketSdk = await index.setupSdk();
6262
+ const supportedFiles = await socketSdk.getReportSupportedFiles().then(res => {
6263
+ if (!res.success) {
6264
+ handleUnsuccessfulApiResponse('getReportSupportedFiles', res, new spinner.Spinner());
6265
+ assert(false, 'handleUnsuccessfulApiResponse should unconditionally throw');
6266
+ }
6267
+ return res.data;
6268
+ }).catch(cause => {
6269
+ throw new Error('Failed getting supported files for report', {
6270
+ cause
6271
+ });
6272
+ });
6273
+
6274
+ // If we updated any inputs then we should print the command line to repeat
6275
+ // the command without requiring user input, as a suggestion.
6276
+ let updatedInput = false;
6277
+ if (!targets.length) {
6278
+ const received = await suggestTarget();
6279
+ targets = received ?? [];
6280
+ updatedInput = true;
6281
+ }
6282
+ const packagePaths = await npmPaths.getPackageFilesFullScans(cwd, targets, supportedFiles);
6283
+
6284
+ // We're going to need an api token to suggest data because those suggestions
6285
+ // must come from data we already know. Don't error on missing api token yet.
6286
+ // If the api-token is not set, ignore it for the sake of suggestions.
6287
+ const apiToken = index.getDefaultToken();
6288
+ if (apiToken && !orgSlug) {
6289
+ const suggestion = await suggestOrgSlug(socketSdk);
6290
+ if (suggestion) orgSlug = suggestion;
6291
+ updatedInput = true;
6292
+ }
6293
+
6294
+ // If the current cwd is unknown and is used as a repo slug anyways, we will
6295
+ // first need to register the slug before we can use it.
6296
+ let repoDefaultBranch = '';
6297
+
6298
+ // (Don't bother asking for the rest if we didn't get an org slug above)
6299
+ if (apiToken && orgSlug && !repoName) {
6300
+ const suggestion = await suggestRepoSlug(socketSdk, orgSlug);
6301
+ if (suggestion) {
6302
+ ({
6303
+ defaultBranch: repoDefaultBranch,
6304
+ slug: repoName
6305
+ } = suggestion);
6306
+ }
6307
+ updatedInput = true;
6308
+ }
6309
+
6310
+ // (Don't bother asking for the rest if we didn't get an org/repo above)
6311
+ if (apiToken && orgSlug && repoName && !branchName) {
6312
+ const suggestion = await suggestBranchSlug(repoDefaultBranch);
6313
+ if (suggestion) branchName = suggestion;
6314
+ updatedInput = true;
6315
+ }
6316
+ if (!orgSlug || !repoName || !branchName || !packagePaths.length) {
6317
+ // Use exit status of 2 to indicate incorrect usage, generally invalid
6318
+ // options or missing arguments.
6319
+ // https://www.gnu.org/software/bash/manual/html_node/Exit-Status.html
6320
+ process$1.exitCode = 2;
6321
+ console.error(`
6322
+ ${colors.bgRed(colors.white('Input error'))}: Please provide the required fields:\n
6323
+ - Org name as the first argument ${!orgSlug ? colors.red('(missing!)') : colors.green('(ok)')}\n
6324
+ - Repository name using --repo ${!repoName ? colors.red('(missing!)') : colors.green('(ok)')}\n
6325
+ - Branch name using --branch ${!branchName ? colors.red('(missing!)') : colors.green('(ok)')}\n
6326
+ - 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
6327
+ ${!apiToken ? 'Note: was unable to make suggestions because no API Token was found; this would make command fail regardless\n' : ''}
6328
+ `);
6329
+ return;
6330
+ }
6331
+ if (updatedInput) {
6332
+ console.log('Note: You can invoke this command next time to skip the interactive questions:');
6333
+ console.log('```');
6334
+ console.log(` socket scan create [other flags...] --repo ${repoName} --branch ${branchName} ${orgSlug} ${targets.join(' ')}`);
6335
+ console.log('```');
6336
+ }
6337
+ if (!apiToken) {
6338
+ 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.');
6339
+ }
6340
+ if (readOnly) {
6341
+ console.log('[ReadOnly] Bailing now');
6342
+ return;
6343
+ }
6102
6344
  const spinnerText = 'Creating a scan... \n';
6103
6345
  const spinner$1 = new spinner.Spinner({
6104
6346
  text: spinnerText
6105
6347
  }).start();
6106
- const socketSdk = await index.setupSdk(apiToken);
6107
6348
  const result = await handleApiCall(socketSdk.createOrgFullScan(orgSlug, {
6108
6349
  repo: repoName,
6109
6350
  branch: branchName,
@@ -6116,7 +6357,7 @@ async function createFullScan({
6116
6357
  handleUnsuccessfulApiResponse('CreateOrgFullScan', result, spinner$1);
6117
6358
  return;
6118
6359
  }
6119
- spinner$1.success('Scan created successfully');
6360
+ spinner$1.successAndStop('Scan created successfully');
6120
6361
  const link = colors.underline(colors.cyan(`${result.data.html_report_url}`));
6121
6362
  console.log(`Available at: ${link}`);
6122
6363
  const rl = readline.createInterface({
@@ -6190,6 +6431,11 @@ const config$6 = {
6190
6431
  default: false,
6191
6432
  description: 'Set as pending head'
6192
6433
  },
6434
+ readOnly: {
6435
+ type: 'boolean',
6436
+ default: false,
6437
+ description: 'Similar to --dry-run except it can read from remote, stops before it would create an actual report'
6438
+ },
6193
6439
  tmp: {
6194
6440
  type: 'boolean',
6195
6441
  shortFlag: 't',
@@ -6229,56 +6475,47 @@ async function run$6(argv, importMeta, {
6229
6475
  });
6230
6476
  const [orgSlug = '', ...targets] = cli.input;
6231
6477
  const cwd = cli.flags['cwd'] && cli.flags['cwd'] !== 'process.cwd()' ? String(cli.flags['cwd']) : process$1.cwd();
6232
-
6233
- // Note exiting earlier to skirt a hidden auth requirement
6234
- if (cli.flags['dryRun']) {
6235
- return console.log('[DryRun] Bailing now');
6236
- }
6237
- const socketSdk = await index.setupSdk();
6238
- const supportedFiles = await socketSdk.getReportSupportedFiles().then(res => {
6239
- if (!res.success) handleUnsuccessfulApiResponse('getReportSupportedFiles', res, new spinner.Spinner());
6240
- // TODO: verify type at runtime? Consider it trusted data and assume type?
6241
- return res.data;
6242
- }).catch(cause => {
6243
- throw new Error('Failed getting supported files for report', {
6244
- cause
6245
- });
6246
- });
6247
- const packagePaths = await npmPaths.getPackageFilesFullScans(cwd, targets, supportedFiles);
6248
- const {
6478
+ let {
6249
6479
  branch: branchName,
6250
6480
  repo: repoName
6251
6481
  } = cli.flags;
6252
- if (!orgSlug || !repoName || !branchName || !packagePaths.length) {
6482
+ const apiToken = index.getDefaultToken();
6483
+ if (!apiToken && (!orgSlug || !repoName || !branchName || !targets.length)) {
6484
+ // Without api token we cannot recover because we can't request more info
6485
+ // from the server, to match and help with the current cwd/git status.
6253
6486
  // Use exit status of 2 to indicate incorrect usage, generally invalid
6254
6487
  // options or missing arguments.
6255
6488
  // https://www.gnu.org/software/bash/manual/html_node/Exit-Status.html
6256
6489
  process$1.exitCode = 2;
6257
- console.error(`${colors.bgRed(colors.white('Input error'))}: Please provide the required fields:\n
6258
- - Org name as the first argument ${!orgSlug ? colors.red('(missing!)') : colors.green('(ok)')}\n
6259
- - Repository name using --repo ${!repoName ? colors.red('(missing!)') : colors.green('(ok)')}\n
6260
- - Branch name using --branch ${!branchName ? colors.red('(missing!)') : colors.green('(ok)')}\n
6261
- - 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`);
6490
+ console.error(`
6491
+ ${colors.bgRed(colors.white('Input error'))}: Please provide the required fields:\n
6492
+ - Org name as the first argument ${!orgSlug ? colors.red('(missing!)') : colors.green('(ok)')}\n
6493
+ - Repository name using --repo ${!repoName ? colors.red('(missing!)') : colors.green('(ok)')}\n
6494
+ - Branch name using --branch ${!branchName ? colors.red('(missing!)') : colors.green('(ok)')}\n
6495
+ - At least one TARGET (e.g. \`.\` or \`./package.json\`) ${!targets.length ? '(missing)' : colors.green('(ok)')}\n
6496
+ (Additionally, no API Token was set so we cannot auto-discover these details)\n
6497
+ `);
6262
6498
  return;
6263
6499
  }
6264
- const apiToken = index.getDefaultToken();
6265
- if (!apiToken) {
6266
- 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.');
6500
+
6501
+ // Note exiting earlier to skirt a hidden auth requirement
6502
+ if (cli.flags['dryRun']) {
6503
+ return console.log('[DryRun] Bailing now');
6267
6504
  }
6268
6505
  await createFullScan({
6269
- apiToken,
6270
- orgSlug,
6271
- repoName: repoName,
6272
6506
  branchName: branchName,
6507
+ commitHash: cli.flags['commitHash'] ?? '',
6273
6508
  commitMessage: cli.flags['commitMessage'] ?? '',
6509
+ committers: cli.flags['committers'] ?? '',
6510
+ cwd,
6274
6511
  defaultBranch: Boolean(cli.flags['defaultBranch']),
6512
+ orgSlug,
6275
6513
  pendingHead: Boolean(cli.flags['pendingHead']),
6276
- tmp: Boolean(cli.flags['tmp']),
6277
- packagePaths,
6278
- cwd,
6279
- commitHash: cli.flags['commitHash'] ?? '',
6280
- committers: cli.flags['committers'] ?? '',
6281
- pullRequest: cli.flags['pullRequest'] ?? undefined
6514
+ pullRequest: cli.flags['pullRequest'] ?? undefined,
6515
+ readOnly: Boolean(cli.flags['readOnly']),
6516
+ repoName: repoName,
6517
+ targets,
6518
+ tmp: Boolean(cli.flags['tmp'])
6282
6519
  });
6283
6520
  }
6284
6521
 
@@ -6290,7 +6527,7 @@ async function deleteOrgFullScan(orgSlug, fullScanId, apiToken) {
6290
6527
  const socketSdk = await index.setupSdk(apiToken);
6291
6528
  const result = await handleApiCall(socketSdk.deleteOrgFullScan(orgSlug, fullScanId), 'Deleting scan');
6292
6529
  if (result.success) {
6293
- spinner$1.success('Scan deleted successfully');
6530
+ spinner$1.successAndStop('Scan deleted successfully');
6294
6531
  } else {
6295
6532
  handleUnsuccessfulApiResponse('deleteOrgFullScan', result, spinner$1);
6296
6533
  }
@@ -7071,5 +7308,5 @@ void (async () => {
7071
7308
  await index.captureException(e);
7072
7309
  }
7073
7310
  })();
7074
- //# debugId=71018fb6-02eb-4cf4-8a1e-dce142ed200
7311
+ //# debugId=76095f49-6cee-41ed-8752-1e7608d29b7d
7075
7312
  //# sourceMappingURL=cli.js.map