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
This commit is contained in:
Jonas Galvez 2018-11-02 01:35:32 -03:00 committed by Sébastien Chopin
parent e9b63deba4
commit 19287cce96
6 changed files with 62 additions and 16 deletions

View File

@ -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

View File

@ -0,0 +1,20 @@
import consola from 'consola'
import NuxtCommand from '../command'
export default {
name: 'help',
description: 'Shows help for <command>',
usage: 'help <command>',
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}`)
}
}
}

View File

@ -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')

View File

@ -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)

View File

@ -19,3 +19,22 @@ exports[`cli/command builds help text 1`] = `
"
`;
exports[`cli/command loads command from name 1`] = `
" Usage: nuxt dev <dir> [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
"
`;

View File

@ -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)