// src/actions/dead/analyzePackage.ts
import path4 from "node:path";

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

// src/lib/match.ts
import { minimatch } from "minimatch";
function makeMatcher(pattern, options = {}) {
  const patterns = Array.isArray(pattern) ? pattern : [pattern];
  return (input) => patterns.some((p) => minimatch(input, p, options));
}

// src/pm/workspaces.ts
import { existsSync, readFileSync } from "node:fs";
import PATH from "node:path";
import { globSync } from "glob";
function readJsonFile(path5) {
  if (!existsSync(path5)) return void 0;
  try {
    return JSON.parse(readFileSync(path5, "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 isInPackages = false;
  for (const line of content.split("\n")) {
    if (/^packages\s*:/.test(line.trim())) {
      isInPackages = true;
      continue;
    }
    if (isInPackages) {
      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 != null && pattern.length > 0)) continue;
    patterns.add(pattern);
    if (!pattern.endsWith("/**")) patterns.add(`${pattern}/**`);
  }
  return [...patterns];
}
function createSourceFileFilter(location, sourceIgnorePatterns) {
  if (sourceIgnorePatterns.length === 0) return () => true;
  const isIgnored = makeMatcher(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 === void 0) return [];
  return typeof bin === "string" ? [bin] : Object.values(bin).filter((entry) => typeof entry === "string");
}
function canResolveToCode(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 != null && resolved.length > 0 ? [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 != null && file.length > 0) || 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 != null && resolved.length > 0 && shouldIncludeFile(resolved) && !seen.has(resolved)) queue.push(resolved);
    }
  }
  return result;
}
var launcherNodeTargetRe = /\bnode(?:\.exe)?\b[^\n]*?["']?([^"'\s]+\.(?:mjs|cjs|js))(?=["'\s]|$)/i;
var launcherDirVarRe = /^(?:\$\{?\w+\}?|%\w+%|%~dp0)\/?/;
var MAX_LAUNCHER_BYTES = 64 * 1024;
function resolveLauncherTarget(launcherAbs) {
  try {
    const stat = fs.statSync(launcherAbs);
    if (!stat.isFile() || stat.size > MAX_LAUNCHER_BYTES) return void 0;
    const match = launcherNodeTargetRe.exec(fs.readFileSync(launcherAbs, "utf8"));
    if (!match) return void 0;
    const target = match[1].replaceAll("\\", "/").replace(launcherDirVarRe, "");
    return resolveCodeFile(path.resolve(path.dirname(launcherAbs), target));
  } catch {
    return void 0;
  }
}
function getBinFiles(location, pkg) {
  const bin = pkg?.bin;
  if (bin === void 0) 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)) {
      if (fs.existsSync(abs)) results.push(abs);
      continue;
    }
    if (!fs.existsSync(abs)) continue;
    const launcherTarget = resolveLauncherTarget(abs);
    if (launcherTarget != null && launcherTarget.length > 0) results.push(launcherTarget);
  }
  return results;
}
function appendUniqueFiles(list, seen, result) {
  for (const file of list) {
    if (seen.has(file)) continue;
    seen.add(file);
    result.push(file);
  }
}
function uniqueFiles(...lists) {
  const seen = /* @__PURE__ */ new Set();
  const result = [];
  for (const list of lists) {
    appendUniqueFiles(list, seen, result);
  }
  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(canResolveToCode))];
  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/dead/classifyPackageVisibility.ts
function isScopedPackageName(name) {
  return typeof name === "string" && name.startsWith("@");
}
function classifyPackageVisibility(manifest) {
  if (manifest?.private === true) return "private";
  const access = manifest?.publishConfig;
  if (typeof access === "object" && access !== null && !Array.isArray(access)) {
    const publishAccess = access.access;
    if (publishAccess === "restricted") return "restricted";
    if (publishAccess === "public") return "public";
  }
  if (isScopedPackageName(manifest?.name)) return "restricted";
  return "public";
}

// src/actions/dead/collectSymbols.ts
import fs2 from "node:fs";
import path2 from "node:path";
import ts3 from "typescript";

