UNPKG

@villedemontreal/scripting

Version:
158 lines 6.1 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.main = main; const caporal_1 = require("@villedemontreal/caporal"); const general_utils_1 = require("@villedemontreal/general-utils"); const scriptBase_1 = require("./scriptBase"); /** * Run a script or display some help, given * the specified arguments. * * The compilation must already have been done. */ async function main(caporal, projectScriptsIndexModule, argv) { addUnhandledRejectionHandler(); const localArgv = argv ?? process.argv.slice(2); await manageHelpCommand(caporal, localArgv); await addProjectScripts(caporal, projectScriptsIndexModule); let executedCommand; addExecutedCommandExtractor(); try { await caporal.run(localArgv); return 0; } catch (err) { // ========================================== // Note that this error might have already been printed from // the BaseScript.run() method. // If that was the case, a tag called '__reported' was injected in // the error object in order to let us know that we should skip this error. // ========================================== if (!err.meta?.error?.__reported) { console.error(`${caporal_1.chalk.redBright('error')}: ${err.message ? err.message : JSON.stringify(err, Object.getOwnPropertyNames(err))}\n`); } // ========================================== // We output the help (global or specific to // the command) on Caporal validation errors. // ========================================== await printHelpOnCaporalError(caporal, err, localArgv, executedCommand); return 1; } function addExecutedCommandExtractor() { const runOriginal = caporal['_run'].bind(caporal); caporal['_run'] = async function (result, cmd) { executedCommand = cmd; // eslint-disable-next-line prefer-rest-params return await runOriginal(...arguments); }; } } function addUnhandledRejectionHandler() { process.on('unhandledRejection', (reason) => { console.error(`Promise rejection error : `, reason); }); } async function manageHelpCommand(caporal, localArgv) { const helpCommand = (await caporal.getAllCommands()).find((cmd) => cmd.name === 'help'); if (helpCommand) { patchHelpCommand(caporal, helpCommand); // ========================================== // Make the "help" command the default one // if no command is provided. // ========================================== if (localArgv.length === 0 || (localArgv.length === 1 && localArgv[0] === '--nc')) { helpCommand.default(); } } } function patchHelpCommand(caporal, helpCommand) { const oldAction = helpCommand._action; if (!oldAction) { throw new Error('Expected to find the command action callback'); } if (helpCommand._action.__hooked) { throw new Error('Help command has already been patched'); } helpCommand._action = (actionParams) => { return new Promise((resolve, reject) => { // ========================================== // The "help" output seems to be done asynchronously, // even with "await". So we use a listener. // ========================================== let result; function onHelp() { caporal.removeListener('help', onHelp); resolve(result); } caporal.addListener('help', onHelp); oldAction(actionParams) .then((res) => { result = res; }) .catch((err) => { caporal.removeListener('help', onHelp); // eslint-disable-next-line @typescript-eslint/prefer-promise-reject-errors reject(err); }); }); }; helpCommand._action.__hooked = true; } async function printHelpOnCaporalError(caporal, err, argv, executedCommand) { if (argv.includes(`--silent`) || argv.includes(`--quiet`)) { return; } // ========================================== // Unknown command, display global help // ========================================== if (err && err.message && err.message.startsWith('Unknown command ') && err.meta && err.meta.command) { await executeHelp(caporal, argv); } // ========================================== // Command error, display command help // ========================================== if (executedCommand && err.meta && err.meta.errors) { await executeHelp(caporal, argv, executedCommand.name); } } async function executeHelp(caporal, argv, command) { const helpOptions = argv.filter((arg) => ['-v', '--verbose', '--quiet', '--silent', '--color'].includes(arg)); const args = ['help']; if (command) { args.push(command); } args.push('--nc', ...helpOptions); await caporal.run(args); } async function addProjectScripts(caporal, scriptsIndexModule) { const scriptsNames = new Set(); if (scriptsIndexModule) { const scriptsModule = await Promise.resolve(`${scriptsIndexModule}`).then(s => require(s)); for (const scriptClass of Object.values(scriptsModule)) { const script = new scriptClass(null); if (await registerScript(caporal, script)) { scriptsNames.add(script.name); } } } return scriptsNames; } /** * Register a Script on Caporal. * * @returns `true` is the script has been registered or * `false` if it was skipped. */ async function registerScript(caporal, script) { if ((script instanceof scriptBase_1.ScriptBase && !script.name.startsWith(scriptBase_1.TESTING_SCRIPT_NAME_PREFIX)) || general_utils_1.globalConstants.testingMode) { await script.registerScript(caporal); return true; } return false; } //# sourceMappingURL=main.js.map