mirror of https://github.com/status-im/metro.git
Makes the Metro CLI commands injectable
Summary: This diff makes the Metro CLI commands injectable into any Yargs object, so that we can override various aspects of it, add extra commands, etc. Reviewed By: davidaurelio Differential Revision: D6988250 fbshipit-source-id: 217c661e4c1b05282b6cdbf4d745d1b29f5cbbe0
This commit is contained in:
parent
60f16aafc2
commit
eb72ad3794
|
@ -14,4 +14,6 @@
|
|||
|
||||
const yargs = require('yargs');
|
||||
|
||||
yargs.demandCommand(1).commandDir(`${__dirname}/commands`).argv;
|
||||
const {attachMetroCli} = require('./index');
|
||||
|
||||
attachMetroCli(yargs.demandCommand(1)).argv;
|
||||
|
|
|
@ -18,76 +18,81 @@ const {Terminal} = require('metro-core');
|
|||
|
||||
import typeof Yargs from 'yargs';
|
||||
|
||||
exports.command = 'build <entry>';
|
||||
|
||||
exports.builder = (yargs: Yargs) => {
|
||||
yargs.option('project-roots', {
|
||||
alias: 'P',
|
||||
type: 'string',
|
||||
array: true,
|
||||
});
|
||||
yargs.option('out', {alias: 'O', type: 'string', demandOption: true});
|
||||
|
||||
yargs.option('platform', {alias: 'p', type: 'string'});
|
||||
yargs.option('output-type', {alias: 't', type: 'string'});
|
||||
|
||||
yargs.option('max-workers', {alias: 'j', type: 'number'});
|
||||
|
||||
yargs.option('optimize', {alias: 'z', type: 'boolean'});
|
||||
yargs.option('dev', {alias: 'g', type: 'boolean'});
|
||||
|
||||
yargs.option('source-map', {type: 'boolean'});
|
||||
yargs.option('source-map-url', {type: 'string'});
|
||||
|
||||
yargs.option('legacy-bundler', {type: 'boolean'});
|
||||
|
||||
yargs.option('config', {alias: 'c', type: 'string'});
|
||||
|
||||
// Deprecated
|
||||
yargs.option('reset-cache', {type: 'boolean', describe: null});
|
||||
};
|
||||
|
||||
const term = new Terminal(process.stdout);
|
||||
const updateReporter = new TerminalReporter(term);
|
||||
|
||||
// eslint-disable-next-line lint/no-unclear-flowtypes
|
||||
exports.handler = makeAsyncCommand(async (argv: any) => {
|
||||
// $FlowFixMe: Flow + Promises don't work consistently https://fb.facebook.com/groups/flow/permalink/1772334656148475/
|
||||
const config = await MetroApi.loadMetroConfig(argv.config);
|
||||
module.exports = () => ({
|
||||
command: 'build <entry>',
|
||||
|
||||
if (argv.projectRoots) {
|
||||
config.getProjectRoots = () => argv.projectRoots;
|
||||
}
|
||||
description:
|
||||
'Generates a JavaScript bundle containing the specified entrypoint and its descendants',
|
||||
|
||||
await MetroApi.runBuild({
|
||||
...argv,
|
||||
config,
|
||||
onBegin: () => {
|
||||
updateReporter.update({
|
||||
buildID: '$',
|
||||
type: 'bundle_build_started',
|
||||
bundleDetails: {
|
||||
entryFile: argv.O,
|
||||
platform: argv.platform,
|
||||
dev: !!argv.dev,
|
||||
minify: !!argv.optimize,
|
||||
bundleType: 'Bundle',
|
||||
},
|
||||
});
|
||||
},
|
||||
onProgress: (transformedFileCount, totalFileCount) => {
|
||||
updateReporter.update({
|
||||
buildID: '$',
|
||||
type: 'bundle_transform_progressed_throttled',
|
||||
transformedFileCount,
|
||||
totalFileCount,
|
||||
});
|
||||
},
|
||||
onComplete: () => {
|
||||
updateReporter.update({
|
||||
buildID: '$',
|
||||
type: 'bundle_build_done',
|
||||
});
|
||||
},
|
||||
});
|
||||
builder: (yargs: Yargs) => {
|
||||
yargs.option('project-roots', {
|
||||
alias: 'P',
|
||||
type: 'string',
|
||||
array: true,
|
||||
});
|
||||
yargs.option('out', {alias: 'O', type: 'string', demandOption: true});
|
||||
|
||||
yargs.option('platform', {alias: 'p', type: 'string'});
|
||||
yargs.option('output-type', {alias: 't', type: 'string'});
|
||||
|
||||
yargs.option('max-workers', {alias: 'j', type: 'number'});
|
||||
|
||||
yargs.option('optimize', {alias: 'z', type: 'boolean'});
|
||||
yargs.option('dev', {alias: 'g', type: 'boolean'});
|
||||
|
||||
yargs.option('source-map', {type: 'boolean'});
|
||||
yargs.option('source-map-url', {type: 'string'});
|
||||
|
||||
yargs.option('legacy-bundler', {type: 'boolean'});
|
||||
|
||||
yargs.option('config', {alias: 'c', type: 'string'});
|
||||
|
||||
// Deprecated
|
||||
yargs.option('reset-cache', {type: 'boolean', describe: null});
|
||||
},
|
||||
|
||||
// eslint-disable-next-line lint/no-unclear-flowtypes
|
||||
handler: makeAsyncCommand(async (argv: any) => {
|
||||
// $FlowFixMe: Flow + Promises don't work consistently https://fb.facebook.com/groups/flow/permalink/1772334656148475/
|
||||
const config = await MetroApi.loadMetroConfig(argv.config);
|
||||
|
||||
if (argv.projectRoots) {
|
||||
config.getProjectRoots = () => argv.projectRoots;
|
||||
}
|
||||
|
||||
await MetroApi.runBuild({
|
||||
...argv,
|
||||
config,
|
||||
onBegin: () => {
|
||||
updateReporter.update({
|
||||
buildID: '$',
|
||||
type: 'bundle_build_started',
|
||||
bundleDetails: {
|
||||
entryFile: argv.entry,
|
||||
platform: argv.platform,
|
||||
dev: !!argv.dev,
|
||||
minify: !!argv.optimize,
|
||||
bundleType: 'Bundle',
|
||||
},
|
||||
});
|
||||
},
|
||||
onProgress: (transformedFileCount, totalFileCount) => {
|
||||
updateReporter.update({
|
||||
buildID: '$',
|
||||
type: 'bundle_transform_progressed_throttled',
|
||||
transformedFileCount,
|
||||
totalFileCount,
|
||||
});
|
||||
},
|
||||
onComplete: () => {
|
||||
updateReporter.update({
|
||||
buildID: '$',
|
||||
type: 'bundle_build_done',
|
||||
});
|
||||
},
|
||||
});
|
||||
}),
|
||||
});
|
||||
|
|
|
@ -17,70 +17,75 @@ const {promisify} = require('util');
|
|||
|
||||
import typeof Yargs from 'yargs';
|
||||
|
||||
exports.command = 'serve';
|
||||
module.exports = () => ({
|
||||
command: 'serve',
|
||||
|
||||
exports.builder = (yargs: Yargs) => {
|
||||
yargs.option('project-roots', {
|
||||
alias: 'P',
|
||||
type: 'string',
|
||||
array: true,
|
||||
});
|
||||
description:
|
||||
'Starts a Metro server on the given port, building bundles on the fly',
|
||||
|
||||
yargs.option('host', {alias: 'h', type: 'string', default: 'localhost'});
|
||||
yargs.option('port', {alias: 'p', type: 'number', default: 8080});
|
||||
|
||||
yargs.option('max-workers', {alias: 'j', type: 'number'});
|
||||
|
||||
yargs.option('secure', {type: 'boolean'});
|
||||
yargs.option('secure-key', {type: 'string'});
|
||||
yargs.option('secure-cert', {type: 'string'});
|
||||
|
||||
yargs.option('hmr-enabled', {alias: 'hmr', type: 'boolean'});
|
||||
|
||||
yargs.option('config', {alias: 'c', type: 'string'});
|
||||
|
||||
// Deprecated
|
||||
yargs.option('reset-cache', {type: 'boolean', describe: null});
|
||||
};
|
||||
|
||||
// eslint-disable-next-line lint/no-unclear-flowtypes
|
||||
exports.handler = makeAsyncCommand(async (argv: any) => {
|
||||
let server = null;
|
||||
let restarting = false;
|
||||
|
||||
async function restart() {
|
||||
if (restarting) {
|
||||
return;
|
||||
} else {
|
||||
restarting = true;
|
||||
}
|
||||
|
||||
if (server) {
|
||||
// eslint-disable-next-line no-console
|
||||
console.log('Configuration changed. Restarting the server...');
|
||||
await promisify(server.close).call(server);
|
||||
}
|
||||
|
||||
// $FlowFixMe: Flow + Promises don't work consistently https://fb.facebook.com/groups/flow/permalink/1772334656148475/
|
||||
const config = await MetroApi.loadMetroConfig(argv.config);
|
||||
|
||||
if (argv.projectRoots) {
|
||||
config.getProjectRoots = () => argv.projectRoots;
|
||||
}
|
||||
|
||||
server = await MetroApi.runServer({
|
||||
...argv,
|
||||
config,
|
||||
builder: (yargs: Yargs) => {
|
||||
yargs.option('project-roots', {
|
||||
alias: 'P',
|
||||
type: 'string',
|
||||
array: true,
|
||||
});
|
||||
|
||||
restarting = false;
|
||||
}
|
||||
yargs.option('host', {alias: 'h', type: 'string', default: 'localhost'});
|
||||
yargs.option('port', {alias: 'p', type: 'number', default: 8080});
|
||||
|
||||
const metroConfigLocation = await MetroApi.findMetroConfig(argv.config);
|
||||
yargs.option('max-workers', {alias: 'j', type: 'number'});
|
||||
|
||||
if (metroConfigLocation) {
|
||||
await watchFile(metroConfigLocation, restart);
|
||||
} else {
|
||||
await restart();
|
||||
}
|
||||
yargs.option('secure', {type: 'boolean'});
|
||||
yargs.option('secure-key', {type: 'string'});
|
||||
yargs.option('secure-cert', {type: 'string'});
|
||||
|
||||
yargs.option('hmr-enabled', {alias: 'hmr', type: 'boolean'});
|
||||
|
||||
yargs.option('config', {alias: 'c', type: 'string'});
|
||||
|
||||
// Deprecated
|
||||
yargs.option('reset-cache', {type: 'boolean', describe: null});
|
||||
},
|
||||
|
||||
// eslint-disable-next-line lint/no-unclear-flowtypes
|
||||
handler: makeAsyncCommand(async (argv: any) => {
|
||||
let server = null;
|
||||
let restarting = false;
|
||||
|
||||
async function restart() {
|
||||
if (restarting) {
|
||||
return;
|
||||
} else {
|
||||
restarting = true;
|
||||
}
|
||||
|
||||
if (server) {
|
||||
// eslint-disable-next-line no-console
|
||||
console.log('Configuration changed. Restarting the server...');
|
||||
await promisify(server.close).call(server);
|
||||
}
|
||||
|
||||
// $FlowFixMe: Flow + Promises don't work consistently https://fb.facebook.com/groups/flow/permalink/1772334656148475/
|
||||
const config = await MetroApi.loadMetroConfig(argv.config);
|
||||
|
||||
if (argv.projectRoots) {
|
||||
config.getProjectRoots = () => argv.projectRoots;
|
||||
}
|
||||
|
||||
server = await MetroApi.runServer({
|
||||
...argv,
|
||||
config,
|
||||
});
|
||||
|
||||
restarting = false;
|
||||
}
|
||||
|
||||
const metroConfigLocation = await MetroApi.findMetroConfig(argv.config);
|
||||
|
||||
if (metroConfigLocation) {
|
||||
await watchFile(metroConfigLocation, restart);
|
||||
} else {
|
||||
await restart();
|
||||
}
|
||||
}),
|
||||
});
|
||||
|
|
|
@ -22,6 +22,8 @@ const fs = require('fs');
|
|||
const getMaxWorkers = require('./lib/getMaxWorkers');
|
||||
const http = require('http');
|
||||
const https = require('https');
|
||||
const makeBuildCommand = require('./commands/build');
|
||||
const makeServeCommand = require('./commands/serve');
|
||||
const outputBundle = require('./shared/output/bundle');
|
||||
const path = require('path');
|
||||
|
||||
|
@ -31,12 +33,13 @@ const {Terminal} = require('metro-core');
|
|||
|
||||
import type {ConfigT} from './Config';
|
||||
import type {GlobalTransformCache} from './lib/GlobalTransformCache';
|
||||
import type {Options as ServerOptions} from './shared/types.flow';
|
||||
import type {TransformCache} from './lib/TransformCaching';
|
||||
import type {Reporter} from './lib/reporting';
|
||||
import type {RequestOptions, OutputOptions} from './shared/types.flow.js';
|
||||
import type {TransformCache} from './lib/TransformCaching';
|
||||
import type {Options as ServerOptions} from './shared/types.flow';
|
||||
import type {Server as HttpServer} from 'http';
|
||||
import type {Server as HttpsServer} from 'https';
|
||||
import typeof Yargs from 'yargs';
|
||||
|
||||
export type {ConfigT} from './Config';
|
||||
|
||||
|
@ -400,7 +403,7 @@ exports.findMetroConfig = function(
|
|||
|
||||
exports.loadMetroConfig = function(
|
||||
filename: ?string,
|
||||
// $FlowFixMe: This is a known Flow issue where it doesn't detect that an empty object is a valid value for a strict shape where all the members are optionals
|
||||
// $FlowFixMe TODO T26072405
|
||||
searchOptions: MetroConfigSearchOptions = {},
|
||||
): ConfigT {
|
||||
const location = exports.findMetroConfig(filename, searchOptions);
|
||||
|
@ -411,6 +414,32 @@ exports.loadMetroConfig = function(
|
|||
return config ? Config.normalize(config) : Config.DEFAULT;
|
||||
};
|
||||
|
||||
type BuildCommandOptions = {||} | null;
|
||||
type ServeCommandOptions = {||} | null;
|
||||
|
||||
exports.attachMetroCli = function(
|
||||
yargs: Yargs,
|
||||
{
|
||||
// $FlowFixMe TODO T26072405
|
||||
build = {},
|
||||
// $FlowFixMe TODO T26072405
|
||||
serve = {},
|
||||
}: {
|
||||
build: BuildCommandOptions,
|
||||
serve: ServeCommandOptions,
|
||||
} = {},
|
||||
) {
|
||||
if (build) {
|
||||
const {command, description, builder, handler} = makeBuildCommand();
|
||||
yargs.command(command, description, builder, handler);
|
||||
}
|
||||
if (serve) {
|
||||
const {command, description, builder, handler} = makeServeCommand();
|
||||
yargs.command(command, description, builder, handler);
|
||||
}
|
||||
return yargs;
|
||||
};
|
||||
|
||||
exports.Config = Config;
|
||||
exports.defaults = defaults;
|
||||
|
||||
|
|
Loading…
Reference in New Issue