UNPKG

@plugjs/plug

Version:
79 lines (78 loc) 2.9 kB
// utils/exec.ts import { spawn } from "node:child_process"; import path from "node:path"; import readline from "node:readline"; import { assert, BuildFailure } from "../asserts.mjs"; import { $p, logOptions } from "../logging.mjs"; import { getCurrentWorkingDirectory, resolveDirectory } from "../paths.mjs"; async function execChild(cmd, args, options = {}, context) { const { env = {}, // default empty environment shell = false, // by default do not use a shell cwd = void 0, // by default use "process.cwd()" coverageDir, // default "undefined" (pass throug from env) ...extraOptions } = options; const childCwd = cwd ? context.resolve(cwd) : getCurrentWorkingDirectory(); assert(resolveDirectory(childCwd), `Current working directory ${$p(childCwd)} does not exist`); const childPaths = []; const baseNodePath = context.resolve("@node_modules", ".bin"); if (resolveDirectory(baseNodePath)) childPaths.push(baseNodePath); const buildNodePath = context.resolve("./node_modules", ".bin"); if (resolveDirectory(buildNodePath)) childPaths.push(buildNodePath); const extraPath = env.PATH || process.env.PATH; if (extraPath) childPaths.push(extraPath); const PATH = childPaths.join(path.delimiter); const childEnv = { ...process.env, // environment from current running process ...env, // environment configured from "execChild" arguments ...logOptions.forkEnv(), // forked log options for child plugjs PATH // path with all ".../node_modules/.bin" directories }; if (coverageDir) childEnv.NODE_V8_COVERAGE = context.resolve(coverageDir); const childOptions = { ...extraOptions, stdio: ["ignore", "pipe", "pipe"], cwd: childCwd, env: childEnv, shell }; context.log.info("Executing", [cmd, ...args]); context.log.debug("Child process options", childOptions); const child = spawn(cmd, args, childOptions); try { context.log.info("Child process PID", child.pid); if (child.stdout) { const out = readline.createInterface(child.stdout); out.on("line", (line) => context.log.notice(line || "\xA0")); } if (child.stderr) { const err = readline.createInterface(child.stderr); err.on("line", (line) => context.log.warn(line || "\xA0")); } } catch (error) { child.kill(); throw error; } return new Promise((resolve, reject) => { child.on("error", (error) => reject(error)); child.on("exit", (code, signal) => { if (code === 0) return resolve(); if (signal) return reject(BuildFailure.withMessage(`Child process exited with signal ${signal}`)); if (code) return reject(BuildFailure.withMessage(`Child process exited with code ${code}`)); reject(BuildFailure.withMessage("Child process failed for an unknown reason")); }); }); } export { execChild }; //# sourceMappingURL=exec.mjs.map