// src/actions/deplint/deplint.ts
import chalk16 from "chalk";

// src/lib/packageManagerRuntime.ts
import { spawnSync } from "child_process";
import fs from "fs";
import chalk from "chalk";
var DISPLAY_NAMES = {
  bun: "Bun",
  npm: "npm",
  pnpm: "pnpm",
  yarn: "Yarn"
};
var MAC_INSTALL_COMMANDS = {
  bun: "brew install oven-sh/bun/bun",
  npm: "brew install node",
  pnpm: "brew install pnpm",
  yarn: "brew install yarn"
};
function currentPlatform() {
  if (process.platform === "darwin" || process.platform === "linux" || process.platform === "win32") {
    return process.platform;
  }
  return "unknown";
}
function askYesNo(question) {
  if (!process.stdin.isTTY || !process.stdout.isTTY) {
    return false;
  }
  process.stdout.write(question);
  const buffer = Buffer.alloc(1024);
  const bytesRead = fs.readSync(process.stdin.fd, buffer, 0, buffer.length, null);
  const answer = buffer.toString("utf8", 0, bytesRead).trim().toLowerCase();
  return answer === "y" || answer === "yes";
}
function isCommandInstalled(command) {
  const result = spawnSync(command, ["--version"], {
    encoding: "utf8",
    shell: false,
    stdio: "ignore"
  });
  return !result.error && result.status === 0;
}
function isPackageManagerInstalled(pm) {
  return isCommandInstalled(pm);
}
function getPackageManagerInstallPlan(pm, platform = currentPlatform()) {
  const displayName = DISPLAY_NAMES[pm];
  if (platform === "darwin") {
    const command = MAC_INSTALL_COMMANDS[pm];
    return {
      command,
      manualInstructions: [
        `Install ${displayName} with: ${command}`
      ],
      packageManager: pm,
      platform,
      supported: true
    };
  }
  if (platform === "linux") {
    return {
      manualInstructions: [
        `Automatic installation for ${displayName} is not implemented on Linux yet.`,
        `Install ${displayName} manually and re-run the command.`
      ],
      packageManager: pm,
      platform,
      supported: false
    };
  }
  if (platform === "win32") {
    return {
      manualInstructions: [
        `Automatic installation for ${displayName} is not implemented on Windows yet.`,
        `Install ${displayName} manually and re-run the command.`
      ],
      packageManager: pm,
      platform,
      supported: false
    };
  }
  return {
    manualInstructions: [
      `Automatic installation for ${displayName} is not implemented on ${platform} yet.`,
      `Install ${displayName} manually and re-run the command.`
    ],
    packageManager: pm,
    platform,
    supported: false
  };
}
function printManualInstructions(plan, context) {
  console.error(chalk.yellow(`${DISPLAY_NAMES[plan.packageManager]} is required for "${context.operation}".`));
  for (const line of plan.manualInstructions) {
    console.error(chalk.gray(`  ${line}`));
  }
}
function installWithHomebrew(pm, cwd) {
  const command = MAC_INSTALL_COMMANDS[pm];
  const result = spawnSync("brew", command.replace("brew ", "").split(" "), {
    cwd,
    encoding: "utf8",
    shell: false,
    stdio: "inherit"
  });
  return result.status === 0;
}
function ensurePackageManagerInstalled(pm, context) {
  if (isPackageManagerInstalled(pm)) return true;
  const plan = getPackageManagerInstallPlan(pm, context.platform ?? currentPlatform());
  const displayName = DISPLAY_NAMES[pm];
  console.error(chalk.yellow(`${context.operation} requires ${displayName}, but it is not installed.`));
  if (!plan.supported) {
    printManualInstructions(plan, context);
    return false;
  }
  if (!isCommandInstalled("brew")) {
    console.error(chalk.yellow("Homebrew is not installed, so automatic installation is unavailable."));
    console.error(chalk.gray("  Install Homebrew from https://brew.sh and then run:"));
    console.error(chalk.gray(`  ${plan.command}`));
    return false;
  }
  const confirmed = askYesNo(chalk.cyan(`Install ${displayName} with Homebrew now? [y/N] `));
  if (!confirmed) {
    console.error(chalk.gray(`Skipping install. Run "${plan.command}" manually and then retry.`));
    return false;
  }
  console.error(chalk.cyan(`Installing ${displayName} via Homebrew...
`));
  if (!installWithHomebrew(pm, context.cwd)) {
    console.error(chalk.red(`Homebrew failed to install ${displayName}.`));
    console.error(chalk.gray(`Run "${plan.command}" manually and then retry.`));
    return false;
  }
  if (!isPackageManagerInstalled(pm)) {
    console.error(chalk.red(`${displayName} still does not appear to be installed after Homebrew completed.`));
    console.error(chalk.gray(`Run "${plan.command}" manually and then retry.`));
    return false;
  }
  console.error(chalk.green(`${displayName} installed successfully.`));
  return true;
}
function failureResult() {
  return {
    output: ["", ""],
    pid: 0,
    signal: null,
    status: 1,
    stderr: "",
    stdout: ""
  };
}
function spawnPackageManagerSync(pm, args, options) {
  if (!ensurePackageManagerInstalled(pm, options.context)) {
    return failureResult();
  }
  return spawnSync(pm, args, { encoding: "utf8", ...options });
}

// src/pm/workspaces.ts
import { existsSync, readFileSync } from "fs";
import PATH from "path";
import { globSync } from "glob";
function readJsonFile(path6) {
  if (!existsSync(path6)) return void 0;
  try {
    return JSON.parse(readFileSync(path6, "utf8"));
  } catch {
    return void 0;
  }
}
function readRootPackageJson(cwd = process.cwd()) {
  return readJsonFile(PATH.resolve(cwd, "package.json"));
}
function detectPackageManagerFromPackageJson(cwd = process.cwd()) {
  const packageManager = readRootPackageJson(cwd)?.packageManager;
  if (!packageManager) return void 0;
  return packageManager.split("@")[0];
}

// src/pm/detectPackageManager.ts
import { existsSync as existsSync2 } from "fs";
var knownPackageManagers = /* @__PURE__ */ new Set(["bun", "npm", "pnpm", "yarn"]);
function detectPackageManager() {
  const packageManager = detectPackageManagerFromPackageJson();
  if (packageManager && knownPackageManagers.has(packageManager)) {
    return packageManager;
  }
  if (existsSync2("pnpm-lock.yaml") || existsSync2("pnpm-workspace.yaml")) return "pnpm";
  if (existsSync2("bun.lock") || existsSync2("bun.lockb")) return "bun";
  if (existsSync2("yarn.lock") || existsSync2(".yarnrc.yml")) return "yarn";
  if (existsSync2("package-lock.json") || existsSync2("npm-shrinkwrap.json")) return "npm";
  return "yarn";
}

// src/pm/registry.ts
var implementations = /* @__PURE__ */ new Map();
function getPackageManager(name) {
  const pmName = name ?? detectPackageManager();
  const pm = implementations.get(pmName);
  if (!pm) {
    throw new Error(
      `No package manager implementation registered for "${pmName}". Ensure registerPackageManager() has been called before getPackageManager().`
    );
  }
  return pm;
}

// src/lib/loadConfig.ts
import chalk2 from "chalk";
import { cosmiconfig } from "cosmiconfig";
import { TypeScriptLoader } from "cosmiconfig-typescript-loader";
import deepmerge from "deepmerge";
var config;
var rootConfigPath;
var workspaceConfigCache = /* @__PURE__ */ new Map();
var deprecationWarned = /* @__PURE__ */ new Set();
function createExplorer() {
  return cosmiconfig("xy", { cache: true, loaders: { ".ts": TypeScriptLoader() } });
}
var loadConfig = async (params) => {
  if (config === void 0) {
    const cosmicConfigResult = await createExplorer().search();
    config = cosmicConfigResult?.config ?? {};
    rootConfigPath = cosmicConfigResult?.filepath;
    const configFilePath = cosmicConfigResult?.filepath;
    if (configFilePath !== void 0) {
      console.log(chalk2.green(`Loaded config from ${configFilePath}`));
      if (config.verbose) {
        console.log(chalk2.gray(`${JSON.stringify(config, null, 2)}`));
      }
    }
  }
  return deepmerge(config, params ?? {});
};
async function loadWorkspaceConfig(workspaceDir) {
  const cached = workspaceConfigCache.get(workspaceDir);
  if (cached !== void 0) return cached;
  const result = await createExplorer().search(workspaceDir);
  if (!result || result.filepath === rootConfigPath) {
    workspaceConfigCache.set(workspaceDir, {});
    return {};
  }
  const wsConfig = result.config ?? {};
  workspaceConfigCache.set(workspaceDir, wsConfig);
  return wsConfig;
}
var DEPRECATED_COMMAND_FIELDS = /* @__PURE__ */ new Set(["deplint", "publint"]);
function resolveCommandField(cfg, commandName, configPath) {
  const commands = cfg.commands;
  const fromCommands = commands?.[commandName];
  const fromTopLevel = cfg[commandName];
  if (fromCommands !== void 0 && typeof fromCommands === "object") {
    return fromCommands;
  }
  if (fromTopLevel !== void 0 && typeof fromTopLevel === "object" && DEPRECATED_COMMAND_FIELDS.has(commandName)) {
    const key = `${configPath ?? "unknown"}:${commandName}`;
    if (!deprecationWarned.has(key)) {
      deprecationWarned.add(key);
      console.warn(chalk2.yellow(
        `[xy] Deprecated: top-level "${commandName}" in ${configPath ?? "xy.config"} \u2014 move to "commands.${commandName}"`
      ));
    }
    return fromTopLevel;
  }
  return {};
}
async function loadWorkspaceCommandConfig(workspaceDir, commandName) {
  const root = await loadConfig();
  const rootCmd = resolveCommandField(root, commandName, rootConfigPath);
  const wsConfig = await loadWorkspaceConfig(workspaceDir);
  const wsConfigPath = workspaceConfigCache.has(workspaceDir) ? workspaceDir : void 0;
  const wsCmd = resolveCommandField(wsConfig, commandName, wsConfigPath);
  return deepmerge(rootCmd, wsCmd);
}

