From 9aed45a9d99218e7468ce2779dcbaa40cce50c83 Mon Sep 17 00:00:00 2001 From: Blake Friedman Date: Thu, 18 Jul 2024 04:48:19 -0700 Subject: [PATCH] always proxy to @react-native-community/cli (#45464) Summary: Pull Request resolved: https://github.com/facebook/react-native/pull/45464 Previous work would cause versions >= react-native 0.76 to exit if called through `npx react-native `. This was intended to be full deprecated and removed. The intention was to shift users to calling react-native-community/cli directly. This change allows commands to be proxied to react-native-community/cli but with no guarantees of success. It's up to each framework / project to explicitly create that dependency. This also provides warnings, which won't go away, suggesting the supported method of calling the community CLI directly. The outcome is that we're not going to break existing workflows. closes: #45461 Changelog: [General][Fixed] allow proxying commands from react-native to react-native-community/cli with explicit warning Reviewed By: cortinico Differential Revision: D59805357 fbshipit-source-id: 21e23b082a9c709effa050d8e7dd04a40f5ab0e6 --- packages/react-native/cli.js | 61 ++++++++++++++++++++++++++---------- 1 file changed, 45 insertions(+), 16 deletions(-) diff --git a/packages/react-native/cli.js b/packages/react-native/cli.js index 416bd2775590c6..1f57a1c01b58a1 100755 --- a/packages/react-native/cli.js +++ b/packages/react-native/cli.js @@ -22,6 +22,13 @@ const deprecated = () => { ); }; +function isMissingCliDependency(error) { + return ( + error.code === 'MODULE_NOT_FOUND' && + /@react-native-community\/cli/.test(error.message) + ); +} + let cli = { bin: '/dev/null', loadConfig: deprecated, @@ -107,17 +114,30 @@ The behavior will be changed on ${chalk.white.bold(CLI_DEPRECATION_DATE.toLocale } function warnWithDeprecated() { - if (process.argv[2] !== 'init') { + if (!isInitCommand) { return; } console.warn(` -${chalk.yellow('⚠')}️ The \`init\` command is deprecated. +${chalk.yellow('🚨')}️ The \`init\` command is deprecated. - Switch to ${chalk.dim('npx @react-native-community/cli init')} for the identical behavior. - Refer to the documentation for information about alternative tools: ${chalk.dim('https://reactnative.dev/docs/getting-started')}`); } +function warnWithExplicitDependency(version = '*') { + console.warn(` +${chalk.yellow('⚠')}️ ${chalk.dim('react-native')} depends on ${chalk.dim('@react-native-community/cli')} for cli commands. To fix update your ${chalk.dim('package.json')} to include: + +${chalk.white.bold(` + "devDependencies": { + "@react-native-community/cli": "latest", + } +`)} + +`); +} + /** * npx react-native -> @react-native-community/cli * @@ -157,24 +177,36 @@ async function main() { currentVersion.startsWith('0.76'); /** - * This command now fails as it's fully deprecated. It will be entirely removed in 0.77. + * This command is now deprecated. We will continue to proxy commands to @react-native-community/cli, but it + * isn't supported anymore. We'll always show the warning. + * + * WARNING: Projects will have to have an explicit dependency on @react-native-community/cli to use the CLI. * * Phase 3 * * @see https://github.com/react-native-community/discussions-and-proposals/tree/main/proposals/0759-react-native-frameworks.md */ - if (currentVersion !== HEAD && isDeprecated) { - warnWithDeprecated(); - process.exit(1); + if (isInitCommand) { + if (currentVersion !== HEAD && isDeprecated) { + warnWithDeprecated(); + // We only exit if the user calls `init` and it's deprecated. All other cases should proxy to to @react-native-community/cli. + // Be careful with this as it can break a lot of users. + process.exit(1); + } else if (currentVersion.startsWith('0.75')) { + warnWithDeprecationSchedule(); + } + warnWhenRunningInit(); } - if (currentVersion.startsWith('0.75')) { - warnWithDeprecationSchedule(); + try { + return require('@react-native-community/cli').run(name); + } catch (e) { + if (isMissingCliDependency(e)) { + warnWithExplicitDependency(); + process.exit(1); + } + throw e; } - - warnWhenRunningInit(); - - return require('@react-native-community/cli').run(name); } if (require.main === module) { @@ -185,10 +217,7 @@ if (require.main === module) { } catch (e) { // We silence @react-native-community/cli missing as it is no // longer a dependency - if ( - !e.code === 'MODULE_NOT_FOUND' && - /@react-native-community\/cli/.test(e.message) - ) { + if (!isMissingCliDependency(e)) { throw e; } }