// src/actions/deplint/checkPackage/getUnusedDependencies.ts
import chalk2 from "chalk";

// src/actions/deplint/getRequiredPeerDependencies.ts
import fs from "fs";
import path from "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;
  }
}
function getRequiredPeerDependencies(location, allDeps) {
  const required = /* @__PURE__ */ new Set();
  for (const dep of allDeps) {
    const depPkgPath = findDepPackageJson(location, dep);
    if (!depPkgPath) continue;
    try {
      const raw = fs.readFileSync(depPkgPath, "utf8");
      const pkg = JSON.parse(raw);
      const peerDeps = pkg.peerDependencies;
      if (peerDeps) {
        for (const peer of Object.keys(peerDeps)) {
          required.add(peer);
        }
      }
    } catch {
    }
  }
  return required;
}

// src/actions/deplint/packageJsonEditor.ts
import fs2 from "fs";
import chalk from "chalk";
import sortPackageJson from "sort-package-json";
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?.[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;
}
function removeDep(pkg, dep, section) {
  const sectionObj = pkg[section];
  if (!sectionObj?.[dep]) return;
  delete sectionObj[dep];
  if (Object.keys(sectionObj).length === 0) {
    delete pkg[section];
  }
}
function logFix(workspace, action, dep, detail) {
  const detailStr = detail ? ` (${detail})` : "";
  console.log(`[${chalk.blue(workspace.name)}] Fixed: ${action} ${chalk.green(dep)}${detailStr}`);
}

// src/actions/deplint/tsScriptsAliases.ts
var VARIANT_MAP = {
  "@xylabs/ts-scripts-yarn3": "@xylabs/ts-scripts-pnpm",
  "@xylabs/ts-scripts-pnpm": "@xylabs/ts-scripts-yarn3",
  "@xylabs/ts-scripts-react-yarn3": "@xylabs/ts-scripts-react-pnpm",
  "@xylabs/ts-scripts-react-pnpm": "@xylabs/ts-scripts-react-yarn3"
};
function isUsedViaTsScriptsVariant(dep, imports) {
  const variant = VARIANT_MAP[dep];
  return variant !== void 0 && imports.includes(variant);
}

// src/actions/deplint/checkPackage/getUnusedDependencies.ts
function isDepImported(dep, distImports, distTypeImports) {
  const baseName = dep.replace(/^@types\//, "");
  return distImports.includes(dep) || distImports.includes(baseName) || distTypeImports.includes(dep) || distTypeImports.includes(baseName);
}
function findUnusedDependencies(location, dependencies, devDependencies, externalDistImports, externalDistTypeImports, externalAllImports, exclude) {
  const runtimeRequiredPeers = getRequiredPeerDependencies(location, dependencies);
  const devRequiredPeers = getRequiredPeerDependencies(location, devDependencies);
  const results = [];
  for (const dep of dependencies) {
    if (exclude?.has(dep)) continue;
    if (runtimeRequiredPeers.has(dep)) continue;
    const isImported = isDepImported(dep, externalDistImports, externalDistTypeImports);
    if (isImported || isUsedViaTsScriptsVariant(dep, [...externalDistImports, ...externalDistTypeImports])) continue;
    if (devRequiredPeers.has(dep)) {
      results.push({
        dep,
        kind: "move-to-dev",
        reason: "only needed as peer of devDependencies"
      });
    } else if (externalAllImports.includes(dep)) {
      results.push({ dep, kind: "move-to-dev" });
    } else {
      results.push({ dep, kind: "remove" });
    }
  }
  return results;
}
function getUnusedDependencies({ name, location }, { dependencies, devDependencies }, {
  externalDistImports,
  externalDistTypeImports,
  externalAllImports
}, exclude) {
  const unused = findUnusedDependencies(location, dependencies, devDependencies, externalDistImports, externalDistTypeImports, externalAllImports, exclude);
  for (const {
    dep,
    kind,
    reason
  } of unused) {
    const reasonStr = reason ? ` (${reason})` : "";
    if (kind === "move-to-dev") {
      console.log(`[${chalk2.blue(name)}] dependency should be devDependency in package.json: ${chalk2.red(dep)}${reasonStr}`);
    } else {
      console.log(`[${chalk2.blue(name)}] Unused dependency in package.json: ${chalk2.red(dep)}`);
    }
  }
  if (unused.length > 0) {
    console.log(`  ${chalk2.yellow(`${location}/package.json`)}
`);
  }
  return unused.length;
}
function fixUnusedDependencies(workspace, { dependencies, devDependencies }, {
  externalDistImports,
  externalDistTypeImports,
  externalAllImports
}, exclude) {
  const unused = findUnusedDependencies(workspace.location, dependencies, devDependencies, externalDistImports, externalDistTypeImports, externalAllImports, exclude);
  if (unused.length === 0) return 0;
  const pkg = readPackageJson(workspace.location);
  for (const { dep, kind } of unused) {
    if (kind === "move-to-dev") {
      moveDep(pkg, dep, "dependencies", "devDependencies");
      logFix(workspace, "moved to devDependencies", dep);
    } else {
      removeDep(pkg, dep, "dependencies");
      logFix(workspace, "removed from dependencies", dep);
    }
  }
  writePackageJson(workspace.location, pkg);
  return unused.length;
}
export {
  findUnusedDependencies,
  fixUnusedDependencies,
  getUnusedDependencies
};
//# sourceMappingURL=getUnusedDependencies.mjs.map