@plugjs/plug
Version:
PlugJS Build System ===================
79 lines (78 loc) • 2.9 kB
JavaScript
// 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