From 19287cce96a3e3c44f28fd85d1774e821168ff54 Mon Sep 17 00:00:00 2001 From: Jonas Galvez Date: Fri, 2 Nov 2018 01:35:32 -0300 Subject: [PATCH] feat(cli): add help command (#4248) * add commands/help * simply cmds in run() * refinement * simply cmds in run() (2) * simply cmds in run() (3) * lint * cmd.showHelp() * check for cmd / uknown cmd * final fix * fixes * remove Set * Add NuxtCommand.load() * updated tests * lint --- packages/cli/src/command.js | 12 +++++++++++ packages/cli/src/commands/help.js | 20 ++++++++++++++++++ packages/cli/src/commands/index.js | 1 + packages/cli/src/run.js | 21 +++++-------------- .../unit/__snapshots__/command.test.js.snap | 19 +++++++++++++++++ packages/cli/test/unit/command.test.js | 5 +++++ 6 files changed, 62 insertions(+), 16 deletions(-) create mode 100644 packages/cli/src/commands/help.js diff --git a/packages/cli/src/command.js b/packages/cli/src/command.js index 5c85a87964..acab1c442b 100644 --- a/packages/cli/src/command.js +++ b/packages/cli/src/command.js @@ -2,6 +2,7 @@ import parseArgs from 'minimist' import { name, version } from '../package.json' import { loadNuxtConfig } from './utils' import { indent, foldLines, startSpaces, optionSpaces } from './formatting' +import * as commands from './commands' import * as imports from './imports' export default class NuxtCommand { @@ -13,6 +14,17 @@ export default class NuxtCommand { this._run = run } + static async load(name) { + // So eslint doesn't complain about lookups + const _commands = { ...commands } + if (name in _commands) { + const cmd = await _commands[name]().then(m => m.default) + return NuxtCommand.from(cmd) + } else { + // TODO dynamic module loading + } + } + static from(options) { if (options instanceof NuxtCommand) { return options diff --git a/packages/cli/src/commands/help.js b/packages/cli/src/commands/help.js new file mode 100644 index 0000000000..9c32681f48 --- /dev/null +++ b/packages/cli/src/commands/help.js @@ -0,0 +1,20 @@ +import consola from 'consola' +import NuxtCommand from '../command' + +export default { + name: 'help', + description: 'Shows help for ', + usage: 'help ', + async run(cmd) { + const argv = cmd.getArgv()._ + const name = argv[0] || null + const command = await NuxtCommand.load(name) + if (command) { + command.showHelp() + } else if (name === null) { + consola.info(`Please specify a command`) + } else { + consola.info(`Unknown command: ${name}`) + } + } +} diff --git a/packages/cli/src/commands/index.js b/packages/cli/src/commands/index.js index d92eb03998..70ad510a39 100644 --- a/packages/cli/src/commands/index.js +++ b/packages/cli/src/commands/index.js @@ -2,3 +2,4 @@ export const start = () => import('./start') export const dev = () => import('./dev') export const build = () => import('./build') export const generate = () => import('./generate') +export const help = () => import('./help') diff --git a/packages/cli/src/run.js b/packages/cli/src/run.js index 54ae0bcb32..1b931cecff 100644 --- a/packages/cli/src/run.js +++ b/packages/cli/src/run.js @@ -6,9 +6,7 @@ import { indent, foldLines, startSpaces, optionSpaces } from './formatting' async function listCommands(_commands) { _commands = await Promise.all( - Object.keys(_commands).map((cmd) => { - return _commands[cmd]().then(m => m.default) - }) + Object.keys(_commands).map(cmd => NuxtCommand.load(cmd)) ) let maxLength = 0 const commandsHelp = [] @@ -33,21 +31,14 @@ async function listCommands(_commands) { export default function run() { const defaultCommand = 'dev' - - const cmds = new Set([ - defaultCommand, - 'build', - 'start', - 'generate' - ]) - let cmd = process.argv[2] - if (cmds.has(cmd)) { + const _commands = { ...commands } + if (_commands[cmd]) { process.argv.splice(2, 1) } else { if (process.argv.includes('--help') || process.argv.includes('-h')) { - listCommands({ ...commands }).then(() => process.exit(0)) + listCommands(_commands).then(() => process.exit(0)) return } cmd = defaultCommand @@ -58,9 +49,7 @@ export default function run() { dev: cmd === 'dev' }) - return commands[cmd]() // eslint-disable-line import/namespace - .then(m => m.default) - .then(options => NuxtCommand.from(options)) + return NuxtCommand.load(cmd) .then(command => command.run()) .catch((error) => { consola.fatal(error) diff --git a/packages/cli/test/unit/__snapshots__/command.test.js.snap b/packages/cli/test/unit/__snapshots__/command.test.js.snap index 017fc5e908..5793b42ed8 100644 --- a/packages/cli/test/unit/__snapshots__/command.test.js.snap +++ b/packages/cli/test/unit/__snapshots__/command.test.js.snap @@ -19,3 +19,22 @@ exports[`cli/command builds help text 1`] = ` " `; + +exports[`cli/command loads command from name 1`] = ` +" Usage: nuxt dev [options] + + Start the application in development mode (e.g. hot-code reloading, error reporting) + + Options: + + --spa, -s Launch in SPA mode + --universal, -u Launch in Universal mode (default) + --config-file, -c Path to Nuxt.js config file (default: nuxt.config.js) + --version Display the Nuxt version + --help, -h Display this message + --port, -p Port number on which to start the application + --hostname, -H Hostname on which to start the application + --unix-socket, -n Path to a UNIX socket + +" +`; diff --git a/packages/cli/test/unit/command.test.js b/packages/cli/test/unit/command.test.js index d3501fdf3b..b337371764 100644 --- a/packages/cli/test/unit/command.test.js +++ b/packages/cli/test/unit/command.test.js @@ -117,6 +117,11 @@ describe('cli/command', () => { expect(cmd._getHelp()).toMatchSnapshot() }) + test('loads command from name', async () => { + const cmd = await Command.load('dev') + expect(cmd._getHelp()).toMatchSnapshot() + }) + test('show version prints to stdout and exits', () => { jest.spyOn(process.stdout, 'write').mockImplementation(() => {}) jest.spyOn(process, 'exit').mockImplementationOnce(code => code)