// src/lib/concurrency.ts
import { AsyncLocalStorage } from "node:async_hooks";
var outputStorage = new AsyncLocalStorage();
async function runWithConcurrency(items, concurrency, fn) {
  let next = 0;
  async function worker() {
    while (next < items.length) {
      const i = next++;
      await fn(items[i]);
    }
  }
  await Promise.all(Array.from({ length: Math.min(concurrency, items.length) }, () => worker()));
}

// src/pm/resolveWorkspace.ts
import chalk from "chalk";
function shortName(name) {
  const slash = name.lastIndexOf("/");
  return slash === -1 ? name : name.slice(slash + 1);
}
function resolveWorkspace(workspaces, query) {
  const exact = workspaces.find((ws) => ws.name === query);
  if (exact) return exact;
  const byLocation = workspaces.find((ws) => ws.location === query);
  if (byLocation) return byLocation;
  const byShort = workspaces.filter((ws) => shortName(ws.name) === query);
  if (byShort.length === 1) return byShort[0];
  if (byShort.length > 1) {
    console.error(chalk.red(`Ambiguous workspace "${query}"; matches: ${byShort.map((ws) => ws.name).join(", ")}`));
    return void 0;
  }
  return void 0;
}

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

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

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

// src/lib/initCwd.ts
function INIT_CWD() {
  return process.env.INIT_CWD ?? process.cwd();
}

// src/lib/secure/classify.ts
var DAY_MS = 24 * 60 * 60 * 1e3;
function classifySecureAge(publishedAt, now = /* @__PURE__ */ new Date()) {
  if (!publishedAt || Number.isNaN(publishedAt.getTime())) {
    return { level: "gray" };
  }
  const ageDays = Math.max(0, (now.getTime() - publishedAt.getTime()) / DAY_MS);
  if (ageDays < 3) return { ageDays, level: "red" };
  if (ageDays < 10) return { ageDays, level: "yellow" };
  if (ageDays < 365) return { ageDays, level: "green" };
  return { ageDays, level: "purple" };
}
function classifySecureDownloads(downloads) {
  if (downloads === void 0 || !Number.isFinite(downloads)) return "gray";
  if (downloads < 1e3) return "red";
  if (downloads < 1e4) return "yellow";
  return "green";
}

// src/lib/secure/collectDeclaredDependencies.ts
import { existsSync as existsSync3, readFileSync as readFileSync2 } from "node:fs";
import PATH2 from "node:path";
var DEP_FIELDS = ["dependencies", "devDependencies"];
var LOCAL_PROTOCOLS = ["workspace:", "file:", "link:", "portal:"];
function readPackageJson(filePath) {
  if (!existsSync3(filePath)) return void 0;
  try {
    return JSON.parse(readFileSync2(filePath, "utf8"));
  } catch {
    return void 0;
  }
}
function collectSecurePackageTargets(cwd, workspaces) {
  const targets = [];
  const seenLocations = /* @__PURE__ */ new Set();
  const root = readPackageJson(PATH2.resolve(cwd, "package.json"));
  if (root?.name) {
    targets.push({ location: ".", name: root.name });
    seenLocations.add(".");
  }
  for (const workspace of workspaces) {
    const normalizedLocation = workspace.location || ".";
    if (seenLocations.has(normalizedLocation)) continue;
    targets.push({ location: normalizedLocation, name: workspace.name });
    seenLocations.add(normalizedLocation);
  }
  return targets.toSorted((a, b) => a.location.localeCompare(b.location));
}
function isLocalSecureDependency(name, range, localPackageNames) {
  return localPackageNames.has(name) || LOCAL_PROTOCOLS.some((protocol) => range.startsWith(protocol));
}
function collectSecureDeclaredDependencies(cwd, targets, localPackageNames) {
  const declared = [];
  for (const target of targets) {
    const pkgPath = PATH2.resolve(cwd, target.location, "package.json");
    const pkg = readPackageJson(pkgPath);
    if (!pkg) continue;
    for (const depType of DEP_FIELDS) {
      const deps = pkg[depType];
      if (!deps) continue;
      for (const [name, range] of Object.entries(deps)) {
        if (typeof range !== "string") continue;
        if (isLocalSecureDependency(name, range, localPackageNames)) continue;
        declared.push({
          depType,
          name,
          packageLocation: target.location,
          packageName: target.name,
          range
        });
      }
    }
  }
  return declared.toSorted((a, b) => {
    return a.name.localeCompare(b.name) || a.packageLocation.localeCompare(b.packageLocation) || a.depType.localeCompare(b.depType);
  });
}

