import { ChildProcess, spawn, StdioOptions } from 'child_process'; import { existsSync, mkdirSync } from 'fs'; import { rimraf } from 'rimraf'; import { Stream } from 'stream'; import { fileDescriptorFromStream, pathFromRoot } from './ActionUtilities'; export namespace Logger { const logPath = pathFromRoot('./logs'); export async function initialize() { if (existsSync(logPath)) { if (!process.env.SPAWNED) { await new Promise(resolve => { rimraf(logPath).then(resolve); }); } } mkdirSync(logPath); } function generateLogPath(command: string, args?: readonly string[]) { return pathFromRoot(`./logs/${command}-${args?.length}-${new Date().toUTCString()}.log`); } export async function create(command: string, args?: readonly string[]): Promise { return fileDescriptorFromStream(generateLogPath(command, args)); } } export namespace ProcessFactory { export type Sink = 'pipe' | 'ipc' | 'ignore' | 'inherit' | Stream | number | null | undefined; export async function createWorker(command: string, args?: readonly string[], stdio?: StdioOptions | 'logfile', detached = true): Promise { if (stdio === 'logfile') { const logFd = await Logger.create(command, args); // eslint-disable-next-line no-param-reassign stdio = ['ignore', logFd, logFd]; } const child = spawn(command, args ?? [], { detached, stdio }); child.unref(); return child; } }