The code utilizes the child_process
and importer
modules to execute external Bash commands and handle errors, with functions such as bashToExec
and execCmd
to prepare and run the commands. The execCmd
function creates a promise that resolves with the output of the executed command and logs the command and its output if not in quiet mode.
npm run import -- "spawn child process"
var {exec} = require('child_process');
var path = require('path');
var importer = require('../Core');
var multiline = process.platform === 'win32' ? '^\n ' : '\\\n ';
var multicmd = process.platform === 'win32' ? ' ^\n&& ' : ' \\\n&& ';
// read cmd template and execute each line?
function bashToExec(code) {
return code
.split(/\n/ig)
.map(l => '{EXEC} ' + l)
.join('\n')
.replace(/\\((\s*\n)+\{EXEC\})+\s*&&/ig, multicmd)
.replace(/\\((\s*\n)+\{EXEC\})+\s*/ig, multiline);
}
function execCmd(script, options) {
if(typeof options == 'undefined') options = {}
// TODO: fix current working directory matching project name in the cwd: option
// add some run commands to the bash script
return importer.runAllPromises(
bashToExec(script)
.split(/\s*\{EXEC\}\s*/ig)
.filter(r => r.trim() !== '')
.map(r => (resolve, reject) => {
if(!options.quiet) console.log('spawning process ' + r)
const ps = exec(r.replace(/\$[0-9]+/ig, i => process.argv[parseInt(i.substr(1))+1] || ''), Object.assign(options || {}, {maxBuffer: 1024 * 50000}), (err, result) => {
if (err) {
return reject(err);
}
return resolve(result);
});
let errors = '';
let data = '';
ps.stderr.on('data', d => {
if(!options.quiet) console.error(d);
data += d;
});
ps.stdout.on('data', d => {
if(!options.quiet) console.log(d);
errors += d;
});
ps.on('exit', (code, signal) => {
if(code > 0) {
const err = new Error(`child process exited with code ${code} and signal ${signal}`);
err.data = data + errors;
reject(err);
}
});
})
);
};
module.exports = execCmd;
// "test": "concurrently --kill-others --success first \"mocha **/*.spec.js\" \"node ./zuora-eloqua-express-mock.js\" ",
const { spawn } = require('child_process');
const path = require('path');
const { runAllPromises } = require('../Core');
const MULTILINE = process.platform === 'win32'? '^\n': '\\\n ';
const MULTICMD = process.platform === 'win32'?'^\n&&':'\\\n&& ';
function bashToExec(code) {
return code
.split('\n')
.map((line) => ({ type: 'line', content: line }))
.map((line) => ({ type: 'cmd', content: `{EXEC} ${line.content}` }));
}
function resolveVariables(script) {
return script
.split(/\n/)
.map((line) => ({ type: 'line', content: line }))
.map((line) => {
const variables = line.content.match(/\$([0-9]+)/g);
if (variables) {
variables.forEach((variable) => {
line.content = line.content.replace(variable, process.argv[parseInt(variable.substr(1)) + 1] || '');
});
}
return line;
})
.map((line) => line.content)
.join('\n');
}
function execCmd(script, options = {}) {
const commands = bashToExec(script)
.map((cmd) => cmd.content)
.filter((cmd) => cmd.trim()!== '');
const promises = commands.map((cmd) => {
const command = resolveVariables(cmd);
if (!options.quiet) console.log(`spawning process: ${command}`);
return new Promise((resolve, reject) => {
const childProcess = spawn(command, {
maxBuffer: 1024 * 50000,
});
let errors = '';
let data = '';
childProcess.stderr.on('data', (d) => {
if (!options.quiet) console.error(d);
data += d;
});
childProcess.stdout.on('data', (d) => {
if (!options.quiet) console.log(d);
errors += d;
});
childProcess.on('exit', (code, signal) => {
if (code > 0) {
const error = new Error(`child process exited with code ${code} and signal ${signal}`);
error.data = data + errors;
reject(error);
} else {
resolve(data);
}
});
});
});
return runAllPromises(promises).catch((err) => {
if (err.data) console.error(err.data);
throw err;
});
}
module.exports = execCmd;
Code Breakdown
The code requires the following modules:
child_process
for executing external commandspath
(not used in this code snippet)importer
(a custom module, likely for running commands)Variables are defined:
multiline
and multicmd
for handling shell commands on different platforms (Windows and Unix-based)bashToExec(code)
code
representing a Bash command{EXEC}
to indicate execution\n &&
and \n
with platform-specific multiline and multicmd patternsexecCmd(script, options)
script
representing a Bash command and an optional options
objectoptions
is not provided, it defaults to an empty objectquiet
is false in options
execCmd
function uses importer.runAllPromises
to execute the commandexec
function from child_process
is used to execute the commandon
method is used to listen to the stderr
and stdout
streams of the process