socket 1.0.0 → 1.0.1

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 (57) hide show
  1. package/dist/cli.js +539 -862
  2. package/dist/cli.js.map +1 -1
  3. package/dist/constants.js +4 -4
  4. package/dist/constants.js.map +1 -1
  5. package/dist/shadow-npm-inject.js +1 -61
  6. package/dist/shadow-npm-inject.js.map +1 -1
  7. package/dist/types/cli.d.mts +1 -0
  8. package/dist/types/commands/fix/agent-fix.d.mts +36 -0
  9. package/dist/types/commands/fix/agent-fix.d.mts.map +1 -0
  10. package/dist/types/commands/fix/cmd-fix.d.mts.map +1 -1
  11. package/dist/types/commands/fix/get-actual-tree.d.mts +3 -0
  12. package/dist/types/commands/fix/get-actual-tree.d.mts.map +1 -0
  13. package/dist/types/commands/fix/handle-fix.d.mts +11 -1
  14. package/dist/types/commands/fix/handle-fix.d.mts.map +1 -1
  15. package/dist/types/commands/fix/npm-fix.d.mts +2 -10
  16. package/dist/types/commands/fix/npm-fix.d.mts.map +1 -1
  17. package/dist/types/commands/fix/pnpm-fix.d.mts +2 -10
  18. package/dist/types/commands/fix/pnpm-fix.d.mts.map +1 -1
  19. package/dist/types/commands/manifest/convert_gradle_to_maven.d.mts.map +1 -1
  20. package/dist/types/commands/optimize/get-overrides-by-agent.d.mts +35 -2
  21. package/dist/types/commands/optimize/get-overrides-by-agent.d.mts.map +1 -1
  22. package/dist/types/commands/repository/output-list-repos.d.mts.map +1 -1
  23. package/dist/types/commands/scan/cmd-scan-create.d.mts.map +1 -1
  24. package/dist/types/commands/scan/cmd-scan-github.d.mts.map +1 -1
  25. package/dist/types/commands/scan/handle-create-github-scan.d.mts.map +1 -1
  26. package/dist/types/commands/scan/output-scan-github.d.mts +3 -0
  27. package/dist/types/commands/scan/output-scan-github.d.mts.map +1 -0
  28. package/dist/types/commands/scan/suggest-org-slug.d.mts.map +1 -1
  29. package/dist/types/commands/scan/suggest-to-persist-orgslug.d.mts +2 -0
  30. package/dist/types/commands/scan/suggest-to-persist-orgslug.d.mts.map +1 -0
  31. package/dist/types/utils/config.d.mts +2 -1
  32. package/dist/types/utils/config.d.mts.map +1 -1
  33. package/dist/types/utils/determine-org-slug.d.mts.map +1 -1
  34. package/dist/types/utils/lockfile.d.mts +2 -0
  35. package/dist/types/utils/lockfile.d.mts.map +1 -0
  36. package/dist/types/utils/meow-with-subcommands.d.mts +1 -1
  37. package/dist/types/utils/meow-with-subcommands.d.mts.map +1 -1
  38. package/dist/types/utils/package-environment.d.mts +11 -11
  39. package/dist/types/utils/package-environment.d.mts.map +1 -1
  40. package/dist/types/utils/pnpm.d.mts +1 -1
  41. package/dist/types/utils/pnpm.d.mts.map +1 -1
  42. package/dist/types/utils/semver.d.mts.map +1 -1
  43. package/dist/utils.js +114 -29
  44. package/dist/utils.js.map +1 -1
  45. package/dist/vendor.js +7129 -7118
  46. package/external/@coana-tech/cli/cli.mjs +14035 -3820
  47. package/external/@socketsecurity/registry/external/@npmcli/package-json/index.js +7 -7
  48. package/external/@socketsecurity/registry/external/@socketregistry/packageurl-js.js +12 -8
  49. package/external/@socketsecurity/registry/external/cacache.js +6 -6
  50. package/external/@socketsecurity/registry/external/libnpmpack.js +47 -45
  51. package/external/@socketsecurity/registry/external/make-fetch-happen.js +37 -36
  52. package/external/@socketsecurity/registry/external/pacote.js +45 -44
  53. package/external/blessed-contrib/lib/widget/charts/bar.js +6 -3
  54. package/external/blessed-contrib/lib/widget/charts/line.js +6 -3
  55. package/package.json +27 -27
  56. package/dist/types/commands/fix/run-fix.d.mts +0 -12
  57. package/dist/types/commands/fix/run-fix.d.mts.map +0 -1
package/dist/cli.js CHANGED
@@ -20,12 +20,12 @@ var packages = require('../external/@socketsecurity/registry/lib/packages');
20
20
  var sorts = require('../external/@socketsecurity/registry/lib/sorts');
21
21
  var path$1 = require('../external/@socketsecurity/registry/lib/path');
22
22
  var regexps = require('../external/@socketsecurity/registry/lib/regexps');
23
+ var shadowNpmInject = require('./shadow-npm-inject.js');
23
24
  var fs$2 = require('../external/@socketsecurity/registry/lib/fs');
24
25
  var strings = require('../external/@socketsecurity/registry/lib/strings');
25
- var shadowNpmInject = require('./shadow-npm-inject.js');
26
+ var objects = require('../external/@socketsecurity/registry/lib/objects');
26
27
  var words = require('../external/@socketsecurity/registry/lib/words');
27
28
  var shadowNpmBin = require('./shadow-npm-bin.js');
28
- var objects = require('../external/@socketsecurity/registry/lib/objects');
29
29
  var require$$7 = require('../external/@socketsecurity/registry/lib/promises');
30
30
  var require$$1 = require('node:util');
31
31
  var os = require('node:os');
@@ -2966,22 +2966,6 @@ const cmdConfig = {
2966
2966
  }
2967
2967
  };
2968
2968
 
2969
- async function outputFixResult(result, outputKind) {
2970
- if (!result.ok) {
2971
- process.exitCode = result.code ?? 1;
2972
- }
2973
- if (outputKind === 'json') {
2974
- logger.logger.log(utils.serializeResultJson(result));
2975
- return;
2976
- }
2977
- if (!result.ok) {
2978
- logger.logger.fail(utils.failMsgWithBadge(result.message, result.cause));
2979
- return;
2980
- }
2981
- logger.logger.log('');
2982
- logger.logger.success('Finished!');
2983
- }
2984
-
2985
2969
  function formatBranchName(name) {
2986
2970
  return name.replace(/[^-a-zA-Z0-9/._-]+/g, '+');
2987
2971
  }
@@ -3264,6 +3248,18 @@ function getActiveBranchesForPackage(ciEnv, partialPurl, openPrs) {
3264
3248
  return activeBranches;
3265
3249
  }
3266
3250
 
3251
+ async function getActualTree(cwd = process.cwd()) {
3252
+ // @npmcli/arborist DOES have partial support for pnpm structured node_modules
3253
+ // folders. However, support is iffy resulting in unhappy path errors and hangs.
3254
+ // So, to avoid the unhappy path, we restrict our usage to --dry-run loading
3255
+ // of the node_modules folder.
3256
+ const arb = new shadowNpmInject.Arborist({
3257
+ path: cwd,
3258
+ ...shadowNpmInject.SAFE_ARBORIST_REIFY_OPTIONS_OVERRIDES
3259
+ });
3260
+ return await arb.loadActual();
3261
+ }
3262
+
3267
3263
  let _octokit;
