From 202a18005f93769f2d347e8abf879957a99a43f3 Mon Sep 17 00:00:00 2001 From: Alex Hunt Date: Mon, 14 Aug 2023 04:17:12 -0700 Subject: [PATCH] Replace Metro stdout check with dep_graph_loaded event (#38960) Summary: Pull Request resolved: https://github.com/facebook/react-native/pull/38960 Code cleanup following `cli-plugin-metro` import. Changelog: [Internal] Reviewed By: motiz88 Differential Revision: D48188228 fbshipit-source-id: caa370989cebae0a36c20d7d6bfa81781e9cb77c --- .../{watchMode.js => attachKeyHandlers.js} | 57 ++++++------------- .../src/commands/start/runServer.js | 39 +++++++------ 2 files changed, 36 insertions(+), 60 deletions(-) rename packages/community-cli-plugin/src/commands/start/{watchMode.js => attachKeyHandlers.js} (60%) diff --git a/packages/community-cli-plugin/src/commands/start/watchMode.js b/packages/community-cli-plugin/src/commands/start/attachKeyHandlers.js similarity index 60% rename from packages/community-cli-plugin/src/commands/start/watchMode.js rename to packages/community-cli-plugin/src/commands/start/attachKeyHandlers.js index 054b1eb88de168..970441abe710b4 100644 --- a/packages/community-cli-plugin/src/commands/start/watchMode.js +++ b/packages/community-cli-plugin/src/commands/start/attachKeyHandlers.js @@ -11,63 +11,33 @@ import type {Config} from '@react-native-community/cli-types'; -import readline from 'readline'; import { addInteractionListener, logger, - hookStdout, } from '@react-native-community/cli-tools'; -import execa from 'execa'; import chalk from 'chalk'; +import execa from 'execa'; +import readline from 'readline'; import {KeyPressHandler} from '../../utils/KeyPressHandler'; const CTRL_C = '\u0003'; const CTRL_Z = '\u0026'; -function printWatchModeInstructions() { - logger.log( - `${chalk.bold('r')} - reload the app\n${chalk.bold( - 'd', - )} - open developer menu\n${chalk.bold('i')} - run on iOS\n${chalk.bold( - 'a', - )} - run on Android`, - ); -} - -function enableWatchMode( +export default function attachKeyHandlers( + cliConfig: Config, messageSocket: $ReadOnly<{ broadcast: (type: string, params?: Record | null) => void, ... }>, - ctx: Config, ) { - // We need to set this to true to catch key presses individually. - // As a result we have to implement our own method for exiting - // and other commands (e.g. ctrl+c & ctrl+z) - // $FlowIgnore[method-unbinding] - // $FlowFixMe[sketchy-null-mixed] - if (!process.stdin.setRawMode) { - logger.debug('Watch mode is not supported in this environment'); - return; + if (process.stdin.isTTY !== true) { + logger.debug('Interactive mode is not supported in this environment'); } readline.emitKeypressEvents(process.stdin); - // $FlowIgnore[prop-missing] process.stdin.setRawMode(true); - // We have no way of knowing when the dependency graph is done loading - // except by hooking into stdout itself. We want to print instructions - // right after its done loading. - const restore: () => void = hookStdout((output: string) => { - // TODO(T160391951) Replace this string check with a suitable integration point - // in Metro - if (output.includes('Fast - Scalable - Integrated')) { - printWatchModeInstructions(); - restore(); - } - }); - const onPressAsync = async (key: string) => { switch (key) { case 'r': @@ -83,7 +53,7 @@ function enableWatchMode( execa('npx', [ 'react-native', 'run-ios', - ...(ctx.project.ios?.watchModeCommandParams ?? []), + ...(cliConfig.project.ios?.watchModeCommandParams ?? []), ]).stdout?.pipe(process.stdout); break; case 'a': @@ -91,7 +61,7 @@ function enableWatchMode( execa('npx', [ 'react-native', 'run-android', - ...(ctx.project.android?.watchModeCommandParams ?? []), + ...(cliConfig.project.android?.watchModeCommandParams ?? []), ]).stdout?.pipe(process.stdout); break; case CTRL_Z: @@ -106,6 +76,13 @@ function enableWatchMode( const listener = keyPressHandler.createInteractionListener(); addInteractionListener(listener); keyPressHandler.startInterceptingKeyStrokes(); -} -export default enableWatchMode; + logger.log( + [ + `${chalk.bold('r')} - reload app`, + `${chalk.bold('d')} - open Dev Menu`, + `${chalk.bold('r')} - run on iOS`, + `${chalk.bold('a')} - run on Android`, + ].join('\n'), + ); +} diff --git a/packages/community-cli-plugin/src/commands/start/runServer.js b/packages/community-cli-plugin/src/commands/start/runServer.js index ca720e26732863..6333094c20a3d3 100644 --- a/packages/community-cli-plugin/src/commands/start/runServer.js +++ b/packages/community-cli-plugin/src/commands/start/runServer.js @@ -33,7 +33,7 @@ import { } from '@react-native-community/cli-tools'; import loadMetroConfig from '../../utils/loadMetroConfig'; -import enableWatchMode from './watchMode'; +import attachKeyHandlers from './attachKeyHandlers'; export type Args = { assetPlugins?: string[], @@ -91,21 +91,6 @@ async function runServer(_argv: Array, ctx: Config, args: Args) { sourceExts: args.sourceExts, }); - let reportEvent: (event: TerminalReportableEvent) => void; - const terminal = new Terminal(process.stdout); - const ReporterImpl = getReporterImpl(args.customLogReporterPath); - const terminalReporter = new ReporterImpl(terminal); - const reporter: Reporter = { - update(event: TerminalReportableEvent) { - terminalReporter.update(event); - if (reportEvent) { - reportEvent(event); - } - }, - }; - // $FlowIgnore[cannot-write] Assigning to readonly property - metroConfig.reporter = reporter; - if (args.assetPlugins) { // $FlowIgnore[cannot-write] Assigning to readonly property metroConfig.transformer.assetPlugins = args.assetPlugins.map(plugin => @@ -137,6 +122,24 @@ async function runServer(_argv: Array, ctx: Config, args: Args) { return middleware.use(metroMiddleware); }; + let reportEvent: (event: TerminalReportableEvent) => void; + const terminal = new Terminal(process.stdout); + const ReporterImpl = getReporterImpl(args.customLogReporterPath); + const terminalReporter = new ReporterImpl(terminal); + const reporter: Reporter = { + update(event: TerminalReportableEvent) { + terminalReporter.update(event); + if (reportEvent) { + reportEvent(event); + } + if (args.interactive && event.type === 'dep_graph_loaded') { + attachKeyHandlers(ctx, messageSocketEndpoint); + } + }, + }; + // $FlowIgnore[cannot-write] Assigning to readonly property + metroConfig.reporter = reporter; + const serverInstance = await Metro.runServer(metroConfig, { host: args.host, secure: args.https, @@ -148,10 +151,6 @@ async function runServer(_argv: Array, ctx: Config, args: Args) { reportEvent = eventsSocketEndpoint.reportEvent; - if (args.interactive) { - enableWatchMode(messageSocketEndpoint, ctx); - } - // In Node 8, the default keep-alive for an HTTP connection is 5 seconds. In // early versions of Node 8, this was implemented in a buggy way which caused // some HTTP responses (like those containing large JS bundles) to be