// src/actions/deplint/findFiles.ts
import fs from "node:fs";
import path from "node:path";
import picomatch from "picomatch";
import ts from "typescript";

// src/pm/workspaces.ts
import { existsSync, readFileSync } from "node:fs";
import PATH from "node:path";
import { globSync } from "glob";
function readJsonFile(path8) {
  if (!existsSync(path8)) return void 0;
  try {
    return JSON.parse(readFileSync(path8, "utf8"));
  } catch {
    return void 0;
  }
}
function readRootPackageJson(cwd = process.cwd()) {
  return readJsonFile(PATH.resolve(cwd, "package.json"));
}
function readWorkspacePatternsFromPackageJson(cwd = process.cwd()) {
  const pkg = readRootPackageJson(cwd);
  if (!pkg?.workspaces) return [];
  if (Array.isArray(pkg.workspaces)) return [...pkg.workspaces];
  return pkg.workspaces.packages ? [...pkg.workspaces.packages] : [];
}
function readPnpmWorkspacePatterns(cwd = process.cwd()) {
  const wsPath = PATH.resolve(cwd, "pnpm-workspace.yaml");
  if (!existsSync(wsPath)) return [];
  const content = readFileSync(wsPath, "utf8");
  const patterns = [];
  let inPackages = false;
  for (const line of content.split("\n")) {
    if (/^packages\s*:/.test(line.trim())) {
      inPackages = true;
      continue;
    }
    if (inPackages) {
      const match = /^\s+-\s+['"]?([^'"]+)['"]?\s*$/.exec(line);
      if (match) {
        patterns.push(match[1]);
      } else if (line.trim() !== "" && !/^\s/.test(line)) {
        break;
      }
    }
  }
  return patterns;
}
function readWorkspacePatterns(cwd = process.cwd()) {
  const fromPackageJson = readWorkspacePatternsFromPackageJson(cwd);
  return fromPackageJson.length > 0 ? fromPackageJson : readPnpmWorkspacePatterns(cwd);
}

// 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,
    dot: true
  });
}

// src/actions/deplint/findFiles.ts
var codeExtensions = "*.{ts,tsx,mts,cts,js,mjs,cjs}";
var codeExtensionRe = /\.(?:ts|tsx|mts|cts|js|mjs|cjs)$/i;
var resolutionExtensions = [".mjs", ".cjs", ".js", ".d.mts", ".d.cts", ".d.ts", ".mts", ".cts", ".ts", ".tsx"];
var dotfileIgnorePatterns = [
  "**/.git/**",
  "**/.yarn/**",
  "**/.pnpm/**",
  "**/.pnpm-store/**",
  "**/.next/**",
  "**/.nuxt/**",
  "**/.svelte-kit/**",
  "**/.angular/**",
  "**/.vercel/**",
  "**/.netlify/**",
  "**/.turbo/**",
  "**/.cache/**",
  "**/.parcel-cache/**",
  "**/.docusaurus/**",
  "**/.vite/**",
  "**/.output/**"
];
function normalizeSourceExcludePattern(location, pattern) {
  const trimmed = pattern.trim();
  if (trimmed === "" || trimmed.startsWith("!")) return void 0;
  const relativePattern = path.isAbsolute(trimmed) ? path.relative(location, trimmed) : trimmed;
  if (relativePattern.startsWith("..")) return void 0;
  return relativePattern.replaceAll(path.sep, "/").replace(/^\.\//, "");
}
function toSourceIgnorePatterns(location, sourceExclude = []) {
  const patterns = /* @__PURE__ */ new Set();
  for (const exclude of sourceExclude) {
    const pattern = normalizeSourceExcludePattern(location, exclude);
    if (!pattern) continue;
    patterns.add(pattern);
    if (!pattern.endsWith("/**")) patterns.add(`${pattern}/**`);
  }
  return [...patterns];
}
function createSourceFileFilter(location, sourceIgnorePatterns) {
  if (sourceIgnorePatterns.length === 0) return () => true;
  const isIgnored = picomatch(sourceIgnorePatterns, { dot: true });
  return (filePath) => {
    const relativePath = path.relative(location, filePath).replaceAll(path.sep, "/");
    return !isIgnored(relativePath);
  };
}
function readPackageJson(location) {
  try {
    return JSON.parse(fs.readFileSync(`${location}/package.json`, "utf8"));
  } catch {
    return void 0;
  }
}
function collectExportTargets(value) {
  if (typeof value === "string") return value.startsWith("./") ? [value] : [];
  if (Array.isArray(value)) return value.flatMap(collectExportTargets);
  if (typeof value !== "object" || value === null) return [];
  return Object.values(value).flatMap(collectExportTargets);
}
function getManifestRuntimeEntries(pkg) {
  return [
    ...collectExportTargets(pkg?.exports),
    pkg?.main,
    pkg?.module,
    pkg?.types,
    pkg?.typings
  ].filter((entry) => typeof entry === "string");
}
function getBinEntries(pkg) {
  const bin = pkg?.bin;
  if (!bin) return [];
  return typeof bin === "string" ? [bin] : Object.values(bin).filter((entry) => typeof entry === "string");
}
function mayResolveToCode(entry) {
  const ext = path.extname(entry);
  return ext === "" || codeExtensionRe.test(entry);
}
function resolveCodeFile(filePath) {
  if (fs.existsSync(filePath) && codeExtensionRe.test(filePath)) return filePath;
  const ext = path.extname(filePath);
  if (ext) {
    const withoutExt = filePath.slice(0, -ext.length);
    for (const candidateExt of resolutionExtensions) {
      const candidate = `${withoutExt}${candidateExt}`;
      if (fs.existsSync(candidate)) return candidate;
    }
  }
  for (const ext2 of resolutionExtensions) {
    const candidate = `${filePath}${ext2}`;
    if (fs.existsSync(candidate)) return candidate;
  }
  for (const ext2 of resolutionExtensions) {
    const candidate = path.join(filePath, `index${ext2}`);
    if (fs.existsSync(candidate)) return candidate;
  }
  return void 0;
}
function resolveRuntimeEntry(location, entry) {
  if (path.isAbsolute(entry)) return [];
  const relativeEntry = entry.startsWith(".") ? entry : `./${entry}`;
  if (relativeEntry.includes("*")) return findFilesByGlob(location, relativeEntry).filter((file) => codeExtensionRe.test(file));
  const resolved = resolveCodeFile(path.resolve(location, relativeEntry));
  return resolved ? [resolved] : [];
}
function collectLocalImportSpecifiers(filePath) {
  const sourceCode = fs.readFileSync(filePath, "utf8");
  const isJsFile = /\.(?:js|mjs|cjs)$/i.test(filePath);
  const sourceFile = ts.createSourceFile(
    path.basename(filePath),
    sourceCode,
    ts.ScriptTarget.Latest,
    true,
    isJsFile ? ts.ScriptKind.JS : void 0
  );
  const imports = [];
  function addModuleSpecifier(moduleSpecifier) {
    if (moduleSpecifier && ts.isStringLiteral(moduleSpecifier) && moduleSpecifier.text.startsWith(".")) {
      imports.push(moduleSpecifier.text);
    }
  }
  function visit(node) {
    if (ts.isImportDeclaration(node) || ts.isExportDeclaration(node)) {
      addModuleSpecifier(node.moduleSpecifier);
    } else if (ts.isCallExpression(node) && node.expression.kind === ts.SyntaxKind.ImportKeyword) {
      addModuleSpecifier(node.arguments[0]);
    } else if (ts.isCallExpression(node) && ts.isIdentifier(node.expression) && node.expression.text === "require" && node.arguments.length > 0) {
      addModuleSpecifier(node.arguments[0]);
    }
    ts.forEachChild(node, visit);
  }
  visit(sourceFile);
  return imports;
}
function getReachableRuntimeFiles(runtimeRoots, shouldIncludeFile) {
  const seen = /* @__PURE__ */ new Set();
  const queue = runtimeRoots.filter(shouldIncludeFile);
  const result = [];
  while (queue.length > 0) {
    const file = queue.shift();
    if (!file || seen.has(file)) continue;
    if (!shouldIncludeFile(file)) continue;
    seen.add(file);
    result.push(file);
    for (const specifier of collectLocalImportSpecifiers(file)) {
      const resolved = resolveCodeFile(path.resolve(path.dirname(file), specifier));
      if (resolved && shouldIncludeFile(resolved) && !seen.has(resolved)) queue.push(resolved);
    }
  }
  return result;
}
function getBinFiles(location, pkg) {
  const bin = pkg?.bin;
  if (!bin) return [];
  const entries = typeof bin === "string" ? [bin] : Object.values(bin);
  const results = [];
  for (const entry of entries) {
    if (typeof entry !== "string") continue;
    const abs = path.resolve(location, entry);
    if (!codeExtensionRe.test(abs)) continue;
    if (!fs.existsSync(abs)) continue;
    results.push(abs);
  }
  return results;
}
function uniqueFiles(...lists) {
  const seen = /* @__PURE__ */ new Set();
  const result = [];
  for (const list of lists) {
    for (const file of list) {
      if (seen.has(file)) continue;
      seen.add(file);
      result.push(file);
    }
  }
  return result;
}
function findFiles(location, sourceExclude) {
  const pkg = readPackageJson(location);
  const workspaceIgnores = readWorkspacePatterns(location).filter((p) => !p.startsWith("!")).map((w) => `${w}/**`);
  const sourceIgnorePatterns = toSourceIgnorePatterns(location, sourceExclude);
  const shouldIncludeFile = createSourceFileFilter(location, sourceIgnorePatterns);
  const ignore = [
    "**/node_modules/**",
    "dist/**",
    ...dotfileIgnorePatterns,
    ...workspaceIgnores,
    ...sourceIgnorePatterns
  ];
  const allFiles = findFilesByGlob(location, `./**/${codeExtensions}`, ignore);
  const manifestRuntimeEntries = getManifestRuntimeEntries(pkg);
  const runtimeEntries = [...new Set([
    ...manifestRuntimeEntries,
    ...getBinEntries(pkg)
  ].filter(mayResolveToCode))];
  const binFiles = getBinFiles(location, pkg);
  const manifestRuntimeFiles = manifestRuntimeEntries.flatMap((entry) => resolveRuntimeEntry(location, entry));
  const runtimeRoots = uniqueFiles(manifestRuntimeFiles, binFiles);
  const distFiles = getReachableRuntimeFiles(runtimeRoots, shouldIncludeFile);
  return {
    allFiles,
    distFiles,
    runtimeRoots: runtimeEntries
  };
}

// src/actions/deplint/getDependenciesFromPackageJson.ts
import fs2 from "node:fs";
import path2 from "node:path";
function getDependenciesFromPackageJson(packageJsonPath) {
  const packageJsonFullPath = path2.resolve(packageJsonPath);
  const rawContent = fs2.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 fs3 from "node: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 parseTsconfig(file) {
  const content = fs3.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];
}

