53 lines
1.7 KiB
JavaScript
53 lines
1.7 KiB
JavaScript
|
|
import {spawn} from 'node:child_process';
|
||
|
|
import {merge} from 'lodash-es';
|
||
|
|
import {bold, dim} from 'colorette';
|
||
|
|
|
||
|
|
import {default as mergePromise} from './merge-promise.js';
|
||
|
|
|
||
|
|
import Debug from 'debug';
|
||
|
|
|
||
|
|
export default function(defaults = {}) {
|
||
|
|
return function(command, args = [], options = {}, stdout = '', stderr = '') {
|
||
|
|
// @TODO: error handling?
|
||
|
|
// merge our options over the defaults
|
||
|
|
options = merge({debug: Debug('@lando/run-command'), ignoreReturnCode: false, env: process.env}, defaults, options); // eslint-disable-line
|
||
|
|
const {debug} = options;
|
||
|
|
|
||
|
|
// birth
|
||
|
|
debug('running command %o %o from %o', command, args, options?.cwd ?? process.cwd());
|
||
|
|
const child = spawn(command, args, options);
|
||
|
|
|
||
|
|
return mergePromise(child, async () => {
|
||
|
|
return new Promise((resolve, reject) => {
|
||
|
|
child.on('error', error => {
|
||
|
|
debug('command %o error %o', command, error?.message);
|
||
|
|
stderr += error?.message ?? error;
|
||
|
|
});
|
||
|
|
|
||
|
|
child.stdout.on('data', data => {
|
||
|
|
debug('%s %s', bold('stdout'), dim(data.toString().trim()));
|
||
|
|
stdout += data;
|
||
|
|
});
|
||
|
|
|
||
|
|
child.stderr.on('data', data => {
|
||
|
|
debug('%s %s', bold('stderr'), dim(data.toString().trim()));
|
||
|
|
stderr += data;
|
||
|
|
});
|
||
|
|
|
||
|
|
child.on('close', code => {
|
||
|
|
debug('command %o done with code %o', command, code);
|
||
|
|
// if code is non-zero and we arent ignoring then reject here
|
||
|
|
if (code !== 0 && !options.ignoreReturnCode) {
|
||
|
|
const error = new Error(stderr);
|
||
|
|
error.code = code;
|
||
|
|
reject(error);
|
||
|
|
}
|
||
|
|
|
||
|
|
// otherwise return
|
||
|
|
resolve({stdout, stderr, code});
|
||
|
|
});
|
||
|
|
});
|
||
|
|
});
|
||
|
|
};
|
||
|
|
};
|