// src/lib/secure/fetchPackageSecurityMetadata.ts
var REGISTRY_BASE = "https://registry.npmjs.org";
var DOWNLOADS_BASE = "https://api.npmjs.org/downloads/point/last-week";
var BULK_DOWNLOADS_CHUNK_SIZE = 100;
var SCOPED_DOWNLOADS_CONCURRENCY = 4;
var manifestCache = /* @__PURE__ */ new Map();
var downloadsCache = /* @__PURE__ */ new Map();
function packageUrlSegment(packageName) {
  return encodeURIComponent(packageName);
}
function isScopedPackageName(packageName) {
  return packageName.startsWith("@");
}
function chunks(items, size) {
  const result = [];
  for (let index = 0; index < items.length; index += size) {
    result.push(items.slice(index, index + size));
  }
  return result;
}
async function fetchManifestUncached(packageName) {
  try {
    const res = await fetch(`${REGISTRY_BASE}/${packageUrlSegment(packageName)}`, { headers: { Accept: "application/json" } });
    if (!res.ok) return void 0;
    const data = await res.json();
    return {
      distTags: data["dist-tags"] ?? {},
      time: data.time ?? {},
      versions: Object.keys(data.versions ?? {})
    };
  } catch {
    return void 0;
  }
}
function fetchSecureRegistryManifest(packageName) {
  const cached = manifestCache.get(packageName);
  if (cached) return cached;
  const pending = fetchManifestUncached(packageName);
  manifestCache.set(packageName, pending);
  return pending;
}
async function fetchDownloadsUncached(packageName) {
  try {
    const res = await fetch(`${DOWNLOADS_BASE}/${packageUrlSegment(packageName)}`);
    if (!res.ok) return void 0;
    const data = await res.json();
    return typeof data.downloads === "number" ? data.downloads : void 0;
  } catch {
    return void 0;
  }
}
function fetchSecureWeeklyDownloads(packageName) {
  const cached = downloadsCache.get(packageName);
  if (cached) return cached;
  const pending = fetchDownloadsUncached(packageName);
  downloadsCache.set(packageName, pending);
  return pending;
}
async function fetchBulkWeeklyDownloads(packageNames) {
  const results = /* @__PURE__ */ new Map();
  if (packageNames.length === 0) return results;
  try {
    const packageSegment = packageNames.map(packageUrlSegment).join(",");
    const res = await fetch(`${DOWNLOADS_BASE}/${packageSegment}`);
    if (!res.ok) {
      await runWithConcurrency(packageNames, SCOPED_DOWNLOADS_CONCURRENCY, async (name) => {
        results.set(name, await fetchSecureWeeklyDownloads(name));
      });
      return results;
    }
    const data = await res.json();
    for (const name of packageNames) {
      const downloads = data[name]?.downloads;
      results.set(name, typeof downloads === "number" ? downloads : void 0);
    }
  } catch {
    await runWithConcurrency(packageNames, SCOPED_DOWNLOADS_CONCURRENCY, async (name) => {
      results.set(name, await fetchSecureWeeklyDownloads(name));
    });
  }
  return results;
}
async function fetchAllSecureWeeklyDownloads(packageNames, concurrency = SCOPED_DOWNLOADS_CONCURRENCY) {
  const uniqueNames = [...new Set(packageNames)].toSorted();
  const unscopedNames = uniqueNames.filter((name) => !isScopedPackageName(name));
  const scopedNames = uniqueNames.filter(isScopedPackageName);
  const results = /* @__PURE__ */ new Map();
  await runWithConcurrency(chunks(unscopedNames, BULK_DOWNLOADS_CHUNK_SIZE), 1, async (chunk) => {
    const chunkResults = await fetchBulkWeeklyDownloads(chunk);
    for (const [name, downloads] of chunkResults) {
      results.set(name, downloads);
    }
  });
  const scopedConcurrency = Math.max(1, Math.min(concurrency, SCOPED_DOWNLOADS_CONCURRENCY));
  await runWithConcurrency(scopedNames, scopedConcurrency, async (name) => {
    results.set(name, await fetchSecureWeeklyDownloads(name));
  });
  return results;
}
async function fetchAllSecurePackageMetadata(packageNames, concurrency = 16) {
  const uniqueNames = [...new Set(packageNames)].toSorted();
  const manifests = /* @__PURE__ */ new Map();
  const results = /* @__PURE__ */ new Map();
  await runWithConcurrency(uniqueNames, concurrency, async (name) => {
    manifests.set(name, await fetchSecureRegistryManifest(name));
  });
  const downloads = await fetchAllSecureWeeklyDownloads(uniqueNames, concurrency);
  for (const name of uniqueNames) {
    results.set(name, {
      downloads: downloads.get(name),
      manifest: manifests.get(name)
    });
  }
  return results;
}