// src/lib/runInstall.ts
import chalk3 from "chalk";
function runInstall(cwd) {
  const pm = detectPackageManager();
  console.log(chalk3.gray(`Running ${pm} install...`));
  const result = spawnPackageManagerSync(pm, ["install"], {
    context: { cwd, operation: `Run ${pm} install` },
    cwd,
    encoding: "utf8",
    stdio: "inherit"
  });
  if (result.status !== 0) {
    console.warn(chalk3.yellow(`${pm} install failed`));
    return false;
  }
  console.log(chalk3.green("Dependencies installed"));
  return true;
}

// src/actions/deplint/packageJsonEditor.ts
import fs3 from "fs";
import chalk4 from "chalk";
import sortPackageJson from "sort-package-json";

// src/actions/deplint/getRequiredPeerDependencies.ts
import fs2 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 (fs2.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 = fs2.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
function readPackageJson(location) {
  return JSON.parse(fs3.readFileSync(`${location}/package.json`, "utf8"));
}
function writePackageJson(location, pkg) {
  const sorted = sortPackageJson(JSON.stringify(pkg, null, 2));
  fs3.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 addDep(pkg, dep, version, section) {
  const sectionObj = pkg[section] ?? {};
  sectionObj[dep] = version;
  pkg[section] = sectionObj;
}
function resolveDepVersion(location, dep) {
  const depPkgPath = findDepPackageJson(location, dep);
  if (depPkgPath) {
    try {
      const depPkg = JSON.parse(fs3.readFileSync(depPkgPath, "utf8"));
      const version = depPkg.version;
      if (version) return `~${version}`;
    } catch {
    }
  }
  return "*";
}
function resolveExpectedPeerVersion(location, dep, currentRange) {
  const depPkgPath = findDepPackageJson(location, dep);
  if (depPkgPath) {
    try {
      const depPkg = JSON.parse(fs3.readFileSync(depPkgPath, "utf8"));
      const version = depPkg.version;
      if (version) {
        const match = /^(\d+)\.(\d+)/.exec(version);
        if (match) {
          if (currentRange?.startsWith("^")) {
            return `^${match[1]}`;
          }
          return `~${match[1]}.${match[2]}`;
        }
        return `~${version}`;
      }
    } catch {
    }
  }
  return "*";
}

// src/actions/deplint/packageEditor.ts
var DeplintPackageEditor = class {
  constructor(workspace) {
    this.workspace = workspace;
    this.pkg = readPackageJson(workspace.location);
  }
  workspace;
  pkg;
  applyFix(fix) {
    switch (fix.action) {
      case "add": {
        addDep(this.pkg, fix.dependency, fix.version, fix.section);
        break;
      }
      case "move": {
        moveDep(this.pkg, fix.dependency, fix.fromSection, fix.toSection);
        if (fix.version !== void 0 && this.pkg[fix.toSection]?.[fix.dependency] !== void 0) {
          this.pkg[fix.toSection][fix.dependency] = fix.version;
        }
        break;
      }
      case "remove": {
        removeDep(this.pkg, fix.dependency, fix.section);
        break;
      }
      case "set-version": {
        addDep(this.pkg, fix.dependency, fix.version, fix.section);
        break;
      }
    }
    return {
      dependency: fix.dependency,
      detail: fix.detail,
      workspace: this.workspace
    };
  }
  save() {
    writePackageJson(this.workspace.location, this.pkg);
  }
};

// src/actions/deplint/fixer.ts
function applyDeplintFixes(diagnostics) {
  const editors = /* @__PURE__ */ new Map();
  const applied = [];
  for (const diagnostic2 of diagnostics) {
    for (const fix of diagnostic2.fixes ?? []) {
      const workspaceKey = diagnostic2.workspace.location;
      let editor = editors.get(workspaceKey);
      if (!editor) {
        editor = new DeplintPackageEditor(diagnostic2.workspace);
        editors.set(workspaceKey, editor);
      }
      applied.push(editor.applyFix(fix));
    }
  }
  for (const editor of editors.values()) {
    editor.save();
  }
  return applied;
}

// src/actions/deplint/findFiles.ts
import fs4 from "fs";

// src/actions/deplint/findFilesByGlob.ts
import { globSync as globSync2 } from "glob";
function findFilesByGlob(cwd, pattern, ignore) {
  return globSync2(pattern, {
    cwd,
    absolute: true,
    ignore,
    nodir: true
  });
}

// src/actions/deplint/findFiles.ts
var codeExtensions = "*.{ts,tsx,mts,cts,js,mjs,cjs}";
function getWorkspaceIgnores(location) {
  try {
    const raw = fs4.readFileSync(`${location}/package.json`, "utf8");
    const pkg = JSON.parse(raw);
    return pkg.workspaces ?? [];
  } catch {
    return [];
  }
}
function findFiles(location) {
  const workspaceIgnores = getWorkspaceIgnores(location).map((w) => `${w}/**`);
  const ignore = ["**/node_modules/**", "dist/**", ...workspaceIgnores];
  const allFiles = findFilesByGlob(location, `./**/${codeExtensions}`, ignore);
  const distFiles = [
    ...findFilesByGlob(location, "./dist/**/*.d.ts"),
    ...findFilesByGlob(location, `./dist/**/${codeExtensions}`)
  ];
  return { allFiles, distFiles };
}

// src/actions/deplint/getDependenciesFromPackageJson.ts
import fs5 from "fs";
import path2 from "path";
function getDependenciesFromPackageJson(packageJsonPath) {
  const packageJsonFullPath = path2.resolve(packageJsonPath);
  const rawContent = fs5.readFileSync(packageJsonFullPath, "utf8");
  const packageJson = JSON.parse(rawContent);
  const depsRecord = packageJson.dependencies ?? {};
  const devDepsRecord = packageJson.devDependencies ?? {};
  const peerDepsRecord = packageJson.peerDependencies ?? {};
  const dependencies = Object.keys(depsRecord);
  const devDependencies = Object.keys(devDepsRecord);
  const peerDependencies = Object.keys(peerDepsRecord);
  const dependencyVersions = depsRecord;
  const devDependencyVersions = devDepsRecord;
  const peerDependencyVersions = peerDepsRecord;
  return {
    dependencies,
    dependencyVersions,
    devDependencies,
    devDependencyVersions,
    peerDependencies,
    peerDependencyVersions
  };
}

// src/actions/deplint/getExtendsFromTsconfigs.ts
import fs6 from "fs";
import { globSync as globSync3 } from "glob";

// src/actions/deplint/getBasePackageName.ts
function getBasePackageName(importName) {
  const importNameScrubbed = importName.replaceAll('"', "").trim();
  if (importNameScrubbed.startsWith("@")) {
    const parts = importNameScrubbed.split("/");
    return parts.length >= 2 ? `${parts[0]}/${parts[1]}` : importNameScrubbed;
  }
  return importNameScrubbed.split("/")[0];
}

// src/actions/deplint/getExtendsFromTsconfigs.ts
var isExternalReference = (ref) => !ref.startsWith(".") && !ref.startsWith("/");
function parseExtendsField(value) {
  if (typeof value === "string") return [value];
  if (Array.isArray(value)) return value.filter((v) => typeof v === "string");
  return [];
}
function parseTypesField(value) {
  if (Array.isArray(value)) return value.filter((v) => typeof v === "string");
  return [];
}
function parseTsconfig(file) {
  const content = fs6.readFileSync(file, "utf8");
  const cleaned = content.replaceAll(/\/\/.*/g, "").replaceAll(/,\s*([}\]])/g, "$1");
  return JSON.parse(cleaned);
}
function getExtendsFromTsconfigs(location) {
  const tsconfigFiles = globSync3("./tsconfig*.json", { cwd: location, absolute: true });
  const packages = /* @__PURE__ */ new Set();
  for (const file of tsconfigFiles) {
    try {
      const parsed = parseTsconfig(file);
      const refs = parseExtendsField(parsed.extends);
      for (const ref of refs) {
        if (isExternalReference(ref)) {
          packages.add(getBasePackageName(ref));
        }
      }
    } catch {
    }
  }
  return [...packages];
}
function getTypesFromTsconfigs(location) {
  const tsconfigFiles = globSync3("./tsconfig*.json", { cwd: location, absolute: true });
  const packages = /* @__PURE__ */ new Set();
  for (const file of tsconfigFiles) {
    try {
      const parsed = parseTsconfig(file);
      const compilerOptions = parsed.compilerOptions;
      const refs = parseTypesField(compilerOptions?.types);
      for (const ref of refs) {
        packages.add(getBasePackageName(ref));
      }
    } catch {
    }
  }
  return [...packages];
}

// src/actions/deplint/getExternalImportsFromFiles.ts
import fs8 from "fs";
import chalk5 from "chalk";

