// src/actions/deplint/packageJsonEditor.ts
import fs2 from "node:fs";
import chalk from "chalk";
import semver from "semver";
import sortPackageJson from "sort-package-json";

// src/actions/deplint/getRequiredPeerDependencies.ts
import fs from "node:fs";
import path from "node:path";
function findDepPackageJson(location, dep) {
  let dir = location;
  while (true) {
    const candidate = path.join(dir, "node_modules", dep, "package.json");
    if (fs.existsSync(candidate)) return candidate;
    const parent = path.dirname(dir);
    if (parent === dir) return void 0;
    dir = parent;
  }
}

// src/actions/deplint/packageJsonEditor.ts
function readPackageJson(location) {
  return JSON.parse(fs2.readFileSync(`${location}/package.json`, "utf8"));
}
function writePackageJson(location, pkg) {
  const sorted = sortPackageJson(JSON.stringify(pkg, null, 2));
  fs2.writeFileSync(`${location}/package.json`, `${sorted}
`);
}
function moveDep(pkg, dep, from, to) {
  const fromSection = pkg[from];
  if (!fromSection || !Object.hasOwn(fromSection, dep)) return;
  const version = fromSection[dep];
  delete fromSection[dep];
  if (Object.keys(fromSection).length === 0) {
    delete pkg[from];
  }
  const toSection = pkg[to] ?? {};
  toSection[dep] = version;
  pkg[to] = toSection;
  if (from === "peerDependencies" && to !== "peerDependencies") {
    removePeerMeta(pkg, dep);
  }
}
function removeDep(pkg, dep, section) {
  const sectionObj = pkg[section];
  if (!sectionObj || !Object.hasOwn(sectionObj, dep)) return;
  delete sectionObj[dep];
  if (Object.keys(sectionObj).length === 0) {
    delete pkg[section];
  }
  if (section === "peerDependencies") {
    removePeerMeta(pkg, dep);
  }
}
function addDep(pkg, dep, version, section) {
  const sectionObj = pkg[section] ?? {};
  sectionObj[dep] = version;
  pkg[section] = sectionObj;
}
function setPeerOptional(pkg, dep, optional) {
  if (optional === void 0) return;
  if (optional) {
    const meta2 = pkg.peerDependenciesMeta ?? {};
    const entry = meta2[dep] ?? {};
    entry.optional = true;
    meta2[dep] = entry;
    pkg.peerDependenciesMeta = meta2;
    return;
  }
  const meta = pkg.peerDependenciesMeta;
  if (!meta || !Object.hasOwn(meta, dep)) return;
  delete meta[dep].optional;
  if (Object.keys(meta[dep]).length === 0) {
    delete meta[dep];
  }
  if (Object.keys(meta).length === 0) {
    delete pkg.peerDependenciesMeta;
  }
}
function removePeerMeta(pkg, dep) {
  const meta = pkg.peerDependenciesMeta;
  if (!meta || !Object.hasOwn(meta, dep)) return;
  delete meta[dep];
  if (Object.keys(meta).length === 0) {
    delete pkg.peerDependenciesMeta;
  }
}
function formatPeerRange(version, boundType = "major") {
  const parsed = semver.parse(version);
  if (!parsed) return `~${version}`;
  if (boundType === "minor") return `>=${parsed.version} <${parsed.major}.${parsed.minor + 1}`;
  return `>=${parsed.version} <${parsed.major + 1}`;
}
function inferPeerBoundType(devRange) {
  return devRange?.startsWith("~") ?? false ? "minor" : "major";
}
function inferPeerShorthandPrefix(devRange) {
  if (!(devRange != null && devRange.length > 0)) return "~";
  if (devRange.startsWith("^")) return "^";
  if (devRange.startsWith("~")) return "~";
  const lower = semver.minVersion(devRange);
  if (!lower) return "~";
  const base = `${lower.major}.${lower.minor}`;
  try {
    if (!semver.subset(devRange, `~${base}`) && semver.subset(devRange, `^${base}`)) return "^";
  } catch {
  }
  return "~";
}
function readInstalledVersion(location, dep) {
  const depPkgPath = findDepPackageJson(location, dep);
  if (!(depPkgPath != null && depPkgPath.length > 0)) return void 0;
  try {
    const depPkg = JSON.parse(fs2.readFileSync(depPkgPath, "utf8"));
    return depPkg.version;
  } catch {
    return void 0;
  }
}
function resolvePeerLowerBound(location, dep, devRange) {
  if (devRange != null && devRange.length > 0 && devRange !== "*" && !devRange.startsWith("workspace:") && !devRange.startsWith("catalog:") && !devRange.startsWith("npm:")) {
    try {
      const min = semver.minVersion(devRange);
      if (min) return min.version;
    } catch {
    }
  }
  return readInstalledVersion(location, dep);
}
function resolveDepVersion(location, dep) {
  const version = readInstalledVersion(location, dep);
  return version != null && version.length > 0 ? `~${version}` : "*";
}
function resolvePeerDepVersion(location, dep, devRange) {
  const lower = resolvePeerLowerBound(location, dep, devRange);
  return lower != null && lower.length > 0 ? formatPeerRange(lower, inferPeerBoundType(devRange)) : "*";
}
function resolveExpectedPeerVersion(location, dep, devRange, boundType) {
  const lower = resolvePeerLowerBound(location, dep, devRange);
  return lower != null && lower.length > 0 ? formatPeerRange(lower, boundType ?? inferPeerBoundType(devRange)) : "*";
}
function resolveExpectedPeerShorthandVersion(location, dep, devRange) {
  const lower = resolvePeerLowerBound(location, dep, devRange);
  if (!(lower != null && lower.length > 0)) return "*";
  const parsed = semver.parse(lower);
  if (!parsed) return devRange != null && devRange.length > 0 && devRange !== "*" ? devRange : `~${lower}`;
  return `${inferPeerShorthandPrefix(devRange)}${parsed.major}.${parsed.minor}`;
}
function resolvePeerVersionForFix(location, dep, devRange, form, boundType) {
  return form === "broad" ? resolveExpectedPeerVersion(location, dep, devRange, boundType) : resolveExpectedPeerShorthandVersion(location, dep, devRange);
}
function resolveExpectedDevVersion(location, dep) {
  const version = readInstalledVersion(location, dep);
  if (!(version != null && version.length > 0)) return "*";
  const match = /^(\d+)\.(\d+)/.exec(version);
  return match ? `~${match[1]}.${match[2]}` : `~${version}`;
}
function logFix(workspace, action, dep, detail) {
  const detailStr = detail != null && detail.length > 0 ? ` (${detail})` : "";
  console.log(`[${chalk.blue(workspace.name)}] Fixed: ${action} ${chalk.green(dep)}${detailStr}`);
}
export {
  addDep,
  formatPeerRange,
  logFix,
  moveDep,
  readPackageJson,
  removeDep,
  resolveDepVersion,
  resolveExpectedDevVersion,
  resolveExpectedPeerShorthandVersion,
  resolveExpectedPeerVersion,
  resolvePeerDepVersion,
  resolvePeerVersionForFix,
  setPeerOptional,
  writePackageJson
};
//# sourceMappingURL=packageJsonEditor.mjs.map
