// 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(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 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 parseTypesField(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];
}
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 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 path6 of allFiles) {
    getImportsFromFile(path6, srcImportPaths, srcTypeImportPaths);
    getStorybookConfigImports(path6, 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 path6 of distCodeFiles) getImportsFromFile(path6, distImportPaths, distImportPaths);
    for (const path6 of distTypeFiles) getImportsFromFile(path6, 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/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;
  }
}

// src/actions/deplint/isTerminalPackage.ts
import fs8 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(
      fs8.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);
  }
}

// src/actions/deplint/checkPackage/getUnsatisfiedPeerDependencies.ts
import fs9 from "node:fs";
import semver from "semver";
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 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 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;
}

// src/actions/deplint/snapshot.ts
function buildUnusedDependencyExclude(options, requiredTransitivePeers) {
  return /* @__PURE__ */ new Set([
    ...options.exclude ?? [],
    ...requiredTransitivePeers,
    ...options.forceDeps ?? [],
    ...options.forceDevs ?? [],
    ...options.forcePeers ?? [],
    ...options.forcePeerOptional?.keys() ?? []
  ]);
}
function buildUnusedPeerDependencyExclude(options, runtimeRootedRequired) {
  return /* @__PURE__ */ new Set([
    ...options.exclude ?? [],
    ...runtimeRootedRequired,
    ...options.forceDeps ?? [],
    ...options.forcePeers ?? [],
    ...options.forcePeerOptional?.keys() ?? []
  ]);
}
function buildWorkspaceContext(workspace, options = {}) {
  const { sourceExclude, terminalOverride } = options;
  const {
    allFiles,
    distFiles,
    runtimeRoots
  } = findFiles(workspace.location, sourceExclude);
  const tsconfigExtends = getExtendsFromTsconfigs(workspace.location);
  const tsconfigTypes = getTypesFromTsconfigs(workspace.location);
  const sourceParams = getExternalImportsFromFiles({
    allFiles,
    distFiles,
    hasRuntimeRoots: runtimeRoots.length > 0,
    location: workspace.location,
    name: workspace.name,
    tsconfigExtends,
    tsconfigTypes
  });
  const packageJsonPath = `${workspace.location}/package.json`;
  const packageParams = getDependenciesFromPackageJson(packageJsonPath);
  const requiredTransitivePeers = getRequiredNonOptionalTransitivePeers(workspace.location, packageParams);
  const runtimeRootedRequired = getRuntimeRootedNonOptionalTransitivePeers(workspace.location, packageParams);
  const packageClassification = classifyDeplintPackage(workspace.location, terminalOverride);
  return {
    exclude: options.exclude,
    fileContext: {
      allFiles,
      distFiles,
      runtimeRoots
    },
    forceDeps: options.forceDeps ?? /* @__PURE__ */ new Set(),
    forceDevs: options.forceDevs ?? /* @__PURE__ */ new Set(),
    forcePeerOptional: options.forcePeerOptional ?? /* @__PURE__ */ new Map(),
    forcePeers: options.forcePeers ?? /* @__PURE__ */ new Set(),
    isTerminalPackage: packageClassification.isTerminalPackage,
    packageKind: packageClassification.kind,
    packageJsonPath,
    packageParams,
    peerRangeBound: options.peerRangeBound,
    peerRangeForm: options.peerRangeForm ?? "shorthand",
    sourceParams,
    sourceExclude: sourceExclude ?? [],
    unusedDependencyExclude: buildUnusedDependencyExclude(options, requiredTransitivePeers),
    unusedPeerDependencyExclude: buildUnusedPeerDependencyExclude(options, runtimeRootedRequired),
    workspace,
    workspaceNames: options.workspaceNames
  };
}
export {
  buildWorkspaceContext
};
//# sourceMappingURL=snapshot.mjs.map