// src/actions/dead/deprecation.ts
import ts2 from "typescript";
function getLeadingRanges(sourceFile, node) {
  const ranges = [
    ...ts2.getLeadingCommentRanges(sourceFile.text, node.pos) ?? [],
    ...ts2.getLeadingCommentRanges(sourceFile.text, node.getFullStart()) ?? []
  ];
  const seen = /* @__PURE__ */ new Set();
  return ranges.filter((range) => {
    if (seen.has(range.pos)) return false;
    seen.add(range.pos);
    return true;
  });
}
function hasDeprecatedTag(sourceFile, node) {
  for (const range of getLeadingRanges(sourceFile, node)) {
    const text = sourceFile.text.slice(range.pos, range.pos + range.end - range.pos);
    if (/@deprecated\b/.test(text)) return true;
  }
  const jsDocs = ts2.getJSDocCommentsAndTags(node);
  return jsDocs.some((doc) => {
    if (!ts2.isJSDoc(doc)) return false;
    return doc.tags?.some((tag) => tag.tagName.text === "deprecated") === true;
  });
}

// src/actions/dead/collectSymbols.ts
function getLineCol(sourceFile, pos) {
  const lc = sourceFile.getLineAndCharacterOfPosition(pos);
  return { column: lc.character + 1, line: lc.line + 1 };
}
function hasExportModifier(node) {
  if (!ts3.canHaveModifiers(node)) return false;
  const mods = ts3.getModifiers(node);
  if (!mods) return false;
  return mods.some((m) => m.kind === ts3.SyntaxKind.ExportKeyword);
}
function hasDefaultModifier(node) {
  if (!ts3.canHaveModifiers(node)) return false;
  const mods = ts3.getModifiers(node);
  if (!mods) return false;
  return mods.some((m) => m.kind === ts3.SyntaxKind.DefaultKeyword);
}
function pushDeclaration(declarations, sourceFile, name, nameNode, isExported, exportedAs, declarationNode) {
  const { line, column } = getLineCol(sourceFile, nameNode.getStart(sourceFile));
  const deprecated = hasDeprecatedTag(sourceFile, declarationNode) ? true : void 0;
  declarations.push({
    column,
    deprecated,
    isExported,
    exportedAs,
    line,
    name
  });
}
function isFunctionOverloadSignature(node) {
  return node.body === void 0;
}
function isGlobalAugmentation(node) {
  return ts3.isIdentifier(node.name) && node.name.text === "global";
}
function tryNamedDeclaration(node) {
  if (ts3.isFunctionDeclaration(node) && node.name) {
    if (isFunctionOverloadSignature(node)) return void 0;
    return { name: node.name };
  }
  if (ts3.isClassDeclaration(node) && node.name) return { name: node.name };
  if (ts3.isInterfaceDeclaration(node)) return { name: node.name };
  if (ts3.isTypeAliasDeclaration(node)) return { name: node.name };
  if (ts3.isEnumDeclaration(node)) return { name: node.name };
  if (ts3.isModuleDeclaration(node) && ts3.isIdentifier(node.name)) {
    if (isGlobalAugmentation(node)) return void 0;
    return { name: node.name };
  }
  return void 0;
}
function collectBindingNames(node, push) {
  if (ts3.isIdentifier(node)) {
    push(node.text);
    return;
  }
  if (ts3.isObjectBindingPattern(node) || ts3.isArrayBindingPattern(node)) {
    for (const el of node.elements) {
      if (ts3.isBindingElement(el)) collectBindingNames(el.name, push);
    }
  }
}
function handleVariableStatement(node, declarations, sourceFile) {
  const isExported = hasExportModifier(node);
  for (const decl of node.declarationList.declarations) {
    collectBindingNames(decl.name, (name) => {
      pushDeclaration(declarations, sourceFile, name, decl.name, isExported, name, node);
    });
  }
}
function handleExportAssignment(node, declarations, sourceFile) {
  if (ts3.isIdentifier(node.expression)) {
    const name = node.expression.text;
    const existing = declarations.find((d) => d.name === name);
    if (existing) {
      existing.isExported = true;
      existing.exportedAs = "default";
    }
  }
  return getLineCol(sourceFile, node.getStart(sourceFile));
}
function handleNamedExportClauseWithModule(clause, moduleSpec, reExportsFromRelative) {
  for (const element of clause.elements) {
    const exportedName = element.name.text;
    const importedName = element.propertyName?.text ?? exportedName;
    reExportsFromRelative.push({
      exportedAs: exportedName,
      imported: importedName,
      specifier: moduleSpec
    });
  }
}
function markExportedDeclarations(declarations, importedName, exportedName) {
  for (const existing of declarations) {
    if (existing.name !== importedName) continue;
    existing.isExported = true;
    existing.exportedAs = exportedName;
  }
}
function handleNamedExportClauseLocal(clause, declarations) {
  for (const element of clause.elements) {
    const exportedName = element.name.text;
    const importedName = element.propertyName?.text ?? exportedName;
    markExportedDeclarations(declarations, importedName, exportedName);
  }
}
function handleExportDeclaration(node, declarations, reExportsFromRelative, reExportAllFromRelative) {
  const moduleSpec = node.moduleSpecifier && ts3.isStringLiteral(node.moduleSpecifier) ? node.moduleSpecifier.text : void 0;
  const isRelative = moduleSpec?.startsWith(".") ?? false;
  if (node.exportClause && ts3.isNamedExports(node.exportClause)) {
    if (moduleSpec != null && moduleSpec.length > 0 && isRelative) {
      handleNamedExportClauseWithModule(node.exportClause, moduleSpec, reExportsFromRelative);
    } else if (!(moduleSpec != null && moduleSpec.length > 0)) {
      handleNamedExportClauseLocal(node.exportClause, declarations);
    }
    return;
  }
  if (!node.exportClause && (moduleSpec != null && moduleSpec.length > 0) && isRelative) {
    reExportAllFromRelative.add(moduleSpec);
  }
}
function visitTopLevel(node, ctx) {
  const named = tryNamedDeclaration(node);
  if (named?.name) {
    pushDeclaration(
      ctx.declarations,
      ctx.sourceFile,
      named.name.text,
      named.name,
      hasExportModifier(node),
      hasDefaultModifier(node) ? "default" : named.name.text,
      node
    );
    return;
  }
  if (ts3.isVariableStatement(node)) {
    handleVariableStatement(node, ctx.declarations, ctx.sourceFile);
    return;
  }
  if (ts3.isExportAssignment(node)) {
    ctx.setDefaultExport(handleExportAssignment(node, ctx.declarations, ctx.sourceFile));
    return;
  }
  if (ts3.isExportDeclaration(node)) {
    handleExportDeclaration(node, ctx.declarations, ctx.reExportsFromRelative, ctx.reExportAllFromRelative);
  }
}
function handleNamedImports(spec, clause, ctx) {
  for (const element of clause.elements) {
    const importedName = element.propertyName?.text ?? element.name.text;
    const alias = element.name.text;
    ctx.importBindingNames.add(alias);
    ctx.namedImportsFromRelative.push({
      alias,
      imported: importedName,
      specifier: spec
    });
  }
}
function visitImports(node, ctx) {
  if (!ts3.isImportDeclaration(node)) return;
  if (!ts3.isStringLiteral(node.moduleSpecifier)) return;
  const spec = node.moduleSpecifier.text;
  if (!spec.startsWith(".")) return;
  const clause = node.importClause;
  if (!clause) {
    ctx.sideEffectFromRelative.add(spec);
    return;
  }
  if (clause.name) {
    const alias = clause.name.text;
    ctx.importBindingNames.add(alias);
    ctx.namedImportsFromRelative.push({
      alias,
      imported: "default",
      specifier: spec
    });
  }
  if (clause.namedBindings) {
    if (ts3.isNamespaceImport(clause.namedBindings)) {
      ctx.importBindingNames.add(clause.namedBindings.name.text);
      ctx.namespaceImportFromRelative.add(spec);
    } else if (ts3.isNamedImports(clause.namedBindings)) {
      handleNamedImports(spec, clause.namedBindings, ctx);
    }
  }
}
function isTopLevelDeclarationName(node, parent) {
  if (ts3.isFunctionDeclaration(parent) && parent.name === node) return true;
  if (ts3.isClassDeclaration(parent) && parent.name === node) return true;
  if (ts3.isInterfaceDeclaration(parent) && parent.name === node) return true;
  if (ts3.isTypeAliasDeclaration(parent) && parent.name === node) return true;
  if (ts3.isEnumDeclaration(parent) && parent.name === node) return true;
  if (ts3.isModuleDeclaration(parent) && parent.name === node) return true;
  return false;
}
function isLocalBindingName(node, parent) {
  if (ts3.isVariableDeclaration(parent) && parent.name === node) return true;
  if (ts3.isParameter(parent) && parent.name === node) return true;
  if (ts3.isBindingElement(parent) && parent.name === node) return true;
  return false;
}
function isMemberName(node, parent) {
  if (ts3.isPropertyAssignment(parent) && parent.name === node) return true;
  if (ts3.isPropertyDeclaration(parent) && parent.name === node) return true;
  if (ts3.isMethodDeclaration(parent) && parent.name === node) return true;
  if (ts3.isPropertySignature(parent) && parent.name === node) return true;
  if (ts3.isMethodSignature(parent) && parent.name === node) return true;
  return false;
}
function isImportExportBindingName(node, parent) {
  if (ts3.isImportSpecifier(parent) && (parent.name === node || parent.propertyName === node)) return true;
  if (ts3.isImportClause(parent) && parent.name === node) return true;
  if (ts3.isNamespaceImport(parent) && parent.name === node) return true;
  if (ts3.isExportSpecifier(parent) && (parent.name === node || parent.propertyName === node)) return true;
  return false;
}
function isQualifiedMemberAccess(node, parent) {
  if (ts3.isQualifiedName(parent) && parent.right === node) return true;
  if (ts3.isPropertyAccessExpression(parent) && parent.name === node) return true;
  return false;
}
function isDeclarationOrBindingPosition(node, parent) {
  return isTopLevelDeclarationName(node, parent) || isLocalBindingName(node, parent) || isMemberName(node, parent) || isImportExportBindingName(node, parent) || isQualifiedMemberAccess(node, parent);
}
function visitForReferences(node, identifierRefs) {
  if (ts3.isIdentifier(node)) {
    const parent = node.parent;
    if (!isDeclarationOrBindingPosition(node, parent)) {
      identifierRefs.add(node.text);
    }
  }
  ts3.forEachChild(node, (child) => visitForReferences(child, identifierRefs));
}
function collectSymbolsFromFile(filePath) {
  const sourceText = fs2.readFileSync(filePath, "utf8");
  const isJsLike = /\.(?:js|mjs|cjs)$/i.test(filePath);
  const sourceFile = ts3.createSourceFile(
    path2.basename(filePath),
    sourceText,
    ts3.ScriptTarget.Latest,
    true,
    isJsLike ? ts3.ScriptKind.JS : void 0
  );
  const declarations = [];
  const identifierRefs = /* @__PURE__ */ new Set();
  const namedImportsFromRelative = [];
  const namespaceImportFromRelative = /* @__PURE__ */ new Set();
  const sideEffectFromRelative = /* @__PURE__ */ new Set();
  const reExportsFromRelative = [];
  const reExportAllFromRelative = /* @__PURE__ */ new Set();
  let defaultExport;
  const importBindingNames = /* @__PURE__ */ new Set();
  const topCtx = {
    declarations,
    reExportAllFromRelative,
    reExportsFromRelative,
    setDefaultExport: (pos) => {
      defaultExport = pos;
    },
    sourceFile
  };
  const importCtx = {
    importBindingNames,
    namedImportsFromRelative,
    namespaceImportFromRelative,
    sideEffectFromRelative
  };
  for (const stmt of sourceFile.statements) {
    visitTopLevel(stmt, topCtx);
    visitImports(stmt, importCtx);
  }
  visitForReferences(sourceFile, identifierRefs);
  return {
    declarations,
    defaultExport,
    identifierRefs,
    namedImportsFromRelative,
    namespaceImportFromRelative,
    reExportAllFromRelative,
    reExportsFromRelative,
    sideEffectFromRelative
  };
}

