runscript
Version:
Run script easy!
175 lines • 14.4 kB
JavaScript
;
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.runscript = exports.RunScriptTimeoutError = exports.RunScriptError = void 0;
exports.runScript = runScript;
const node_util_1 = require("node:util");
const node_assert_1 = __importDefault(require("node:assert"));
const node_path_1 = __importDefault(require("node:path"));
const node_child_process_1 = require("node:child_process");
const is_type_of_1 = require("is-type-of");
const debug = (0, node_util_1.debuglog)('runscript');
function isCmd() {
if (process.platform !== 'win32') {
return false;
}
try {
const result = (0, node_child_process_1.spawnSync)('ls', {
stdio: 'pipe',
});
return result.error !== undefined;
}
catch (err) {
return true;
}
}
class RunScriptError extends Error {
stdio;
exitcode;
constructor(message, stdio, exitcode, options) {
super(message, options);
this.name = this.constructor.name;
this.stdio = stdio;
this.exitcode = exitcode;
Error.captureStackTrace(this, this.constructor);
}
}
exports.RunScriptError = RunScriptError;
class RunScriptTimeoutError extends Error {
stdio;
timeout;
constructor(message, stdio, timeout, options) {
super(message, options);
this.name = this.constructor.name;
this.stdio = stdio;
this.timeout = timeout;
Error.captureStackTrace(this, this.constructor);
}
}
exports.RunScriptTimeoutError = RunScriptTimeoutError;
/**
* Run shell script in child process
* Support OSX, Linux and Windows
* @param {String} script - full script string, like `git clone https://github.com/node-modules/runscript.git`
* @param {Object} [options] - spawn options
* @see https://nodejs.org/api/child_process.html#child_process_child_process_spawn_command_args_options
* @param {Object} [extraOptions] - extra options for running
* - {Number} [extraOptions.timeout] - child process running timeout
* @return {Object} stdio object, will contains stdio.stdout and stdio.stderr buffer.
*/
function runScript(script, options = {}, extraOptions = {}) {
return new Promise((resolve, reject) => {
options.env = options.env || Object.assign({}, process.env);
options.cwd = options.cwd || process.cwd();
if (typeof options.cwd === 'object') {
// convert URL object to string
options.cwd = String(options.cwd);
}
options.stdio = options.stdio || 'inherit';
if (options.stdout) {
(0, node_assert_1.default)((0, is_type_of_1.isWritable)(options.stdout), 'options.stdout should be writable stream');
}
if (options.stderr) {
(0, node_assert_1.default)((0, is_type_of_1.isWritable)(options.stderr), 'options.stderr should be writable stream');
}
let sh = 'sh';
let shFlag = '-c';
if (process.platform === 'win32') {
sh = process.env.comspec || 'cmd';
shFlag = '/d /s /c';
options.windowsVerbatimArguments = true;
if (script.indexOf('./') === 0 || script.indexOf('.\\') === 0 ||
script.indexOf('../') === 0 || script.indexOf('..\\') === 0) {
const splits = script.split(' ');
// in bash C:\Windows\system32 -> C:\\Windows\\system32
splits[0] = node_path_1.default.join(isCmd() ? options.cwd : node_path_1.default.normalize(options.cwd), splits[0]);
script = splits.join(' ');
}
}
debug('%s %s %s, %j, %j', sh, shFlag, script, options, extraOptions);
const proc = (0, node_child_process_1.spawn)(sh, [shFlag, script], options);
const stdout = [];
const stderr = [];
let isEnd = false;
let timeoutTimer;
if (proc.stdout) {
proc.stdout.on('data', (buf) => {
debug('stdout %d bytes', buf.length);
stdout.push(buf);
});
if (options.stdout) {
proc.stdout.pipe(options.stdout);
}
}
if (proc.stderr) {
proc.stderr.on('data', (buf) => {
debug('stderr %d bytes', buf.length);
stderr.push(buf);
});
if (options.stderr) {
proc.stderr.pipe(options.stderr);
}
}
proc.on('error', err => {
debug('proc emit error: %s', err);
if (isEnd) {
return;
}
isEnd = true;
clearTimeout(timeoutTimer);
reject(err);
});
proc.on('exit', code => {
debug('proc emit exit: %s', code);
if (isEnd) {
return;
}
isEnd = true;
clearTimeout(timeoutTimer);
const stdio = {
stdout: null,
stderr: null,
};
if (stdout.length > 0) {
stdio.stdout = Buffer.concat(stdout);
}
if (stderr.length > 0) {
stdio.stderr = Buffer.concat(stderr);
}
if (code !== 0) {
const err = new RunScriptError(`Run "${sh} ${shFlag} ${script}" error, exit code ${code}`, stdio, code);
return reject(err);
}
return resolve(stdio);
});
proc.on('close', code => {
debug('proc emit close: %s', code);
});
if (typeof extraOptions.timeout === 'number' && extraOptions.timeout > 0) {
const timeout = extraOptions.timeout;
// start timer
timeoutTimer = setTimeout(() => {
debug('proc run timeout: %dms', timeout);
isEnd = true;
debug('kill child process %s', proc.pid);
proc.kill();
const stdio = {
stdout: null,
stderr: null,
};
if (stdout.length > 0) {
stdio.stdout = Buffer.concat(stdout);
}
if (stderr.length > 0) {
stdio.stderr = Buffer.concat(stderr);
}
const err = new RunScriptTimeoutError(`Run "${sh} ${shFlag} ${script}" timeout in ${extraOptions.timeout}ms`, stdio, timeout);
return reject(err);
}, timeout);
}
});
}
exports.runscript = runScript;
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi9zcmMvaW5kZXgudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7Ozs7O0FBK0VBLDhCQTRIQztBQTNNRCx5Q0FBcUM7QUFDckMsOERBQWlDO0FBQ2pDLDBEQUE2QjtBQUM3QiwyREFBeUU7QUFFekUsMkNBQXdDO0FBRXhDLE1BQU0sS0FBSyxHQUFHLElBQUEsb0JBQVEsRUFBQyxXQUFXLENBQUMsQ0FBQztBQUVwQyxTQUFTLEtBQUs7SUFDWixJQUFJLE9BQU8sQ0FBQyxRQUFRLEtBQUssT0FBTyxFQUFFLENBQUM7UUFDakMsT0FBTyxLQUFLLENBQUM7SUFDZixDQUFDO0lBRUQsSUFBSSxDQUFDO1FBQ0gsTUFBTSxNQUFNLEdBQUcsSUFBQSw4QkFBUyxFQUFDLElBQUksRUFBRTtZQUM3QixLQUFLLEVBQUUsTUFBTTtTQUNkLENBQUMsQ0FBQztRQUVILE9BQU8sTUFBTSxDQUFDLEtBQUssS0FBSyxTQUFTLENBQUM7SUFDcEMsQ0FBQztJQUFDLE9BQU8sR0FBRyxFQUFFLENBQUM7UUFDYixPQUFPLElBQUksQ0FBQztJQUNkLENBQUM7QUFDSCxDQUFDO0FBb0JELE1BQWEsY0FBZSxTQUFRLEtBQUs7SUFDdkMsS0FBSyxDQUFRO0lBQ2IsUUFBUSxDQUFnQjtJQUV4QixZQUFZLE9BQWUsRUFBRSxLQUFZLEVBQUUsUUFBdUIsRUFBRSxPQUFzQjtRQUN4RixLQUFLLENBQUMsT0FBTyxFQUFFLE9BQU8sQ0FBQyxDQUFDO1FBQ3hCLElBQUksQ0FBQyxJQUFJLEdBQUcsSUFBSSxDQUFDLFdBQVcsQ0FBQyxJQUFJLENBQUM7UUFDbEMsSUFBSSxDQUFDLEtBQUssR0FBRyxLQUFLLENBQUM7UUFDbkIsSUFBSSxDQUFDLFFBQVEsR0FBRyxRQUFRLENBQUM7UUFDekIsS0FBSyxDQUFDLGlCQUFpQixDQUFDLElBQUksRUFBRSxJQUFJLENBQUMsV0FBVyxDQUFDLENBQUM7SUFDbEQsQ0FBQztDQUNGO0FB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