actionhero
Version:
The reusable, scalable, and quick node.js API server for stateless and stateful applications
179 lines (178 loc) • 7.84 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.ActionheroCLIRunner = void 0;
const path = require("path");
const fs = require("fs");
const commander_1 = require("commander");
const typescript_1 = require("../classes/process/typescript");
const projectRoot_1 = require("../classes/process/projectRoot");
const ensureNoTsHeaderOrSpecFiles_1 = require("../modules/utils/ensureNoTsHeaderOrSpecFiles");
// load explicitly to find the type changes for the config module
require("../config/api");
require("../config/plugins");
require("../config/logger");
require("../config/routes");
const safeGlob_1 = require("../modules/utils/safeGlob");
var ActionheroCLIRunner;
(function (ActionheroCLIRunner) {
async function run() {
commander_1.program.storeOptionsAsProperties(false);
commander_1.program.version(getVersion());
let pathsLoaded = [];
try {
const { config } = await Promise.resolve().then(() => require("../index"));
// this project
for (const p of config.general.paths.cli) {
await loadDirectory(path.join(p), pathsLoaded);
}
// plugins
for (const plugin of Object.values(config.plugins)) {
if (plugin.cli !== false) {
// old plugins
await loadDirectory(path.join(plugin.path, "bin"), pathsLoaded);
// new plugins
await loadDirectory(path.join(plugin.path, "dist", "bin"), pathsLoaded);
}
}
// core
if (config.general.cliIncludeInternal !== false) {
await loadDirectory(__dirname, pathsLoaded);
}
}
catch (e) {
// we are trying to build a new project, only load the generate command
await loadDirectory(path.join(__dirname), pathsLoaded, "generate");
}
commander_1.program.parse(process.argv);
}
ActionheroCLIRunner.run = run;
// --- Utils --- //
async function loadDirectory(dir, pathsLoaded, match = "*") {
if (!fs.existsSync(dir))
return;
const realpath = fs.realpathSync(dir);
if (pathsLoaded.includes(realpath))
return;
pathsLoaded.push(realpath);
const matcher = `${realpath}/**/+(${typescript_1.typescript ? `${match}.js|*.ts` : `${match}.js`})`;
const files = (0, ensureNoTsHeaderOrSpecFiles_1.ensureNoTsHeaderOrSpecFiles)((0, safeGlob_1.safeGlobSync)(matcher));
for (const i in files) {
const collection = await Promise.resolve(`${files[i]}`).then(s => require(s));
for (const j in collection) {
const command = collection[j];
convertCLIToCommanderAction(command);
}
}
}
ActionheroCLIRunner.loadDirectory = loadDirectory;
async function convertCLIToCommanderAction(cliConstructor) {
var _a;
if (Object.getPrototypeOf(((_a = cliConstructor === null || cliConstructor === void 0 ? void 0 : cliConstructor.prototype) === null || _a === void 0 ? void 0 : _a.constructor) || {})
.name !== "CLI") {
return;
}
const instance = new cliConstructor();
const command = commander_1.program
.command(instance.name)
.description(instance.description)
.action(async (_arg1, _arg2, _arg3, _arg4, _arg5) => {
await runCommand(instance, _arg1, _arg2, _arg3, _arg4, _arg5);
})
.on("--help", () => {
if (instance.example) {
console.log("");
console.log("Example: \r\n" + " " + instance.example);
}
if (typeof instance.help === "function")
instance.help();
});
for (const key in instance.inputs) {
const input = instance.inputs[key];
if (input.flag && !input.letter) {
throw new Error(`flag inputs require a short letter (${JSON.stringify(input)})`);
}
const separators = input.required || input.requiredValue ? ["<", ">"] : ["[", "]"];
const methodName = input.required ? "requiredOption" : "option";
const argString = `${input.letter ? `-${input.letter}, ` : ""}--${key} ${input.flag
? ""
: `${separators[0]}${input.placeholder || key}${input.variadic ? "..." : ""}${separators[1]}`}`;
const argProcessor = (value, accumulator) => {
var _a;
try {
if (typeof input.formatter === "function") {
value = input.formatter(value);
}
if (typeof input.validator === "function") {
input.validator(value);
}
if (input.variadic) {
if (!Array.isArray(accumulator))
accumulator = [];
accumulator.push(value);
return accumulator;
}
return value;
}
catch (error) {
throw new commander_1.InvalidArgumentError((_a = error === null || error === void 0 ? void 0 : error.message) !== null && _a !== void 0 ? _a : error);
}
};
command[methodName](argString, input.description, argProcessor, input.default);
}
}
ActionheroCLIRunner.convertCLIToCommanderAction = convertCLIToCommanderAction;
async function runCommand(instance, _arg1, _arg2, _arg3, _arg4, _arg5) {
let toStop = false;
let _arguments = [];
let params = {};
[_arg1, _arg2, _arg3, _arg4, _arg5].forEach((arg) => {
if (typeof (arg === null || arg === void 0 ? void 0 : arg.opts) === "function") {
params = arg.opts();
}
else if (arg !== null && arg !== undefined && typeof arg !== "object") {
_arguments.push(arg);
}
});
params["_arguments"] = _arguments;
if (instance.initialize === false && instance.start === false) {
toStop = await instance.run({ params });
}
else {
try {
const { Process } = await Promise.resolve().then(() => require("../index"));
const actionHeroProcess = new Process();
if (instance.initialize)
await actionHeroProcess.initialize();
if (instance.start)
await actionHeroProcess.start();
toStop = await instance.run({ params });
}
catch (error) {
console.error(error.toString());
process.exit(1);
}
}
if (toStop || toStop === null || toStop === undefined) {
setTimeout(process.exit, 500, 0);
}
}
ActionheroCLIRunner.runCommand = runCommand;
function readPackageJSON(file) {
return JSON.parse(fs.readFileSync(file).toString());
}
ActionheroCLIRunner.readPackageJSON = readPackageJSON;
function getVersion() {
const parentPackageJSON = path.join(projectRoot_1.projectRoot, "package.json");
if (fs.existsSync(parentPackageJSON)) {
const pkg = readPackageJSON(parentPackageJSON);
return pkg.version;
}
else {
const pkg = readPackageJSON(path.join(__dirname, "..", "..", "package.json"));
return pkg.version;
}
}
ActionheroCLIRunner.getVersion = getVersion;
})(ActionheroCLIRunner || (exports.ActionheroCLIRunner = ActionheroCLIRunner = {}));
ActionheroCLIRunner.run();