// src/actions/deplint/getExternalImportsFromFiles.ts
import fs6 from "node:fs";
import PATH2 from "node:path";
import chalk from "chalk";

// src/actions/deplint/getImportsFromFile.ts
import fs4 from "node:fs";
import path3 from "node:path";
import ts2 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 === ts2.SyntaxKind.TypeKeyword;
  }
  return clause.isTypeOnly ?? false;
}
function getImportsFromFile(filePath, importPaths, typeImportPaths) {
  const sourceCode = fs4.readFileSync(filePath, "utf8");
  const isJsFile = filePath.endsWith(".mjs") || filePath.endsWith(".cjs");
  const sourceFile = ts2.createSourceFile(
    path3.basename(filePath),
    sourceCode,
    ts2.ScriptTarget.Latest,
    true,
    isJsFile ? ts2.ScriptKind.JS : void 0
  );
  const imports = [];
  const typeImports = [];
  const isDeclarationFile2 = filePath.endsWith(".d.ts") || filePath.endsWith(".d.mts") || filePath.endsWith(".d.cts");
  function visit(node) {
    if (ts2.isImportDeclaration(node) || ts2.isExportDeclaration(node)) {
      const moduleSpecifier = node.moduleSpecifier?.getFullText();
      const isTypeImport = ts2.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 (ts2.isCallExpression(node) && node.expression.kind === ts2.SyntaxKind.ImportKeyword) {
      const [arg] = node.arguments;
      if (ts2.isStringLiteral(arg)) {
        imports.push(arg.text);
      }
    } else if (ts2.isCallExpression(node) && ts2.isIdentifier(node.expression) && node.expression.text === "require" && node.arguments.length > 0 && ts2.isStringLiteral(node.arguments[0])) {
      imports.push(node.arguments[0].text);
    }
    ts2.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/getStorybookConfigImports.ts
import fs5 from "node:fs";
import path4 from "node:path";
import ts3 from "typescript";
var storybookMainPattern = /(?:^|[\\/])\.storybook[\\/]main\.[cm]?[jt]sx?$/;
var npmPackageNamePattern = /^@?[a-z0-9][\w./-]*$/i;
function isStorybookMainFile(filePath) {
  return storybookMainPattern.test(filePath);
}
function getPropertyName(prop) {
  if (ts3.isIdentifier(prop.name)) return prop.name.text;
  if (ts3.isStringLiteral(prop.name) || ts3.isNoSubstitutionTemplateLiteral(prop.name)) return prop.name.text;
  return void 0;
}
function pushIfPackage(text, collected) {
  const trimmed = text.trim();
  if (trimmed.length === 0) return;
  if (trimmed.startsWith(".") || trimmed.startsWith("/") || trimmed.startsWith("node:")) return;
  if (!npmPackageNamePattern.test(trimmed)) return;
  collected.push(trimmed);
}
function extractFromEntry(node, collected) {
  if (ts3.isStringLiteral(node) || ts3.isNoSubstitutionTemplateLiteral(node)) {
    pushIfPackage(node.text, collected);
    return;
  }
  if (ts3.isObjectLiteralExpression(node)) {
    for (const prop of node.properties) {
      if (ts3.isPropertyAssignment(prop) && getPropertyName(prop) === "name") {
        extractFromEntry(prop.initializer, collected);
      }
    }
    return;
  }
  if (ts3.isCallExpression(node)) {
    for (const arg of node.arguments) {
      if (ts3.isStringLiteral(arg) || ts3.isNoSubstitutionTemplateLiteral(arg)) {
        pushIfPackage(arg.text, collected);
      }
    }
    return;
  }
  if (ts3.isArrayLiteralExpression(node)) {
    for (const element of node.elements) extractFromEntry(element, collected);
  }
}
function getStorybookConfigImports(filePath, importPaths) {
  if (!isStorybookMainFile(filePath)) return [];
  let sourceCode;
  try {
    sourceCode = fs5.readFileSync(filePath, "utf8");
  } catch {
    return [];
  }
  const sourceFile = ts3.createSourceFile(
    path4.basename(filePath),
    sourceCode,
    ts3.ScriptTarget.Latest,
    true
  );
  const collected = [];
  function visit(node) {
    if (ts3.isPropertyAssignment(node)) {
      const name = getPropertyName(node);
      if (name === "addons") {
        if (ts3.isArrayLiteralExpression(node.initializer)) {
          for (const element of node.initializer.elements) extractFromEntry(element, collected);
        }
      } else if (name === "framework" || name === "builder") {
        extractFromEntry(node.initializer, collected);
      }
    }
    ts3.forEachChild(node, visit);
  }
  visit(sourceFile);
  const cleaned = [...new Set(collected.map(getBasePackageName))];
  for (const imp of cleaned) {
    importPaths[imp] = importPaths[imp] ?? [];
    if (!importPaths[imp].includes(filePath)) importPaths[imp].push(filePath);
  }
  return cleaned;
}

// 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 formatExportPath(pathParts) {
  return pathParts.map((part, index) => {
    if (index === 0) return part;
    if (part.startsWith("[")) return part;
    return /^[a-zA-Z_$][\w$]*$/.test(part) ? `.${part}` : `[${JSON.stringify(part)}]`;
  }).join("");
}
function collectExportTargets2(value, pathParts = ["exports"]) {
  if (typeof value === "string") {
    if (!value.startsWith("./")) return [];
    return [{ path: formatExportPath(pathParts), target: value }];
  }
  if (Array.isArray(value)) {
    return value.flatMap((entry, index) => collectExportTargets2(entry, [...pathParts, `[${index}]`]));
  }
  if (typeof value !== "object" || value === null) return [];
  return Object.entries(value).flatMap(([key, nested]) => collectExportTargets2(nested, [...pathParts, key]));
}
function exportTargetExists(location, target) {
  if (target.includes("*")) return findFilesByGlob(location, target).length > 0;
  return fs6.existsSync(PATH2.resolve(location, target));
}
function readPackageJson2(location) {
  try {
    return JSON.parse(fs6.readFileSync(`${location}/package.json`, "utf8"));
  } catch {
    return void 0;
  }
}
function warnMissingExportTargets(name, location) {
  const pkg = readPackageJson2(location);
  const targets = collectExportTargets2(pkg?.exports);
  const warnedTargets = /* @__PURE__ */ new Set();
  const prefix = name ? `[${chalk.blue(name)}] ` : "";
  for (const { path: exportPath, target } of targets) {
    if (warnedTargets.has(target)) continue;
    warnedTargets.add(target);
    if (exportTargetExists(location, target)) continue;
    const description = target.includes("*") ? "pattern matched no files" : "file missing";
    console.warn(`${prefix}${chalk.yellow(`deplint: package.json export ${description}: ${target} (${exportPath})`)}`);
  }
}
function shipsTsconfig(location) {
  const pkg = readPackageJson2(location);
  const files = pkg?.files;
  return files?.some((f) => f === "tsconfig.json" || f.includes("tsconfig")) ?? false;
}
function getEffectiveRuntimeImportPaths({
  distImportPaths,
  distTypeImportPaths,
  hasDist,
  hasRuntimeRoots,
  srcImportPaths,
  srcTypeImportPaths
}) {
  if (hasDist) {
    return {
      importPaths: distImportPaths,
      typeImportPaths: distTypeImportPaths
    };
  }
  if (!hasRuntimeRoots) {
    return {
      importPaths: {},
      typeImportPaths: {}
    };
  }
  return {
    importPaths: excludeToolingConfigImports(srcImportPaths),
    typeImportPaths: excludeToolingConfigImports(srcTypeImportPaths)
  };
}
function getExternalImportsFromFiles({
  allFiles,
  distFiles,
  hasRuntimeRoots = true,
  location,
  name,
  tsconfigExtends = [],
  tsconfigTypes = []
}) {
  const srcImportPaths = {};
  const srcTypeImportPaths = {};
  for (const path8 of allFiles) {
    getImportsFromFile(path8, srcImportPaths, srcTypeImportPaths);
    getStorybookConfigImports(path8, srcImportPaths);
  }
  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 path8 of distCodeFiles) getImportsFromFile(path8, distImportPaths, distImportPaths);
    for (const path8 of distTypeFiles) getImportsFromFile(path8, distTypeImportPaths, distTypeImportPaths);
  }
  warnMissingExportTargets(name, location);
  const {
    importPaths: effectiveDistImportPaths,
    typeImportPaths: effectiveDistTypeImportPaths
  } = getEffectiveRuntimeImportPaths({
    distImportPaths,
    distTypeImportPaths,
    hasDist,
    hasRuntimeRoots,
    srcImportPaths,
    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 chalk3 from "chalk";
import semver2 from "semver";

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

// src/actions/deplint/getRequiredPeerDependencies.ts
import fs7 from "node:fs";
import path5 from "node:path";
function findDepPackageJson(location, dep) {
  let dir = location;
  while (true) {
    const candidate = path5.join(dir, "node_modules", dep, "package.json");
    if (fs7.existsSync(candidate)) return candidate;
    const parent = path5.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 = fs7.readFileSync(depPkgPath, "utf8");
      const pkg = JSON.parse(raw);
      const peerDeps = pkg.peerDependencies;
      const meta = pkg.peerDependenciesMeta;
      if (peerDeps) {
        for (const peer of Object.keys(peerDeps)) {
          if (meta?.[peer]?.optional) continue;
          required.add(peer);
        }
      }
    } catch {
    }
  }
  return required;
}

// src/actions/deplint/packageJsonEditor.ts
function readPackageJson3(location) {
  return JSON.parse(fs8.readFileSync(`${location}/package.json`, "utf8"));
}
function writePackageJson(location, pkg) {
  const sorted = sortPackageJson(JSON.stringify(pkg, null, 2));
  fs8.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;
  if (from === "peerDependencies" && to !== "peerDependencies") {
    removePeerMeta(pkg, dep);
  }
}
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];
  }
  if (section === "peerDependencies") {
    removePeerMeta(pkg, dep);
  }
}
function addDep(pkg, dep, version, section) {
  const sectionObj = pkg[section] ?? {};
  sectionObj[dep] = version;
  pkg[section] = sectionObj;
}
function removePeerMeta(pkg, dep) {
  const meta = pkg.peerDependenciesMeta;
  if (!meta?.[dep]) return;
  delete meta[dep];
  if (Object.keys(meta).length === 0) {
    delete pkg.peerDependenciesMeta;
  }
}
function formatPeerRange(version, boundType = "major") {
  const parsed = semver.parse(version);
  if (!parsed) return `~${version}`;
  if (boundType === "minor") return `>=${parsed.version} <${parsed.major}.${parsed.minor + 1}`;
  return `>=${parsed.version} <${parsed.major + 1}`;
}
function inferPeerBoundType(devRange) {
  return devRange?.startsWith("~") ? "minor" : "major";
}
function readInstalledVersion(location, dep) {
  const depPkgPath = findDepPackageJson(location, dep);
  if (!depPkgPath) return void 0;
  try {
    const depPkg = JSON.parse(fs8.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 resolvePeerDepVersion(location, dep, devRange) {
  const lower = resolvePeerLowerBound(location, dep, devRange);
  return lower ? formatPeerRange(lower, inferPeerBoundType(devRange)) : "*";
}
function logFix(workspace, action, dep, detail) {
  const detailStr = detail ? ` (${detail})` : "";
  console.log(`[${chalk2.blue(workspace.name)}] Fixed: ${action} ${chalk2.green(dep)}${detailStr}`);
}

// src/actions/deplint/checkPackage/getMismatchedPeerDevVersions.ts
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 && !semver2.subset(devVersion, peerVersion)) {
      mismatches.push({
        dep,
        devVersion,
        peerVersion
      });
    }
  }
  return mismatches;
}
function getMismatchedPeerDevVersions({ name, location }, packageParams, exclude) {
  const mismatches = findMismatchedPeerDevVersions(packageParams, exclude);
  for (const {
    dep,
    peerVersion,
    devVersion
  } of mismatches) {
    console.log(
      `[${chalk3.blue(name)}] Peer/dev version mismatch ${chalk3.red(dep)} \u2014 peer: ${chalk3.yellow(peerVersion)}, dev: ${chalk3.cyan(devVersion)}`
    );
  }
  if (mismatches.length > 0) {
    console.log(`  ${chalk3.yellow(`${location}/package.json`)}
`);
  }
  return mismatches.length;
}
function fixMismatchedPeerDevVersions(workspace, packageParams, exclude) {
  const mismatches = findMismatchedPeerDevVersions(packageParams, exclude);
  if (mismatches.length === 0) return 0;
  const pkg = readPackageJson3(workspace.location);
  for (const { dep, devVersion } of mismatches) {
    if (pkg.peerDependencies?.[dep]) {
      pkg.peerDependencies[dep] = devVersion;
      console.log(
        `[${chalk3.blue(workspace.name)}] Fixed: synced peerDependency ${chalk3.green(dep)} to devDependency version ${chalk3.cyan(devVersion)}`
      );
    }
  }
  writePackageJson(workspace.location, pkg);
  return mismatches.length;
}

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

