From e93d6998f7ed060a18bfab45e0c025c5f92456c8 Mon Sep 17 00:00:00 2001 From: Alex Hunt Date: Fri, 24 Jul 2026 07:22:05 -0700 Subject: [PATCH 1/2] Move codegen and spm command wrappers into community-cli-plugin MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Summary: Migrate the `codegen` and `spm` command implementations out of `react-native.config.js` and into the `react-native/community-cli-plugin` package, alongside the existing `bundleCommand` and `startCommand`. This continues moving command definitions into the plugin so `react-native.config.js` becomes a thin routing layer, as the file's own comment already calls for. **Changes** - Add `src/commands/spm/index.js` and `src/commands/codegen/index.js`, each defining and default-exporting its command (unchanged `name`, `description`, and `options`) plus an exported args type — mirroring the `bundle`/`start` command structure. - Export `spmCommand` and `codegenCommand` from `src/index.flow.js`. - Drop the inline `spmCommand` and `codegenCommand` definitions from `react-native.config.js`. Changelog: [Internal] Differential Revision: D113412987 --- packages/community-cli-plugin/README.md | 42 ++++++ .../src/commands/codegen.js | 63 +++++++++ .../community-cli-plugin/src/commands/spm.js | 118 ++++++++++++++++ .../community-cli-plugin/src/index.flow.js | 2 + packages/react-native/react-native.config.js | 132 ++---------------- 5 files changed, 235 insertions(+), 122 deletions(-) create mode 100644 packages/community-cli-plugin/src/commands/codegen.js create mode 100644 packages/community-cli-plugin/src/commands/spm.js diff --git a/packages/community-cli-plugin/README.md b/packages/community-cli-plugin/README.md index 030640fdc67b..109193ff9c81 100644 --- a/packages/community-cli-plugin/README.md +++ b/packages/community-cli-plugin/README.md @@ -75,6 +75,48 @@ npx @react-native-community/cli bundle --entry-file [options] | `--read-global-cache` | Attempt to fetch transformed JS code from the global cache, if configured. Defaults to `false`. | | `--config ` | Path to the CLI configuration file. | +### `codegen` + +Run the React Native codegen, generating native boilerplate from JS spec files. + +#### Usage + +```sh +npx @react-native-community/cli codegen [options] +``` + +#### Options + +| Option | Description | +| - | - | +| `--path ` | Path to the React Native project root. Defaults to the current working directory. | +| `--platform ` | Target platform. Supported values: `"android"`, `"ios"`, `"all"`. Defaults to `"all"`. | +| `--outputPath ` | Path where generated artifacts will be output to. | +| `--source ` | Whether the script is invoked from an `app` or a `library`. Defaults to `"app"`. | + +### `spm [action]` + +Set up or maintain Swift Package Manager support for the iOS/macOS app. Actions: `add`, `update`, `deinit`, `scaffold`. With no action: `add` (or `update` if SPM is already set up). + +#### Usage + +```sh +npx @react-native-community/cli spm [action] [options] +``` + +#### Options + +| Option | Description | +| - | - | +| `--version ` | React Native version (e.g. `0.80.0`). Defaults to the version in `node_modules/react-native/package.json`. | +| `--yes` | Skip the dirty-pbxproj confirmation prompt. | +| `--xcodeproj ` | **[add]** Path to the `.xcodeproj` to inject SPM packages into (disambiguates when several exist). | +| `--productName ` | **[add]** App target to inject into (disambiguates when several exist). | +| `--deintegrate` | **[add]** Run `pod deintegrate` and strip React Native from the Podfile before injecting (CocoaPods → SwiftPM migration). | +| `--artifacts ` | **[advanced]** Local artifact root containing complete `debug/` and `release/` slots. | +| `--download ` | **[advanced]** Artifact download policy: `auto` (default), `skip`, or `force`. | +| `--skipCodegen` | **[advanced]** Skip the react-native codegen step. | + ## Contributing Changes to this package can be made locally and tested against the `rn-tester` app, per the [Contributing guide](https://reactnative.dev/contributing/overview#contributing-code). During development, this package is automatically run from source with no build step. diff --git a/packages/community-cli-plugin/src/commands/codegen.js b/packages/community-cli-plugin/src/commands/codegen.js new file mode 100644 index 000000000000..cb158a1e8bb6 --- /dev/null +++ b/packages/community-cli-plugin/src/commands/codegen.js @@ -0,0 +1,63 @@ +/** + * Copyright (c) Meta Platforms, Inc. and affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + * + * @flow strict-local + * @format + */ + +import type {Command, Config} from '@react-native-community/cli-types'; + +export type CodegenCommandArgs = { + path: string, + platform: string, + outputPath?: string, + source: string, +}; + +const codegenCommand: Command = { + name: 'codegen', + options: [ + { + name: '--path ', + description: 'Path to the React Native project root.', + default: process.cwd(), + }, + { + name: '--platform ', + description: + 'Target platform. Supported values: "android", "ios", "all".', + default: 'all', + }, + { + name: '--outputPath ', + description: 'Path where generated artifacts will be output to.', + }, + { + name: '--source ', + description: 'Whether the script is invoked from an `app` or a `library`', + default: 'app', + }, + ], + func: ( + argv: Array, + config: Config, + args: CodegenCommandArgs, + ): void => { + const generateArtifactsExecutor = require.resolve( + 'react-native/scripts/codegen/generate-artifacts-executor', + {paths: [config.root]}, + ); + // $FlowFixMe[unsupported-syntax] dynamic require of a resolved path + require(generateArtifactsExecutor).execute( + args.path, + args.platform, + args.outputPath, + args.source, + ); + }, +}; + +export default codegenCommand; diff --git a/packages/community-cli-plugin/src/commands/spm.js b/packages/community-cli-plugin/src/commands/spm.js new file mode 100644 index 000000000000..181ad4ff812e --- /dev/null +++ b/packages/community-cli-plugin/src/commands/spm.js @@ -0,0 +1,118 @@ +/** + * Copyright (c) Meta Platforms, Inc. and affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + * + * @flow strict-local + * @format + */ + +import type {Command, Config} from '@react-native-community/cli-types'; + +export type SpmCommandArgs = { + version?: string, + yes?: boolean, + xcodeproj?: string, + productName?: string, + deintegrate?: boolean, + artifacts?: string, + download?: string, + skipCodegen?: boolean, +}; + +const spmCommand: Command = { + name: 'spm [action]', + description: + 'Set up or maintain Swift Package Manager support for the iOS/macOS app. ' + + 'Actions: add, update, deinit, scaffold. With no action: add (or update ' + + 'if SPM is already set up).', + options: [ + { + name: '--version ', + description: + 'React Native version (e.g. 0.80.0). Defaults to the version in node_modules/react-native/package.json.', + }, + { + name: '--yes', + description: 'Skip the dirty-pbxproj confirmation prompt.', + }, + { + name: '--xcodeproj ', + description: + '[add] Path to the .xcodeproj to inject SPM packages into ' + + '(disambiguates when several exist).', + }, + { + name: '--productName ', + description: + '[add] App target to inject into (disambiguates when several exist).', + }, + { + name: '--deintegrate', + description: + '[add] Run `pod deintegrate` and strip React Native from the Podfile ' + + 'before injecting (CocoaPods → SwiftPM migration).', + }, + { + name: '--artifacts ', + description: + '[advanced] Local artifact root containing complete debug/ and release/ slots.', + }, + { + name: '--download ', + description: + '[advanced] Artifact download policy: auto (default), skip, or force.', + }, + { + name: '--skipCodegen', + description: '[advanced] Skip the react-native codegen step.', + }, + ], + func: async ( + argv: Array, + config: Config, + args: SpmCommandArgs, + ): Promise => { + const passthrough: Array = []; + if (argv[0] != null) { + passthrough.push(argv[0]); + } + const stringOpts: Array< + [ + 'version' | 'productName' | 'xcodeproj' | 'artifacts' | 'download', + string, + ], + > = [ + ['version', '--version'], + ['productName', '--product-name'], + ['xcodeproj', '--xcodeproj'], + ['artifacts', '--artifacts'], + ['download', '--download'], + ]; + for (const [key, flag] of stringOpts) { + const value = args[key]; + if (value != null) { + passthrough.push(flag, String(value)); + } + } + const boolOpts: Array<['skipCodegen' | 'deintegrate' | 'yes', string]> = [ + ['skipCodegen', '--skip-codegen'], + ['deintegrate', '--deintegrate'], + ['yes', '--yes'], + ]; + for (const [key, flag] of boolOpts) { + if (args[key] === true) { + passthrough.push(flag); + } + } + const setupAppleSpm = require.resolve( + 'react-native/scripts/setup-apple-spm', + {paths: [config.root]}, + ); + // $FlowFixMe[unsupported-syntax] dynamic require of a resolved path + await require(setupAppleSpm).main(passthrough); + }, +}; + +export default spmCommand; diff --git a/packages/community-cli-plugin/src/index.flow.js b/packages/community-cli-plugin/src/index.flow.js index 0b4dccbe5bda..7b0fa97aceba 100644 --- a/packages/community-cli-plugin/src/index.flow.js +++ b/packages/community-cli-plugin/src/index.flow.js @@ -12,6 +12,8 @@ export { default as bundleCommand, unstable_createBundleCommandParser, } from './commands/bundle'; +export {default as codegenCommand} from './commands/codegen'; +export {default as spmCommand} from './commands/spm'; export {default as startCommand} from './commands/start'; export {unstable_buildBundleWithConfig} from './commands/bundle/buildBundle'; diff --git a/packages/react-native/react-native.config.js b/packages/react-native/react-native.config.js index 44fb2a25229b..36cc09508d4a 100644 --- a/packages/react-native/react-native.config.js +++ b/packages/react-native/react-native.config.js @@ -14,14 +14,16 @@ import type {Command} from '@react-native-community/cli-types'; */ -// React Native shouldn't be exporting itself like this, the Community Template should be be directly -// depending on and injecting: +// IMPORTANT: This is a routing file only. Do NOT add new command +// definitions or implementations here. +// +// New CLI commands belong in @react-native/community-cli-plugin, and +// may (temporarily) be imported and registered here. +// +// Future state: The Community Template should directly depend on and inject: // - @react-native-community/cli-platform-android // - @react-native-community/cli-platform-ios // - @react-native/community-cli-plugin -// - codegen command should be inhoused into @react-native-community/cli -// -// This is a temporary workaround. const verbose = Boolean(process.env.DEBUG?.includes('react-native')); @@ -72,126 +74,12 @@ const commands /*: Array */ = []; const { bundleCommand, + codegenCommand, + spmCommand, startCommand, } = require('@react-native/community-cli-plugin'); -commands.push(bundleCommand, startCommand); - -const codegenCommand /*: Command */ = { - name: 'codegen', - options: [ - { - name: '--path ', - description: 'Path to the React Native project root.', - default: process.cwd(), - }, - { - name: '--platform ', - description: - 'Target platform. Supported values: "android", "ios", "all".', - default: 'all', - }, - { - name: '--outputPath ', - description: 'Path where generated artifacts will be output to.', - }, - { - name: '--source ', - description: 'Whether the script is invoked from an `app` or a `library`', - default: 'app', - }, - ], - func: (argv, config, args) => - require('./scripts/codegen/generate-artifacts-executor').execute( - args.path, - args.platform, - args.outputPath, - args.source, - ), -}; - -commands.push(codegenCommand); - -const spmCommand /*: Command */ = { - name: 'spm [action]', - description: - 'Set up or maintain Swift Package Manager support for the iOS/macOS app. ' + - 'Actions: add, update, deinit, scaffold. With no action: add (or update ' + - 'if SPM is already set up).', - options: [ - { - name: '--version ', - description: - 'React Native version (e.g. 0.80.0). Defaults to the version in node_modules/react-native/package.json.', - }, - { - name: '--yes', - description: 'Skip the dirty-pbxproj confirmation prompt.', - }, - { - name: '--xcodeproj ', - description: - '[add] Path to the .xcodeproj to inject SPM packages into ' + - '(disambiguates when several exist).', - }, - { - name: '--productName ', - description: - '[add] App target to inject into (disambiguates when several exist).', - }, - { - name: '--deintegrate', - description: - '[add] Run `pod deintegrate` and strip React Native from the Podfile ' + - 'before injecting (CocoaPods → SwiftPM migration).', - }, - { - name: '--artifacts ', - description: - '[advanced] Local artifact root containing complete debug/ and release/ slots.', - }, - { - name: '--download ', - description: - '[advanced] Artifact download policy: auto (default), skip, or force.', - }, - { - name: '--skipCodegen', - description: '[advanced] Skip the react-native codegen step.', - }, - ], - func: async (argv, _config, args) => { - const passthrough /*: Array */ = []; - if (argv[0] != null) { - passthrough.push(argv[0]); - } - const stringOpts /*: Array<[string, string]> */ = [ - ['version', '--version'], - ['productName', '--product-name'], - ['xcodeproj', '--xcodeproj'], - ['artifacts', '--artifacts'], - ['download', '--download'], - ]; - for (const [key, flag] of stringOpts) { - if (args[key] != null) { - passthrough.push(flag, String(args[key])); - } - } - const boolOpts /*: Array<[string, string]> */ = [ - ['skipCodegen', '--skip-codegen'], - ['deintegrate', '--deintegrate'], - ['yes', '--yes'], - ]; - for (const [key, flag] of boolOpts) { - if (args[key]) { - passthrough.push(flag); - } - } - await require('./scripts/setup-apple-spm').main(passthrough); - }, -}; - -commands.push(spmCommand); +commands.push(bundleCommand, startCommand, spmCommand, codegenCommand); const config = { commands, From c3455b2741b890fc4c4bf0feaadb7e43db4f7cde Mon Sep 17 00:00:00 2001 From: Alex Hunt Date: Fri, 24 Jul 2026 07:29:16 -0700 Subject: [PATCH 2/2] Relocate CLI plugin server modules (#57654) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Summary: Pull Request resolved: https://github.com/react/react-native/pull/57654 Reorganise these modules under a `src/dev-server/` directory (out of `src/(commands|utils)/`, more clearly identifying this unit of the codebase. No public API change: the package still exports `startCommand` unchanged. Renames inside this directory: - `middleware.js` → `loadCommunityMiddleware.js` - `runServer.js` → `runDevServer.js` Changelog: [Internal] Reviewed By: cortinico Differential Revision: D113412985 --- .../src/commands/{start/index.js => start.js} | 6 +- .../src/commands/start/middleware.js | 96 ------------------- .../OpenDebuggerKeyboardHandler.js | 0 .../start => dev-server}/attachKeyHandlers.js | 0 .../createDevMiddlewareLogger.js | 0 .../isDevServerRunning.js | 1 + .../src/dev-server/loadCommunityMiddleware.js | 93 ++++++++++++++++++ .../runDevServer.js} | 21 ++-- .../src/{utils => dev-server}/version.js | 0 9 files changed, 107 insertions(+), 110 deletions(-) rename packages/community-cli-plugin/src/commands/{start/index.js => start.js} (96%) delete mode 100644 packages/community-cli-plugin/src/commands/start/middleware.js rename packages/community-cli-plugin/src/{commands/start => dev-server}/OpenDebuggerKeyboardHandler.js (100%) rename packages/community-cli-plugin/src/{commands/start => dev-server}/attachKeyHandlers.js (100%) rename packages/community-cli-plugin/src/{utils => dev-server}/createDevMiddlewareLogger.js (100%) rename packages/community-cli-plugin/src/{utils => dev-server}/isDevServerRunning.js (96%) create mode 100644 packages/community-cli-plugin/src/dev-server/loadCommunityMiddleware.js rename packages/community-cli-plugin/src/{commands/start/runServer.js => dev-server/runDevServer.js} (91%) rename packages/community-cli-plugin/src/{utils => dev-server}/version.js (100%) diff --git a/packages/community-cli-plugin/src/commands/start/index.js b/packages/community-cli-plugin/src/commands/start.js similarity index 96% rename from packages/community-cli-plugin/src/commands/start/index.js rename to packages/community-cli-plugin/src/commands/start.js index 1c866de3ed88..ab9c1e7a67cf 100644 --- a/packages/community-cli-plugin/src/commands/start/index.js +++ b/packages/community-cli-plugin/src/commands/start.js @@ -10,14 +10,12 @@ import type {Command} from '@react-native-community/cli-types'; -import runServer from './runServer'; +import runDevServer from '../dev-server/runDevServer'; import path from 'node:path'; -export type {StartCommandArgs} from './runServer'; - const startCommand: Command = { name: 'start', - func: runServer, + func: runDevServer, description: 'Start the React Native development server.', options: [ { diff --git a/packages/community-cli-plugin/src/commands/start/middleware.js b/packages/community-cli-plugin/src/commands/start/middleware.js deleted file mode 100644 index 806d8c393537..000000000000 --- a/packages/community-cli-plugin/src/commands/start/middleware.js +++ /dev/null @@ -1,96 +0,0 @@ -/** - * Copyright (c) Meta Platforms, Inc. and affiliates. - * - * This source code is licensed under the MIT license found in the - * LICENSE file in the root directory of this source tree. - * - * @flow strict-local - * @format - */ - -import type {Server} from 'connect'; -import type {TerminalReportableEvent} from 'metro'; - -import {typeof createDevServerMiddleware as CreateDevServerMiddleware} from '@react-native-community/cli-server-api'; - -const debug = require('debug')('ReactNative:CommunityCliPlugin'); - -type MiddlewareReturn = { - middleware: Server, - websocketEndpoints: { - [path: string]: ws$WebSocketServer, - }, - messageSocketEndpoint: { - server: ws$WebSocketServer, - broadcast: ( - method: string, - params?: Record | null, - ) => void, - }, - eventsSocketEndpoint: { - server: ws$WebSocketServer, - reportEvent: (event: TerminalReportableEvent) => void, - }, - ... -}; - -// $FlowFixMe[incompatible-type] -const unusedStubWSServer: ws$WebSocketServer = {}; -// $FlowFixMe[incompatible-type] -const unusedMiddlewareStub: Server = {}; - -const communityMiddlewareFallback = { - createDevServerMiddleware: (params: { - host?: string, - port: number, - watchFolders: ReadonlyArray, - }): MiddlewareReturn => ({ - // FIXME: Several features will break without community middleware and - // should be migrated into core. - // e.g. used by Libraries/Core/Devtools: - // - /open-stack-frame - // - /open-url - // - /symbolicate - middleware: unusedMiddlewareStub, - websocketEndpoints: {}, - messageSocketEndpoint: { - server: unusedStubWSServer, - broadcast: ( - method: string, - _params?: Record | null, - ): void => {}, - }, - eventsSocketEndpoint: { - server: unusedStubWSServer, - reportEvent: (event: TerminalReportableEvent) => {}, - }, - }), -}; - -// Attempt to use the community middleware if it exists, but fallback to -// the stubs if it doesn't. -try { - // `@react-native-community/cli` is an optional peer dependency of this - // package, and should be a dev dependency of the host project (via the - // community template's package.json). - const communityCliPath = require.resolve('@react-native-community/cli'); - - // Until https://github.com/react-native-community/cli/pull/2605 lands, - // we need to find `@react-native-community/cli-server-api` via - // `@react-native-community/cli`. Once that lands, we can simply - // require('@react-native-community/cli'). - const communityCliServerApiPath = require.resolve( - '@react-native-community/cli-server-api', - {paths: [communityCliPath]}, - ); - // $FlowFixMe[unsupported-syntax] dynamic import - communityMiddlewareFallback.createDevServerMiddleware = require( - communityCliServerApiPath, - ).createDevServerMiddleware as CreateDevServerMiddleware; -} catch { - debug(`⚠️ Unable to find @react-native-community/cli-server-api -Starting the server without the community middleware.`); -} - -export const createDevServerMiddleware = - communityMiddlewareFallback.createDevServerMiddleware; diff --git a/packages/community-cli-plugin/src/commands/start/OpenDebuggerKeyboardHandler.js b/packages/community-cli-plugin/src/dev-server/OpenDebuggerKeyboardHandler.js similarity index 100% rename from packages/community-cli-plugin/src/commands/start/OpenDebuggerKeyboardHandler.js rename to packages/community-cli-plugin/src/dev-server/OpenDebuggerKeyboardHandler.js diff --git a/packages/community-cli-plugin/src/commands/start/attachKeyHandlers.js b/packages/community-cli-plugin/src/dev-server/attachKeyHandlers.js similarity index 100% rename from packages/community-cli-plugin/src/commands/start/attachKeyHandlers.js rename to packages/community-cli-plugin/src/dev-server/attachKeyHandlers.js diff --git a/packages/community-cli-plugin/src/utils/createDevMiddlewareLogger.js b/packages/community-cli-plugin/src/dev-server/createDevMiddlewareLogger.js similarity index 100% rename from packages/community-cli-plugin/src/utils/createDevMiddlewareLogger.js rename to packages/community-cli-plugin/src/dev-server/createDevMiddlewareLogger.js diff --git a/packages/community-cli-plugin/src/utils/isDevServerRunning.js b/packages/community-cli-plugin/src/dev-server/isDevServerRunning.js similarity index 96% rename from packages/community-cli-plugin/src/utils/isDevServerRunning.js rename to packages/community-cli-plugin/src/dev-server/isDevServerRunning.js index c580d9c9017e..5cf83ebda690 100644 --- a/packages/community-cli-plugin/src/utils/isDevServerRunning.js +++ b/packages/community-cli-plugin/src/dev-server/isDevServerRunning.js @@ -33,6 +33,7 @@ export default async function isDevServerRunning( return 'not_running'; } + // FIXME: Depends on @react-native-community/cli-server-api const statusResponse = await fetch(`${devServerUrl}/status`); const body = await statusResponse.text(); diff --git a/packages/community-cli-plugin/src/dev-server/loadCommunityMiddleware.js b/packages/community-cli-plugin/src/dev-server/loadCommunityMiddleware.js new file mode 100644 index 000000000000..21063eef9fd7 --- /dev/null +++ b/packages/community-cli-plugin/src/dev-server/loadCommunityMiddleware.js @@ -0,0 +1,93 @@ +/** + * Copyright (c) Meta Platforms, Inc. and affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + * + * @flow strict-local + * @format + */ + +import type {Server} from 'connect'; +import type {TerminalReportableEvent} from 'metro'; + +const debug = require('debug')('ReactNative:CommunityCliPlugin'); + +type DevServerMiddlewareFactory = (params: { + host?: string, + port: number, + watchFolders: ReadonlyArray, +}) => { + middleware: Server, + websocketEndpoints: {[path: string]: ws$WebSocketServer}, + messageSocketEndpoint: { + server: ws$WebSocketServer, + broadcast: ( + method: string, + params?: Record | null, + ) => void, + }, + eventsSocketEndpoint: { + server: ws$WebSocketServer, + reportEvent: (event: TerminalReportableEvent) => void, + }, + ... +}; + +// $FlowFixMe[incompatible-type] +const unusedStubWSServer: ws$WebSocketServer = {}; +// $FlowFixMe[incompatible-type] +const unusedMiddlewareStub: Server = {}; + +// FIXME: Several features will break without community middleware +// (@react-native-community/cli-server-api) and should be migrated into core. +// e.g. used by packages/react-native/Libraries/Core/Devtools/: +// - /open-stack-frame +// - /open-url +// - /symbolicate +// e.g. used by ./isDevServerRunning.js: +// - /status +const communityMiddlewareFallback: DevServerMiddlewareFactory = () => ({ + middleware: unusedMiddlewareStub, + websocketEndpoints: {}, + messageSocketEndpoint: { + server: unusedStubWSServer, + broadcast: ( + method: string, + _params?: Record | null, + ): void => {}, + }, + eventsSocketEndpoint: { + server: unusedStubWSServer, + reportEvent: (event: TerminalReportableEvent) => {}, + }, +}); + +/** + * Attempt to load the `createDevServerMiddleware` factory from + * `@react-native-community/cli` (an optional peer dependency). If it cannot be + * found, return a factory that produces stub middleware instead. + */ +export default function loadCommunityMiddleware(): DevServerMiddlewareFactory { + try { + // `@react-native-community/cli` is an optional peer dependency of this + // package, and should be a dev dependency of the host project (via the + // community template's package.json). + const communityCliPath = require.resolve('@react-native-community/cli'); + + // Until https://github.com/react-native-community/cli/pull/2605 lands, + // we need to find `@react-native-community/cli-server-api` via + // `@react-native-community/cli`. Once that lands, we can simply + // require('@react-native-community/cli'). + const communityCliServerApiPath = require.resolve( + '@react-native-community/cli-server-api', + {paths: [communityCliPath]}, + ); + // $FlowFixMe[unsupported-syntax] dynamic import + return require(communityCliServerApiPath).createDevServerMiddleware; + } catch { + debug(`⚠️ Unable to find @react-native-community/cli-server-api +Starting the server without the community middleware.`); + return communityMiddlewareFallback; + } +} diff --git a/packages/community-cli-plugin/src/commands/start/runServer.js b/packages/community-cli-plugin/src/dev-server/runDevServer.js similarity index 91% rename from packages/community-cli-plugin/src/commands/start/runServer.js rename to packages/community-cli-plugin/src/dev-server/runDevServer.js index c2c5fa13a50d..fe120f4e9537 100644 --- a/packages/community-cli-plugin/src/commands/start/runServer.js +++ b/packages/community-cli-plugin/src/dev-server/runDevServer.js @@ -11,19 +11,19 @@ import type {Config} from '@react-native-community/cli-types'; import type {Reporter, TerminalReportableEvent, TerminalReporter} from 'metro'; -import createDevMiddlewareLogger from '../../utils/createDevMiddlewareLogger'; -import isDevServerRunning from '../../utils/isDevServerRunning'; -import loadMetroConfig from '../../utils/loadMetroConfig'; -import * as version from '../../utils/version'; +import loadMetroConfig from '../utils/loadMetroConfig'; import attachKeyHandlers from './attachKeyHandlers'; -import {createDevServerMiddleware} from './middleware'; +import createDevMiddlewareLogger from './createDevMiddlewareLogger'; +import isDevServerRunning from './isDevServerRunning'; +import loadCommunityMiddleware from './loadCommunityMiddleware'; +import * as version from './version'; import {createDevMiddleware} from '@react-native/dev-middleware'; import * as Metro from 'metro'; import path from 'node:path'; import url from 'node:url'; import {styleText} from 'node:util'; -export type StartCommandArgs = { +export type DevServerOptions = { assetPlugins?: string[], cert?: string, customLogReporterPath?: string, @@ -43,10 +43,10 @@ export type StartCommandArgs = { clientLogs: boolean, }; -async function runServer( +async function runDevServer( _argv: Array, cliConfig: Config, - args: StartCommandArgs, + args: DevServerOptions, ) { const metroConfig = await loadMetroConfig(cliConfig, { config: args.config, @@ -107,12 +107,13 @@ async function runServer( const ReporterImpl = getReporterImpl(args.customLogReporterPath); const terminalReporter = new ReporterImpl(terminal); + const createCommunityMiddleware = loadCommunityMiddleware(); const { middleware: communityMiddleware, websocketEndpoints: communityWebsocketEndpoints, messageSocketEndpoint, eventsSocketEndpoint, - } = createDevServerMiddleware({ + } = createCommunityMiddleware({ host: hostname, port, watchFolders, @@ -186,4 +187,4 @@ function getReporterImpl( } } -export default runServer; +export default runDevServer; diff --git a/packages/community-cli-plugin/src/utils/version.js b/packages/community-cli-plugin/src/dev-server/version.js similarity index 100% rename from packages/community-cli-plugin/src/utils/version.js rename to packages/community-cli-plugin/src/dev-server/version.js