!function CLIModuleWrapper() {
let core; let mod; let o = {};
/**
* Blackrock CLI Module
*
* @public
* @class Server.Modules.CLI
* @augments Server.Modules.Core.Module
* @param {Server.Modules.Core} coreObj - The Core Module Singleton
* @return {Server.Modules.CLI} module - The CLI Module Singleton
*
* @description This is the CLI Module of the Blackrock Application Server.
* It is responsible for parsing command-line arguments passed to the application
* server at startup, and then executing methods from within other modules that have
* registered with the CLI module for those specific command-line arguments.
*
* @author Darren Smith
* @copyright Copyright (c) 2021 Darren Smith
* @license Licensed under the LGPL license.
*/
module.exports = function CLIModule(coreObj) {
if (mod) return mod;
core = coreObj; mod = new core.Mod('CLI'); o.cliCommands = {};
o.setupExternalModuleMethods(); mod.register = register;
o.log('debug', 'CLI > Initialising...', {module: mod.name}, 'MODULE_INIT');
core.on('CORE_FINALISING', function() {
start();
});
return mod;
};
/**
* Setup External Methods
*
* @private
* @memberof Server.Modules.CLI
* @name setupExternalModuleMethods
* @function
* @ignore
*
* @description
* This method binds the handlers - 'log' and 'enableConsole' to the internal module object (o)
*
* @example
* o.setupExternalModuleMethods();
* // log and enableConsole methods are now bound to the internal module object (o)
*/
o.setupExternalModuleMethods = function CLISetupExtModMethods() {
o.log = function CLILog(level, logMsg, attrObj, evtName) {
const logger = core.module('logger');
if (logger && logger.log) {
logger.log(level, logMsg, attrObj, evtName);
}
};
o.enableConsole = function CLIEnableConsole() {
const logger = core.module('logger');
if (logger && logger.enableConsole) {
logger.enableConsole();
}
};
};
/**
* (External) Register CLI Commands
*
* @public
* @memberof Server.Modules.CLI
* @name register
* @function
* @param {object} commands - The Commands Object
* @return {boolean} result - Method Result
*
* @description
* The register method on the CLI Module is used to register function handlers against a collection of
* defined command-line arguments. It can only be called internally (from other modules) within the application
* server, and must be called as part of the module's construction. Once all dependencies are loaded, the CLI
* Module will check the command-line arguments for the presence of any registered commands, and where present
* will execute the registered handlers for those commands.
*
* @example
* core.module.isLoaded('cli').then(function(cliMod) {
* cliMod.register([
* {'cmd': 'install', 'params': '[app]', 'info': 'Installs a new app', 'fn': function(params) {
* core.emit('INSTALLER_INIT_INSTALLER', {'command': 'install', 'params': params});
* }},
* {'cmd': 'remove', 'params': '[app]', 'info': 'Removes an installed app', 'fn': function(params) {
* core.emit('INSTALLER_INIT_INSTALLER', {'command': 'remove', 'params': params});
* }},
* ]);
* }).catch(function(err) {
* log('error',
* 'Failed to register with CLI - CLI module not loaded',
* err, 'INSTALLER_CLI_MOD_NOT_LOADED');
* });
*/
const register = function CLIRegCmds(commands) {
if (typeof commands === 'object' && commands !== null && !Array.isArray(commands)) {
o.cliCommands[commands.cmd] = commands;
} else if (Array.isArray(commands) && commands !== null) {
for (let i = 0; i < commands.length; i++) {
o.cliCommands[commands[i].cmd] = commands[i];
}
}
return true;
};
/**
* Initialises CLI Module
*
* @private
* @memberof Server.Modules.CLI
* @name start
* @ignore
* @function
*
* @description
* This method is internal to the CLI Module and can only be called from within it. It initialises the module
* once all server dependencies have been loaded.
*
* @example
* start();
* // CLI Module Initialisation Begins...
*/
const start = function CLIStart() {
process.nextTick(function CLIStartNextTickCb() {
process.argv.push('terminator');
// eslint-disable-next-line new-cap
const lib = core.lib;
// noinspection JSUnresolvedVariable
const rx = lib.rxjs;
const op = lib.operators; const stream = new rx.from(process.argv);
const showHelp = function CLIModuleShowHelp() {
core.stopActivation = true;
console.log('\n');
console.log('Usage: ' + core.pkg().name + ' [options]\n');
console.log('Options: ');
console.log('start console\t\t\t\tStarts the server in console mode');
// eslint-disable-next-line guard-for-in
for (const cmd in o.cliCommands) {
// noinspection JSUnfilteredForInLoop
console.log(cmd + ' ' + o.cliCommands[cmd].params + '\t\t\t' + o.cliCommands[cmd].info);
}
console.log('\n');
process.exit();
};
o.log('debug',
'CLI > Server Initialisation Pipeline Created - Executing Now:',
{module: mod.name}, 'CLI_EXEC_INIT_PIPELINE'
);
stream.pipe(
op.filter(function CLIStreamFn1Filter(evt) {
// eslint-disable-next-line no-extend-native
String.prototype.endsWith = function CLIEndsWith(suffix) {
return this.indexOf(suffix, this.length - suffix.length) !== -1;
};
const endsWithAny = function CLIEndsWithAny(suffixes, string) {
for (const suffix of suffixes) {
if (string.endsWith(suffix)) return true;
} return false;
};
// noinspection JSUnresolvedVariable
return !endsWithAny([
'sudo', 'node', 'nodemon', 'forever', 'blackrock', 'index.js',
'npm', 'pm2', 'server.js', Object.keys(core.pkg().bin)[0],
], evt);
}),
op.map(function CLIStreamFn2Map(evt) {
o.log('debug', 'CLI > [1] Command-Line Arguments Filtered',
{module: mod.name}, 'CLI_ARGS_FILTERED');
return evt;
}),
op.reduce(function CLIStreamFn3Reduce(acc, one) {
return acc + ' ' + one;
}),
op.map(function CLIModuleStreamFn4Map(evt) {
o.log('debug', 'CLI > [2] Remaining Arguments Reduced',
{module: mod.name}, 'CLI_ARGS_REDUCED');
return evt;
})
).subscribe(function CLISubscribeCallback(val) {
val = val.replace('terminator', '').trim();
setTimeout(function() {
let command;
for (const cmd in o.cliCommands) {
// noinspection JSUnfilteredForInLoop
if (val.startsWith(cmd)) {
command = cmd;
}
}
if (val === 'start console' || core.globals.get('test') || process.send) {
core.stopActivation = false;
o.log('debug',
'CLI > [3] Start Console Called - Enabling Console and emitting CORE_START_INTERFACES',
{module: mod.name}, 'CLI_ENABLE_CONSOLE');
setTimeout(function CLIEnableConsoleTimeout() {
o.enableConsole();
}, 50);
core.emit('CORE_START_INTERFACES');
} else if (o.cliCommands[command] && o.cliCommands[command].fn) {
o.log('debug',
'CLI > [3] Registered CLI command being executed',
{'cmd': val, module: mod.name}, 'CLI_EXECUTING_CLI_COMMAND');
o.cliCommands[command].fn(val.slice(command.length));
} else {
showHelp();
o.log('debug',
'CLI > [3] No valid commands received - Displaying Command-Line Help',
{module: mod.name}, 'CLI_NO_ARGS_SHOWING_HELP');
}
}, 5);
}).unsubscribe();
});
};
}();