// src/actions/dead/runtimeEntries.ts
import fs3 from "node:fs";
import path3 from "node:path";
var codeExtensionRe2 = /\.(?:ts|tsx|mts|cts|js|mjs|cjs)$/i;
var resolutionExtensions2 = [".mjs", ".cjs", ".js", ".d.mts", ".d.cts", ".d.ts", ".mts", ".cts", ".ts", ".tsx"];
function readPackageManifest(location) {
  try {
    return JSON.parse(fs3.readFileSync(path3.join(location, "package.json"), "utf8"));
  } catch {
    return void 0;
  }
}
function collectExportTargets2(value) {
  if (typeof value === "string") return value.startsWith("./") ? [value] : [];
  if (Array.isArray(value)) return value.flatMap(collectExportTargets2);
  if (typeof value !== "object" || value === null) return [];
  return Object.values(value).flatMap(collectExportTargets2);
}
function resolveCodeFile2(filePath) {
  if (fs3.existsSync(filePath) && codeExtensionRe2.test(filePath)) return filePath;
  const ext = path3.extname(filePath);
  if (ext) {
    const withoutExt = filePath.slice(0, -ext.length);
    for (const candidateExt of resolutionExtensions2) {
      const candidate = `${withoutExt}${candidateExt}`;
      if (fs3.existsSync(candidate)) return candidate;
    }
  }
  for (const candidateExt of resolutionExtensions2) {
    const candidate = `${filePath}${candidateExt}`;
    if (fs3.existsSync(candidate)) return candidate;
  }
  for (const candidateExt of resolutionExtensions2) {
    const candidate = path3.join(filePath, `index${candidateExt}`);
    if (fs3.existsSync(candidate)) return candidate;
  }
  return void 0;
}
function resolveManifestEntry(location, entry) {
  if (path3.isAbsolute(entry)) return void 0;
  if (entry.includes("*")) return void 0;
  const relativeEntry = entry.startsWith(".") ? entry : `./${entry}`;
  return resolveCodeFile2(path3.resolve(location, relativeEntry));
}
function getRuntimeRootFiles(location, manifest) {
  if (!manifest) return [];
  const candidates = [
    ...collectExportTargets2(manifest.exports),
    manifest.main,
    manifest.module,
    manifest.types,
    manifest.typings
  ].filter((entry) => typeof entry === "string");
  const bin = manifest.bin;
  if (bin !== void 0) {
    if (typeof bin === "string") candidates.push(bin);
    else for (const value of Object.values(bin)) if (typeof value === "string") candidates.push(value);
  }
  const seen = /* @__PURE__ */ new Set();
  const results = [];
  for (const entry of candidates) {
    const resolved = resolveManifestEntry(location, entry);
    if (!(resolved != null && resolved.length > 0) || seen.has(resolved)) continue;
    const distMapped = mapDistToSrc(location, resolved);
    const final = distMapped ?? resolved;
    if (seen.has(final)) continue;
    seen.add(final);
    results.push(final);
  }
  return results;
}
function mapDistToSrc(location, file) {
  const rel = path3.relative(location, file);
  if (!rel.startsWith("dist" + path3.sep) && !rel.startsWith("dist/")) return void 0;
  const tail = rel.slice("dist".length).replace(/^[\\/]/, "");
  const tailNoExt = tail.replace(/\.(?:mjs|cjs|js|d\.mts|d\.cts|d\.ts)$/i, "");
  const candidates = [
    path3.join(location, "src", tailNoExt),
    path3.join(location, "src", tailNoExt + ".ts"),
    path3.join(location, "src", tailNoExt + ".tsx"),
    path3.join(location, "src", tailNoExt + ".mts"),
    path3.join(location, "src", tailNoExt + ".cts")
  ];
  for (const candidate of candidates) {
    const resolved = resolveCodeFile2(candidate);
    if (resolved != null && resolved.length > 0) return resolved;
  }
  return void 0;
}

