@coana-tech/cli 14.12.94 → 14.12.96

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.
package/cli.mjs CHANGED
@@ -87128,9 +87128,9 @@ var require_lockfile = __commonJS({
87128
87128
  /* 85 */
87129
87129
  /***/
87130
87130
  function(module3, exports3) {
87131
- module3.exports = function(exec3) {
87131
+ module3.exports = function(exec5) {
87132
87132
  try {
87133
- return !!exec3();
87133
+ return !!exec5();
87134
87134
  } catch (e) {
87135
87135
  return true;
87136
87136
  }
@@ -87262,9 +87262,9 @@ var require_lockfile = __commonJS({
87262
87262
  /* 104 */
87263
87263
  /***/
87264
87264
  function(module3, exports3) {
87265
- module3.exports = function(exec3) {
87265
+ module3.exports = function(exec5) {
87266
87266
  try {
87267
- return { e: false, v: exec3() };
87267
+ return { e: false, v: exec5() };
87268
87268
  } catch (e) {
87269
87269
  return { e: true, v: e };
87270
87270
  }
@@ -88737,7 +88737,7 @@ ${indent3}`);
88737
88737
  });
88738
88738
  } catch (e) {
88739
88739
  }
88740
- module3.exports = function(exec3, skipClosing) {
88740
+ module3.exports = function(exec5, skipClosing) {
88741
88741
  if (!skipClosing && !SAFE_CLOSING) return false;
88742
88742
  var safe = false;
88743
88743
  try {
@@ -88749,7 +88749,7 @@ ${indent3}`);
88749
88749
  arr[ITERATOR] = function() {
88750
88750
  return iter;
88751
88751
  };
88752
- exec3(arr);
88752
+ exec5(arr);
88753
88753
  } catch (e) {
88754
88754
  }
88755
88755
  return safe;
@@ -89072,8 +89072,8 @@ ${indent3}`);
89072
89072
  var USE_NATIVE = !!function() {
89073
89073
  try {
89074
89074
  var promise = $Promise.resolve(1);
89075
- var FakePromise = (promise.constructor = {})[__webpack_require__(13)("species")] = function(exec3) {
89076
- exec3(empty2, empty2);
89075
+ var FakePromise = (promise.constructor = {})[__webpack_require__(13)("species")] = function(exec5) {
89076
+ exec5(empty2, empty2);
89077
89077
  };
89078
89078
  return (isNode2 || typeof PromiseRejectionEvent == "function") && promise.then(empty2) instanceof FakePromise && v8.indexOf("6.6") !== 0 && userAgent.indexOf("Chrome/66") === -1;
89079
89079
  } catch (e) {
@@ -206541,6 +206541,58 @@ async function parseShellArgs(args2) {
206541
206541
  );
206542
206542
  }
206543
206543
 
206544
+ // ../utils/src/command-utils-with-debug-logging.ts
206545
+ function formatCmd(cmd, dir) {
206546
+ const cmdStr = typeof cmd === "string" ? cmd : cmd.join(" ");
206547
+ return dir ? `${cmdStr} in ${dir}` : cmdStr;
206548
+ }
206549
+ async function execAndLogOnFailure2(cmd, dir, options, logLevel = "info") {
206550
+ logger.debug(`Running command: ${formatCmd(cmd, dir)}`);
206551
+ const result = await execAndLogOnFailure(cmd, dir, options, logLevel);
206552
+ if (result) {
206553
+ logger.debug(`Command ${formatCmd(cmd, dir)} finished successfully`);
206554
+ return true;
206555
+ }
206556
+ return result;
206557
+ }
206558
+ async function execPipeAndLogOnFailure2(cmd, dir, options) {
206559
+ logger.debug(`Running command: ${formatCmd(cmd, dir)}`);
206560
+ const result = await execPipeAndLogOnFailure(cmd, dir, options);
206561
+ if (result) {
206562
+ logger.debug(`Command ${formatCmd(cmd, dir)} finished successfully`);
206563
+ return true;
206564
+ }
206565
+ return result;
206566
+ }
206567
+ async function execNeverFail2(cmd, dir, options) {
206568
+ logger.debug(`Running command: ${formatCmd(cmd, dir)}`);
206569
+ const result = await execNeverFail(cmd, dir, options);
206570
+ logger.debug(`Command ${formatCmd(cmd, dir)} finished ${result.error ? "with error" : "successfully"}`);
206571
+ return result;
206572
+ }
206573
+ async function exec2(cmd, dir, options) {
206574
+ logger.debug(`Running command: ${formatCmd(cmd, dir)}`);
206575
+ try {
206576
+ const result = await exec(cmd, dir, options);
206577
+ logger.debug(`Command ${formatCmd(cmd, dir)} finished successfully`);
206578
+ return result;
206579
+ } catch (error) {
206580
+ logger.debug(`Command ${formatCmd(cmd, dir)} finished with error`);
206581
+ throw error;
206582
+ }
206583
+ }
206584
+ async function runCommandResolveStdOut2(cmd, dir, options) {
206585
+ logger.debug(`Running command: ${formatCmd(cmd, dir)}`);
206586
+ try {
206587
+ const result = await runCommandResolveStdOut(cmd, dir, options);
206588
+ logger.debug(`Command ${formatCmd(cmd, dir)} finished successfully`);
206589
+ return result;
206590
+ } catch (error) {
206591
+ logger.debug(`Command ${formatCmd(cmd, dir)} finished with error`);
206592
+ throw error;
206593
+ }
206594
+ }
206595
+
206544
206596
  // ../web-compat-utils/src/async.ts
206545
206597
  async function asyncMap(array, mapper, concurrency = 1) {
206546
206598
  const arrCp = [...array];
@@ -206606,7 +206658,7 @@ var GoFixingManager = class {
206606
206658
  async applySecurityFixesForWorkspace(workspacePath, fixes, dependencyNameToVersion) {
206607
206659
  const subprojectPath = resolve2(this.rootDir, this.subprojectPath, workspacePath);
206608
206660
  const runGoGetCmd = async (projectPath, oldModule, newModule) => {
206609
- const success = await execAndLogOnFailure(["go", "get", newModule], projectPath);
206661
+ const success = await execAndLogOnFailure2(["go", "get", newModule], projectPath);
206610
206662
  if (!success)
206611
206663
  throw new Error(
206612
206664
  `Could not apply module fix '${oldModule}' => '${newModule}' for Go project at: ${projectPath}`
@@ -206616,7 +206668,7 @@ var GoFixingManager = class {
206616
206668
  const isDowngrade = (0, import_semver.gt)(fix.currentVersion, fix.fixedVersion);
206617
206669
  if (isDowngrade) {
206618
206670
  const excludedRelease = `${fix.dependencyName}@v${fix.currentVersion}`;
206619
- await execAndLogOnFailure(["go", "mod", "edit", `-exclude=${excludedRelease}`], projectPath);
206671
+ await execAndLogOnFailure2(["go", "mod", "edit", `-exclude=${excludedRelease}`], projectPath);
206620
206672
  }
206621
206673
  };
206622
206674
  for (const fix of fixes) {
@@ -206717,13 +206769,13 @@ var Diff = class {
206717
206769
  editLength++;
206718
206770
  };
206719
206771
  if (callback) {
206720
- (function exec3() {
206772
+ (function exec5() {
206721
206773
  setTimeout(function() {
206722
206774
  if (editLength > maxEditLength || Date.now() > abortAfterTimestamp) {
206723
206775
  return callback(void 0);
206724
206776
  }
206725
206777
  if (!execEditLength()) {
206726
- exec3();
206778
+ exec5();
206727
206779
  }
206728
206780
  }, 0);
206729
206781
  })();
@@ -209713,7 +209765,7 @@ replace ${modulePath} ${currentVersion} => ${modulePath} ${newVersion}
209713
209765
  await asyncForEach(Object.entries(checksumFileToArtifacts), async ([checksumFile, artifacts]) => {
209714
209766
  const goModDir = dirname2(resolve5(this.rootDir, checksumFile));
209715
209767
  const oldFileContent = await readFile5(resolve5(this.rootDir, checksumFile), "utf-8").catch(() => "");
209716
- const result = await execNeverFail(["go", "mod", "tidy"], goModDir);
209768
+ const result = await execNeverFail2(["go", "mod", "tidy"], goModDir);
209717
209769
  if (result.error) {
209718
209770
  ctxt.statusUpdater?.({
209719
209771
  status: "error",
@@ -219541,8 +219593,8 @@ var Spinner2 = class _Spinner {
219541
219593
  };
219542
219594
 
219543
219595
  // ../utils/dist/command-utils.js
219544
- async function execAndLogOnFailure2(cmd, dir, options, logLevel = "info") {
219545
- const result = await execNeverFail2(cmd, dir, options);
219596
+ async function execAndLogOnFailure3(cmd, dir, options, logLevel = "info") {
219597
+ const result = await execNeverFail3(cmd, dir, options);
219546
219598
  if (result.error)
219547
219599
  logCommandOutput2(result, cmd, dir, logLevel);
219548
219600
  return !result.error;
@@ -219559,7 +219611,7 @@ ${stderr}`) ? em.slice(0, -stderr.length - 1) : em}`);
219559
219611
  logger[logLevel](`stdout: ${stdout}`);
219560
219612
  logger[logLevel](`stderr: ${stderr}`);
219561
219613
  }
219562
- async function execNeverFail2(cmd, dir, options) {
219614
+ async function execNeverFail3(cmd, dir, options) {
219563
219615
  return new Promise((resolve44) => {
219564
219616
  let args2;
219565
219617
  if (typeof cmd !== "string")
@@ -219584,8 +219636,8 @@ async function execNeverFail2(cmd, dir, options) {
219584
219636
  childProcess.stdin?.end();
219585
219637
  });
219586
219638
  }
219587
- async function runCommandResolveStdOut2(cmd, dir, options) {
219588
- const { stdout, error } = await execNeverFail2(cmd, dir, options);
219639
+ async function runCommandResolveStdOut3(cmd, dir, options) {
219640
+ const { stdout, error } = await execNeverFail3(cmd, dir, options);
219589
219641
  if (error)
219590
219642
  throw error;
219591
219643
  return stdout.trim();
@@ -219640,6 +219692,32 @@ function argt2(statics, ...values) {
219640
219692
  return res;
219641
219693
  }
219642
219694
 
219695
+ // ../utils/dist/command-utils-with-debug-logging.js
219696
+ function formatCmd2(cmd, dir) {
219697
+ const cmdStr = typeof cmd === "string" ? cmd : cmd.join(" ");
219698
+ return dir ? `${cmdStr} in ${dir}` : cmdStr;
219699
+ }
219700
+ async function execAndLogOnFailure4(cmd, dir, options, logLevel = "info") {
219701
+ logger.debug(`Running command: ${formatCmd2(cmd, dir)}`);
219702
+ const result = await execAndLogOnFailure3(cmd, dir, options, logLevel);
219703
+ if (result) {
219704
+ logger.debug(`Command ${formatCmd2(cmd, dir)} finished successfully`);
219705
+ return true;
219706
+ }
219707
+ return result;
219708
+ }
219709
+ async function runCommandResolveStdOut4(cmd, dir, options) {
219710
+ logger.debug(`Running command: ${formatCmd2(cmd, dir)}`);
219711
+ try {
219712
+ const result = await runCommandResolveStdOut3(cmd, dir, options);
219713
+ logger.debug(`Command ${formatCmd2(cmd, dir)} finished successfully`);
219714
+ return result;
219715
+ } catch (error) {
219716
+ logger.debug(`Command ${formatCmd2(cmd, dir)} finished with error`);
219717
+ throw error;
219718
+ }
219719
+ }
219720
+
219643
219721
  // ../utils/dist/package-utils.js
219644
219722
  import { parse, join as join6, resolve as resolve16, normalize as normalize2, dirname as dirname7, basename as basename2, relative as relative4 } from "path";
219645
219723
  import { existsSync as existsSync8, readFileSync, readdirSync as readdirSync2, statSync, writeFileSync } from "fs";
@@ -219664,7 +219742,7 @@ var import_lockfile_file = __toESM(require_lib25(), 1);
219664
219742
  var { once } = import_lodash4.default;
219665
219743
  async function getPackageVersionDetailsFromNpm(packageName, version3) {
219666
219744
  const npmViewCmd = cmdt2`npm view ${packageName}@${version3} -json`;
219667
- const output = await runCommandResolveStdOut2(npmViewCmd);
219745
+ const output = await runCommandResolveStdOut4(npmViewCmd);
219668
219746
  const pkgDetails = JSON.parse(output);
219669
219747
  const relevantDetails = {
219670
219748
  resolved: pkgDetails.dist.tarball,
@@ -219680,12 +219758,12 @@ async function getPackageVersionDetailsFromNpm(packageName, version3) {
219680
219758
  return relevantDetails;
219681
219759
  }
219682
219760
  var getNpmBin = once(async () => {
219683
- const prefix = await runCommandResolveStdOut2("npm config get prefix", "/");
219761
+ const prefix = await runCommandResolveStdOut4("npm config get prefix", "/");
219684
219762
  let npmBin = `${prefix}/bin/npm`;
219685
219763
  try {
219686
219764
  await access(npmBin, constants.X_OK);
219687
219765
  } catch (e) {
219688
- npmBin = await runCommandResolveStdOut2("which npm", "/");
219766
+ npmBin = await runCommandResolveStdOut4("which npm", "/");
219689
219767
  logger.warn(`Could not find npm at ${prefix}/bin/npm. Trying ${npmBin}`);
219690
219768
  await access(npmBin, constants.X_OK);
219691
219769
  }
@@ -219694,7 +219772,7 @@ var getNpmBin = once(async () => {
219694
219772
  async function actuallyRunInstall(specificPackagesArgs = [], dir) {
219695
219773
  const installationCommand = cmdt2`${await getNpmBin()} install -f --ignore-scripts --no-fund --no-audit --no-progress ${specificPackagesArgs}`;
219696
219774
  logger.debug(`Running installation command: "${installationCommand}" in ${dir}`);
219697
- const result = execAndLogOnFailure2(installationCommand, dir);
219775
+ const result = execAndLogOnFailure4(installationCommand, dir);
219698
219776
  logger.info(`Installation completed.`);
219699
219777
  return result;
219700
219778
  }
@@ -219821,7 +219899,7 @@ var PnpmFixingManager = class extends NpmEcosystemFixingManager {
219821
219899
  pnpmMajorVersion;
219822
219900
  async getPnpmMajorVersion() {
219823
219901
  if (!this.pnpmMajorVersion) {
219824
- const pnpmVersion = await runCommandResolveStdOut(cmdt`pnpm -v`);
219902
+ const pnpmVersion = await runCommandResolveStdOut2(cmdt`pnpm -v`);
219825
219903
  this.pnpmMajorVersion = parseInt(pnpmVersion.trim().split(".")[0]);
219826
219904
  }
219827
219905
  return this.pnpmMajorVersion;
@@ -219847,7 +219925,7 @@ var PnpmFixingManager = class extends NpmEcosystemFixingManager {
219847
219925
  const installationCommand = cmdt`pnpm install --ignore-scripts${await this.getPnpmMajorVersion() >= 9 && specificPackagesCmd.length === 0 ? "--no-frozen-lockfile" : ""} --config.confirmModulesPurge=false ${specificPackagesCmd}`;
219848
219926
  const installDir = resolve19(this.rootDir, this.subprojectPath, workspacePath);
219849
219927
  logger.info(`Running installation command: "${installationCommand}" in ${installDir}`);
219850
- await exec(installationCommand, installDir);
219928
+ await exec2(installationCommand, installDir);
219851
219929
  logger.info(`Installation completed.`);
219852
219930
  }
219853
219931
  async getLockFileYaml() {
@@ -219947,7 +220025,7 @@ var PnpmFixingManager = class extends NpmEcosystemFixingManager {
219947
220025
  async finalizeFixes() {
219948
220026
  const cmd = cmdt`pnpm install --ignore-scripts --fix-lockfile --config.confirmModulesPurge=false `;
219949
220027
  logger.info(`Adjusting lock file changes by running '${cmd}'`);
219950
- await exec(cmd, resolve19(this.rootDir, this.subprojectPath));
220028
+ await exec2(cmd, resolve19(this.rootDir, this.subprojectPath));
219951
220029
  }
219952
220030
  };
219953
220031
  function getVersionNumber(version3) {
@@ -220078,8 +220156,8 @@ var YarnFixingManager = class extends NpmEcosystemFixingManager {
220078
220156
  this.setPackageManagerField("yarn@1.2.3");
220079
220157
  const yarnType = await this.getYarnType();
220080
220158
  const corepackUseCommand = cmdt`corepack use yarn@${yarnType === "classic" ? 1 : 4}`;
220081
- await execNeverFail(corepackUseCommand, resolve22(this.rootDir, this.subprojectPath));
220082
- const cmdResult = await execNeverFail(cmd, dir, options);
220159
+ await execNeverFail2(corepackUseCommand, resolve22(this.rootDir, this.subprojectPath));
220160
+ const cmdResult = await execNeverFail2(cmd, dir, options);
220083
220161
  try {
220084
220162
  writePackageJsonContent(resolve22(this.rootDir, this.subprojectPath), originalPackageJson);
220085
220163
  } catch (err) {
@@ -220089,7 +220167,7 @@ var YarnFixingManager = class extends NpmEcosystemFixingManager {
220089
220167
  }
220090
220168
  return cmdResult;
220091
220169
  }
220092
- return execNeverFail(cmd, dir, options);
220170
+ return execNeverFail2(cmd, dir, options);
220093
220171
  }
220094
220172
  setPackageManagerField(manager) {
220095
220173
  setFieldInPackageJson(resolve22(this.rootDir, this.subprojectPath), "packageManager", manager);
@@ -220611,14 +220689,14 @@ var NugetFixingManager = class {
220611
220689
  });
220612
220690
  if (solutionFiles) {
220613
220691
  for (const solutionFile of solutionFiles) {
220614
- const succeeded = await execAndLogOnFailure(
220692
+ const succeeded = await execAndLogOnFailure2(
220615
220693
  cmdt`dotnet restore ${solutionFile} --use-lock-file`,
220616
220694
  join9(this.rootDir, this.subprojectPath)
220617
220695
  );
220618
220696
  if (!succeeded) throw new Error(`Error applying fix - could not restore project ${this.subprojectPath}`);
220619
220697
  }
220620
220698
  } else {
220621
- const succeeded = await execAndLogOnFailure(
220699
+ const succeeded = await execAndLogOnFailure2(
220622
220700
  "dotnet restore --use-lock-file",
220623
220701
  join9(this.rootDir, this.subprojectPath)
220624
220702
  );
@@ -220703,7 +220781,7 @@ var NugetFixingManager = class {
220703
220781
  }
220704
220782
  async addPackage(packageName, version3, framework, wsPath) {
220705
220783
  const dir = join9(this.rootDir, this.subprojectPath, wsPath);
220706
- const succeeded = await execAndLogOnFailure(
220784
+ const succeeded = await execAndLogOnFailure2(
220707
220785
  cmdt`dotnet add package ${packageName} --version ${version3} --no-restore --framework ${framework}`,
220708
220786
  dir
220709
220787
  );
@@ -220714,7 +220792,7 @@ var NugetFixingManager = class {
220714
220792
  }
220715
220793
  }
220716
220794
  async restoreWorkspaceAndParseLockFile(wsPath) {
220717
- const succeeded = await execAndLogOnFailure("dotnet restore --use-lock-file", this.getAbsWsPath(wsPath));
220795
+ const succeeded = await execAndLogOnFailure2("dotnet restore --use-lock-file", this.getAbsWsPath(wsPath));
220718
220796
  if (!succeeded) throw new Error(`Error applying fix - could not restore project ${this.subprojectPath}/${wsPath}`);
220719
220797
  return JSON.parse(await readFile20(this.getLockFilePath(wsPath), "utf-8"));
220720
220798
  }
@@ -220775,7 +220853,7 @@ var CargoFixingManager = class {
220775
220853
  for (const fix of fixes) {
220776
220854
  const depTreeNode = dependencyTree.transitiveDependencies[fix.dependencyIdentifier];
220777
220855
  if (!depTreeNode || depTreeNode.version !== fix.currentVersion) throw Error("Error applying fix!");
220778
- const success = await execAndLogOnFailure(
220856
+ const success = await execAndLogOnFailure2(
220779
220857
  cmdt`cargo update --package ${fix.dependencyName}@${fix.currentVersion} --precise ${fix.fixedVersion}`,
220780
220858
  subprojectPath
220781
220859
  );
@@ -223547,7 +223625,7 @@ ${newDependencyLine}`
223547
223625
  const oldFileContent = await readFile23(resolve27(this.rootDir, lockfile2), "utf-8");
223548
223626
  let result;
223549
223627
  if (this.cargoLockMatcher(lockfile2)) {
223550
- result = await execNeverFail(["cargo", "fetch"], lockfileDir);
223628
+ result = await execNeverFail2(["cargo", "fetch"], lockfileDir);
223551
223629
  } else {
223552
223630
  ctxt.statusUpdater?.({
223553
223631
  status: "error",
@@ -224487,7 +224565,7 @@ ${" ".repeat(4)}"${artifact.name}==${upgradeVersion}",
224487
224565
  const oldFileContent = await readFile26(resolve31(this.rootDir, lockfile2), "utf-8");
224488
224566
  let result;
224489
224567
  if (this.uvLockMatcher(lockfile2)) {
224490
- result = await execNeverFail(["uv", "lock"], lockfileDir);
224568
+ result = await execNeverFail2(["uv", "lock"], lockfileDir);
224491
224569
  } else {
224492
224570
  ctxt.statusUpdater?.({
224493
224571
  status: "error",
@@ -225225,7 +225303,7 @@ var RubygemsSocketUpgradeManager = class {
225225
225303
  }
225226
225304
  await asyncForEach(Object.entries(lockfileToArtifacts), async ([file, artifacts]) => {
225227
225305
  const oldFileContent = await readFile27(resolve33(this.rootDir, file), "utf-8");
225228
- const result = await execNeverFail("bundle lock", dirname18(resolve33(this.rootDir, file)));
225306
+ const result = await execNeverFail2("bundle lock", dirname18(resolve33(this.rootDir, file)));
225229
225307
  const updatedFileContent = await readFile27(resolve33(this.rootDir, file), "utf-8");
225230
225308
  if (!result.error) {
225231
225309
  ctxt.statusUpdater?.({
@@ -225267,7 +225345,7 @@ var RubygemsSocketUpgradeManager = class {
225267
225345
  await applyPatches("RUBYGEMS", this.rootDir, directPatches, ctxt);
225268
225346
  await asyncForEach(Object.entries(lockfileToArtifacts), async ([file, artifacts]) => {
225269
225347
  const oldFileContent = await readFile27(resolve33(this.rootDir, file), "utf-8");
225270
- const result = await execNeverFail(cmdt`bundler lock`, dirname18(resolve33(this.rootDir, file)));
225348
+ const result = await execNeverFail2(cmdt`bundler lock`, dirname18(resolve33(this.rootDir, file)));
225271
225349
  const updatedFileContent = await readFile27(resolve33(this.rootDir, file), "utf-8");
225272
225350
  if (!result.error) {
225273
225351
  ctxt.statusUpdater?.({
@@ -226260,7 +226338,7 @@ var DOCKER_ENV_WHITE_LIST = [
226260
226338
  // ../other-modules-communicator/src/other-modules-communicator.ts
226261
226339
  var { memoize, once: once7, take } = import_lodash12.default;
226262
226340
  var pullDockerImage = memoize(async (image) => {
226263
- const { error, stderr } = await execNeverFail(["docker", "pull", image]);
226341
+ const { error, stderr } = await execNeverFail2(["docker", "pull", image]);
226264
226342
  if (error) {
226265
226343
  if (stderr?.includes("Cannot connect"))
226266
226344
  throw new Error(`Failed to pull docker image ${image}. Is docker installed and running on your system?`);
@@ -226331,7 +226409,7 @@ var OtherModulesCommunicator = class {
226331
226409
  async () => {
226332
226410
  let succeeded;
226333
226411
  if (this.options.runWithoutDocker) {
226334
- succeeded = await execPipeAndLogOnFailure(
226412
+ succeeded = await execPipeAndLogOnFailure2(
226335
226413
  ["node", PACKAGE_MANAGER_SCRIPT_PATH(), commandName, ...finalArgs],
226336
226414
  subprojectPath,
226337
226415
  { env }
@@ -226397,7 +226475,7 @@ var OtherModulesCommunicator = class {
226397
226475
  async () => {
226398
226476
  let succeeded = true;
226399
226477
  if (this.options.runWithoutDocker) {
226400
- succeeded = await execPipeAndLogOnFailure(
226478
+ succeeded = await execPipeAndLogOnFailure2(
226401
226479
  ["node", REACHABILITY_ANALYZERS_SCRIPT_PATH(), commandName, ...finalArgs],
226402
226480
  subprojectPath,
226403
226481
  { env }
@@ -226445,7 +226523,7 @@ var OtherModulesCommunicator = class {
226445
226523
  -v=${this.options.coanaLogPath}:${LOG_PATH_IN_DOCKER}
226446
226524
  ${await getEcosystemSpecificDockerArgs(ecosystem)}
226447
226525
  ${envArgs} ${image} ${entryPoint} ${commandName} ${args2}`;
226448
- return execPipeAndLogOnFailure(cmd, subprojectPath, { env });
226526
+ return execPipeAndLogOnFailure2(cmd, subprojectPath, { env });
226449
226527
  }
226450
226528
  async getWorkspacePaths(packageManagerName, subprojectPath) {
226451
226529
  return this.runPackageManagerCommandWithOutput("getWorkspacePaths", packageManagerName, subprojectPath);
@@ -226533,7 +226611,7 @@ var OtherModulesCommunicator = class {
226533
226611
  }
226534
226612
  };
226535
226613
  var setUpGoModuleCache = once7(async () => {
226536
- const { stdout, error } = await execNeverFail("go env GOMODCACHE");
226614
+ const { stdout, error } = await execNeverFail2("go env GOMODCACHE");
226537
226615
  if (error ?? !await exists(stdout.trim()))
226538
226616
  return;
226539
226617
  if (platform() !== "linux") return stdout.trim();
@@ -226551,7 +226629,7 @@ var setUpGoModuleCache = once7(async () => {
226551
226629
  });
226552
226630
  const [upper, work] = [join21(tmpDir, "upper"), join21(tmpDir, "work")];
226553
226631
  for (const dir of [upper, work]) await mkdir(dir);
226554
- const o7 = await execNeverFail(
226632
+ const o7 = await execNeverFail2(
226555
226633
  cmdt`docker volume create --driver local --opt type=overlay
226556
226634
  --opt o=lowerdir=${stdout.trim()},upperdir=${upper},workdir=${work}
226557
226635
  --opt device=overlay`
@@ -227534,7 +227612,7 @@ var GitHubPRTools = class {
227534
227612
  commentBody += `Please review the ${vulnerabilityWord} below and take appropriate action before merging the PR.
227535
227613
 
227536
227614
  `;
227537
- const getSha = await execNeverFail(cmdt`git rev-parse HEAD`, void 0, { timeout: 1e4 });
227615
+ const getSha = await execNeverFail2(cmdt`git rev-parse HEAD`, void 0, { timeout: 1e4 });
227538
227616
  let sha;
227539
227617
  if (!getSha.error) {
227540
227618
  sha = getSha.stdout.trim();
@@ -229667,7 +229745,7 @@ function getMongoClient() {
229667
229745
  }
229668
229746
 
229669
229747
  // ../security-auditor/security-auditor-api/src/vulnerability-patterns-helper/get-interesting-urls-for-vulnerability.ts
229670
- import { exec as exec2 } from "child_process";
229748
+ import { exec as exec4 } from "child_process";
229671
229749
  import { promisify } from "util";
229672
229750
 
229673
229751
  // ../../node_modules/.pnpm/cheerio@1.0.0-rc.12/node_modules/cheerio/lib/esm/options.js
@@ -243263,7 +243341,7 @@ async function getInterestingURLsForVulnerability(vulnerability, packageMetadata
243263
243341
  }
243264
243342
  async function computeComparisonURLs(scmUrl, vulnAndFixVersionsArr) {
243265
243343
  try {
243266
- const gitTags = (await promisify(exec2)(`git ls-remote ${scmUrl} | grep -F "refs/tags"`)).stdout.split("\n");
243344
+ const gitTags = (await promisify(exec4)(`git ls-remote ${scmUrl} | grep -F "refs/tags"`)).stdout.split("\n");
243267
243345
  logger3.debug("gitTags", gitTags);
243268
243346
  logger3.debug("vulnAndFixVersionsArr", vulnAndFixVersionsArr);
243269
243347
  const versionToSha = {};
@@ -243298,7 +243376,7 @@ async function computeInterestingCommitURLs(text3, scmUrl) {
243298
243376
  const repo = scmUrl.split("/").slice(-2).join("/");
243299
243377
  const cmd = `gh search commits ${text3} --repo ${repo}`;
243300
243378
  logger3.debug(`Finding issue or PR url for text ${text3}`, cmd);
243301
- const { stdout } = await promisify(exec2)(cmd, { shell: "/bin/zsh" });
243379
+ const { stdout } = await promisify(exec4)(cmd, { shell: "/bin/zsh" });
243302
243380
  return stdout.split("\n").filter((line) => line).map((line) => {
243303
243381
  const [repo2, sha] = line.split(" ");
243304
243382
  return `https://www.github.com/${repo2}/commit/${sha}`;
@@ -243312,7 +243390,7 @@ async function computeInterestingIssueAndPRUrlsWithText(text3, scmUrl) {
243312
243390
  const repo = scmUrl.split("/").slice(-2).join("/");
243313
243391
  const cmd = `gh search issues ${text3} in:title,body,comment --repo ${repo} --include-prs`;
243314
243392
  console.log(`Finding issue or PR url for text ${text3}`, cmd);
243315
- const { stdout } = await promisify(exec2)(cmd, { shell: "/bin/zsh" });
243393
+ const { stdout } = await promisify(exec4)(cmd, { shell: "/bin/zsh" });
243316
243394
  return stdout.split("\n").filter((line) => line).map((line) => {
243317
243395
  const [issueOrPr, repo2, id] = line.split(" ");
243318
243396
  const issueOrPrUrlPart = issueOrPr === "issue" ? "issues" : "pull";
@@ -244541,7 +244619,7 @@ async function onlineScan(dependencyTree, apiKey, timeout) {
244541
244619
  }
244542
244620
 
244543
244621
  // dist/version.js
244544
- var version2 = "14.12.94";
244622
+ var version2 = "14.12.96";
244545
244623
 
244546
244624
  // dist/cli-core.js
244547
244625
  var { mapValues, omit, partition, pick } = import_lodash15.default;
@@ -244938,8 +245016,8 @@ Subproject: ${subproject}`);
244938
245016
  ["heap", "-d"],
244939
245017
  ["virtual_memory", "-v"]
244940
245018
  ].map(async ([name, flag]) => {
244941
- const soft = await runCommandResolveStdOut(`ulimit -S ${flag}`);
244942
- const hard = await runCommandResolveStdOut(`ulimit -H ${flag}`);
245019
+ const soft = await runCommandResolveStdOut2(`ulimit -S ${flag}`);
245020
+ const hard = await runCommandResolveStdOut2(`ulimit -H ${flag}`);
244943
245021
  return [name, { soft, hard }];
244944
245022
  }));
244945
245023
  logger.info("ulimits: %O", Object.fromEntries(limits));
@@ -245319,8 +245397,8 @@ async function getGitDataToMetadataIfAvailable(rootWorkingDirectory) {
245319
245397
  const base = cmdt`git -c safe.directory=${rootWorkingDirectory} rev-parse`;
245320
245398
  try {
245321
245399
  return {
245322
- sha: await runCommandResolveStdOut([...base, "HEAD"], rootWorkingDirectory),
245323
- branchName: await runCommandResolveStdOut([...base, "--abbrev-ref", "HEAD"], rootWorkingDirectory)
245400
+ sha: await runCommandResolveStdOut2([...base, "HEAD"], rootWorkingDirectory),
245401
+ branchName: await runCommandResolveStdOut2([...base, "--abbrev-ref", "HEAD"], rootWorkingDirectory)
245324
245402
  };
245325
245403
  } catch (e) {
245326
245404
  logger.debug("Unable to get git data. Is the folder even in a git repository?", e);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@coana-tech/cli",
3
- "version": "14.12.94",
3
+ "version": "14.12.96",
4
4
  "description": "Coana CLI",
5
5
  "type": "module",
6
6
  "bin": {
@@ -80579,6 +80579,49 @@ async function parseShellArgs(args) {
80579
80579
  );
80580
80580
  }
80581
80581
 
80582
+ // ../utils/src/command-utils-with-debug-logging.ts
80583
+ function formatCmd(cmd, dir) {
80584
+ const cmdStr = typeof cmd === "string" ? cmd : cmd.join(" ");
80585
+ return dir ? `${cmdStr} in ${dir}` : cmdStr;
80586
+ }
80587
+ async function execAndLogOnFailure2(cmd, dir, options, logLevel = "info") {
80588
+ logger.debug(`Running command: ${formatCmd(cmd, dir)}`);
80589
+ const result = await execAndLogOnFailure(cmd, dir, options, logLevel);
80590
+ if (result) {
80591
+ logger.debug(`Command ${formatCmd(cmd, dir)} finished successfully`);
80592
+ return true;
80593
+ }
80594
+ return result;
80595
+ }
80596
+ async function execNeverFail2(cmd, dir, options) {
80597
+ logger.debug(`Running command: ${formatCmd(cmd, dir)}`);
80598
+ const result = await execNeverFail(cmd, dir, options);
80599
+ logger.debug(`Command ${formatCmd(cmd, dir)} finished ${result.error ? "with error" : "successfully"}`);
80600
+ return result;
80601
+ }
80602
+ async function exec2(cmd, dir, options) {
80603
+ logger.debug(`Running command: ${formatCmd(cmd, dir)}`);
80604
+ try {
80605
+ const result = await exec(cmd, dir, options);
80606
+ logger.debug(`Command ${formatCmd(cmd, dir)} finished successfully`);
80607
+ return result;
80608
+ } catch (error) {
80609
+ logger.debug(`Command ${formatCmd(cmd, dir)} finished with error`);
80610
+ throw error;
80611
+ }
80612
+ }
80613
+ async function runCommandResolveStdOut2(cmd, dir, options) {
80614
+ logger.debug(`Running command: ${formatCmd(cmd, dir)}`);
80615
+ try {
80616
+ const result = await runCommandResolveStdOut(cmd, dir, options);
80617
+ logger.debug(`Command ${formatCmd(cmd, dir)} finished successfully`);
80618
+ return result;
80619
+ } catch (error) {
80620
+ logger.debug(`Command ${formatCmd(cmd, dir)} finished with error`);
80621
+ throw error;
80622
+ }
80623
+ }
80624
+
80582
80625
  // ../utils/src/file-utils.ts
80583
80626
  var import_lodash3 = __toESM(require_lodash(), 1);
80584
80627
  var import_micromatch = __toESM(require_micromatch(), 1);
@@ -80677,28 +80720,24 @@ async function exists(path10, mode) {
80677
80720
  // ../utils/src/go-utils.ts
80678
80721
  var modWhyRegex = /^\(main module does not need to vendor (?:module|package) (\S+)\)$/gm;
80679
80722
  async function runGoModWhy(moduleMode, projectFolder, toCheck) {
80680
- logger.debug(`Running 'go mod why' in ${projectFolder} with ${moduleMode ? "module" : "package"} mode`);
80681
- const modWhyOutput = await runCommandResolveStdOut(
80723
+ const modWhyOutput = await runCommandResolveStdOut2(
80682
80724
  // -vendor flag tells why to disregard imports in dependencies' tests
80683
80725
  ["go", ...`mod why${moduleMode ? " -m" : ""} -vendor`.split(" "), ...toCheck],
80684
80726
  projectFolder,
80685
80727
  { timeout: 30 * 60 * 1e3 }
80686
80728
  // 30 minutes
80687
80729
  );
80688
- logger.debug(`'go mod why' finished`);
80689
80730
  return Array.from(modWhyOutput.matchAll(modWhyRegex), ([, m]) => m);
80690
80731
  }
80691
80732
  var getIrrelevantModules = runGoModWhy.bind(null, true);
80692
80733
  var getIrrelevantPackages = runGoModWhy.bind(null, false);
80693
80734
  async function getModuleInfo(goModPath) {
80694
80735
  if (!goModPath.endsWith(".mod")) goModPath = join3(goModPath, "go.mod");
80695
- const stdout = await runCommandResolveStdOut(["go", "mod", "edit", "-json", goModPath]);
80736
+ const stdout = await runCommandResolveStdOut2(["go", "mod", "edit", "-json", goModPath]);
80696
80737
  return JSON.parse(stdout);
80697
80738
  }
80698
80739
  async function runGoModTidy(moduleDir, { continueOnError = false } = {}) {
80699
- logger.debug(`Running 'go mod tidy' in ${moduleDir}`);
80700
- const { error } = await execNeverFail(["go", "mod", "tidy"], moduleDir, { timeout: 30 * 60 * 1e3 });
80701
- logger.debug(`'go mod tidy' finished`);
80740
+ const { error } = await execNeverFail2(["go", "mod", "tidy"], moduleDir, { timeout: 30 * 60 * 1e3 });
80702
80741
  if (error) {
80703
80742
  const { Module, Go } = await getModuleInfo(moduleDir);
80704
80743
  logger.warn(
@@ -89804,6 +89843,31 @@ function evaluate(expression, project) {
89804
89843
 
89805
89844
  // dist/whole-program-code-aware-vulnerability-scanner/dotnet/dotnet-code-aware-vulnerability-scanner.js
89806
89845
  var { uniq: uniq2, uniqWith, isEqual } = import_lodash6.default;
89846
+ async function ensureDotnet6OrAbove() {
89847
+ const result = await execNeverFail2(cmdt`dotnet --list-runtimes`);
89848
+ if (result.error)
89849
+ throw new Error(".NET runtime not found. Please install .NET 6 runtime or above.");
89850
+ const runtimesOutput = result.stdout ?? "";
89851
+ const runtimeLines = runtimesOutput.split("\n").map((line) => line.trim()).filter(Boolean);
89852
+ const netCoreRuntimes = runtimeLines.filter((line) => line.startsWith("Microsoft.NETCore.App")).map((line) => {
89853
+ const versionMatch = line.match(/Microsoft\.NETCore\.App\s+(\d+)(?:\.(\d+))?(?:\.(\d+))?/);
89854
+ if (versionMatch) {
89855
+ return {
89856
+ major: parseInt(versionMatch[1], 10),
89857
+ minor: versionMatch[2] ? parseInt(versionMatch[2], 10) : 0,
89858
+ patch: versionMatch[3] ? parseInt(versionMatch[3], 10) : 0
89859
+ };
89860
+ }
89861
+ return void 0;
89862
+ }).filter((v) => v !== void 0);
89863
+ if (netCoreRuntimes.length === 0)
89864
+ throw new Error(".NET runtime not found. Please install .NET 6 runtime or above.");
89865
+ const hasValidRuntime = netCoreRuntimes.some((version3) => version3.major >= 6);
89866
+ if (!hasValidRuntime) {
89867
+ const foundVersions = netCoreRuntimes.map((v) => `${v.major}.${v.minor}.${v.patch}`).join(", ");
89868
+ throw new Error(`.NET runtime versions found: ${foundVersions}. None are supported. Please install .NET 6 runtime or above.`);
89869
+ }
89870
+ }
89807
89871
  var DotnetCodeAwareVulnerabilityScanner = class _DotnetCodeAwareVulnerabilityScanner {
89808
89872
  apps;
89809
89873
  deps;
@@ -89909,6 +89973,11 @@ var DotnetCodeAwareVulnerabilityScanner = class _DotnetCodeAwareVulnerabilitySca
89909
89973
  }
89910
89974
  async runPhantomDependencyAnalysis() {
89911
89975
  return withTmpDirectory("dotnet-direct-dependency-analysis", async (tmpDir) => {
89976
+ try {
89977
+ await ensureDotnet6OrAbove();
89978
+ } catch {
89979
+ return void 0;
89980
+ }
89912
89981
  const options = {
89913
89982
  apps: this.apps,
89914
89983
  deps: this.deps,
@@ -89918,7 +89987,7 @@ var DotnetCodeAwareVulnerabilityScanner = class _DotnetCodeAwareVulnerabilitySca
89918
89987
  const outputFile = resolve8(tmpDir, "output.json");
89919
89988
  await writeFile3(inputFile, JSON.stringify(options));
89920
89989
  const timeoutMs = this.timeoutInSeconds ? Math.max(this.timeoutInSeconds * 1.5, this.timeoutInSeconds + 30) * 1e3 : 750 * 1e3;
89921
- const result = await execNeverFail(cmdt`node ${classGraphAnalysisCliPath} runDotnetDirectDependencyAnalysis -i ${inputFile} -o ${outputFile} --cocoa ${cocoaPath} --tree-sitter-c-sharp ${treeSitterCSharpPath}`, void 0, { timeout: timeoutMs });
89990
+ const result = await execNeverFail2(cmdt`node ${classGraphAnalysisCliPath} runDotnetDirectDependencyAnalysis -i ${inputFile} -o ${outputFile} --cocoa ${cocoaPath} --tree-sitter-c-sharp ${treeSitterCSharpPath}`, void 0, { timeout: timeoutMs });
89922
89991
  if (result.error)
89923
89992
  return void 0;
89924
89993
  const packageIds = JSON.parse(await readFile6(outputFile, "utf-8")).result;
@@ -89942,6 +90011,11 @@ var DotnetCodeAwareVulnerabilityScanner = class _DotnetCodeAwareVulnerabilitySca
89942
90011
  async actuallyRunAnalysis(vulnerabilityAccessPaths, filteredDeps) {
89943
90012
  this.statusUpdater?.("Running analysis...");
89944
90013
  return withTmpDirectory("dotnet-run-analysis", async (tmpDir) => {
90014
+ try {
90015
+ await ensureDotnet6OrAbove();
90016
+ } catch (e) {
90017
+ return { type: "error", message: e.message };
90018
+ }
89945
90019
  const options = {
89946
90020
  apps: this.apps,
89947
90021
  deps: filteredDeps ?? this.deps,
@@ -89952,7 +90026,7 @@ var DotnetCodeAwareVulnerabilityScanner = class _DotnetCodeAwareVulnerabilitySca
89952
90026
  const outputFile = resolve8(tmpDir, "output.json");
89953
90027
  await writeFile3(inputFile, JSON.stringify(options));
89954
90028
  const timeoutMs = this.timeoutInSeconds ? Math.max(this.timeoutInSeconds * 1.5, this.timeoutInSeconds + 30) * 1e3 : 750 * 1e3;
89955
- const result = await execNeverFail(cmdt`node ${classGraphAnalysisCliPath} runDotnetReachabilityAnalysis -i ${inputFile} -o ${outputFile} --cocoa ${cocoaPath} --tree-sitter-c-sharp ${treeSitterCSharpPath}`, void 0, { timeout: timeoutMs });
90029
+ const result = await execNeverFail2(cmdt`node ${classGraphAnalysisCliPath} runDotnetReachabilityAnalysis -i ${inputFile} -o ${outputFile} --cocoa ${cocoaPath} --tree-sitter-c-sharp ${treeSitterCSharpPath}`, void 0, { timeout: timeoutMs });
89956
90030
  if (result.error)
89957
90031
  return { type: "error", message: result.error.message ?? "unknown error" };
89958
90032
  const { success, error, analysisDiagnostics: diagnostics, vulnerablePaths, reachablePackageIds } = JSON.parse(await readFile6(outputFile, "utf-8")).result;
@@ -103749,6 +103823,21 @@ var treeSitterScalaPath = join13(COANA_REPOS_PATH(), "tree-sitter-scala");
103749
103823
  // dist/whole-program-code-aware-vulnerability-scanner/java/java-code-aware-vulnerability-scanner.js
103750
103824
  var import_picomatch2 = __toESM(require_picomatch4(), 1);
103751
103825
  var { uniq: uniq3, uniqWith: uniqWith2, isEqual: isEqual2 } = import_lodash8.default;
103826
+ async function ensureJdk8OrAbove() {
103827
+ const javapResult = await execNeverFail2(cmdt`javap -version`);
103828
+ if (javapResult.error)
103829
+ throw new Error("JDK not found. Please install JDK 8 or above.");
103830
+ const javapOutput = javapResult.stdout.trim() || "";
103831
+ const versionMatch = javapOutput.match(/(\d+)(?:\.(\d+))?(?:\.(\d+))?/);
103832
+ if (!versionMatch)
103833
+ throw new Error("Could not determine Java version. Please ensure JDK 8 or above is installed.");
103834
+ const major = parseInt(versionMatch[1], 10);
103835
+ const minor = versionMatch[2] ? parseInt(versionMatch[2], 10) : 0;
103836
+ const isValid = major === 1 && minor >= 8 || major >= 8;
103837
+ if (!isValid) {
103838
+ throw new Error(`JDK version ${javapOutput} is not supported. Please install JDK 8 or above.`);
103839
+ }
103840
+ }
103752
103841
  var JavaCodeAwareVulnerabilityScanner = class _JavaCodeAwareVulnerabilityScanner {
103753
103842
  apps;
103754
103843
  deps;
@@ -103855,6 +103944,11 @@ var JavaCodeAwareVulnerabilityScanner = class _JavaCodeAwareVulnerabilityScanner
103855
103944
  }
103856
103945
  async runPhantomDependencyAnalysis() {
103857
103946
  return withTmpDirectory("java-direct-dependency-analysis", async (tmpDir) => {
103947
+ try {
103948
+ await ensureJdk8OrAbove();
103949
+ } catch {
103950
+ return void 0;
103951
+ }
103858
103952
  const options = {
103859
103953
  apps: this.apps,
103860
103954
  deps: this.deps,
@@ -103864,7 +103958,7 @@ var JavaCodeAwareVulnerabilityScanner = class _JavaCodeAwareVulnerabilityScanner
103864
103958
  const outputFile = resolve9(tmpDir, "output.json");
103865
103959
  await writeFile4(inputFile, JSON.stringify(options));
103866
103960
  const timeoutMs = this.timeoutInSeconds ? Math.max(this.timeoutInSeconds * 1.5, this.timeoutInSeconds + 30) * 1e3 : 750 * 1e3;
103867
- const result = await execNeverFail(cmdt`node ${classGraphAnalysisCliPath} runJvmDirectDependencyAnalysis -i ${inputFile} -o ${outputFile} --javap-service ${javapServicePath} --tree-sitter-java ${treeSitterJavaPath} --tree-sitter-kotlin ${treeSitterKotlinPath} --tree-sitter-scala ${treeSitterScalaPath}`, void 0, { timeout: timeoutMs });
103961
+ const result = await execNeverFail2(cmdt`node ${classGraphAnalysisCliPath} runJvmDirectDependencyAnalysis -i ${inputFile} -o ${outputFile} --javap-service ${javapServicePath} --tree-sitter-java ${treeSitterJavaPath} --tree-sitter-kotlin ${treeSitterKotlinPath} --tree-sitter-scala ${treeSitterScalaPath}`, void 0, { timeout: timeoutMs });
103868
103962
  if (result.error)
103869
103963
  return void 0;
103870
103964
  const packageIds = JSON.parse(await readFile7(outputFile, "utf-8")).result;
@@ -103888,6 +103982,11 @@ var JavaCodeAwareVulnerabilityScanner = class _JavaCodeAwareVulnerabilityScanner
103888
103982
  async actuallyRunAnalysis(vulnerabilityAccessPaths, filteredDeps) {
103889
103983
  this.statusUpdater?.("Running analysis...");
103890
103984
  return withTmpDirectory("java-run-analysis", async (tmpDir) => {
103985
+ try {
103986
+ await ensureJdk8OrAbove();
103987
+ } catch (e) {
103988
+ return { type: "error", message: e.message };
103989
+ }
103891
103990
  const options = {
103892
103991
  apps: this.apps,
103893
103992
  deps: filteredDeps ?? this.deps,
@@ -103898,7 +103997,7 @@ var JavaCodeAwareVulnerabilityScanner = class _JavaCodeAwareVulnerabilityScanner
103898
103997
  const outputFile = resolve9(tmpDir, "output.json");
103899
103998
  await writeFile4(inputFile, JSON.stringify(options));
103900
103999
  const timeoutMs = this.timeoutInSeconds ? Math.max(this.timeoutInSeconds * 1.5, this.timeoutInSeconds + 30) * 1e3 : 750 * 1e3;
103901
- const result = await execNeverFail(cmdt`node ${classGraphAnalysisCliPath} runJvmReachabilityAnalysis -i ${inputFile} -o ${outputFile} --javap-service ${javapServicePath} --tree-sitter-java ${treeSitterJavaPath} --tree-sitter-kotlin ${treeSitterKotlinPath} --tree-sitter-scala ${treeSitterScalaPath}`, void 0, { timeout: timeoutMs });
104000
+ const result = await execNeverFail2(cmdt`node ${classGraphAnalysisCliPath} runJvmReachabilityAnalysis -i ${inputFile} -o ${outputFile} --javap-service ${javapServicePath} --tree-sitter-java ${treeSitterJavaPath} --tree-sitter-kotlin ${treeSitterKotlinPath} --tree-sitter-scala ${treeSitterScalaPath}`, void 0, { timeout: timeoutMs });
103902
104001
  if (result.error)
103903
104002
  return { type: "error", message: result.error.message ?? "unknown error" };
103904
104003
  const { success, error, analysisDiagnostics: diagnostics, vulnerablePaths, reachablePackageIds } = JSON.parse(await readFile7(outputFile, "utf-8")).result;
@@ -104018,7 +104117,7 @@ async function convertSocketArtifacts2(rootDir, artifacts, tmpDir) {
104018
104117
  if (mavenInstalled && pomFile) {
104019
104118
  try {
104020
104119
  const dependencyGetCmd = cmdt`mvn -f=${basename6(resolve9(rootDir, pomFile))} dependency:get -DgroupId=${groupId} -DartifactId=${artifactId} -Dpackaging=${type} -Dclassifier${classifier} -Dversion=${version3} -Dtransitive=false`;
104021
- await execNeverFail(dependencyGetCmd, dirname6(resolve9(rootDir, pomFile)));
104120
+ await execNeverFail2(dependencyGetCmd, dirname6(resolve9(rootDir, pomFile)));
104022
104121
  const mavenArtifact = getPathToArtifact(mavenLocalRepo, groupId, artifactId, type, classifier, version3);
104023
104122
  if (existsSync8(mavenArtifact))
104024
104123
  return mavenArtifact;
@@ -109287,7 +109386,7 @@ async function downloadDependenciesToDir(dependenciesToInstall, tmpDir) {
109287
109386
  do {
109288
109387
  failed = false;
109289
109388
  try {
109290
- const stdout = await runCommandResolveStdOut(cmdt`npm pack --json ${chunk2.map((dep) => {
109389
+ const stdout = await runCommandResolveStdOut2(cmdt`npm pack --json ${chunk2.map((dep) => {
109291
109390
  if (dep.resolutionString)
109292
109391
  return dep.resolutionString;
109293
109392
  return `${dep.name}@${dep.version}`;
@@ -109706,7 +109805,7 @@ async function runJellyAnalysis(mainProjectRoot, projectRoot, jellyOptions, reac
109706
109805
  `;
109707
109806
  if (PRINT_JELLY_COMMAND)
109708
109807
  logger.info("Jelly command:", jellyCmd.join(" "));
109709
- await runCommandResolveStdOut(
109808
+ await runCommandResolveStdOut2(
109710
109809
  jellyCmd,
109711
109810
  void 0,
109712
109811
  // If it is an experimental run, make sure to crash the process if Jelly takes more than 50% longer than the timeout.
@@ -109750,7 +109849,7 @@ async function runJellyPhantomDependencyAnalysis(projectRoot, options) {
109750
109849
  const jellyCmd = cmdt`node --max-old-space-size=${options.memoryLimitInMB}
109751
109850
  ${jellyExecutable} --basedir ${projectRoot} --modules-only --ignore-dependencies
109752
109851
  --reachable-json ${reachablePackagesFile} ${projectRoot}`;
109753
- await runCommandResolveStdOut(jellyCmd);
109852
+ await runCommandResolveStdOut2(jellyCmd);
109754
109853
  return JSON.parse(await readFile8(reachablePackagesFile, "utf-8")).packages;
109755
109854
  } finally {
109756
109855
  await rm2(tmpFolder, { recursive: true });
@@ -109764,7 +109863,7 @@ async function runJellyImportReachabilityAnalysis(baseDir, projectDir, options)
109764
109863
  const jellyCmd = cmdt`node --max-old-space-size=${options.memoryLimitInMB}
109765
109864
  ${jellyExecutable} --basedir ${baseDir} --modules-only
109766
109865
  --reachable-json ${reachableModulesFile} ${projectDir}`;
109767
- await runCommandResolveStdOut(jellyCmd);
109866
+ await runCommandResolveStdOut2(jellyCmd);
109768
109867
  return JSON.parse(await readFile8(reachableModulesFile, "utf-8"));
109769
109868
  } finally {
109770
109869
  await rm2(tmpFolder, { recursive: true });
@@ -109903,7 +110002,7 @@ var JSCodeAwareVulnerabilityScanner = class _JSCodeAwareVulnerabilityScanner {
109903
110002
  const tmpDir = mkdtempSync(join16(tmpdir2(), "run-on-dependency-chain"));
109904
110003
  const packageJsonFileLoc = join16(tmpDir, "package.json");
109905
110004
  await writeFile6(packageJsonFileLoc, JSON.stringify(packageJSONContent));
109906
- await exec("npm install -f --ignore-scripts", tmpDir);
110005
+ await exec2("npm install -f --ignore-scripts", tmpDir);
109907
110006
  const restWithoutLast = rest.slice(0, -1);
109908
110007
  const projectDir = join16(tmpDir, "node_modules", first2.packageName);
109909
110008
  const scanner = new _JSCodeAwareVulnerabilityScanner(tmpDir, projectDir, reachabilityAnalysisOptions);
@@ -110019,7 +110118,7 @@ var GoCodeAwareVulnerabilityScanner = class {
110019
110118
  throw new Error(`goana binary '${binaryName}' not found`);
110020
110119
  await pipeline(createReadStream(binaryPath), zlib2.createGunzip(), createWriteStream2(join17(tmpDir, "goana"), { mode: 493 }));
110021
110120
  const vulnAccPaths = uniq5(vulns.flatMap((v) => v.vulnerabilityAccessPaths));
110022
- const { error, stderr } = await execNeverFail(cmdt`${join17(tmpDir, "goana")}
110121
+ const { error, stderr } = await execNeverFail2(cmdt`${join17(tmpDir, "goana")}
110023
110122
  -output-vulnerabilities ${vulnsOutputFile}
110024
110123
  -output-diagnostics ${diagnosticsOutputFile}
110025
110124
  -output-reached-modules ${reachedModulesOutputFile}
@@ -110064,7 +110163,7 @@ ${stderr}`);
110064
110163
  const i3 = path10.lastIndexOf("/");
110065
110164
  return i3 === -1 ? { type: "golang" /* GOLANG */, name: path10, version: version3 } : { type: "golang" /* GOLANG */, namespace: path10.slice(0, i3), name: path10.slice(i3 + 1), version: version3 };
110066
110165
  }),
110067
- computeDetectedOccurrences: detectedOccurrencesFromAPMatches(result.matches, await runCommandResolveStdOut("go env GOMODCACHE") + sep2)
110166
+ computeDetectedOccurrences: detectedOccurrencesFromAPMatches(result.matches, await runCommandResolveStdOut2("go env GOMODCACHE") + sep2)
110068
110167
  };
110069
110168
  } finally {
110070
110169
  await rm4(tmpDir, { recursive: true, force: true });
@@ -110072,18 +110171,18 @@ ${stderr}`);
110072
110171
  }
110073
110172
  static async runOnDependencyChain([first2, ...rest], vuln, options = {}) {
110074
110173
  assert4(first2.version);
110075
- const { Dir, GoMod } = JSON.parse(await runCommandResolveStdOut(cmdt`go mod download -json ${first2.packageName}@v${first2.version}`));
110174
+ const { Dir, GoMod } = JSON.parse(await runCommandResolveStdOut2(cmdt`go mod download -json ${first2.packageName}@v${first2.version}`));
110076
110175
  const projectDir = await createTmpDirectory("go-run-on-dependency-chain-");
110077
110176
  try {
110078
110177
  await cp4(Dir, projectDir, { recursive: true });
110079
110178
  const projGoMod = resolve14(projectDir, "go.mod");
110080
110179
  if (!existsSync10(projGoMod))
110081
110180
  await cp4(GoMod, projGoMod);
110082
- await exec(cmdt`chmod --recursive +w ${projectDir}`);
110181
+ await exec2(cmdt`chmod --recursive +w ${projectDir}`);
110083
110182
  await runGoModTidy(projectDir);
110084
110183
  if (rest.length) {
110085
110184
  const replacements = rest.map((dep) => `-replace=${dep.packageName}=${dep.packageName}@v${dep.version}`);
110086
- await exec(cmdt`go mod edit ${replacements}`, projectDir);
110185
+ await exec2(cmdt`go mod edit ${replacements}`, projectDir);
110087
110186
  await runGoModTidy(projectDir);
110088
110187
  }
110089
110188
  const heuristic = GoanaHeuristics.NO_TESTS;
@@ -110116,7 +110215,7 @@ ${stderr}`);
110116
110215
  const { Module: { Path: Path2 } } = await getModuleInfo(dep);
110117
110216
  return `-replace=${Path2}=${dep}`;
110118
110217
  }));
110119
- await exec(cmdt`go mod edit ${replacements}`, projectDir);
110218
+ await exec2(cmdt`go mod edit ${replacements}`, projectDir);
110120
110219
  await runGoModTidy(projectDir);
110121
110220
  }
110122
110221
  const heuristic = GoanaHeuristics.NO_TESTS;
@@ -110426,7 +110525,7 @@ var RustCodeAwareVulnerabilityScanner = class _RustCodeAwareVulnerabilityScanner
110426
110525
  const outputFile = resolve15(tmpDir, "output.json");
110427
110526
  await writeFile7(inputFile, JSON.stringify(options));
110428
110527
  const timeoutMs = this.timeoutInSeconds ? Math.max(this.timeoutInSeconds * 1.5, this.timeoutInSeconds + 30) * 1e3 : 750 * 1e3;
110429
- const result = await execNeverFail(cmdt`node ${classGraphAnalysisCliPath} runRustDirectDependencyAnalysis -i ${inputFile} -o ${outputFile} --tree-sitter-rust ${treeSitterRustPath}`, void 0, { timeout: timeoutMs });
110528
+ const result = await execNeverFail2(cmdt`node ${classGraphAnalysisCliPath} runRustDirectDependencyAnalysis -i ${inputFile} -o ${outputFile} --tree-sitter-rust ${treeSitterRustPath}`, void 0, { timeout: timeoutMs });
110430
110529
  if (result.error)
110431
110530
  return void 0;
110432
110531
  const packageIds = JSON.parse(await readFile10(outputFile, "utf-8")).result;
@@ -110461,7 +110560,7 @@ var RustCodeAwareVulnerabilityScanner = class _RustCodeAwareVulnerabilityScanner
110461
110560
  const outputFile = resolve15(tmpDir, "output.json");
110462
110561
  await writeFile7(inputFile, JSON.stringify(options));
110463
110562
  const timeoutMs = this.timeoutInSeconds ? Math.max(this.timeoutInSeconds * 1.5, this.timeoutInSeconds + 30) * 1e3 : 750 * 1e3;
110464
- const result = await execNeverFail(cmdt`node ${classGraphAnalysisCliPath} runRustReachabilityAnalysis -i ${inputFile} -o ${outputFile} --tree-sitter-rust ${treeSitterRustPath}`, void 0, { timeout: timeoutMs });
110563
+ const result = await execNeverFail2(cmdt`node ${classGraphAnalysisCliPath} runRustReachabilityAnalysis -i ${inputFile} -o ${outputFile} --tree-sitter-rust ${treeSitterRustPath}`, void 0, { timeout: timeoutMs });
110465
110564
  if (result.error)
110466
110565
  return { type: "error", message: result.error.message ?? "unknown error" };
110467
110566
  const { success, error, analysisDiagnostics: diagnostics, vulnerablePaths, reachablePackageIds } = JSON.parse(await readFile10(outputFile, "utf-8")).result;
@@ -110596,7 +110695,7 @@ async function extractCargoCrate(crateFilePath, packageName, version3, tmpDir) {
110596
110695
  }
110597
110696
  }
110598
110697
  try {
110599
- await execAndLogOnFailure(["tar", "-xzf", crateFilePath], tmpDir);
110698
+ await execAndLogOnFailure2(["tar", "-xzf", crateFilePath], tmpDir);
110600
110699
  const cargoTomlPath = resolve15(packageDir, "Cargo.toml");
110601
110700
  const depCrateInfo = await getCrateInfo(cargoTomlPath);
110602
110701
  return [depCrateInfo.lib];
@@ -110876,7 +110975,7 @@ async function runWithJSHeuristics(cb) {
110876
110975
  return result;
110877
110976
  }
110878
110977
  async function getCurrentCommitHash(project) {
110879
- return (await runCommandResolveStdOut("git rev-parse HEAD", resolve16(COANA_REPOS_PATH(), project))).trim();
110978
+ return (await runCommandResolveStdOut2("git rev-parse HEAD", resolve16(COANA_REPOS_PATH(), project))).trim();
110880
110979
  }
110881
110980
  function detectedOccurrencesFromAPMatches(matches, pathPrefixToRemove) {
110882
110981
  for (const match2 of Object.values(matches))
@@ -110999,7 +111098,7 @@ ${vulnAccPaths.join("\n")}`);
110999
111098
  logger.debug(`With args: ${mambaladeArgs.slice(1).join(" ")}`);
111000
111099
  }
111001
111100
  try {
111002
- const { stderr } = await exec(mambaladeArgs, this.projectDir, { stdin: memlimitWrapper });
111101
+ const { stderr } = await exec2(mambaladeArgs, this.projectDir, { stdin: memlimitWrapper });
111003
111102
  logger.debug("Done running mambalade");
111004
111103
  const errors = stderr.split("\n").filter((line) => line.startsWith("ERROR:") && !/^ERROR: Excluded distribution/.test(line));
111005
111104
  if (errors.length > 0)
@@ -111123,7 +111222,7 @@ ${msg}`;
111123
111222
  const candidate = findBestWheel(packageName, version3, meta);
111124
111223
  if (candidate) {
111125
111224
  const filename = candidate.url.split("/").at(-1);
111126
- if (await downloadFile(candidate.url, join19(tmpDir, filename)) && await execAndLogOnFailure(["unzip", filename], tmpDir, void 0, "debug"))
111225
+ if (await downloadFile(candidate.url, join19(tmpDir, filename)) && await execAndLogOnFailure2(["unzip", filename], tmpDir, void 0, "debug"))
111127
111226
  return;
111128
111227
  }
111129
111228
  await execUvPipInstall(cmdt`uv pip install --python-platform ${uvPythonPlatform} --target ${tmpDir} --no-deps ${packageName}==${version3}`);
@@ -111177,7 +111276,7 @@ ${msg}`;
111177
111276
  const tmpDir = await createTmpDirectory("coana-python-analysis-venv");
111178
111277
  const virtualEnvFolder = join19(tmpDir, ".venv");
111179
111278
  const pythonExecutable = await this.vm.getPythonExecutableForWorkspace(this.projectDir, false);
111180
- await exec(cmdt`uv venv --python ${pythonExecutable} .venv`, tmpDir);
111279
+ await exec2(cmdt`uv venv --python ${pythonExecutable} .venv`, tmpDir);
111181
111280
  logger.debug("Virtual environment created at", virtualEnvFolder);
111182
111281
  const installStats = {
111183
111282
  installedUsingOnlyBinary: [],
@@ -111210,7 +111309,7 @@ ${msg}`;
111210
111309
  if (!candidate)
111211
111310
  return true;
111212
111311
  const filename = candidate.url.split("/").at(-1);
111213
- if (await downloadFile(candidate.url, join19(tmpDir, filename)) && await execAndLogOnFailure(cmdt`${uvTool(pythonExecutable)} --from installer==0.7.0 python -m installer
111312
+ if (await downloadFile(candidate.url, join19(tmpDir, filename)) && await execAndLogOnFailure2(cmdt`${uvTool(pythonExecutable)} --from installer==0.7.0 python -m installer
111214
111313
  --no-compile-bytecode --prefix .venv ${filename}`, tmpDir, void 0, "debug")) {
111215
111314
  installStats.installedUsingSpecializedInstallCommand.push(packageName);
111216
111315
  return false;
@@ -111228,7 +111327,7 @@ ${msg}`;
111228
111327
  let success = await execUvPipInstallAndLogOnFailure([...uvInstallBase, "--no-deps", "--no-binary", packageName, requirementToInstall], void 0, void 0, "debug");
111229
111328
  if (!success) {
111230
111329
  await installPipDeps();
111231
- success = await execAndLogOnFailure(
111330
+ success = await execAndLogOnFailure2(
111232
111331
  // Disable cache directory to prevent concurrent modifications when analyzing multiple Python projects in parallel.
111233
111332
  // --isolated is used to ignore environment variables and prevents the user's pip.conf from being used.
111234
111333
  cmdt`.venv/bin/python -m pip
@@ -111298,7 +111397,7 @@ for metadata_file in pathlib.Path("lib").glob(
111298
111397
 
111299
111398
  json.dump(result, sys.stdout)
111300
111399
  `;
111301
- return Object.fromEntries(JSON.parse(await runCommandResolveStdOut([systemPython(), "-SIc", prog], venvDir)).map(([name2, version3, distInfoDir]) => [normalizePackageName(name2), { version: version3, distInfoDir }]));
111400
+ return Object.fromEntries(JSON.parse(await runCommandResolveStdOut2([systemPython(), "-SIc", prog], venvDir)).map(([name2, version3, distInfoDir]) => [normalizePackageName(name2), { version: version3, distInfoDir }]));
111302
111401
  }
111303
111402
  function transformSourceLocations2(appPath, fileMappings, detectedOccurrences) {
111304
111403
  const entries = [...fileMappings.entries()];
@@ -111320,10 +111419,10 @@ function transformSourceLocations2(appPath, fileMappings, detectedOccurrences) {
111320
111419
  async function getPythonRequest() {
111321
111420
  for (const impl of ["pypy", "cpython"]) {
111322
111421
  const req = `${impl}>=3.11`;
111323
- let { stdout, error } = await execNeverFail(cmdt`uv python find --no-project --python-preference=system ${req}`);
111422
+ let { stdout, error } = await execNeverFail2(cmdt`uv python find --no-project --python-preference=system ${req}`);
111324
111423
  if (!error)
111325
111424
  return stdout.trim();
111326
- ({ error } = await execNeverFail(cmdt`uv python install ${req}`));
111425
+ ({ error } = await execNeverFail2(cmdt`uv python install ${req}`));
111327
111426
  if (!error)
111328
111427
  return req;
111329
111428
  }
@@ -111331,7 +111430,7 @@ async function getPythonRequest() {
111331
111430
  for (const cmd of ["pypy3", "python3"]) {
111332
111431
  const version3 = await getPythonVersion(cmd).catch(() => void 0);
111333
111432
  if (version3 && (0, import_semver3.satisfies)(version3, pythonVersionRequired))
111334
- return runCommandResolveStdOut(`which ${cmd}`);
111433
+ return runCommandResolveStdOut2(`which ${cmd}`);
111335
111434
  }
111336
111435
  throw new Error(`No Python ${pythonVersionRequired} interpreter found`);
111337
111436
  }
@@ -111340,7 +111439,7 @@ async function setupMambalade() {
111340
111439
  logger.debug("Creating Mambalade virtual environment");
111341
111440
  const python = await getPythonRequest();
111342
111441
  logger.debug(`Using Python interpreter: ${python}`);
111343
- await exec(cmdt`uv venv --python=${python} ${venvDir}`);
111442
+ await exec2(cmdt`uv venv --python=${python} ${venvDir}`);
111344
111443
  const mambaladeWheelsPath = join19(COANA_REPOS_PATH(), "mambalade", "dist");
111345
111444
  const mambaladeWheels = (await readdir4(mambaladeWheelsPath)).filter((f2) => f2.endsWith(".whl")).map((f2) => join19(mambaladeWheelsPath, f2));
111346
111445
  if (!mambaladeWheels.length)
@@ -111350,7 +111449,7 @@ async function setupMambalade() {
111350
111449
  logger.debug("Mambalade virtual environment setup complete");
111351
111450
  return venvDir;
111352
111451
  }
111353
- var hasUv = once3(async () => !(await execNeverFail("which uv")).error);
111452
+ var hasUv = once3(async () => !(await execNeverFail2("which uv")).error);
111354
111453
  function isSSLCertificateError(errorMessage) {
111355
111454
  return errorMessage.includes("invalid peer certificate") || errorMessage.includes("UnknownIssuer") || errorMessage.includes("certificate verify failed") || errorMessage.includes("SSL") || errorMessage.includes("TLS");
111356
111455
  }
@@ -111364,35 +111463,35 @@ function addNativeTlsFlag(args) {
111364
111463
  }
111365
111464
  async function execUvPipInstall(args, cwd) {
111366
111465
  try {
111367
- return await exec(args, cwd);
111466
+ return await exec2(args, cwd);
111368
111467
  } catch (e) {
111369
111468
  const errorMessage = e?.stderr ?? e?.message ?? "";
111370
111469
  if (isSSLCertificateError(errorMessage)) {
111371
111470
  logger.debug("SSL certificate error detected, retrying with --native-tls flag");
111372
- return await exec(addNativeTlsFlag(args), cwd);
111471
+ return await exec2(addNativeTlsFlag(args), cwd);
111373
111472
  }
111374
111473
  throw e;
111375
111474
  }
111376
111475
  }
111377
111476
  async function execUvPipInstallNeverFail(args, cwd) {
111378
- const result = await execNeverFail(args, cwd);
111477
+ const result = await execNeverFail2(args, cwd);
111379
111478
  if (result.error) {
111380
111479
  const errorMessage = result.stderr ?? result.error?.message ?? "";
111381
111480
  if (isSSLCertificateError(errorMessage)) {
111382
111481
  logger.debug("SSL certificate error detected, retrying with --native-tls flag");
111383
- return await execNeverFail(addNativeTlsFlag(args), cwd);
111482
+ return await execNeverFail2(addNativeTlsFlag(args), cwd);
111384
111483
  }
111385
111484
  }
111386
111485
  return result;
111387
111486
  }
111388
111487
  async function execUvPipInstallAndLogOnFailure(args, cwd, options, logLevel = "info") {
111389
- let success = await execAndLogOnFailure(args, cwd, options, logLevel);
111488
+ let success = await execAndLogOnFailure2(args, cwd, options, logLevel);
111390
111489
  if (!success) {
111391
- const result = await execNeverFail(args, cwd, options);
111490
+ const result = await execNeverFail2(args, cwd, options);
111392
111491
  const errorMessage = result.stderr ?? result.error?.message ?? "";
111393
111492
  if (isSSLCertificateError(errorMessage)) {
111394
111493
  logger.debug("SSL certificate error detected, retrying with --native-tls flag");
111395
- success = await execAndLogOnFailure(addNativeTlsFlag(args), cwd, options, logLevel);
111494
+ success = await execAndLogOnFailure2(addNativeTlsFlag(args), cwd, options, logLevel);
111396
111495
  }
111397
111496
  }
111398
111497
  return success;
@@ -111469,7 +111568,7 @@ print('\\n'.join(i for i in imports if i.partition('.')[0] not in sys.stdlib_mod
111469
111568
  async function processProject(projectDir) {
111470
111569
  const files = await findFilesToAnalyze(projectDir);
111471
111570
  return uniq8((await asyncMap(files, async (file) => {
111472
- const { stdout, error } = await execNeverFail([systemPython(), "-SIc", extractImportsProg, file], projectDir);
111571
+ const { stdout, error } = await execNeverFail2([systemPython(), "-SIc", extractImportsProg, file], projectDir);
111473
111572
  if (error) {
111474
111573
  logger.warn("Error extracting imports from '%s': %s", file, error);
111475
111574
  return [];
@@ -115560,7 +115659,7 @@ var RubyCodeAwareVulnerabilityScanner = class {
115560
115659
  logger.info("Ruby analysis command:", cmd.join(" "));
115561
115660
  try {
115562
115661
  this.numberAnalysesRun++;
115563
- await exec(cmd, this.projectDir);
115662
+ await exec2(cmd, this.projectDir);
115564
115663
  const result = JSON.parse(await readFile12(vulnsOutputFile, "utf-8"));
115565
115664
  const relativeLoadPathsToPackageNames = new Map([...loadPathsToPackageNames.entries()].map(([k, v]) => [join20("vendor", relative8(this.vendorDir, k)), v]));
115566
115665
  const { timedOut, ...diagnostics } = JSON.parse(await readFile12(diagnosticsOutputFile, "utf-8"));
@@ -115667,8 +115766,8 @@ async function downloadAndExtractGem(gemName, version3, vendorDir) {
115667
115766
  await pipeline2(response.body, createWriteStream3(tempGemFile));
115668
115767
  await mkdir8(gemDir, { recursive: true });
115669
115768
  logger.debug(`Extracting gem ${gemName}@${version3}`);
115670
- await exec(["tar", "-xf", tempGemFile, "data.tar.gz"], gemDir);
115671
- await exec(["tar", "-xzf", "data.tar.gz"], gemDir);
115769
+ await exec2(["tar", "-xf", tempGemFile, "data.tar.gz"], gemDir);
115770
+ await exec2(["tar", "-xzf", "data.tar.gz"], gemDir);
115672
115771
  await rm7(join20(gemDir, "data.tar.gz"));
115673
115772
  const hasValidStructure = [`${gemName}.gemspec`, "Rakefile", "lib"].some((f2) => existsSync14(join20(gemDir, f2)));
115674
115773
  if (!hasValidStructure)