// src/lib/checkResult.ts
import chalk from "chalk";
function logFailure(name, result, level, suffix) {
  const message = `${name} had ${result} failures [${suffix}]`;
  if (level === "error") {
    console.error(chalk.red(message));
    return;
  }
  console.warn(chalk.yellow(message));
}
var checkResult = (name, result, level = "error", shouldExitOnFail = false) => {
  if (!result) return;
  if (shouldExitOnFail) {
    logFailure(name, result, level, "Exiting Process");
    process.exit(result);
    return;
  }
  logFailure(name, result, level, "Continuing");
};

// src/lib/crossSpawn.ts
import crossSpawn from "cross-spawn";
function spawnSync(command, args, options) {
  return crossSpawn.sync(command, args, options);
}

// src/lib/packageManagerRuntime.ts
import fs from "node:fs";
import chalk2 from "chalk";
var DISPLAY_NAMES = {
  bun: "Bun",
  npm: "npm",
  pnpm: "pnpm",
  yarn: "Yarn"
};
var MAC_INSTALL_COMMANDS = {
  bun: "brew install oven-sh/bun/bun",
  npm: "brew install node",
  pnpm: "brew install pnpm",
  yarn: "brew install yarn"
};
var SUPPORTED_PLATFORMS = ["darwin", "linux", "win32"];
function currentPlatform() {
  return SUPPORTED_PLATFORMS.find((platform) => platform === process.platform) ?? "unknown";
}
function shouldAskYesNo(question) {
  if (!process.stdin.isTTY || !process.stdout.isTTY) {
    return false;
  }
  process.stdout.write(question);
  const buffer = Buffer.alloc(1024);
  const bytesRead = fs.readSync(process.stdin.fd, buffer, 0, buffer.length, null);
  const answer = buffer.toString("utf8", 0, bytesRead).trim().toLowerCase();
  return answer === "y" || answer === "yes";
}
function isCommandInstalled(command) {
  const result = spawnSync(command, ["--version"], {
    encoding: "utf8",
    stdio: "ignore"
  });
  return !result.error && result.status === 0;
}
function isPackageManagerInstalled(pm) {
  return isCommandInstalled(pm);
}
function getPackageManagerInstallPlan(pm, platform = currentPlatform()) {
  const displayName = DISPLAY_NAMES[pm];
  if (platform === "darwin") {
    const command = MAC_INSTALL_COMMANDS[pm];
    return {
      command,
      manualInstructions: [
        `Install ${displayName} with: ${command}`
      ],
      packageManager: pm,
      platform,
      supported: true
    };
  }
  if (platform === "linux") {
    return {
      manualInstructions: [
        `Automatic installation for ${displayName} is not implemented on Linux yet.`,
        `Install ${displayName} manually and re-run the command.`
      ],
      packageManager: pm,
      platform,
      supported: false
    };
  }
  if (platform === "win32") {
    return {
      manualInstructions: [
        `Automatic installation for ${displayName} is not implemented on Windows yet.`,
        `Install ${displayName} manually and re-run the command.`
      ],
      packageManager: pm,
      platform,
      supported: false
    };
  }
  return {
    manualInstructions: [
      `Automatic installation for ${displayName} is not implemented on ${platform} yet.`,
      `Install ${displayName} manually and re-run the command.`
    ],
    packageManager: pm,
    platform,
    supported: false
  };
}
function printManualInstructions(plan, context) {
  console.error(chalk2.yellow(`${DISPLAY_NAMES[plan.packageManager]} is required for "${context.operation}".`));
  for (const line of plan.manualInstructions) {
    console.error(chalk2.gray(`  ${line}`));
  }
}
function shouldInstallWithHomebrew(pm, cwd) {
  const command = MAC_INSTALL_COMMANDS[pm];
  const result = spawnSync("brew", command.replace("brew ", "").split(" "), {
    cwd,
    encoding: "utf8",
    stdio: "inherit"
  });
  return result.status === 0;
}
function didEnsurePackageManagerInstalled(pm, context) {
  if (isPackageManagerInstalled(pm)) return true;
  const plan = getPackageManagerInstallPlan(pm, context.platform ?? currentPlatform());
  const displayName = DISPLAY_NAMES[pm];
  console.error(chalk2.yellow(`${context.operation} requires ${displayName}, but it is not installed.`));
  if (!plan.supported) {
    printManualInstructions(plan, context);
    return false;
  }
  if (!isCommandInstalled("brew")) {
    console.error(chalk2.yellow("Homebrew is not installed, so automatic installation is unavailable."));
    console.error(chalk2.gray("  Install Homebrew from https://brew.sh and then run:"));
    console.error(chalk2.gray(`  ${plan.command}`));
    return false;
  }
  const isConfirmed = shouldAskYesNo(chalk2.cyan(`Install ${displayName} with Homebrew now? [y/N] `));
  if (!isConfirmed) {
    console.error(chalk2.gray(`Skipping install. Run "${plan.command}" manually and then retry.`));
    return false;
  }
  console.error(chalk2.cyan(`Installing ${displayName} via Homebrew...
`));
  if (!shouldInstallWithHomebrew(pm, context.cwd)) {
    console.error(chalk2.red(`Homebrew failed to install ${displayName}.`));
    console.error(chalk2.gray(`Run "${plan.command}" manually and then retry.`));
    return false;
  }
  if (!isPackageManagerInstalled(pm)) {
    console.error(chalk2.red(`${displayName} still does not appear to be installed after Homebrew completed.`));
    console.error(chalk2.gray(`Run "${plan.command}" manually and then retry.`));
    return false;
  }
  console.error(chalk2.green(`${displayName} installed successfully.`));
  return true;
}

