import { ChildProcessWithoutNullStreams, spawn } from "child_process"; import Emittery from "emittery"; export default function simpleSpawn( cmd: string, arg: string[] ): Promise<{ stdout: string; stderr: string }> { const process = spawn(cmd, arg); let output = ""; let err = ""; return new Promise((resolve, reject) => { process.on("close", (code) => { code === 0 ? resolve({ stdout: output, stderr: err }) : reject(err); }); process.stdout.on("data", (data) => (output += data.toString("utf-8"))); process.stderr.on("data", (data) => (err += data.toString("utf-8"))); }); } export class DeferedSpawn extends Emittery { constructor(private process: ChildProcessWithoutNullStreams) { super(); this.on("data", (data) => console.log("data", data.toString())); } async waitForAnswer(): Promise { return new Promise((resolve, reject) => { this.on("success", (data) => { resolve(data); }); this.on("error", reject); }); } async waitForNextData(): Promise { console.log( "waiting for next data from",, this.process.spawnargs.join(" ") ); return new Promise((resolve, reject) => { this.on("data", (data) => { console.log("got answer from process", this.process.spawnfile); resolve(data.toString("utf-8")); }); this.on("error", (err) => { console.error("Rejecting from process", this.process.spawnfile, err); reject(err); }); this.on("end", () => resolve(null)); }); } kill() { console.log("killing process!", this.process.spawnargs.join(" ")); process.kill(-this.process.pid); // https://stackoverflow.com/a/49842576 } write(data: string) { this.process.stdin.write(data); } } export function deferedSpawn( cmd: string, arg: string[] ): Promise { const process = spawn(cmd, arg, { detached: true }); let spawned = false; let output = ""; let err = ""; const emitter = new DeferedSpawn(process); return new Promise((resolve, reject) => { process.stdout.on("data", (data) => { output += data.toString("utf-8"); emitter.emit("data", data); }); process.stderr.on("data", (data) => { err += data.toString("utf-8"); }); process.on("spawn", () => { resolve(emitter); }); process.on("close", (code) => { if (!spawned) { reject(err); } else { console.log("!!!!!!!!!!!!!!!!!!!! PROCESS CLOSED"); if (code === 0) { emitter.emit("success", output); } else { emitter.emit("error", err); } emitter.emit("end", { err, output }); } }); }); }