UNPKG

turbo-gulp

Version:

Gulp tasks to boost high-quality projects.

108 lines (107 loc) 3.89 kB
import { execFile as _execFile, spawn as _spawn, } from "child_process"; import * as fs from "fs"; import { Incident } from "incident"; import { PassThrough } from "stream"; import { promisify } from "util"; function asBuffer(val) { return val instanceof Buffer ? val : new Buffer(val, "utf8"); } export class ExecFileError extends Incident { constructor(nativeError, stdout, stderr) { const data = { cmd: nativeError.cmd, killed: nativeError.killed, code: nativeError.code, signal: nativeError.signal, stdout: asBuffer(stdout), stderr: asBuffer(stderr), }; const message = `An error occured during the execution of: ${data.cmd}\n${nativeError.stack}`; super(nativeError, "ExecFileError", data, message); } } const _readFile = promisify(fs.readFile); const _writeFile = promisify(fs.writeFile); export async function readText(file) { return _readFile(file, "utf8"); } export async function writeText(file, text) { return _writeFile(file, text); } export async function execFile(file, args, options) { return new Promise((resolve, reject) => { const normalizedOptions = Object.assign({}, options, { encoding: "buffer" }); _execFile(file, args, normalizedOptions, (error, stdout, stderr) => { if (error !== null) { reject(new ExecFileError(error, stdout, stderr)); return; } const result = { stdout: asBuffer(stdout), stderr: asBuffer(stderr), }; resolve(result); }); }); } export class SpawnedProcess { constructor(file, args, options) { this.stdoutChunks = []; this.stderrChunks = []; this.exit = undefined; const detached = options.detached !== undefined ? options.detached : false; this.process = _spawn(file, args, { stdio: [process.stdin, "pipe", "pipe"], cwd: options.cwd, env: options.env, detached }); const stdout = new PassThrough(); this.process.stdout.pipe(stdout); const stderr = new PassThrough(); this.process.stderr.pipe(stderr); if (options.stdio === "inherit") { stdout.pipe(process.stdout); stderr.pipe(process.stderr); } stdout.on("data", (chunk) => { this.stdoutChunks.push(chunk); }); stderr.on("data", (chunk) => { this.stderrChunks.push(chunk); }); this.process.once("exit", (code, signal) => { if (code !== null) { this.exit = { type: "code", code }; } else { this.exit = { type: "signal", signal: signal }; } }); } async toPromise() { return new Promise((resolve, reject) => { if (this.exit !== undefined) { const [stdout, stderr] = this.getBuffers(); resolve({ stdout, stderr, exit: this.exit }); } else { this.process.once("exit", (code, signal) => { let exit; if (code !== null) { exit = { type: "code", code }; } else { exit = { type: "signal", signal: signal }; } const [stdout, stderr] = this.getBuffers(); resolve({ stdout, stderr, exit }); }); } }); } getBuffers() { const stdout = Buffer.concat(this.stdoutChunks); const stderr = Buffer.concat(this.stderrChunks); this.stdoutChunks.length = 0; this.stderrChunks.length = 0; this.stdoutChunks.push(stdout); this.stderrChunks.push(stderr); return [stdout, stderr]; } }