// src/lib/dependencies/workspaceCycles.ts
import { readFileSync } from "node:fs";
import PATH from "node:path";
import chalk from "chalk";
function detectWorkspaceCycles(workspaces) {
  const workspaceNames = new Set(workspaces.map((ws) => ws.name));
  const graph = /* @__PURE__ */ new Map();
  for (const ws of workspaces) {
    const pkgPath = PATH.join(ws.location, "package.json");
    const pkg = JSON.parse(readFileSync(pkgPath, "utf8"));
    const deps = pkg.dependencies ?? {};
    const devDeps = pkg.devDependencies ?? {};
    const edges = [];
    for (const dep of Object.keys(deps)) {
      if (workspaceNames.has(dep)) edges.push({ name: dep, type: "dep" });
    }
    for (const dep of Object.keys(devDeps)) {
      if (workspaceNames.has(dep)) edges.push({ name: dep, type: "devDep" });
    }
    graph.set(ws.name, edges);
  }
  const WHITE = 0;
  const GRAY = 1;
  const BLACK = 2;
  const color = /* @__PURE__ */ new Map();
  const cycles = [];
  const path = [];
  const onPath = /* @__PURE__ */ new Set();
  for (const name of workspaceNames) color.set(name, WHITE);
  function dfs(u, incomingEdgeType) {
    color.set(u, GRAY);
    onPath.add(u);
    path.push({ name: u, edgeType: incomingEdgeType });
    for (const edge of graph.get(u) ?? []) {
      const v = edge.name;
      if (onPath.has(v)) {
        const cycleEdges = [];
        const startIdx = path.findIndex((p) => p.name === v);
        for (let i = startIdx; i < path.length - 1; i++) {
          const nextEdgeType = path[i + 1].edgeType ?? "dep";
          cycleEdges.push({
            from: path[i].name,
            to: path[i + 1].name,
            type: nextEdgeType
          });
        }
        cycleEdges.push({
          from: u,
          to: v,
          type: edge.type
        });
        cycles.push(cycleEdges);
      } else if (color.get(v) === WHITE) {
        dfs(v, edge.type);
      }
    }
    path.pop();
    onPath.delete(u);
    color.set(u, BLACK);
  }
  for (const name of workspaceNames) {
    if (color.get(name) === WHITE) dfs(name);
  }
  return cycles;
}
function printWorkspaceCycles(cycles) {
  for (const cycle of cycles) {
    console.error(chalk.red("  Workspace dependency cycle:"));
    for (const edge of cycle) {
      const edgeLabel = edge.type === "devDep" ? chalk.yellow("devDep") : chalk.cyan("dep");
      console.error(`    ${chalk.white(edge.from)} --(${edgeLabel})--> ${chalk.white(edge.to)}`);
    }
  }
}
export {
  detectWorkspaceCycles,
  printWorkspaceCycles
};
//# sourceMappingURL=workspaceCycles.mjs.map