// src/actions/deplint/getImportsFromFile.ts
import fs7 from "fs";
import path3 from "path";
import ts from "typescript";
function isTypeOnlyImportClause(clause) {
  if (clause === void 0) {
    return false;
  }
  if ("phaseModifier" in clause) {
    const mod = clause.phaseModifier;
    const kind = typeof mod === "number" ? mod : mod?.kind;
    return kind === ts.SyntaxKind.TypeKeyword;
  }
  return clause.isTypeOnly ?? false;
}
function getImportsFromFile(filePath, importPaths, typeImportPaths) {
  const sourceCode = fs7.readFileSync(filePath, "utf8");
  const isMjsFile = filePath.endsWith(".mjs");
  const sourceFile = ts.createSourceFile(
    path3.basename(filePath),
    sourceCode,
    ts.ScriptTarget.Latest,
    true,
    isMjsFile ? ts.ScriptKind.JS : void 0
  );
  const imports = [];
  const typeImports = [];
  const isDeclarationFile2 = filePath.endsWith(".d.ts");
  function visit(node) {
    if (ts.isImportDeclaration(node) || ts.isExportDeclaration(node)) {
      const moduleSpecifier = node.moduleSpecifier?.getFullText();
      const isTypeImport = ts.isImportDeclaration(node) ? isTypeOnlyImportClause(node.importClause) : false;
      if (typeof moduleSpecifier === "string") {
        const trimmed = moduleSpecifier.replaceAll("'", "").replaceAll('"', "").trim();
        if (isTypeImport || isDeclarationFile2) {
          typeImports.push(trimmed);
        } else {
          imports.push(trimmed);
        }
      }
    } else if (ts.isCallExpression(node) && node.expression.kind === ts.SyntaxKind.ImportKeyword) {
      const [arg] = node.arguments;
      if (ts.isStringLiteral(arg)) {
        imports.push(arg.text);
      }
    } else if (ts.isCallExpression(node) && ts.isIdentifier(node.expression) && node.expression.text === "require" && node.arguments.length > 0 && ts.isStringLiteral(node.arguments[0])) {
      imports.push(node.arguments[0].text);
    }
    ts.forEachChild(node, visit);
  }
  visit(sourceFile);
  for (const ref of sourceFile.typeReferenceDirectives) {
    typeImports.push(ref.fileName);
  }
  const importsStartsWithExcludes = [".", "#", "node:"];
  const isValidImport = (imp) => !importsStartsWithExcludes.some((exc) => imp.startsWith(exc)) && !imp.includes("*") && !imp.includes("!");
  const cleanedImports = imports.filter(isValidImport).map(getBasePackageName);
  const cleanedTypeImports = typeImports.filter(isValidImport).map(getBasePackageName);
  for (const imp of cleanedImports) {
    importPaths[imp] = importPaths[imp] ?? [];
    importPaths[imp].push(filePath);
  }
  for (const imp of cleanedTypeImports) {
    typeImportPaths[imp] = typeImportPaths[imp] ?? [];
    typeImportPaths[imp].push(filePath);
  }
  return [cleanedImports, cleanedTypeImports];
}

// src/actions/deplint/getExternalImportsFromFiles.ts
var internalImportPrefixes = [".", "#", "node:"];
var removeInternalImports = (imports) => {
  return imports.filter((imp) => !internalImportPrefixes.some((prefix) => imp.startsWith(prefix)));
};
var isDeclarationFile = (file) => file.endsWith(".d.ts") || file.endsWith(".d.cts") || file.endsWith(".d.mts");
var toolingConfigFilePattern = /(?:^|[\\/])xy\.config\.[cm]?[jt]sx?$/;
var isToolingConfigFile = (file) => toolingConfigFilePattern.test(file);
function excludeToolingConfigImports(paths) {
  const filtered = {};
  for (const [imp, files] of Object.entries(paths)) {
    const kept = files.filter((file) => !isToolingConfigFile(file));
    if (kept.length > 0) filtered[imp] = kept;
  }
  return filtered;
}
function warnMissingDist(name, location, allFiles) {
  if (allFiles.length > 0 && fs8.existsSync(`${location}/src`)) {
    const prefix = name ? `[${chalk5.blue(name)}] ` : "";
    console.warn(`${prefix}${chalk5.yellow("deplint: dist/ not found \u2014 using source imports (compile first for best accuracy)")}`);
  }
}
function shipsTsconfig(location) {
  try {
    const raw = fs8.readFileSync(`${location}/package.json`, "utf8");
    const pkg = JSON.parse(raw);
    const files = pkg.files;
    return files?.some((f) => f === "tsconfig.json" || f.includes("tsconfig")) ?? false;
  } catch {
    return false;
  }
}
function getExternalImportsFromFiles({
  allFiles,
  distFiles,
  location,
  name,
  tsconfigExtends = [],
  tsconfigTypes = []
}) {
  const srcImportPaths = {};
  const srcTypeImportPaths = {};
  for (const path6 of allFiles) getImportsFromFile(path6, srcImportPaths, srcTypeImportPaths);
  const allImportPaths = { ...srcImportPaths };
  for (const [key, paths] of Object.entries(srcTypeImportPaths)) {
    allImportPaths[key] = [...allImportPaths[key] ?? [], ...paths];
  }
  const distImportPaths = {};
  const distTypeImportPaths = {};
  const hasDist = distFiles.length > 0;
  if (hasDist) {
    const distTypeFiles = distFiles.filter(isDeclarationFile);
    const distCodeFiles = distFiles.filter((file) => !isDeclarationFile(file));
    for (const path6 of distCodeFiles) getImportsFromFile(path6, distImportPaths, distImportPaths);
    for (const path6 of distTypeFiles) getImportsFromFile(path6, distTypeImportPaths, distTypeImportPaths);
  } else {
    warnMissingDist(name, location, allFiles);
  }
  const effectiveDistImportPaths = hasDist ? distImportPaths : excludeToolingConfigImports(srcImportPaths);
  const effectiveDistTypeImportPaths = hasDist ? distTypeImportPaths : excludeToolingConfigImports(srcTypeImportPaths);
  const allImports = Object.keys(allImportPaths);
  const distImports = Object.keys(effectiveDistImportPaths);
  const externalAllImports = removeInternalImports(allImports);
  const externalDistImports = removeInternalImports(distImports);
  const externalDistTypeImports = removeInternalImports(Object.keys(effectiveDistTypeImportPaths));
  const isDistTsconfig = shipsTsconfig(location);
  for (const ext of tsconfigExtends) {
    if (!externalAllImports.includes(ext)) externalAllImports.push(ext);
    if (isDistTsconfig && !externalDistImports.includes(ext)) externalDistImports.push(ext);
  }
  for (const typ of tsconfigTypes) {
    if (!externalAllImports.includes(typ)) externalAllImports.push(typ);
  }
  return {
    allImportPaths,
    allImports,
    distImportPaths: effectiveDistImportPaths,
    distImports,
    externalAllImports,
    externalDistImports,
    externalDistTypeImports,
    tsconfigExtends: [...tsconfigExtends]
  };
}

// src/actions/deplint/checkPackage/getMismatchedPeerDevVersions.ts
import chalk6 from "chalk";
import semver from "semver";
function findMismatchedPeerDevVersions({
  peerDependencies,
  peerDependencyVersions,
  devDependencyVersions
}, exclude) {
  const mismatches = [];
  for (const dep of peerDependencies) {
    if (exclude?.has(dep)) continue;
    const peerVersion = peerDependencyVersions[dep];
    const devVersion = devDependencyVersions[dep];
    const hasWorkspaceProtocol = devVersion?.startsWith("workspace:") || peerVersion?.startsWith("workspace:");
    if (devVersion && peerVersion !== devVersion && !hasWorkspaceProtocol && !semver.subset(devVersion, peerVersion)) {
      mismatches.push({
        dep,
        devVersion,
        peerVersion
      });
    }
  }
  return mismatches;
}

// src/actions/deplint/checkPackage/getUnlistedDependencies.ts
import { builtinModules } from "module";
import chalk7 from "chalk";

// 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 isSatisfiedByTsScriptsVariant(imp, allDeps) {
  const variant = VARIANT_MAP[imp];
  return variant !== void 0 && allDeps.includes(variant);
}
function isUsedViaTsScriptsVariant(dep, imports) {
  const variant = VARIANT_MAP[dep];
  return variant !== void 0 && imports.includes(variant);
}

// src/actions/deplint/checkPackage/getUnlistedDependencies.ts
function isRuntimeImportListed(imp, name, dependencies, peerDependencies) {
  return dependencies.includes(imp) || imp === name || peerDependencies.includes(imp) || builtinModules.includes(imp);
}
function isDistTypeImportListed(imp, name, dependencies, devDependencies, peerDependencies) {
  return dependencies.includes(imp) || imp === name || dependencies.includes(`@types/${imp}`) || devDependencies.includes(`@types/${imp}`) || peerDependencies.includes(imp) || peerDependencies.includes(`@types/${imp}`) || builtinModules.includes(imp);
}
function shouldBePeerDependency(imp, _location, _currentPeers, _distImports, workspaceNames) {
  if (workspaceNames?.has(imp)) return false;
  if (imp.startsWith("@types/")) return false;
  return true;
}
function findUnlistedDependencies(name, dependencies, devDependencies, peerDependencies, externalDistImports, externalDistTypeImports) {
  const allDeps = [...dependencies, ...devDependencies, ...peerDependencies];
  const results = [];
  for (const imp of externalDistImports) {
    if (!isRuntimeImportListed(imp, name, dependencies, peerDependencies) && !isSatisfiedByTsScriptsVariant(imp, allDeps)) {
      results.push({ imp, section: "dependencies" });
    }
  }
  for (const imp of externalDistTypeImports) {
    if (!isDistTypeImportListed(imp, name, dependencies, devDependencies, peerDependencies) && !isSatisfiedByTsScriptsVariant(imp, allDeps)) {
      results.push({ imp, section: "dependencies" });
    }
  }
  return results;
}

