UNPKG

hpal

Version:
136 lines (95 loc) 4.54 kB
'use strict'; const Path = require('path'); const PkgDir = require('pkg-dir'); const DisplayError = require('../display-error'); const internals = {}; module.exports = async (cwd, list, cmd, args, ctx) => { const root = await PkgDir(cwd); if (!root) { throw new DisplayError(ctx.colors.red('No nearby package.json found– you don\'t seem to be in a project.')); } const server = await internals.getServer(root, ctx); try { if (list && !cmd) { ctx.output(''); // Just a newline to make some room const pluginNames = Object.keys(server.plugins); const commandList = pluginNames.reduce((collect, pluginName) => { const plugin = server.plugins[pluginName]; const commands = Object.keys(plugin.commands || {}).map((cmdName) => { const name = pluginName.replace(/^hpal-/, '') + ((cmdName === 'default') ? '' : internals.kebabize(`:${cmdName}`)); const command = internals.normalizeCommand(plugin.commands[cmdName]); const description = typeof command.description === 'function' ? command.description(ctx) : command.description; return { name, description }; }); return collect.concat(commands); }, []); if (!commandList.length) { ctx.output(ctx.colors.yellow('No commands found on your server.')); } else { ctx.output(ctx.colors.green('Here are some commands found on your server:')); ctx.output(''); ctx.output(commandList.map((command) => ctx.colors.bold(` hpal run ${command.name}\n`) + (command.description ? ` • ${command.description}\n` : '')).join('')); } return; } const pluginName = cmd.split(':')[0]; const rawCommandName = cmd.slice(pluginName.length + 1) || 'default'; const commandName = internals.camelize(rawCommandName); const commandInfo = internals.normalizeCommand( internals.getCommand(server, commandName, pluginName) || internals.getCommand(server, commandName, `hpal-${pluginName}`) || internals.getCommand(server, rawCommandName, pluginName) || internals.getCommand(server, rawCommandName, `hpal-${pluginName}`) ); if (!commandInfo || typeof commandInfo.command !== 'function') { throw new DisplayError(ctx.colors.red(`Plugin ${pluginName} does not have ` + ((rawCommandName === 'default') ? 'a default command.' : `the command "${rawCommandName}".`))); } if (!commandInfo.noDefaultOutput) { ctx.output(''); // Just a newline to make some room ctx.output(ctx.colors.green(`Running ${cmd}...\n`)); } await commandInfo.command(server, args, root, ctx); if (!commandInfo.noDefaultOutput) { ctx.output(ctx.colors.green('\nComplete!')); } await server.stop(); } catch (err) { if (err instanceof DisplayError) { await server.stop(); } throw err; } }; internals.getServer = async (root, ctx) => { const path = Path.join(root, 'server'); try { const srv = require(path); if (typeof srv.deployment !== 'function') { throw new DisplayError(ctx.colors.red(`No server found! To run commands the current project must export { deployment: async () => server } from ${root}/server.`)); } const server = await srv.deployment(); await server.initialize(); return server; } catch (err) { if (err.code === 'MODULE_NOT_FOUND' && err.message.includes(`'${path}'`)) { throw new DisplayError(ctx.colors.red(`No server found! To run commands the current project must export { deployment: async () => server } from ${root}/server.`)); } throw err; } }; internals.kebabize = (str) => str.replace(/[A-Z]/g, (m) => (`-${m}`).toLowerCase()); internals.camelize = (str) => str.replace(/[_-]./g, (m) => m[1].toUpperCase()); internals.normalizeCommand = (command) => { if (typeof command === 'function') { return { command }; } return command; }; internals.getCommand = (server, commandName, pluginName) => { return server.plugins[pluginName] && server.plugins[pluginName].commands && server.plugins[pluginName].commands[commandName]; };