gulp-spawn
Version:
spawn plugin for gulp
100 lines (84 loc) • 2.43 kB
JavaScript
import cp from 'node:child_process';
import path from 'node:path';
import Stream from 'node:stream';
import {Buffer} from 'node:buffer';
import Duplexer from 'plexer';
import PluginError from 'plugin-error';
const PLUGIN_NAME = 'gulp-spawn';
export default function gulpSpawn(options) {
const stream = new Stream.PassThrough({objectMode: true});
// Options.cmd required
if (!options.cmd) {
throw new PluginError(PLUGIN_NAME, 'command ("cmd") argument required');
}
stream._transform = function (file, unused, cb) {
if (file.isNull()) {
stream.push(file);
return cb();
}
// Rename file if optional `filename` function specified
if (options.filename && typeof options.filename === 'function') {
const dir = path.dirname(file.path);
const ext = path.extname(file.path);
const base = path.basename(file.path, ext);
file.shortened = options.filename(base, ext);
file.path = path.join(dir, file.shortened);
}
// Spawn program
const program = cp.spawn(options.cmd, options.args, options.opts);
// Listen to stderr and emit errors if any
let errorBuffer = Buffer.alloc(0);
program.stderr.on('readable', () => {
let chunk;
while ((chunk = program.stderr.read())) {
errorBuffer = Buffer.concat(
[ ],
errorBuffer.length + chunk.length,
);
}
});
program.stderr.on('end', () => {
if (errorBuffer.length > 0) {
stream.emit(
'error',
new PluginError(PLUGIN_NAME, errorBuffer.toString('utf8')),
);
}
});
// Check if we have a buffer or stream
if (file.contents instanceof Buffer) {
// Create buffer
let newBuffer = Buffer.alloc(0);
// When program receives data add it to buffer
program.stdout.on('readable', () => {
let chunk;
while ((chunk = program.stdout.read())) {
newBuffer = Buffer.concat(
[ ],
newBuffer.length + chunk.length,
);
}
});
// When program finishes call callback
program.stdout.on('end', () => {
file.contents = newBuffer;
stream.push(file);
cb();
});
// "execute"
// write file buffer to program
program.stdin.write(file.contents, () => {
program.stdin.end();
});
} else {
// Assume we have a stream.Readable
// stream away!
file.contents = file.contents.pipe(
new Duplexer(program.stdin, program.stdout),
);
stream.push(file);
cb();
}
};
return stream;
}