// src/lib/secure/renderSecurityAudit.ts
import chalk2 from "chalk";
var PURPLE = chalk2.hex("#b26cff");
var COLOR = {
  gray: chalk2.gray,
  green: chalk2.green,
  purple: PURPLE,
  red: chalk2.red,
  yellow: chalk2.yellow
};
function depTypeLabel(depTypes) {
  return depTypes.map((depType) => depType === "dependencies" ? "dep" : "dev").join(",");
}
function formatAge(ageDays) {
  if (ageDays === void 0) return "-";
  if (ageDays < 1) return "<1d";
  if (ageDays < 365) return `${Math.floor(ageDays)}d`;
  return `${(ageDays / 365).toFixed(1)}y`;
}
function formatSecureDownloads(downloads) {
  if (downloads === void 0) return "-";
  if (downloads < 1e3) return `${downloads}`;
  const formatter = new Intl.NumberFormat("en-US", {
    maximumFractionDigits: 1,
    notation: "compact"
  });
  return formatter.format(downloads).toLowerCase();
}
function pad(raw, colored, width) {
  return colored + " ".repeat(Math.max(0, width - raw.length));
}
var columns = [
  {
    color: (_row, raw) => chalk2.white(raw),
    header: "Package",
    value: (row) => row.name
  },
  {
    color: (_row, raw) => chalk2.gray(raw),
    header: "Version",
    value: (row) => row.version ?? "-"
  },
  {
    color: (_row, raw) => chalk2.gray(raw),
    header: "Type",
    value: (row) => depTypeLabel(row.depTypes)
  },
  {
    color: (_row, raw) => chalk2.gray(raw),
    header: "Decls",
    value: (row) => `${row.declarationCount}`
  },
  {
    color: (row, raw) => COLOR[row.ageLevel](raw),
    header: "Age",
    value: (row) => formatAge(row.ageDays)
  },
  {
    color: (row, raw) => COLOR[row.downloadsLevel](raw),
    header: "Downloads/wk",
    value: (row) => formatSecureDownloads(row.downloads)
  }
];
function renderSecurityAuditRows(rows) {
  if (rows.length === 0) {
    console.log(chalk2.green("Secure: no external direct dependencies found."));
    return;
  }
  const widths = columns.map((column) => {
    let width = column.header.length;
    for (const row of rows) {
      width = Math.max(width, column.value(row).length);
    }
    return width;
  });
  console.log(chalk2.green("Secure: direct dependency audit"));
  const header = columns.map((column, index) => chalk2.bold(column.header.padEnd(widths[index]))).join("  ");
  console.log(header);
  console.log(chalk2.gray("\u2500".repeat(widths.reduce((total, width) => total + width + 2, -2))));
  for (const row of rows) {
    const line = columns.map((column, index) => {
      const raw = column.value(row);
      return pad(raw, column.color(row, raw), widths[index]);
    }).join("  ");
    console.log(line);
  }
  const redCount = rows.filter((row) => row.red).length;
  if (redCount > 0) {
    console.warn(chalk2.red(`Secure: ${redCount} red finding${redCount === 1 ? "" : "s"} found.`));
  } else {
    console.log(chalk2.green("Secure: no red findings."));
  }
}

