mirror of
https://github.com/vuejs/vue-cli.git
synced 2026-01-15 20:00:38 -06:00
250 lines
8.6 KiB
JavaScript
Executable File
250 lines
8.6 KiB
JavaScript
Executable File
#!/usr/bin/env node
|
|
|
|
// Check node version before requiring/doing anything else
|
|
// The user may be on a very old node version
|
|
|
|
const chalk = require('chalk')
|
|
const semver = require('semver')
|
|
const requiredVersion = require('../package.json').engines.node
|
|
|
|
function checkNodeVersion (wanted, id) {
|
|
if (!semver.satisfies(process.version, wanted)) {
|
|
console.log(chalk.red(
|
|
'You are using Node ' + process.version + ', but this version of ' + id +
|
|
' requires Node ' + wanted + '.\nPlease upgrade your Node version.'
|
|
))
|
|
process.exit(1)
|
|
}
|
|
}
|
|
|
|
checkNodeVersion(requiredVersion, 'vue-cli')
|
|
|
|
if (semver.satisfies(process.version, '9.x')) {
|
|
console.log(chalk.red(
|
|
`You are using Node ${process.version}.\n` +
|
|
`Node.js 9.x has already reached end-of-life and will not be supported in future major releases.\n` +
|
|
`It's strongly recommended to use an active LTS version instead.`
|
|
))
|
|
}
|
|
|
|
const fs = require('fs')
|
|
const path = require('path')
|
|
const slash = require('slash')
|
|
const minimist = require('minimist')
|
|
|
|
// enter debug mode when creating test repo
|
|
if (
|
|
slash(process.cwd()).indexOf('/packages/test') > 0 && (
|
|
fs.existsSync(path.resolve(process.cwd(), '../@vue')) ||
|
|
fs.existsSync(path.resolve(process.cwd(), '../../@vue'))
|
|
)
|
|
) {
|
|
process.env.VUE_CLI_DEBUG = true
|
|
}
|
|
|
|
const program = require('commander')
|
|
const loadCommand = require('../lib/util/loadCommand')
|
|
|
|
program
|
|
.version(require('../package').version)
|
|
.usage('<command> [options]')
|
|
|
|
program
|
|
.command('create <app-name>')
|
|
.description('create a new project powered by vue-cli-service')
|
|
.option('-p, --preset <presetName>', 'Skip prompts and use saved or remote preset')
|
|
.option('-d, --default', 'Skip prompts and use default preset')
|
|
.option('-i, --inlinePreset <json>', 'Skip prompts and use inline JSON string as preset')
|
|
.option('-m, --packageManager <command>', 'Use specified npm client when installing dependencies')
|
|
.option('-r, --registry <url>', 'Use specified npm registry when installing dependencies (only for npm)')
|
|
.option('-g, --git [message]', 'Force git initialization with initial commit message')
|
|
.option('-n, --no-git', 'Skip git initialization')
|
|
.option('-f, --force', 'Overwrite target directory if it exists')
|
|
.option('-c, --clone', 'Use git clone when fetching remote preset')
|
|
.option('-x, --proxy', 'Use specified proxy when creating project')
|
|
.option('-b, --bare', 'Scaffold project without beginner instructions')
|
|
.action((name, cmd) => {
|
|
const options = cleanArgs(cmd)
|
|
|
|
if (minimist(process.argv.slice(3))._.length > 1) {
|
|
console.log(chalk.yellow('\n Info: You provided more than one argument. The first one will be used as the app\'s name, the rest are ignored.'))
|
|
}
|
|
// --git makes commander to default git to true
|
|
if (process.argv.includes('-g') || process.argv.includes('--git')) {
|
|
options.forceGit = true
|
|
}
|
|
require('../lib/create')(name, options)
|
|
})
|
|
|
|
program
|
|
.command('add <plugin> [pluginOptions]')
|
|
.description('install a plugin and invoke its generator in an already created project')
|
|
.option('--registry <url>', 'Use specified npm registry when installing dependencies (only for npm)')
|
|
.allowUnknownOption()
|
|
.action((plugin) => {
|
|
require('../lib/add')(plugin, minimist(process.argv.slice(3)))
|
|
})
|
|
|
|
program
|
|
.command('invoke <plugin> [pluginOptions]')
|
|
.description('invoke the generator of a plugin in an already created project')
|
|
.option('--registry <url>', 'Use specified npm registry when installing dependencies (only for npm)')
|
|
.allowUnknownOption()
|
|
.action((plugin) => {
|
|
require('../lib/invoke')(plugin, minimist(process.argv.slice(3)))
|
|
})
|
|
|
|
program
|
|
.command('inspect [paths...]')
|
|
.description('inspect the webpack config in a project with vue-cli-service')
|
|
.option('--mode <mode>')
|
|
.option('--rule <ruleName>', 'inspect a specific module rule')
|
|
.option('--plugin <pluginName>', 'inspect a specific plugin')
|
|
.option('--rules', 'list all module rule names')
|
|
.option('--plugins', 'list all plugin names')
|
|
.option('-v --verbose', 'Show full function definitions in output')
|
|
.action((paths, cmd) => {
|
|
require('../lib/inspect')(paths, cleanArgs(cmd))
|
|
})
|
|
|
|
program
|
|
.command('serve [entry]')
|
|
.description('serve a .js or .vue file in development mode with zero config')
|
|
.option('-o, --open', 'Open browser')
|
|
.option('-c, --copy', 'Copy local url to clipboard')
|
|
.action((entry, cmd) => {
|
|
loadCommand('serve', '@vue/cli-service-global').serve(entry, cleanArgs(cmd))
|
|
})
|
|
|
|
program
|
|
.command('build [entry]')
|
|
.description('build a .js or .vue file in production mode with zero config')
|
|
.option('-t, --target <target>', 'Build target (app | lib | wc | wc-async, default: app)')
|
|
.option('-n, --name <name>', 'name for lib or web-component mode (default: entry filename)')
|
|
.option('-d, --dest <dir>', 'output directory (default: dist)')
|
|
.action((entry, cmd) => {
|
|
loadCommand('build', '@vue/cli-service-global').build(entry, cleanArgs(cmd))
|
|
})
|
|
|
|
program
|
|
.command('ui')
|
|
.description('start and open the vue-cli ui')
|
|
.option('-H, --host <host>', 'Host used for the UI server (default: localhost)')
|
|
.option('-p, --port <port>', 'Port used for the UI server (by default search for available port)')
|
|
.option('-D, --dev', 'Run in dev mode')
|
|
.option('--quiet', `Don't output starting messages`)
|
|
.option('--headless', `Don't open browser on start and output port`)
|
|
.action((cmd) => {
|
|
checkNodeVersion('>=8.6', 'vue ui')
|
|
require('../lib/ui')(cleanArgs(cmd))
|
|
})
|
|
|
|
program
|
|
.command('init <template> <app-name>')
|
|
.description('generate a project from a remote template (legacy API, requires @vue/cli-init)')
|
|
.option('-c, --clone', 'Use git clone when fetching remote template')
|
|
.option('--offline', 'Use cached template')
|
|
.action(() => {
|
|
loadCommand('init', '@vue/cli-init')
|
|
})
|
|
|
|
program
|
|
.command('config [value]')
|
|
.description('inspect and modify the config')
|
|
.option('-g, --get <path>', 'get value from option')
|
|
.option('-s, --set <path> <value>', 'set option value')
|
|
.option('-d, --delete <path>', 'delete option from config')
|
|
.option('-e, --edit', 'open config with default editor')
|
|
.option('--json', 'outputs JSON result only')
|
|
.action((value, cmd) => {
|
|
require('../lib/config')(value, cleanArgs(cmd))
|
|
})
|
|
|
|
program
|
|
.command('upgrade [semverLevel]')
|
|
.description('upgrade vue cli service / plugins (default semverLevel: minor)')
|
|
.action((semverLevel, cmd) => {
|
|
loadCommand('upgrade', '@vue/cli-upgrade')(semverLevel, cleanArgs(cmd))
|
|
})
|
|
|
|
program
|
|
.command('info')
|
|
.description('print debugging information about your environment')
|
|
.action((cmd) => {
|
|
console.log(chalk.bold('\nEnvironment Info:'))
|
|
require('envinfo').run(
|
|
{
|
|
System: ['OS', 'CPU'],
|
|
Binaries: ['Node', 'Yarn', 'npm'],
|
|
Browsers: ['Chrome', 'Edge', 'Firefox', 'Safari'],
|
|
npmPackages: '/**/{typescript,*vue*,@vue/*/}',
|
|
npmGlobalPackages: ['@vue/cli']
|
|
},
|
|
{
|
|
showNotFound: true,
|
|
duplicates: true,
|
|
fullTree: true
|
|
}
|
|
).then(console.log)
|
|
})
|
|
|
|
// output help information on unknown commands
|
|
program
|
|
.arguments('<command>')
|
|
.action((cmd) => {
|
|
program.outputHelp()
|
|
console.log(` ` + chalk.red(`Unknown command ${chalk.yellow(cmd)}.`))
|
|
console.log()
|
|
})
|
|
|
|
// add some useful info on help
|
|
program.on('--help', () => {
|
|
console.log()
|
|
console.log(` Run ${chalk.cyan(`vue <command> --help`)} for detailed usage of given command.`)
|
|
console.log()
|
|
})
|
|
|
|
program.commands.forEach(c => c.on('--help', () => console.log()))
|
|
|
|
// enhance common error messages
|
|
const enhanceErrorMessages = require('../lib/util/enhanceErrorMessages')
|
|
|
|
enhanceErrorMessages('missingArgument', argName => {
|
|
return `Missing required argument ${chalk.yellow(`<${argName}>`)}.`
|
|
})
|
|
|
|
enhanceErrorMessages('unknownOption', optionName => {
|
|
return `Unknown option ${chalk.yellow(optionName)}.`
|
|
})
|
|
|
|
enhanceErrorMessages('optionMissingArgument', (option, flag) => {
|
|
return `Missing required argument for option ${chalk.yellow(option.flags)}` + (
|
|
flag ? `, got ${chalk.yellow(flag)}` : ``
|
|
)
|
|
})
|
|
|
|
program.parse(process.argv)
|
|
|
|
if (!process.argv.slice(2).length) {
|
|
program.outputHelp()
|
|
}
|
|
|
|
function camelize (str) {
|
|
return str.replace(/-(\w)/g, (_, c) => c ? c.toUpperCase() : '')
|
|
}
|
|
|
|
// commander passes the Command object itself as options,
|
|
// extract only actual options into a fresh object.
|
|
function cleanArgs (cmd) {
|
|
const args = {}
|
|
cmd.options.forEach(o => {
|
|
const key = camelize(o.long.replace(/^--/, ''))
|
|
// if an option is not present and Command has a method with the same name
|
|
// it should not be copied
|
|
if (typeof cmd[key] !== 'function' && typeof cmd[key] !== 'undefined') {
|
|
args[key] = cmd[key]
|
|
}
|
|
})
|
|
return args
|
|
}
|