1 | #!/usr/bin/env node
|
2 |
|
3 |
|
4 |
|
5 |
|
6 | const { chalk, semver } = require('@vue/cli-shared-utils')
|
7 | const requiredVersion = require('../package.json').engines.node
|
8 | const leven = require('leven')
|
9 |
|
10 | function checkNodeVersion (wanted, id) {
|
11 | if (!semver.satisfies(process.version, wanted, { includePrerelease: true })) {
|
12 | console.log(chalk.red(
|
13 | 'You are using Node ' + process.version + ', but this version of ' + id +
|
14 | ' requires Node ' + wanted + '.\nPlease upgrade your Node version.'
|
15 | ))
|
16 | process.exit(1)
|
17 | }
|
18 | }
|
19 |
|
20 | checkNodeVersion(requiredVersion, '@vue/cli')
|
21 |
|
22 | if (semver.satisfies(process.version, '9.x')) {
|
23 | console.log(chalk.red(
|
24 | `You are using Node ${process.version}.\n` +
|
25 | `Node.js 9.x has already reached end-of-life and will not be supported in future major releases.\n` +
|
26 | `It's strongly recommended to use an active LTS version instead.`
|
27 | ))
|
28 | }
|
29 |
|
30 | const fs = require('fs')
|
31 | const path = require('path')
|
32 | const slash = require('slash')
|
33 | const minimist = require('minimist')
|
34 |
|
35 |
|
36 | if (
|
37 | slash(process.cwd()).indexOf('/packages/test') > 0 && (
|
38 | fs.existsSync(path.resolve(process.cwd(), '../@vue')) ||
|
39 | fs.existsSync(path.resolve(process.cwd(), '../../@vue'))
|
40 | )
|
41 | ) {
|
42 | process.env.VUE_CLI_DEBUG = true
|
43 | }
|
44 |
|
45 | const program = require('commander')
|
46 | const loadCommand = require('../lib/util/loadCommand')
|
47 |
|
48 | program
|
49 | .version(`@vue/cli ${require('../package').version}`)
|
50 | .usage('<command> [options]')
|
51 |
|
52 | program
|
53 | .command('create <app-name>')
|
54 | .description('create a new project powered by vue-cli-service')
|
55 | .option('-p, --preset <presetName>', 'Skip prompts and use saved or remote preset')
|
56 | .option('-d, --default', 'Skip prompts and use default preset')
|
57 | .option('-i, --inlinePreset <json>', 'Skip prompts and use inline JSON string as preset')
|
58 | .option('-m, --packageManager <command>', 'Use specified npm client when installing dependencies')
|
59 | .option('-r, --registry <url>', 'Use specified npm registry when installing dependencies (only for npm)')
|
60 | .option('-g, --git [message]', 'Force git initialization with initial commit message')
|
61 | .option('-n, --no-git', 'Skip git initialization')
|
62 | .option('-f, --force', 'Overwrite target directory if it exists')
|
63 | .option('--merge', 'Merge target directory if it exists')
|
64 | .option('-c, --clone', 'Use git clone when fetching remote preset')
|
65 | .option('-x, --proxy', 'Use specified proxy when creating project')
|
66 | .option('-b, --bare', 'Scaffold project without beginner instructions')
|
67 | .option('--skipGetStarted', 'Skip displaying "Get started" instructions')
|
68 | .action((name, cmd) => {
|
69 | const options = cleanArgs(cmd)
|
70 |
|
71 | if (minimist(process.argv.slice(3))._.length > 1) {
|
72 | 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.'))
|
73 | }
|
74 |
|
75 | if (process.argv.includes('-g') || process.argv.includes('--git')) {
|
76 | options.forceGit = true
|
77 | }
|
78 | require('../lib/create')(name, options)
|
79 | })
|
80 |
|
81 | program
|
82 | .command('add <plugin> [pluginOptions]')
|
83 | .description('install a plugin and invoke its generator in an already created project')
|
84 | .option('--registry <url>', 'Use specified npm registry when installing dependencies (only for npm)')
|
85 | .allowUnknownOption()
|
86 | .action((plugin) => {
|
87 | require('../lib/add')(plugin, minimist(process.argv.slice(3)))
|
88 | })
|
89 |
|
90 | program
|
91 | .command('invoke <plugin> [pluginOptions]')
|
92 | .description('invoke the generator of a plugin in an already created project')
|
93 | .option('--registry <url>', 'Use specified npm registry when installing dependencies (only for npm)')
|
94 | .allowUnknownOption()
|
95 | .action((plugin) => {
|
96 | require('../lib/invoke')(plugin, minimist(process.argv.slice(3)))
|
97 | })
|
98 |
|
99 | program
|
100 | .command('inspect [paths...]')
|
101 | .description('inspect the webpack config in a project with vue-cli-service')
|
102 | .option('--mode <mode>')
|
103 | .option('--rule <ruleName>', 'inspect a specific module rule')
|
104 | .option('--plugin <pluginName>', 'inspect a specific plugin')
|
105 | .option('--rules', 'list all module rule names')
|
106 | .option('--plugins', 'list all plugin names')
|
107 | .option('-v --verbose', 'Show full function definitions in output')
|
108 | .action((paths, cmd) => {
|
109 | require('../lib/inspect')(paths, cleanArgs(cmd))
|
110 | })
|
111 |
|
112 | program
|
113 | .command('serve [entry]')
|
114 | .description('serve a .js or .vue file in development mode with zero config')
|
115 | .option('-o, --open', 'Open browser')
|
116 | .option('-c, --copy', 'Copy local url to clipboard')
|
117 | .option('-p, --port <port>', 'Port used by the server (default: 8080 or next available port)')
|
118 | .action((entry, cmd) => {
|
119 | loadCommand('serve', '@vue/cli-service-global').serve(entry, cleanArgs(cmd))
|
120 | })
|
121 |
|
122 | program
|
123 | .command('build [entry]')
|
124 | .description('build a .js or .vue file in production mode with zero config')
|
125 | .option('-t, --target <target>', 'Build target (app | lib | wc | wc-async, default: app)')
|
126 | .option('-n, --name <name>', 'name for lib or web-component mode (default: entry filename)')
|
127 | .option('-d, --dest <dir>', 'output directory (default: dist)')
|
128 | .action((entry, cmd) => {
|
129 | loadCommand('build', '@vue/cli-service-global').build(entry, cleanArgs(cmd))
|
130 | })
|
131 |
|
132 | program
|
133 | .command('ui')
|
134 | .description('start and open the vue-cli ui')
|
135 | .option('-H, --host <host>', 'Host used for the UI server (default: localhost)')
|
136 | .option('-p, --port <port>', 'Port used for the UI server (by default search for available port)')
|
137 | .option('-D, --dev', 'Run in dev mode')
|
138 | .option('--quiet', `Don't output starting messages`)
|
139 | .option('--headless', `Don't open browser on start and output port`)
|
140 | .action((cmd) => {
|
141 | checkNodeVersion('>=8.6', 'vue ui')
|
142 | require('../lib/ui')(cleanArgs(cmd))
|
143 | })
|
144 |
|
145 | program
|
146 | .command('init <template> <app-name>')
|
147 | .description('generate a project from a remote template (legacy API, requires @vue/cli-init)')
|
148 | .option('-c, --clone', 'Use git clone when fetching remote template')
|
149 | .option('--offline', 'Use cached template')
|
150 | .action(() => {
|
151 | loadCommand('init', '@vue/cli-init')
|
152 | })
|
153 |
|
154 | program
|
155 | .command('config [value]')
|
156 | .description('inspect and modify the config')
|
157 | .option('-g, --get <path>', 'get value from option')
|
158 | .option('-s, --set <path> <value>', 'set option value')
|
159 | .option('-d, --delete <path>', 'delete option from config')
|
160 | .option('-e, --edit', 'open config with default editor')
|
161 | .option('--json', 'outputs JSON result only')
|
162 | .action((value, cmd) => {
|
163 | require('../lib/config')(value, cleanArgs(cmd))
|
164 | })
|
165 |
|
166 | program
|
167 | .command('outdated')
|
168 | .description('(experimental) check for outdated vue cli service / plugins')
|
169 | .option('--next', 'Also check for alpha / beta / rc versions when upgrading')
|
170 | .action((cmd) => {
|
171 | require('../lib/outdated')(cleanArgs(cmd))
|
172 | })
|
173 |
|
174 | program
|
175 | .command('upgrade [plugin-name]')
|
176 | .description('(experimental) upgrade vue cli service / plugins')
|
177 | .option('-t, --to <version>', 'Upgrade <package-name> to a version that is not latest')
|
178 | .option('-f, --from <version>', 'Skip probing installed plugin, assuming it is upgraded from the designated version')
|
179 | .option('-r, --registry <url>', 'Use specified npm registry when installing dependencies')
|
180 | .option('--all', 'Upgrade all plugins')
|
181 | .option('--next', 'Also check for alpha / beta / rc versions when upgrading')
|
182 | .action((packageName, cmd) => {
|
183 | require('../lib/upgrade')(packageName, cleanArgs(cmd))
|
184 | })
|
185 |
|
186 | program
|
187 | .command('migrate [plugin-name]')
|
188 | .description('(experimental) run migrator for an already-installed cli plugin')
|
189 |
|
190 | .option('-f, --from <version>', 'The base version for the migrator to migrate from')
|
191 | .action((packageName, cmd) => {
|
192 | require('../lib/migrate')(packageName, cleanArgs(cmd))
|
193 | })
|
194 |
|
195 | program
|
196 | .command('info')
|
197 | .description('print debugging information about your environment')
|
198 | .action((cmd) => {
|
199 | console.log(chalk.bold('\nEnvironment Info:'))
|
200 | require('envinfo').run(
|
201 | {
|
202 | System: ['OS', 'CPU'],
|
203 | Binaries: ['Node', 'Yarn', 'npm'],
|
204 | Browsers: ['Chrome', 'Edge', 'Firefox', 'Safari'],
|
205 | npmPackages: '/**/{typescript,*vue*,@vue/*/}',
|
206 | npmGlobalPackages: ['@vue/cli']
|
207 | },
|
208 | {
|
209 | showNotFound: true,
|
210 | duplicates: true,
|
211 | fullTree: true
|
212 | }
|
213 | ).then(console.log)
|
214 | })
|
215 |
|
216 |
|
217 | program
|
218 | .arguments('<command>')
|
219 | .action((cmd) => {
|
220 | program.outputHelp()
|
221 | console.log(` ` + chalk.red(`Unknown command ${chalk.yellow(cmd)}.`))
|
222 | console.log()
|
223 | suggestCommands(cmd)
|
224 | })
|
225 |
|
226 |
|
227 | program.on('--help', () => {
|
228 | console.log()
|
229 | console.log(` Run ${chalk.cyan(`vue <command> --help`)} for detailed usage of given command.`)
|
230 | console.log()
|
231 | })
|
232 |
|
233 | program.commands.forEach(c => c.on('--help', () => console.log()))
|
234 |
|
235 |
|
236 | const enhanceErrorMessages = require('../lib/util/enhanceErrorMessages')
|
237 |
|
238 | enhanceErrorMessages('missingArgument', argName => {
|
239 | return `Missing required argument ${chalk.yellow(`<${argName}>`)}.`
|
240 | })
|
241 |
|
242 | enhanceErrorMessages('unknownOption', optionName => {
|
243 | return `Unknown option ${chalk.yellow(optionName)}.`
|
244 | })
|
245 |
|
246 | enhanceErrorMessages('optionMissingArgument', (option, flag) => {
|
247 | return `Missing required argument for option ${chalk.yellow(option.flags)}` + (
|
248 | flag ? `, got ${chalk.yellow(flag)}` : ``
|
249 | )
|
250 | })
|
251 |
|
252 | program.parse(process.argv)
|
253 |
|
254 | if (!process.argv.slice(2).length) {
|
255 | program.outputHelp()
|
256 | }
|
257 |
|
258 | function suggestCommands (unknownCommand) {
|
259 | const availableCommands = program.commands.map(cmd => cmd._name)
|
260 |
|
261 | let suggestion
|
262 |
|
263 | availableCommands.forEach(cmd => {
|
264 | const isBestMatch = leven(cmd, unknownCommand) < leven(suggestion || '', unknownCommand)
|
265 | if (leven(cmd, unknownCommand) < 3 && isBestMatch) {
|
266 | suggestion = cmd
|
267 | }
|
268 | })
|
269 |
|
270 | if (suggestion) {
|
271 | console.log(` ` + chalk.red(`Did you mean ${chalk.yellow(suggestion)}?`))
|
272 | }
|
273 | }
|
274 |
|
275 | function camelize (str) {
|
276 | return str.replace(/-(\w)/g, (_, c) => c ? c.toUpperCase() : '')
|
277 | }
|
278 |
|
279 |
|
280 |
|
281 | function cleanArgs (cmd) {
|
282 | const args = {}
|
283 | cmd.options.forEach(o => {
|
284 | const key = camelize(o.long.replace(/^--/, ''))
|
285 |
|
286 |
|
287 | if (typeof cmd[key] !== 'function' && typeof cmd[key] !== 'undefined') {
|
288 | args[key] = cmd[key]
|
289 | }
|
290 | })
|
291 | return args
|
292 | }
|