@aetherinox/noxenv
Version:
Set and use environment variables across different platforms.
125 lines (97 loc) • 3.33 kB
JavaScript
const { spawn } = require('cross-spawn');
const cmdConvert = require('./cmd');
const envConvertVar = require('./var');
module.exports = noxEnv;
const envSetterRegex = /(\w+)=('(.*)'|"(.*)"|(.*))/;
function noxEnv(args, options = {}) {
const [envSetters, cmd, cmdArgs] = parseCommand(args);
const env = getEnvVars(envSetters);
if (cmd) {
const proc = spawn(
/*
run path.normalize for cmd on windows
*/
cmdConvert(cmd, env, true),
/*
normalize is false by default; do not run on cmd args
*/
cmdArgs.map((arg) => cmdConvert(arg, env)),
{
stdio: 'inherit',
shell: options.shell,
env
}
);
process.on('SIGTERM', () => proc.kill('SIGTERM'));
process.on('SIGINT', () => proc.kill('SIGINT'));
process.on('SIGBREAK', () => proc.kill('SIGBREAK'));
process.on('SIGHUP', () => proc.kill('SIGHUP'));
proc.on('exit', (code, signal) => {
let exitCode = code;
/*
exit code may be null when operating system kills the process for any number of reasons.
IE: out of memory, hanging, etc.
SIGINT means user exited process; return exit code 0
*/
if (exitCode === null) {
exitCode = signal === 'SIGINT' ? 0 : 1;
}
process.exit(exitCode);
});
return proc;
}
return null;
}
function parseCommand(args) {
const envSetters = {};
let cmd = null;
let cmdArgs = [];
for (let i = 0; i < args.length; i++) {
const match = envSetterRegex.exec(args[i]);
if (match) {
let val;
if (typeof match[3] !== 'undefined') {
val = match[3];
} else if (typeof match[4] === 'undefined') {
val = match[5];
} else {
val = match[4];
}
envSetters[match[1]] = val;
} else {
/*
no more env setters remain; the rest of the line is the command and arguments
*/
let cStart = [];
cStart = args
.slice(i)
/*
regex: match "\'" or "'"
match "\" if followed by [$"\] (lookahead)
*/
.map((a) => {
const re = /\\\\|(\\)?'|([\\])(?=[$"\\])/g;
// Eliminate all matches except for "\'" => "'"
return a.replace(re, (m) => {
if (m === '\\\\') return '\\';
if (m === "\\'") return "'";
return '';
});
});
cmd = cStart[0];
cmdArgs = cStart.slice(1);
break;
}
}
return [envSetters, cmd, cmdArgs];
}
function getEnvVars(envSetters) {
const envVars = { ...process.env };
if (process.env.APPDATA) {
envVars.APPDATA = process.env.APPDATA;
}
Object.keys(envSetters).forEach((varName) => {
envVars[varName] = envConvertVar(envSetters[varName], varName);
});
return envVars;
}