// src/actions/deplint/isTerminalPackage.ts
import fs9 from "node:fs";
var EXPORT_META_KEYS = /* @__PURE__ */ new Set([".", "./package.json", "./README.md"]);
function hasBinSetup(bin) {
  if (typeof bin === "string") return bin.length > 0;
  if (typeof bin !== "object" || bin === null || Array.isArray(bin)) return false;
  return Object.keys(bin).length > 0;
}
function exportsLookCliOnly(exports) {
  if (exports === void 0) return true;
  if (typeof exports === "string") return true;
  if (typeof exports !== "object" || exports === null || Array.isArray(exports)) return false;
  return Object.keys(exports).every((k) => EXPORT_META_KEYS.has(k));
}
function hasLibrarySurface(pkg) {
  return pkg.main !== void 0 || pkg.module !== void 0 || !exportsLookCliOnly(pkg.exports);
}
function withTerminalOverride(classification, terminalOverride) {
  if (terminalOverride === void 0) return classification;
  if (terminalOverride) {
    return {
      isTerminalPackage: true,
      kind: classification.kind === "terminal[private]" ? "terminal[private]" : "terminal[cli]"
    };
  }
  return {
    isTerminalPackage: false,
    kind: classification.kind === "library/cli" || classification.kind === "terminal[cli]" ? "library/cli" : "library"
  };
}
function classifyDeplintPackage(location, terminalOverride) {
  try {
    const pkg = JSON.parse(
      fs9.readFileSync(`${location}/package.json`, "utf8")
    );
    if (pkg.private === true) {
      return withTerminalOverride({
        isTerminalPackage: true,
        kind: "terminal[private]"
      }, terminalOverride);
    }
    if (pkg.xy?.commands?.deplint?.terminal === true) {
      return withTerminalOverride({
        isTerminalPackage: true,
        kind: "terminal[cli]"
      }, terminalOverride);
    }
    const hasBin = hasBinSetup(pkg.bin);
    if (hasBin && hasLibrarySurface(pkg)) {
      return withTerminalOverride({
        isTerminalPackage: false,
        kind: "library/cli"
      }, terminalOverride);
    }
    if (hasBin) {
      return withTerminalOverride({
        isTerminalPackage: true,
        kind: "terminal[cli]"
      }, terminalOverride);
    }
    return withTerminalOverride({
      isTerminalPackage: false,
      kind: "library"
    }, terminalOverride);
  } catch {
    return withTerminalOverride({
      isTerminalPackage: false,
      kind: "library"
    }, terminalOverride);
  }
}
function isTerminalPackage(location) {
  return classifyDeplintPackage(location).isTerminalPackage;
}

