Skip to content
Permalink
8d14cd4781
Go to file
 
 
Cannot retrieve contributors at this time
227 lines (184 sloc) 5.63 KB
import path from 'path'
import consola from 'consola'
import minimist from 'minimist'
import { name, version } from '../package.json'
import { forceExit } from './utils'
import { loadNuxtConfig } from './utils/config'
import { indent, foldLines, colorize } from './utils/formatting'
import { startSpaces, optionSpaces, forceExitTimeout } from './utils/constants'
import { detectTypeScript } from './utils/typescript'
import * as imports from './imports'
export default class NuxtCommand {
constructor(cmd = { name: '', usage: '', description: '' }, argv = process.argv.slice(2)) {
if (!cmd.options) {
cmd.options = {}
}
this.cmd = cmd
this._argv = Array.from(argv)
this._parsedArgv = null // Lazy evaluate
}
static run(cmd, argv) {
return NuxtCommand.from(cmd, argv).run()
}
static from(cmd, argv) {
if (cmd instanceof NuxtCommand) {
return cmd
}
return new NuxtCommand(cmd, argv)
}
async run() {
if (this.argv.help) {
this.showHelp()
return
}
if (this.argv.version) {
this.showVersion()
return
}
if (typeof this.cmd.run !== 'function') {
return
}
let cmdError
try {
await this.cmd.run(this)
} catch (e) {
cmdError = e
}
if (this.argv.lock) {
await this.releaseLock()
}
if (this.argv['force-exit']) {
const forceExitByUser = this.isUserSuppliedArg('force-exit')
if (cmdError) {
consola.fatal(cmdError)
}
forceExit(this.cmd.name, forceExitByUser ? false : forceExitTimeout)
if (forceExitByUser) {
return
}
}
if (cmdError) {
throw cmdError
}
}
showVersion() {
process.stdout.write(`${name} v${version}\n`)
}
showHelp() {
process.stdout.write(this._getHelp())
}
get argv() {
if (!this._parsedArgv) {
const minimistOptions = this._getMinimistOptions()
this._parsedArgv = minimist(this._argv, minimistOptions)
}
return this._parsedArgv
}
async getNuxtConfig(extraOptions = {}) {
const rootDir = path.resolve(this.argv._[0] || '.')
// Typescript support
extraOptions._typescript = await detectTypeScript(rootDir, {
transpileOnly: this.cmd.name === 'start'
})
const config = await loadNuxtConfig(this.argv)
const options = Object.assign(config, extraOptions)
for (const name of Object.keys(this.cmd.options)) {
this.cmd.options[name].prepare && this.cmd.options[name].prepare(this, options, this.argv)
}
return options
}
async getNuxt(options) {
const { Nuxt } = await imports.core()
const nuxt = new Nuxt(options)
await nuxt.ready()
return nuxt
}
async getBuilder(nuxt) {
const { Builder } = await imports.builder()
const { BundleBuilder } = await imports.webpack()
return new Builder(nuxt, BundleBuilder)
}
async getGenerator(nuxt) {
const { Generator } = await imports.generator()
const builder = await this.getBuilder(nuxt)
return new Generator(nuxt, builder)
}
async setLock(lockRelease) {
if (lockRelease) {
if (this._lockRelease) {
consola.warn(`A previous unreleased lock was found, this shouldn't happen and is probably an error in 'nuxt ${this.cmd.name}' command. The lock will be removed but be aware of potential strange results`)
await this.releaseLock()
this._lockRelease = lockRelease
} else {
this._lockRelease = lockRelease
}
}
}
async releaseLock() {
if (this._lockRelease) {
await this._lockRelease()
this._lockRelease = undefined
}
}
isUserSuppliedArg(option) {
return this._argv.includes(`--${option}`) || this._argv.includes(`--no-${option}`)
}
_getDefaultOptionValue(option) {
return typeof option.default === 'function' ? option.default(this.cmd) : option.default
}
_getMinimistOptions() {
const minimistOptions = {
alias: {},
boolean: [],
string: [],
default: {}
}
for (const name of Object.keys(this.cmd.options)) {
const option = this.cmd.options[name]
if (option.alias) {
minimistOptions.alias[option.alias] = name
}
if (option.type) {
minimistOptions[option.type].push(option.alias || name)
}
if (option.default) {
minimistOptions.default[option.alias || name] = this._getDefaultOptionValue(option)
}
}
return minimistOptions
}
_getHelp() {
const options = []
let maxOptionLength = 0
for (const name in this.cmd.options) {
const option = this.cmd.options[name]
let optionHelp = '--'
optionHelp += option.type === 'boolean' && this._getDefaultOptionValue(option) ? 'no-' : ''
optionHelp += name
if (option.alias) {
optionHelp += `, -${option.alias}`
}
maxOptionLength = Math.max(maxOptionLength, optionHelp.length)
options.push([ optionHelp, option.description ])
}
const _opts = options.map(([option, description]) => {
const i = indent(maxOptionLength + optionSpaces - option.length)
return foldLines(
option + i + description,
startSpaces + maxOptionLength + optionSpaces * 2,
startSpaces + optionSpaces
)
}).join('\n')
const usage = foldLines(`Usage: nuxt ${this.cmd.usage} [options]`, startSpaces)
const description = foldLines(this.cmd.description, startSpaces)
const opts = foldLines(`Options:`, startSpaces) + '\n\n' + _opts
let helpText = colorize(`${usage}\n\n`)
if (this.cmd.description) {
helpText += colorize(`${description}\n\n`)
}
if (options.length) {
helpText += colorize(`${opts}\n\n`)
}
return helpText
}
}
You can’t perform that action at this time.