json-processing
Version:
JSON Processing Tool
139 lines (138 loc) • 4.98 kB
JavaScript
"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.ScriptRunner = void 0;
const vm2_1 = require("vm2");
const filter_1 = __importDefault(require("./lib/filter"));
const lodash_1 = require("lodash");
const require_dir_1 = __importDefault(require("require-dir"));
const fs_1 = require("fs");
const path_1 = require("path");
const lodash_2 = require("lodash");
const core_1 = require("@babel/core");
const plugin_proposal_pipeline_operator_1 = __importDefault(require("@babel/plugin-proposal-pipeline-operator"));
class ScriptRunner {
constructor(input) {
this._input = input;
this._global = {};
}
_createSandbox() {
let sandbox = lodash_1.merge({
requireDir: require_dir_1.default,
__transpileCode: this._transpileCode,
run: (command, input) => this._run(command, input),
from: (path) => fs_1.createReadStream(path_1.resolve(process.cwd(), path)),
select: (pathOrInput, input) => {
let path;
if (!input && !lodash_2.isString(pathOrInput)) {
input = pathOrInput;
path = '$';
}
else if (typeof pathOrInput == 'string') {
path = pathOrInput;
}
else {
throw new Error("Invalid Parameters on select()");
}
path = path[0] != '$' ? `$${path}` : path;
return filter_1.default(input || this._input, path);
}
}, this._global);
return sandbox;
}
_createVM() {
return new vm2_1.NodeVM({
sandbox: this._createSandbox(),
require: { external: true, context: 'sandbox', builtin: ['*'] },
compiler: this._transpileCode
});
}
_runScript(script, path) {
const vm = this._createVM();
return vm.run(`'use strict';${script}`, path);
}
_transpileCode(code, filename) {
const transpiled = core_1.transformSync(code, {
plugins: [[
plugin_proposal_pipeline_operator_1.default,
{ proposal: 'minimal' }
]]
});
if (!transpiled || !transpiled.code) {
throw new Error('script transpilation failed');
}
return transpiled.code;
}
addGlobal(object) {
this._global = lodash_1.merge({}, this._global, object || {});
return this;
}
addGlobalFromPath(path) {
return this.addGlobal(this._loadPath(path));
}
setInlineScript(inline) {
this._inlineScript = inline;
return this;
}
setCommand(command) {
this._command = command;
return this;
}
setCommandArgs(args) {
this._commandArgs = args;
return this;
}
setCommandsPath(path) {
this._commandsPath = path;
return this;
}
setPluginsInfo(pluginsInfo) {
return this.addGlobal(this._loadPlugins(pluginsInfo));
}
run() {
if (!lodash_2.isEmpty(this._command)) {
const commandFile = resolveCommand(this._commandsPath, this._command);
return this._runScript(`
const command = require('${commandFile}');
module.exports = (argv) => command(argv)${this._inlineScript ? this._inlineScript : ''};`, commandFile)(this._commandArgs || {});
}
const inlineScript = lodash_2.isEmpty(this._inlineScript) ?
'select()' : this._inlineScript;
return this._runScript(`module.exports = () => ${inlineScript};`)();
}
_loadPlugins(pluginsInfo) {
const homeDir = path_1.dirname(pluginsInfo);
return this._runScript(`
module.exports = () => {
const pluginsInfo = require("${pluginsInfo}");
const result = {};
Object.keys(pluginsInfo).forEach(name => {
result["$" + name] = require(pluginsInfo[name])("${homeDir}");
});
return result;
}
`, pluginsInfo)();
}
_loadPath(path) {
return this._runScript(`
module.exports = () =>
requireDir('${path}', {
recurse: true
})`, `${path}/index.js`)();
}
_run(command, input) {
const runner = new ScriptRunner(input);
runner._global = this._global;
runner._command = command;
runner._commandsPath = this._commandsPath;
return runner.run();
}
}
exports.ScriptRunner = ScriptRunner;
function resolveCommand(commandsPath, command) {
if (/^.+\.js$/.test(command))
return path_1.resolve(process.cwd(), command);
return path_1.resolve(commandsPath, `${command}.js`);
}