Press n or j to go to the next uncovered block, b, p or k for the previous block.
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 | 1x 1x 1x | import childProcess from "child_process";
export type ChildProcess = childProcess.ChildProcess;
interface SpawnLogFns {
onLog?: (msg: string) => void;
onError?: (msg: string) => void;
}
const spawn = (
command: string,
args: string[],
options: childProcess.SpawnOptions,
{ onLog = () => {}, onError = () => {} }: SpawnLogFns,
) => {
let code = 0;
const child = childProcess.spawn(command, args, options);
// Ensure consistent encoding
child.stdout?.setEncoding("utf8");
child.stderr?.setEncoding("utf8");
let stdoutBuffer = "";
let stderrBuffer = "";
const processBuffer = (
buffer: string,
data: string,
cb: (line: string) => void,
): string => {
buffer += data;
const lines = buffer.split(/\r?\n/);
// Keep last partial line in buffer
const remainder = lines.pop() ?? "";
for (const line of lines) {
cb(line);
}
return remainder;
};
child.stdout?.on("data", (data: string) => {
stdoutBuffer = processBuffer(stdoutBuffer, data, onLog);
});
child.stderr?.on("data", (data: string) => {
stderrBuffer = processBuffer(stderrBuffer, data, onError);
});
child.on("error", (err) => {
onError(err.toString());
});
const completed = new Promise<void>((resolve, reject) => {
child.on("close", (childCode) => {
code = childCode ?? 0;
// Flush remaining buffered content
Iif (stdoutBuffer) onLog(stdoutBuffer);
Iif (stderrBuffer) onError(stderrBuffer);
if (code === 0) {
resolve();
} else {
reject(code);
}
});
});
return {
child,
completed,
};
};
export default spawn;
|