PATH:
usr
/
local
/
lib
/
node_modules
/
ghost-cli
/
lib
const fs = require('fs-extra'); const each = require('lodash/each'); const path = require('path'); const abbrev = require('abbrev'); const createDebug = require('debug'); const Command = require('./command'); const findExtensions = require('./utils/find-extensions'); const debug = createDebug('ghost-cli:bootstrap'); // Extra alises for commands const extraAliases = { '--version': 'version', '-v': 'version', busters: 'buster', intsall: 'install', insall: 'install', status: 'ls', upgrade: 'update', udpate: 'update' }; // Ensure if any promises aren't handled correctly then they get logged process.on('unhandledRejection', (reason, promise) => { console.warn('A promise was rejected but did not have a .catch() handler:'); console.warn(reason && reason.stack || reason || promise); throw reason; }); const bootstrap = { /** * Discovers any commands inside of an extension folder * If a command name conflict occurs, commands will be namespaced according to * the extension name, e.g. `ghost exname:commandname` * * @param {Object} commands Current commands hash * @param {string} dir Directory to look for commands in * @param {string} extensionName Name of extension * @return {Object} Object hash with any discovered commands added */ discoverCommands: function discoverCommands(commands, dir, extensionName) { const commandsDir = path.join(dir, 'commands'); // No commands here if commands dir doesn't exist if (!fs.existsSync(commandsDir)) { return commands; } // Read the directory and find the commands fs.readdirSync(commandsDir).filter( // Don't treat non-js files as commands, but also make sure any commands that are folders // with index.js files in them are loaded command => path.extname(command) === '.js' || fs.existsSync(path.join(commandsDir, command, 'index.js')) ).forEach((command) => { const basename = path.basename(command, '.js'); const commandName = commands[basename] ? `${extensionName}:${basename}` : basename; commands[commandName] = path.resolve(commandsDir, basename); }); return commands; }, /** * Configure a single command * * @param {String} commandName name of command * @param {String} commandPath path to command file * @param {Yargs} yargs Yargs instance * @param {Array<String>} array of string aliases for command * @param {Array<Object>} array of extensions */ loadCommand: function loadCommand(commandName, commandPath, yargs, aliases, extensions) { const CommandClass = require(commandPath); if (!(CommandClass.prototype instanceof Command)) { // This should only be thrown by extensions, not internal CLI commands, // but needs to be here nonetheless console.error(`Command class for ${commandName} does not inherit from Ghost-CLI's command class.`); return; } // Configure the command CommandClass.configure(commandName, aliases, yargs, extensions); }, /** * Runs the CLI! * This is where the magic happens * * @param {Array} Array of string arguments (taken from process.argv) * @param Yargs yargs instance */ run: function run(argv, yargs) { debug('Starting bootstrap process'); // Look for any available extensions, including ones built-in to the CLI itself const extensions = findExtensions(); debug(`Found ${extensions.length} extensions: ${extensions.map(({pkg}) => pkg.name).join(', ')}`); debug('loading built-in commands'); // Load built-in commands first let commands = bootstrap.discoverCommands({}, __dirname); debug('loading commands from extensions'); // Then load commands from extensions extensions.forEach((extension) => { commands = bootstrap.discoverCommands(commands, extension.dir, extension.name); }); debug(`discovered commands: ${Object.keys(commands).join(', ')}`); // Use abbrev to handle shortnened command names let abbreviations = abbrev(Object.keys(commands)); // Get the first argument so we can not load all the commands at once const firstArg = argv.shift(); // Apply extra aliases abbreviations = Object.assign(abbreviations, extraAliases); // Special-case `help` because we only want to configure all the commands // for this one case if (firstArg === 'help' || firstArg === '--help') { debug('running help command, requiring and configuring every command'); each(commands, (commandPath, commandName) => { // Don't fetch aliases for help commands to keep the output clean. bootstrap.loadCommand(commandName, commandPath, yargs, [], extensions); }); argv.unshift('help'); } else if (abbreviations[firstArg]) { // Command found, instantiate/configure it and run! const commandName = abbreviations[firstArg]; const commandPath = commands[commandName]; // Get aliases of the command (so it will show up in yargs help) const aliases = Object.keys(abbreviations).filter(key => abbreviations[key] === commandName); bootstrap.loadCommand(commandName, commandPath, yargs, aliases, extensions); // Put the first arg back into the array argv.unshift(commandName); } else { // Command not found :( Error and exit console.error(`Unrecognized command: '${firstArg}'. Run \`ghost help\` for usage.`); process.exit(1); } // Yargs magic yargs.wrap(Math.min(150, yargs.terminalWidth())) .epilogue('For more information, see our docs at https://ghost.org/docs/api/ghost-cli/') .group('help', 'Global Options:') .option('d', { alias: 'dir', describe: 'Folder to run command in', group: 'Global Options:' }).option('D', { alias: 'development', describe: 'Run in development mode', type: 'boolean', group: 'Global Options:' }) .option('V', { alias: 'verbose', describe: 'Enable verbose output', type: 'boolean', group: 'Global Options:' }) .options('prompt', { describe: '[--no-prompt] Allow/Disallow UI prompting', type: 'boolean', default: true, group: 'Global Options:' }) .option('color', { describe: '[--no-color] Allow/Disallow colorful logging', type: 'boolean', default: true, group: 'Global Options:' }) .option('auto', { describe: 'Automatically run as much as possible', type: 'boolean', default: false, group: 'Global Options:' }) .version(false) .parse(argv); } }; module.exports = bootstrap;
[+]
ui
[-] process-manager.js
[edit]
[-] errors.js
[edit]
[+]
..
[-] migrations.js
[edit]
[+]
commands
[+]
utils
[-] bootstrap.js
[edit]
[-] extension.js
[edit]
[+]
tasks
[-] index.js
[edit]
[-] command.js
[edit]
[-] system.js
[edit]
[-] instance.js
[edit]