// src/actions/dead/runtimeEntries.ts
import fs from "node:fs";
import path from "node:path";
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"];
function readPackageManifest(location) {
  try {
    return JSON.parse(fs.readFileSync(path.join(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 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 candidateExt of resolutionExtensions) {
    const candidate = `${filePath}${candidateExt}`;
    if (fs.existsSync(candidate)) return candidate;
  }
  for (const candidateExt of resolutionExtensions) {
    const candidate = path.join(filePath, `index${candidateExt}`);
    if (fs.existsSync(candidate)) return candidate;
  }
  return void 0;
}
function resolveManifestEntry(location, entry) {
  if (path.isAbsolute(entry)) return void 0;
  if (entry.includes("*")) return void 0;
  const relativeEntry = entry.startsWith(".") ? entry : `./${entry}`;
  return resolveCodeFile(path.resolve(location, relativeEntry));
}
function getRuntimeRootFiles(location, manifest) {
  if (!manifest) return [];
  const candidates = [
    ...collectExportTargets(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 = path.relative(location, file);
  if (!rel.startsWith("dist" + path.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 = [
    path.join(location, "src", tailNoExt),
    path.join(location, "src", tailNoExt + ".ts"),
    path.join(location, "src", tailNoExt + ".tsx"),
    path.join(location, "src", tailNoExt + ".mts"),
    path.join(location, "src", tailNoExt + ".cts")
  ];
  for (const candidate of candidates) {
    const resolved = resolveCodeFile(candidate);
    if (resolved != null && resolved.length > 0) return resolved;
  }
  return void 0;
}

// src/actions/barrel/getReExportSpecs.ts
import fs2 from "node:fs";
import PATH from "node:path";
import ts from "typescript";

// 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("/", 1)[0];
}

// src/actions/barrel/getReExportSpecs.ts
function getReExportSpecs(file) {
  let sourceText;
  try {
    sourceText = fs2.readFileSync(file, "utf8");
  } catch {
    return [];
  }
  const isJsLike = /\.(?:js|mjs|cjs)$/i.test(file);
  const sourceFile = ts.createSourceFile(
    PATH.basename(file),
    sourceText,
    ts.ScriptTarget.Latest,
    true,
    isJsLike ? ts.ScriptKind.JS : void 0
  );
  const specs = /* @__PURE__ */ new Set();
  function visit(node) {
    if (ts.isExportDeclaration(node) && node.moduleSpecifier && ts.isStringLiteral(node.moduleSpecifier)) {
      const spec = node.moduleSpecifier.text;
      if (!spec.startsWith(".") && !spec.startsWith("node:")) {
        specs.add(getBasePackageName(spec));
      }
    }
    ts.forEachChild(node, visit);
  }
  visit(sourceFile);
  return [...specs];
}

// src/actions/barrel/resolveBarrel.ts
import fs3 from "node:fs";
import { createRequire } from "node:module";
import PATH2 from "node:path";
var require2 = createRequire(import.meta.url);
function findPackageRoot(entry, pkg) {
  let dir = PATH2.dirname(entry);
  for (; ; ) {
    const manifestPath = PATH2.join(dir, "package.json");
    if (fs3.existsSync(manifestPath)) {
      try {
        const manifest = JSON.parse(fs3.readFileSync(manifestPath, "utf8"));
        if (manifest.name === pkg) return dir;
      } catch {
      }
    }
    const parent = PATH2.dirname(dir);
    if (parent === dir) return void 0;
    dir = parent;
  }
}
function resolvePackageDir(pkg, fromDir) {
  try {
    return PATH2.dirname(require2.resolve(`${pkg}/package.json`, { paths: [fromDir] }));
  } catch {
  }
  try {
    const entry = require2.resolve(pkg, { paths: [fromDir] });
    return findPackageRoot(entry, pkg);
  } catch {
    return void 0;
  }
}

// src/actions/barrel/analyzeBarrel.ts
function analyzeBarrel(barrelPkg, fromDir, scopePrefix) {
  const collected = /* @__PURE__ */ new Set();
  const visited = /* @__PURE__ */ new Set();
  const queue = [{ fromDir, pkg: barrelPkg }];
  while (queue.length > 0) {
    const current = queue.shift();
    if (!current || visited.has(current.pkg)) continue;
    visited.add(current.pkg);
    const location = resolvePackageDir(current.pkg, current.fromDir);
    if (!(location != null && location.length > 0)) continue;
    const roots = getRuntimeRootFiles(location, readPackageManifest(location));
    const specs = /* @__PURE__ */ new Set();
    for (const root of roots) {
      for (const spec of getReExportSpecs(root)) specs.add(spec);
    }
    const eligibleSpecs = [...specs].filter(
      (spec) => spec !== barrelPkg && (!(scopePrefix != null && scopePrefix.length > 0) || spec.startsWith(scopePrefix))
    );
    for (const spec of eligibleSpecs) {
      collected.add(spec);
      if (!visited.has(spec)) queue.push({ fromDir: location, pkg: spec });
    }
  }
  collected.delete(barrelPkg);
  return [...collected].toSorted((a, b) => a.localeCompare(b));
}
export {
  analyzeBarrel,
  getReExportSpecs,
  resolvePackageDir
};
//# sourceMappingURL=index.mjs.map
