diff --git a/packages/cli/package.json b/packages/cli/package.json index 5662ced6b..fff93c214 100644 --- a/packages/cli/package.json +++ b/packages/cli/package.json @@ -20,7 +20,7 @@ }, "dependencies": { "chalk": "^1.1.1", - "commander": "^2.9.0", + "commander": "^2.19.0", "compression": "^1.7.1", "connect": "^3.6.5", "denodeify": "^1.2.1", diff --git a/packages/cli/src/cliEntry.js b/packages/cli/src/cliEntry.js index 90ee8dea5..7b03f702e 100644 --- a/packages/cli/src/cliEntry.js +++ b/packages/cli/src/cliEntry.js @@ -10,7 +10,6 @@ import chalk from 'chalk'; import childProcess from 'child_process'; import commander from 'commander'; -import minimist from 'minimist'; import path from 'path'; import type {CommandT, ContextT} from './tools/types.flow'; import getLegacyConfig from './tools/getLegacyConfig'; @@ -18,10 +17,10 @@ import {getCommands} from './commands'; import init from './commands/init/init'; import assertRequiredOptions from './tools/assertRequiredOptions'; import logger from './tools/logger'; -import pkg from '../package.json'; +import pkgJson from '../package.json'; commander - .version(pkg.version) + .option('--version', 'Print CLI version') .option('--projectRoot [string]', 'Path to the root of the project') .option('--reactNativePath [string]', 'Path to React Native'); @@ -39,41 +38,33 @@ const handleError = err => { // Custom printHelpInformation command inspired by internal Commander.js // one modified to suit our needs -function printHelpInformation() { +function printHelpInformation(examples, pkg) { let cmdName = this._name; if (this._alias) { cmdName = `${cmdName}|${this._alias}`; } - const sourceInformation = this.pkg - ? [` ${chalk.bold('Source:')} ${this.pkg.name}@${this.pkg.version}`, ''] + const sourceInformation = pkg + ? [`${chalk.bold('Source:')} ${pkg.name}@${pkg.version}`, ''] : []; let output = [ - '', - chalk.bold(chalk.cyan(` react-native ${cmdName} ${this.usage()}`)), - this._description ? ` ${this._description}` : '', - '', + chalk.bold(`react-native ${cmdName} ${this.usage()}`), + this._description ? `\n${this._description}\n` : '', ...sourceInformation, - ` ${chalk.bold('Options:')}`, - '', - this.optionHelp().replace(/^/gm, ' '), - '', + `${chalk.bold('Options:')}`, + this.optionHelp().replace(/^/gm, ' '), ]; - if (this.examples && this.examples.length > 0) { - const formattedUsage = this.examples - .map(example => ` ${example.desc}: \n ${chalk.cyan(example.cmd)}`) + if (examples && examples.length > 0) { + const formattedUsage = examples + .map(example => ` ${example.desc}: \n ${chalk.cyan(example.cmd)}`) .join('\n\n'); - output = output.concat([ - chalk.bold(' Example usage:'), - '', - formattedUsage, - ]); + output = output.concat([chalk.bold('\nExample usage:'), formattedUsage]); } - return output.concat(['', '']).join('\n'); + return output.join('\n'); } function printUnknownCommand(cmdName) { @@ -93,9 +84,7 @@ const addCommand = (command: CommandT, ctx: ContextT) => { const options = command.options || []; const cmd = commander - .command(command.name, undefined, { - noHelp: !command.description, - }) + .command(command.name, undefined, {noHelp: !command.description}) .description(command.description) .action(function handleAction(...args) { const passedOptions = this.opts(); @@ -109,10 +98,12 @@ const addCommand = (command: CommandT, ctx: ContextT) => { .catch(handleError); }); - cmd.helpInformation = printHelpInformation.bind(cmd); - cmd.examples = command.examples; - // $FlowFixMe: This is either null or not - cmd.pkg = command.pkg; + cmd.helpInformation = printHelpInformation.bind( + cmd, + command.examples, + // $FlowFixMe - we know pkg may be missing... + command.pkg, + ); options.forEach(opt => cmd.option( @@ -123,7 +114,11 @@ const addCommand = (command: CommandT, ctx: ContextT) => { ), ); - // Redefined here to appear in the `--help` section + /** + * We want every command (like "start", "link") to accept below options. + * To achieve that we append them to regular options of each command here. + * This way they'll be displayed in the commands --help menus. + */ cmd .option('--projectRoot [string]', 'Path to the root of the project') .option('--reactNativePath [string]', 'Path to React Native'); @@ -157,20 +152,12 @@ async function setupAndRun() { } } - /** - * Read passed `options` and take the "global" settings - * - * @todo(grabbou): Consider unifying this by removing either `commander` - * or `minimist` - */ - const options = minimist(process.argv.slice(2)); - - const root = options.projectRoot - ? path.resolve(options.projectRoot) + const root = commander.projectRoot + ? path.resolve(commander.projectRoot) : process.cwd(); - const reactNativePath = options.reactNativePath - ? path.resolve(options.reactNativePath) + const reactNativePath = commander.reactNativePath + ? path.resolve(commander.reactNativePath) : (() => { try { return path.dirname( @@ -198,9 +185,16 @@ async function setupAndRun() { commander.parse(process.argv); - if (!options._.length) { + if (commander.rawArgs.length === 2) { commander.outputHelp(); } + + // We handle --version as a special case like this because both `commander` + // and `yargs` append it to every command and we don't want to do that. + // E.g. outside command `init` has --version flag and we want to preserve it. + if (commander.args.length === 0 && commander.version === true) { + console.log(pkgJson.version); + } } export default { diff --git a/yarn.lock b/yarn.lock index 004d46d55..77823481f 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2381,17 +2381,20 @@ combined-stream@^1.0.6, combined-stream@~1.0.6: dependencies: delayed-stream "~1.0.0" -commander@^2.9.0: +commander@^2.19.0: version "2.19.0" resolved "https://registry.yarnpkg.com/commander/-/commander-2.19.0.tgz#f6198aa84e5b83c46054b94ddedbfed5ee9ff12a" + integrity sha512-6tvAOO+D6OENvRAh524Dh9jcfKTYDQAqvqezbCW82xj5X0pSrcpxtvRKHLG0yBY6SD7PSDrJaj+0AiOcKVd1Xg== commander@~2.13.0: version "2.13.0" resolved "https://registry.yarnpkg.com/commander/-/commander-2.13.0.tgz#6964bca67685df7c1f1430c584f07d7597885b9c" + integrity sha512-MVuS359B+YzaWqjCL/c+22gfryv+mCBPHAv3zyVI2GN8EY6IRP8VwtasXn8jyyhvvq84R4ImN1OKRtcbIasjYA== commander@~2.17.1: version "2.17.1" resolved "https://registry.yarnpkg.com/commander/-/commander-2.17.1.tgz#bd77ab7de6de94205ceacc72f1716d29f20a77bf" + integrity sha512-wPMUt6FnH2yzG95SA6mzjQOEKUU3aLaDEmzs1ti+1E9h+CsrZghRlqEM/EJ4KscsQVG8uNN4uVreUeT8+drlgg== compare-func@^1.3.1: version "1.3.2"