3268
3264
  function getOctokit() {
3269
3265
  if (_octokit === undefined) {
@@ -3634,133 +3630,94 @@ async function setGitRemoteGithubRepoUrl(owner, repo, token, cwd = process.cwd()
3634
3630
  }
3635
3631
  }
3636
3632
 
3637
- async function getEnvRepoInfo(cwd) {
3638
- // Lazily access constants.ENV.GITHUB_REPOSITORY.
3639
- const {
3640
- GITHUB_REPOSITORY
3641
- } = constants.ENV;
3642
- if (!GITHUB_REPOSITORY) {
3643
- debug.debugFn('miss: GITHUB_REPOSITORY env var');
3644
- }
3645
- const ownerSlashRepo = GITHUB_REPOSITORY;
3646
- const slashIndex = ownerSlashRepo.indexOf('/');
3647
- if (slashIndex !== -1) {
3648
- return {
3649
- owner: ownerSlashRepo.slice(0, slashIndex),
3650
- repo: ownerSlashRepo.slice(slashIndex + 1)
3651
- };
3652
- }
3653
- return await gitRepoInfo(cwd);
3633
+ const {
3634
+ BUN: BUN$4,
3635
+ NPM: NPM$8,
3636
+ OVERRIDES: OVERRIDES$2,
3637
+ PNPM: PNPM$8,
3638
+ RESOLUTIONS: RESOLUTIONS$1,
3639
+ VLT: VLT$5,
3640
+ YARN_BERRY: YARN_BERRY$4,
3641
+ YARN_CLASSIC: YARN_CLASSIC$5
3642
+ } = constants;
3643
+ function getOverridesDataBun(pkgEnvDetails, pkgJson = pkgEnvDetails.editablePkgJson.content) {
3644
+ const overrides = pkgJson?.[RESOLUTIONS$1] ?? {};
3645
+ return {
3646
+ type: YARN_BERRY$4,
3647
+ overrides
3648
+ };
3654
3649
  }
3655
- async function getCiEnv() {
3656
- const gitEmail = constants.ENV.SOCKET_CLI_GIT_USER_EMAIL;
3657
- const gitUser = constants.ENV.SOCKET_CLI_GIT_USER_NAME;
3658
- const githubToken = constants.ENV.SOCKET_CLI_GITHUB_TOKEN;
3659
- const isCi = !!(constants.ENV.CI && gitEmail && gitUser && githubToken);
3660
- if (!isCi) {
3661
- return null;
3662
- }
3663
- const baseBranch = await getBaseGitBranch();
3664
- if (!baseBranch) {
3665
- return null;
3666
- }
3667
- const repoInfo = await getEnvRepoInfo();
3668
- if (!repoInfo) {
3669
- return null;
3670
- }
3650
+
3651
+ // npm overrides documentation:
3652
+ // https://docs.npmjs.com/cli/v10/configuring-npm/package-json#overrides
3653
+ function getOverridesDataNpm(pkgEnvDetails, pkgJson = pkgEnvDetails.editablePkgJson.content) {
3654
+ const overrides = pkgJson?.[OVERRIDES$2] ?? {};
3671
3655
  return {
3672
- gitEmail,
3673
- gitUser,
3674
- githubToken,
3675
- repoInfo,
3676
- baseBranch,
3677
- branchParser: createSocketBranchParser()
3656
+ type: NPM$8,
3657
+ overrides
3678
3658
  };
3679
3659
  }
3680
- async function getOpenPrsForEnvironment(env) {
3681
- return env ? await getOpenSocketPrs(env.repoInfo.owner, env.repoInfo.repo, {
3682
- author: env.gitUser
3683
- }) : [];
3660
+
3661
+ // pnpm overrides documentation:
3662
+ // https://pnpm.io/package_json#pnpmoverrides
3663
+ function getOverridesDataPnpm(pkgEnvDetails, pkgJson = pkgEnvDetails.editablePkgJson.content) {
3664
+ const overrides = pkgJson?.[PNPM$8]?.[OVERRIDES$2] ?? {};
3665
+ return {
3666
+ type: PNPM$8,
3667
+ overrides
3668
+ };
3669
+ }
3670
+ function getOverridesDataVlt(pkgEnvDetails, pkgJson = pkgEnvDetails.editablePkgJson.content) {
3671
+ const overrides = pkgJson?.[OVERRIDES$2] ?? {};
3672
+ return {
3673
+ type: VLT$5,
3674
+ overrides
3675
+ };
3684
3676
  }
3685
3677
 
3686
- const CMD_NAME$1 = 'socket fix';
3687
- function getAlertsMapOptions(options = {}) {
3678
+ // Yarn resolutions documentation:
3679
+ // https://yarnpkg.com/configuration/manifest#resolutions
3680
+ function getOverridesDataYarn(pkgEnvDetails, pkgJson = pkgEnvDetails.editablePkgJson.content) {
3681
+ const overrides = pkgJson?.[RESOLUTIONS$1] ?? {};
3688
3682
  return {
3689
- __proto__: null,
3690
- consolidate: true,
3691
- nothrow: true,
3692
- ...options,
3693
- include: {
3694
- __proto__: null,
3695
- existing: true,
3696
- unfixable: false,
3697
- upgradable: false,
3698
- ...options?.include
3699
- }
3683
+ type: YARN_BERRY$4,
3684
+ overrides
3700
3685
  };
3701
3686
  }
3702
3687
 
3703
- async function install$1(arb, options) {
3704
- const {
3705
- cwd = process.cwd()
3706
- } = {
3707
- __proto__: null,
3708
- ...options
3688
+ // Yarn resolutions documentation:
3689
+ // https://classic.yarnpkg.com/en/docs/selective-version-resolutions
3690
+ function getOverridesDataYarnClassic(pkgEnvDetails, pkgJson = pkgEnvDetails.editablePkgJson.content) {
3691
+ const overrides = pkgJson?.[RESOLUTIONS$1] ?? {};
3692
+ return {
3693
+ type: YARN_CLASSIC$5,
3694
+ overrides
3709
3695
  };
3710
- try {
3711
- const newArb = new shadowNpmInject.Arborist({
3712
- path: cwd
3713
- });
3714
- newArb.idealTree = await arb.buildIdealTree();
3715
- const actualTree = await newArb.reify();
3716
- arb.actualTree = actualTree;
3717
- return actualTree;
3718
- } catch {}
3719
- return null;
3720
3696
  }
3721
- async function npmFix(pkgEnvDetails, {
3722
- autoMerge,
3723
- cwd,
3724
- limit,
3725
- purls,
3726
- rangeStyle,
3727
- test,
3728
- testScript
3729
- }) {
3730
- // Lazily access constants.spinner.
3697
+ const overridesDataByAgent = new Map([[BUN$4, getOverridesDataBun], [NPM$8, getOverridesDataNpm], [PNPM$8, getOverridesDataPnpm], [VLT$5, getOverridesDataVlt], [YARN_BERRY$4, getOverridesDataYarn], [YARN_CLASSIC$5, getOverridesDataYarnClassic]]);
3698
+
3699
+ const noopHandler = () => {};
3700
+ async function agentFix(pkgEnvDetails, actualTree, alertsMap, installer, {
3701
+ beforeInstall = noopHandler,
3702
+ // eslint-disable-next-line sort-destructure-keys/sort-destructure-keys
3703
+ afterInstall = noopHandler,
3704
+ revertInstall = noopHandler
3705
+ }, ciEnv, openPrs, options) {
3706
+ const {
3707
+ autoMerge,
3708
+ cwd,
3709
+ limit,
3710
+ rangeStyle,
3711
+ test,
3712
+ testScript
3713
+ } = options;
3731
3714
  const {
3732
3715
  spinner
3733
3716
  } = constants;
3734
3717
  const {
3735
3718
  pkgPath: rootPath
3736
3719
  } = pkgEnvDetails;
3737
- spinner?.start();
3738
- const ciEnv = await getCiEnv();
3739
- const openPrs = ciEnv ? await getOpenPrsForEnvironment(ciEnv) : [];
3740
3720
  let count = 0;
3741
- const arb = new shadowNpmInject.Arborist({
3742
- path: rootPath,
3743
- ...shadowNpmInject.SAFE_ARBORIST_REIFY_OPTIONS_OVERRIDES
3744
- });
3745
- // Calling arb.reify() creates the arb.diff object, nulls-out arb.idealTree,
3746
- // and populates arb.actualTree.
3747
- let actualTree = await arb.reify();
3748
- let alertsMap;
3749
- try {
3750
- alertsMap = purls.length ? await utils.getAlertsMapFromPurls(purls, getAlertsMapOptions({
3751
- limit: Math.max(limit, openPrs.length)
3752
- })) : await shadowNpmInject.getAlertsMapFromArborist(arb, getAlertsMapOptions({
3753
- limit: Math.max(limit, openPrs.length)
3754
- }));
3755
- } catch (e) {
3756
- spinner?.stop();
3757
- debug.debugFn('catch: PURL API\n', e);
3758
- return {
3759
- ok: false,
3760
- message: 'API Error',
3761
- cause: e?.message || 'Unknown Socket batch PURL API error.'
3762
- };
3763
- }
3764
3721
  const infoByPartialPurl = utils.getCveInfoFromAlertsMap(alertsMap, {
3765
3722
  limit: Math.max(limit, openPrs.length)
3766
3723
  });
@@ -3774,6 +3731,9 @@ async function npmFix(pkgEnvDetails, {
3774
3731
  }
3775
3732
  };
3776
3733
  }
3734
+ if (debug.isDebug()) {
3735
+ debug.debugFn('found: cves for', Array.from(infoByPartialPurl.keys()));
3736
+ }
3777
3737
 
3778
3738
  // Lazily access constants.packumentCache.
3779
3739
  const {
@@ -3784,6 +3744,7 @@ async function npmFix(pkgEnvDetails, {
3784
3744
  // Process the workspace root last since it will add an override to package.json.
3785
3745
  pkgEnvDetails.editablePkgJson.filename];
3786
3746
  const sortedInfoEntries = Array.from(infoByPartialPurl.entries()).sort((a, b) => sorts.naturalCompare(a[0], b[0]));
3747
+ const getOverridesData = overridesDataByAgent.get(pkgEnvDetails.agent);
3787
3748
  const cleanupInfoEntriesLoop = () => {
3788
3749
  logger.logger.dedent();
3789
3750
  spinner?.dedent();
@@ -3793,8 +3754,8 @@ async function npmFix(pkgEnvDetails, {
3793
3754
  cleanupInfoEntriesLoop();
3794
3755
  return {
3795
3756
  ok: false,
3796
- message: 'Installation failure',
3797
- cause: `Unexpected condition: ${pkgEnvDetails.agent} install failed.`
3757
+ message: 'Install failed',
3758
+ cause: `Unexpected condition: ${pkgEnvDetails.agent} install failed`
3798
3759
  };
3799
3760
  };
3800
3761
  spinner?.stop();
@@ -3836,7 +3797,33 @@ async function npmFix(pkgEnvDetails, {
3836
3797
  const isWorkspaceRoot = pkgJsonPath === pkgEnvDetails.editablePkgJson.filename;
3837
3798
  const workspace = isWorkspaceRoot ? 'root' : path.relative(rootPath, pkgPath);
3838
3799
  const branchWorkspace = ciEnv ? getSocketBranchWorkspaceComponent(workspace) : '';
3839
- const oldVersions = arrays.arrayUnique(shadowNpmInject.findPackageNodes(actualTree, name).map(n => n.target?.version ?? n.version).filter(Boolean));
3800
+
3801
+ // actualTree may not be defined on the first iteration of pkgJsonPathsLoop.
3802
+ if (!actualTree) {
3803
+ if (!ciEnv) {
3804
+ // eslint-disable-next-line no-await-in-loop
3805
+ await utils.removeNodeModules(cwd);
3806
+ }
3807
+ const maybeActualTree = ciEnv && fs$1.existsSync(path.join(rootPath, 'node_modules')) ?
3808
+ // eslint-disable-next-line no-await-in-loop
3809
+ await getActualTree(cwd) :
3810
+ // eslint-disable-next-line no-await-in-loop
3811
+ await installer(pkgEnvDetails, {
3812
+ cwd,
3813
+ spinner
3814
+ });
3815
+ const maybeLockSrc = maybeActualTree ?
3816
+ // eslint-disable-next-line no-await-in-loop
3817
+ await utils.readLockfile(pkgEnvDetails.lockPath) : null;
3818
+ if (maybeActualTree && maybeLockSrc) {
3819
+ actualTree = maybeActualTree;
3820
+ }
3821
+ }
3822
+ if (!actualTree) {
3823
+ // Exit early if install fails.
3824
+ return handleInstallFail();
3825
+ }
3826
+ const oldVersions = arrays.arrayUnique(shadowNpmInject.findPackageNodes(actualTree, name).map(n => n.version).filter(Boolean));
3840
3827
  if (!oldVersions.length) {
3841
3828
  debug.debugFn(`skip: ${name} not found\n`);
3842
3829
  // Skip to next package.
@@ -3850,7 +3837,7 @@ async function npmFix(pkgEnvDetails, {
3850
3837
  const editablePkgJson = await packages.readPackageJson(pkgJsonPath, {
3851
3838
  editable: true
3852
3839
  });
3853
- const fixedVersions = new Set();
3840
+ const seenVersions = new Set();
3854
3841
  let hasAnnouncedWorkspace = false;
3855
3842
  let workspaceLogCallCount = logger.logger.logCallCount;
3856
3843
  if (debug.isDebug()) {
@@ -3869,14 +3856,14 @@ async function npmFix(pkgEnvDetails, {
3869
3856
  infosLoop: for (const {
3870
3857
  firstPatchedVersionIdentifier,
3871
3858
  vulnerableVersionRange
3872
- } of infos.values()) {
3859
+ } of infos) {
3873
3860
  const newVersion = shadowNpmInject.findBestPatchVersion(node, availableVersions, vulnerableVersionRange);
3874
3861
  const newVersionPackument = newVersion ? packument.versions[newVersion] : undefined;
3875
3862
  if (!(newVersion && newVersionPackument)) {
3876
3863
  warningsForAfter.add(`${oldId} not updated: requires >=${firstPatchedVersionIdentifier}`);
3877
3864
  continue infosLoop;
3878
3865
  }
3879
- if (fixedVersions.has(newVersion)) {
3866
+ if (seenVersions.has(newVersion)) {
3880
3867
  continue infosLoop;
3881
3868
  }
3882
3869
  if (vendor.semverExports.gte(oldVersion, newVersion)) {
@@ -3891,29 +3878,14 @@ async function npmFix(pkgEnvDetails, {
3891
3878
  }
3892
3879
  continue infosLoop;
3893
3880
  }
3894
- const newVersionRange = utils.applyRange(oldVersion, newVersion, rangeStyle);
3881
+ const oldOverrides = getOverridesData(pkgEnvDetails, editablePkgJson.content);
3882
+ const overrideKey = `${name}@${vulnerableVersionRange}`;
3883
+ const newVersionRange = utils.applyRange(oldOverrides?.[overrideKey] ?? oldVersion, newVersion, rangeStyle);
3895
3884
  const newId = `${name}@${newVersionRange}`;
3896
- const revertData = {
3897
- ...(editablePkgJson.content.dependencies && {
3898
- dependencies: {
3899
- ...editablePkgJson.content.dependencies
3900
- }
3901
- }),
3902
- ...(editablePkgJson.content.optionalDependencies && {
3903
- optionalDependencies: {
3904
- ...editablePkgJson.content.optionalDependencies
3905
- }
3906
- }),
3907
- ...(editablePkgJson.content.peerDependencies && {
3908
- peerDependencies: {
3909
- ...editablePkgJson.content.peerDependencies
3910
- }
3911
- })
3912
- };
3913
- shadowNpmInject.updateNode(node, newVersion, newVersionPackument);
3914
- shadowNpmInject.updatePackageJsonFromNode(editablePkgJson,
3885
+
3915
3886
  // eslint-disable-next-line no-await-in-loop
3916
- await arb.buildIdealTree(), node, newVersion, rangeStyle);
3887
+ await beforeInstall(editablePkgJson, name, oldVersion, newVersion, vulnerableVersionRange, options);
3888
+ shadowNpmInject.updatePackageJsonFromNode(editablePkgJson, actualTree, node, newVersion, rangeStyle);
3917
3889
  // eslint-disable-next-line no-await-in-loop
3918
3890
  if (!(await editablePkgJson.save({
3919
3891
  ignoreWhitespace: true
@@ -3936,11 +3908,17 @@ async function npmFix(pkgEnvDetails, {
3936
3908
  let errored = false;
3937
3909
  try {
3938
3910
  // eslint-disable-next-line no-await-in-loop
3939
- const maybeActualTree = await install$1(arb, {
3940
- cwd
3911
+ const maybeActualTree = await installer(pkgEnvDetails, {
3912
+ cwd,
3913
+ spinner
3941
3914
  });
3942
- if (maybeActualTree) {
3915
+ const maybeLockSrc = maybeActualTree ?
3916
+ // eslint-disable-next-line no-await-in-loop
3917
+ await utils.readLockfile(pkgEnvDetails.lockPath) : null;
3918
+ if (maybeActualTree && maybeLockSrc) {
3943
3919
  actualTree = maybeActualTree;
3920
+ // eslint-disable-next-line no-await-in-loop
3921
+ await afterInstall(editablePkgJson, name, oldVersion, newVersion, vulnerableVersionRange, options);
3944
3922
  if (test) {
3945
3923
  spinner?.info(`Testing ${newId} in ${workspace}.`);
3946
3924
  // eslint-disable-next-line no-await-in-loop
@@ -3950,13 +3928,13 @@ async function npmFix(pkgEnvDetails, {
3950
3928
  });
3951
3929
  }
3952
3930
  spinner?.success(`Fixed ${name} in ${workspace}.`);
3953
- fixedVersions.add(newVersion);
3931
+ seenVersions.add(newVersion);
3954
3932
  } else {
3955
3933
  errored = true;
3956
3934
  }
3957
3935
  } catch (e) {
3958
- errored = true;
3959
3936
  error = e;
3937
+ errored = true;
3960
3938
  }
3961
3939
  spinner?.stop();
3962
3940
 
@@ -3966,14 +3944,12 @@ async function npmFix(pkgEnvDetails, {
3966
3944
  // eslint-disable-next-line no-await-in-loop
3967
3945
  const result = await gitUnstagedModifiedFiles(cwd);
3968
3946
  if (!result.ok) {
3969
- // Do we fail if this fails? If this git command
3970
- // fails then probably other git commands do too?
3971
3947
  logger.logger.warn('Unexpected condition: Nothing to commit, skipping PR creation.');
3972
- continue infosLoop;
3948
+ continue;
3973
3949
  }
3974
- const moddedFilepaths = result.data.filter(p => {
3975
- const basename = path.basename(p);
3976
- return basename === 'package.json' || basename === 'package-lock.json';
3950
+ const moddedFilepaths = result.data.filter(filepath => {
3951
+ const basename = path.basename(filepath);
3952
+ return basename === 'package.json' || basename === pkgEnvDetails.lockName;
3977
3953
  });
3978
3954
  if (!moddedFilepaths.length) {
3979
3955
  logger.logger.warn('Unexpected condition: Nothing to commit, skipping PR creation.');
@@ -4005,15 +3981,19 @@ async function npmFix(pkgEnvDetails, {
4005
3981
  // eslint-disable-next-line no-await-in-loop
4006
3982
  await gitResetAndClean(ciEnv.baseBranch, cwd);
4007
3983
  // eslint-disable-next-line no-await-in-loop
4008
- const maybeActualTree = await install$1(arb, {
4009
- cwd
3984
+ const maybeActualTree = await installer(pkgEnvDetails, {
3985
+ cwd,
3986
+ spinner
4010
3987
  });
4011
- if (!maybeActualTree) {
4012
- // Exit early if install fails.
4013
- return handleInstallFail();
3988
+ const maybeLockSrc = maybeActualTree ?
3989
+ // eslint-disable-next-line no-await-in-loop
3990
+ await utils.readLockfile(pkgEnvDetails.lockPath) : null;
3991
+ if (maybeActualTree && maybeLockSrc) {
3992
+ actualTree = maybeActualTree;
3993
+ continue infosLoop;
4014
3994
  }
4015
- actualTree = maybeActualTree;
4016
- continue infosLoop;
3995
+ // Exit early if install fails.
3996
+ return handleInstallFail();
4017
3997
  }
4018
3998
 
4019
3999
  // eslint-disable-next-line no-await-in-loop
@@ -4062,8 +4042,9 @@ async function npmFix(pkgEnvDetails, {
4062
4042
  // eslint-disable-next-line no-await-in-loop
4063
4043
  await gitResetAndClean(ciEnv.baseBranch, cwd);
4064
4044
  // eslint-disable-next-line no-await-in-loop
4065
- const maybeActualTree = await install$1(arb, {
4066
- cwd
4045
+ const maybeActualTree = await installer(pkgEnvDetails, {
4046
+ cwd,
4047
+ spinner
4067
4048
  });
4068
4049
  spinner?.stop();
4069
4050
  if (maybeActualTree) {
@@ -4075,24 +4056,33 @@ async function npmFix(pkgEnvDetails, {
4075
4056
  if (errored) {
4076
4057
  if (!ciEnv) {
4077
4058
  spinner?.start();
4078
- editablePkgJson.update(revertData);
4059
+ // eslint-disable-next-line no-await-in-loop
4060
+ await revertInstall(editablePkgJson, name, oldVersion, newVersion, vulnerableVersionRange, options);
4079
4061
  // eslint-disable-next-line no-await-in-loop
4080
4062
  await Promise.all([utils.removeNodeModules(cwd), editablePkgJson.save({
4081
4063
  ignoreWhitespace: true
4082
4064
  })]);
4083
4065
  // eslint-disable-next-line no-await-in-loop
4084
- const maybeActualTree = await install$1(arb, {
4085
- cwd
4066
+ const maybeActualTree = await installer(pkgEnvDetails, {
4067
+ cwd,
4068
+ spinner
4086
4069
  });
4087
4070
  spinner?.stop();
4088
- if (!maybeActualTree) {
4071
+ if (maybeActualTree) {
4072
+ actualTree = maybeActualTree;
4073
+ } else {
4089
4074
  // Exit early if install fails.
4090
4075
  return handleInstallFail();
4091
4076
  }
4092
- actualTree = maybeActualTree;
4093
4077
  }
4094
- logger.logger.fail(`Update failed for ${oldId} in ${workspace}.`, error);
4078
+ return {
4079
+ ok: false,
4080
+ message: 'Update failed',
4081
+ cause: `Update failed for ${oldId} in ${workspace}${error ? '; ' + error : ''}`
4082
+ };
4095
4083
  }
4084
+ debug.debugFn('name:', name);
4085
+ debug.debugFn('increment: count', count + 1);
4096
4086
  if (++count >= limit) {
4097
4087
  cleanupInfoEntriesLoop();
4098
4088
  break infoEntriesLoop;
@@ -4112,30 +4102,83 @@ async function npmFix(pkgEnvDetails, {
4112
4102
  cleanupInfoEntriesLoop();
4113
4103
  }
4114
4104
  spinner?.stop();
4105
+
4106
+ // Or, did we change anything?
4115
4107
  return {
4116
4108
  ok: true,
4117
4109
  data: {
4118
4110
  fixed: true
4119
4111
  }
4120
- }; // true? did we actually change anything?
4112
+ };
4121
4113
  }
4122
4114
 
4123
- const {
4124
- OVERRIDES: OVERRIDES$2,
4125
- PNPM: PNPM$8
4126
- } = constants;
4127
- async function getActualTree(cwd = process.cwd()) {
4128
- // @npmcli/arborist DOES have partial support for pnpm structured node_modules
4129
- // folders. However, support is iffy resulting in unhappy path errors and hangs.
4130
- // So, to avoid the unhappy path, we restrict our usage to --dry-run loading
4131
- // of the node_modules folder.
4132
- const arb = new shadowNpmInject.Arborist({
4133
- path: cwd,
4134
- ...shadowNpmInject.SAFE_ARBORIST_REIFY_OPTIONS_OVERRIDES
4135
- });
4136
- return await arb.loadActual();
4137
- }
4138
- async function install(pkgEnvDetails, options) {
4115
+ async function getEnvRepoInfo(cwd) {
4116
+ // Lazily access constants.ENV.GITHUB_REPOSITORY.
4117
+ const {
4118
+ GITHUB_REPOSITORY
4119
+ } = constants.ENV;
4120
+ if (!GITHUB_REPOSITORY) {
4121
+ debug.debugFn('miss: GITHUB_REPOSITORY env var');
4122
+ }
4123
+ const ownerSlashRepo = GITHUB_REPOSITORY;
4124
+ const slashIndex = ownerSlashRepo.indexOf('/');
4125
+ if (slashIndex !== -1) {
4126
+ return {
4127
+ owner: ownerSlashRepo.slice(0, slashIndex),
4128
+ repo: ownerSlashRepo.slice(slashIndex + 1)
4129
+ };
4130
+ }
4131
+ return await gitRepoInfo(cwd);
4132
+ }
4133
+ async function getCiEnv() {
4134
+ const gitEmail = constants.ENV.SOCKET_CLI_GIT_USER_EMAIL;
4135
+ const gitUser = constants.ENV.SOCKET_CLI_GIT_USER_NAME;
4136
+ const githubToken = constants.ENV.SOCKET_CLI_GITHUB_TOKEN;
4137
+ const isCi = !!(constants.ENV.CI && gitEmail && gitUser && githubToken);
4138
+ if (!isCi) {
4139
+ return null;
4140
+ }
4141
+ const baseBranch = await getBaseGitBranch();
4142
+ if (!baseBranch) {
4143
+ return null;
4144
+ }
4145
+ const repoInfo = await getEnvRepoInfo();
4146
+ if (!repoInfo) {
4147
+ return null;
4148
+ }
4149
+ return {
4150
+ gitEmail,
4151
+ gitUser,
4152
+ githubToken,
4153
+ repoInfo,
4154
+ baseBranch,
4155
+ branchParser: createSocketBranchParser()
4156
+ };
4157
+ }
4158
+ async function getOpenPrsForEnvironment(env) {
4159
+ return env ? await getOpenSocketPrs(env.repoInfo.owner, env.repoInfo.repo, {
4160
+ author: env.gitUser
4161
+ }) : [];
4162
+ }
4163
+
4164
+ const CMD_NAME$1 = 'socket fix';
4165
+ function getAlertsMapOptions(options = {}) {
4166
+ return {
4167
+ __proto__: null,
4168
+ consolidate: true,
4169
+ nothrow: true,
4170
+ ...options,
4171
+ include: {
4172
+ __proto__: null,
4173
+ existing: true,
4174
+ unfixable: false,
4175
+ upgradable: false,
4176
+ ...options?.include
4177
+ }
4178
+ };
4179
+ }
4180
+
4181
+ async function install$1(pkgEnvDetails, options) {
4139
4182
  const {
4140
4183
  args,
4141
4184
  cwd,
@@ -4146,13 +4189,7 @@ async function install(pkgEnvDetails, options) {
4146
4189
  };
4147
4190
  try {
4148
4191
  await utils.runAgentInstall(pkgEnvDetails, {
4149
- args: [...(args ?? []),
4150
- // Enable pnpm updates to pnpm-lock.yaml in CI environments.
4151
- // https://pnpm.io/cli/install#--frozen-lockfile
4152
- '--no-frozen-lockfile',
4153
- // Enable a non-interactive pnpm install
4154
- // https://github.com/pnpm/pnpm/issues/6778
4155
- '--config.confirmModulesPurge=false'],
4192
+ args,
4156
4193
  spinner,
4157
4194
  stdio: debug.isDebug() ? 'inherit' : 'ignore'
4158
4195
  });
@@ -4160,78 +4197,34 @@ async function install(pkgEnvDetails, options) {
4160
4197
  } catch {}
4161
4198
  return null;
4162
4199
  }
4163
- async function pnpmFix(pkgEnvDetails, {
4164
- autoMerge,
4165
- cwd,
4166
- limit,
4167
- purls,
4168
- rangeStyle,
4169
- test,
4170
- testScript
4171
- }) {
4172
- // Lazily access constants.spinner.
4200
+ async function npmFix(pkgEnvDetails, options) {
4173
4201
  const {
4202
+ limit,
4203
+ purls,
4174
4204
  spinner
4175
- } = constants;
4176
- const {
4177
- pkgPath: rootPath
4178
- } = pkgEnvDetails;
4205
+ } = options;
4179
4206
  spinner?.start();
4180
4207
  const ciEnv = await getCiEnv();
4181
4208
  const openPrs = ciEnv ? await getOpenPrsForEnvironment(ciEnv) : [];
4182
- let count = 0;
4183
4209
  let actualTree;
4184
- const lockfilePath = path.join(rootPath, 'pnpm-lock.yaml');
4185
- let lockfileContent = await utils.readPnpmLockfile(lockfilePath);
4186
-
4187
- // If pnpm-lock.yaml does NOT exist then install with pnpm to create it.
4188
- if (!lockfileContent) {
4189
- const maybeActualTree = await install(pkgEnvDetails, {
4190
- cwd,
4191
- spinner
4192
- });
4193
- const maybeLockfileContent = maybeActualTree ? await utils.readPnpmLockfile(lockfilePath) : null;
4194
- if (maybeActualTree) {
4195
- actualTree = maybeActualTree;
4196
- lockfileContent = maybeLockfileContent;
4197
- }
4198
- }
4199
- let lockfile = utils.parsePnpmLockfile(lockfileContent);
4200
- // Update pnpm-lock.yaml if its version is older than what the installed pnpm
4201
- // produces.
4202
- if (lockfileContent && pkgEnvDetails.agentVersion.major >= 10 && (utils.parsePnpmLockfileVersion(lockfile?.lockfileVersion)?.major ?? 0) <= 6) {
4203
- const maybeActualTree = await install(pkgEnvDetails, {
4204
- args: ['--lockfile-only'],
4205
- cwd,
4206
- spinner
4207
- });
4208
- const maybeLockfileContent = maybeActualTree ? await utils.readPnpmLockfile(lockfilePath) : null;
4209
- if (maybeActualTree && maybeLockfileContent) {
4210
- actualTree = maybeActualTree;
4211
- lockfileContent = maybeLockfileContent;
4212
- lockfile = utils.parsePnpmLockfile(lockfileContent);
4213
- } else {
4214
- lockfile = null;
4215
- }
4216
- }
4217
-
4218
- // Exit early if pnpm-lock.yaml is not found or usable.
4219
- // Check !lockfileContent to make TypeScript happy.
4220
- if (!lockfile || !lockfileContent) {
4221
- spinner?.stop();
4222
- return {
4223
- ok: false,
4224
- message: 'Missing lockfile',
4225
- cause: 'Required pnpm-lock.yaml not found or usable'
4226
- };
4227
- }
4228
4210
  let alertsMap;
4229
4211
  try {
4230
- alertsMap = purls.length ? await utils.getAlertsMapFromPurls(purls, getAlertsMapOptions({
4231
- limit: Math.max(limit, openPrs.length)
4232
- })) : await utils.getAlertsMapFromPnpmLockfile(lockfile, getAlertsMapOptions({
4233
- limit: Math.max(limit, openPrs.length)
4234
- }));
4212
+ if (purls.length) {
4213
+ alertsMap = await utils.getAlertsMapFromPurls(purls, getAlertsMapOptions({
4214
+ limit: Math.max(limit, openPrs.length)
4215
+ }));
4216
+ } else {
4217
+ const arb = new shadowNpmInject.Arborist({
4218
+ path: pkgEnvDetails.pkgPath,
4219
+ ...shadowNpmInject.SAFE_ARBORIST_REIFY_OPTIONS_OVERRIDES
4220
+ });
4221
+ actualTree = await arb.reify();
4222
+ // Calling arb.reify() creates the arb.diff object, nulls-out arb.idealTree,
4223
+ // and populates arb.actualTree.
4224
+ alertsMap = await shadowNpmInject.getAlertsMapFromArborist(arb, getAlertsMapOptions({
4225
+ limit: Math.max(limit, openPrs.length)
4226
+ }));
4227
+ }
4235
4228
  } catch (e) {
4236
4229
  spinner?.stop();
4237
4230
  debug.debugFn('catch: PURL API\n', e);
@@ -4241,483 +4234,239 @@ async function pnpmFix(pkgEnvDetails, {
4241
4234
  cause: e?.message || 'Unknown Socket batch PURL API error.'
4242
4235
  };
4243
4236
  }
4244
- const infoByPartialPurl = utils.getCveInfoFromAlertsMap(alertsMap, {
4245
- limit: Math.max(limit, openPrs.length)
4246
- });
4247
- if (!infoByPartialPurl) {
4248
- spinner?.stop();
4249
- logger.logger.info('No fixable vulns found.');
4250
- return {
4251
- ok: true,
4252
- data: {
4253
- fixed: false
4237
+ let revertData;
4238
+ return await agentFix(pkgEnvDetails, actualTree, alertsMap, install$1, {
4239
+ async beforeInstall(editablePkgJson) {
4240
+ revertData = {
4241
+ ...(editablePkgJson.content.dependencies && {
4242
+ dependencies: {
4243
+ ...editablePkgJson.content.dependencies
4244
+ }
4245
+ }),
4246
+ ...(editablePkgJson.content.optionalDependencies && {
4247
+ optionalDependencies: {
4248
+ ...editablePkgJson.content.optionalDependencies
4249
+ }
4250
+ }),
4251
+ ...(editablePkgJson.content.peerDependencies && {
4252
+ peerDependencies: {
4253
+ ...editablePkgJson.content.peerDependencies
4254
+ }
4255
+ })
4256
+ };
4257
+ },
4258
+ async revertInstall(editablePkgJson) {
4259
+ if (revertData) {
4260
+ editablePkgJson.update(revertData);
4254
4261
  }
4255
- };
4262
+ }
4263
+ }, ciEnv, openPrs, options);
4264
+ }
4265
+
4266
+ async function outputFixResult(result, outputKind) {
4267
+ if (!result.ok) {
4268
+ process.exitCode = result.code ?? 1;
4256
4269
  }
4257
- if (debug.isDebug()) {
4258
- debug.debugFn('found: cves for', Array.from(infoByPartialPurl.keys()));
4270
+ if (outputKind === 'json') {
4271
+ logger.logger.log(utils.serializeResultJson(result));
4272
+ return;
4273
+ }
4274
+ if (!result.ok) {
4275
+ logger.logger.fail(utils.failMsgWithBadge(result.message, result.cause));
4276
+ return;
4259
4277
  }
4278
+ logger.logger.log('');
4279
+ logger.logger.success('Finished!');
4280
+ }
4260
4281
 
4261
- // Lazily access constants.packumentCache.
4282
+ const {
4283
+ OVERRIDES: OVERRIDES$1,
4284
+ PNPM: PNPM$7
4285
+ } = constants;
4286
+ async function install(pkgEnvDetails, options) {
4262
4287
  const {
4263
- packumentCache
4264
- } = constants;
4265
- const workspacePkgJsonPaths = await utils.globWorkspace(pkgEnvDetails.agent, rootPath);
4266
- const pkgJsonPaths = [...workspacePkgJsonPaths,
4267
- // Process the workspace root last since it will add an override to package.json.
4268
- pkgEnvDetails.editablePkgJson.filename];
4269
- const sortedInfoEntries = Array.from(infoByPartialPurl.entries()).sort((a, b) => sorts.naturalCompare(a[0], b[0]));
4270
- const cleanupInfoEntriesLoop = () => {
4271
- logger.logger.dedent();
4272
- spinner?.dedent();
4273
- packumentCache.clear();
4274
- };
4275
- const handleInstallFail = () => {
4276
- cleanupInfoEntriesLoop();
4277
- return {
4278
- ok: false,
4279
- message: 'Install failed',
4280
- cause: `Unexpected condition: ${pkgEnvDetails.agent} install failed`
4281
- };
4288
+ args,
4289
+ cwd,
4290
+ spinner
4291
+ } = {
4292
+ __proto__: null,
4293
+ ...options
4282
4294
  };
4283
- spinner?.stop();
4284
- infoEntriesLoop: for (let i = 0, {
4285
- length
4286
- } = sortedInfoEntries; i < length; i += 1) {
4287
- const isLastInfoEntry = i === length - 1;
4288
- const infoEntry = sortedInfoEntries[i];
4289
- const partialPurlObj = utils.getPurlObject(infoEntry[0]);
4290
- const name = packages.resolvePackageName(partialPurlObj);
4291
- const infos = Array.from(infoEntry[1].values());
4292
- if (!infos.length) {
4293
- continue infoEntriesLoop;
4294
- }
4295
- logger.logger.log(`Processing vulns for ${name}:`);
4296
- logger.logger.indent();
4297
- spinner?.indent();
4298
- if (registry.getManifestData(partialPurlObj.type, name)) {
4299
- debug.debugFn(`found: Socket Optimize variant for ${name}`);
4300
- }
4301
- // eslint-disable-next-line no-await-in-loop
4302
- const packument = await packages.fetchPackagePackument(name);
4303
- if (!packument) {
4304
- logger.logger.warn(`Unexpected condition: No packument found for ${name}.\n`);
4305
- cleanupInfoEntriesLoop();
4306
- continue infoEntriesLoop;
4307
- }
4308
- const activeBranches = getActiveBranchesForPackage(ciEnv, infoEntry[0], openPrs);
4309
- const availableVersions = Object.keys(packument.versions);
4310
- const warningsForAfter = new Set();
4311
-
4312
- // eslint-disable-next-line no-unused-labels
4313
- for (let j = 0, {
4314
- length: length_j
4315
- } = pkgJsonPaths; j < length_j; j += 1) {
4316
- const isLastPkgJsonPath = j === length_j - 1;
4317
- const pkgJsonPath = pkgJsonPaths[j];
4318
- const pkgPath = path.dirname(pkgJsonPath);
4319
- const isWorkspaceRoot = pkgJsonPath === pkgEnvDetails.editablePkgJson.filename;
4320
- const workspace = isWorkspaceRoot ? 'root' : path.relative(rootPath, pkgPath);
4321
- const branchWorkspace = ciEnv ? getSocketBranchWorkspaceComponent(workspace) : '';
4322
-
4323
- // actualTree may not be defined on the first iteration of pkgJsonPathsLoop.
4324
- if (!actualTree) {
4325
- if (!ciEnv) {
4326
- // eslint-disable-next-line no-await-in-loop
4327
- await utils.removeNodeModules(cwd);
4328
- }
4329
- const maybeActualTree = ciEnv && fs$1.existsSync(path.join(rootPath, 'node_modules')) ?
4330
- // eslint-disable-next-line no-await-in-loop
4331
- await getActualTree(cwd) :
4332
- // eslint-disable-next-line no-await-in-loop
4333
- await install(pkgEnvDetails, {
4334
- cwd,
4335
- spinner
4336
- });
4337
- const maybeLockfileContent = maybeActualTree ?
4338
- // eslint-disable-next-line no-await-in-loop
4339
- await utils.readPnpmLockfile(lockfilePath) : null;
4340
- if (maybeActualTree && maybeLockfileContent) {
4341
- actualTree = maybeActualTree;
4342
- lockfileContent = maybeLockfileContent;
4343
- }
4344
- }
4345
- if (!actualTree) {
4346
- // Exit early if install fails.
4347
- return handleInstallFail();
4348
- }
4349
- const oldVersions = arrays.arrayUnique(shadowNpmInject.findPackageNodes(actualTree, name).map(n => n.version).filter(Boolean));
4350
- if (!oldVersions.length) {
4351
- debug.debugFn(`skip: ${name} not found\n`);
4352
- // Skip to next package.
4353
- cleanupInfoEntriesLoop();
4354
- continue infoEntriesLoop;
4355
- }
4356
-
4357
- // Always re-read the editable package.json to avoid stale mutations
4358
- // across iterations.
4359
- // eslint-disable-next-line no-await-in-loop
4360
- const editablePkgJson = await packages.readPackageJson(pkgJsonPath, {
4361
- editable: true
4362
- });
4363
- const fixedVersions = new Set();
4364
-
4365
- // Get current overrides for revert logic.
4366
- const oldPnpmSection = editablePkgJson.content[PNPM$8];
4367
- const oldOverrides = oldPnpmSection?.[OVERRIDES$2];
4368
- let hasAnnouncedWorkspace = false;
4369
- let workspaceLogCallCount = logger.logger.logCallCount;
4370
- if (debug.isDebug()) {
4371
- debug.debugFn(`check: workspace ${workspace}`);
4372
- hasAnnouncedWorkspace = true;
4373
- workspaceLogCallCount = logger.logger.logCallCount;
4374
- }
4375
- oldVersionsLoop: for (const oldVersion of oldVersions) {
4376
- const oldId = `${name}@${oldVersion}`;
4377
- const oldPurl = utils.idToPurl(oldId, partialPurlObj.type);
4378
- const node = shadowNpmInject.findPackageNode(actualTree, name, oldVersion);
4379
- if (!node) {
4380
- debug.debugFn(`skip: ${oldId} not found`);
4381
- continue oldVersionsLoop;
4382
- }
4383
- infosLoop: for (const {
4384
- firstPatchedVersionIdentifier,
4385
- vulnerableVersionRange
4386
- } of infos) {
4387
- const newVersion = shadowNpmInject.findBestPatchVersion(node, availableVersions, vulnerableVersionRange);
4388
- const newVersionPackument = newVersion ? packument.versions[newVersion] : undefined;
4389
- if (!(newVersion && newVersionPackument)) {
4390
- warningsForAfter.add(`${oldId} not updated: requires >=${firstPatchedVersionIdentifier}`);
4391
- continue infosLoop;
4392
- }
4393
- if (fixedVersions.has(newVersion)) {
4394
- continue infosLoop;
4395
- }
4396
- if (vendor.semverExports.gte(oldVersion, newVersion)) {
4397
- debug.debugFn(`skip: ${oldId} is >= ${newVersion}`);
4398
- continue infosLoop;
4399
- }
4400
- if (activeBranches.find(b => b.workspace === branchWorkspace && b.newVersion === newVersion)) {
4401
- debug.debugFn(`skip: open PR found for ${name}@${newVersion}`);
4402
- if (++count >= limit) {
4403
- cleanupInfoEntriesLoop();
4404
- break infoEntriesLoop;
4405
- }
4406
- continue infosLoop;
4407
- }
4408
- const overrideKey = `${name}@${vulnerableVersionRange}`;
4409
- const newVersionRange = utils.applyRange(oldOverrides?.[overrideKey] ?? oldVersion, newVersion, rangeStyle);
4410
- const newId = `${name}@${newVersionRange}`;
4411
- const updateOverrides = isWorkspaceRoot ? {
4412
- [PNPM$8]: {
4413
- ...oldPnpmSection,
4414
- [OVERRIDES$2]: {
4415
- ...oldOverrides,
4416
- [overrideKey]: newVersionRange
4417
- }
4418
- }
4419
- } : undefined;
4420
- const revertOverrides = isWorkspaceRoot ? {
4421
- [PNPM$8]: oldPnpmSection ? {
4422
- ...oldPnpmSection,
4423
- [OVERRIDES$2]: oldOverrides && Object.keys(oldOverrides).length > 1 ? {
4424
- ...oldOverrides,
4425
- [overrideKey]: undefined
4426
- } : undefined
4427
- } : undefined
4428
- } : {};
4429
- const revertData = {
4430
- ...revertOverrides,
4431
- ...(editablePkgJson.content.dependencies && {
4432
- dependencies: {
4433
- ...editablePkgJson.content.dependencies
4434
- }
4435
- }),
4436
- ...(editablePkgJson.content.optionalDependencies && {
4437
- optionalDependencies: {
4438
- ...editablePkgJson.content.optionalDependencies
4439
- }
4440
- }),
4441
- ...(editablePkgJson.content.peerDependencies && {
4442
- peerDependencies: {
4443
- ...editablePkgJson.content.peerDependencies
4444
- }
4445
- })
4446
- };
4447
- if (updateOverrides) {
4448
- // Update overrides in the root package.json so that when `pnpm install`
4449
- // generates pnpm-lock.yaml it updates transitive dependencies too.
4450
- editablePkgJson.update(updateOverrides);
4451
- }
4452
- shadowNpmInject.updatePackageJsonFromNode(editablePkgJson, actualTree, node, newVersion, rangeStyle);
4453
- // eslint-disable-next-line no-await-in-loop
4454
- if (!(await editablePkgJson.save({
4455
- ignoreWhitespace: true
4456
- }))) {
4457
- debug.debugFn(`skip: ${workspace}/package.json unchanged`);
4458
- // Reset things just in case.
4459
- if (ciEnv) {
4460
- // eslint-disable-next-line no-await-in-loop
4461
- await gitResetAndClean(ciEnv.baseBranch, cwd);
4462
- }
4463
- continue infosLoop;
4464
- }
4465
- if (!hasAnnouncedWorkspace) {
4466
- hasAnnouncedWorkspace = true;
4467
- workspaceLogCallCount = logger.logger.logCallCount;
4468
- }
4469
- spinner?.start();
4470
- spinner?.info(`Installing ${newId} in ${workspace}.`);
4471
- let error;
4472
- let errored = false;
4473
- try {
4474
- const revertOverridesContent = utils.extractOverridesFromPnpmLockfileContent(lockfileContent);
4475
- // eslint-disable-next-line no-await-in-loop
4476
- const maybeActualTree = await install(pkgEnvDetails, {
4477
- cwd,
4478
- spinner
4479
- });
4480
- const maybeLockfileContent = maybeActualTree ?
4481
- // eslint-disable-next-line no-await-in-loop
4482
- await utils.readPnpmLockfile(lockfilePath) : null;
4483
- if (maybeActualTree && maybeLockfileContent) {
4484
- actualTree = maybeActualTree;
4485
- lockfileContent = maybeLockfileContent;
4486
- // Revert overrides metadata in package.json now that pnpm-lock.yaml
4487
- // has been updated.
4488
- editablePkgJson.update(revertOverrides);
4489
- // eslint-disable-next-line no-await-in-loop
4490
- await editablePkgJson.save({
4491
- ignoreWhitespace: true
4492
- });
4493
- const updatedOverridesContent = utils.extractOverridesFromPnpmLockfileContent(lockfileContent);
4494
- if (updatedOverridesContent) {
4495
- lockfileContent = lockfileContent.replace(updatedOverridesContent, revertOverridesContent);
4496
- // eslint-disable-next-line no-await-in-loop
4497
- await fs$1.promises.writeFile(lockfilePath, lockfileContent, 'utf8');
4498
- }
4499
- if (test) {
4500
- spinner?.info(`Testing ${newId} in ${workspace}.`);
4501
- // eslint-disable-next-line no-await-in-loop
4502
- await npm.runScript(testScript, [], {
4503
- spinner,
4504
- stdio: 'ignore'
4505
- });
4506
- }
4507
- spinner?.success(`Fixed ${name} in ${workspace}.`);
4508
- fixedVersions.add(newVersion);
4509
- } else {
4510
- errored = true;
4511
- }
4512
- } catch (e) {
4513
- error = e;
4514
- errored = true;
4515
- }
4516
- spinner?.stop();
4517
-
4518
- // Check repoInfo to make TypeScript happy.
4519
- if (!errored && ciEnv?.repoInfo) {
4520
- try {
4521
- // eslint-disable-next-line no-await-in-loop
4522
- const result = await gitUnstagedModifiedFiles(cwd);
4523
- if (!result.ok) {
4524
- logger.logger.warn('Unexpected condition: Nothing to commit, skipping PR creation.');
4525
- continue;
4526
- }
4527
- const moddedFilepaths = result.data.filter(p => {
4528
- const basename = path.basename(p);
4529
- return basename === 'package.json' || basename === 'pnpm-lock.yaml';
4530
- });
4531
- if (!moddedFilepaths.length) {
4532
- logger.logger.warn('Unexpected condition: Nothing to commit, skipping PR creation.');
4533
- continue infosLoop;
4534
- }
4535
- const branch = getSocketBranchName(oldPurl, newVersion, workspace);
4536
- let skipPr = false;
4537
- if (
4538
- // eslint-disable-next-line no-await-in-loop
4539
- await prExistForBranch(ciEnv.repoInfo.owner, ciEnv.repoInfo.repo, branch)) {
4540
- skipPr = true;
4541
- debug.debugFn(`skip: branch "${branch}" exists`);
4542
- }
4543
- // eslint-disable-next-line no-await-in-loop
4544
- else if (await gitRemoteBranchExists(branch, cwd)) {
4545
- skipPr = true;
4546
- debug.debugFn(`skip: remote branch "${branch}" exists`);
4547
- } else if (
4548
- // eslint-disable-next-line no-await-in-loop
4549
- !(await gitCreateAndPushBranch(branch, getSocketCommitMessage(oldPurl, newVersion, workspace), moddedFilepaths, {
4550
- cwd,
4551
- email: ciEnv.gitEmail,
4552
- user: ciEnv.gitUser
4553
- }))) {
4554
- skipPr = true;
4555
- logger.logger.warn('Unexpected condition: Push failed, skipping PR creation.');
4556
- }
4557
- if (skipPr) {
4558
- // eslint-disable-next-line no-await-in-loop
4559
- await gitResetAndClean(ciEnv.baseBranch, cwd);
4560
- // eslint-disable-next-line no-await-in-loop
4561
- const maybeActualTree = await install(pkgEnvDetails, {
4562
- cwd,
4563
- spinner
4564
- });
4565
- const maybeLockfileContent = maybeActualTree ?
4566
- // eslint-disable-next-line no-await-in-loop
4567
- await utils.readPnpmLockfile(lockfilePath) : null;
4568
- if (maybeActualTree && maybeLockfileContent) {
4569
- actualTree = maybeActualTree;
4570
- lockfileContent = maybeLockfileContent;
4571
- continue infosLoop;
4572
- }
4573
- // Exit early if install fails.
4574
- return handleInstallFail();
4575
- }
4576
-
4577
- // eslint-disable-next-line no-await-in-loop
4578
- await Promise.allSettled([setGitRemoteGithubRepoUrl(ciEnv.repoInfo.owner, ciEnv.repoInfo.repo, ciEnv.githubToken, cwd), cleanupOpenPrs(ciEnv.repoInfo.owner, ciEnv.repoInfo.repo, {
4579
- newVersion,
4580
- purl: oldPurl,
4581
- workspace
4582
- })]);
4583
- // eslint-disable-next-line no-await-in-loop
4584
- const prResponse = await openPr(ciEnv.repoInfo.owner, ciEnv.repoInfo.repo, branch, oldPurl, newVersion, {
4585
- baseBranch: ciEnv.baseBranch,
4586
- cwd,
4587
- workspace
4588
- });
4589
- if (prResponse) {
4590
- const {
4591
- data
4592
- } = prResponse;
4593
- const prRef = `PR #${data.number}`;
4594
- logger.logger.success(`Opened ${prRef}.`);
4595
- if (autoMerge) {
4596
- logger.logger.indent();
4597
- spinner?.indent();
4598
- // eslint-disable-next-line no-await-in-loop
4599
- const {
4600
- details,
4601
- enabled
4602
- } = await enablePrAutoMerge(data);
4603
- if (enabled) {
4604
- logger.logger.info(`Auto-merge enabled for ${prRef}.`);
4605
- } else {
4606
- const message = `Failed to enable auto-merge for ${prRef}${details ? `:\n${details.map(d => ` - ${d}`).join('\n')}` : '.'}`;
4607
- logger.logger.error(message);
4608
- }
4609
- logger.logger.dedent();
4610
- spinner?.dedent();
4611
- }
4612
- }
4613
- } catch (e) {
4614
- error = e;
4615
- errored = true;
4295
+ try {
4296
+ await utils.runAgentInstall(pkgEnvDetails, {
4297
+ args: [...(args ?? []),
4298
+ // Enable pnpm updates to pnpm-lock.yaml in CI environments.
4299
+ // https://pnpm.io/cli/install#--frozen-lockfile
4300
+ '--no-frozen-lockfile',
4301
+ // Enable a non-interactive pnpm install
4302
+ // https://github.com/pnpm/pnpm/issues/6778
4303
+ '--config.confirmModulesPurge=false'],
4304
+ spinner,
4305
+ stdio: debug.isDebug() ? 'inherit' : 'ignore'
4306
+ });
4307
+ return await getActualTree(cwd);
4308
+ } catch {}
4309
+ return null;
4310
+ }
4311
+ async function pnpmFix(pkgEnvDetails, options) {
4312
+ const {
4313
+ cwd,
4314
+ limit,
4315
+ purls,
4316
+ spinner
4317
+ } = options;
4318
+ spinner?.start();
4319
+ let actualTree;
4320
+ let {
4321
+ lockSrc
4322
+ } = pkgEnvDetails;
4323
+ let lockfile = utils.parsePnpmLockfile(lockSrc);
4324
+ // Update pnpm-lock.yaml if its version is older than what the installed pnpm
4325
+ // produces.
4326
+ if (pkgEnvDetails.agentVersion.major >= 10 && (utils.parsePnpmLockfileVersion(lockfile?.lockfileVersion)?.major ?? 0) <= 6) {
4327
+ const maybeActualTree = await install(pkgEnvDetails, {
4328
+ args: ['--lockfile-only'],
4329
+ cwd,
4330
+ spinner
4331
+ });
4332
+ const maybeLockSrc = maybeActualTree ? await utils.readLockfile(pkgEnvDetails.lockPath) : null;
4333
+ if (maybeActualTree && maybeLockSrc) {
4334
+ actualTree = maybeActualTree;
4335
+ lockSrc = maybeLockSrc;
4336
+ lockfile = utils.parsePnpmLockfile(lockSrc);
4337
+ } else {
4338
+ lockfile = null;
4339
+ }
4340
+ }
4341
+
4342
+ // Exit early if pnpm-lock.yaml is not found or usable.
4343
+ // Check !lockSrc to make TypeScript happy.
4344
+ if (!lockfile || !lockSrc) {
4345
+ spinner?.stop();
4346
+ return {
4347
+ ok: false,
4348
+ message: 'Missing lockfile',
4349
+ cause: 'Required pnpm-lock.yaml not found or usable'
4350
+ };
4351
+ }
4352
+ const ciEnv = await getCiEnv();
4353
+ const openPrs = ciEnv ? await getOpenPrsForEnvironment(ciEnv) : [];
4354
+ let alertsMap;
4355
+ try {
4356
+ alertsMap = purls.length ? await utils.getAlertsMapFromPurls(purls, getAlertsMapOptions({
4357
+ limit: Math.max(limit, openPrs.length)
4358
+ })) : await utils.getAlertsMapFromPnpmLockfile(lockfile, getAlertsMapOptions({
4359
+ limit: Math.max(limit, openPrs.length)
4360
+ }));
4361
+ } catch (e) {
4362
+ spinner?.stop();
4363
+ debug.debugFn('catch: PURL API\n', e);
4364
+ return {
4365
+ ok: false,
4366
+ message: 'API Error',
4367
+ cause: e?.message || 'Unknown Socket batch PURL API error.'
4368
+ };
4369
+ }
4370
+ let revertData;
4371
+ let revertOverrides;
4372
+ let revertOverridesSrc;
4373
+ return await agentFix(pkgEnvDetails, actualTree, alertsMap, install, {
4374
+ async beforeInstall(editablePkgJson, name, oldVersion, newVersion, vulnerableVersionRange, options) {
4375
+ const isWorkspaceRoot = editablePkgJson.path === pkgEnvDetails.editablePkgJson.filename;
4376
+ // Get current overrides for revert logic.
4377
+ const {
4378
+ overrides: oldOverrides
4379
+ } = getOverridesDataPnpm(pkgEnvDetails, editablePkgJson.content);
4380
+ const oldPnpmSection = editablePkgJson.content[PNPM$7];
4381
+ const overrideKey = `${name}@${vulnerableVersionRange}`;
4382
+ revertOverrides = undefined;
4383
+ revertOverridesSrc = utils.extractOverridesFromPnpmLockSrc(lockSrc);
4384
+ if (isWorkspaceRoot) {
4385
+ revertOverrides = {
4386
+ [PNPM$7]: oldPnpmSection ? {
4387
+ ...oldPnpmSection,
4388
+ [OVERRIDES$1]: objects.hasKeys(oldOverrides) ? {
4389
+ ...oldOverrides,
4390
+ [overrideKey]: undefined
4391
+ } : undefined
4392
+ } : undefined
4393
+ };
4394
+ // Update overrides in the root package.json so that when `pnpm install`
4395
+ // generates pnpm-lock.yaml it updates transitive dependencies too.
4396
+ editablePkgJson.update({
4397
+ [PNPM$7]: {
4398
+ ...oldPnpmSection,
4399
+ [OVERRIDES$1]: {
4400
+ ...oldOverrides,
4401
+ [overrideKey]: utils.applyRange(oldOverrides?.[overrideKey] ?? oldVersion, newVersion, options.rangeStyle)
4616
4402
  }
4617
4403
  }
4618
- if (ciEnv) {
4619
- spinner?.start();
4620
- // eslint-disable-next-line no-await-in-loop
4621
- await gitResetAndClean(ciEnv.baseBranch, cwd);
4622
- // eslint-disable-next-line no-await-in-loop
4623
- const maybeActualTree = await install(pkgEnvDetails, {
4624
- cwd,
4625
- spinner
4626
- });
4627
- const maybeLockfileContent = maybeActualTree ?
4628
- // eslint-disable-next-line no-await-in-loop
4629
- await utils.readPnpmLockfile(lockfilePath) : null;
4630
- spinner?.stop();
4631
- if (maybeActualTree) {
4632
- actualTree = maybeActualTree;
4633
- lockfileContent = maybeLockfileContent;
4634
- } else {
4635
- errored = true;
4636
- }
4404
+ });
4405
+ }
4406
+ revertData = {
4407
+ ...revertOverrides,
4408
+ ...(editablePkgJson.content.dependencies && {
4409
+ dependencies: {
4410
+ ...editablePkgJson.content.dependencies
4637
4411
  }
4638
- if (errored) {
4639
- if (!ciEnv) {
4640
- spinner?.start();
4641
- editablePkgJson.update(revertData);
4642
- // eslint-disable-next-line no-await-in-loop
4643
- await Promise.all([utils.removeNodeModules(cwd), editablePkgJson.save({
4644
- ignoreWhitespace: true
4645
- })]);
4646
- // eslint-disable-next-line no-await-in-loop
4647
- const maybeActualTree = await install(pkgEnvDetails, {
4648
- cwd,
4649
- spinner
4650
- });
4651
- const maybeLockfileContent = maybeActualTree ?
4652
- // eslint-disable-next-line no-await-in-loop
4653
- await utils.readPnpmLockfile(lockfilePath) : null;
4654
- spinner?.stop();
4655
- if (maybeActualTree) {
4656
- actualTree = maybeActualTree;
4657
- lockfileContent = maybeLockfileContent;
4658
- } else {
4659
- // Exit early if install fails.
4660
- return handleInstallFail();
4661
- }
4662
- }
4663
- return {
4664
- ok: false,
4665
- message: 'Update failed',
4666
- cause: `Update failed for ${oldId} in ${workspace}${error ? '; ' + error : ''}`
4667
- };
4412
+ }),
4413
+ ...(editablePkgJson.content.optionalDependencies && {
4414
+ optionalDependencies: {
4415
+ ...editablePkgJson.content.optionalDependencies
4668
4416
  }
4669
- debug.debugFn('name:', name);
4670
- debug.debugFn('increment: count', count + 1);
4671
- if (++count >= limit) {
4672
- cleanupInfoEntriesLoop();
4673
- break infoEntriesLoop;
4417
+ }),
4418
+ ...(editablePkgJson.content.peerDependencies && {
4419
+ peerDependencies: {
4420
+ ...editablePkgJson.content.peerDependencies
4674
4421
  }
4675
- }
4422
+ })
4423
+ };
4424
+ },
4425
+ async afterInstall(editablePkgJson) {
4426
+ if (revertOverrides) {
4427
+ // Revert overrides metadata in package.json now that pnpm-lock.yaml
4428
+ // has been updated.
4429
+ editablePkgJson.update(revertOverrides);
4676
4430
  }
4677
- if (!isLastPkgJsonPath && logger.logger.logCallCount > workspaceLogCallCount) {
4678
- logger.logger.logNewline();
4431
+ await editablePkgJson.save({
4432
+ ignoreWhitespace: true
4433
+ });
4434
+ const updatedOverridesContent = utils.extractOverridesFromPnpmLockSrc(lockSrc);
4435
+ if (updatedOverridesContent && revertOverridesSrc) {
4436
+ lockSrc = lockSrc.replace(updatedOverridesContent, revertOverridesSrc);
4437
+ await fs$1.promises.writeFile(pkgEnvDetails.lockPath, lockSrc, 'utf8');
4438
+ }
4439
+ },
4440
+ async revertInstall(editablePkgJson) {
4441
+ if (revertData) {
4442
+ editablePkgJson.update(revertData);
4679
4443
  }
4680
4444
  }
4681
- for (const warningText of warningsForAfter) {
4682
- logger.logger.warn(warningText);
4683
- }
4684
- if (!isLastInfoEntry) {
4685
- logger.logger.logNewline();
4686
- }
4687
- cleanupInfoEntriesLoop();
4688
- }
4689
- spinner?.stop();
4690
-
4691
- // Or, did we change anything?
4692
- return {
4693
- ok: true,
4694
- data: {
4695
- fixed: true
4696
- }
4697
- };
4445
+ }, ciEnv, openPrs, options);
4698
4446
  }
4699
4447
 
4700
4448
  const {
4701
- NPM: NPM$8,
4702
- PNPM: PNPM$7
4449
+ NPM: NPM$7,
4450
+ PNPM: PNPM$6
4703
4451
  } = constants;
4704
- async function runFix({
4452
+ async function handleFix({
4705
4453
  autoMerge,
4706
4454
  cwd,
4707
4455
  limit,
4456
+ outputKind,
4708
4457
  purls,
4709
4458
  rangeStyle,
4710
4459
  test,
4711
4460
  testScript
4712
4461
  }) {
4713
- const result = await utils.detectAndValidatePackageEnvironment(cwd, {
4462
+ const pkgEnvResult = await utils.detectAndValidatePackageEnvironment(cwd, {
4714
4463
  cmdName: CMD_NAME$1,
4715
4464
  logger: logger.logger
4716
4465
  });
4717
- if (!result.ok) {
4718
- return result;
4466
+ if (!pkgEnvResult.ok) {
4467
+ return pkgEnvResult;
4719
4468
  }
4720
- const pkgEnvDetails = result.data;
4469
+ const pkgEnvDetails = pkgEnvResult.data;
4721
4470
  if (!pkgEnvDetails) {
4722
4471
  return {
4723
4472
  ok: false,
@@ -4725,55 +4474,30 @@ async function runFix({
4725
4474
  cause: `No valid package environment was found in given cwd (${cwd})`
4726
4475
  };
4727
4476
  }
4728
- logger.logger.info(`Fixing packages for ${pkgEnvDetails.agent}.\n`);
4477
+ logger.logger.info(`Fixing packages for ${pkgEnvDetails.agent} v${pkgEnvDetails.agentVersion}.\n`);
4729
4478
  const {
4730
4479
  agent
4731
4480
  } = pkgEnvDetails;
4732
- if (agent === NPM$8) {
4733
- return await npmFix(pkgEnvDetails, {
4734
- autoMerge,
4735
- cwd,
4736
- limit,
4737
- purls,
4738
- rangeStyle,
4739
- test,
4740
- testScript
4741
- });
4742
- } else if (agent === PNPM$7) {
4743
- return await pnpmFix(pkgEnvDetails, {
4744
- autoMerge,
4745
- cwd,
4746
- limit,
4747
- purls,
4748
- rangeStyle,
4749
- test,
4750
- testScript
4751
- });
4752
- } else {
4481
+ if (agent !== NPM$7 && agent !== PNPM$6) {
4753
4482
  return {
4754
4483
  ok: false,
4755
4484
  message: 'Not supported',
4756
4485
  cause: `${agent} is not supported by this command at the moment.`
4757
4486
  };
4758
4487
  }
4759
- }
4760
4488
 
4761
- async function handleFix({
4762
- autoMerge,
4763
- cwd,
4764
- limit,
4765
- outputKind,
4766
- purls,
4767
- rangeStyle,
4768
- test,
4769
- testScript
4770
- }) {
4771
- const result = await runFix({
4489
+ // Lazily access spinner.
4490
+ const {
4491
+ spinner
4492
+ } = constants;
4493
+ const fixer = agent === NPM$7 ? npmFix : pnpmFix;
4494
+ const result = await fixer(pkgEnvDetails, {
4772
4495
  autoMerge,
4773
4496
  cwd,
4774
4497
  limit,
4775
4498
  purls,
4776
4499
  rangeStyle,
4500
+ spinner,
4777
4501
  test,
4778
4502
  testScript
4779
4503
  });
@@ -4869,25 +4593,16 @@ async function run$H(argv, importMeta, {
4869
4593
  json,
4870
4594
  markdown
4871
4595
  } = cli.flags;
4872
- let {
4873
- autoMerge,
4874
- rangeStyle,
4875
- test
4876
- } = cli.flags;
4877
4596
  const outputKind = utils.getOutputKind(json, markdown);
4878
- let [cwd = '.'] = cli.input;
4879
- // Note: path.resolve vs .join:
4880
- // If given path is absolute then cwd should not affect it.
4881
- cwd = path.resolve(process.cwd(), cwd);
4882
- if (autopilot) {
4883
- autoMerge = true;
4884
- test = true;
4597
+ let rangeStyle = cli.flags['rangeStyle'];
4598
+ if (!rangeStyle) {
4599
+ rangeStyle = 'preserve';
4885
4600
  }
4886
4601
  const wasValidInput = utils.checkCommandInput(outputKind, {
4887
- test: utils.RangeStyles.includes(cli.flags['rangeStyle']),
4602
+ test: utils.RangeStyles.includes(rangeStyle),
4888
4603
  message: `Expecting range style of ${arrays.joinOr(utils.RangeStyles)}`,
4889
4604
  pass: 'ok',
4890
- fail: 'missing'
4605
+ fail: 'invalid'
4891
4606
  });
4892
4607
  if (!wasValidInput) {
4893
4608
  return;
@@ -4896,20 +4611,28 @@ async function run$H(argv, importMeta, {
4896
4611
  logger.logger.log(DRY_RUN_NOT_SAVING);
4897
4612
  return;
4898
4613
  }
4899
- let purls = Array.isArray(cli.flags['purl']) ? cli.flags['purl'] : [];
4900
- purls = purls.flatMap(p => p.split(/, */));
4901
- if (!['caret', 'gt', 'gte', 'lt', 'lte', 'pin', 'preserve', 'tilde'].includes(rangeStyle)) {
4902
- rangeStyle = 'preserve';
4614
+ let [cwd = '.'] = cli.input;
4615
+ // Note: path.resolve vs .join:
4616
+ // If given path is absolute then cwd should not affect it.
4617
+ cwd = path.resolve(process.cwd(), cwd);
4618
+ let autoMerge = Boolean(cli.flags['autoMerge']);
4619
+ let test = Boolean(cli.flags['test']);
4620
+ if (autopilot) {
4621
+ autoMerge = true;
4622
+ test = true;
4903
4623
  }
4624
+ const limit = (cli.flags['limit'] ? parseInt(String(cli.flags['limit'] || ''), 10) : Infinity) || Infinity;
4625
+ const purls = Array.isArray(cli.flags['purl']) ? cli.flags['purl'].flatMap(p => p.split(/, */)) : [];
4626
+ const testScript = String(cli.flags['testScript'] || 'test');
4904
4627
  await handleFix({
4905
- autoMerge: Boolean(autoMerge),
4628
+ autoMerge,
4906
4629
  cwd,
4907
- limit: (cli.flags['limit'] ? parseInt(String(cli.flags['limit'] || ''), 10) : Infinity) || Infinity,
4630
+ limit,
4908
4631
  outputKind,
4909
4632
  purls,
4910
- rangeStyle: rangeStyle,
4911
- test: Boolean(test),
4912
- testScript: String(cli.flags['testScript'] || 'test')
4633
+ rangeStyle,
4634
+ test,
4635
+ testScript
4913
4636
  });
4914
4637
  }
4915
4638
 
@@ -5425,14 +5148,14 @@ async function run$D(argv, importMeta, {
5425
5148
  }
5426
5149
 
5427
5150
  const {
5428
- NPM: NPM$7,
5151
+ NPM: NPM$6,
5429
5152
  NPX: NPX$1,
5430
5153
  PACKAGE_LOCK_JSON,
5431
- PNPM: PNPM$6,
5154
+ PNPM: PNPM$5,
5432
5155
  YARN,
5433
5156
  YARN_LOCK
5434
5157
  } = constants;
5435
- const nodejsPlatformTypes = new Set(['javascript', 'js', 'nodejs', NPM$7, PNPM$6, 'ts', 'tsx', 'typescript']);
5158
+ const nodejsPlatformTypes = new Set(['javascript', 'js', 'nodejs', NPM$6, PNPM$5, 'ts', 'tsx', 'typescript']);
5436
5159
  function argvToArray(argv) {
5437
5160
  if (argv['help']) {
5438
5161
  return ['--help'];
@@ -5474,7 +5197,7 @@ async function runCdxgen(yargvWithYes) {
5474
5197
  const yesArgs = yes ? ['--yes'] : [];
5475
5198
  if (yargv.type !== YARN && nodejsPlatformTypes.has(yargv.type) && fs$1.existsSync(`./${YARN_LOCK}`)) {
5476
5199
  if (fs$1.existsSync(`./${PACKAGE_LOCK_JSON}`)) {
5477
- yargv.type = NPM$7;
5200
+ yargv.type = NPM$6;
5478
5201
  } else {
5479
5202
  // Use synp to create a package-lock.json from the yarn.lock,
5480
5203
  // based on the node_modules folder, for a more accurate SBOM.
@@ -5482,7 +5205,7 @@ async function runCdxgen(yargvWithYes) {
5482
5205
  await shadowNpmBin(NPX$1, [...yesArgs,
5483
5206
  // Lazily access constants.ENV.INLINED_SYNP_VERSION.
5484
5207
  `synp@${constants.ENV.INLINED_SYNP_VERSION}`, '--source-file', `./${YARN_LOCK}`]);
5485
- yargv.type = NPM$7;
5208
+ yargv.type = NPM$6;
5486
5209
  cleanupPackageLock = true;
5487
5210
  } catch {}
5488
5211
  }
@@ -5548,7 +5271,7 @@ const arrayToLower = arg => arg.map(toLower);
5548
5271
  // sable. [boolean] [default: true]
5549
5272
  // --evidence Generate SBOM with evidence for supported languages. [boolean] [default: false]
5550
5273
  // --spec-version CycloneDX Specification version to use. Defaults to 1.6
5551
- // [number] [choices: 1.4, 1.5, 1.6] [default: 1.6]
5274
+ // [number] [choices: 1.4, 1.5, 1.6, 1.7] [default: 1.6]
5552
5275
  // --filter Filter components containing this word in purl or component.properties.value. Multiple va
5553
5276
  // lues allowed. [array]
5554
5277
  // --only Include components only containing this word in purl. Useful to generate BOM with first p
@@ -7190,12 +6913,12 @@ async function run$s(argv, importMeta, {
7190
6913
  }
7191
6914
 
7192
6915
  const {
7193
- BUN: BUN$4,
7194
- NPM: NPM$6,
7195
- PNPM: PNPM$5,
7196
- VLT: VLT$5,
7197
- YARN_BERRY: YARN_BERRY$4,
7198
- YARN_CLASSIC: YARN_CLASSIC$5
6916
+ BUN: BUN$3,
6917
+ NPM: NPM$5,
6918
+ PNPM: PNPM$4,
6919
+ VLT: VLT$4,
6920
+ YARN_BERRY: YARN_BERRY$3,
6921
+ YARN_CLASSIC: YARN_CLASSIC$4
7199
6922
  } = constants;
7200
6923
  function matchLsCmdViewHumanStdout(stdout, name) {
7201
6924
  return stdout.includes(` ${name}@`);
@@ -7203,7 +6926,7 @@ function matchLsCmdViewHumanStdout(stdout, name) {
7203
6926
  function matchQueryCmdStdout(stdout, name) {
7204
6927
  return stdout.includes(`"${name}"`);
7205
6928
  }
7206
- const depsIncludesByAgent = new Map([[BUN$4, matchLsCmdViewHumanStdout], [NPM$6, matchQueryCmdStdout], [PNPM$5, matchQueryCmdStdout], [VLT$5, matchQueryCmdStdout], [YARN_BERRY$4, matchLsCmdViewHumanStdout], [YARN_CLASSIC$5, matchLsCmdViewHumanStdout]]);
6929
+ const depsIncludesByAgent = new Map([[BUN$3, matchLsCmdViewHumanStdout], [NPM$5, matchQueryCmdStdout], [PNPM$4, matchQueryCmdStdout], [VLT$4, matchQueryCmdStdout], [YARN_BERRY$3, matchLsCmdViewHumanStdout], [YARN_CLASSIC$4, matchLsCmdViewHumanStdout]]);
7207
6930
 
7208
6931
  function getDependencyEntries(pkgEnvDetails) {
7209
6932
  const {
@@ -7229,72 +6952,6 @@ function getDependencyEntries(pkgEnvDetails) {
7229
6952
  }) => o);
7230
6953
  }
7231
6954
 
7232
- const {
7233
- BUN: BUN$3,
7234
- NPM: NPM$5,
7235
- OVERRIDES: OVERRIDES$1,
7236
- PNPM: PNPM$4,
7237
- RESOLUTIONS: RESOLUTIONS$1,
7238
- VLT: VLT$4,
7239
- YARN_BERRY: YARN_BERRY$3,
7240
- YARN_CLASSIC: YARN_CLASSIC$4
7241
- } = constants;
7242
- function getOverridesDataBun(pkgEnvDetails) {
7243
- const overrides = pkgEnvDetails.editablePkgJson.content?.[RESOLUTIONS$1] ?? {};
7244
- return {
7245
- type: YARN_BERRY$3,
7246
- overrides
7247
- };
7248
- }
7249
-
7250
- // npm overrides documentation:
7251
- // https://docs.npmjs.com/cli/v10/configuring-npm/package-json#overrides
7252
- function getOverridesDataNpm(pkgEnvDetails) {
7253
- const overrides = pkgEnvDetails.editablePkgJson.content?.[OVERRIDES$1] ?? {};
7254
- return {
7255
- type: NPM$5,
7256
- overrides
7257
- };
7258
- }
7259
-
7260
- // pnpm overrides documentation:
7261
- // https://pnpm.io/package_json#pnpmoverrides
7262
- function getOverridesDataPnpm(pkgEnvDetails) {
7263
- const overrides = pkgEnvDetails.editablePkgJson.content?.[PNPM$4]?.[OVERRIDES$1] ?? {};
7264
- return {
7265
- type: PNPM$4,
7266
- overrides
7267
- };
7268
- }
7269
- function getOverridesDataVlt(pkgEnvDetails) {
7270
- const overrides = pkgEnvDetails.editablePkgJson.content?.[OVERRIDES$1] ?? {};
7271
- return {
7272
- type: VLT$4,
7273
- overrides
7274
- };
7275
- }
7276
-
7277
- // Yarn resolutions documentation:
7278
- // https://yarnpkg.com/configuration/manifest#resolutions
7279
- function getOverridesDataYarn(pkgEnvDetails) {
7280
- const overrides = pkgEnvDetails.editablePkgJson.content?.[RESOLUTIONS$1] ?? {};
7281
- return {
7282
- type: YARN_BERRY$3,
7283
- overrides
7284
- };
7285
- }
7286
-
7287
- // Yarn resolutions documentation:
7288
- // https://classic.yarnpkg.com/en/docs/selective-version-resolutions
7289
- function getOverridesDataYarnClassic(pkgEnvDetails) {
7290
- const overrides = pkgEnvDetails.editablePkgJson.content?.[RESOLUTIONS$1] ?? {};
7291
- return {
7292
- type: YARN_CLASSIC$4,
7293
- overrides
7294
- };
7295
- }
7296
- const overridesDataByAgent = new Map([[BUN$3, getOverridesDataBun], [NPM$5, getOverridesDataNpm], [PNPM$4, getOverridesDataPnpm], [VLT$4, getOverridesDataVlt], [YARN_BERRY$3, getOverridesDataYarn], [YARN_CLASSIC$4, getOverridesDataYarnClassic]]);
7297
-
7298
6955
  const {
7299
6956
  BUN: BUN$2,
7300
6957
  LOCK_EXT,
@@ -9979,7 +9636,7 @@ async function outputListRepos(result, outputKind, page, nextPage, sort, perPage
9979
9636
  logger.logger.log(vendor.srcExports(options, result.data.results));
9980
9637
  if (nextPage) {
9981
9638
  logger.logger.info(`This is page ${page}. Server indicated there are more results available on page ${nextPage}...`);
9982
- logger.logger.info(`(Hint: you can use \`socket repos list --page ${nextPage}\`)`);
9639
+ logger.logger.info(`(Hint: you can use \`socket repository list --page ${nextPage}\`)`);
9983
9640
  } else if (perPage === Infinity) {
9984
9641
  logger.logger.info(`This should be the entire list available on the server.`);
9985
9642
  } else {
@@ -10768,6 +10425,14 @@ async function run$c(argv, importMeta, {
10768
10425
  if (hasApiToken && !dryRun && interactive) {
10769
10426
  if (!orgSlug) {
10770
10427
  const suggestion = await utils.suggestOrgSlug();
10428
+ if (suggestion === undefined) {
10429
+ await outputCreateNewScan({
10430
+ ok: false,
10431
+ message: 'Canceled by user',
10432
+ cause: 'Org selector was canceled by user'
10433
+ }, outputKind, false);
10434
+ return;
10435
+ }
10771
10436
  if (suggestion) {
10772
10437
  orgSlug = suggestion;
10773
10438
  }
@@ -11895,6 +11560,19 @@ async function getRepoBranchTree({
11895
11560
  };
11896
11561
  }
11897
11562
 
11563
+ async function outputScanGithub(result, outputKind) {
11564
+ if (outputKind === 'json') {
11565
+ logger.logger.log(utils.serializeResultJson(result));
11566
+ return;
11567
+ }
11568
+ if (!result.ok) {
11569
+ logger.logger.fail(utils.failMsgWithBadge(result.message, result.cause));
11570
+ return;
11571
+ }
11572
+ logger.logger.log('');
11573
+ logger.logger.success('Finished!');
11574
+ }
11575
+
11898
11576
  async function handleCreateGithubScan({
11899
11577
  all,
11900
11578
  githubApiUrl,
@@ -11915,16 +11593,7 @@ async function handleCreateGithubScan({
11915
11593
  outputKind,
11916
11594
  repos: String(repos || '')
11917
11595
  });
11918
- if (outputKind === 'json') {
11919
- logger.logger.log(utils.serializeResultJson(result));
11920
- return;
11921
- }
11922
- if (!result.ok) {
11923
- logger.logger.fail(utils.failMsgWithBadge(result.message, result.cause));
11924
- return;
11925
- }
11926
- logger.logger.log('');
11927
- logger.logger.success('Finished!');
11596
+ await outputScanGithub(result, outputKind);
11928
11597
  }
11929
11598
 
11930
11599
  const {
@@ -12079,6 +11748,14 @@ async function run$9(argv, importMeta, {
12079
11748
  if (hasSocketApiToken && !dryRun && interactive) {
12080
11749
  if (!orgSlug) {
12081
11750
  const suggestion = await utils.suggestOrgSlug();
11751
+ if (suggestion === undefined) {
11752
+ await outputScanGithub({
11753
+ ok: false,
11754
+ message: 'Canceled by user',
11755
+ cause: 'Org selector was canceled by user'
11756
+ }, outputKind);
11757
+ return;
11758
+ }
12082
11759
  if (suggestion) {
12083
11760
  orgSlug = suggestion;
12084
11761
  }
@@ -14393,5 +14070,5 @@ void (async () => {
14393
14070
  await utils.captureException(e);
14394
14071
  }
14395
14072
  })();
14396
- //# debugId=13304ad0-96c0-432a-b125-801db7775ab7
14073
+ //# debugId=2d2b9a8c-0021-4a50-be2d-f6b89034705e
14397
14074
  //# sourceMappingURL=cli.js.map