shAsync

tcmts.dev.shAsync · #3cpvtwt2 · term · runs on the server

uses node:child_process

sh, without waiting: run a program, resolving with whether it passed and what it printed, so several can run side by side. onLine hears each line as it's printed.

import { spawn } from "node:child_process";

export function shAsync(
  program: string,
  args: string[],
  cwd: string,
  env: NodeJS.ProcessEnv = {},
  onLine?: (line: string) => void,
): Promise<{ ok: boolean; out: string }> {
  return new Promise((resolve) => {
    const child = spawn(program, args, {
      cwd,
      env: { ...process.env, NO_COLOR: "1", FORCE_COLOR: "0", ...env },
    });
    let out = "";
    let partial = "";
    const heard = (d: string) => {
      out += d;
      if (!onLine) return;
      const lines = (partial + d).split("\n");
      partial = lines.pop()!;
      for (const l of lines) onLine(l);
    };
    child.stdout.setEncoding("utf8").on("data", heard);
    child.stderr.setEncoding("utf8").on("data", heard);
    child.on("error", (e) => (out += String(e)));
    child.on("close", (code) => resolve({ ok: code === 0, out }));
  });
}

used by