import { spawn } from "node:child_process";
async function runCommand(cmd, args, opts = {}) {
  return new Promise((resolve, reject) => {
    const spawnOpts = {
      cwd: opts.cwd,
      env: opts.env ?? process.env,
      stdio: ["ignore", "pipe", "pipe"]
    };
    let child;
    try {
      child = spawn(cmd, args, spawnOpts);
    } catch (err) {
      reject(err);
      return;
    }
    let stdout = "";
    let stderr = "";
    let stdoutBuf = "";
    let stderrBuf = "";
    let timedOut = false;
    const flushLines = (buf, stream) => {
      const parts = buf.split("\n");
      const tail = parts.pop() ?? "";
      for (const line of parts) {
        if (opts.onLine) opts.onLine(line, stream);
      }
      return tail;
    };
    child.stdout?.setEncoding("utf-8");
    child.stdout?.on("data", (chunk) => {
      stdout += chunk;
      stdoutBuf = flushLines(stdoutBuf + chunk, "stdout");
    });
    child.stderr?.setEncoding("utf-8");
    child.stderr?.on("data", (chunk) => {
      stderr += chunk;
      stderrBuf = flushLines(stderrBuf + chunk, "stderr");
    });
    let timer = null;
    if (opts.timeout && opts.timeout > 0) {
      timer = setTimeout(() => {
        timedOut = true;
        child.kill("SIGTERM");
        setTimeout(() => {
          try {
            child.kill("SIGKILL");
          } catch {
          }
        }, 2e3).unref();
      }, opts.timeout);
    }
    child.on("error", (err) => {
      if (timer) clearTimeout(timer);
      reject(err);
    });
    child.on("close", (code) => {
      if (timer) clearTimeout(timer);
      if (stdoutBuf && opts.onLine) opts.onLine(stdoutBuf, "stdout");
      if (stderrBuf && opts.onLine) opts.onLine(stderrBuf, "stderr");
      resolve({
        code: code ?? (timedOut ? -1 : 1),
        stdout,
        stderr,
        timedOut
      });
    });
  });
}
export {
  runCommand
};
//# sourceMappingURL=run-command.js.map