@socketsecurity/cli-with-sentry 0.15.53 → 0.15.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.
Files changed (31) hide show
  1. package/dist/cli.js +561 -314
  2. package/dist/cli.js.map +1 -1
  3. package/dist/constants.js +15 -3
  4. package/dist/constants.js.map +1 -1
  5. package/dist/types/commands/fix/npm-fix.d.mts.map +1 -1
  6. package/dist/types/commands/json/cmd-json.d.mts +10 -0
  7. package/dist/types/commands/json/cmd-json.d.mts.map +1 -0
  8. package/dist/types/commands/json/handle-cmd-json.d.mts +2 -0
  9. package/dist/types/commands/json/handle-cmd-json.d.mts.map +1 -0
  10. package/dist/types/commands/json/output-cmd-json.d.mts +2 -0
  11. package/dist/types/commands/json/output-cmd-json.d.mts.map +1 -0
  12. package/dist/types/commands/oops/cmd-oops.d.mts.map +1 -1
  13. package/dist/types/commands/optimize/lockfile-includes-by-agent.d.mts.map +1 -1
  14. package/dist/types/commands/package/output-purls-deep-score.d.mts +5 -0
  15. package/dist/types/commands/package/output-purls-deep-score.d.mts.map +1 -0
  16. package/dist/types/commands/package/output-purls-shallow-score.d.mts +25 -0
  17. package/dist/types/commands/package/output-purls-shallow-score.d.mts.map +1 -1
  18. package/dist/types/commands/scan/cmd-scan-reach.d.mts.map +1 -1
  19. package/dist/types/commands/scan/scan-reachability.d.mts.map +1 -1
  20. package/dist/types/constants.d.mts +3 -0
  21. package/dist/types/constants.d.mts.map +1 -1
  22. package/dist/types/utils/meow-with-subcommands.d.mts.map +1 -1
  23. package/dist/types/utils/tildify.d.mts +4 -0
  24. package/dist/types/utils/tildify.d.mts.map +1 -0
  25. package/dist/utils.js +63 -36
  26. package/dist/utils.js.map +1 -1
  27. package/dist/vendor.js +31637 -31637
  28. package/external/@coana-tech/cli/cli.mjs +216492 -0
  29. package/package.json +7 -7
  30. package/dist/types/commands/package/output-purl-score.d.mts +0 -4
  31. package/dist/types/commands/package/output-purl-score.d.mts.map +0 -1
