diff --git a/packages/metro/src/Server.js b/packages/metro/src/Server.js index 56389d0db5..cad61c6dbf 100644 --- a/packages/metro/src/Server.js +++ b/packages/metro/src/Server.js @@ -349,7 +349,7 @@ class Server { +dev: boolean, +entryFile: string, +minify: boolean, - +platform: string, + +platform: ?string, ... }): Promise> { const { diff --git a/packages/metro/src/cli-utils.js b/packages/metro/src/cli-utils.js index 768fa7db69..146e203cf8 100644 --- a/packages/metro/src/cli-utils.js +++ b/packages/metro/src/cli-utils.js @@ -11,8 +11,6 @@ 'use strict'; -import type {YargArguments} from 'metro-config/src/configTypes.flow'; - const fs = require('fs'); exports.watchFile = async function ( @@ -27,10 +25,8 @@ exports.watchFile = async function ( }; exports.makeAsyncCommand = - ( - command: (argv: YargArguments) => Promise, - ): ((argv: YargArguments) => void) => - (argv: YargArguments) => { + (command: (argv: T) => Promise): ((argv: T) => void) => + (argv: T) => { Promise.resolve(command(argv)).catch(error => { console.error(error.stack); process.exitCode = 1; diff --git a/packages/metro/src/commands/build.js b/packages/metro/src/commands/build.js index 9bf0b83c5f..7208c426e9 100644 --- a/packages/metro/src/commands/build.js +++ b/packages/metro/src/commands/build.js @@ -12,7 +12,6 @@ 'use strict'; import type {RunBuildOptions} from '../index'; -import type {YargArguments} from 'metro-config/src/configTypes.flow'; import typeof Yargs from 'yargs'; import type {ModuleObject} from 'yargs'; @@ -24,6 +23,22 @@ const {Terminal} = require('metro-core'); const term = new Terminal(process.stdout); const updateReporter = new TerminalReporter(term); +type Args = $ReadOnly<{ + config?: string, + dev?: boolean, + entry: string, + legacyBundler?: boolean, + maxWorkers?: number, + minify?: boolean, + out: string, + outputType?: string, + platform?: string, + projectRoots?: $ReadOnlyArray, + resetCache?: boolean, + sourceMap?: boolean, + sourceMapUrl?: string, +}>; + module.exports = (): { ...ModuleObject, handler: Function, @@ -58,10 +73,17 @@ module.exports = (): { yargs.option('reset-cache', {type: 'boolean'}); }, - handler: makeAsyncCommand(async (argv: YargArguments) => { + handler: makeAsyncCommand(async (argv: Args) => { const config = await loadConfig(argv); - // $FlowExpectedError YargArguments and RunBuildOptions are used interchangeable but their types are not yet compatible - const options = (argv: RunBuildOptions); + const options: RunBuildOptions = { + entry: argv.entry, + dev: argv.dev, + out: argv.out, + minify: argv.minify, + platform: argv.platform, + sourceMap: argv.sourceMap, + sourceMapUrl: argv.sourceMapUrl, + }; // Inline require() to avoid circular dependency with ../index const MetroApi = require('../index'); diff --git a/packages/metro/src/commands/dependencies.js b/packages/metro/src/commands/dependencies.js index 4d2a8492ee..3f17c05463 100644 --- a/packages/metro/src/commands/dependencies.js +++ b/packages/metro/src/commands/dependencies.js @@ -4,23 +4,35 @@ * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. * + * @flow * @format * @oncall react_native */ 'use strict'; +import type {ConfigT} from 'metro-config'; import typeof Yargs from 'yargs'; import type {ModuleObject} from 'yargs'; const {makeAsyncCommand} = require('../cli-utils'); const Server = require('../Server'); -const denodeify = require('denodeify'); const fs = require('fs'); const {loadConfig} = require('metro-config'); const path = require('path'); +const {promisify} = require('util'); -async function dependencies(args: any, config: any) { +type Args = $ReadOnly<{ + entryFile: string, + output?: string, + platform?: string, + transformer?: string, + maxWorkers?: number, + dev: boolean, + verbose: boolean, +}>; + +async function dependencies(args: Args, config: ConfigT) { const rootModuleAbsolutePath = args.entryFile; if (!fs.existsSync(rootModuleAbsolutePath)) { return Promise.reject( @@ -28,6 +40,7 @@ async function dependencies(args: any, config: any) { ); } + // $FlowFixMe[cannot-write] config.cacheStores = []; const relativePath = path.relative( @@ -43,10 +56,8 @@ async function dependencies(args: any, config: any) { generateSourceMaps: !args.dev, }; - const writeToFile = args.output; - const outStream = writeToFile - ? fs.createWriteStream(args.output) - : process.stdout; + const outStream = + args.output != null ? fs.createWriteStream(args.output) : process.stdout; const server = new Server(config); const deps = await server.getOrderedDependencyPaths(options); @@ -64,12 +75,13 @@ async function dependencies(args: any, config: any) { }); server.end(); - return writeToFile - ? denodeify(outStream.end).bind(outStream)() + return args.output != null + ? // $FlowFixMe[method-unbinding] + promisify(outStream.end).bind(outStream)() : Promise.resolve(); } -module.exports = (): ModuleObject => ({ +module.exports = (): {...ModuleObject, handler: Function} => ({ command: 'get-dependencies', desc: 'List dependencies', builder: (yargs: Yargs) => { @@ -109,7 +121,7 @@ module.exports = (): ModuleObject => ({ description: 'Enables logging', }); }, - handler: makeAsyncCommand(async (argv: any) => { + handler: makeAsyncCommand(async (argv: Args) => { const config = await loadConfig(argv); await dependencies(argv, config); }), diff --git a/packages/metro/src/commands/serve.js b/packages/metro/src/commands/serve.js index dceb3e7136..fcc080f42d 100644 --- a/packages/metro/src/commands/serve.js +++ b/packages/metro/src/commands/serve.js @@ -11,8 +11,6 @@ 'use strict'; -import type {RunServerOptions} from '../index'; -import type {YargArguments} from 'metro-config/src/configTypes.flow'; import typeof Yargs from 'yargs'; import type {ModuleObject} from 'yargs'; @@ -20,6 +18,20 @@ const {makeAsyncCommand, watchFile} = require('../cli-utils'); const {loadConfig, resolveConfig} = require('metro-config'); const {promisify} = require('util'); +type Args = $ReadOnly<{ + projectRoots?: $ReadOnlyArray, + host: string, + port: number, + maxWorkers?: number, + secure?: boolean, + secureKey?: string, + secureCert?: string, + secureServerOptions?: string, + hmrEnabled?: boolean, + config?: string, + resetCache?: boolean, +}>; + module.exports = (): { ...ModuleObject, handler: Function, @@ -63,7 +75,7 @@ module.exports = (): { ); }, - handler: makeAsyncCommand(async (argv: YargArguments) => { + handler: makeAsyncCommand(async (argv: Args) => { let server = null; let restarting = false; @@ -86,13 +98,21 @@ module.exports = (): { // Inline require() to avoid circular dependency with ../index const MetroApi = require('../index'); - // $FlowExpectedError YargArguments and RunBuildOptions are used interchangeable but their types are not yet compatible - server = await MetroApi.runServer(config, (argv: RunServerOptions)); + const { + config: _config, + hmrEnabled: _hmrEnabled, + maxWorkers: _maxWorkers, + port: _port, + projectRoots: _projectRoots, + resetCache: _resetCache, + ...runServerOptions + } = argv; + server = await MetroApi.runServer(config, runServerOptions); restarting = false; } - const foundConfig = await resolveConfig(argv.config, argv.cwd); + const foundConfig = await resolveConfig(argv.config); if (foundConfig) { await watchFile(foundConfig.filepath, restart); diff --git a/packages/metro/src/index.flow.js b/packages/metro/src/index.flow.js index 1aecaec4b1..9a31e20db0 100644 --- a/packages/metro/src/index.flow.js +++ b/packages/metro/src/index.flow.js @@ -54,7 +54,7 @@ export type RunMetroOptions = { waitForBundler?: boolean, }; -export type RunServerOptions = { +export type RunServerOptions = $ReadOnly<{ hasReducedPerformance?: boolean, host?: string, onError?: (Error & {code?: string}) => void, @@ -66,10 +66,10 @@ export type RunServerOptions = { secureKey?: string, // deprecated waitForBundler?: boolean, watch?: boolean, - websocketEndpoints?: { + websocketEndpoints?: $ReadOnly<{ [path: string]: typeof ws.Server, - }, -}; + }>, +}>; type BuildGraphOptions = { entries: $ReadOnlyArray, @@ -291,7 +291,8 @@ exports.runServer = async ( onReady(httpServer); } - Object.assign(websocketEndpoints, { + websocketEndpoints = { + ...websocketEndpoints, ...(inspectorProxy ? {...inspectorProxy.createWebSocketListeners(httpServer)} : {}), @@ -302,7 +303,7 @@ exports.runServer = async ( config, ), }), - }); + }; httpServer.on('upgrade', (request, socket, head) => { const {pathname} = parse(request.url);