Files
SubMiner/launcher/test-support/exit-intercept.ts
T

48 lines
1.4 KiB
TypeScript

export class ExitSignal extends Error {
code: number;
stderr: string;
constructor(code: number, stderr: string) {
super(`exit:${code}`);
this.code = code;
this.stderr = stderr;
}
}
function stderrChunkToString(chunk: string | Uint8Array, encoding?: BufferEncoding): string {
if (typeof chunk === 'string') return chunk;
return Buffer.from(chunk).toString(encoding);
}
export function withProcessExitIntercept(callback: () => void): ExitSignal {
const originalExit = process.exit;
const originalStderrWrite = process.stderr.write;
let stderr = '';
try {
process.stderr.write = ((chunk: string | Uint8Array, ...args: unknown[]) => {
const encoding = typeof args[0] === 'string' ? (args[0] as BufferEncoding) : undefined;
stderr += stderrChunkToString(chunk, encoding);
const writeCallback = args.find((arg): arg is (error?: Error | null) => void => {
return typeof arg === 'function';
});
writeCallback?.();
return true;
}) as typeof process.stderr.write;
process.exit = ((code?: number) => {
throw new ExitSignal(code ?? 0, stderr);
}) as typeof process.exit;
callback();
} catch (error) {
if (error instanceof ExitSignal) {
return error;
}
throw error;
} finally {
process.stderr.write = originalStderrWrite;
process.exit = originalExit;
}
throw new Error('expected process.exit');
}