Skip to content

Commit 5f68c5f

Browse files
huntiefacebook-github-bot
authored andcommitted
Replace and remove optional dep on cli-tools logger
Summary: (Further refactors to logging after D63255296.) Fully decouples `community-cli-plugin` from the unlisted optional dependency on `react-native-community/cli-tools'`. This is motivated by changes in facebook#46627 which switch to using Metro's `TerminalReporter` API for emitting logs safely. - Swaps out logs in the dev server for the `unstable_server_log` Metro reporter event. - Swaps out `logger.debug()` calls for the `debug` package, currently used by Metro and `dev-middleware`. - Swaps out other logs in the `bundle` command for `console`. - (Also specify missing `semver` dep.) Changelog: [Internal] Reviewed By: hoxyq Differential Revision: D63328268
1 parent 54c5015 commit 5f68c5f

File tree

10 files changed

+149
-184
lines changed

10 files changed

+149
-184
lines changed

packages/community-cli-plugin/package.json

+3-1
Original file line numberDiff line numberDiff line change
@@ -25,12 +25,14 @@
2525
"@react-native/dev-middleware": "0.77.0-main",
2626
"@react-native/metro-babel-transformer": "0.77.0-main",
2727
"chalk": "^4.0.0",
28+
"debug": "^2.2.0",
2829
"invariant": "^2.2.4",
2930
"metro": "^0.81.0-alpha.2",
3031
"metro-config": "^0.81.0-alpha.2",
3132
"metro-core": "^0.81.0-alpha.2",
3233
"node-fetch": "^2.2.0",
33-
"readline": "^1.3.0"
34+
"readline": "^1.3.0",
35+
"semver": "^7.1.3"
3436
},
3537
"devDependencies": {
3638
"metro-resolver": "^0.81.0-alpha.2"

packages/community-cli-plugin/src/commands/bundle/buildBundle.js

+4-5
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,6 @@ import type {ConfigT} from 'metro-config';
1414
import type {RequestOptions} from 'metro/src/shared/types.flow';
1515

1616
import loadMetroConfig from '../../utils/loadMetroConfig';
17-
import {logger} from '../../utils/logger';
1817
import parseKeyValueParamArray from '../../utils/parseKeyValueParamArray';
1918
import saveAssets from './saveAssets';
2019
import chalk from 'chalk';
@@ -72,13 +71,13 @@ async function buildBundleWithConfig(
7271
);
7372

7473
if (config.resolver.platforms.indexOf(args.platform) === -1) {
75-
logger.error(
76-
`Invalid platform ${
74+
console.error(
75+
`${chalk.red('error')}: Invalid platform ${
7776
args.platform ? `"${chalk.bold(args.platform)}" ` : ''
7877
}selected.`,
7978
);
8079

81-
logger.info(
80+
console.info(
8281
`Available platforms are: ${config.resolver.platforms
8382
.map(x => `"${chalk.bold(x)}"`)
8483
.join(
@@ -123,7 +122,7 @@ async function buildBundleWithConfig(
123122
// $FlowIgnore[incompatible-call]
124123
// $FlowIgnore[prop-missing]
125124
// $FlowIgnore[incompatible-exact]
126-
await bundleImpl.save(bundle, args, logger.info);
125+
await bundleImpl.save(bundle, args, console.info);
127126

128127
// Save the assets of the bundle
129128
const outputAssets = await server.getAssets({

packages/community-cli-plugin/src/commands/bundle/saveAssets.js

+8-8
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,6 @@
1111

1212
import type {AssetData} from 'metro/src/Assets';
1313

14-
import {logger} from '../../utils/logger';
1514
import {
1615
cleanAssetCatalog,
1716
getImageSet,
@@ -21,6 +20,7 @@ import {
2120
import filterPlatformAssetScales from './filterPlatformAssetScales';
2221
import getAssetDestPathAndroid from './getAssetDestPathAndroid';
2322
import getAssetDestPathIOS from './getAssetDestPathIOS';
23+
import chalk from 'chalk';
2424
import fs from 'fs';
2525
import path from 'path';
2626

@@ -35,7 +35,7 @@ async function saveAssets(
3535
assetCatalogDest?: string,
3636
): Promise<void> {
3737
if (assetsDest == null) {
38-
logger.warn('Assets destination folder is not set, skipping...');
38+
console.warn('Warning: Assets destination folder is not set, skipping...');
3939
return;
4040
}
4141

@@ -64,13 +64,13 @@ async function saveAssets(
6464
// remove unused scales from the optimized bundle.
6565
const catalogDir = path.join(assetCatalogDest, 'RNAssets.xcassets');
6666
if (!fs.existsSync(catalogDir)) {
67-
logger.error(
68-
`Could not find asset catalog 'RNAssets.xcassets' in ${assetCatalogDest}. Make sure to create it if it does not exist.`,
67+
console.error(
68+
`${chalk.red('error')}: Could not find asset catalog 'RNAssets.xcassets' in ${assetCatalogDest}. Make sure to create it if it does not exist.`,
6969
);
7070
return;
7171
}
7272

73-
logger.info('Adding images to asset catalog', catalogDir);
73+
console.info('Adding images to asset catalog', catalogDir);
7474
cleanAssetCatalog(catalogDir);
7575
for (const asset of assets) {
7676
if (isCatalogAsset(asset)) {
@@ -84,7 +84,7 @@ async function saveAssets(
8484
addAssetToCopy(asset);
8585
}
8686
}
87-
logger.info('Done adding images to asset catalog');
87+
console.info('Done adding images to asset catalog');
8888
} else {
8989
assets.forEach(addAssetToCopy);
9090
}
@@ -98,15 +98,15 @@ function copyAll(filesToCopy: CopiedFiles) {
9898
return Promise.resolve();
9999
}
100100

101-
logger.info(`Copying ${queue.length} asset files`);
101+
console.info(`Copying ${queue.length} asset files`);
102102
return new Promise<void>((resolve, reject) => {
103103
const copyNext = (error?: Error) => {
104104
if (error) {
105105
reject(error);
106106
return;
107107
}
108108
if (queue.length === 0) {
109-
logger.info('Done copying assets');
109+
console.info('Done copying assets');
110110
resolve();
111111
} else {
112112
// queue.length === 0 is checked in previous branch, so this is string

packages/community-cli-plugin/src/commands/start/attachKeyHandlers.js

+42-20
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,6 @@
1212
import type {Config} from '@react-native-community/cli-types';
1313
import type TerminalReporter from 'metro/src/lib/TerminalReporter';
1414

15-
import {logger} from '../../utils/logger';
1615
import OpenDebuggerKeyboardHandler from './OpenDebuggerKeyboardHandler';
1716
import chalk from 'chalk';
1817
import {spawn} from 'child_process';
@@ -62,15 +61,23 @@ export default function attachKeyHandlers({
6261
reporter: TerminalReporter,
6362
}) {
6463
if (process.stdin.isTTY !== true) {
65-
logger.debug('Interactive mode is not supported in this environment');
64+
reporter.update({
65+
type: 'unstable_server_log',
66+
level: 'info',
67+
data: 'Interactive mode is not supported in this environment',
68+
});
6669
return;
6770
}
6871

6972
readline.emitKeypressEvents(process.stdin);
7073
setRawMode(true);
7174

7275
const reload = throttle(() => {
73-
logger.info('Reloading connected app(s)...');
76+
reporter.update({
77+
type: 'unstable_server_log',
78+
level: 'info',
79+
data: 'Reloading connected app(s)...',
80+
});
7481
messageSocket.broadcast('reload', null);
7582
}, RELOAD_TIMEOUT);
7683

@@ -80,8 +87,6 @@ export default function attachKeyHandlers({
8087
});
8188

8289
process.stdin.on('keypress', (str: string, key: KeyEvent) => {
83-
logger.debug(`Key pressed: ${key.sequence}`);
84-
8590
if (openDebuggerKeyboardHandler.maybeHandleTargetSelection(key.name)) {
8691
return;
8792
}
@@ -91,11 +96,19 @@ export default function attachKeyHandlers({
9196
reload();
9297
break;
9398
case 'd':
94-
logger.info('Opening Dev Menu...');
99+
reporter.update({
100+
type: 'unstable_server_log',
101+
level: 'info',
102+
data: 'Opening Dev Menu...',
103+
});
95104
messageSocket.broadcast('devMenu', null);
96105
break;
97106
case 'i':
98-
logger.info('Opening app on iOS...');
107+
reporter.update({
108+
type: 'unstable_server_log',
109+
level: 'info',
110+
data: 'Opening app on iOS...',
111+
});
99112
spawn(
100113
'npx',
101114
[
@@ -107,7 +120,11 @@ export default function attachKeyHandlers({
107120
).stdout?.pipe(process.stdout);
108121
break;
109122
case 'a':
110-
logger.info('Opening app on Android...');
123+
reporter.update({
124+
type: 'unstable_server_log',
125+
level: 'info',
126+
data: 'Opening app on Android...',
127+
});
111128
spawn(
112129
'npx',
113130
[
@@ -125,25 +142,30 @@ export default function attachKeyHandlers({
125142
case CTRL_C:
126143
case CTRL_D:
127144
openDebuggerKeyboardHandler.dismiss();
128-
logger.info('Stopping server');
145+
reporter.update({
146+
type: 'unstable_server_log',
147+
level: 'info',
148+
data: 'Stopping server',
149+
});
129150
setRawMode(false);
130151
process.stdin.pause();
131152
process.emit('SIGINT');
132153
process.exit();
133154
}
134155
});
135156

136-
logger.log(
137-
[
138-
'',
139-
`${chalk.bold('i')} - run on iOS`,
140-
`${chalk.bold('a')} - run on Android`,
141-
`${chalk.bold('r')} - reload app`,
142-
`${chalk.bold('d')} - open Dev Menu`,
143-
`${chalk.bold('j')} - open DevTools`,
144-
'',
145-
].join('\n'),
146-
);
157+
reporter.update({
158+
type: 'unstable_server_log',
159+
level: 'info',
160+
data: `Key commands available:
161+
162+
${chalk.bold('i')} - run on iOS
163+
${chalk.bold('a')} - run on Android
164+
${chalk.bold('r')} - reload app(s)
165+
${chalk.bold('d')} - open Dev Menu
166+
${chalk.bold('j')} - open DevTools
167+
`,
168+
});
147169
}
148170

149171
function setRawMode(enable: boolean) {

packages/community-cli-plugin/src/commands/start/middleware.js

+2-2
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@
1212
import type {NextHandleFunction, Server} from 'connect';
1313
import type {TerminalReportableEvent} from 'metro/src/lib/TerminalReporter';
1414

15-
import {logger} from '../../utils/logger';
15+
const debug = require('debug')('ReactNative:CommunityCliPlugin');
1616

1717
type MiddlewareReturn = {
1818
middleware: Server,
@@ -71,7 +71,7 @@ try {
7171
communityMiddlewareFallback.createDevServerMiddleware =
7272
community.createDevServerMiddleware;
7373
} catch {
74-
logger.debug(`⚠️ Unable to find @react-native-community/cli-server-api
74+
debug(`⚠️ Unable to find @react-native-community/cli-server-api
7575
Starting the server without the community middleware.`);
7676
}
7777

packages/community-cli-plugin/src/commands/start/runServer.js

+18-13
Original file line numberDiff line numberDiff line change
@@ -14,9 +14,9 @@ import type {Reporter} from 'metro/src/lib/reporting';
1414
import type {TerminalReportableEvent} from 'metro/src/lib/TerminalReporter';
1515
import typeof TerminalReporter from 'metro/src/lib/TerminalReporter';
1616

17+
import createDevMiddlewareLogger from '../../utils/createDevMiddlewareLogger';
1718
import isDevServerRunning from '../../utils/isDevServerRunning';
1819
import loadMetroConfig from '../../utils/loadMetroConfig';
19-
import {logger} from '../../utils/logger';
2020
import * as version from '../../utils/version';
2121
import attachKeyHandlers from './attachKeyHandlers';
2222
import {
@@ -72,24 +72,24 @@ async function runServer(
7272
const protocol = args.https === true ? 'https' : 'http';
7373
const devServerUrl = url.format({protocol, hostname, port});
7474

75-
logger.info(`Welcome to React Native v${ctx.reactNativeVersion}`);
75+
console.info(`Welcome to React Native v${ctx.reactNativeVersion}`);
7676

7777
const serverStatus = await isDevServerRunning(devServerUrl, projectRoot);
7878

7979
if (serverStatus === 'matched_server_running') {
80-
logger.info(
80+
console.info(
8181
`A dev server is already running for this project on port ${port}. Exiting.`,
8282
);
8383
return;
8484
} else if (serverStatus === 'port_taken') {
85-
logger.error(
86-
`Another process is running on port ${port}. Please terminate this ` +
85+
console.error(
86+
`${chalk.red('error')}: Another process is running on port ${port}. Please terminate this ` +
8787
'process and try again, or use another port with "--port".',
8888
);
8989
return;
9090
}
9191

92-
logger.info(`Starting dev server on port ${chalk.bold(String(port))}...`);
92+
console.info(`Starting dev server on port ${chalk.bold(String(port))}...`);
9393

9494
if (args.assetPlugins) {
9595
// $FlowIgnore[cannot-write] Assigning to readonly property
@@ -98,6 +98,11 @@ async function runServer(
9898
);
9999
}
100100

101+
let reportEvent: (event: TerminalReportableEvent) => void;
102+
const terminal = new Terminal(process.stdout);
103+
const ReporterImpl = getReporterImpl(args.customLogReporterPath);
104+
const terminalReporter = new ReporterImpl(terminal);
105+
101106
const {
102107
middleware: communityMiddleware,
103108
websocketEndpoints: communityWebsocketEndpoints,
@@ -111,21 +116,21 @@ async function runServer(
111116
const {middleware, websocketEndpoints} = createDevMiddleware({
112117
projectRoot,
113118
serverBaseUrl: devServerUrl,
114-
logger,
119+
logger: createDevMiddlewareLogger(terminalReporter),
115120
});
116121

117-
let reportEvent: (event: TerminalReportableEvent) => void;
118-
const terminal = new Terminal(process.stdout);
119-
const ReporterImpl = getReporterImpl(args.customLogReporterPath);
120-
const terminalReporter = new ReporterImpl(terminal);
121122
const reporter: Reporter = {
122123
update(event: TerminalReportableEvent) {
123124
terminalReporter.update(event);
124125
if (reportEvent) {
125126
reportEvent(event);
126127
}
127128
if (args.interactive && event.type === 'initialize_done') {
128-
logger.info('Dev server ready');
129+
terminalReporter.update({
130+
type: 'unstable_server_log',
131+
level: 'info',
132+
data: 'Dev server ready',
133+
});
129134
attachKeyHandlers({
130135
cliConfig: ctx,
131136
devServerUrl,
@@ -168,7 +173,7 @@ async function runServer(
168173
//
169174
serverInstance.keepAliveTimeout = 30000;
170175

171-
await version.logIfUpdateAvailable(ctx.root);
176+
await version.logIfUpdateAvailable(ctx.root, terminalReporter);
172177
}
173178

174179
function getReporterImpl(customLogReporterPath?: string): TerminalReporter {
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
/**
2+
* Copyright (c) Meta Platforms, Inc. and affiliates.
3+
*
4+
* This source code is licensed under the MIT license found in the
5+
* LICENSE file in the root directory of this source tree.
6+
*
7+
* @flow strict-local
8+
* @format
9+
* @oncall react_native
10+
*/
11+
12+
import type TerminalReporter from 'metro/src/lib/TerminalReporter';
13+
14+
type LoggerFn = (...message: $ReadOnlyArray<string>) => void;
15+
16+
/**
17+
* Create a dev-middleware logger object that will emit logs via Metro's
18+
* terminal reporter.
19+
*/
20+
export default function createDevMiddlewareLogger(
21+
reporter: TerminalReporter,
22+
): $ReadOnly<{
23+
info: LoggerFn,
24+
error: LoggerFn,
25+
warn: LoggerFn,
26+
}> {
27+
return {
28+
info: makeLogger(reporter, 'info'),
29+
warn: makeLogger(reporter, 'warn'),
30+
error: makeLogger(reporter, 'error'),
31+
};
32+
}
33+
34+
function makeLogger(
35+
reporter: TerminalReporter,
36+
level: 'info' | 'warn' | 'error',
37+
): LoggerFn {
38+
return (...data: Array<mixed>) =>
39+
reporter.update({
40+
type: 'unstable_server_log',
41+
level,
42+
data,
43+
});
44+
}

0 commit comments

Comments
 (0)