var __defProp = Object.defineProperty;
var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
import { p as networkFetch, h as getDefaultNetworkController, ak as join, al as downloadAndExtract, am as base64ToUint8, an as uint8ToBase64, H as almostnodeDebugLog, ao as almostnodeDebugError } from "./fetch-virtual-server-BZi6n2Qk.js";
import { proxy, wrap } from "comlink";
const DEFAULT_REGISTRY = "https://registry.npmjs.org";
class Registry {
  constructor(options = {}) {
    __publicField(this, "registryUrl");
    __publicField(this, "cache");
    this.registryUrl = options.registry || DEFAULT_REGISTRY;
    this.cache = options.cache || /* @__PURE__ */ new Map();
  }
  /**
   * Fetch package manifest (all versions metadata)
   */
  async getPackageManifest(packageName) {
    if (this.cache.has(packageName)) {
      return this.cache.get(packageName);
    }
    const url = `${this.registryUrl}/${encodePackageName(packageName)}`;
    const response = await networkFetch(
      url,
      {
        headers: {
          Accept: "application/vnd.npm.install-v1+json; q=1.0, application/json; q=0.8"
        }
      },
      getDefaultNetworkController()
    );
    if (!response.ok) {
      if (response.status === 404) {
        throw new Error(`Package not found: ${packageName}`);
      }
      throw new Error(`Failed to fetch package ${packageName}: ${response.status}`);
    }
    const manifest = await response.json();
    this.cache.set(packageName, manifest);
    return manifest;
  }
  /**
   * Get specific version metadata
   */
  async getPackageVersion(packageName, version) {
    const manifest = await this.getPackageManifest(packageName);
    if (manifest["dist-tags"][version]) {
      version = manifest["dist-tags"][version];
    }
    const versionData = manifest.versions[version];
    if (!versionData) {
      throw new Error(`Version ${version} not found for package ${packageName}`);
    }
    return versionData;
  }
  /**
   * Get latest version number
   */
  async getLatestVersion(packageName) {
    const manifest = await this.getPackageManifest(packageName);
    return manifest["dist-tags"].latest;
  }
  /**
   * Get all available versions
   */
  async getVersions(packageName) {
    const manifest = await this.getPackageManifest(packageName);
    return Object.keys(manifest.versions);
  }
  /**
   * Download tarball as ArrayBuffer
   */
  async downloadTarball(tarballUrl) {
    const response = await networkFetch(
      tarballUrl,
      void 0,
      getDefaultNetworkController()
    );
    if (!response.ok) {
      throw new Error(`Failed to download tarball: ${response.status}`);
    }
    return response.arrayBuffer();
  }
  /**
   * Clear the cache
   */
  clearCache() {
    this.cache.clear();
  }
}
function encodePackageName(name) {
  return name.replace("/", "%2f");
}
new Registry();
function parseVersion(version) {
  const match = version.match(/^(\d+)\.(\d+)\.(\d+)(?:-(.+))?$/);
  if (!match) return null;
  return {
    major: parseInt(match[1], 10),
    minor: parseInt(match[2], 10),
    patch: parseInt(match[3], 10),
    prerelease: match[4]
  };
}
function compareVersions(a, b) {
  const parsedA = parseVersion(a);
  const parsedB = parseVersion(b);
  if (!parsedA || !parsedB) {
    return a.localeCompare(b);
  }
  if (parsedA.major !== parsedB.major) {
    return parsedA.major - parsedB.major;
  }
  if (parsedA.minor !== parsedB.minor) {
    return parsedA.minor - parsedB.minor;
  }
  if (parsedA.patch !== parsedB.patch) {
    return parsedA.patch - parsedB.patch;
  }
  if (parsedA.prerelease && !parsedB.prerelease) return -1;
  if (!parsedA.prerelease && parsedB.prerelease) return 1;
  if (parsedA.prerelease && parsedB.prerelease) {
    return parsedA.prerelease.localeCompare(parsedB.prerelease);
  }
  return 0;
}
function padVersion(v) {
  v = v.replace(/^v/, "");
  const parts = v.split(".");
  while (parts.length < 3) parts.push("0");
  return parts.join(".");
}
function parseComparator(raw) {
  const match = raw.trim().match(/^(>=|<=|>|<|=)?\s*(\d+(?:\.\d+){0,2}(?:-[^\s]+)?)$/);
  if (!match) return null;
  return {
    op: match[1] || "=",
    version: padVersion(match[2])
  };
}
function satisfiesComparator(version, rawComparator) {
  const comparator = parseComparator(rawComparator);
  if (!comparator) return false;
  switch (comparator.op) {
    case ">=":
      return compareVersions(version, comparator.version) >= 0;
    case "<=":
      return compareVersions(version, comparator.version) <= 0;
    case ">":
      return compareVersions(version, comparator.version) > 0;
    case "<":
      return compareVersions(version, comparator.version) < 0;
    case "=":
      return compareVersions(version, comparator.version) === 0;
    default:
      return compareVersions(version, comparator.version) === 0;
  }
}
function satisfies(version, range) {
  const parsed = parseVersion(version);
  if (!parsed) return false;
  if (parsed.prerelease && !range.includes("-")) {
    return false;
  }
  range = range.trim();
  if (range.startsWith("=")) range = range.slice(1).trim();
  if (/^\d+\.\d+\.\d+/.test(range) && !range.includes(" ")) {
    const rangeMatch = range.match(/^(\d+\.\d+\.\d+(?:-[^\s]+)?)/);
    if (rangeMatch) {
      return compareVersions(version, rangeMatch[1]) === 0;
    }
  }
  if (range === "*" || range === "latest" || range === "") {
    return true;
  }
  if (range.includes("||")) {
    return range.split("||").some((r) => satisfies(version, r.trim()));
  }
  if (range.includes(" - ")) {
    const [min, max] = range.split(" - ").map((s) => s.trim());
    return compareVersions(version, min) >= 0 && compareVersions(version, max) <= 0;
  }
  const operatorMatches = range.match(/(>=|<=|>|<|=)?\s*\d+(?:\.\d+){0,2}(?:-[^\s]+)?/g);
  if (operatorMatches) {
    const compactRange = range.replace(/\s+/g, "");
    const compactMatches = operatorMatches.map((match) => match.replace(/\s+/g, "")).join("");
    const hasOperator = operatorMatches.some((match) => /^(>=|<=|>|<|=)/.test(match.trim()));
    if (compactRange === compactMatches && (hasOperator || operatorMatches.length > 1)) {
      return operatorMatches.every((match) => satisfiesComparator(version, match));
    }
  }
  if (range.startsWith("^")) {
    const base = padVersion(range.slice(1));
    const baseParsed = parseVersion(base);
    if (!baseParsed) return false;
    if (parsed.major !== baseParsed.major) {
      return false;
    }
    if (baseParsed.major === 0) {
      if (baseParsed.minor !== 0 && parsed.minor !== baseParsed.minor) {
        return false;
      }
      if (baseParsed.minor === 0 && parsed.minor !== 0) {
        return false;
      }
    }
    return compareVersions(version, base) >= 0;
  }
  if (range.startsWith("~")) {
    const base = padVersion(range.slice(1));
    const baseParsed = parseVersion(base);
    if (!baseParsed) return false;
    if (parsed.major !== baseParsed.major || parsed.minor !== baseParsed.minor) {
      return false;
    }
    return compareVersions(version, base) >= 0;
  }
  if (range.startsWith(">=")) {
    const base = padVersion(range.slice(2).trim());
    return compareVersions(version, base) >= 0;
  }
  if (range.startsWith(">")) {
    const base = padVersion(range.slice(1).trim());
    return compareVersions(version, base) > 0;
  }
  if (range.startsWith("<=")) {
    const base = padVersion(range.slice(2).trim());
    return compareVersions(version, base) <= 0;
  }
  if (range.startsWith("<")) {
    const base = padVersion(range.slice(1).trim());
    return compareVersions(version, base) < 0;
  }
  if (range.includes("x") || range.includes("X") || /^\d+$/.test(range) || /^\d+\.\d+$/.test(range)) {
    const parts = range.replace(/[xX]/g, "").split(".").filter(Boolean);
    if (parts.length === 1) {
      return parsed.major === parseInt(parts[0], 10);
    }
    if (parts.length === 2) {
      return parsed.major === parseInt(parts[0], 10) && parsed.minor === parseInt(parts[1], 10);
    }
  }
  if (range.includes(" ")) {
    const conditions = range.split(/\s+/).filter(Boolean);
    return conditions.every((r) => satisfies(version, r));
  }
  return compareVersions(version, range) === 0;
}
function findBestVersion(versions, range) {
  const sorted = [...versions].sort((a, b) => compareVersions(b, a));
  if (range.includes("||")) {
    const subRanges = range.split("||").map((r) => r.trim());
    for (const subRange of subRanges) {
      for (const version of sorted) {
        if (satisfies(version, subRange)) {
          return version;
        }
      }
    }
    return null;
  }
  for (const version of sorted) {
    if (satisfies(version, range)) {
      return version;
    }
  }
  return null;
}
function parseNpmAliasRange(range) {
  if (!range.startsWith("npm:")) {
    return null;
  }
  const target = range.slice(4).trim();
  if (!target) {
    throw new Error(`Invalid npm alias spec: ${range}`);
  }
  return parsePackageNameAndRange(target);
}
function parsePackageNameAndRange(spec) {
  if (spec.startsWith("@")) {
    const slashIndex = spec.indexOf("/");
    if (slashIndex === -1) {
      throw new Error(`Invalid package spec: ${spec}`);
    }
    const afterSlash = spec.slice(slashIndex + 1);
    const atIndex2 = afterSlash.indexOf("@");
    if (atIndex2 === -1) {
      return { packageName: spec, versionRange: "latest" };
    }
    const versionRange2 = afterSlash.slice(atIndex2 + 1) || "latest";
    return {
      packageName: spec.slice(0, slashIndex + 1 + atIndex2),
      versionRange: versionRange2
    };
  }
  const atIndex = spec.indexOf("@");
  if (atIndex === -1) {
    return { packageName: spec, versionRange: "latest" };
  }
  const versionRange = spec.slice(atIndex + 1) || "latest";
  return {
    packageName: spec.slice(0, atIndex),
    versionRange
  };
}
async function resolveDependencies(packageName, versionRange = "latest", options = {}) {
  const registry = options.registry || new Registry();
  const context = {
    registry,
    resolved: /* @__PURE__ */ new Map(),
    resolvedSource: /* @__PURE__ */ new Map(),
    resolving: /* @__PURE__ */ new Set(),
    options
  };
  await resolvePackage(packageName, versionRange, context);
  return context.resolved;
}
async function resolveFromPackageJson(packageJson, options = {}) {
  const registry = options.registry || new Registry();
  const context = {
    registry,
    resolved: /* @__PURE__ */ new Map(),
    resolvedSource: /* @__PURE__ */ new Map(),
    resolving: /* @__PURE__ */ new Set(),
    options
  };
  const deps = { ...packageJson.dependencies };
  if (options.includeDev && packageJson.devDependencies) {
    Object.assign(deps, packageJson.devDependencies);
  }
  for (const [name, range] of Object.entries(deps)) {
    await resolvePackage(name, range, context);
  }
  return context.resolved;
}
async function resolvePackage(packageName, versionRange, context) {
  var _a, _b;
  const { registry, resolved, resolvedSource, resolving, options } = context;
  const aliasTarget = parseNpmAliasRange(versionRange);
  const sourcePackageName = (aliasTarget == null ? void 0 : aliasTarget.packageName) || packageName;
  const sourceVersionRange = (aliasTarget == null ? void 0 : aliasTarget.versionRange) || versionRange;
  const key = `${packageName}@${versionRange}`;
  if (resolving.has(key)) {
    return;
  }
  if (resolved.has(packageName)) {
    const existing = resolved.get(packageName);
    const existingSourcePackage = resolvedSource.get(packageName) || packageName;
    if (existingSourcePackage === sourcePackageName && satisfies(existing.version, sourceVersionRange)) {
      return;
    }
    return;
  }
  resolving.add(key);
  try {
    (_a = options.onProgress) == null ? void 0 : _a.call(options, `Resolving ${packageName}@${versionRange}`);
    const manifest = await registry.getPackageManifest(sourcePackageName);
    const versions = Object.keys(manifest.versions);
    let targetVersion;
    if (sourceVersionRange === "latest" || sourceVersionRange === "*") {
      targetVersion = manifest["dist-tags"].latest;
    } else if (manifest["dist-tags"][sourceVersionRange]) {
      targetVersion = manifest["dist-tags"][sourceVersionRange];
    } else {
      const best = findBestVersion(versions, sourceVersionRange);
      if (!best) {
        throw new Error(
          `No matching version found for ${sourcePackageName}@${sourceVersionRange}`
        );
      }
      targetVersion = best;
    }
    const versionData = manifest.versions[targetVersion];
    const resolvedPackage = {
      name: packageName,
      version: targetVersion,
      tarballUrl: versionData.dist.tarball,
      dependencies: versionData.dependencies || {}
    };
    resolved.set(packageName, resolvedPackage);
    resolvedSource.set(packageName, sourcePackageName);
    const deps = {};
    if (versionData.peerDependencies) {
      const meta = versionData.peerDependenciesMeta || {};
      for (const [name, range] of Object.entries(versionData.peerDependencies)) {
        if (!((_b = meta[name]) == null ? void 0 : _b.optional)) {
          deps[name] = range;
        }
      }
    }
    Object.assign(deps, versionData.dependencies);
    if (options.includeOptional && versionData.optionalDependencies) {
      Object.assign(deps, versionData.optionalDependencies);
    }
    const depEntries = Object.entries(deps);
    if (depEntries.length > 0) {
      const CONCURRENCY = 8;
      for (let i = 0; i < depEntries.length; i += CONCURRENCY) {
        const batch = depEntries.slice(i, i + CONCURRENCY);
        await Promise.all(
          batch.map(([depName, depRange]) => resolvePackage(depName, depRange, context))
        );
      }
    }
  } finally {
    resolving.delete(key);
  }
}
function normalizeBin(pkgName, bin) {
  if (!bin) return {};
  if (typeof bin === "string") {
    const cmdName = pkgName.includes("/") ? pkgName.split("/").pop() : pkgName;
    return { [cmdName]: bin };
  }
  return bin;
}
function parsePackageSpec(spec) {
  if (spec.startsWith("@")) {
    const slashIndex = spec.indexOf("/");
    if (slashIndex === -1) {
      throw new Error(`Invalid package spec: ${spec}`);
    }
    const afterSlash = spec.slice(slashIndex + 1);
    const atIndex2 = afterSlash.indexOf("@");
    if (atIndex2 === -1) {
      return { name: spec };
    }
    return {
      name: spec.slice(0, slashIndex + 1 + atIndex2),
      version: afterSlash.slice(atIndex2 + 1)
    };
  }
  const atIndex = spec.indexOf("@");
  if (atIndex === -1) {
    return { name: spec };
  }
  return {
    name: spec.slice(0, atIndex),
    version: spec.slice(atIndex + 1)
  };
}
function serializeInstallResult(result) {
  return {
    installed: Array.from(result.installed.entries()),
    added: [...result.added]
  };
}
function deserializeInstallResult(result) {
  return {
    installed: new Map(result.installed),
    added: [...result.added]
  };
}
function toSerializableInstallOptions(options) {
  const { onProgress: _onProgress, ...serializable } = options;
  return serializable;
}
async function executeInstallRequest(vfs, settings, request, options = {}) {
  const registry = new Registry({
    registry: options.registry || settings.registry,
    cache: settings.cache
  });
  if (request.kind === "packageJson") {
    return installFromPackageJson(vfs, settings.cwd, registry, options);
  }
  return installPackage(vfs, settings.cwd, registry, request.packageSpec, options);
}
function listInstalledPackages(vfs, cwd) {
  const nodeModulesPath = join(cwd, "node_modules");
  if (!vfs.existsSync(nodeModulesPath)) {
    return {};
  }
  const packages = {};
  const entries = vfs.readdirSync(nodeModulesPath);
  for (const entry of entries) {
    if (entry.startsWith(".")) continue;
    if (entry.startsWith("@")) {
      const scopePath = join(nodeModulesPath, entry);
      const scopedPkgs = vfs.readdirSync(scopePath);
      for (const scopedPkg of scopedPkgs) {
        const pkgJsonPath = join(scopePath, scopedPkg, "package.json");
        if (vfs.existsSync(pkgJsonPath)) {
          const pkgJson = JSON.parse(vfs.readFileSync(pkgJsonPath, "utf8"));
          packages[`${entry}/${scopedPkg}`] = pkgJson.version;
        }
      }
    } else {
      const pkgJsonPath = join(nodeModulesPath, entry, "package.json");
      if (vfs.existsSync(pkgJsonPath)) {
        const pkgJson = JSON.parse(vfs.readFileSync(pkgJsonPath, "utf8"));
        packages[entry] = pkgJson.version;
      }
    }
  }
  return packages;
}
async function installPackage(vfs, cwd, registry, packageSpec, options = {}) {
  const { onProgress } = options;
  const { name, version } = parsePackageSpec(packageSpec);
  onProgress == null ? void 0 : onProgress(`Resolving ${name}@${version || "latest"}...`);
  const resolved = await resolveDependencies(name, version || "latest", {
    registry,
    includeDev: options.includeDev,
    includeOptional: options.includeOptional,
    onProgress
  });
  const added = await installResolved(vfs, cwd, resolved, options);
  if (options.save || options.saveDev) {
    const pkgToAdd = resolved.get(name);
    if (pkgToAdd) {
      await updatePackageJson(vfs, cwd, name, `^${pkgToAdd.version}`, options.saveDev || false);
    }
  }
  onProgress == null ? void 0 : onProgress(`Installed ${resolved.size} packages`);
  return { installed: resolved, added };
}
async function installFromPackageJson(vfs, cwd, registry, options = {}) {
  const { onProgress } = options;
  const includeDev = options.includeDev ?? true;
  const pkgJsonPath = join(cwd, "package.json");
  if (!vfs.existsSync(pkgJsonPath)) {
    throw new Error("No package.json found");
  }
  const pkgJson = JSON.parse(vfs.readFileSync(pkgJsonPath, "utf8"));
  onProgress == null ? void 0 : onProgress("Resolving dependencies...");
  const resolved = await resolveFromPackageJson(pkgJson, {
    registry,
    includeDev,
    includeOptional: options.includeOptional,
    onProgress
  });
  const added = await installResolved(vfs, cwd, resolved, options);
  onProgress == null ? void 0 : onProgress(`Installed ${resolved.size} packages`);
  return { installed: resolved, added };
}
async function installResolved(vfs, cwd, resolved, options) {
  const { onProgress } = options;
  const added = [];
  const nodeModulesPath = join(cwd, "node_modules");
  vfs.mkdirSync(nodeModulesPath, { recursive: true });
  const toInstall = [];
  for (const [name, pkg] of resolved) {
    const pkgPath = join(nodeModulesPath, name);
    const existingPkgJson = join(pkgPath, "package.json");
    if (vfs.existsSync(existingPkgJson)) {
      try {
        const existing = JSON.parse(vfs.readFileSync(existingPkgJson, "utf8"));
        if (existing.version === pkg.version) {
          onProgress == null ? void 0 : onProgress(`Skipping ${name}@${pkg.version} (already installed)`);
          continue;
        }
      } catch {
      }
    }
    toInstall.push({ name, pkg, pkgPath });
  }
  const concurrency = 6;
  onProgress == null ? void 0 : onProgress(`Installing ${toInstall.length} packages...`);
  for (let i = 0; i < toInstall.length; i += concurrency) {
    const batch = toInstall.slice(i, i + concurrency);
    await Promise.all(
      batch.map(async ({ name, pkg, pkgPath }) => {
        onProgress == null ? void 0 : onProgress(`  Downloading ${name}@${pkg.version}...`);
        await downloadAndExtract(pkg.tarballUrl, vfs, pkgPath, {
          stripComponents: 1
        });
        try {
          const pkgJsonPath = join(pkgPath, "package.json");
          if (vfs.existsSync(pkgJsonPath)) {
            const pkgJson = JSON.parse(vfs.readFileSync(pkgJsonPath, "utf8"));
            const binEntries = normalizeBin(name, pkgJson.bin);
            const binDir = join(nodeModulesPath, ".bin");
            for (const [cmdName, entryPath] of Object.entries(binEntries)) {
              vfs.mkdirSync(binDir, { recursive: true });
              const targetPath = join(pkgPath, entryPath);
              vfs.writeFileSync(
                join(binDir, cmdName),
                `node "${targetPath}" "$@"
`
              );
            }
          }
        } catch {
        }
        added.push(name);
      })
    );
  }
  await writeLockfile(vfs, cwd, resolved);
  return added;
}
async function writeLockfile(vfs, cwd, resolved) {
  const lockfile = {};
  for (const [name, pkg] of resolved) {
    lockfile[name] = {
      version: pkg.version,
      resolved: pkg.tarballUrl
    };
  }
  const lockfilePath = join(cwd, "node_modules", ".package-lock.json");
  vfs.writeFileSync(lockfilePath, JSON.stringify(lockfile, null, 2));
}
async function updatePackageJson(vfs, cwd, packageName, version, isDev) {
  const pkgJsonPath = join(cwd, "package.json");
  let pkgJson = {};
  if (vfs.existsSync(pkgJsonPath)) {
    pkgJson = JSON.parse(vfs.readFileSync(pkgJsonPath, "utf8"));
  }
  const field = isDev ? "devDependencies" : "dependencies";
  if (!pkgJson[field]) {
    pkgJson[field] = {};
  }
  pkgJson[field][packageName] = version;
  vfs.writeFileSync(pkgJsonPath, JSON.stringify(pkgJson, null, 2));
}
function createInstallSnapshot(vfs, cwd) {
  const files = [];
  const seen = /* @__PURE__ */ new Set();
  addDirectoryChain(vfs, cwd, files, seen);
  const packageJsonPath = joinPath(cwd, "package.json");
  if (vfs.existsSync(packageJsonPath)) {
    addFileEntry(vfs, packageJsonPath, files, seen);
  }
  const nodeModulesPath = joinPath(cwd, "node_modules");
  if (vfs.existsSync(nodeModulesPath)) {
    addNodeModulesSnapshot(vfs, nodeModulesPath, files, seen);
  }
  return { files };
}
async function applyVfsPatch(vfs, patch, options = {}) {
  const chunkSize = options.chunkSize ?? 64;
  const yieldControl = options.yieldControl || defaultYieldControl;
  for (let index2 = 0; index2 < patch.operations.length; index2 += 1) {
    const operation = patch.operations[index2];
    switch (operation.type) {
      case "mkdir":
        vfs.mkdirSync(operation.path, { recursive: true });
        break;
      case "writeFile":
        vfs.writeFileSync(operation.path, base64ToUint8(operation.content));
        break;
      case "unlink":
        if (vfs.existsSync(operation.path)) {
          vfs.unlinkSync(operation.path);
        }
        break;
      case "rmdir":
        if (vfs.existsSync(operation.path)) {
          vfs.rmdirSync(operation.path);
        }
        break;
    }
    if ((index2 + 1) % chunkSize === 0 && index2 + 1 < patch.operations.length) {
      await yieldControl();
    }
  }
}
function addDirectoryChain(vfs, targetPath, files, seen) {
  const normalized = normalizePath(targetPath);
  const segments = normalized.split("/").filter(Boolean);
  addDirectoryEntry("/", files, seen);
  let current = "";
  for (const segment of segments) {
    current += `/${segment}`;
    if (vfs.existsSync(current)) {
      addDirectoryEntry(current, files, seen);
    }
  }
}
function addNodeModulesSnapshot(vfs, nodeModulesPath, files, seen) {
  addDirectoryEntry(nodeModulesPath, files, seen);
  for (const entry of vfs.readdirSync(nodeModulesPath)) {
    if (entry.startsWith(".")) continue;
    const childPath = joinPath(nodeModulesPath, entry);
    if (entry.startsWith("@")) {
      addDirectoryEntry(childPath, files, seen);
      for (const scopedEntry of vfs.readdirSync(childPath)) {
        addPackageSnapshot(vfs, joinPath(childPath, scopedEntry), files, seen);
      }
    } else {
      addPackageSnapshot(vfs, childPath, files, seen);
    }
  }
}
function addPackageSnapshot(vfs, pkgPath, files, seen) {
  try {
    const stats = vfs.statSync(pkgPath);
    if (!stats.isDirectory()) return;
  } catch {
    return;
  }
  addDirectoryEntry(pkgPath, files, seen);
  const pkgJsonPath = joinPath(pkgPath, "package.json");
  if (vfs.existsSync(pkgJsonPath)) {
    addFileEntry(vfs, pkgJsonPath, files, seen);
  }
  const nestedNm = joinPath(pkgPath, "node_modules");
  if (vfs.existsSync(nestedNm)) {
    addNodeModulesSnapshot(vfs, nestedNm, files, seen);
  }
}
function addDirectoryEntry(path, files, seen) {
  const normalized = normalizePath(path);
  if (seen.has(normalized)) {
    return;
  }
  seen.add(normalized);
  files.push({ path: normalized, type: "directory" });
}
function addFileEntry(vfs, path, files, seen) {
  const normalized = normalizePath(path);
  if (seen.has(normalized)) {
    return;
  }
  seen.add(normalized);
  const isEssential = normalized.endsWith("/package.json") || normalized === "package.json";
  files.push({
    path: normalized,
    type: "file",
    content: isEssential ? uint8ToBase64(vfs.readFileSync(normalized)) : ""
  });
}
function normalizePath(path) {
  if (!path) return "/";
  return path.startsWith("/") ? path.replace(/\/+/g, "/") : `/${path}`.replace(/\/+/g, "/");
}
function joinPath(parent, child) {
  const prefix = normalizePath(parent);
  return prefix === "/" ? `/${child}` : `${prefix}/${child}`;
}
async function defaultYieldControl() {
  if (typeof window !== "undefined" && typeof window.requestAnimationFrame === "function") {
    await new Promise((resolve) => {
      window.requestAnimationFrame(() => resolve());
    });
    return;
  }
  await new Promise((resolve) => {
    setTimeout(resolve, 0);
  });
}
class NpmInstallWorkerClient {
  constructor() {
    __publicField(this, "worker", null);
    __publicField(this, "workerApi", null);
  }
  async runInstall(payload, onProgress) {
    const api = this.getWorkerApi();
    return api.runInstall(payload, onProgress ? proxy(onProgress) : null);
  }
  terminate() {
    var _a;
    this.workerApi = null;
    (_a = this.worker) == null ? void 0 : _a.terminate();
    this.worker = null;
  }
  getWorkerApi() {
    if (this.workerApi) {
      return this.workerApi;
    }
    this.worker = new Worker(
      new URL(
        /* @vite-ignore */
        "/assets/npm-install-worker-iyEMlxzB.js",
        import.meta.url
      ),
      { type: "module" }
    );
    this.workerApi = wrap(this.worker);
    return this.workerApi;
  }
}
class PackageManager {
  constructor(vfs, options = {}) {
    __publicField(this, "vfs");
    __publicField(this, "cwd");
    __publicField(this, "registryOptions");
    __publicField(this, "installMode");
    __publicField(this, "onMutation");
    __publicField(this, "workerClientFactory");
    __publicField(this, "workerClient", null);
    this.vfs = vfs;
    this.cwd = options.cwd || "/";
    this.registryOptions = {
      registry: options.registry,
      cache: options.cache || /* @__PURE__ */ new Map()
    };
    this.installMode = options.installMode || "auto";
    this.onMutation = options.onMutation || null;
    this.workerClientFactory = options.workerClientFactory || (() => new NpmInstallWorkerClient());
  }
  /**
   * Install a package and its dependencies
   */
  async install(packageSpec, options = {}) {
    return this.executeInstallRequest({ kind: "package", packageSpec }, options);
  }
  /**
   * Install all dependencies from package.json
   */
  async installFromPackageJson(options = {}) {
    return this.executeInstallRequest({ kind: "packageJson" }, options);
  }
  /**
   * List installed packages
   */
  list() {
    return listInstalledPackages(this.vfs, this.cwd);
  }
  async executeInstallRequest(request, options) {
    var _a, _b, _c, _d;
    if (this.shouldUseWorker()) {
      almostnodeDebugLog("npm", `[almostnode DEBUG] npm worker start: ${formatInstallRequest(request)} cwd=${this.cwd}`);
      try {
        return await this.installInWorker(request, options);
      } catch (error) {
        const workerMessage = toErrorMessage(error);
        almostnodeDebugError("npm", `[almostnode DEBUG] npm worker failed: ${formatInstallRequest(request)} -> ${workerMessage}`);
        (_b = (_a = this.workerClient) == null ? void 0 : _a.terminate) == null ? void 0 : _b.call(_a);
        this.workerClient = null;
        (_c = options.onProgress) == null ? void 0 : _c.call(options, "npm: worker install failed; retrying on main thread...");
        try {
          const result = await this.installInMainThread(request, options);
          almostnodeDebugLog("npm", `[almostnode DEBUG] npm main-thread retry succeeded: ${formatInstallRequest(request)} cwd=${this.cwd}`);
          return result;
        } catch (mainThreadError) {
          const mainThreadMessage = toErrorMessage(mainThreadError);
          almostnodeDebugError(
            "npm",
            `[almostnode DEBUG] npm main-thread retry failed: ${formatInstallRequest(request)} -> ${mainThreadMessage}`
          );
          (_d = options.onProgress) == null ? void 0 : _d.call(options, "npm: install failed after worker retry and main-thread retry.");
          throw new Error(`worker install failed: ${workerMessage}; main-thread retry failed: ${mainThreadMessage}`);
        }
      }
    }
    return this.installInMainThread(request, options);
  }
  async installInMainThread(request, options) {
    const result = await executeInstallRequest(this.vfs, this.getSettings(), request, options);
    await this.notifyMutation({
      touchesNodeModules: result.added.length > 0,
      touchesPackageJson: request.kind === "package" && !!(options.save || options.saveDev)
    });
    return result;
  }
  shouldUseWorker() {
    if (this.installMode === "main-thread") {
      return false;
    }
    return typeof Worker !== "undefined";
  }
  async installInWorker(request, options) {
    var _a, _b, _c, _d;
    const client = this.workerClient || this.workerClientFactory();
    this.workerClient = client;
    const snapshot = createInstallSnapshot(this.vfs, this.cwd);
    const response = await client.runInstall(
      {
        snapshot,
        settings: {
          cwd: this.cwd,
          registry: options.registry || this.registryOptions.registry
        },
        request,
        options: toSerializableInstallOptions(options)
      },
      options.onProgress || null
    );
    almostnodeDebugLog(
      "npm",
      `[almostnode DEBUG] npm worker patch: ${formatInstallRequest(request)} operations=${response.patch.operations.length} changedPaths=${response.patch.changedPaths.length} snapshotEntries=${snapshot.files.length}`
    );
    if (response.patch.operations.length > 0) {
      (_a = options.onProgress) == null ? void 0 : _a.call(options, `Applying ${response.patch.operations.length} file changes...`);
      await applyVfsPatch(this.vfs, response.patch);
      (_b = options.onProgress) == null ? void 0 : _b.call(options, "Install changes applied");
      almostnodeDebugLog(
        "npm",
        `[almostnode DEBUG] npm worker patch applied: ${formatInstallRequest(request)} operations=${response.patch.operations.length}`
      );
    } else {
      almostnodeDebugLog("npm", `[almostnode DEBUG] npm worker patch applied: ${formatInstallRequest(request)} operations=0`);
    }
    await this.notifyMutation({
      touchesNodeModules: response.patch.touchesNodeModules,
      touchesPackageJson: response.patch.touchesPackageJson
    });
    (_d = (_c = this.workerClient) == null ? void 0 : _c.terminate) == null ? void 0 : _d.call(_c);
    this.workerClient = null;
    return deserializeInstallResult(response.result);
  }
  getSettings() {
    return {
      cwd: this.cwd,
      registry: this.registryOptions.registry,
      cache: this.registryOptions.cache
    };
  }
  dispose() {
    var _a, _b;
    (_b = (_a = this.workerClient) == null ? void 0 : _a.terminate) == null ? void 0 : _b.call(_a);
    this.workerClient = null;
  }
  async notifyMutation(summary) {
    var _a;
    await ((_a = this.onMutation) == null ? void 0 : _a.call(this, summary));
  }
}
function formatInstallRequest(request) {
  if (request.kind === "package") {
    return `package:${request.packageSpec}`;
  }
  return "packageJson";
}
function toErrorMessage(error) {
  return error instanceof Error ? error.message : String(error);
}
async function install(packageSpec, vfs, options) {
  const pm = new PackageManager(vfs);
  return pm.install(packageSpec, options);
}
const index = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProperty({
  __proto__: null,
  PackageManager,
  Registry,
  deserializeInstallResult,
  install,
  normalizeBin,
  parsePackageSpec,
  serializeInstallResult
}, Symbol.toStringTag, { value: "Module" }));
export {
  PackageManager as P,
  index as a,
  install as i
};
//# sourceMappingURL=index-DDTngCOi.js.map
