// 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 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("~") ? "minor" : "major";
}
function inferPeerShorthandPrefix(devRange) {
  if (!devRange) 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) 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 && 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 ? `~${version}` : "*";
}
function resolveExpectedPeerVersion(location, dep, devRange, boundType) {
  const lower = resolvePeerLowerBound(location, dep, devRange);
  return lower ? formatPeerRange(lower, boundType ?? inferPeerBoundType(devRange)) : "*";
}
function resolveExpectedPeerShorthandVersion(location, dep, devRange) {
  const lower = resolvePeerLowerBound(location, dep, devRange);
  if (!lower) return "*";
  const parsed = semver.parse(lower);
  if (!parsed) return devRange && 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);
}

// src/actions/deplint/checkPackage/getUnlistedDependencies.ts
import chalk2 from "chalk";
function shouldBePeerDependency(imp, _location, _currentPeers, _distImports, workspaceNames) {
  if (workspaceNames?.has(imp)) return false;
  if (imp.startsWith("@types/")) return false;
  return true;
}

// src/actions/deplint/rulesDiagnostic.ts
function resolvedAddFix(context, dependency, section, detail, optional) {
  const devRange = context.packageParams.devDependencyVersions[dependency];
  const version = section === "peerDependencies" ? resolvePeerVersionForFix(
    context.workspace.location,
    dependency,
    devRange,
    context.peerRangeForm,
    context.peerRangeBound
  ) : resolveDepVersion(context.workspace.location, dependency);
  return {
    action: "add",
    dependency,
    detail,
    ...section === "peerDependencies" && optional !== void 0 ? { optional } : {},
    section,
    version
  };
}

// src/actions/deplint/rulesMisplaced.ts
var misplacedDependenciesRule = {
  category: "dependencies",
  id: "deplint.dependencies.misplaced",
  meta: {
    description: "Dependencies declared in the wrong package.json section",
    fixable: ["manifest"],
    severity: "error"
  },
  evaluate(context) {
    for (const dep of context.packageParams.dependencies) {
      if (context.forceDevs.has(dep)) {
        context.report({
          data: { dep, mode: "to-dev" },
          dependency: dep,
          message: `dependency ${dep} should be a devDependency \u2014 configured as refType "dev"`
        });
        continue;
      }
      if (context.isTerminalPackage) continue;
      if (context.forceDeps.has(dep)) continue;
      if (context.packageParams.dependencyVersions[dep]?.startsWith("workspace:")) continue;
      if (context.forcePeers.has(dep) || shouldBePeerDependency(dep, context.workspace.location, context.packageParams.peerDependencies, context.sourceParams.externalDistImports, context.workspaceNames)) {
        const reason = context.forcePeers.has(dep) ? 'configured as refType "peer"' : "external runtime dep \u2014 consumers should control the version";
        context.report({
          data: {
            dep,
            mode: "to-peer",
            needsDevCompanion: !context.packageParams.devDependencies.includes(dep)
          },
          dependency: dep,
          message: `dependency ${dep} should be a peerDependency \u2014 ${reason}`
        });
      }
    }
  },
  resolveFixes(diagnostic, context) {
    const data = diagnostic.data;
    if (!data) return [];
    if (data.mode === "to-dev") {
      return [{
        action: "move",
        dependency: data.dep,
        detail: "moved from dependencies to devDependencies",
        fromSection: "dependencies",
        toSection: "devDependencies"
      }];
    }
    const optional = context.forcePeerOptional.get(data.dep);
    const fixes = [{
      action: "move",
      dependency: data.dep,
      detail: "moved from dependencies to peerDependencies",
      fromSection: "dependencies",
      ...optional === void 0 ? {} : { optional },
      toSection: "peerDependencies"
    }];
    if (data.needsDevCompanion) {
      fixes.push(resolvedAddFix(context, data.dep, "devDependencies", "added to devDependencies"));
    }
    return fixes;
  }
};
var misplacedPeerDependenciesRule = {
  category: "peerDependencies",
  id: "deplint.peerDependencies.misplaced",
  meta: {
    description: "Peer dependencies declared in the wrong package.json section",
    fixable: ["manifest"],
    severity: "error"
  },
  evaluate(context) {
    for (const dep of context.packageParams.peerDependencies) {
      const version = context.packageParams.peerDependencyVersions[dep] ?? (context.workspaceNames?.has(dep) ? "workspace:~" : "*");
      if (context.forceDeps.has(dep)) {
        const alreadyIn = context.packageParams.dependencies.includes(dep);
        context.report({
          data: {
            alreadyInTarget: alreadyIn,
            dep,
            mode: "to-dep",
            version
          },
          dependency: dep,
          message: `peerDependency ${dep} should be a dependency \u2014 configured as refType "dep"`
        });
        continue;
      }
      if (context.forceDevs.has(dep)) {
        const alreadyIn = context.packageParams.devDependencies.includes(dep);
        context.report({
          data: {
            alreadyInTarget: alreadyIn,
            dep,
            mode: "to-dev",
            version
          },
          dependency: dep,
          message: `peerDependency ${dep} should be a devDependency \u2014 configured as refType "dev"`
        });
        continue;
      }
      if (context.workspaceNames?.has(dep) && !context.forcePeers.has(dep)) {
        const alreadyIn = context.packageParams.dependencies.includes(dep);
        context.report({
          data: {
            alreadyInTarget: alreadyIn,
            dep,
            mode: "to-dep",
            version
          },
          dependency: dep,
          message: `peerDependency ${dep} should be a dependency \u2014 sibling workspace packages ship in lockstep; set refType "peer" in xy.config.ts to override`
        });
      }
    }
  },
  resolveFixes(diagnostic) {
    const data = diagnostic.data;
    if (!data) return [];
    if (data.alreadyInTarget) {
      return [{
        action: "remove",
        dependency: data.dep,
        detail: `removed from peerDependencies (already in ${data.mode === "to-dep" ? "dependencies" : "devDependencies"})`,
        section: "peerDependencies"
      }];
    }
    return [{
      action: "move",
      dependency: data.dep,
      detail: data.mode === "to-dep" ? "moved from peerDependencies to dependencies" : "moved from peerDependencies to devDependencies",
      fromSection: "peerDependencies",
      toSection: data.mode === "to-dep" ? "dependencies" : "devDependencies",
      version: data.version
    }];
  }
};
export {
  misplacedDependenciesRule,
  misplacedPeerDependenciesRule
};
//# sourceMappingURL=rulesMisplaced.mjs.map