// src/actions/deplint/getStorybookConfigImports.ts
import ts4 from "typescript";
var storybookMainPattern = /(?:^|[\\/])\.storybook[\\/]main\.[cm]?[jt]sx?$/;
function isStorybookMainFile(filePath) {
  return storybookMainPattern.test(filePath);
}

// src/actions/dead/storybookConventions.ts
var storyFilePattern = /\.stories\.[cm]?[jt]sx?$/i;
var storybookPreviewPattern = /(?:^|[\\/])\.storybook[\\/]preview\.[cm]?[jt]sx?$/i;
var storybookManagerPattern = /(?:^|[\\/])\.storybook[\\/]manager\.[cm]?[jt]sx?$/i;
function isStorybookConventionFile(filePath) {
  return storyFilePattern.test(filePath) || storybookPreviewPattern.test(filePath) || storybookManagerPattern.test(filePath) || isStorybookMainFile(filePath);
}

// src/actions/dead/analyzePackage.ts
function isAnalyzableFile(file) {
  if (!codeExtensionRe2.test(file)) return false;
  if (file.endsWith(".d.ts") || file.endsWith(".d.mts") || file.endsWith(".d.cts")) return false;
  return true;
}
function resolveRelativeImport(fromFile, specifier) {
  return resolveCodeFile2(path4.resolve(path4.dirname(fromFile), specifier));
}
function loadReports(files) {
  const reports = [];
  for (const file of files) {
    if (!isAnalyzableFile(file)) continue;
    const symbols = collectSymbolsFromFile(file);
    const resolvedRelative = /* @__PURE__ */ new Map();
    const specifiers = /* @__PURE__ */ new Set([
      ...symbols.namedImportsFromRelative.map((i) => i.specifier),
      ...symbols.namespaceImportFromRelative,
      ...symbols.sideEffectFromRelative,
      ...symbols.reExportsFromRelative.map((r) => r.specifier),
      ...symbols.reExportAllFromRelative
    ]);
    for (const spec of specifiers) {
      const resolved = resolveRelativeImport(file, spec);
      if (resolved != null && resolved.length > 0) resolvedRelative.set(spec, resolved);
    }
    reports.push({
      file,
      resolvedRelative,
      symbols
    });
  }
  return reports;
}
function computeCrossFileUsage(reports) {
  const namedSymbolUsage = /* @__PURE__ */ new Map();
  const filesWithFullExportUse = /* @__PURE__ */ new Set();
  function addNamed(targetFile, name) {
    let bucket = namedSymbolUsage.get(targetFile);
    if (!bucket) {
      bucket = /* @__PURE__ */ new Set();
      namedSymbolUsage.set(targetFile, bucket);
    }
    bucket.add(name);
  }
  for (const report of reports) {
    for (const named of report.symbols.namedImportsFromRelative) {
      const target = report.resolvedRelative.get(named.specifier);
      if (target != null && target.length > 0) addNamed(target, named.imported);
    }
    for (const reExport of report.symbols.reExportsFromRelative) {
      const target = report.resolvedRelative.get(reExport.specifier);
      if (target != null && target.length > 0) addNamed(target, reExport.imported);
    }
    for (const spec of report.symbols.namespaceImportFromRelative) {
      const target = report.resolvedRelative.get(spec);
      if (target != null && target.length > 0) filesWithFullExportUse.add(target);
    }
    for (const spec of report.symbols.reExportAllFromRelative) {
      const target = report.resolvedRelative.get(spec);
      if (target != null && target.length > 0) filesWithFullExportUse.add(target);
    }
  }
  return { filesWithFullExportUse, namedSymbolUsage };
}
function addStarDeclarations(file, report, out) {
  for (const decl of report.symbols.declarations) {
    if (!decl.isExported || !(decl.exportedAs != null && decl.exportedAs.length > 0) || decl.exportedAs === "default") continue;
    out.set(decl.exportedAs, {
      column: decl.column,
      file,
      line: decl.line
    });
  }
}
function addNamedStarReExports(file, report, ctx, out) {
  for (const reExport of report.symbols.reExportsFromRelative) {
    if (reExport.exportedAs === "default") continue;
    const target = report.resolvedRelative.get(reExport.specifier);
    const origin = target != null && target.length > 0 ? findOrigin(target, reExport.imported, ctx) : void 0;
    out.set(reExport.exportedAs, origin ?? {
      column: 1,
      file,
      line: 1
    });
  }
}
function addChildStarExports(report, ctx, out) {
  for (const spec of report.symbols.reExportAllFromRelative) {
    const target = report.resolvedRelative.get(spec);
    if (!(target != null && target.length > 0)) continue;
    const child = getStarExports(target, ctx);
    for (const [name, origin] of child) {
      if (!out.has(name)) out.set(name, origin);
    }
  }
}
function getStarExports(file, ctx) {
  const cached = ctx.starExportMemo.get(file);
  if (cached !== void 0) return cached;
  if (ctx.visiting.has(file)) return /* @__PURE__ */ new Map();
  ctx.visiting.add(file);
  const out = /* @__PURE__ */ new Map();
  const report = ctx.byFile.get(file);
  if (report !== void 0) {
    addStarDeclarations(file, report, out);
    addNamedStarReExports(file, report, ctx, out);
    addChildStarExports(report, ctx, out);
  }
  ctx.visiting.delete(file);
  ctx.starExportMemo.set(file, out);
  return out;
}
function findOrigin(targetFile, name, ctx) {
  const stars = getStarExports(targetFile, ctx);
  return stars.get(name);
}
function addDirectDeclarations(report, rootFile, results) {
  for (const decl of report.symbols.declarations) {
    if (!decl.isExported || !(decl.exportedAs != null && decl.exportedAs.length > 0)) continue;
    const name = decl.exportedAs;
    if (results.has(name)) continue;
    results.set(name, {
      column: decl.column,
      file: rootFile,
      line: decl.line,
      name,
      rootFile
    });
  }
}
function addDefaultExport(report, rootFile, results) {
  const def = report.symbols.defaultExport;
  if (!def || results.has("default")) return;
  results.set("default", {
    column: def.column,
    file: rootFile,
    line: def.line,
    name: "default",
    rootFile
  });
}
function addReExports(report, rootFile, ctx, results) {
  for (const reExport of report.symbols.reExportsFromRelative) {
    const exportedAs = reExport.exportedAs;
    if (results.has(exportedAs)) continue;
    const target = report.resolvedRelative.get(reExport.specifier);
    const origin = target != null && target.length > 0 ? findOrigin(target, reExport.imported, ctx) : void 0;
    results.set(exportedAs, {
      column: origin?.column ?? 1,
      file: origin?.file ?? rootFile,
      line: origin?.line ?? 1,
      name: exportedAs,
      rootFile
    });
  }
}
function addReExportAll(report, rootFile, ctx, results) {
  for (const spec of report.symbols.reExportAllFromRelative) {
    const target = report.resolvedRelative.get(spec);
    if (!(target != null && target.length > 0)) continue;
    const stars = getStarExports(target, ctx);
    const pendingStars = [...stars].filter(([name]) => !results.has(name));
    for (const [name, origin] of pendingStars) {
      results.set(name, {
        column: origin.column,
        file: origin.file,
        line: origin.line,
        name,
        rootFile
      });
    }
  }
}
function collectPublicExports(reports, runtimeRoots) {
  const byFile = new Map(reports.map((r) => [r.file, r]));
  const ctx = {
    byFile,
    results: /* @__PURE__ */ new Map(),
    starExportMemo: /* @__PURE__ */ new Map(),
    visiting: /* @__PURE__ */ new Set()
  };
  const results = /* @__PURE__ */ new Map();
  for (const rootFile of runtimeRoots) {
    const report = byFile.get(rootFile);
    if (!report) continue;
    addDirectDeclarations(report, rootFile, results);
    addDefaultExport(report, rootFile, results);
    addReExports(report, rootFile, ctx, results);
    addReExportAll(report, rootFile, ctx, results);
  }
  return results.values().toArray();
}
function buildPublicSurfaceKeys(publicExports) {
  const keys = /* @__PURE__ */ new Set();
  for (const exp of publicExports) {
    keys.add(`${exp.file}\0${exp.name}`);
    keys.add(`${exp.file}\0${exp.line}\0${exp.column}`);
  }
  return keys;
}
function isOnPublicSurface(decl, file, publicSurfaceKeys) {
  const exportedAs = decl.exportedAs ?? decl.name;
  if (publicSurfaceKeys.has(`${file}\0${exportedAs}`)) return true;
  return publicSurfaceKeys.has(`${file}\0${decl.line}\0${decl.column}`);
}
function isUsedInPackage(decl, file, hasFileFullExportUse, namedUsesForFile, report) {
  if (report.symbols.identifierRefs.has(decl.name)) return true;
  if (decl.isExported && isStorybookConventionFile(file)) return true;
  if (!decl.isExported) return false;
  const exportedAs = decl.exportedAs ?? decl.name;
  if (namedUsesForFile.has(exportedAs) || namedUsesForFile.has(decl.name)) return true;
  return hasFileFullExportUse;
}
function buildAnalyzedSymbol(decl, file, hasFileFullExportUse, namedUsesForFile, report, publicSurfaceKeys) {
  const isSymbolUsedInPackage = isUsedInPackage(decl, file, hasFileFullExportUse, namedUsesForFile, report);
  return {
    column: decl.column,
    deprecated: decl.deprecated,
    exportedAs: decl.isExported ? decl.exportedAs ?? decl.name : void 0,
    file,
    line: decl.line,
    name: decl.name,
    onPublicSurface: isOnPublicSurface(decl, file, publicSurfaceKeys),
    usedInMonorepo: isSymbolUsedInPackage,
    isUsedInPackage: isSymbolUsedInPackage
  };
}
function applyMonorepoUsage(analyses, repoUsage) {
  return analyses.map((analysis) => {
    const pkgUsage = repoUsage.get(analysis.packageName);
    if (!pkgUsage) return analysis;
    return {
      ...analysis,
      symbols: analysis.symbols.map((symbol) => {
        if (symbol.usedInMonorepo || symbol.onPublicSurface) return symbol;
        const exportedAs = symbol.exportedAs;
        if (!(exportedAs != null && exportedAs.length > 0)) return symbol;
        const isConsumed = pkgUsage.hasNamespace || exportedAs === "default" && pkgUsage.hasDefault || pkgUsage.named.has(exportedAs);
        return isConsumed ? { ...symbol, usedInMonorepo: true } : symbol;
      })
    };
  });
}
function analyzePackage(workspace) {
  const location = path4.resolve(workspace.location);
  const manifest = readPackageManifest(location);
  const manifestName = manifest && typeof manifest.name === "string" ? manifest.name : void 0;
  const packageName = manifestName ?? workspace.name;
  const { allFiles } = findFiles(location);
  const reports = loadReports(allFiles);
  const runtimeRoots = getRuntimeRootFiles(location, manifest);
  const usage = computeCrossFileUsage(reports);
  const publicExports = collectPublicExports(reports, runtimeRoots);
  const publicSurfaceKeys = buildPublicSurfaceKeys(publicExports);
  const symbols = [];
  for (const report of reports) {
    const isFileHasFullExportUse = usage.filesWithFullExportUse.has(report.file);
    const namedUsesForFile = usage.namedSymbolUsage.get(report.file) ?? /* @__PURE__ */ new Set();
    for (const decl of report.symbols.declarations) {
      symbols.push(buildAnalyzedSymbol(
        decl,
        report.file,
        isFileHasFullExportUse,
        namedUsesForFile,
        report,
        publicSurfaceKeys
      ));
    }
  }
  return {
    location,
    packageName,
    publicExports,
    scannedFiles: reports.length,
    symbols,
    visibility: classifyPackageVisibility(manifest),
    workspaceName: workspace.name
  };
}
export {
  analyzePackage,
  applyMonorepoUsage
};
//# sourceMappingURL=analyzePackage.mjs.map
