// src/actions/package-lint-engines.ts
import { readFileSync, writeFileSync } from "node:fs";
import PATH from "node:path";
import chalk from "chalk";
import semver from "semver";

// src/lib/latestVersions.ts
var latestVersions = {
  node: "24.14.1",
  nodeLtsCodename: "Krypton",
  npm: "11.11.0",
  pnpm: "10.33.0",
  yarn: "4.13.0"
};

// src/actions/package-lint-engines.ts
function emptyResult() {
  return {
    errors: [],
    fixable: [],
    warnings: []
  };
}
function isTerminalPackage(pkg) {
  return pkg.private === true;
}
function checkVoltaOnlyInRoot(cwd, workspaces) {
  const result = emptyResult();
  for (const { location, name } of workspaces) {
    if (location === ".") continue;
    const pkgPath = PATH.resolve(cwd, location, "package.json");
    try {
      const pkg = JSON.parse(readFileSync(pkgPath, "utf8"));
      if (Boolean(pkg.volta)) {
        result.fixable.push(`${name} (${location}) has a volta field \u2014 only the root should define this`);
      }
    } catch {
    }
  }
  return result;
}
function fixVoltaOnlyInRoot(cwd, _pkg, workspaces) {
  for (const { location } of workspaces) {
    if (location === ".") continue;
    const pkgPath = PATH.resolve(cwd, location, "package.json");
    try {
      const raw = readFileSync(pkgPath, "utf8");
      const pkg = JSON.parse(raw);
      if (Boolean(pkg.volta)) {
        delete pkg.volta;
        writeFileSync(pkgPath, `${JSON.stringify(pkg, null, 2)}
`, "utf8");
        console.log(chalk.green(`  \u2714 Fixed: removed volta from ${location}/package.json`));
      }
    } catch {
    }
  }
}
function checkEnginesOnlyInNonTerminal(cwd, workspaces) {
  const result = emptyResult();
  const rootPkg = JSON.parse(readFileSync(PATH.resolve(cwd, "package.json"), "utf8"));
  if (Boolean(rootPkg.engines)) {
    result.fixable.push("Root package.json has engines \u2014 terminal packages should not declare engines (use volta instead)");
  }
  for (const { location, name } of workspaces) {
    if (location === ".") continue;
    const pkgPath = PATH.resolve(cwd, location, "package.json");
    try {
      const pkg = JSON.parse(readFileSync(pkgPath, "utf8"));
      if (isTerminalPackage(pkg) && Boolean(pkg.engines)) {
        result.fixable.push(`${name} (${location}) is terminal (private) but has engines \u2014 terminal packages should not declare engines`);
      }
      if (!isTerminalPackage(pkg) && !Boolean(pkg.engines)) {
        result.fixable.push(`${name} (${location}) is a library but has no engines field`);
      }
    } catch {
    }
  }
  return result;
}
function resolveEnginesTemplate(cwd, workspaces) {
  for (const { location } of workspaces) {
    if (location === ".") continue;
    try {
      const pkg = JSON.parse(readFileSync(PATH.resolve(cwd, location, "package.json"), "utf8"));
      if (!isTerminalPackage(pkg) && Boolean(pkg.engines)) {
        return pkg.engines;
      }
    } catch {
    }
  }
  return void 0;
}
function fixEnginesOnlyInNonTerminal(cwd, _pkg, workspaces) {
  const rootPath = PATH.resolve(cwd, "package.json");
  const rootRaw = readFileSync(rootPath, "utf8");
  const rootPkg = JSON.parse(rootRaw);
  if (Boolean(rootPkg.engines)) {
    delete rootPkg.engines;
    writeFileSync(rootPath, `${JSON.stringify(rootPkg, null, 2)}
`, "utf8");
    console.log(chalk.green("  \u2714 Fixed: removed engines from root package.json"));
  }
  const enginesTemplate = resolveEnginesTemplate(cwd, workspaces);
  for (const { location } of workspaces) {
    if (location === ".") continue;
    const pkgPath = PATH.resolve(cwd, location, "package.json");
    try {
      const raw = readFileSync(pkgPath, "utf8");
      const pkg = JSON.parse(raw);
      if (isTerminalPackage(pkg) && Boolean(pkg.engines)) {
        delete pkg.engines;
        writeFileSync(pkgPath, `${JSON.stringify(pkg, null, 2)}
`, "utf8");
        console.log(chalk.green(`  \u2714 Fixed: removed engines from ${location}/package.json`));
      }
      if (!isTerminalPackage(pkg) && !Boolean(pkg.engines) && enginesTemplate) {
        pkg.engines = enginesTemplate;
        writeFileSync(pkgPath, `${JSON.stringify(pkg, null, 2)}
`, "utf8");
        console.log(chalk.green(`  \u2714 Fixed: added engines to ${location}/package.json`));
      }
    } catch {
    }
  }
}
function checkVersionsIncludeLts(cwd, workspaces) {
  const result = emptyResult();
  const toolVersions = {
    node: latestVersions.node,
    npm: latestVersions.npm,
    pnpm: latestVersions.pnpm,
    yarn: latestVersions.yarn
  };
  for (const { location, name } of workspaces) {
    const pkgPath = location === "." ? PATH.resolve(cwd, "package.json") : PATH.resolve(cwd, location, "package.json");
    try {
      const pkg = JSON.parse(readFileSync(pkgPath, "utf8"));
      const label = location === "." ? "root" : `${name} (${location})`;
      const engines = pkg.engines;
      if (engines) {
        for (const [tool, range] of Object.entries(engines)) {
          const latest = toolVersions[tool];
          if (latest && !semver.satisfies(latest, range)) {
            result.errors.push(
              `${label} engines.${tool} "${range}" does not include latest ${tool === "node" ? "LTS " : ""}version ${latest}`
            );
          }
        }
      }
      const volta = pkg.volta;
      if (volta) {
        for (const [tool, pinnedVersion] of Object.entries(volta)) {
          const latest = toolVersions[tool];
          if (latest && semver.lt(pinnedVersion, latest)) {
            result.warnings.push(
              `${label} volta.${tool} "${pinnedVersion}" is older than latest ${tool === "node" ? "LTS " : ""}version ${latest}`
            );
          }
        }
      }
    } catch {
    }
  }
  return result;
}
export {
  checkEnginesOnlyInNonTerminal,
  checkVersionsIncludeLts,
  checkVoltaOnlyInRoot,
  fixEnginesOnlyInNonTerminal,
  fixVoltaOnlyInRoot
};
//# sourceMappingURL=package-lint-engines.mjs.map