// src/actions/deplint/checkPackage/getUnlistedDevDependencies.ts
import { builtinModules as builtinModules2 } from "module";
import chalk8 from "chalk";
function findUnlistedDevDeps(name, dependencies, devDependencies, peerDependencies, externalAllImports, distImports, externalDistTypeImports) {
  const results = [];
  for (const imp of externalAllImports) {
    if (!distImports.includes(imp) && !externalDistTypeImports.includes(imp) && imp !== name && !dependencies.includes(imp) && !dependencies.includes(`@types/${imp}`) && !peerDependencies.includes(imp) && !peerDependencies.includes(`@types/${imp}`) && !devDependencies.includes(imp) && !devDependencies.includes(`@types/${imp}`) && !builtinModules2.includes(imp) && !isSatisfiedByTsScriptsVariant(imp, [...dependencies, ...devDependencies, ...peerDependencies])) {
      results.push(imp);
    }
  }
  return results;
}

// src/actions/deplint/checkPackage/getUnnecessaryPeerDependencies.ts
import fs10 from "fs";
import chalk10 from "chalk";

// src/actions/deplint/checkPackage/getUnsatisfiedPeerDependencies.ts
import fs9 from "fs";
import chalk9 from "chalk";
import semver2 from "semver";
import sortPackageJson2 from "sort-package-json";
function readDepPackageJson(location, dep) {
  const depPkgPath = findDepPackageJson(location, dep);
  if (!depPkgPath) return void 0;
  try {
    return JSON.parse(fs9.readFileSync(depPkgPath, "utf8"));
  } catch {
    return void 0;
  }
}
function readPeerDeps(location, dep) {
  const pkg = readDepPackageJson(location, dep);
  if (!pkg) return [];
  const peers = pkg.peerDependencies;
  return Object.keys(peers ?? {});
}
function readPeerVersionRange(location, dep, peer) {
  const pkg = readDepPackageJson(location, dep);
  if (!pkg) return void 0;
  const peers = pkg.peerDependencies;
  return peers?.[peer];
}
function readInstalledVersion(location, dep) {
  const pkg = readDepPackageJson(location, dep);
  if (!pkg) return void 0;
  return pkg.version;
}
function isPeerOptionalInAll(location, peer, sources) {
  for (const source of sources) {
    const pkg = readDepPackageJson(location, source.requiredBy);
    if (!pkg) continue;
    const meta = pkg.peerDependenciesMeta?.[peer];
    if (!meta?.optional) return false;
  }
  return true;
}
var MAX_TRANSITIVE_DEPTH = 2;
function collectPeerSources(location, dependencies, devDependencies) {
  const peerSources = /* @__PURE__ */ new Map();
  const visited = /* @__PURE__ */ new Set();
  function addPeerSource(peer, source) {
    const sources = peerSources.get(peer) ?? [];
    sources.push(source);
    peerSources.set(peer, sources);
  }
  function collectFromDeps(deps, isRuntime, chain) {
    for (const dep of deps) {
      const visitKey = `${dep}:${chain.join(">")}`;
      if (visited.has(visitKey)) continue;
      visited.add(visitKey);
      for (const peer of readPeerDeps(location, dep)) {
        addPeerSource(peer, {
          chain: chain.length > 0 ? [...chain, dep] : void 0,
          isRuntimeDep: isRuntime,
          requiredBy: dep
        });
      }
      if (chain.length < MAX_TRANSITIVE_DEPTH) {
        const depPkg = readDepPackageJson(location, dep);
        if (depPkg) {
          const transitiveDeps = Object.keys(depPkg.dependencies ?? {});
          collectFromDeps(transitiveDeps, isRuntime, [...chain, dep]);
        }
      }
    }
  }
  collectFromDeps(dependencies, true, []);
  const devOnly = devDependencies.filter((d) => !dependencies.includes(d));
  collectFromDeps(devOnly, false, []);
  return peerSources;
}
function getRequiredTransitivePeers(location, { dependencies, devDependencies }) {
  const peerSources = collectPeerSources(location, dependencies, devDependencies);
  return new Set(peerSources.keys());
}
function resolveVersionRange(location, sources, peer) {
  for (const source of sources) {
    const range = readPeerVersionRange(location, source.requiredBy, peer);
    if (range) return range;
  }
  return "*";
}
function checkVersionSatisfaction(location, peer, requestedRange) {
  const installedVersion = readInstalledVersion(location, peer);
  if (!installedVersion) return { satisfied: true };
  if (requestedRange === "*") return { installedVersion, satisfied: true };
  if (requestedRange.startsWith("workspace:")) return { installedVersion, satisfied: true };
  try {
    const satisfied = semver2.satisfies(installedVersion, requestedRange, { includePrerelease: true });
    return { installedVersion, satisfied };
  } catch {
    return { installedVersion, satisfied: true };
  }
}
function findDeclaredPeerVersionMismatches(name, location, peerDependencies, peerDependencyVersions, exclude) {
  const results = [];
  for (const peer of peerDependencies) {
    if (exclude?.has(peer) || peer === name) continue;
    const declaredRange = peerDependencyVersions[peer];
    if (!declaredRange || declaredRange === "*") continue;
    const { installedVersion, satisfied } = checkVersionSatisfaction(location, peer, declaredRange);
    if (!satisfied) {
      results.push({
        hasRuntimeSource: true,
        installedVersion,
        peer,
        reason: "version-mismatch",
        sources: [{ isRuntimeDep: true, requiredBy: name }],
        versionRange: declaredRange
      });
    }
  }
  return results;
}
function findUnsatisfiedPeers({ name, location }, {
  dependencies,
  devDependencies,
  peerDependencies,
  peerDependencyVersions
}, exclude, isTerminal) {
  const peerSources = collectPeerSources(location, dependencies, devDependencies);
  const depsSet = new Set(dependencies);
  const devDepsSet = new Set(devDependencies);
  const peerDepsSet = new Set(peerDependencies);
  const isTerminalResolved = isTerminal ?? isTerminalPackage(`${location}/package.json`);
  const unsatisfied = [];
  for (const [peer, sources] of peerSources) {
    if (exclude?.has(peer) || peer === name) continue;
    if (isPeerOptionalInAll(location, peer, sources)) continue;
    const hasRuntimeSource = sources.some((s) => s.isRuntimeDep);
    const isPresent = depsSet.has(peer) || devDepsSet.has(peer);
    if (!isPresent) {
      const versionRange2 = resolveVersionRange(location, sources, peer);
      unsatisfied.push({
        hasRuntimeSource,
        peer,
        reason: "missing",
        sources,
        versionRange: versionRange2
      });
      continue;
    }
    const hasDirectRuntimeSource = sources.some((s) => s.isRuntimeDep && !s.chain);
    if (hasDirectRuntimeSource && !isTerminalResolved && !depsSet.has(peer) && !peerDepsSet.has(peer)) {
      const versionRange2 = resolveVersionRange(location, sources, peer);
      unsatisfied.push({
        hasRuntimeSource,
        peer,
        reason: "under-exposed",
        sources,
        versionRange: versionRange2
      });
      continue;
    }
    const versionRange = resolveVersionRange(location, sources, peer);
    const { installedVersion, satisfied } = checkVersionSatisfaction(location, peer, versionRange);
    if (!satisfied) {
      const mismatchedSources = findMismatchedSources(location, sources, peer, installedVersion);
      unsatisfied.push({
        hasRuntimeSource,
        installedVersion,
        mismatchedSources,
        peer,
        reason: "version-mismatch",
        sources,
        versionRange
      });
    }
  }
  return [
    ...unsatisfied,
    ...findDeclaredPeerVersionMismatches(name, location, peerDependencies, peerDependencyVersions, exclude)
  ];
}
function findMismatchedSources(location, sources, peer, installedVersion) {
  if (!installedVersion) return [];
  return sources.filter((source) => {
    const range = readPeerVersionRange(location, source.requiredBy, peer);
    if (!range || range === "*" || range.startsWith("workspace:")) return false;
    try {
      return !semver2.satisfies(installedVersion, range, { includePrerelease: true });
    } catch {
      return false;
    }
  });
}
function isTerminalPackage(packageJsonPath) {
  try {
    const pkg = JSON.parse(fs9.readFileSync(packageJsonPath, "utf8"));
    return pkg.private === true;
  } catch {
    return false;
  }
}
function resolvePeerTargetSections(hasRuntimeSource, isTerminal) {
  if (!hasRuntimeSource) return ["devDependencies"];
  if (isTerminal) return ["dependencies"];
  return ["peerDependencies", "devDependencies"];
}

// src/actions/deplint/checkPackage/getUnnecessaryPeerDependencies.ts
function isPeerImportedInDist(dep, externalDistImports, externalDistTypeImports) {
  const baseName = dep.replace(/^@types\//, "");
  return externalDistImports.includes(dep) || externalDistImports.includes(baseName) || externalDistTypeImports.includes(dep) || externalDistTypeImports.includes(baseName);
}
function findUnrequestedPeerDeps(location, packageParams, { externalDistImports, externalDistTypeImports }, exclude) {
  const requiredPeers = getRequiredTransitivePeers(location, packageParams);
  const unrequested = [];
  for (const dep of packageParams.peerDependencies) {
    if (exclude?.has(dep)) continue;
    if (packageParams.dependencies.includes(dep)) continue;
    if (!isPeerImportedInDist(dep, externalDistImports, externalDistTypeImports)) continue;
    if (!requiredPeers.has(dep)) {
      unrequested.push(dep);
    }
  }
  return unrequested;
}
function findRedundantPeerDeps({ peerDependencies, dependencies }, exclude) {
  const depsSet = new Set(dependencies);
  const redundant = [];
  for (const dep of peerDependencies) {
    if (exclude?.has(dep)) continue;
    if (depsSet.has(dep)) {
      redundant.push(dep);
    }
  }
  return redundant;
}

// src/actions/deplint/checkPackage/getUnusedDependencies.ts
import chalk11 from "chalk";
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;
}

