UNPKG

jbash

Version:

Helpers for bash like shell scripting in JavaScript

131 lines (119 loc) 3.68 kB
// jbash - v1.69.0 // https://github.com/bradymholt/jbash#readme global.options = global.options || {}; global.options.errexit = (typeof global.options.errexit === 'undefined') ? false : global.options.errexit; global.options.xtrace = (typeof global.options.xtrace === 'undefined') ? false : global.options.xtrace; global.set = (opt) => { if (!opt.match(/^(-|\+)/)) { throw new Error("Invalid set value"); } let val = opt[0] == "-"; switch (opt[1]) { case "x": global.options.xtrace = val; case "e": global.options.errexit = val; } }; // Aliases global.args = process.argv.slice(global.shebangInvoked ? 3 : 2); // Current filename aliased as $0 const path = require("path"); if (global.scriptName) { // global.scriptName is set by ./bin scripts and used when jBash is used via npx global[`$0`] = global.scriptName; } else if (!!module.parent) { global[`$0`] = path.basename(module.parent.filename); } else { global[`$0`] = path.basename(process.argv[0]); } // Arguments aliased as $1, $2, etc. // $1 through $10, at a minimum, will be declared and have argument value or be set to undefined if not specified for (let i = 1; i <= Math.max(10, args.length); i++) { if (args.length >= i) { global[`$${i}`] = args[i - 1]; } else { global[`$${i}`] = undefined; } } global.cd = process.chdir; global.exit = process.exit; global.env = process.env; // Environmental variables prefixed with $ for (let p in env) { global[`$${p}`] = env[p]; } // File access const fs = require("fs"); global.readFile = (path, encoding = "utf-8") => { return fs.readFileSync(path, { encoding }); }; global.writeFile = (path, contents, encoding = "utf-8") => { fs.writeFileSync(path, contents, { encoding }); }; global.cat = global.readFile; global.printf = (contents) => { process.stdout.write(contents); }; global.echo = (contents, outPath, encoding) => { if (outPath === undefined) { global.printf(contents + "\n"); } else { global.writeFile(outPath, contents, encoding); } }; global.dirExists = (path) => { return fs.existsSync(path) && fs.statSync(path).isDirectory(); }; global.mkdir = (path) => { if (!fs.existsSync(path)) { fs.mkdirSync(path); } }; global.rmdir = (path) => { if (fs.existsSync(path)) { fs.rmdirSync(path); } }; // Command execution global["$"] = (cmd, stream) => { if (global["options"].xtrace) { global.echo(cmd); } let result = require("child_process").spawnSync(cmd, [], { stdio: [0, stream ? "inherit" : "pipe", stream ? "inherit" : "pipe"], shell: "/bin/bash", }); if (result.status != 0) { let stderr = result.stderr ? result.stderr.toString().replace("/bin/sh: ", "") : null; let msg = stderr || `Error running: ${cmd}`; if (global.options.errexit) { err = new Error(msg); err.status = result.status; err.stderr = stderr; err.output = result.output; throw err; } else { process.stderr.write(msg + "\n"); } return !stream ? msg : null; } return !!result.stdout ? result.stdout.toString().replace(/^\n|\n$/g, "") : null; }; global.eval = (cmd) => { return $(cmd, true); }; global.exec = eval; // Error handling const handleUnhandledError = (err) => { if (global.options.errexit) { // Since errexit is on, error message was not printed when error was thrown. // But, now we know the error was not handled so print the error (on stderr) before we exit. process.stderr.write(err.message + "\n"); exit(err.status || 1); } else { throw err; } }; process.on("unhandledRejection", handleUnhandledError); process.on("uncaughtException", handleUnhandledError);