// src/actions/deplint/tsScriptsAliases.ts
var VARIANT_MAP = {
  "@xylabs/toolchain": "@xylabs/toolchain",
  "@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 logMissing(name, imp, importPaths) {
  console.log(`[${chalk4.blue(name)}] Missing dependency in package.json: ${chalk4.red(imp)}`);
  if (importPaths[imp]) {
    console.log(`  ${importPaths[imp].join("\n ")}`);
  }
}
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;
}
function getUnlistedDependencies({ name, location }, {
  dependencies,
  devDependencies,
  peerDependencies
}, {
  externalDistImports,
  externalDistTypeImports,
  distImportPaths
}) {
  const unlisted = findUnlistedDependencies(name, dependencies, devDependencies, peerDependencies, externalDistImports, externalDistTypeImports);
  for (const { imp } of unlisted) {
    logMissing(name, imp, distImportPaths);
  }
  if (unlisted.length > 0) {
    console.log(`  ${chalk4.yellow(`${location}/package.json`)}
`);
  }
  return unlisted.length;
}
function fixUnlistedDependencies(workspace, {
  dependencies,
  devDependencies,
  peerDependencies
}, { externalDistImports, externalDistTypeImports }, workspaceNames, isTerminal) {
  const unlisted = findUnlistedDependencies(workspace.name, dependencies, devDependencies, peerDependencies, externalDistImports, externalDistTypeImports);
  if (unlisted.length === 0) return 0;
  const pkg = readPackageJson3(workspace.location);
  const isTerminalResolved = isTerminal ?? isTerminalPackage(workspace.location);
  const devVersions = pkg.devDependencies ?? {};
  for (const { imp, section } of unlisted) {
    const isPeer = !isTerminalResolved && section === "dependencies" && shouldBePeerDependency(imp, workspace.location, peerDependencies, externalDistImports, workspaceNames);
    if (isPeer) {
      const devVersion = resolveDepVersion(workspace.location, imp);
      const peerVersion = resolvePeerDepVersion(workspace.location, imp, devVersions[imp] ?? devVersion);
      addDep(pkg, imp, peerVersion, "peerDependencies");
      logFix(workspace, "added to peerDependencies", imp, peerVersion);
      addDep(pkg, imp, devVersion, "devDependencies");
      logFix(workspace, "added to devDependencies", imp, devVersion);
    } else {
      const version = resolveDepVersion(workspace.location, imp);
      addDep(pkg, imp, version, section);
      logFix(workspace, `added to ${section}`, imp, version);
    }
  }
  writePackageJson(workspace.location, pkg);
  return unlisted.length;
}

// src/actions/deplint/checkPackage/getUnlistedDevDependencies.ts
import { builtinModules as builtinModules2 } from "node:module";
import chalk5 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;
}
function getUnlistedDevDependencies({ name, location }, {
  devDependencies,
  dependencies,
  peerDependencies
}, {
  allImportPaths,
  externalAllImports,
  distImports,
  externalDistTypeImports
}) {
  const unlisted = findUnlistedDevDeps(name, dependencies, devDependencies, peerDependencies, externalAllImports, distImports, externalDistTypeImports);
  for (const imp of unlisted) {
    console.log(`[${chalk5.blue(name)}] Missing devDependency in package.json: ${chalk5.red(imp)}`);
    if (allImportPaths[imp]) {
      console.log(`  ${allImportPaths[imp].join("\n ")}`);
    }
  }
  if (unlisted.length > 0) {
    console.log(`  ${chalk5.yellow(`${location}/package.json`)}
`);
  }
  return unlisted.length;
}
function fixUnlistedDevDependencies(workspace, {
  devDependencies,
  dependencies,
  peerDependencies
}, {
  externalAllImports,
  distImports,
  externalDistTypeImports
}) {
  const unlisted = findUnlistedDevDeps(workspace.name, dependencies, devDependencies, peerDependencies, externalAllImports, distImports, externalDistTypeImports);
  if (unlisted.length === 0) return 0;
  const pkg = readPackageJson3(workspace.location);
  for (const imp of unlisted) {
    const version = resolveDepVersion(workspace.location, imp);
    addDep(pkg, imp, version, "devDependencies");
    logFix(workspace, "added to devDependencies", imp, version);
  }
  writePackageJson(workspace.location, pkg);
  return unlisted.length;
}