// src/lib/secure/runSecurityAudit.ts
import chalk3 from "chalk";
import semver from "semver";
function parseDate(value) {
  if (!value) return void 0;
  const date = new Date(value);
  return Number.isNaN(date.getTime()) ? void 0 : date;
}
function canUseInstalledVersion(version, range) {
  if (!semver.valid(version)) return false;
  const validRange = semver.validRange(range);
  if (!validRange) return true;
  return semver.satisfies(version, validRange, { includePrerelease: range.includes("-") });
}
function resolveSecureDependencyVersion(dep, installedVersion, manifest) {
  if (installedVersion && canUseInstalledVersion(installedVersion, dep.range)) {
    return installedVersion;
  }
  if (!manifest) return void 0;
  const distTagVersion = manifest.distTags[dep.range];
  if (distTagVersion) return distTagVersion;
  const validRange = semver.validRange(dep.range);
  if (!validRange) return void 0;
  return semver.maxSatisfying(
    manifest.versions.filter((version) => semver.valid(version) !== null),
    validRange,
    { includePrerelease: dep.range.includes("-") }
  ) ?? void 0;
}
function buildSecurityAuditRows(declaredDeps, installedVersions, metadata, now = /* @__PURE__ */ new Date()) {
  const groups = /* @__PURE__ */ new Map();
  for (const dep of declaredDeps) {
    const packageMetadata = metadata.get(dep.name);
    const version = resolveSecureDependencyVersion(dep, installedVersions.get(dep.name), packageMetadata?.manifest);
    const key = `${dep.name}\0${version ?? ""}`;
    let group = groups.get(key);
    if (!group) {
      group = {
        declarations: [],
        depTypes: /* @__PURE__ */ new Set(),
        name: dep.name,
        packageLocations: /* @__PURE__ */ new Set(),
        packageNames: /* @__PURE__ */ new Set(),
        version
      };
      groups.set(key, group);
    }
    group.declarations.push(dep);
    group.depTypes.add(dep.depType);
    group.packageLocations.add(dep.packageLocation);
    group.packageNames.add(dep.packageName);
  }
  return [...groups.values()].map((group) => {
    const packageMetadata = metadata.get(group.name);
    const publishedAt = parseDate(group.version ? packageMetadata?.manifest?.time[group.version] : void 0);
    const age = classifySecureAge(publishedAt, now);
    const downloadsLevel = classifySecureDownloads(packageMetadata?.downloads);
    return {
      ageDays: age.ageDays,
      ageLevel: age.level,
      declarationCount: group.declarations.length,
      depTypes: [...group.depTypes].toSorted(),
      downloads: packageMetadata?.downloads,
      downloadsLevel,
      name: group.name,
      packageLocations: [...group.packageLocations].toSorted(),
      packageNames: [...group.packageNames].toSorted(),
      red: age.level === "red" || downloadsLevel === "red",
      version: group.version
    };
  }).toSorted((a, b) => {
    return a.name.localeCompare(b.name) || (a.version ?? "").localeCompare(b.version ?? "");
  });
}
function resolveTargetPackages(targets, pkg) {
  if (pkg === void 0) return targets;
  const target = resolveWorkspace(targets, pkg);
  return target ? [target] : [];
}
async function runSecurityAudit(pm, options = {}) {
  const cwd = options.cwd ?? INIT_CWD();
  const allTargets = collectSecurePackageTargets(cwd, pm.listWorkspaces());
  const targetPackages = resolveTargetPackages(allTargets, options.pkg);
  if (targetPackages.length === 0) {
    console.error(chalk3.red(`Package not found: ${options.pkg}`));
    return 1;
  }
  const localPackageNames = new Set(allTargets.map((target) => target.name));
  const declaredDeps = collectSecureDeclaredDependencies(cwd, targetPackages, localPackageNames);
  if (options.verbose) {
    console.log(chalk3.gray(`Secure: found ${declaredDeps.length} external direct dependency declarations`));
  }
  const packageNames = [...new Set(declaredDeps.map((dep) => dep.name))].toSorted();
  const fetchMetadata = options.fetchMetadata ?? fetchAllSecurePackageMetadata;
  const metadata = await fetchMetadata(packageNames, options.concurrency ?? 16);
  const rows = buildSecurityAuditRows(
    declaredDeps,
    pm.listInstalledVersions(),
    metadata,
    options.now
  );
  const render = options.render ?? renderSecurityAuditRows;
  render(rows);
  return rows.some((row) => row.red) ? 1 : 0;
}

// src/actions/secure.ts
var secure = async ({
  jobs = 16,
  pkg,
  verbose = false
} = {}) => {
  return await runSecurityAudit(getPackageManager(), {
    concurrency: jobs,
    pkg,
    verbose
  });
};
export {
  secure
};
//# sourceMappingURL=secure.mjs.map
