From c27f1732241cb029be92fbe1e58b2079e26a8702 Mon Sep 17 00:00:00 2001 From: Alex Hunt Date: Fri, 26 Jun 2026 09:51:48 -0700 Subject: [PATCH] Remove deprecated init command handling from CLI MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Summary: The deprecation timeline for proxying `npx react-native init` to `react-native-community/cli` has long since passed. The version check, staged deprecation warnings, and proxy spawn are all dead code. Strip out — leaving only the `warnWithExplicitDependency` exit path that runs when `react-native-community/cli` is not installed. Changelog: [Internal] Reviewed By: robhogan Differential Revision: D109854306 --- packages/react-native/cli.js | 185 +---------------------------------- 1 file changed, 3 insertions(+), 182 deletions(-) diff --git a/packages/react-native/cli.js b/packages/react-native/cli.js index 2c6f6f779b22..09740a4a25de 100755 --- a/packages/react-native/cli.js +++ b/packages/react-native/cli.js @@ -11,16 +11,8 @@ 'use strict'; -/*:: -import type {IncomingMessage} from 'https'; -*/ - // $FlowFixMe[untyped-import] -const {name, version: currentVersion} = require('./package.json'); -const {spawn} = require('child_process'); -const {get} = require('https'); -const semver = require('semver'); -const {URL} = require('url'); +const {name} = require('./package.json'); const {styleText} = require('util'); const deprecated = () => { @@ -57,105 +49,13 @@ let cli /*: Readonly<{ run: deprecated, }; -const isNpxRuntime = process.env.npm_lifecycle_event === 'npx'; -const isInitCommand = process.argv[2] === 'init'; -const DEFAULT_REGISTRY_HOST = - process.env.npm_config_registry ?? 'https://registry.npmjs.org/'; -const HEAD = '1000.0.0'; - -// We're going to deprecate the `init` command proxying requests to @react-native-community/cli transparently -// on December 31th, 2024 or 0.76 (whichever arrives first). This is part of work to decouple of community CLI from React Native core. -// -// See https://github.com/react-native-community/discussions-and-proposals/blob/main/proposals/0759-react-native-frameworks.md -const CLI_DEPRECATION_DATE = new Date('2024-12-31'); - -function getLatestVersion( - registryHost /*: string */ = DEFAULT_REGISTRY_HOST, -) /*: Promise */ { - return new Promise((resolve, reject) => { - const url = new URL(registryHost); - url.pathname = 'react-native/latest'; - get(url.toString(), (resp /*: IncomingMessage */) => { - const buffer = []; - resp.on('data', data => buffer.push(data)); - resp.on('end', () => { - try { - resolve(JSON.parse(Buffer.concat(buffer).toString('utf8')).version); - } catch (e) { - reject(e); - } - }); - }).on('error', e => reject(e)); - }); -} - -/** - * Warn when users are using `npx react-native init`, to raise awareness of the changes from RFC 0759. - * - * Phase 1 - * - * @see https://github.com/react-native-community/discussions-and-proposals/tree/main/proposals/0759-react-native-frameworks.md - */ -function warnWhenRunningInit() { - if (isInitCommand) { - console.warn( - `\nRunning: ${styleText(['grey', 'bold'], 'npx @react-native-community/cli init')}\n`, - ); - } -} - -/** - * Warn more sternly that the ability to call `npx react-native init` is going away. - * - * Phase 2 - * - * @see https://github.com/react-native-community/discussions-and-proposals/tree/main/proposals/0759-react-native-frameworks.md - */ -function warnWithDeprecationSchedule() { - if (!isInitCommand) { - return; - } - - const daysRemaining = Math.ceil( - (CLI_DEPRECATION_DATE.getTime() - new Date().getTime()) / 86_400_000, - ); - - const emphasis = (text /*: string */) => - daysRemaining < 10 - ? styleText(['bgRed', 'white', 'bold'], text) - : daysRemaining < 30 - ? styleText(['red', 'bold'], text) - : daysRemaining < 60 - ? styleText(['green', 'bold'], text) - : styleText(['blueBright', 'bold'], text); - - console.warn(` -${styleText('yellow', '⚠️')} The \`init\` command is deprecated. -The behavior will be changed on ${styleText(['white', 'bold'], CLI_DEPRECATION_DATE.toLocaleDateString())} ${emphasis(`(${daysRemaining} day${daysRemaining > 1 ? 's' : ''})`)}. - -- Switch to ${styleText(['grey', 'bold'], 'npx @react-native-community/cli init')} for the identical behavior. -- Refer to the documentation for information about alternative tools: ${styleText('dim', 'https://reactnative.dev/docs/getting-started')}`); -} - -function warnWithDeprecated() { - if (!isInitCommand) { - return; - } - console.warn(` -🚨️ The \`init\` command is deprecated. - -- Switch to ${styleText(['grey', 'bold'], 'npx @react-native-community/cli init')} for the identical behavior. -- Refer to the documentation for information about alternative tools: ${styleText('dim', 'https://reactnative.dev/docs/getting-started')}`); -} - function warnWithExplicitDependency(version /*: string */ = '*') { console.warn(` ${styleText('yellow', '⚠')}️ ${styleText(['dim'], 'react-native')} depends on ${styleText('dim', '@react-native-community/cli')} for cli commands. To fix update your ${styleText(['dim'], 'package.json')} to include: ${styleText( ['white', 'bold'], - ` - "devDependencies": { + ` "devDependencies": { "@react-native-community/cli": "latest", } `, @@ -164,86 +64,7 @@ ${styleText( `); } -/** - * npx react-native -> @react-native-community/cli - * - * Will perform a version check and warning if you're not running the latest community cli when executed using npx. If - * you know what you're doing, you can skip this check: - * - * SKIP=true npx react-native ... - * - */ -async function main() { - if ( - isNpxRuntime && - !Boolean(process.env.SKIP) && - currentVersion !== HEAD && - isInitCommand - ) { - try { - const latest = await getLatestVersion(); - // TODO: T184416093 When cli is deprecated, remove semver from package.json - if (semver.lt(currentVersion, latest)) { - const msg = ` - ${styleText(['bold', 'yellow'], 'WARNING:')} You should run ${styleText( - ['white', 'bold'], - 'npx react-native@latest', - )} to ensure you're always using the most current version of the CLI. NPX has cached version (${styleText( - ['bold', 'yellow'], - currentVersion, - )}) != current release (${styleText(['bold', 'green'], latest)}) - `; - console.warn(msg); - } - } catch (_) { - // Ignore errors, since it's a nice to have warning - } - } - - const isDeprecated = - CLI_DEPRECATION_DATE.getTime() <= new Date().getTime() || - currentVersion.startsWith('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 (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. - console.warn(`${styleText('green', 'Exiting...')}`); - process.exit(1); - } else if ( - currentVersion.startsWith('0.75') || - currentVersion.startsWith('0.76') - ) { - // We check deprecation schedule only for 0.75 and 0.76 and 0.77 is expected to land in Jan 2025. - warnWithDeprecationSchedule(); - } - warnWhenRunningInit(); - - const proc = spawn( - 'npx', - ['@react-native-community/cli', ...process.argv.slice(2)], - { - stdio: 'inherit', - }, - ); - - const code /*: number */ = await new Promise(resolve => { - proc.on('exit', resolve); - }); - process.exit(code); - } - +function main() { try { return findCommunityCli().run(name); } catch (e) {