// src/actions/deplint/checkPackage/getUnnecessaryPeerDependencies.ts
import chalk6 from "chalk";

// src/actions/deplint/checkPackage/getUnsatisfiedPeerDependencies.ts
import fs10 from "node:fs";
import semver3 from "semver";
function readDepPackageJson(location, dep) {
  const depPkgPath = findDepPackageJson(location, dep);
  if (!depPkgPath) return void 0;
  try {
    return JSON.parse(fs10.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 readInstalledVersion2(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, peerDependencies = []) {
  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]);
        }
      }
    }
  }
  const runtimeRoots = [.../* @__PURE__ */ new Set([...dependencies, ...peerDependencies])];
  collectFromDeps(runtimeRoots, true, []);
  const devOnly = devDependencies.filter((d) => !runtimeRoots.includes(d));
  collectFromDeps(devOnly, false, []);
  return peerSources;
}
function getRequiredTransitivePeers(location, {
  dependencies,
  devDependencies,
  peerDependencies
}) {
  const peerSources = collectPeerSources(location, dependencies, devDependencies, peerDependencies);
  return new Set(peerSources.keys());
}
function getRequiredNonOptionalTransitivePeers(location, {
  dependencies,
  devDependencies,
  peerDependencies
}) {
  const peerSources = collectPeerSources(location, dependencies, devDependencies, peerDependencies);
  const result = /* @__PURE__ */ new Set();
  for (const [peer, sources] of peerSources) {
    if (!isPeerOptionalInAll(location, peer, sources)) result.add(peer);
  }
  return result;
}
function getRuntimeRootedNonOptionalTransitivePeers(location, {
  dependencies,
  devDependencies,
  peerDependencies
}) {
  const peerSources = collectPeerSources(location, dependencies, devDependencies, peerDependencies);
  const result = /* @__PURE__ */ new Set();
  for (const [peer, sources] of peerSources) {
    const runtimeSources = sources.filter((s) => s.isRuntimeDep);
    if (runtimeSources.length === 0) continue;
    if (isPeerOptionalInAll(location, peer, runtimeSources)) continue;
    result.add(peer);
  }
  return result;
}
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 = readInstalledVersion2(location, peer);
  if (!installedVersion) return { satisfied: true };
  if (requestedRange === "*") return { installedVersion, satisfied: true };
  if (requestedRange.startsWith("workspace:")) return { installedVersion, satisfied: true };
  try {
    const satisfied = semver3.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 classifyPeer(peer, sources, ctx) {
  const {
    location,
    depsSet,
    devDepsSet,
    peerDepsSet,
    isTerminal,
    forceDevs,
    forcePeerOptional
  } = ctx;
  if (forceDevs.has(peer)) return void 0;
  const isPeerForced = forcePeerOptional?.has(peer) ?? false;
  const runtimeSources = sources.filter((s) => s.isRuntimeDep);
  const hasRuntimeSource = runtimeSources.length > 0 && (isPeerForced || !isPeerOptionalInAll(location, peer, runtimeSources));
  if (!depsSet.has(peer) && !devDepsSet.has(peer)) {
    return {
      hasRuntimeSource,
      peer,
      reason: "missing",
      sources,
      versionRange: resolveVersionRange(location, sources, peer)
    };
  }
  const directRuntimeSources = sources.filter((s) => s.isRuntimeDep && !s.chain);
  const shouldForwardRuntime = directRuntimeSources.length > 0 && (isPeerForced || !isPeerOptionalInAll(location, peer, directRuntimeSources));
  if (shouldForwardRuntime && !isTerminal && !depsSet.has(peer) && !peerDepsSet.has(peer)) {
    return {
      hasRuntimeSource,
      peer,
      reason: "under-exposed",
      sources,
      versionRange: resolveVersionRange(location, sources, peer)
    };
  }
  const versionRange = resolveVersionRange(location, sources, peer);
  const { installedVersion, satisfied } = checkVersionSatisfaction(location, peer, versionRange);
  if (satisfied) return void 0;
  return {
    hasRuntimeSource,
    installedVersion,
    mismatchedSources: findMismatchedSources(location, sources, peer, installedVersion),
    peer,
    reason: "version-mismatch",
    sources,
    versionRange
  };
}
function findUnsatisfiedPeers({ name, location }, {
  dependencies,
  devDependencies,
  peerDependencies,
  peerDependencyVersions
}, exclude, isTerminal, forcePeerOptional, forceDevs) {
  const peerSources = collectPeerSources(location, dependencies, devDependencies, peerDependencies);
  const ctx = {
    depsSet: new Set(dependencies),
    devDepsSet: new Set(devDependencies),
    forceDevs: forceDevs ?? /* @__PURE__ */ new Set(),
    forcePeerOptional,
    isTerminal: isTerminal ?? isTerminalPackage(location),
    location,
    peerDepsSet: new Set(peerDependencies)
  };
  const unsatisfied = [];
  for (const [peer, sources] of peerSources) {
    if (exclude?.has(peer) || peer === name) continue;
    if (!forcePeerOptional?.has(peer) && isPeerOptionalInAll(location, peer, sources)) continue;
    const finding = classifyPeer(peer, sources, ctx);
    if (finding) unsatisfied.push(finding);
  }
  const declaredMismatches = findDeclaredPeerVersionMismatches(name, location, peerDependencies, peerDependencyVersions, exclude).filter((m) => !forceDevs?.has(m.peer));
  return [
    ...unsatisfied,
    ...declaredMismatches
  ];
}
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 !semver3.satisfies(installedVersion, range, { includePrerelease: 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 }, isTerminal, exclude) {
  const requiredPeers = isTerminal ? null : 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 getUnrequestedPeerDependencies({ name, location }, packageParams, sourceParams, exclude, isTerminal) {
  const isTerminalResolved = isTerminal ?? isTerminalPackage(location);
  if (!isTerminalResolved) return 0;
  const unrequested = findUnrequestedPeerDeps(location, packageParams, sourceParams, true, exclude);
  for (const dep of unrequested) {
    console.log(
      `[${chalk6.blue(name)}] Unnecessary peerDependency ${chalk6.red(dep)} \u2014 imported in dist but no dependency requires it as a peer; should be a dependency`
    );
  }
  if (unrequested.length > 0) {
    console.log(`  ${chalk6.yellow(`${location}/package.json`)}
`);
  }
  return unrequested.length;
}
function fixUnrequestedPeerDependencies(workspace, packageParams, sourceParams, exclude, isTerminal) {
  const isTerminalResolved = isTerminal ?? isTerminalPackage(workspace.location);
  const unrequested = findUnrequestedPeerDeps(workspace.location, packageParams, sourceParams, isTerminalResolved, exclude);
  if (unrequested.length === 0) return 0;
  const tsconfigExtendsSet = new Set(sourceParams.tsconfigExtends);
  const fixable = isTerminalResolved ? unrequested : unrequested.filter((dep) => tsconfigExtendsSet.has(dep));
  if (fixable.length === 0) return 0;
  const pkg = readPackageJson3(workspace.location);
  for (const dep of fixable) {
    const version = packageParams.peerDependencyVersions[dep] ?? "*";
    removeDep(pkg, dep, "peerDependencies");
    pkg.dependencies = pkg.dependencies ?? {};
    pkg.dependencies[dep] = version;
    logFix(workspace, "moved from peerDependencies to dependencies", dep);
  }
  writePackageJson(workspace.location, pkg);
  return fixable.length;
}
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;
}
function getRedundantPeerDependencies({ name, location }, packageParams, exclude) {
  const redundant = findRedundantPeerDeps(packageParams, exclude);
  for (const dep of redundant) {
    console.log(
      `[${chalk6.blue(name)}] Redundant peerDependency ${chalk6.red(dep)} \u2014 already listed in dependencies`
    );
  }
  if (redundant.length > 0) {
    console.log(`  ${chalk6.yellow(`${location}/package.json`)}
`);
  }
  return redundant.length;
}
function fixRedundantPeerDependencies(workspace, packageParams, exclude) {
  const redundant = findRedundantPeerDeps(packageParams, exclude);
  if (redundant.length === 0) return 0;
  const pkg = readPackageJson3(workspace.location);
  for (const dep of redundant) {
    removeDep(pkg, dep, "peerDependencies");
    logFix(workspace, "removed redundant peerDependency (kept in dependencies)", dep);
  }
  writePackageJson(workspace.location, pkg);
  return redundant.length;
}

// src/actions/deplint/checkPackage/getUnusedDependencies.ts
import chalk7 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;
}
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(`[${chalk7.blue(name)}] dependency should be devDependency in package.json: ${chalk7.red(dep)}${reasonStr}`);
    } else {
      console.log(`[${chalk7.blue(name)}] Unused dependency in package.json: ${chalk7.red(dep)}`);
    }
  }
  if (unused.length > 0) {
    console.log(`  ${chalk7.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 = readPackageJson3(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;
}

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

// src/actions/deplint/getCliReferencedPackagesFromFiles.ts
import fs12 from "node:fs";
import path7 from "node:path";
import ts4 from "typescript";

// src/actions/deplint/getScriptReferencedPackages.ts
import fs11 from "node:fs";
import path6 from "node: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 = path6.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 = ts4.createSourceFile(
    path7.basename(filePath),
    sourceCode,
    ts4.ScriptTarget.Latest,
    true,
    isMjsFile ? ts4.ScriptKind.JS : void 0
  );
  function visit(node) {
    if (ts4.isCallExpression(node) && node.arguments.length > 0) {
      const fnName = getFunctionName(node.expression);
      if (fnName && allExecFunctions.has(fnName)) {
        const firstArg = node.arguments[0];
        if (ts4.isStringLiteral(firstArg) || ts4.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 (ts4.isTemplateExpression(firstArg)) {
          const head = firstArg.head.text;
          if (head) {
            for (const token of tokenizeScript(head)) {
              tokens.add(token);
            }
          }
        }
      }
    }
    ts4.forEachChild(node, visit);
  }
  visit(sourceFile);
  return tokens;
}
function getFunctionName(expr) {
  if (ts4.isIdentifier(expr)) {
    return expr.text;
  }
  if (ts4.isPropertyAccessExpression(expr) && ts4.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 "node: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;
}
function getUnusedDevDependencies({ name, location }, {
  devDependencies,
  dependencies,
  peerDependencies
}, sourceParams, fileContext, exclude) {
  const unused = findUnusedDevDeps(location, dependencies, devDependencies, peerDependencies, sourceParams, fileContext, exclude);
  for (const dep of unused) {
    console.log(`[${chalk8.blue(name)}] Unused devDependency in package.json: ${chalk8.red(dep)}`);
  }
  if (unused.length > 0) {
    console.log(`  ${chalk8.yellow(`${location}/package.json`)}
`);
  }
  return unused.length;
}
function fixUnusedDevDependencies(workspace, {
  devDependencies,
  dependencies,
  peerDependencies
}, sourceParams, fileContext, exclude) {
  const unused = findUnusedDevDeps(workspace.location, dependencies, devDependencies, peerDependencies, sourceParams, fileContext, exclude);
  if (unused.length === 0) return 0;
  const pkg = readPackageJson3(workspace.location);
  for (const dep of unused) {
    removeDep(pkg, dep, "devDependencies");
    logFix(workspace, "removed from devDependencies", dep);
  }
  writePackageJson(workspace.location, pkg);
  return unused.length;
}

// src/actions/deplint/checkPackage/getUnusedPeerDependencies.ts
import chalk9 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;
}
function getUnusedPeerDependencies({ name, location }, { peerDependencies, dependencies }, { externalDistImports, externalDistTypeImports }, exclude) {
  const unused = findUnusedPeerDeps(peerDependencies, externalDistImports, externalDistTypeImports, exclude);
  for (const dep of unused) {
    if (dependencies.includes(dep)) {
      console.log(`[${chalk9.blue(name)}] Unused peerDependency [already a dependency] in package.json: ${chalk9.red(dep)}`);
    } else {
      console.log(`[${chalk9.blue(name)}] Unused peerDependency in package.json: ${chalk9.red(dep)}`);
    }
  }
  if (unused.length > 0) {
    console.log(`  ${chalk9.yellow(`${location}/package.json`)}
`);
  }
  return unused.length;
}
function fixUnusedPeerDependencies(workspace, { peerDependencies }, { externalDistImports, externalDistTypeImports }, exclude) {
  const unused = findUnusedPeerDeps(peerDependencies, externalDistImports, externalDistTypeImports, exclude);
  if (unused.length === 0) return 0;
  const pkg = readPackageJson3(workspace.location);
  for (const dep of unused) {
    removeDep(pkg, dep, "peerDependencies");
    logFix(workspace, "removed from peerDependencies", dep);
  }
  writePackageJson(workspace.location, pkg);
  return unused.length;
}

// src/actions/deplint/checkPackage/getWorkspaceVersionProblems.ts
import chalk10 from "chalk";
import semver4 from "semver";
function checkSection(deps, versions, section, workspaceNames, problems, expectedVersion) {
  for (const dep of deps) {
    if (!workspaceNames.has(dep)) continue;
    const version = versions[dep];
    const invalidVersion = expectedVersion === void 0 ? version && !version.startsWith("workspace:") : version !== expectedVersion;
    if (version && invalidVersion) {
      problems.push({
        dep,
        expectedVersion,
        section,
        version
      });
    }
  }
}
function findWorkspaceVersionProblems(packageParams, workspaceNames, expectedVersion) {
  const problems = [];
  checkSection(packageParams.dependencies, packageParams.dependencyVersions, "dependencies", workspaceNames, problems, expectedVersion);
  checkSection(packageParams.devDependencies, packageParams.devDependencyVersions, "devDependencies", workspaceNames, problems, expectedVersion);
  checkSection(packageParams.peerDependencies, packageParams.peerDependencyVersions, "peerDependencies", workspaceNames, problems, expectedVersion);
  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 (!semver4.satisfies(actualVersion, declaredRange)) {
      problems.push({
        actualVersion,
        declaredRange,
        dep
      });
    }
  }
  return problems;
}
function getWorkspaceVersionProblems({ name, location }, packageParams, workspaceNames) {
  const problems = findWorkspaceVersionProblems(packageParams, workspaceNames);
  for (const {
    dep,
    section,
    version
  } of problems) {
    console.log(
      `[${chalk10.blue(name)}] Workspace dependency ${chalk10.red(dep)} in ${chalk10.cyan(section)} should use workspace: protocol \u2014 found ${chalk10.yellow(version)}`
    );
  }
  if (problems.length > 0) {
    console.log(`  ${chalk10.yellow(`${location}/package.json`)}
`);
  }
  return problems.length;
}
function fixWorkspaceVersionProblems(workspace, packageParams, workspaceNames, expectedVersion = "workspace:~") {
  const problems = findWorkspaceVersionProblems(packageParams, workspaceNames, expectedVersion);
  if (problems.length === 0) return 0;
  const pkg = readPackageJson3(workspace.location);
  for (const { dep, section } of problems) {
    addDep(pkg, dep, expectedVersion, section);
    logFix(workspace, `set ${expectedVersion} for ${section}`, dep);
  }
  writePackageJson(workspace.location, pkg);
  return problems.length;
}

// src/actions/deplint/checkPackage/legacyPeerCheck.ts
import fs14 from "node:fs";
import chalk11 from "chalk";
import sortPackageJson2 from "sort-package-json";
function formatChain(sources) {
  const chainsWithDepth = sources.filter((s) => s.chain && s.chain.length > 0);
  if (chainsWithDepth.length === 0) return "";
  const first = chainsWithDepth[0];
  return ` (via ${chalk11.dim(first.chain.join(" \u2192 "))})`;
}
function logUnsatisfiedPeer(name, unsatisfied) {
  const {
    peer,
    sources,
    reason,
    hasRuntimeSource,
    installedVersion,
    versionRange
  } = unsatisfied;
  const chainInfo = formatChain(sources);
  if (reason === "version-mismatch") {
    const requiredByList = sources.map((s) => s.requiredBy);
    console.log(
      `[${chalk11.blue(name)}] Peer dependency version mismatch ${chalk11.red(peer)} \u2014 installed ${chalk11.yellow(installedVersion ?? "unknown")} does not satisfy ${chalk11.cyan(versionRange)} (required by ${chalk11.cyan(requiredByList.join(", "))})` + chainInfo
    );
  } else if (reason === "under-exposed") {
    const requiredByList = sources.filter((s) => s.isRuntimeDep).map((s) => s.requiredBy);
    console.log(
      `[${chalk11.blue(name)}] Under-exposed peer dependency ${chalk11.red(peer)} (required by ${chalk11.cyan(requiredByList.join(", "))})` + chainInfo + " \u2014 present in devDependencies but must also be in dependencies or peerDependencies for consumers"
    );
  } else if (hasRuntimeSource) {
    const requiredByList = sources.filter((s) => s.isRuntimeDep).map((s) => s.requiredBy);
    console.log(
      `[${chalk11.blue(name)}] Unsatisfied peer dependency ${chalk11.red(peer)} (required by ${chalk11.cyan(requiredByList.join(", "))})` + chainInfo + " \u2014 must be in dependencies or peerDependencies"
    );
  } else {
    const requiredByList = sources.map((s) => s.requiredBy);
    console.log(
      `[${chalk11.blue(name)}] Unsatisfied peer dependency ${chalk11.red(peer)} (required by devDependency ${chalk11.cyan(requiredByList.join(", "))})` + chainInfo + " \u2014 must be in dependencies, devDependencies, or peerDependencies"
    );
  }
}
function getUnsatisfiedPeerDependencies(workspace, packageParams, exclude) {
  const unsatisfied = findUnsatisfiedPeers(workspace, packageParams, exclude);
  for (const entry of unsatisfied) {
    logUnsatisfiedPeer(workspace.name, entry);
  }
  if (unsatisfied.length > 0) {
    console.log(`  ${chalk11.yellow(`${workspace.location}/package.json`)}
`);
  }
  return {
    count: unsatisfied.length,
    unsatisfiedPeers: new Set(unsatisfied.map((u) => u.peer))
  };
}
function fixVersionMismatch(workspaceName, entry, pkg) {
  const {
    installedVersion,
    peer,
    versionRange
  } = entry;
  if (!installedVersion) {
    logUnsatisfiedPeer(workspaceName, entry);
    console.log(`  ${chalk11.dim("(version mismatch \u2014 could not resolve installed version)")}`);
    return false;
  }
  const match = /^(\d+)\.(\d+)/.exec(installedVersion);
  if (!match) {
    logUnsatisfiedPeer(workspaceName, entry);
    console.log(`  ${chalk11.dim("(version mismatch \u2014 could not resolve installed version)")}`);
    return false;
  }
  const expectedVersion = versionRange.startsWith("^") ? `^${match[1]}` : `~${match[1]}.${match[2]}`;
  if (pkg.peerDependencies?.[peer] && !pkg.peerDependencies[peer].startsWith("workspace:")) {
    pkg.peerDependencies[peer] = expectedVersion;
  }
  if (pkg.devDependencies?.[peer] && !pkg.devDependencies[peer].startsWith("workspace:")) {
    pkg.devDependencies[peer] = expectedVersion;
  }
  console.log(
    `[${chalk11.blue(workspaceName)}] Fixed: updated ${chalk11.green(peer)} version to ${chalk11.cyan(expectedVersion)} (was ${chalk11.yellow(versionRange)})`
  );
  return true;
}
function fixUnsatisfiedPeerDependencies(workspace, packageParams, exclude, isTerminal) {
  const isTerminalResolved = isTerminal ?? isTerminalPackage(workspace.location);
  const unsatisfied = findUnsatisfiedPeers(workspace, packageParams, exclude, isTerminalResolved);
  if (unsatisfied.length === 0) return { addedPeers: /* @__PURE__ */ new Set(), count: 0 };
  const packageJsonPath = `${workspace.location}/package.json`;
  const pkg = JSON.parse(fs14.readFileSync(packageJsonPath, "utf8"));
  const addedPeers = /* @__PURE__ */ new Set();
  let fixedCount = 0;
  for (const entry of unsatisfied) {
    const {
      hasRuntimeSource,
      peer,
      reason,
      sources,
      versionRange
    } = entry;
    if (reason === "version-mismatch") {
      if (fixVersionMismatch(workspace.name, entry, pkg)) fixedCount++;
      continue;
    }
    const sections = reason === "under-exposed" ? ["peerDependencies"] : resolvePeerTargetSections(hasRuntimeSource, isTerminalResolved);
    for (const section of sections) {
      pkg[section] = pkg[section] ?? {};
      pkg[section][peer] = versionRange;
    }
    addedPeers.add(peer);
    const requiredByList = sources.map((s) => s.requiredBy).join(", ");
    console.log(
      `[${chalk11.blue(workspace.name)}] Fixed: added ${chalk11.green(peer)}@${versionRange} to ${chalk11.cyan(sections.join(" + "))} (required by ${requiredByList})`
    );
    fixedCount++;
  }
  if (fixedCount > 0) {
    const sorted = sortPackageJson2(JSON.stringify(pkg, null, 2));
    fs14.writeFileSync(packageJsonPath, `${sorted}
`);
  }
  return { addedPeers, count: unsatisfied.length };
}

// src/actions/deplint/checkPackage/checkPackage.ts
function logVerbose(name, location, allFiles, distFiles, tsconfigExtends) {
  console.info(`Checking package: ${name} at ${location}`);
  console.info(`All files: ${allFiles.length}, Distribution files: ${distFiles.length}`);
  for (const file of allFiles) {
    console.info(`File: ${file}`);
  }
  for (const file of distFiles) {
    console.info(`Distribution file: ${file}`);
  }
  for (const ext of tsconfigExtends) {
    console.info(`Tsconfig extends: ${ext}`);
  }
}
function resolveCheckFlags(deps, devDeps, peerDeps) {
  const noneExplicit = !(deps || devDeps || peerDeps);
  return {
    checkDeps: deps || noneExplicit,
    checkDevDeps: devDeps || noneExplicit,
    checkPeerDeps: peerDeps || noneExplicit
  };
}
function checkPackage({
  name,
  location,
  deps = false,
  devDeps = false,
  exclude,
  fix = false,
  peerDeps = false,
  verbose = false,
  workspaceNames
}) {
  const { allFiles, distFiles } = findFiles(location);
  const tsconfigExtends = getExtendsFromTsconfigs(location);
  if (verbose) {
    logVerbose(name, location, allFiles, distFiles, tsconfigExtends);
  }
  const {
    checkDeps,
    checkDevDeps,
    checkPeerDeps
  } = resolveCheckFlags(deps, devDeps, peerDeps);
  const sourceParams = getExternalImportsFromFiles({
    allFiles,
    distFiles,
    location,
    name,
    tsconfigExtends
  });
  const packageJsonPath = `${location}/package.json`;
  const packageParams = getDependenciesFromPackageJson(packageJsonPath);
  const workspace = { name, location };
  const fileContext = { allFiles, distFiles };
  if (fix) {
    return fixPackage(workspace, packageParams, sourceParams, fileContext, checkDeps, checkDevDeps, checkPeerDeps, exclude, packageJsonPath, workspaceNames);
  }
  return checkPackageProblems(workspace, packageParams, sourceParams, fileContext, checkDeps, checkDevDeps, checkPeerDeps, exclude, workspaceNames);
}
function checkPackageProblems(workspace, packageParams, sourceParams, fileContext, checkDeps, checkDevDeps, checkPeerDeps, exclude, workspaceNames) {
  const allRequiredPeers = checkDeps || checkDevDeps ? getRequiredTransitivePeers(workspace.location, packageParams) : /* @__PURE__ */ new Set();
  const peerExclude = /* @__PURE__ */ new Set([...exclude ?? [], ...allRequiredPeers]);
  const { count: unsatisfiedPeerDependencies } = checkDeps || checkDevDeps ? getUnsatisfiedPeerDependencies(workspace, packageParams, exclude) : { count: 0 };
  const unlistedDependencies = checkDeps ? getUnlistedDependencies(workspace, packageParams, sourceParams) : 0;
  const unusedDependencies = checkDeps ? getUnusedDependencies(workspace, packageParams, sourceParams, peerExclude) : 0;
  const unlistedDevDependencies = checkDevDeps ? getUnlistedDevDependencies(workspace, packageParams, sourceParams) : 0;
  const unusedDevDependencies = checkDevDeps ? getUnusedDevDependencies(workspace, packageParams, sourceParams, fileContext, peerExclude) : 0;
  const unusedPeerDependencies = checkPeerDeps ? getUnusedPeerDependencies(workspace, packageParams, sourceParams, exclude) : 0;
  const unrequestedPeerDependencies = checkPeerDeps ? getUnrequestedPeerDependencies(workspace, packageParams, sourceParams, exclude) : 0;
  const redundantPeerDependencies = checkPeerDeps ? getRedundantPeerDependencies(workspace, packageParams, exclude) : 0;
  const mismatchedPeerDevVersions = checkPeerDeps ? getMismatchedPeerDevVersions(workspace, packageParams, exclude) : 0;
  const workspaceVersionProblems = workspaceNames ? getWorkspaceVersionProblems(workspace, packageParams, workspaceNames) : 0;
  return unlistedDependencies + unlistedDevDependencies + unusedDependencies + unusedDevDependencies + unusedPeerDependencies + unrequestedPeerDependencies + redundantPeerDependencies + unsatisfiedPeerDependencies + mismatchedPeerDevVersions + workspaceVersionProblems;
}
function fixPhase1AddMissing(ctx, packageParams) {
  let total = 0;
  total += ctx.checkDeps ? fixUnlistedDependencies(ctx.workspace, packageParams, ctx.sourceParams, ctx.workspaceNames) : 0;
  const afterDepsParams = total > 0 ? getDependenciesFromPackageJson(ctx.packageJsonPath) : packageParams;
  total += ctx.checkDevDeps ? fixUnlistedDevDependencies(ctx.workspace, afterDepsParams, ctx.sourceParams) : 0;
  const beforePeersParams = total > 0 ? getDependenciesFromPackageJson(ctx.packageJsonPath) : afterDepsParams;
  const peerResult = ctx.checkDeps || ctx.checkDevDeps ? fixUnsatisfiedPeerDependencies(ctx.workspace, beforePeersParams, ctx.exclude) : { addedPeers: /* @__PURE__ */ new Set(), count: 0 };
  total += peerResult.count;
  return { addedPeers: peerResult.addedPeers, total };
}
function fixPhase2RemoveUnused(ctx, addedPeers, prevTotal) {
  let total = 0;
  const updatedParams = getDependenciesFromPackageJson(ctx.packageJsonPath);
  const allRequiredPeers = ctx.checkDeps || ctx.checkDevDeps ? getRequiredTransitivePeers(ctx.workspace.location, updatedParams) : /* @__PURE__ */ new Set();
  const peerExclude = /* @__PURE__ */ new Set([...ctx.exclude ?? [], ...addedPeers, ...allRequiredPeers]);
  total += ctx.checkPeerDeps ? fixUnrequestedPeerDependencies(ctx.workspace, updatedParams, ctx.sourceParams, ctx.exclude) : 0;
  const afterMoveParams = ctx.checkPeerDeps && total + prevTotal > 0 ? getDependenciesFromPackageJson(ctx.packageJsonPath) : updatedParams;
  total += ctx.checkDeps ? fixUnusedDependencies(ctx.workspace, afterMoveParams, ctx.sourceParams, peerExclude) : 0;
  total += ctx.checkDevDeps ? fixUnusedDevDependencies(ctx.workspace, afterMoveParams, ctx.sourceParams, ctx.fileContext, peerExclude) : 0;
  total += ctx.checkPeerDeps ? fixUnusedPeerDependencies(ctx.workspace, afterMoveParams, ctx.sourceParams, ctx.exclude) : 0;
  total += ctx.checkPeerDeps ? fixRedundantPeerDependencies(ctx.workspace, afterMoveParams, ctx.exclude) : 0;
  return total;
}
function fixPhase3SyncVersions(ctx) {
  let total = 0;
  const finalParams = getDependenciesFromPackageJson(ctx.packageJsonPath);
  if (ctx.checkPeerDeps) {
    total += fixMismatchedPeerDevVersions(ctx.workspace, finalParams, ctx.exclude);
  }
  if (ctx.workspaceNames) {
    total += fixWorkspaceVersionProblems(ctx.workspace, finalParams, ctx.workspaceNames);
  }
  return total;
}
function fixPackage(workspace, packageParams, sourceParams, fileContext, checkDeps, checkDevDeps, checkPeerDeps, exclude, packageJsonPath, workspaceNames) {
  const ctx = {
    checkDeps,
    checkDevDeps,
    checkPeerDeps,
    exclude,
    fileContext,
    packageJsonPath,
    sourceParams,
    workspace,
    workspaceNames
  };
  const { addedPeers, total: phase1Total } = fixPhase1AddMissing(ctx, packageParams);
  const phase2Total = fixPhase2RemoveUnused(ctx, addedPeers, phase1Total);
  const phase3Total = fixPhase3SyncVersions(ctx);
  return phase1Total + phase2Total + phase3Total;
}
export {
  checkPackage,
  findMismatchedPeerDevVersions,
  findRedundantPeerDeps,
  findUnlistedDependencies,
  findUnlistedDevDeps,
  findUnrequestedPeerDeps,
  findUnsatisfiedPeers,
  findUnusedDependencies,
  findUnusedDevDeps,
  findUnusedPeerDeps,
  findWorkspacePeerVersionProblems,
  findWorkspaceVersionProblems,
  fixMismatchedPeerDevVersions,
  fixRedundantPeerDependencies,
  fixUnlistedDependencies,
  fixUnlistedDevDependencies,
  fixUnrequestedPeerDependencies,
  fixUnsatisfiedPeerDependencies,
  fixUnusedDependencies,
  fixUnusedDevDependencies,
  fixUnusedPeerDependencies,
  fixWorkspaceVersionProblems,
  getMismatchedPeerDevVersions,
  getRedundantPeerDependencies,
  getRequiredNonOptionalTransitivePeers,
  getRequiredTransitivePeers,
  getRuntimeRootedNonOptionalTransitivePeers,
  getUnlistedDependencies,
  getUnlistedDevDependencies,
  getUnrequestedPeerDependencies,
  getUnsatisfiedPeerDependencies,
  getUnusedDependencies,
  getUnusedDevDependencies,
  getUnusedPeerDependencies,
  getWorkspaceVersionProblems,
  isPeerOptionalInAll,
  resolvePeerTargetSections,
  shouldBePeerDependency
};
//# sourceMappingURL=index.mjs.map
