hpal
Version:
hapi pal CLI
136 lines (95 loc) • 4.54 kB
JavaScript
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];
};
;