package/dist/cli.js CHANGED
@@ -305,7 +305,7 @@ async function handleAnalytics({
305
305
  const {
306
306
  DRY_RUN_BAILING_NOW: DRY_RUN_BAILING_NOW$O
307
307
  } = constants;
308
- const config$T = {
308
+ const config$U = {
309
309
  commandName: 'analytics',
310
310
  description: `Look up analytics data`,
311
311
  hidden: false,
@@ -367,16 +367,16 @@ const config$T = {
367
367
  .replace(/\n(?: *\n)+/g, '\n\n')
368
368
  };
369
369
  const cmdAnalytics = {
370
- description: config$T.description,
371
- hidden: config$T.hidden,
372
- run: run$T
370
+ description: config$U.description,
371
+ hidden: config$U.hidden,
372
+ run: run$U
373
373
  };
374
- async function run$T(argv, importMeta, {
374
+ async function run$U(argv, importMeta, {
375
375
  parentName
376
376
  }) {
377
377
  const cli = utils.meowOrExit({
378
378
  argv,
379
- config: config$T,
379
+ config: config$U,
380
380
  importMeta,
381
381
  parentName
382
382
  });
@@ -663,7 +663,7 @@ const {
663
663
  DRY_RUN_BAILING_NOW: DRY_RUN_BAILING_NOW$N,
664
664
  SOCKET_WEBSITE_URL: SOCKET_WEBSITE_URL$3
665
665
  } = constants;
666
- const config$S = {
666
+ const config$T = {
667
667
  commandName: 'audit-log',
668
668
  description: 'Look up the audit log for an organization',
669
669
  hidden: false,
@@ -717,16 +717,16 @@ const config$S = {
717
717
  `
718
718
  };
719
719
  const cmdAuditLog = {
720
- description: config$S.description,
721
- hidden: config$S.hidden,
722
- run: run$S
720
+ description: config$T.description,
721
+ hidden: config$T.hidden,
722
+ run: run$T
723
723
  };
724
- async function run$S(argv, importMeta, {
724
+ async function run$T(argv, importMeta, {
725
725
  parentName
726
726
  }) {
727
727
  const cli = utils.meowOrExit({
728
728
  argv,
729
- config: config$S,
729
+ config: config$T,
730
730
  importMeta,
731
731
  parentName
732
732
  });
@@ -1059,7 +1059,7 @@ const yargsConfig = {
1059
1059
  'usages-slices-file' // hidden
1060
1060
  ]
1061
1061
  };
1062
- const config$R = {
1062
+ const config$S = {
1063
1063
  commandName: 'cdxgen',
1064
1064
  description: 'Create an SBOM with CycloneDX generator (cdxgen)',
1065
1065
  hidden: false,
@@ -1069,17 +1069,17 @@ const config$R = {
1069
1069
  help: () => ''
1070
1070
  };
1071
1071
  const cmdManifestCdxgen = {
1072
- description: config$R.description,
1073
- hidden: config$R.hidden,
1074
- run: run$R
1072
+ description: config$S.description,
1073
+ hidden: config$S.hidden,
1074
+ run: run$S
1075
1075
  };
1076
- async function run$R(argv, importMeta, {
1076
+ async function run$S(argv, importMeta, {
1077
1077
  parentName
1078
1078
  }) {
1079
1079
  const cli = utils.meowOrExit({
1080
1080
  // Don't let meow take over --help.
1081
1081
  argv: argv.filter(a => !utils.isHelpFlag(a)),
1082
- config: config$R,
1082
+ config: config$S,
1083
1083
  importMeta,
1084
1084
  parentName
1085
1085
  });
@@ -1130,15 +1130,15 @@ async function handleCdxgen(argv, importMeta, {
1130
1130
  });
1131
1131
  }
1132
1132
 
1133
- const config$Q = {
1133
+ const config$R = {
1134
1134
  description: 'Create an SBOM with CycloneDX generator (cdxgen)',
1135
1135
  hidden: true};
1136
1136
  const cmdCdxgen = {
1137
- description: config$Q.description,
1138
- hidden: config$Q.hidden,
1139
- run: run$Q
1137
+ description: config$R.description,
1138
+ hidden: config$R.hidden,
1139
+ run: run$R
1140
1140
  };
1141
- async function run$Q(argv, importMeta, {
1141
+ async function run$R(argv, importMeta, {
1142
1142
  parentName
1143
1143
  }) {
1144
1144
  logger.logger.warn('Warning: The `socket cdxgen` command moved to `socket manifest cdxgen` and will be removed as a toplevel command in the next major bump.');
@@ -2373,7 +2373,7 @@ async function handleCI(autoManifest) {
2373
2373
  const {
2374
2374
  DRY_RUN_BAILING_NOW: DRY_RUN_BAILING_NOW$L
2375
2375
  } = constants;
2376
- const config$P = {
2376
+ const config$Q = {
2377
2377
  commandName: 'ci',
2378
2378
  description: 'Create a new scan and report whether it passes your security policy',
2379
2379
  hidden: true,
@@ -2391,7 +2391,7 @@ const config$P = {
2391
2391
  $ ${parentName}
2392
2392
 
2393
2393
  Options
2394
- ${utils.getFlagListOutput(config$P.flags, 6)}
2394
+ ${utils.getFlagListOutput(config$Q.flags, 6)}
2395
2395
 
2396
2396
  This command is intended to use in CI runs to allow automated systems to
2397
2397
  accept or reject a current build. When the scan does not pass your security
@@ -2406,16 +2406,16 @@ const config$P = {
2406
2406
  `
2407
2407
  };
2408
2408
  const cmdCI = {
2409
- description: config$P.description,
2410
- hidden: config$P.hidden,
2411
- run: run$P
2409
+ description: config$Q.description,
2410
+ hidden: config$Q.hidden,
2411
+ run: run$Q
2412
2412
  };
2413
- async function run$P(argv, importMeta, {
2413
+ async function run$Q(argv, importMeta, {
2414
2414
  parentName
2415
2415
  }) {
2416
2416
  const cli = utils.meowOrExit({
2417
2417
  argv,
2418
- config: config$P,
2418
+ config: config$Q,
2419
2419
  importMeta,
2420
2420
  parentName
2421
2421
  });
@@ -2666,7 +2666,7 @@ async function handleConfigAuto({
2666
2666
  const {
2667
2667
  DRY_RUN_BAILING_NOW: DRY_RUN_BAILING_NOW$K
2668
2668
  } = constants;
2669
- const config$O = {
2669
+ const config$P = {
2670
2670
  commandName: 'auto',
2671
2671
  description: 'Automatically discover and set the correct value config item',
2672
2672
  hidden: false,
@@ -2695,16 +2695,16 @@ ${Array.from(utils.supportedConfigKeys.entries()).map(([key, desc]) => ` - $
2695
2695
  `
2696
2696
  };
2697
2697
  const cmdConfigAuto = {
2698
- description: config$O.description,
2699
- hidden: config$O.hidden,
2700
- run: run$O
2698
+ description: config$P.description,
2699
+ hidden: config$P.hidden,
2700
+ run: run$P
2701
2701
  };
2702
- async function run$O(argv, importMeta, {
2702
+ async function run$P(argv, importMeta, {
2703
2703
  parentName
2704
2704
  }) {
2705
2705
  const cli = utils.meowOrExit({
2706
2706
  argv,
2707
- config: config$O,
2707
+ config: config$P,
2708
2708
  importMeta,
2709
2709
  parentName
2710
2710
  });
@@ -2780,7 +2780,7 @@ async function handleConfigGet({
2780
2780
  const {
2781
2781
  DRY_RUN_BAILING_NOW: DRY_RUN_BAILING_NOW$J
2782
2782
  } = constants;
2783
- const config$N = {
2783
+ const config$O = {
2784
2784
  commandName: 'get',
2785
2785
  description: 'Get the value of a local CLI config item',
2786
2786
  hidden: false,
@@ -2804,16 +2804,16 @@ ${Array.from(utils.supportedConfigKeys.entries()).map(([key, desc]) => ` - $
2804
2804
  `
2805
2805
  };
2806
2806
  const cmdConfigGet = {
2807
- description: config$N.description,
2808
- hidden: config$N.hidden,
2809
- run: run$N
2807
+ description: config$O.description,
2808
+ hidden: config$O.hidden,
2809
+ run: run$O
2810
2810
  };
2811
- async function run$N(argv, importMeta, {
2811
+ async function run$O(argv, importMeta, {
2812
2812
  parentName
2813
2813
  }) {
2814
2814
  const cli = utils.meowOrExit({
2815
2815
  argv,
2816
- config: config$N,
2816
+ config: config$O,
2817
2817
  importMeta,
2818
2818
  parentName
2819
2819
  });
@@ -2918,7 +2918,7 @@ async function outputConfigList({
2918
2918
  const {
2919
2919
  DRY_RUN_BAILING_NOW: DRY_RUN_BAILING_NOW$I
2920
2920
  } = constants;
2921
- const config$M = {
2921
+ const config$N = {
2922
2922
  commandName: 'list',
2923
2923
  description: 'Show all local CLI config items and their values',
2924
2924
  hidden: false,
@@ -2947,16 +2947,16 @@ ${Array.from(utils.supportedConfigKeys.entries()).map(([key, desc]) => ` - $
2947
2947
  `
2948
2948
  };
2949
2949
  const cmdConfigList = {
2950
- description: config$M.description,
2951
- hidden: config$M.hidden,
2952
- run: run$M
2950
+ description: config$N.description,
2951
+ hidden: config$N.hidden,
2952
+ run: run$N
2953
2953
  };
2954
- async function run$M(argv, importMeta, {
2954
+ async function run$N(argv, importMeta, {
2955
2955
  parentName
2956
2956
  }) {
2957
2957
  const cli = utils.meowOrExit({
2958
2958
  argv,
2959
- config: config$M,
2959
+ config: config$N,
2960
2960
  importMeta,
2961
2961
  parentName
2962
2962
  });
@@ -3028,7 +3028,7 @@ async function handleConfigSet({
3028
3028
  const {
3029
3029
  DRY_RUN_BAILING_NOW: DRY_RUN_BAILING_NOW$H
3030
3030
  } = constants;
3031
- const config$L = {
3031
+ const config$M = {
3032
3032
  commandName: 'set',
3033
3033
  description: 'Update the value of a local CLI config item',
3034
3034
  hidden: false,
@@ -3057,16 +3057,16 @@ ${Array.from(utils.supportedConfigKeys.entries()).map(([key, desc]) => ` - $
3057
3057
  `
3058
3058
  };
3059
3059
  const cmdConfigSet = {
3060
- description: config$L.description,
3061
- hidden: config$L.hidden,
3062
- run: run$L
3060
+ description: config$M.description,
3061
+ hidden: config$M.hidden,
3062
+ run: run$M
3063
3063
  };
3064
- async function run$L(argv, importMeta, {
3064
+ async function run$M(argv, importMeta, {
3065
3065
  parentName
3066
3066
  }) {
3067
3067
  const cli = utils.meowOrExit({
3068
3068
  argv,
3069
- config: config$L,
3069
+ config: config$M,
3070
3070
  importMeta,
3071
3071
  parentName
3072
3072
  });
@@ -3150,7 +3150,7 @@ async function handleConfigUnset({
3150
3150
  const {
3151
3151
  DRY_RUN_BAILING_NOW: DRY_RUN_BAILING_NOW$G
3152
3152
  } = constants;
3153
- const config$K = {
3153
+ const config$L = {
3154
3154
  commandName: 'unset',
3155
3155
  description: 'Clear the value of a local CLI config item',
3156
3156
  hidden: false,
@@ -3174,16 +3174,16 @@ ${Array.from(utils.supportedConfigKeys.entries()).map(([key, desc]) => ` - $
3174
3174
  `
3175
3175
  };
3176
3176
  const cmdConfigUnset = {
3177
- description: config$K.description,
3178
- hidden: config$K.hidden,
3179
- run: run$K
3177
+ description: config$L.description,
3178
+ hidden: config$L.hidden,
3179
+ run: run$L
3180
3180
  };
3181
- async function run$K(argv, importMeta, {
3181
+ async function run$L(argv, importMeta, {
3182
3182
  parentName
3183
3183
  }) {
3184
3184
  const cli = utils.meowOrExit({
3185
3185
  argv,
3186
- config: config$K,
3186
+ config: config$L,
3187
3187
  importMeta,
3188
3188
  parentName
3189
3189
  });
@@ -3320,7 +3320,7 @@ async function handleDependencies({
3320
3320
  const {
3321
3321
  DRY_RUN_BAILING_NOW: DRY_RUN_BAILING_NOW$F
3322
3322
  } = constants;
3323
- const config$J = {
3323
+ const config$K = {
3324
3324
  commandName: 'dependencies',
3325
3325
  description: 'Search for any dependency that is being used in your organization',
3326
3326
  hidden: false,
@@ -3356,16 +3356,16 @@ const config$J = {
3356
3356
  `
3357
3357
  };
3358
3358
  const cmdScanCreate$1 = {
3359
- description: config$J.description,
3360
- hidden: config$J.hidden,
3361
- run: run$J
3359
+ description: config$K.description,
3360
+ hidden: config$K.hidden,
3361
+ run: run$K
3362
3362
  };
3363
- async function run$J(argv, importMeta, {
3363
+ async function run$K(argv, importMeta, {
3364
3364
  parentName
3365
3365
  }) {
3366
3366
  const cli = utils.meowOrExit({
3367
3367
  argv,
3368
- config: config$J,
3368
+ config: config$K,
3369
3369
  importMeta,
3370
3370
  parentName
3371
3371
  });
@@ -3493,7 +3493,7 @@ async function handleDiffScan$1({
3493
3493
  const {
3494
3494
  DRY_RUN_BAILING_NOW: DRY_RUN_BAILING_NOW$E
3495
3495
  } = constants;
3496
- const config$I = {
3496
+ const config$J = {
3497
3497
  commandName: 'get',
3498
3498
  description: 'Get a diff scan for an organization',
3499
3499
  hidden: false,
@@ -3552,16 +3552,16 @@ const config$I = {
3552
3552
  `
3553
3553
  };
3554
3554
  const cmdDiffScanGet = {
3555
- description: config$I.description,
3556
- hidden: config$I.hidden,
3557
- run: run$I
3555
+ description: config$J.description,
3556
+ hidden: config$J.hidden,
3557
+ run: run$J
3558
3558
  };
3559
- async function run$I(argv, importMeta, {
3559
+ async function run$J(argv, importMeta, {
3560
3560
  parentName
3561
3561
  }) {
3562
3562
  const cli = utils.meowOrExit({
3563
3563
  argv,
3564
- config: config$I,
3564
+ config: config$J,
3565
3565
  importMeta,
3566
3566
  parentName
3567
3567
  });
@@ -4316,10 +4316,7 @@ async function npmFix(pkgEnvDetails, {
4316
4316
  isCi && repoInfo ? await getOpenSocketPrs(repoInfo.owner, repoInfo.repo, {
4317
4317
  author: gitUser
4318
4318
  }) : [];
4319
- if (openPrs.length) {
4320
- debug.debugFn(`found: ${openPrs.length} open PRs`);
4321
- }
4322
- let count = isCi ? openPrs.length : 0;
4319
+ let count = 0;
4323
4320
  const arb = new shadowInject.Arborist({
4324
4321
  path: rootPath,
4325
4322
  ...shadowInject.SAFE_ARBORIST_REIFY_OPTIONS_OVERRIDES
@@ -4330,9 +4327,9 @@ async function npmFix(pkgEnvDetails, {
4330
4327
  let alertsMap;
4331
4328
  try {
4332
4329
  alertsMap = purls.length ? await utils.getAlertsMapFromPurls(purls, getAlertsMapOptions({
4333
- limit: limit + openPrs.length
4330
+ limit: Math.max(limit, openPrs.length)
4334
4331
  })) : await shadowInject.getAlertsMapFromArborist(arb, getAlertsMapOptions({
4335
- limit: limit + openPrs.length
4332
+ limit: Math.max(limit, openPrs.length)
4336
4333
  }));
4337
4334
  } catch (e) {
4338
4335
  spinner?.stop();
@@ -4344,7 +4341,7 @@ async function npmFix(pkgEnvDetails, {
4344
4341
  };
4345
4342
  }
4346
4343
  const infoByPartialPurl = utils.getCveInfoFromAlertsMap(alertsMap, {
4347
- limit: limit + openPrs.length
4344
+ limit: Math.max(limit, openPrs.length)
4348
4345
  });
4349
4346
  if (!infoByPartialPurl) {
4350
4347
  spinner?.stop();
@@ -4381,11 +4378,14 @@ async function npmFix(pkgEnvDetails, {
4381
4378
  const infoEntry = sortedInfoEntries[i];
4382
4379
  const partialPurlObj = utils.getPurlObject(infoEntry[0]);
4383
4380
  const name = packages.resolvePackageName(partialPurlObj);
4384
- let infos = [...infoEntry[1].values()];
4381
+ const infos = [...infoEntry[1].values()];
4382
+ if (!infos.length) {
4383
+ continue infoEntriesLoop;
4384
+ }
4385
+ const activeBranches = [];
4385
4386
  if (isCi) {
4386
4387
  const branchFullName = getSocketBranchFullNameComponent(partialPurlObj);
4387
4388
  const branchPurlType = getSocketBranchPurlTypeComponent(partialPurlObj);
4388
- const activeBranches = [];
4389
4389
  for (const pr of openPrs) {
4390
4390
  const parsedBranch = branchParser(pr.headRefName);
4391
4391
  if (branchPurlType === parsedBranch?.type && branchFullName === parsedBranch?.fullName) {
@@ -4397,10 +4397,6 @@ async function npmFix(pkgEnvDetails, {
4397
4397
  } else if (openPrs.length) {
4398
4398
  debug.debugFn('miss: 0 active branches found');
4399
4399
  }
4400
- infos = infos.filter(info => !activeBranches.find(b => b.newVersion === info.firstPatchedVersionIdentifier));
4401
- }
4402
- if (!infos.length) {
4403
- continue infoEntriesLoop;
4404
4400
  }
4405
4401
  logger.logger.log(`Processing vulns for ${name}:`);
4406
4402
  logger.logger.indent();
@@ -4428,6 +4424,7 @@ async function npmFix(pkgEnvDetails, {
4428
4424
  const pkgPath = path.dirname(pkgJsonPath);
4429
4425
  const isWorkspaceRoot = pkgJsonPath === pkgEnvDetails.editablePkgJson.filename;
4430
4426
  const workspace = isWorkspaceRoot ? 'root' : path.relative(rootPath, pkgPath);
4427
+ const branchWorkspace = isCi ? getSocketBranchWorkspaceComponent(workspace) : '';
4431
4428
  const oldVersions = arrays.arrayUnique(shadowInject.findPackageNodes(actualTree, name).map(n => n.target?.version ?? n.version).filter(Boolean));
4432
4429
  if (!oldVersions.length) {
4433
4430
  debug.debugFn(`skip: ${name} not found\n`);
@@ -4467,6 +4464,15 @@ async function npmFix(pkgEnvDetails, {
4467
4464
  continue infosLoop;
4468
4465
  }
4469
4466
  const newVersion = shadowInject.findBestPatchVersion(node, availableVersions, vulnerableVersionRange);
4467
+ if (activeBranches.find(b => b.workspace === branchWorkspace && b.newVersion === newVersion)) {
4468
+ debug.debugFn(`skip: open PR found for ${name}@${newVersion}`);
4469
+ if (++count >= limit) {
4470
+ logger.logger.dedent();
4471
+ spinner?.dedent();
4472
+ break infoEntriesLoop;
4473
+ }
4474
+ continue infosLoop;
4475
+ }
4470
4476
  const newVersionPackument = newVersion ? packument.versions[newVersion] : undefined;
4471
4477
  if (!(newVersion && newVersionPackument)) {
4472
4478
  warningsForAfter.add(`${oldId} not updated: requires >=${firstPatchedVersionIdentifier}`);
@@ -5379,7 +5385,7 @@ async function handleFix({
5379
5385
  const {
5380
5386
  DRY_RUN_NOT_SAVING
5381
5387
  } = constants;
5382
- const config$H = {
5388
+ const config$I = {
5383
5389
  commandName: 'fix',
5384
5390
  description: 'Update dependencies with "fixable" Socket alerts',
5385
5391
  hidden: false,
@@ -5447,16 +5453,16 @@ const config$H = {
5447
5453
  `
5448
5454
  };
5449
5455
  const cmdFix = {
5450
- description: config$H.description,
5451
- hidden: config$H.hidden,
5452
- run: run$H
5456
+ description: config$I.description,
5457
+ hidden: config$I.hidden,
5458
+ run: run$I
5453
5459
  };
5454
- async function run$H(argv, importMeta, {
5460
+ async function run$I(argv, importMeta, {
5455
5461
  parentName
5456
5462
  }) {
5457
5463
  const cli = utils.meowOrExit({
5458
5464
  argv,
5459
- config: config$H,
5465
+ config: config$I,
5460
5466
  importMeta,
5461
5467
  parentName
5462
5468
  });
@@ -5660,7 +5666,7 @@ async function handlePackageInfo({
5660
5666
  const {
5661
5667
  DRY_RUN_BAILING_NOW: DRY_RUN_BAILING_NOW$D
5662
5668
  } = constants;
5663
- const config$G = {
5669
+ const config$H = {
5664
5670
  commandName: 'info',
5665
5671
  description: 'Look up info regarding a package',
5666
5672
  hidden: true,
@@ -5685,16 +5691,16 @@ const config$G = {
5685
5691
  `
5686
5692
  };
5687
5693
  const cmdInfo = {
5688
- description: config$G.description,
5689
- hidden: config$G.hidden,
5690
- run: run$G
5694
+ description: config$H.description,
5695
+ hidden: config$H.hidden,
5696
+ run: run$H
5691
5697
  };
5692
- async function run$G(argv, importMeta, {
5698
+ async function run$H(argv, importMeta, {
5693
5699
  parentName
5694
5700
  }) {
5695
5701
  const cli = utils.meowOrExit({
5696
5702
  argv,
5697
- config: config$G,
5703
+ config: config$H,
5698
5704
  importMeta,
5699
5705
  parentName
5700
5706
  });
@@ -5735,7 +5741,7 @@ async function run$G(argv, importMeta, {
5735
5741
  return;
5736
5742
  }
5737
5743
  await handlePackageInfo({
5738
- commandName: `${parentName} ${config$G.commandName}`,
5744
+ commandName: `${parentName} ${config$H.commandName}`,
5739
5745
  includeAllIssues: Boolean(all),
5740
5746
  outputKind,
5741
5747
  pkgName,
@@ -5865,7 +5871,7 @@ async function handleInstallCompletion(targetName) {
5865
5871
  const {
5866
5872
  DRY_RUN_BAILING_NOW: DRY_RUN_BAILING_NOW$C
5867
5873
  } = constants;
5868
- const config$F = {
5874
+ const config$G = {
5869
5875
  commandName: 'completion',
5870
5876
  description: 'Install bash completion for Socket CLI',
5871
5877
  hidden: true,
@@ -5903,16 +5909,16 @@ const config$F = {
5903
5909
  `
5904
5910
  };
5905
5911
  const cmdInstallCompletion = {
5906
- description: config$F.description,
5907
- hidden: config$F.hidden,
5908
- run: run$F
5912
+ description: config$G.description,
5913
+ hidden: config$G.hidden,
5914
+ run: run$G
5909
5915
  };
5910
- async function run$F(argv, importMeta, {
5916
+ async function run$G(argv, importMeta, {
5911
5917
  parentName
5912
5918
  }) {
5913
5919
  const cli = utils.meowOrExit({
5914
5920
  argv,
5915
- config: config$F,
5921
+ config: config$G,
5916
5922
  importMeta,
5917
5923
  parentName
5918
5924
  });
@@ -5943,6 +5949,67 @@ const cmdInstall = {
5943
5949
  }
5944
5950
  };
5945
5951
 
5952
+ async function outputCmdJson(cwd) {
5953
+ logger.logger.info('Target cwd:', constants.ENV.VITEST ? '<redacted>' : utils.tildify(cwd));
5954
+ const sjpath = path.join(cwd, 'socket.json');
5955
+ const tildeSjpath = constants.ENV.VITEST ? '<redacted>' : utils.tildify(sjpath);
5956
+ if (!fs$1.existsSync(sjpath)) {
5957
+ logger.logger.fail(`Not found: ${tildeSjpath}`);
5958
+ process.exitCode = 1;
5959
+ return;
5960
+ }
5961
+ if (!fs$1.lstatSync(sjpath).isFile()) {
5962
+ logger.logger.fail(`This is not a regular file (maybe a directory?): ${tildeSjpath}`);
5963
+ process.exitCode = 1;
5964
+ return;
5965
+ }
5966
+ const data = fs$1.readFileSync(sjpath, 'utf8');
5967
+ logger.logger.success(`This is the contents of ${tildeSjpath}:`);
5968
+ logger.logger.error('');
5969
+ logger.logger.log(data);
5970
+ }
5971
+
5972
+ async function handleCmdJson(cwd) {
5973
+ await outputCmdJson(cwd);
5974
+ }
5975
+
5976
+ const config$F = {
5977
+ commandName: 'json',
5978
+ description: 'Display the `socket.json` that would be applied for target folder',
5979
+ hidden: true,
5980
+ // This is a power tool. No need to clutter the toplevel.
5981
+ flags: {
5982
+ ...utils.commonFlags
5983
+ },
5984
+ help: parentName => `
5985
+ Usage
5986
+ $ ${parentName} [CWD=.]
5987
+
5988
+ Display the \`socket.json\` file that would apply when running relevant commands
5989
+ in the target directory.
5990
+ `
5991
+ };
5992
+ const cmdJson = {
5993
+ description: config$F.description,
5994
+ hidden: config$F.hidden,
5995
+ run: run$F
5996
+ };
5997
+ async function run$F(argv, importMeta, {
5998
+ parentName
5999
+ }) {
6000
+ const cli = utils.meowOrExit({
6001
+ argv,
6002
+ config: config$F,
6003
+ importMeta,
6004
+ parentName
6005
+ });
6006
+ let [cwd = '.'] = cli.input;
6007
+ // Note: path.resolve vs .join:
6008
+ // If given path is absolute then cwd should not affect it.
6009
+ cwd = path.resolve(process.cwd(), cwd);
6010
+ await handleCmdJson(cwd);
6011
+ }
6012
+
5946
6013
  function applyLogin(apiToken, enforcedOrgs, apiBaseUrl, apiProxy) {
5947
6014
  utils.updateConfigValue('enforcedOrgs', enforcedOrgs);
5948
6015
  utils.updateConfigValue('apiToken', apiToken);
@@ -7498,7 +7565,12 @@ const config$t = {
7498
7565
  hidden: true,
7499
7566
  flags: {
7500
7567
  ...utils.commonFlags,
7501
- ...utils.outputFlags
7568
+ ...utils.outputFlags,
7569
+ throw: {
7570
+ type: 'boolean',
7571
+ default: false,
7572
+ description: 'Throw an explicit error even if --json or --markdown are set'
7573
+ }
7502
7574
  },
7503
7575
  help: (parentName, config) => `
7504
7576
  Usage
@@ -7523,13 +7595,14 @@ async function run$t(argv, importMeta, {
7523
7595
  });
7524
7596
  const {
7525
7597
  json,
7526
- markdown
7598
+ markdown,
7599
+ throw: justThrow
7527
7600
  } = cli.flags;
7528
7601
  if (cli.flags['dryRun']) {
7529
7602
  logger.logger.log(DRY_RUN_BAILING_NOW$r);
7530
7603
  return;
7531
7604
  }
7532
- if (json) {
7605
+ if (json && !justThrow) {
7533
7606
  process.exitCode = 1;
7534
7607
  logger.logger.log(utils.serializeResultJson({
7535
7608
  ok: false,
@@ -7537,7 +7610,7 @@ async function run$t(argv, importMeta, {
7537
7610
  cause: 'This error was intentionally left blank'
7538
7611
  }));
7539
7612
  }
7540
- if (markdown) {
7613
+ if (markdown && !justThrow) {
7541
7614
  process.exitCode = 1;
7542
7615
  logger.logger.fail(utils.failMsgWithBadge('Oops', 'This error was intentionally left blank'));
7543
7616
  return;
@@ -7676,12 +7749,14 @@ function includesBun(lockSrc, name, lockName) {
7676
7749
  function includesPnpm(lockSrc, name) {
7677
7750
  const escapedName = regexps.escapeRegExp(name);
7678
7751
  return new RegExp(
7679
- // Detects the package name in the following cases:
7680
- // /name/
7752
+ // Detects the package name.
7753
+ // v9.0 and v6.0 lockfile patterns:
7681
7754
  // 'name'
7682
7755
  // name:
7683
7756
  // name@
7684
- `(?<=^\\s*)(?:(['/])${escapedName}\\1|${escapedName}(?=[:@]))`, 'm').test(lockSrc);
7757
+ // v6.0 lockfile patterns:
7758
+ // /name@
7759
+ `(?<=^\\s*)(?:'${escapedName}'|/?${escapedName}(?=[:@]))`, 'm').test(lockSrc);
7685
7760
  }
7686
7761
  function includesVlt(lockSrc, name) {
7687
7762
  // Detects the package name in the following cases:
@@ -8910,7 +8985,7 @@ async function fetchPurlDeepScore(purl) {
8910
8985
  return await utils.queryApiSafeJson(`purl/score/${encodeURIComponent(purl)}`, 'the deep package scores');
8911
8986
  }
8912
8987
 
8913
- async function outputPurlScore(purl, result, outputKind) {
8988
+ async function outputPurlsDeepScore(purl, result, outputKind) {
8914
8989
  if (!result.ok) {
8915
8990
  process.exitCode = result.code ?? 1;
8916
8991
  }
@@ -8923,151 +8998,156 @@ async function outputPurlScore(purl, result, outputKind) {
8923
8998
  return;
8924
8999
  }
8925
9000
  if (outputKind === 'markdown') {
8926
- const {
8927
- purl: requestedPurl,
8928
- self: {
8929
- alerts: selfAlerts,
8930
- capabilities: selfCaps,
8931
- purl,
8932
- score: selfScore
8933
- },
8934
- transitively: {
8935
- alerts,
8936
- capabilities,
8937
- dependencyCount,
8938
- func,
8939
- lowest,
8940
- score
8941
- }
8942
- } = result.data;
8943
- logger.logger.success(`Score report for "${requestedPurl}" ("${purl}"):\n`);
8944
- logger.logger.log('# Complete Package Score');
8945
- logger.logger.log('');
8946
- if (dependencyCount) {
8947
- logger.logger.log(`This is a Socket report for the package *"${purl}"* and its *${dependencyCount}* direct/transitive dependencies.`);
8948
- } else {
8949
- logger.logger.log(`This is a Socket report for the package *"${purl}"*. It has *no dependencies*.`);
8950
- }
8951
- logger.logger.log('');
8952
- if (dependencyCount) {
8953
- logger.logger.log(`It will show you the shallow score for just the package itself and a deep score for all the transitives combined. Additionally you can see which capabilities were found and the top alerts as well as a package that was responsible for it.`);
8954
- } else {
8955
- logger.logger.log(`It will show you the shallow score for the package itself, which capabilities were found, and its top alerts.`);
8956
- logger.logger.log('');
8957
- logger.logger.log('Since it has no dependencies, the shallow score is also the deep score.');
8958
- }
8959
- logger.logger.log('');
9001
+ const md = createMarkdownReport(result.data);
9002
+ logger.logger.success(`Score report for "${result.data.purl}" ("${purl}"):\n`);
9003
+ logger.logger.log(md);
9004
+ return;
9005
+ }
9006
+ logger.logger.log(`Score report for "${purl}" (use --json for raw and --markdown for formatted reports):`);
9007
+ logger.logger.log(result.data);
9008
+ logger.logger.log('');
9009
+ }
9010
+ function createMarkdownReport(data) {
9011
+ const {
9012
+ self: {
9013
+ alerts: selfAlerts,
9014
+ capabilities: selfCaps,
9015
+ purl,
9016
+ score: selfScore
9017
+ },
9018
+ transitively: {
9019
+ alerts,
9020
+ capabilities,
9021
+ dependencyCount,
9022
+ func,
9023
+ lowest,
9024
+ score
9025
+ }
9026
+ } = data;
9027
+ const arr = [];
9028
+ arr.push('# Complete Package Score');
9029
+ arr.push('');
9030
+ if (dependencyCount) {
9031
+ arr.push(`This is a Socket report for the package *"${purl}"* and its *${dependencyCount}* direct/transitive dependencies.`);
9032
+ } else {
9033
+ arr.push(`This is a Socket report for the package *"${purl}"*. It has *no dependencies*.`);
9034
+ }
9035
+ arr.push('');
9036
+ if (dependencyCount) {
9037
+ arr.push(`It will show you the shallow score for just the package itself and a deep score for all the transitives combined. Additionally you can see which capabilities were found and the top alerts as well as a package that was responsible for it.`);
9038
+ } else {
9039
+ arr.push(`It will show you the shallow score for the package itself, which capabilities were found, and its top alerts.`);
9040
+ arr.push('');
9041
+ arr.push('Since it has no dependencies, the shallow score is also the deep score.');
9042
+ }
9043
+ arr.push('');
9044
+ if (dependencyCount) {
9045
+ // This doesn't make much sense if there are no dependencies. Better to omit it.
9046
+ arr.push('The report should give you a good insight into the status of this package.');
9047
+ arr.push('');
9048
+ arr.push('## Package itself');
9049
+ arr.push('');
9050
+ arr.push('Here are results for the package itself (excluding data from dependencies).');
9051
+ } else {
9052
+ arr.push('## Report');
9053
+ arr.push('');
9054
+ arr.push('The report should give you a good insight into the status of this package.');
9055
+ }
9056
+ arr.push('');
9057
+ arr.push('### Shallow Score');
9058
+ arr.push('');
9059
+ arr.push('This score is just for the package itself:');
9060
+ arr.push('');
9061
+ arr.push('- Overall: ' + selfScore.overall);
9062
+ arr.push('- Maintenance: ' + selfScore.maintenance);
9063
+ arr.push('- Quality: ' + selfScore.quality);
9064
+ arr.push('- Supply Chain: ' + selfScore.supplyChain);
9065
+ arr.push('- Vulnerability: ' + selfScore.vulnerability);
9066
+ arr.push('- License: ' + selfScore.license);
9067
+ arr.push('');
9068
+ arr.push('### Capabilities');
9069
+ arr.push('');
9070
+ if (selfCaps.length) {
9071
+ arr.push('These are the capabilities detected in the package itself:');
9072
+ arr.push('');
9073
+ selfCaps.forEach(cap => {
9074
+ arr.push(`- ${cap}`);
9075
+ });
9076
+ } else {
9077
+ arr.push('No capabilities were found in the package.');
9078
+ }
9079
+ arr.push('');
9080
+ arr.push('### Alerts for this package');
9081
+ arr.push('');
9082
+ if (selfAlerts.length) {
8960
9083
  if (dependencyCount) {
8961
- // This doesn't make much sense if there are no dependencies. Better to omit it.
8962
- logger.logger.log('The report should give you a good insight into the status of this package.');
8963
- logger.logger.log('');
8964
- logger.logger.log('## Package itself');
8965
- logger.logger.log('');
8966
- logger.logger.log('Here are results for the package itself (excluding data from dependencies).');
9084
+ arr.push('These are the alerts found for the package itself:');
8967
9085
  } else {
8968
- logger.logger.log('## Report');
8969
- logger.logger.log('');
8970
- logger.logger.log('The report should give you a good insight into the status of this package.');
9086
+ arr.push('These are the alerts found for this package:');
8971
9087
  }
8972
- logger.logger.log('');
8973
- logger.logger.log('### Shallow Score');
8974
- logger.logger.log('');
8975
- logger.logger.log('This score is just for the package itself:');
8976
- logger.logger.log('');
8977
- logger.logger.log('- Overall: ' + selfScore.overall);
8978
- logger.logger.log('- Maintenance: ' + selfScore.maintenance);
8979
- logger.logger.log('- Quality: ' + selfScore.quality);
8980
- logger.logger.log('- Supply Chain: ' + selfScore.supplyChain);
8981
- logger.logger.log('- Vulnerability: ' + selfScore.vulnerability);
8982
- logger.logger.log('- License: ' + selfScore.license);
8983
- logger.logger.log('');
8984
- logger.logger.log('### Capabilities');
8985
- logger.logger.log('');
8986
- if (selfCaps.length) {
8987
- logger.logger.log('These are the capabilities detected in the package itself:');
8988
- logger.logger.log('');
8989
- selfCaps.forEach(cap => {
8990
- logger.logger.log(`- ${cap}`);
9088
+ arr.push('');
9089
+ arr.push(utils.mdTable(selfAlerts, ['severity', 'name'], ['Severity', 'Alert Name']));
9090
+ } else {
9091
+ arr.push('There are currently no alerts for this package.');
9092
+ }
9093
+ arr.push('');
9094
+ if (dependencyCount) {
9095
+ arr.push('## Transitive Package Results');
9096
+ arr.push('');
9097
+ arr.push('Here are results for the package and its direct/transitive dependencies.');
9098
+ arr.push('');
9099
+ arr.push('### Deep Score');
9100
+ arr.push('');
9101
+ arr.push('This score represents the package and and its direct/transitive dependencies:');
9102
+ arr.push(`The function used to calculate the values in aggregate is: *"${func}"*`);
9103
+ arr.push('');
9104
+ arr.push('- Overall: ' + score.overall);
9105
+ arr.push('- Maintenance: ' + score.maintenance);
9106
+ arr.push('- Quality: ' + score.quality);
9107
+ arr.push('- Supply Chain: ' + score.supplyChain);
9108
+ arr.push('- Vulnerability: ' + score.vulnerability);
9109
+ arr.push('- License: ' + score.license);
9110
+ arr.push('');
9111
+ arr.push('### Capabilities');
9112
+ arr.push('');
9113
+ arr.push('These are the packages with the lowest recorded score. If there is more than one with the lowest score, just one is shown here. This may help you figure out the source of low scores.');
9114
+ arr.push('');
9115
+ arr.push('- Overall: ' + lowest.overall);
9116
+ arr.push('- Maintenance: ' + lowest.maintenance);
9117
+ arr.push('- Quality: ' + lowest.quality);
9118
+ arr.push('- Supply Chain: ' + lowest.supplyChain);
9119
+ arr.push('- Vulnerability: ' + lowest.vulnerability);
9120
+ arr.push('- License: ' + lowest.license);
9121
+ arr.push('');
9122
+ arr.push('### Capabilities');
9123
+ arr.push('');
9124
+ if (capabilities.length) {
9125
+ arr.push('These are the capabilities detected in at least one package:');
9126
+ arr.push('');
9127
+ capabilities.forEach(cap => {
9128
+ arr.push(`- ${cap}`);
8991
9129
  });
8992
9130
  } else {
8993
- logger.logger.log('No capabilities were found in the package.');
9131
+ arr.push('This package had no capabilities and neither did any of its direct/transitive dependencies.');
8994
9132
  }
8995
- logger.logger.log('');
8996
- logger.logger.log('### Alerts for this package');
8997
- logger.logger.log('');
8998
- if (selfAlerts.length) {
8999
- if (dependencyCount) {
9000
- logger.logger.log('These are the alerts found for the package itself:');
9001
- } else {
9002
- logger.logger.log('These are the alerts found for this package:');
9003
- }
9004
- logger.logger.log('');
9005
- logger.logger.log(utils.mdTable(selfAlerts, ['severity', 'name'], ['Severity', 'Alert Name']));
9133
+ arr.push('');
9134
+ arr.push('### Alerts');
9135
+ arr.push('');
9136
+ if (alerts.length) {
9137
+ arr.push('These are the alerts found:');
9138
+ arr.push('');
9139
+ arr.push(utils.mdTable(alerts, ['severity', 'name', 'example'], ['Severity', 'Alert Name', 'Example package reporting it']));
9006
9140
  } else {
9007
- logger.logger.log('There are currently no alerts for this package.');
9008
- }
9009
- logger.logger.log('');
9010
- if (dependencyCount) {
9011
- logger.logger.log('## Transitive Package Results');
9012
- logger.logger.log('');
9013
- logger.logger.log('Here are results for the package and its direct/transitive dependencies.');
9014
- logger.logger.log('');
9015
- logger.logger.log('### Deep Score');
9016
- logger.logger.log('');
9017
- logger.logger.log('This score represents the package and and its direct/transitive dependencies:');
9018
- logger.logger.log(`The function used to calculate the values in aggregate is: *"${func}"*`);
9019
- logger.logger.log('');
9020
- logger.logger.log('- Overall: ' + score.overall);
9021
- logger.logger.log('- Maintenance: ' + score.maintenance);
9022
- logger.logger.log('- Quality: ' + score.quality);
9023
- logger.logger.log('- Supply Chain: ' + score.supplyChain);
9024
- logger.logger.log('- Vulnerability: ' + score.vulnerability);
9025
- logger.logger.log('- License: ' + score.license);
9026
- logger.logger.log('');
9027
- logger.logger.log('### Capabilities');
9028
- logger.logger.log('');
9029
- logger.logger.log('These are the packages with the lowest recorded score. If there is more than one with the lowest score, just one is shown here. This may help you figure out the source of low scores.');
9030
- logger.logger.log('');
9031
- logger.logger.log('- Overall: ' + lowest.overall);
9032
- logger.logger.log('- Maintenance: ' + lowest.maintenance);
9033
- logger.logger.log('- Quality: ' + lowest.quality);
9034
- logger.logger.log('- Supply Chain: ' + lowest.supplyChain);
9035
- logger.logger.log('- Vulnerability: ' + lowest.vulnerability);
9036
- logger.logger.log('- License: ' + lowest.license);
9037
- logger.logger.log('');
9038
- logger.logger.log('### Capabilities');
9039
- logger.logger.log('');
9040
- if (capabilities.length) {
9041
- logger.logger.log('These are the capabilities detected in at least one package:');
9042
- logger.logger.log('');
9043
- capabilities.forEach(cap => {
9044
- logger.logger.log(`- ${cap}`);
9045
- });
9046
- } else {
9047
- logger.logger.log('This package had no capabilities and neither did any of its direct/transitive dependencies.');
9048
- }
9049
- logger.logger.log('');
9050
- logger.logger.log('### Alerts');
9051
- logger.logger.log('');
9052
- if (alerts.length) {
9053
- logger.logger.log('These are the alerts found:');
9054
- logger.logger.log('');
9055
- logger.logger.log(utils.mdTable(alerts, ['severity', 'name', 'example'], ['Severity', 'Alert Name', 'Example package reporting it']));
9056
- } else {
9057
- logger.logger.log('This package had no alerts and neither did any of its direct/transitive dependencies');
9058
- }
9059
- logger.logger.log('');
9141
+ arr.push('This package had no alerts and neither did any of its direct/transitive dependencies');
9060
9142
  }
9061
- return;
9143
+ arr.push('');
9144
+ return arr.join('\n');
9062
9145
  }
9063
- logger.logger.log(`Score report for "${purl}" (use --json for raw and --markdown for formatted reports):`);
9064
- logger.logger.log(result.data);
9065
- logger.logger.log('');
9066
9146
  }
9067
9147
 
9068
9148
  async function handlePurlDeepScore(purl, outputKind) {
9069
9149
  const result = await fetchPurlDeepScore(purl);
9070
- await outputPurlScore(purl, result, outputKind);
9150
+ await outputPurlsDeepScore(purl, result, outputKind);
9071
9151
  }
9072
9152
 
9073
9153
  // Either an ecosystem was given or all args must be (namespaced) purls
@@ -9247,6 +9327,8 @@ async function fetchPurlsShallowScore(purls) {
9247
9327
  };
9248
9328
  }
9249
9329
 
9330
+ // This is a simplified view of an artifact. Potentially merged with other artifacts.
9331
+
9250
9332
  function outputPurlsShallowScore(purls, result, outputKind) {
9251
9333
  if (!result.ok) {
9252
9334
  process.exitCode = result.code ?? 1;
@@ -9259,59 +9341,31 @@ function outputPurlsShallowScore(purls, result, outputKind) {
9259
9341
  logger.logger.fail(utils.failMsgWithBadge(result.message, result.cause));
9260
9342
  return;
9261
9343
  }
9262
-
9263
- // Make some effort to match the requested data with the response
9264
-
9265
- const set = new Set();
9266
- result.data.forEach(data => {
9267
- set.add('pkg:' + data.type + '/' + data.name + '@' + data.version);
9268
- set.add('pkg:' + data.type + '/' + data.name);
9269
- });
9270
- const missing = purls.filter(purl => {
9271
- if (set.has(purl)) {
9272
- return false;
9273
- }
9274
- if (purl.endsWith('@latest') && set.has(purl.slice(0, -'@latest'.length))) {
9275
- return false;
9276
- }
9277
- return true; // not found
9278
- });
9344
+ const {
9345
+ missing,
9346
+ rows
9347
+ } = preProcess(result.data, purls);
9279
9348
  if (outputKind === 'markdown') {
9280
- logger.logger.log(`
9281
- # Shallow Package Report
9282
-
9283
- This report contains the response for requesting data on some package url(s).
9284
-
9285
- Please note: The listed scores are ONLY for the package itself. It does NOT
9286
- reflect the scores of any dependencies, transitive or otherwise.
9287
-
9288
- ${missing.length ? `\n## Missing response\n\nAt least one package had no response or the purl was not canonical:\n\n${missing.map(purl => '- ' + purl + '\n').join('')}` : ''}
9289
-
9290
- ${result.data.map(data => '## ' + formatReportCard(data, false)).join('\n\n\n')}
9291
- `.trim());
9349
+ const md = generateMarkdownReport(rows, missing);
9350
+ logger.logger.log(md);
9292
9351
  return;
9293
9352
  }
9294
- logger.logger.log('\n' + vendor.yoctocolorsCjsExports.bold('Shallow Package Score') + '\n');
9295
- logger.logger.log('Please note: The listed scores are ONLY for the package itself. It does NOT\n' + ' reflect the scores of any dependencies, transitive or otherwise.');
9296
- if (missing.length) {
9297
- logger.logger.log(`\nAt least one package had no response or the purl was not canonical:\n${missing.map(purl => '\n- ' + vendor.yoctocolorsCjsExports.bold(purl)).join('')}`);
9298
- }
9299
- result.data.forEach(data => {
9300
- logger.logger.log('\n');
9301
- logger.logger.log(formatReportCard(data, true));
9302
- });
9303
- logger.logger.log('');
9353
+ const txt = generateTextReport(rows, missing);
9354
+ logger.logger.log(txt);
9304
9355
  }
9305
- function formatReportCard(data, color) {
9356
+ function formatReportCard(artifact, color) {
9306
9357
  const scoreResult = {
9307
- 'Supply Chain Risk': Math.floor((data.score?.supplyChain ?? 0) * 100),
9308
- Maintenance: Math.floor((data.score?.maintenance ?? 0) * 100),
9309
- Quality: Math.floor((data.score?.quality ?? 0) * 100),
9310
- Vulnerabilities: Math.floor((data.score?.vulnerability ?? 0) * 100),
9311
- License: Math.floor((data.score?.license ?? 0) * 100)
9358
+ 'Supply Chain Risk': Math.floor((artifact.score?.supplyChain ?? 0) * 100),
9359
+ Maintenance: Math.floor((artifact.score?.maintenance ?? 0) * 100),
9360
+ Quality: Math.floor((artifact.score?.quality ?? 0) * 100),
9361
+ Vulnerabilities: Math.floor((artifact.score?.vulnerability ?? 0) * 100),
9362
+ License: Math.floor((artifact.score?.license ?? 0) * 100)
9312
9363
  };
9313
- const alertString = getAlertString(data.alerts, !color);
9314
- const purl = 'pkg:' + data.type + '/' + data.name + '@' + data.version;
9364
+ const alertString = getAlertString(artifact.alerts, !color);
9365
+ if (!artifact.ecosystem) {
9366
+ console.log('WTF?', artifact);
9367
+ }
9368
+ const purl = `pkg:${artifact.ecosystem}/${artifact.name}${artifact.version ? '@' + artifact.version : ''}`;
9315
9369
  return ['Package: ' + (color ? vendor.yoctocolorsCjsExports.bold(purl) : purl), '', ...Object.entries(scoreResult).map(score => `- ${score[0]}:`.padEnd(20, ' ') + ` ${formatScore(score[1], !color, true)}`), alertString].join('\n');
9316
9370
  }
9317
9371
  function formatScore(score, noColor = false, pad = false) {
@@ -9328,12 +9382,13 @@ function formatScore(score, noColor = false, pad = false) {
9328
9382
  return vendor.yoctocolorsCjsExports.red(padded);
9329
9383
  }
9330
9384
  function getAlertString(alerts, noColor = false) {
9331
- if (!alerts?.length) {
9385
+ if (!alerts.size) {
9332
9386
  return noColor ? `- Alerts: none!` : `- Alerts: ${vendor.yoctocolorsCjsExports.green('none')}!`;
9333
9387
  }
9334
- const bad = alerts.filter(alert => alert.severity !== 'low' && alert.severity !== 'middle').sort((a, b) => a.type < b.type ? -1 : a.type > b.type ? 1 : 0);
9335
- const mid = alerts.filter(alert => alert.severity === 'middle').sort((a, b) => a.type < b.type ? -1 : a.type > b.type ? 1 : 0);
9336
- const low = alerts.filter(alert => alert.severity === 'low').sort((a, b) => a.type < b.type ? -1 : a.type > b.type ? 1 : 0);
9388
+ const arr = Array.from(alerts.values());
9389
+ const bad = arr.filter(alert => alert.severity !== 'low' && alert.severity !== 'middle').sort((a, b) => a.type < b.type ? -1 : a.type > b.type ? 1 : 0);
9390
+ const mid = arr.filter(alert => alert.severity === 'middle').sort((a, b) => a.type < b.type ? -1 : a.type > b.type ? 1 : 0);
9391
+ const low = arr.filter(alert => alert.severity === 'low').sort((a, b) => a.type < b.type ? -1 : a.type > b.type ? 1 : 0);
9337
9392
 
9338
9393
  // We need to create the no-color string regardless because the actual string
9339
9394
  // contains a bunch of invisible ANSI chars which would screw up length checks.
@@ -9343,6 +9398,146 @@ function getAlertString(alerts, noColor = false) {
9343
9398
  }
9344
9399
  return `- Alerts (${vendor.yoctocolorsCjsExports.red(bad.length.toString())}/${vendor.yoctocolorsCjsExports.yellow(mid.length.toString())}/${low.length}):` + ' '.repeat(Math.max(0, 20 - colorless.length)) + ' ' + [bad.map(alert => vendor.yoctocolorsCjsExports.red(vendor.yoctocolorsCjsExports.dim(`[${alert.severity}] `) + alert.type)).join(', '), mid.map(alert => vendor.yoctocolorsCjsExports.yellow(vendor.yoctocolorsCjsExports.dim(`[${alert.severity}] `) + alert.type)).join(', '), low.map(alert => vendor.yoctocolorsCjsExports.dim(`[${alert.severity}] `) + alert.type).join(', ')].filter(Boolean).join(', ');
9345
9400
  }
9401
+ function preProcess(artifacts, requestedPurls) {
9402
+ // Dedupe results (for example, pypi will emit one package for each system release (win/mac/cpu) even if it's
9403
+ // the same package version with same results. The duplication is irrelevant and annoying to the user.
9404
+
9405
+ // Make some effort to match the requested data with the response
9406
+ // Dedupe and merge results when only the .release value is different
9407
+
9408
+ // API does not tell us which purls were not found.
9409
+ // Generate all purls to try so we can try to match search request.
9410
+ const purls = new Set();
9411
+ artifacts.forEach(data => {
9412
+ purls.add(`pkg:${data.type}/${data.namespace ? `${data.namespace}/` : ''}${data.name}@${data.version}`);
9413
+ purls.add(`pkg:${data.type}/${data.name}@${data.version}`);
9414
+ purls.add(`pkg:${data.type}/${data.name}`);
9415
+ purls.add(`pkg:${data.type}/${data.namespace ? `${data.namespace}/` : ''}${data.name}`);
9416
+ });
9417
+ // Try to match the searched purls against this list
9418
+ const missing = requestedPurls.filter(purl => {
9419
+ if (purls.has(purl)) {
9420
+ return false;
9421
+ }
9422
+ if (purl.endsWith('@latest') && purls.has(purl.slice(0, -'@latest'.length))) {
9423
+ return false;
9424
+ }
9425
+ return true; // not found
9426
+ });
9427
+
9428
+ // Create a unique set of rows which represents each artifact that is returned
9429
+ // while deduping when the artifact (main) meta data only differs due to the
9430
+ // .release field (observed with python, at least).
9431
+ // Merge the alerts for duped packages. Use lowest score between all of them.
9432
+ const rows = new Map();
9433
+ artifacts.forEach(artifact => {
9434
+ const purl = `pkg:${artifact.type}/${artifact.namespace ? `${artifact.namespace}/` : ''}${artifact.name}${artifact.version ? `@${artifact.version}` : ''}`;
9435
+ if (rows.has(purl)) {
9436
+ const row = rows.get(purl);
9437
+ if (!row) {
9438
+ // unreachable; satisfy TS
9439
+ return;
9440
+ }
9441
+ if ((artifact.score?.supplyChain || 100) < row.score.supplyChain) {
9442
+ row.score.supplyChain = artifact.score?.supplyChain || 100;
9443
+ }
9444
+ if ((artifact.score?.maintenance || 100) < row.score.maintenance) {
9445
+ row.score.maintenance = artifact.score?.maintenance || 100;
9446
+ }
9447
+ if ((artifact.score?.quality || 100) < row.score.quality) {
9448
+ row.score.quality = artifact.score?.quality || 100;
9449
+ }
9450
+ if ((artifact.score?.vulnerability || 100) < row.score.vulnerability) {
9451
+ row.score.vulnerability = artifact.score?.vulnerability || 100;
9452
+ }
9453
+ if ((artifact.score?.license || 100) < row.score.license) {
9454
+ row.score.license = artifact.score?.license || 100;
9455
+ }
9456
+ artifact.alerts?.forEach(({
9457
+ severity,
9458
+ type
9459
+ }) => {
9460
+ row.alerts.set(`${type}:${severity}`, {
9461
+ type: type ?? 'unknown',
9462
+ severity: severity ?? 'none'
9463
+ });
9464
+ });
9465
+ } else {
9466
+ const alerts = new Map();
9467
+ artifact.alerts?.forEach(({
9468
+ severity,
9469
+ type
9470
+ }) => {
9471
+ alerts.set(`${type}:${severity}`, {
9472
+ type: type ?? 'unknown',
9473
+ severity: severity ?? 'none'
9474
+ });
9475
+ });
9476
+ rows.set(purl, {
9477
+ ecosystem: artifact.type,
9478
+ namespace: artifact.namespace || '',
9479
+ name: artifact.name,
9480
+ version: artifact.version || '',
9481
+ score: {
9482
+ supplyChain: artifact.score?.supplyChain || 100,
9483
+ maintenance: artifact.score?.maintenance || 100,
9484
+ quality: artifact.score?.quality || 100,
9485
+ vulnerability: artifact.score?.vulnerability || 100,
9486
+ license: artifact.score?.license || 100
9487
+ },
9488
+ alerts
9489
+ });
9490
+ }
9491
+ });
9492
+ return {
9493
+ rows,
9494
+ missing
9495
+ };
9496
+ }
9497
+ function generateMarkdownReport(artifacts, missing) {
9498
+ const blocks = [];
9499
+ const dupes = new Set();
9500
+ artifacts.forEach(artifact => {
9501
+ const block = '## ' + formatReportCard(artifact, false);
9502
+ if (dupes.has(block)) {
9503
+ return;
9504
+ }
9505
+ dupes.add(block);
9506
+ blocks.push(block);
9507
+ });
9508
+ return `
9509
+ # Shallow Package Report
9510
+
9511
+ This report contains the response for requesting data on some package url(s).
9512
+
9513
+ Please note: The listed scores are ONLY for the package itself. It does NOT
9514
+ reflect the scores of any dependencies, transitive or otherwise.
9515
+
9516
+ ${missing.length ? `\n## Missing response\n\nAt least one package had no response or the purl was not canonical:\n\n${missing.map(purl => '- ' + purl + '\n').join('')}` : ''}
9517
+
9518
+ ${blocks.join('\n\n\n')}
9519
+ `.trim();
9520
+ }
9521
+ function generateTextReport(artifacts, missing) {
9522
+ const arr = [];
9523
+ arr.push('\n' + vendor.yoctocolorsCjsExports.bold('Shallow Package Score') + '\n');
9524
+ arr.push('Please note: The listed scores are ONLY for the package itself. It does NOT\n' + ' reflect the scores of any dependencies, transitive or otherwise.');
9525
+ if (missing.length) {
9526
+ arr.push(`\nAt least one package had no response or the purl was not canonical:\n${missing.map(purl => '\n- ' + vendor.yoctocolorsCjsExports.bold(purl)).join('')}`);
9527
+ }
9528
+ const dupes = new Set(); // Omit dupes when output is identical
9529
+ artifacts.forEach(artifact => {
9530
+ const block = formatReportCard(artifact, true);
9531
+ if (dupes.has(block)) {
9532
+ return;
9533
+ }
9534
+ dupes.add(block);
9535
+ arr.push('\n');
9536
+ arr.push(block);
9537
+ });
9538
+ arr.push('');
9539
+ return arr.join('\n');
9540
+ }
9346
9541
 
9347
9542
  async function handlePurlsShallowScore({
9348
9543
  outputKind,
@@ -11769,6 +11964,15 @@ async function streamDownloadWithFetch(localPath, downloadUrl) {
11769
11964
  cause: 'Response body is null or undefined.'
11770
11965
  };
11771
11966
  }
11967
+
11968
+ // Make sure the dir exists. It may be nested and we need to construct that
11969
+ // before starting the download.
11970
+ const dir = path.dirname(localPath);
11971
+ if (!fs$1.existsSync(dir)) {
11972
+ fs$1.mkdirSync(dir, {
11973
+ recursive: true
11974
+ });
11975
+ }
11772
11976
  const fileStream = fs$1.createWriteStream(localPath);
11773
11977
 
11774
11978
  // Using stream.pipeline for better error handling and cleanup
@@ -12645,12 +12849,35 @@ async function outputScanReach(result, cwd, outputKind) {
12645
12849
  logger.logger.success('finished on', cwd);
12646
12850
  }
12647
12851
 
12852
+ const {
12853
+ DOT_SOCKET_DOT_FACTS_JSON
12854
+ } = constants;
12648
12855
  async function scanReachability(cwd) {
12649
- logger.logger.log('Scanning now... as soon as you implement me! From', cwd);
12650
- return {
12651
- ok: true,
12652
- data: undefined
12653
- };
12856
+ try {
12857
+ const result = await spawn.spawn(constants.execPath, [
12858
+ // Lazily access constants.nodeNoWarningsFlags.
12859
+ ...constants.nodeNoWarningsFlags,
12860
+ // Lazily access constants.coanaBinPath.
12861
+ constants.coanaBinPath, 'run', cwd, '--output-dir', cwd, '--disable-report-submission', '--socket-mode', DOT_SOCKET_DOT_FACTS_JSON], {
12862
+ cwd,
12863
+ env: {
12864
+ ...process.env,
12865
+ // Lazily access constants.ENV.SOCKET_CLI_API_TOKEN
12866
+ SOCKET_CLI_API_TOKEN: constants.ENV.SOCKET_CLI_API_TOKEN
12867
+ }
12868
+ });
12869
+ return {
12870
+ ok: true,
12871
+ data: result.stdout.trim()
12872
+ };
12873
+ } catch (e) {
12874
+ const message = e?.stdout ?? e?.message;
12875
+ return {
12876
+ ok: false,
12877
+ data: e,
12878
+ message
12879
+ };
12880
+ }
12654
12881
  }
12655
12882
 
12656
12883
  async function handleScanReach(cwd, outputKind) {
@@ -12667,12 +12894,7 @@ const config$6 = {
12667
12894
  hidden: true,
12668
12895
  flags: {
12669
12896
  ...utils.commonFlags,
12670
- ...utils.outputFlags,
12671
- interactive: {
12672
- type: 'boolean',
12673
- default: true,
12674
- description: 'Allow for interactive elements, asking for input. Use --no-interactive to prevent any input questions, defaulting them to cancel/no.'
12675
- }
12897
+ ...utils.outputFlags
12676
12898
  },
12677
12899
  help: (command, config) => `
12678
12900
  Usage
@@ -12702,7 +12924,6 @@ async function run$6(argv, importMeta, {
12702
12924
  });
12703
12925
  const {
12704
12926
  dryRun,
12705
- interactive,
12706
12927
  json,
12707
12928
  markdown
12708
12929
  } = cli.flags;
@@ -12711,7 +12932,6 @@ async function run$6(argv, importMeta, {
12711
12932
  // Note: path.resolve vs .join:
12712
12933
  // If given path is absolute then cwd should not affect it.
12713
12934
  cwd = path.resolve(process.cwd(), cwd);
12714
- logger.logger.info('If you dont have any interactive bits then drop the flag', interactive);
12715
12935
  const wasValidInput = utils.checkCommandInput(outputKind);
12716
12936
  if (!wasValidInput) {
12717
12937
  return;
@@ -14239,6 +14459,7 @@ void (async () => {
14239
14459
  fix: cmdFix,
14240
14460
  info: cmdInfo,
14241
14461
  install: cmdInstall,
14462
+ json: cmdJson,
14242
14463
  login: cmdLogin,
14243
14464
  logout: cmdLogout,
14244
14465
  npm: cmdNpm,
@@ -14346,6 +14567,24 @@ void (async () => {
14346
14567
  });
14347
14568
  } catch (e) {
14348
14569
  process.exitCode = 1;
14570
+ debug.debugFn('Uncaught error (BAD!):');
14571
+ debug.debugFn(e);
14572
+
14573
+ // Try to parse the flags, find out if --json or --markdown is set
14574
+ let isJson = false;
14575
+ try {
14576
+ const cli = vendor.meow(``, {
14577
+ argv: process.argv.slice(2),
14578
+ importMeta: {
14579
+ url: `${require$$0.pathToFileURL(__filename$1)}`
14580
+ },
14581
+ flags: {},
14582
+ // Do not strictly check for flags here.
14583
+ allowUnknownFlags: true,
14584
+ autoHelp: false
14585
+ });
14586
+ isJson = !!cli.flags['json'];
14587
+ } catch {}
14349
14588
  let errorBody;
14350
14589
  let errorTitle;
14351
14590
  let errorMessage = '';
@@ -14363,14 +14602,22 @@ void (async () => {
14363
14602
  } else {
14364
14603
  errorTitle = 'Unexpected error with no details';
14365
14604
  }
14366
- logger.logger.error('\n'); // Any-spinner-newline
14367
- logger.logger.fail(utils.failMsgWithBadge(errorTitle, errorMessage));
14368
- if (errorBody) {
14369
- // Explicitly use debugLog here.
14370
- debug.debugLog(errorBody);
14605
+ if (isJson) {
14606
+ logger.logger.log(utils.serializeResultJson({
14607
+ ok: false,
14608
+ message: errorTitle,
14609
+ cause: errorMessage
14610
+ }));
14611
+ } else {
14612
+ logger.logger.error('\n'); // Any-spinner-newline
14613
+ logger.logger.fail(utils.failMsgWithBadge(errorTitle, errorMessage));
14614
+ if (errorBody) {
14615
+ // Explicitly use debugLog here.
14616
+ debug.debugLog(errorBody);
14617
+ }
14371
14618
  }
14372
14619
  await utils.captureException(e);
14373
14620
  }
14374
14621
  })();
14375
- //# debugId=fc631456-d58c-4127-856d-214963966236
14622
+ //# debugId=46cd08dc-8e3e-40e8-bfdb-0a0801cce912
14376
14623
  //# sourceMappingURL=cli.js.map