// src/pm/workspaces.ts
import { existsSync, readFileSync } from "node:fs";
import PATH from "node:path";
import { globSync } from "glob";
function readJsonFile(path2) {
  if (!existsSync(path2)) return void 0;
  try {
    return JSON.parse(readFileSync(path2, "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);
}
function detectPackageManagerFromPackageJson(cwd = process.cwd()) {
  const packageManager = readRootPackageJson(cwd)?.packageManager;
  if (!(packageManager != null && packageManager.length > 0)) return void 0;
  return packageManager.split("@", 1)[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 != null && packageManager.length > 0 && 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/processEx.ts
import chalk3 from "chalk";

// src/lib/withError.ts
var withError = (ex, closure, predicate = (ex2) => !!ex2.name && !!ex2.message) => {
  return predicate(ex) ? closure(ex) : void 0;
};

// src/lib/withErrnoException.ts
var withErrnoException = (ex, closure) => {
  return withError(ex, closure, (ex2) => ex2.errno !== void 0);
};

// src/lib/processEx.ts
var processEx = (ex) => {
  const error = typeof ex === "string" ? new Error(ex) : ex;
  const exitCode = withErrnoException(error, (error2) => {
    if (error2.code === "ENOENT") {
      console.error(chalk3.red(`'${error2.path}' not found.`));
    } else {
      console.error(chalk3.red(`Errno: ${error2.code}`));
    }
    return error2.errno ?? -1;
  }) ?? withError(error, (error2) => {
    console.error(chalk3.red(`${error2.name}: ${error2.message}`));
    return -1;
  }) ?? (() => {
    console.error(chalk3.red(`Unexpected Error: ${JSON.stringify(ex, null, 2)}`));
    return -1;
  })();
  process.exit(process.exitCode ?? exitCode);
};

// src/lib/safeExit.ts
function resultExitCode(result) {
  return typeof result === "number" ? result : result.exitCode;
}
var safeExit = (func, shouldExitOnFail = true) => {
  try {
    const result = func();
    const exitCode = resultExitCode(result);
    if (exitCode && shouldExitOnFail) {
      process.exit(exitCode);
    }
    return result;
  } catch (ex) {
    return processEx(ex);
  }
};

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

// src/lib/packageName.ts
import { readFileSync as readFileSync2 } from "node:fs";
import path from "node:path";
function packageName() {
  if (process.env.npm_package_name != null && process.env.npm_package_name.length > 0) {
    return process.env.npm_package_name;
  }
  try {
    const pkgPath = path.join(INIT_CWD(), "package.json");
    const pkg = JSON.parse(readFileSync2(pkgPath, "utf8"));
    return pkg.name;
  } catch {
    return void 0;
  }
}

// src/lib/reporting/xyReporter.ts
var reporterState = {
  currentCommand: "unknown",
  isEnvelopeEmitted: false,
  isJsonModeEnabled: false,
  isStrictModeEnabled: false,
  originalStdoutWrite: void 0,
  startTime: 0
};
function isJsonMode() {
  return reporterState.isJsonModeEnabled;
}

// src/lib/runSteps.ts
import { existsSync as existsSync3 } from "node:fs";
import chalk4 from "chalk";
var packageManagers = /* @__PURE__ */ new Set(["bun", "npm", "pnpm", "yarn"]);
var runSteps = (name, steps, shouldExitOnFail = true, messages) => {
  return safeExit(() => {
    const pkgName = packageName();
    console.log(chalk4.green(`${name} [${pkgName}]`));
    let totalStatus = 0;
    for (const [i, [command, args, config]] of steps.entries()) {
      if (messages && Object.hasOwn(messages, i)) {
        console.log(chalk4.gray(messages[i]));
      }
      const argList = Array.isArray(args) ? args : args.split(" ");
      if (command === "node" && !existsSync3(argList[0])) {
        throw new Error(`File not found [${argList[0]}]`);
      }
      if (packageManagers.has(command) && !didEnsurePackageManagerInstalled(command, { operation: `${name}: ${command} ${Array.isArray(args) ? args.join(" ") : args}`.trim() })) {
        checkResult(name, 1, "error", shouldExitOnFail);
        totalStatus += 1;
        continue;
      }
      const status = spawnSync(command, Array.isArray(args) ? args : args.split(" "), {
        ...config,
        encoding: "utf8",
        // Merge per-step env on top so callers can supply overrides
        // (e.g. NODE_OPTIONS=--max-old-space-size=...); process.env still
        // seeds the common case so FORCE_COLOR etc. survive.
        env: {
          FORCE_COLOR: "3",
          ...process.env,
          ...config?.env
        },
        stdio: isJsonMode() ? ["inherit", 2, 2] : "inherit"
      }).status ?? 0;
      checkResult(name, status, "error", shouldExitOnFail);
      totalStatus += status ?? 0;
    }
    return totalStatus;
  }, !!shouldExitOnFail);
};

// src/actions/packman/clean.ts
import {
  existsSync as existsSync5,
  rmSync,
  writeFileSync
} from "node:fs";
import PATH3 from "node:path";
import chalk6 from "chalk";

// src/actions/packman/convert.ts
import {
  existsSync as existsSync4,
  readdirSync,
  statSync
} from "node:fs";
import PATH2 from "node:path";
import chalk5 from "chalk";
var TARGET_PMS = ["bun", "npm", "pnpm", "yarn"];
function detectCurrentPM(cwd) {
  const packageManager = detectPackageManagerFromPackageJson(cwd);
  const target = TARGET_PMS.find((pm) => pm === packageManager);
  if (target) {
    return target;
  }
  if (existsSync4(PATH2.join(cwd, "pnpm-lock.yaml")) || existsSync4(PATH2.join(cwd, "pnpm-workspace.yaml"))) {
    return "pnpm";
  }
  if (existsSync4(PATH2.join(cwd, "bun.lock")) || existsSync4(PATH2.join(cwd, "bun.lockb"))) {
    return "bun";
  }
  if (existsSync4(PATH2.join(cwd, "yarn.lock")) || existsSync4(PATH2.join(cwd, ".yarnrc.yml"))) {
    return "yarn";
  }
  if (existsSync4(PATH2.join(cwd, "package-lock.json")) || existsSync4(PATH2.join(cwd, "npm-shrinkwrap.json"))) {
    return "npm";
  }
  return "unknown";
}
function findWorkspacePackagePaths(cwd) {
  const patterns = readWorkspacePatterns(cwd);
  const dirs = [];
  for (const pattern of patterns) {
    const resolved = resolveWorkspaceGlob(cwd, pattern);
    dirs.push(...resolved);
  }
  return dirs;
}
function resolveWorkspaceGlob(cwd, pattern) {
  const parts = pattern.split("/");
  return walkGlob(cwd, parts, "");
}
function walkGlob(basePath, parts, currentPath) {
  let remaining = parts;
  let path2 = currentPath;
  while (remaining.length > 0) {
    const [segment, ...rest2] = remaining;
    if (segment === "*" || segment === "**") {
      break;
    }
    path2 = path2 ? `${path2}/${segment}` : segment;
    remaining = rest2;
  }
  if (remaining.length === 0) {
    const fullPath = PATH2.join(basePath, path2);
    if (existsSync4(PATH2.join(fullPath, "package.json"))) {
      return [path2];
    }
    return [];
  }
  const [part, ...rest] = remaining;
  const dirPath = PATH2.join(basePath, path2);
  if (!existsSync4(dirPath) || !statSync(dirPath).isDirectory()) {
    return [];
  }
  if (part === "*" || part === "**") {
    const entries = readdirSync(dirPath, { withFileTypes: true }).filter((e) => e.isDirectory() && !e.name.startsWith(".") && e.name !== "node_modules" && e.name !== "dist");
    const results = [];
    if (part === "**") {
      results.push(...walkGlob(basePath, rest, path2));
    }
    for (const entry of entries) {
      const subPath = path2 ? `${path2}/${entry.name}` : entry.name;
      if (part === "**") {
        results.push(
          ...walkGlob(basePath, rest, subPath),
          ...walkGlob(basePath, remaining, subPath)
        );
      } else {
        results.push(...walkGlob(basePath, rest, subPath));
      }
    }
    return results;
  }
  return [];
}

// src/actions/packman/clean.ts
function shouldRemoveNodeModules(dir, isVerbose) {
  const nmPath = PATH3.join(dir, "node_modules");
  if (existsSync5(nmPath)) {
    if (isVerbose ?? false) console.log(chalk6.gray(`Removing ${nmPath}`));
    rmSync(nmPath, { force: true, recursive: true });
    return true;
  }
  return false;
}
function cleanLockFiles(cwd, pm) {
  switch (pm) {
    case "yarn": {
      const lockPath = PATH3.join(cwd, "yarn.lock");
      if (existsSync5(lockPath)) {
        writeFileSync(lockPath, "");
        console.log(chalk6.green("Truncated yarn.lock"));
      }
      break;
    }
    case "npm": {
      const lockPath = PATH3.join(cwd, "package-lock.json");
      if (existsSync5(lockPath)) {
        rmSync(lockPath);
        console.log(chalk6.green("Deleted package-lock.json"));
      }
      break;
    }
    case "bun": {
      for (const lockfile of ["bun.lock", "bun.lockb"]) {
        const lockPath = PATH3.join(cwd, lockfile);
        if (existsSync5(lockPath)) {
          rmSync(lockPath);
          console.log(chalk6.green(`Deleted ${lockfile}`));
        }
      }
      break;
    }
    case "pnpm": {
      const lockPath = PATH3.join(cwd, "pnpm-lock.yaml");
      if (existsSync5(lockPath)) {
        rmSync(lockPath);
        console.log(chalk6.green("Deleted pnpm-lock.yaml"));
      }
      break;
    }
  }
}
function packmanClean({ isVerbose }) {
  const cwd = process.cwd();
  const pm = detectCurrentPM(cwd);
  if (pm === "unknown") {
    console.error(chalk6.red("Could not detect current package manager. No packageManager field or known lockfile found."));
    return 1;
  }
  console.log(chalk6.blue(`Detected package manager: ${pm}`));
  let removedCount = 0;
  if (shouldRemoveNodeModules(cwd, isVerbose)) removedCount++;
  const workspacePaths = findWorkspacePackagePaths(cwd);
  for (const wsPath of workspacePaths) {
    if (shouldRemoveNodeModules(PATH3.join(cwd, wsPath), isVerbose)) removedCount++;
  }
  console.log(chalk6.green(`Removed ${removedCount} node_modules folder${removedCount === 1 ? "" : "s"}`));
  cleanLockFiles(cwd, pm);
  console.log(chalk6.green("Ready for a clean install"));
  return 0;
}

// src/actions/reinstall.ts
var reinstall = (isVerbose) => {
  const cleanResult = packmanClean({ isVerbose });
  if (cleanResult !== 0) return cleanResult;
  const pm = getPackageManager();
  return runSteps("Reinstall", [pm.install()]);
};
export {
  reinstall
};
//# sourceMappingURL=reinstall.mjs.map
