// src/xy/xyParseOptions.ts
import { availableParallelism } from "node:os";
import chalk3 from "chalk";
import yargs from "yargs";
import { hideBin } from "yargs/helpers";

// 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 chalk 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(chalk.yellow(`${DISPLAY_NAMES[plan.packageManager]} is required for "${context.operation}".`));
  for (const line of plan.manualInstructions) {
    console.error(chalk.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(chalk.yellow(`${context.operation} requires ${displayName}, but it is not installed.`));
  if (!plan.supported) {
    printManualInstructions(plan, context);
    return false;
  }
  if (!isCommandInstalled("brew")) {
    console.error(chalk.yellow("Homebrew is not installed, so automatic installation is unavailable."));
    console.error(chalk.gray("  Install Homebrew from https://brew.sh and then run:"));
    console.error(chalk.gray(`  ${plan.command}`));
    return false;
  }
  const isConfirmed = shouldAskYesNo(chalk.cyan(`Install ${displayName} with Homebrew now? [y/N] `));
  if (!isConfirmed) {
    console.error(chalk.gray(`Skipping install. Run "${plan.command}" manually and then retry.`));
    return false;
  }
  console.error(chalk.cyan(`Installing ${displayName} via Homebrew...
`));
  if (!shouldInstallWithHomebrew(pm, context.cwd)) {
    console.error(chalk.red(`Homebrew failed to install ${displayName}.`));
    console.error(chalk.gray(`Run "${plan.command}" manually and then retry.`));
    return false;
  }
  if (!isPackageManagerInstalled(pm)) {
    console.error(chalk.red(`${displayName} still does not appear to be installed after Homebrew completed.`));
    console.error(chalk.gray(`Run "${plan.command}" manually and then retry.`));
    return false;
  }
  console.error(chalk.green(`${displayName} installed successfully.`));
  return true;
}
function failureResult() {
  return {
    output: ["", ""],
    pid: 0,
    signal: null,
    status: 1,
    stderr: "",
    stdout: ""
  };
}
function spawnPackageManagerSync(pm, args, options) {
  if (!didEnsurePackageManagerInstalled(pm, options.context)) {
    return failureResult();
  }
  return spawnSync(pm, args, { encoding: "utf8", ...options });
}

// 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 != 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/reporting/xyReporter.ts
import { performance } from "node:perf_hooks";
var reporterState = {
  currentCommand: "unknown",
  isEnvelopeEmitted: false,
  isJsonModeEnabled: false,
  isStrictModeEnabled: false,
  originalStdoutWrite: void 0,
  startTime: 0
};
function setJsonMode(isEnabled) {
  if (reporterState.isJsonModeEnabled === isEnabled) return;
  reporterState.isJsonModeEnabled = isEnabled;
  if (isEnabled && !reporterState.originalStdoutWrite) {
    reporterState.originalStdoutWrite = process.stdout.write.bind(process.stdout);
    const stderrWrite = process.stderr.write.bind(process.stderr);
    process.stdout.write = stderrWrite;
    process.on("exit", emitFallbackEnvelope);
  }
}
function setStrictMode(isEnabled) {
  reporterState.isStrictModeEnabled = isEnabled;
  if (isEnabled) {
    process.env.XY_STRICT = "1";
  }
}
function emitJson(envelope) {
  if (reporterState.isEnvelopeEmitted) return;
  reporterState.isEnvelopeEmitted = true;
  const json = JSON.stringify(envelope) + "\n";
  if (reporterState.originalStdoutWrite) {
    reporterState.originalStdoutWrite(json);
  } else {
    process.stdout.write(json);
  }
}
function emitFallbackEnvelope() {
  if (reporterState.isEnvelopeEmitted) return;
  const raw = process.exitCode ?? 0;
  const code = typeof raw === "number" ? raw : Number(raw) || 0;
  emitJson({
    command: reporterState.currentCommand,
    durationMs: Math.round(performance.now() - reporterState.startTime),
    errorCount: code === 0 ? 0 : 1,
    exitCode: code,
    schemaVersion: 1,
    success: code === 0,
    warningCount: 0
  });
}

// src/lib/tryRunLocalScript.ts
import { readFileSync as readFileSync2 } from "node:fs";
import PATH2 from "node:path";
import chalk2 from "chalk";
function tryRunLocalScript(commandName) {
  if (process.env.XY_LOCAL_SCRIPT === "1") return void 0;
  const rootPkgPath = PATH2.resolve(process.cwd(), "package.json");
  let rootPkg;
  try {
    rootPkg = JSON.parse(readFileSync2(rootPkgPath, "utf8"));
  } catch {
    return void 0;
  }
  if (!rootPkg.scripts || !Object.hasOwn(rootPkg.scripts, commandName)) return void 0;
  const extraArgs = process.argv.slice(process.argv.indexOf(commandName) + 1);
  console.log(chalk2.blue(`Delegating "${commandName}" to local script`));
  const pm = getPackageManager();
  const result = spawnPackageManagerSync(pm.name, ["run", commandName, ...extraArgs], {
    cwd: process.cwd(),
    context: { operation: `Run local "${commandName}" script with ${pm.command}` },
    encoding: "utf8",
    env: {
      FORCE_COLOR: "3",
      ...process.env,
      XY_LOCAL_SCRIPT: "1"
    },
    stdio: "inherit"
  });
  return result.status ?? 1;
}

// src/xy/xyParseOptions.ts
function scriptNameForPackageManager() {
  switch (detectPackageManager()) {
    case "bun": {
      return "bun run xy";
    }
    case "npm": {
      return "npm exec -- xy";
    }
    case "pnpm": {
      return "pnpm xy";
    }
    default: {
      return "yarn xy";
    }
  }
}
function formatDuration(ms) {
  if (ms < 1e3) return `${ms}ms`;
  if (ms < 6e4) return `${(ms / 1e3).toFixed(2)}s`;
  const minutes = Math.floor(ms / 6e4);
  const seconds = (ms % 6e4 / 1e3).toFixed(1);
  return `${minutes}m ${seconds}s`;
}
var xyParseOptions = () => {
  let isTimerRegistered = false;
  return yargs(hideBin(process.argv)).scriptName(process.env.SCRIPT_NAME ?? scriptNameForPackageManager()).middleware((argv) => {
    if (Boolean(argv.json)) setJsonMode(true);
    if (Boolean(argv.strict) || process.env.XY_STRICT === "1") setStrictMode(true);
  }, true).middleware((argv) => {
    if (process.argv.includes("--no-defer") || process.env.XY_NO_DEFER === "1") return;
    const commandName = argv._[0];
    if (commandName && argv._.length <= 1) {
      const result = tryRunLocalScript(commandName);
      if (result !== void 0) {
        process.exit(result);
      }
    }
  }, true).middleware((argv) => {
    if (isTimerRegistered) return;
    isTimerRegistered = true;
    if (Boolean(argv.json)) return;
    const commandName = argv._[0];
    const jobs = argv.jobs;
    const label = commandName != null && commandName.length > 0 ? ` [${chalk3.white(commandName)}]` : "";
    console.log(
      chalk3.blue("\u2B21 XY") + label + chalk3.gray(` [threads: ${jobs}]`)
    );
    const start = Date.now();
    process.on("exit", () => {
      const whiteCommand = commandName != null && commandName.length > 0 ? chalk3.white(commandName) : void 0;
      const exitLabel = whiteCommand != null && whiteCommand.length > 0 ? ` [${whiteCommand}]` : "";
      const duration = formatDuration(Date.now() - start);
      console.log(chalk3.blue(`Finished${exitLabel} in ${duration}`));
    });
  }, true).option("jobs", {
    alias: "j",
    default: availableParallelism(),
    description: "Max parallel jobs",
    type: "number"
  }).option("verbose", {
    alias: "v",
    default: false,
    description: "Run with verbose logging",
    type: "boolean"
  }).option("incremental", {
    alias: "i",
    description: "Attempt to perform the action only on changed packages",
    type: "boolean"
  }).option("profile", {
    alias: "p",
    default: false,
    description: "Profile action",
    type: "boolean"
  }).option("json", {
    default: false,
    description: "Emit machine-readable JSON to stdout; suppress decorative output",
    type: "boolean"
  }).option("no-defer", {
    default: false,
    description: "Do not defer to local package.json script of the same name",
    type: "boolean"
  }).option("strict", {
    default: false,
    description: "Treat warnings as errors (exit code = errorCount + warningCount)",
    type: "boolean"
  });
};
export {
  xyParseOptions
};
//# sourceMappingURL=xyParseOptions.mjs.map