// src/actions/deplint/checkPackage/getUnusedDevDependencies.ts
import chalk12 from "chalk";

// src/actions/deplint/getCliReferencedPackagesFromFiles.ts
import fs12 from "fs";
import path5 from "path";
import ts2 from "typescript";

// src/actions/deplint/getScriptReferencedPackages.ts
import fs11 from "fs";
import path4 from "path";
function getBinNames(location, dep) {
  const depPkgPath = findDepPackageJson(location, dep);
  if (!depPkgPath) return [];
  try {
    const raw = fs11.readFileSync(depPkgPath, "utf8");
    const pkg = JSON.parse(raw);
    if (!pkg.bin) return [];
    if (typeof pkg.bin === "string") return [pkg.name?.split("/").pop() ?? dep];
    return Object.keys(pkg.bin);
  } catch {
    return [];
  }
}
function tokenizeScript(script) {
  return script.split(/[&|;$()"`\s]+/).map((t) => t.trim()).filter(Boolean);
}
function getScriptReferencedPackages(location, allDeps) {
  const pkgPath = path4.join(location, "package.json");
  let scripts;
  try {
    const raw = fs11.readFileSync(pkgPath, "utf8");
    const pkg = JSON.parse(raw);
    scripts = pkg.scripts ?? {};
  } catch {
    return /* @__PURE__ */ new Set();
  }
  const scriptText = Object.values(scripts).join(" ");
  const tokens = new Set(tokenizeScript(scriptText));
  const binToPackage = /* @__PURE__ */ new Map();
  for (const dep of allDeps) {
    const bins = getBinNames(location, dep);
    for (const bin of bins) {
      binToPackage.set(bin, dep);
    }
  }
  const referenced = /* @__PURE__ */ new Set();
  for (const token of tokens) {
    const baseName = getBasePackageName(token);
    if (allDeps.includes(baseName)) {
      referenced.add(baseName);
    }
    const pkg = binToPackage.get(token);
    if (pkg) {
      referenced.add(pkg);
    }
  }
  return referenced;
}

// src/actions/deplint/getCliReferencedPackagesFromFiles.ts
var shellCommandFunctions = /* @__PURE__ */ new Set(["execSync", "exec"]);
var directExecFunctions = /* @__PURE__ */ new Set(["spawn", "spawnSync", "execFile", "execFileSync"]);
var allExecFunctions = /* @__PURE__ */ new Set([...shellCommandFunctions, ...directExecFunctions]);
function getCommandTokensFromFile(filePath) {
  const tokens = /* @__PURE__ */ new Set();
  let sourceCode;
  try {
    sourceCode = fs12.readFileSync(filePath, "utf8");
  } catch {
    return tokens;
  }
  const isMjsFile = filePath.endsWith(".mjs");
  const sourceFile = ts2.createSourceFile(
    path5.basename(filePath),
    sourceCode,
    ts2.ScriptTarget.Latest,
    true,
    isMjsFile ? ts2.ScriptKind.JS : void 0
  );
  function visit(node) {
    if (ts2.isCallExpression(node) && node.arguments.length > 0) {
      const fnName = getFunctionName(node.expression);
      if (fnName && allExecFunctions.has(fnName)) {
        const firstArg = node.arguments[0];
        if (ts2.isStringLiteral(firstArg) || ts2.isNoSubstitutionTemplateLiteral(firstArg)) {
          const value = firstArg.text;
          if (shellCommandFunctions.has(fnName)) {
            for (const token of tokenizeScript(value)) {
              tokens.add(token);
            }
          } else {
            tokens.add(value);
          }
        } else if (ts2.isTemplateExpression(firstArg)) {
          const head = firstArg.head.text;
          if (head) {
            for (const token of tokenizeScript(head)) {
              tokens.add(token);
            }
          }
        }
      }
    }
    ts2.forEachChild(node, visit);
  }
  visit(sourceFile);
  return tokens;
}
function getFunctionName(expr) {
  if (ts2.isIdentifier(expr)) {
    return expr.text;
  }
  if (ts2.isPropertyAccessExpression(expr) && ts2.isIdentifier(expr.name)) {
    return expr.name.text;
  }
  return void 0;
}
function getCliReferencedPackagesFromFiles(allFiles, location, allDeps) {
  const allTokens = /* @__PURE__ */ new Set();
  for (const file of allFiles) {
    for (const token of getCommandTokensFromFile(file)) {
      allTokens.add(token);
    }
  }
  if (allTokens.size === 0) return /* @__PURE__ */ new Set();
  const binToPackage = /* @__PURE__ */ new Map();
  for (const dep of allDeps) {
    for (const bin of getBinNames(location, dep)) {
      binToPackage.set(bin, dep);
    }
  }
  const referenced = /* @__PURE__ */ new Set();
  for (const token of allTokens) {
    const baseName = getBasePackageName(token);
    if (allDeps.includes(baseName)) {
      referenced.add(baseName);
    }
    const pkg = binToPackage.get(token);
    if (pkg) {
      referenced.add(pkg);
    }
  }
  return referenced;
}

// src/actions/deplint/implicitDevDependencies.ts
import fs13 from "fs";
var hasFileWithExtension = (files, extensions) => files.some((f) => extensions.some((ext) => f.endsWith(ext)));
var tsExtensions = [".ts", ".tsx", ".mts", ".cts"];
var hasTypescriptFiles = ({ allFiles }) => hasFileWithExtension(allFiles, tsExtensions);
var decoratorPattern = /^\s*@[a-zA-Z]\w*/m;
var hasDecorators = ({ allFiles }) => allFiles.filter((f) => tsExtensions.some((ext) => f.endsWith(ext))).some((file) => {
  try {
    const content = fs13.readFileSync(file, "utf8");
    return decoratorPattern.test(content);
  } catch {
    return false;
  }
});
var hasDependencyRequiringTslib = ({ location, allDependencies }) => allDependencies.some((dep) => {
  const pkgPath = findDepPackageJson(location, dep);
  if (!pkgPath) return false;
  try {
    const pkg = JSON.parse(fs13.readFileSync(pkgPath, "utf8"));
    const peers = pkg.peerDependencies;
    return peers !== void 0 && "tslib" in peers;
  } catch {
    return false;
  }
});
var importPlugins = /* @__PURE__ */ new Set(["eslint-plugin-import-x", "eslint-plugin-import"]);
function hasImportPlugin({ location, allDependencies }) {
  if (allDependencies.some((d) => importPlugins.has(d))) return true;
  for (const dep of allDependencies) {
    const pkgPath = findDepPackageJson(location, dep);
    if (!pkgPath) continue;
    try {
      const pkg = JSON.parse(fs13.readFileSync(pkgPath, "utf8"));
      const transitiveDeps = [
        ...Object.keys(pkg.dependencies ?? {}),
        ...Object.keys(pkg.peerDependencies ?? {})
      ];
      if (transitiveDeps.some((d) => importPlugins.has(d))) return true;
    } catch {
    }
  }
  return false;
}
var hasVitest = ({ allDependencies }) => allDependencies.includes("vitest");
var rules = [
  {
    package: "typescript",
    isNeeded: hasTypescriptFiles
  },
  {
    package: "eslint-import-resolver-typescript",
    isNeeded: (context) => hasTypescriptFiles(context) && context.allDependencies.includes("eslint") && hasImportPlugin(context)
  },
  {
    package: "tslib",
    isNeeded: (context) => hasDecorators(context) || hasDependencyRequiringTslib(context)
  },
  {
    package: "@vitest/coverage-v8",
    isNeeded: hasVitest
  },
  {
    package: "@xylabs/toolchain",
    isNeeded: hasTypescriptFiles
  }
];
function getImplicitDevDependencies(context) {
  const implicit = /* @__PURE__ */ new Set();
  for (const rule of rules) {
    if (rule.isNeeded(context)) {
      implicit.add(rule.package);
    }
  }
  return implicit;
}

// src/actions/deplint/checkPackage/getUnusedDevDependencies.ts
var allExternalImports = ({
  externalAllImports,
  externalDistImports,
  externalDistTypeImports
}) => {
  return /* @__PURE__ */ new Set([
    ...externalAllImports,
    ...externalDistImports,
    ...externalDistTypeImports
  ]);
};
function isDevDepUsed(dep, allImports, implicitDeps, requiredPeers, scriptRefs, cliRefs) {
  if (implicitDeps.has(dep)) return true;
  if (requiredPeers.has(dep)) return true;
  if (scriptRefs.has(dep)) return true;
  if (cliRefs.has(dep)) return true;
  if (dep.startsWith("@types/")) {
    const baseName = dep.replace(/^@types\//, "");
    return allImports.has(baseName) || allImports.has(dep) || implicitDeps.has(baseName);
  }
  if (allImports.has(dep)) return true;
  return isUsedViaTsScriptsVariant(dep, [...allImports]);
}
function findUnusedDevDeps(location, dependencies, devDependencies, peerDependencies, sourceParams, fileContext, exclude) {
  const allImports = allExternalImports(sourceParams);
  const allDeps = [...dependencies, ...devDependencies, ...peerDependencies];
  const implicitDeps = getImplicitDevDependencies({
    ...fileContext,
    allDependencies: allDeps,
    location
  });
  const requiredPeers = getRequiredPeerDependencies(location, allDeps);
  const scriptRefs = getScriptReferencedPackages(location, allDeps);
  const cliRefs = getCliReferencedPackagesFromFiles(fileContext.allFiles, location, allDeps);
  const unused = [];
  for (const dep of devDependencies) {
    if (exclude?.has(dep)) continue;
    if (dependencies.includes(dep) || peerDependencies.includes(dep)) continue;
    if (!isDevDepUsed(dep, allImports, implicitDeps, requiredPeers, scriptRefs, cliRefs)) {
      unused.push(dep);
    }
  }
  return unused;
}

// src/actions/deplint/checkPackage/getUnusedPeerDependencies.ts
import chalk13 from "chalk";
function isPeerUsed(dep, externalDistImports, externalDistTypeImports) {
  const baseName = dep.replace(/^@types\//, "");
  return externalDistImports.includes(dep) || externalDistImports.includes(baseName) || externalDistTypeImports.includes(dep) || externalDistTypeImports.includes(baseName);
}
function findUnusedPeerDeps(peerDependencies, externalDistImports, externalDistTypeImports, exclude) {
  const unused = [];
  for (const dep of peerDependencies) {
    if (exclude?.has(dep)) continue;
    if (!isPeerUsed(dep, externalDistImports, externalDistTypeImports)) {
      unused.push(dep);
    }
  }
  return unused;
}

// src/actions/deplint/checkPackage/getWorkspaceVersionProblems.ts
import chalk14 from "chalk";
import semver3 from "semver";
function checkSection(deps, versions, section, workspaceNames, problems) {
  for (const dep of deps) {
    if (!workspaceNames.has(dep)) continue;
    const version = versions[dep];
    if (version && !version.startsWith("workspace:")) {
      problems.push({
        dep,
        section,
        version
      });
    }
  }
}
function findWorkspaceVersionProblems(packageParams, workspaceNames) {
  const problems = [];
  checkSection(packageParams.dependencies, packageParams.dependencyVersions, "dependencies", workspaceNames, problems);
  checkSection(packageParams.devDependencies, packageParams.devDependencyVersions, "devDependencies", workspaceNames, problems);
  return problems;
}
function findWorkspacePeerVersionProblems(packageParams, workspaceNames, location) {
  const problems = [];
  for (const dep of packageParams.peerDependencies) {
    if (!workspaceNames.has(dep)) continue;
    const declaredRange = packageParams.peerDependencyVersions[dep];
    if (!declaredRange || declaredRange.startsWith("workspace:")) continue;
    const resolved = resolveDepVersion(location, dep);
    const actualVersion = resolved.startsWith("~") ? resolved.slice(1) : resolved;
    if (actualVersion === "*") continue;
    if (!semver3.satisfies(actualVersion, declaredRange)) {
      problems.push({
        actualVersion,
        declaredRange,
        dep
      });
    }
  }
  return problems;
}

// src/actions/deplint/rulesDiagnostic.ts
function diagnostic(context, id, message, dependency, evidence, fixes) {
  return {
    dependency,
    evidence,
    file: context.packageJsonPath,
    fixes,
    id,
    message,
    severity: "error",
    workspace: context.workspace
  };
}
function resolvedAddFix(context, dependency, section, detail) {
  return {
    action: "add",
    dependency,
    detail,
    section,
    version: resolveDepVersion(context.workspace.location, dependency)
  };
}

// src/actions/deplint/rulesMisplaced.ts
var misplacedDependenciesRule = {
  category: "dependencies",
  id: "deplint.dependencies.misplaced",
  evaluate(context) {
    const diagnostics = [];
    for (const dep of context.packageParams.dependencies) {
      if (context.forceDevs.has(dep)) {
        diagnostics.push(diagnostic(
          context,
          "deplint.dependencies.misplaced",
          `dependency ${dep} should be a devDependency \u2014 configured as refType "dev"`,
          dep,
          void 0,
          [{
            action: "move",
            dependency: dep,
            detail: "moved from dependencies to devDependencies",
            fromSection: "dependencies",
            toSection: "devDependencies"
          }]
        ));
        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 fixes = [{
          action: "move",
          dependency: dep,
          detail: "moved from dependencies to peerDependencies",
          fromSection: "dependencies",
          toSection: "peerDependencies"
        }];
        if (!context.packageParams.devDependencies.includes(dep)) {
          fixes.push(resolvedAddFix(context, dep, "devDependencies", "added to devDependencies"));
        }
        const reason = context.forcePeers.has(dep) ? 'configured as refType "peer"' : "external runtime dep \u2014 consumers should control the version";
        diagnostics.push(diagnostic(
          context,
          "deplint.dependencies.misplaced",
          `dependency ${dep} should be a peerDependency \u2014 ${reason}`,
          dep,
          void 0,
          fixes
        ));
      }
    }
    return diagnostics;
  }
};
var misplacedPeerDependenciesRule = {
  category: "peerDependencies",
  id: "deplint.peerDependencies.misplaced",
  evaluate(context) {
    const diagnostics = [];
    for (const dep of context.packageParams.peerDependencies) {
      if (context.forceDeps.has(dep)) {
        diagnostics.push(diagnostic(
          context,
          "deplint.peerDependencies.misplaced",
          `peerDependency ${dep} should be a dependency \u2014 configured as refType "dep"`,
          dep,
          void 0,
          [{
            action: "move",
            dependency: dep,
            detail: "moved from peerDependencies to dependencies",
            fromSection: "peerDependencies",
            toSection: "dependencies",
            version: context.packageParams.peerDependencyVersions[dep] ?? "*"
          }]
        ));
        continue;
      }
      if (context.forceDevs.has(dep)) {
        diagnostics.push(diagnostic(
          context,
          "deplint.peerDependencies.misplaced",
          `peerDependency ${dep} should be a devDependency \u2014 configured as refType "dev"`,
          dep,
          void 0,
          [{
            action: "move",
            dependency: dep,
            detail: "moved from peerDependencies to devDependencies",
            fromSection: "peerDependencies",
            toSection: "devDependencies",
            version: context.packageParams.peerDependencyVersions[dep] ?? "*"
          }]
        ));
      }
    }
    return diagnostics;
  }
};

// src/actions/deplint/versionMismatchFixes.ts
function computeBumpedRange(installedVersion, currentRange) {
  const match = /^(\d+)\.(\d+)/.exec(installedVersion);
  if (!match) return void 0;
  if (currentRange.startsWith("^")) return `^${match[1]}`;
  return `~${match[1]}.${match[2]}`;
}
function sectionLookupsFor(context) {
  const {
    dependencies,
    devDependencies,
    peerDependencies,
    dependencyVersions,
    devDependencyVersions,
    peerDependencyVersions
  } = context.packageParams;
  return [
    ["dependencies", dependencies, dependencyVersions],
    ["devDependencies", devDependencies, devDependencyVersions],
    ["peerDependencies", peerDependencies, peerDependencyVersions]
  ];
}
function addSourceBumpFixes(context, finding, fixes) {
  if (!finding.installedVersion || !finding.mismatchedSources) return;
  const sectionLookups = sectionLookupsFor(context);
  const seen = /* @__PURE__ */ new Set();
  for (const source of finding.mismatchedSources) {
    const dep = source.requiredBy;
    if (seen.has(dep) || dep === context.workspace.name) continue;
    seen.add(dep);
    for (const [section, names, versions] of sectionLookups) {
      if (!names.includes(dep)) continue;
      const current = versions[dep];
      if (!current || current.startsWith("workspace:")) continue;
      const bumped = computeBumpedRange(finding.installedVersion, current);
      if (!bumped || bumped === current) continue;
      fixes.push({
        action: "set-version",
        dependency: dep,
        detail: `bumped ${section} range to ${bumped} so a newer version is installed that accepts peer ${finding.peer}@${finding.installedVersion}`,
        section,
        version: bumped
      });
    }
  }
}
function generateVersionMismatchFixes(context, finding) {
  const fixes = [];
  const expectedVersion = resolveExpectedPeerVersion(
    context.workspace.location,
    finding.peer,
    finding.versionRange
  );
  if (expectedVersion !== "*") {
    if (context.packageParams.peerDependencies.includes(finding.peer)) {
      fixes.push({
        action: "set-version",
        dependency: finding.peer,
        detail: `updated peerDependency version to match installed (${finding.installedVersion})`,
        section: "peerDependencies",
        version: expectedVersion
      });
    }
    if (context.packageParams.devDependencies.includes(finding.peer)) {
      const devVersion = context.packageParams.devDependencyVersions[finding.peer];
      if (devVersion && !devVersion.startsWith("workspace:")) {
        fixes.push({
          action: "set-version",
          dependency: finding.peer,
          detail: `updated devDependency version to match installed (${finding.installedVersion})`,
          section: "devDependencies",
          version: expectedVersion
        });
      }
    }
  }
  addSourceBumpFixes(context, finding, fixes);
  return fixes;
}

// src/actions/deplint/rules.ts
var unlistedDependenciesRule = {
  category: "dependencies",
  id: "deplint.dependencies.unlisted",
  evaluate(context) {
    const findings = findUnlistedDependencies(
      context.workspace.name,
      context.packageParams.dependencies,
      context.packageParams.devDependencies,
      context.packageParams.peerDependencies,
      context.sourceParams.externalDistImports,
      context.sourceParams.externalDistTypeImports
    );
    const diagnostics = [];
    for (const { imp, section } of findings) {
      if (context.forceDevs.has(imp)) {
        if (context.packageParams.devDependencies.includes(imp)) continue;
        diagnostics.push(diagnostic(
          context,
          "deplint.dependencies.unlisted",
          `Missing devDependency in package.json: ${imp}`,
          imp,
          context.sourceParams.distImportPaths[imp],
          [resolvedAddFix(context, imp, "devDependencies", "added to devDependencies")]
        ));
        continue;
      }
      const isPeer = !context.isTerminalPackage && section === "dependencies" && !context.forceDeps.has(imp) && shouldBePeerDependency(imp, context.workspace.location, context.packageParams.peerDependencies, context.sourceParams.externalDistImports, context.workspaceNames);
      const fixes = isPeer ? ["peerDependencies", "devDependencies"].map(
        (s) => resolvedAddFix(context, imp, s, `added to ${s}`)
      ) : [resolvedAddFix(context, imp, section, `added to ${section}`)];
      diagnostics.push(diagnostic(
        context,
        "deplint.dependencies.unlisted",
        `Missing dependency in package.json: ${imp}`,
        imp,
        context.sourceParams.distImportPaths[imp],
        fixes
      ));
    }
    return diagnostics;
  }
};
var unusedDependenciesRule = {
  category: "dependencies",
  id: "deplint.dependencies.unused",
  evaluate(context) {
    const findings = findUnusedDependencies(
      context.workspace.location,
      context.packageParams.dependencies,
      context.packageParams.devDependencies,
      context.sourceParams.externalDistImports,
      context.sourceParams.externalDistTypeImports,
      context.sourceParams.externalAllImports,
      context.unusedDependencyExclude
    );
    return findings.map(({
      dep,
      kind,
      reason
    }) => diagnostic(
      context,
      "deplint.dependencies.unused",
      kind === "move-to-dev" ? `dependency should be devDependency in package.json: ${dep}${reason ? ` (${reason})` : ""}` : `Unused dependency in package.json: ${dep}`,
      dep,
      void 0,
      [kind === "move-to-dev" ? {
        action: "move",
        dependency: dep,
        detail: "moved to devDependencies",
        fromSection: "dependencies",
        toSection: "devDependencies"
      } : {
        action: "remove",
        dependency: dep,
        detail: "removed from dependencies",
        section: "dependencies"
      }]
    ));
  }
};
var unlistedDevDependenciesRule = {
  category: "devDependencies",
  id: "deplint.devDependencies.unlisted",
  evaluate(context) {
    const findings = findUnlistedDevDeps(
      context.workspace.name,
      context.packageParams.dependencies,
      context.packageParams.devDependencies,
      context.packageParams.peerDependencies,
      context.sourceParams.externalAllImports,
      context.sourceParams.distImports,
      context.sourceParams.externalDistTypeImports
    );
    return findings.map((imp) => diagnostic(
      context,
      "deplint.devDependencies.unlisted",
      `Missing devDependency in package.json: ${imp}`,
      imp,
      context.sourceParams.allImportPaths[imp],
      [resolvedAddFix(context, imp, "devDependencies", "added to devDependencies")]
    ));
  }
};
var unusedDevDependenciesRule = {
  category: "devDependencies",
  id: "deplint.devDependencies.unused",
  evaluate(context) {
    const findings = findUnusedDevDeps(
      context.workspace.location,
      context.packageParams.dependencies,
      context.packageParams.devDependencies,
      context.packageParams.peerDependencies,
      context.sourceParams,
      context.fileContext,
      context.unusedDependencyExclude
    );
    return findings.map((dep) => diagnostic(
      context,
      "deplint.devDependencies.unused",
      `Unused devDependency in package.json: ${dep}`,
      dep,
      void 0,
      [{
        action: "remove",
        dependency: dep,
        detail: "removed from devDependencies",
        section: "devDependencies"
      }]
    ));
  }
};
var redundantDevDependenciesRule = {
  category: "devDependencies",
  id: "deplint.devDependencies.redundant",
  evaluate(context) {
    const diagnostics = [];
    for (const dep of context.packageParams.devDependencies) {
      if (!context.packageParams.dependencies.includes(dep)) continue;
      if (!context.isTerminalPackage && !context.forceDeps.has(dep) && shouldBePeerDependency(dep, context.workspace.location, context.packageParams.peerDependencies, context.sourceParams.externalDistImports, context.workspaceNames)) {
        continue;
      }
      diagnostics.push(diagnostic(
        context,
        "deplint.devDependencies.redundant",
        `Redundant devDependency ${dep} \u2014 already listed in dependencies`,
        dep,
        void 0,
        [{
          action: "remove",
          dependency: dep,
          detail: "removed redundant devDependency (kept in dependencies)",
          section: "devDependencies"
        }]
      ));
    }
    return diagnostics;
  }
};
var unsatisfiedPeersRule = {
  category: "peerDependencies",
  id: "deplint.peerDependencies.unsatisfied",
  evaluate(context) {
    const findings = findUnsatisfiedPeers(
      context.workspace,
      context.packageParams,
      context.exclude,
      context.isTerminalPackage
    );
    return findings.map((finding) => {
      const requiredBy = finding.sources.map((source) => source.requiredBy).join(", ");
      const chain = finding.sources.find((source) => source.chain && source.chain.length > 0)?.chain?.join(" -> ");
      const evidence = chain ? [`via ${chain}`] : void 0;
      const message = finding.reason === "version-mismatch" ? `Peer dependency version mismatch ${finding.peer} \u2014 installed ${finding.installedVersion ?? "unknown"} does not satisfy ${finding.versionRange} (required by ${requiredBy})` : finding.reason === "under-exposed" ? `Under-exposed peer dependency ${finding.peer} (required by ${requiredBy}) \u2014 in devDependencies only; must also be in dependencies or peerDependencies` : finding.hasRuntimeSource ? `Unsatisfied peer dependency ${finding.peer} (required by ${requiredBy}) \u2014 must be in dependencies or peerDependencies` : `Unsatisfied peer dependency ${finding.peer} (required by devDependency ${requiredBy}) \u2014 must be in dependencies, devDependencies, or peerDependencies`;
      const fixes = finding.reason === "missing" ? resolvePeerTargetSections(finding.hasRuntimeSource, context.isTerminalPackage).map((section) => ({
        action: "add",
        dependency: finding.peer,
        detail: `added to ${section}`,
        section,
        version: finding.versionRange
      })) : finding.reason === "under-exposed" ? [{
        action: "add",
        dependency: finding.peer,
        detail: "added to peerDependencies",
        section: "peerDependencies",
        version: finding.versionRange
      }] : finding.reason === "version-mismatch" ? generateVersionMismatchFixes(context, finding) : void 0;
      return diagnostic(
        context,
        "deplint.peerDependencies.unsatisfied",
        message,
        finding.peer,
        evidence,
        fixes
      );
    });
  }
};
var unusedPeerDependenciesRule = {
  category: "peerDependencies",
  id: "deplint.peerDependencies.unused",
  evaluate(context) {
    const findings = findUnusedPeerDeps(
      context.packageParams.peerDependencies,
      context.sourceParams.externalDistImports,
      context.sourceParams.externalDistTypeImports,
      context.unusedDependencyExclude
    );
    return findings.map((dep) => diagnostic(
      context,
      "deplint.peerDependencies.unused",
      context.packageParams.dependencies.includes(dep) ? `Unused peerDependency [already a dependency] in package.json: ${dep}` : `Unused peerDependency in package.json: ${dep}`,
      dep,
      void 0,
      [{
        action: "remove",
        dependency: dep,
        detail: "removed from peerDependencies",
        section: "peerDependencies"
      }]
    ));
  }
};
var unrequestedPeerDependenciesRule = {
  category: "peerDependencies",
  id: "deplint.peerDependencies.unrequested",
  evaluate(context) {
    if (!context.isTerminalPackage) return [];
    const findings = findUnrequestedPeerDeps(
      context.workspace.location,
      context.packageParams,
      context.sourceParams,
      context.exclude
    );
    return findings.map((dep) => diagnostic(
      context,
      "deplint.peerDependencies.unrequested",
      `Unnecessary peerDependency ${dep} \u2014 imported in dist but no dependency requires it as a peer; should be a dependency`,
      dep,
      void 0,
      [{
        action: "move",
        dependency: dep,
        detail: "moved from peerDependencies to dependencies",
        fromSection: "peerDependencies",
        toSection: "dependencies",
        version: context.packageParams.peerDependencyVersions[dep] ?? "*"
      }]
    ));
  }
};
var redundantPeerDependenciesRule = {
  category: "peerDependencies",
  id: "deplint.peerDependencies.redundant",
  evaluate(context) {
    const findings = findRedundantPeerDeps(context.packageParams, context.exclude);
    return findings.map((dep) => diagnostic(
      context,
      "deplint.peerDependencies.redundant",
      `Redundant peerDependency ${dep} \u2014 already listed in dependencies`,
      dep,
      void 0,
      [{
        action: "remove",
        dependency: dep,
        detail: "removed redundant peerDependency (kept in dependencies)",
        section: "peerDependencies"
      }]
    ));
  }
};
var mismatchedPeerDevVersionsRule = {
  category: "peerDependencies",
  id: "deplint.peerDependencies.version-mismatch",
  evaluate(context) {
    const findings = findMismatchedPeerDevVersions(context.packageParams, context.exclude);
    return findings.map(({
      dep,
      devVersion,
      peerVersion
    }) => diagnostic(
      context,
      "deplint.peerDependencies.version-mismatch",
      `Peer/dev version mismatch ${dep} \u2014 peer: ${peerVersion}, dev: ${devVersion}`,
      dep,
      void 0,
      [{
        action: "set-version",
        dependency: dep,
        detail: "synced peerDependency to devDependency version",
        section: "peerDependencies",
        version: devVersion
      }]
    ));
  }
};
var workspaceVersionProblemsRule = {
  category: "peerDependencies",
  id: "deplint.workspace.protocol",
  evaluate(context) {
    if (!context.workspaceNames) return [];
    const protocolFindings = findWorkspaceVersionProblems(context.packageParams, context.workspaceNames);
    const protocolDiagnostics = protocolFindings.map(({
      dep,
      section,
      version
    }) => diagnostic(
      context,
      "deplint.workspace.protocol",
      `Workspace dependency ${dep} in ${section} should use workspace: protocol \u2014 found ${version}`,
      dep,
      void 0,
      [{
        action: "set-version",
        dependency: dep,
        detail: `set workspace:~ for ${section}`,
        section,
        version: "workspace:~"
      }]
    ));
    const peerFindings = findWorkspacePeerVersionProblems(
      context.packageParams,
      context.workspaceNames,
      context.workspace.location
    );
    const peerDiagnostics = peerFindings.map(({
      dep,
      actualVersion,
      declaredRange
    }) => {
      const expectedRange = resolveExpectedPeerVersion(
        context.workspace.location,
        dep,
        declaredRange
      );
      return diagnostic(
        context,
        "deplint.workspace.protocol",
        `Workspace peerDependency ${dep} range ${declaredRange} does not satisfy workspace version ${actualVersion}`,
        dep,
        void 0,
        expectedRange === "*" ? void 0 : [{
          action: "set-version",
          dependency: dep,
          detail: "updated peerDependency to match workspace version",
          section: "peerDependencies",
          version: expectedRange
        }]
      );
    });
    return [...protocolDiagnostics, ...peerDiagnostics];
  }
};
var deplintRules = [
  unlistedDependenciesRule,
  unusedDependenciesRule,
  misplacedDependenciesRule,
  unlistedDevDependenciesRule,
  unusedDevDependenciesRule,
  redundantDevDependenciesRule,
  unsatisfiedPeersRule,
  unusedPeerDependenciesRule,
  unrequestedPeerDependenciesRule,
  misplacedPeerDependenciesRule,
  redundantPeerDependenciesRule,
  mismatchedPeerDevVersionsRule,
  workspaceVersionProblemsRule
];

// src/actions/deplint/snapshot.ts
import fs14 from "fs";
function isTerminalPackage2(location) {
  try {
    const pkg = JSON.parse(fs14.readFileSync(`${location}/package.json`, "utf8"));
    return pkg.private === true;
  } catch {
    return false;
  }
}
function buildWorkspaceContext(workspace, exclude, workspaceNames, forceDeps, forcePeers, forceDevs) {
  const { allFiles, distFiles } = findFiles(workspace.location);
  const tsconfigExtends = getExtendsFromTsconfigs(workspace.location);
  const tsconfigTypes = getTypesFromTsconfigs(workspace.location);
  const sourceParams = getExternalImportsFromFiles({
    allFiles,
    distFiles,
    location: workspace.location,
    name: workspace.name,
    tsconfigExtends,
    tsconfigTypes
  });
  const packageJsonPath = `${workspace.location}/package.json`;
  const packageParams = getDependenciesFromPackageJson(packageJsonPath);
  const requiredTransitivePeers = getRequiredTransitivePeers(workspace.location, packageParams);
  return {
    exclude,
    fileContext: { allFiles, distFiles },
    forceDeps: forceDeps ?? /* @__PURE__ */ new Set(),
    forceDevs: forceDevs ?? /* @__PURE__ */ new Set(),
    forcePeers: forcePeers ?? /* @__PURE__ */ new Set(),
    isTerminalPackage: isTerminalPackage2(workspace.location),
    packageJsonPath,
    packageParams,
    sourceParams,
    unusedDependencyExclude: /* @__PURE__ */ new Set([...exclude ?? [], ...requiredTransitivePeers, ...forcePeers ?? []]),
    workspace,
    workspaceNames
  };
}

// src/actions/deplint/engine.ts
function resolveCheckFlags(deps = false, devDeps = false, peerDeps = false) {
  const noneExplicit = !(deps || devDeps || peerDeps);
  return {
    checkDependencies: deps || noneExplicit,
    checkDevDependencies: devDeps || noneExplicit,
    checkPeerDependencies: peerDeps || noneExplicit
  };
}
function shouldRunRule(category, ruleId, options) {
  const flags = resolveCheckFlags(options.deps, options.devDeps, options.peerDeps);
  if (ruleId === "deplint.peerDependencies.unsatisfied") {
    return flags.checkDependencies || flags.checkDevDependencies || flags.checkPeerDependencies;
  }
  if (ruleId === "deplint.workspace.protocol") {
    return flags.checkDependencies || flags.checkDevDependencies || flags.checkPeerDependencies;
  }
  if (category === "dependencies") return flags.checkDependencies;
  if (category === "devDependencies") return flags.checkDevDependencies;
  return flags.checkPeerDependencies;
}
async function evaluateWorkspaces(workspaces, options, workspaceNames) {
  const diagnostics = [];
  for (const workspace of workspaces) {
    const wsConfig = await loadWorkspaceCommandConfig(workspace.location, "deplint");
    const exclude = /* @__PURE__ */ new Set([
      ...wsConfig.exclude ?? [],
      ...options.cliExclude ?? []
    ]);
    const packageEntries = Object.entries(wsConfig.packages ?? {});
    const forceDeps = new Set(
      packageEntries.filter(([, cfg]) => cfg.refType === "dep").map(([name]) => name)
    );
    const forceDevs = new Set(
      packageEntries.filter(([, cfg]) => cfg.refType === "dev").map(([name]) => name)
    );
    const forcePeers = new Set(
      packageEntries.filter(([, cfg]) => cfg.refType === "peer").map(([name]) => name)
    );
    const context = buildWorkspaceContext(workspace, exclude, workspaceNames, forceDeps, forcePeers, forceDevs);
    if (options.verbose) {
      console.info(`Checking package: ${workspace.name} at ${workspace.location}`);
      console.info(`All files: ${context.fileContext.allFiles.length}, Distribution files: ${context.fileContext.distFiles.length}`);
    }
    for (const rule of deplintRules) {
      if (shouldRunRule(rule.category, rule.id, options)) {
        diagnostics.push(...rule.evaluate(context));
      }
    }
  }
  return diagnostics;
}
async function runDeplint(workspaces, options, workspaceNames) {
  let diagnostics = await evaluateWorkspaces(workspaces, options, workspaceNames);
  const appliedFixes = [];
  const MAX_FIX_PASSES = 5;
  for (let pass = 0; options.fix && diagnostics.length > 0 && pass < MAX_FIX_PASSES; pass++) {
    appliedFixes.push(...applyDeplintFixes(diagnostics));
    diagnostics = await evaluateWorkspaces(workspaces, options, workspaceNames);
  }
  const errorCount = diagnostics.filter((diagnostic2) => diagnostic2.severity === "error").length;
  const warningCount = diagnostics.filter((diagnostic2) => diagnostic2.severity === "warning").length;
  return {
    appliedFixes,
    diagnostics,
    summary: {
      appliedFixes: appliedFixes.length,
      errorCount,
      warningCount,
      workspacesChecked: workspaces.length
    }
  };
}

// src/actions/deplint/reporters.ts
import chalk15 from "chalk";
var humanDeplintReporter = {
  render(result) {
    for (const fix of result.appliedFixes) {
      console.log(`[${chalk15.blue(fix.workspace.name)}] Fixed: ${fix.detail} ${chalk15.green(fix.dependency)}`);
    }
    for (const diagnostic2 of result.diagnostics) {
      console.log(`[${chalk15.blue(diagnostic2.workspace.name)}] ${diagnostic2.message}`);
      for (const line of diagnostic2.evidence ?? []) {
        console.log(`  ${line}`);
      }
      console.log(`  ${chalk15.yellow(diagnostic2.file)}
`);
    }
    if (result.summary.errorCount > 0) {
      console.warn(`Deplint: Found ${chalk15.red(result.summary.errorCount)} dependency problems. ${chalk15.red("\u2716")}`);
      return;
    }
    console.info(`Deplint: Found no dependency problems. ${chalk15.green("\u2714")}`);
  }
};
var jsonDeplintReporter = {
  render(result) {
    console.log(JSON.stringify(result, null, 2));
  }
};
function getDeplintReporter(format) {
  return format === "json" ? jsonDeplintReporter : humanDeplintReporter;
}

// src/actions/deplint/deplint.ts
var deplint = async ({
  pkg,
  deps,
  devDeps,
  fix,
  peerDeps,
  verbose,
  cliExclude,
  format = "human"
}) => {
  const pm = getPackageManager();
  const workspaces = pm.listWorkspaces();
  const workspaceNames = pm.name === "pnpm" ? new Set(workspaces.map((ws) => ws.name)) : void 0;
  if (pkg === void 0 && format === "human") {
    console.info("Deplint Started...");
  }
  const targetWorkspace = pkg === void 0 ? void 0 : pm.findWorkspace(pkg);
  const targetWorkspaces = pkg === void 0 ? workspaces : targetWorkspace ? [targetWorkspace] : [];
  if (targetWorkspaces.length === 0) {
    console.error(chalk16.red(`Workspace not found: ${pkg}`));
    return 1;
  }
  const result = await runDeplint(targetWorkspaces, {
    cliExclude,
    deps,
    devDeps,
    fix,
    peerDeps,
    reporter: format,
    verbose
  }, workspaceNames);
  getDeplintReporter(format).render(result);
  if (fix && result.summary.appliedFixes > 0) {
    runInstall();
  }
  return result.summary.errorCount > 0 ? 1 : 0;
};
export {
  DeplintPackageEditor,
  applyDeplintFixes,
  buildWorkspaceContext,
  deplint,
  deplintRules,
  getDeplintReporter,
  humanDeplintReporter,
  jsonDeplintReporter,
  runDeplint
};
//# sourceMappingURL=index.mjs.map