Break out defaults, add flow for Config

Summary: In order to make `Config` and defaults available to our new code, I’ve added flow types and put default values into one shared modile

Reviewed By: cpojer

Differential Revision: D4044600

fbshipit-source-id: 875ed3ade69c5b22bb3c1b177e7bad732834d476
This commit is contained in:
David Aurelio 2016-10-22 06:07:01 -07:00 committed by Facebook Github Bot
parent 254b1ec6b3
commit d7aa297762
12 changed files with 121 additions and 76 deletions

View File

@ -1,5 +1,6 @@
{ {
"rules": { "rules": {
"extra-arrow-initializer": 0 "extra-arrow-initializer": 0,
"no-console-disallow": 0
} }
} }

View File

@ -8,12 +8,13 @@
*/ */
const log = require('../util/log').out('bundle'); const log = require('../util/log').out('bundle');
const Promise = require('promise');
const Server = require('../../packager/react-packager/src/Server');
const outputBundle = require('./output/bundle'); const outputBundle = require('./output/bundle');
const path = require('path'); const path = require('path');
const Promise = require('promise');
const saveAssets = require('./saveAssets'); const saveAssets = require('./saveAssets');
const Server = require('../../packager/react-packager/src/Server'); const defaultAssetExts = require('../../packager/defaults').assetExts;
const defaultAssetExts = require('../../packager/defaultAssetExts');
function saveBundle(output, bundle, args) { function saveBundle(output, bundle, args) {
return Promise.resolve( return Promise.resolve(
@ -38,7 +39,7 @@ function buildBundle(args, config, output = outputBundle, packagerInstance) {
// bundle command and close it down afterwards. // bundle command and close it down afterwards.
var shouldClosePackager = false; var shouldClosePackager = false;
if (!packagerInstance) { if (!packagerInstance) {
let assetExts = (config.getAssetExts && config.getAssetExts()) || []; const assetExts = (config.getAssetExts && config.getAssetExts()) || [];
const transformModulePath = const transformModulePath =
args.transformer ? path.resolve(args.transformer) : args.transformer ? path.resolve(args.transformer) :

View File

@ -24,7 +24,8 @@ const minimist = require('minimist');
const path = require('path'); const path = require('path');
const pkg = require('../package.json'); const pkg = require('../package.json');
import type { Command } from './commands'; import type {Command} from './commands';
import type {ConfigT} from './util/Config';
commander.version(pkg.version); commander.version(pkg.version);
@ -93,7 +94,7 @@ function printUnknownCommand(cmdName) {
].join('\n')); ].join('\n'));
} }
const addCommand = (command: Command, config: Config) => { const addCommand = (command: Command, config: ConfigT) => {
const options = command.options || []; const options = command.options || [];
const cmd = commander const cmd = commander

View File

@ -10,19 +10,20 @@
*/ */
'use strict'; 'use strict';
const Config = require('./util/Config');
const getUserCommands = require('./core/getCommands'); const getUserCommands = require('./core/getCommands');
import type {ConfigT} from './util/Config';
export type Command = { export type Command = {
name: string, name: string,
description?: string, description?: string,
usage?: string, usage?: string,
func: (argv: Array<string>, config: Config, args: Object) => ?Promise<void>, func: (argv: Array<string>, config: ConfigT, args: Object) => ?Promise<void>,
options?: Array<{ options?: Array<{
command: string, command: string,
description?: string, description?: string,
parse?: (val: string) => any, parse?: (val: string) => any,
default?: (config: Config) => any | any, default?: (config: ConfigT) => any | any,
}>, }>,
examples?: Array<{ examples?: Array<{
desc: string, desc: string,
@ -60,7 +61,7 @@ const undocumentedCommands = [
func: () => { func: () => {
console.log([ console.log([
'Looks like React Native project already exists in the current', 'Looks like React Native project already exists in the current',
'folder. Run this command from a different folder or remove node_modules/react-native' 'folder. Run this command from a different folder or remove node_modules/react-native',
].join('\n')); ].join('\n'));
}, },
}, },

View File

@ -8,24 +8,25 @@
*/ */
'use strict'; 'use strict';
const ReactPackager = require('../../packager/react-packager');
const attachHMRServer = require('./util/attachHMRServer'); const attachHMRServer = require('./util/attachHMRServer');
const connect = require('connect'); const connect = require('connect');
const copyToClipBoardMiddleware = require('./middleware/copyToClipBoardMiddleware');
const cpuProfilerMiddleware = require('./middleware/cpuProfilerMiddleware'); const cpuProfilerMiddleware = require('./middleware/cpuProfilerMiddleware');
const getDevToolsMiddleware = require('./middleware/getDevToolsMiddleware'); const getDevToolsMiddleware = require('./middleware/getDevToolsMiddleware');
const heapCaptureMiddleware = require('./middleware/heapCaptureMiddleware.js');
const http = require('http'); const http = require('http');
const indexPageMiddleware = require('./middleware/indexPage');
const jscProfilerMiddleware = require('./middleware/jscProfilerMiddleware'); const jscProfilerMiddleware = require('./middleware/jscProfilerMiddleware');
const loadRawBodyMiddleware = require('./middleware/loadRawBodyMiddleware'); const loadRawBodyMiddleware = require('./middleware/loadRawBodyMiddleware');
const messageSocket = require('./util/messageSocket.js'); const messageSocket = require('./util/messageSocket.js');
const openStackFrameInEditorMiddleware = require('./middleware/openStackFrameInEditorMiddleware'); const openStackFrameInEditorMiddleware = require('./middleware/openStackFrameInEditorMiddleware');
const copyToClipBoardMiddleware = require('./middleware/copyToClipBoardMiddleware');
const path = require('path'); const path = require('path');
const ReactPackager = require('../../packager/react-packager');
const statusPageMiddleware = require('./middleware/statusPageMiddleware.js'); const statusPageMiddleware = require('./middleware/statusPageMiddleware.js');
const indexPageMiddleware = require('./middleware/indexPage');
const systraceProfileMiddleware = require('./middleware/systraceProfileMiddleware.js'); const systraceProfileMiddleware = require('./middleware/systraceProfileMiddleware.js');
const heapCaptureMiddleware = require('./middleware/heapCaptureMiddleware.js');
const webSocketProxy = require('./util/webSocketProxy.js'); const webSocketProxy = require('./util/webSocketProxy.js');
const defaultAssetExts = require('../../packager/defaultAssetExts'); const defaultAssetExts = require('../../packager/defaults').assetExts;
function runServer(args, config, readyCallback) { function runServer(args, config, readyCallback) {
var wsProxy = null; var wsProxy = null;

View File

@ -5,6 +5,8 @@
* This source code is licensed under the BSD-style license found in the * This source code is licensed under the BSD-style license found in the
* LICENSE file in the root directory of this source tree. An additional grant * LICENSE file in the root directory of this source tree. An additional grant
* of patent rights can be found in the PATENTS file in the same directory. * of patent rights can be found in the PATENTS file in the same directory.
*
* @flow
*/ */
'use strict'; 'use strict';
@ -14,6 +16,18 @@ const path = require('path');
const RN_CLI_CONFIG = 'rn-cli.config.js'; const RN_CLI_CONFIG = 'rn-cli.config.js';
export type ConfigT = {
extraNodeModules?: {[id: string]: string},
getAssetExts?: () => Array<string>,
getTransformModulePath?: () => string,
getTransformOptionsModulePath?: () => string,
transformVariants?: () => {[name: string]: Object},
getAssetRoots(): Array<string>,
getBlacklistRE(): RegExp,
getProjectRoots(): Array<string>,
};
/** /**
* Module capable of getting the configuration that should be used for * Module capable of getting the configuration that should be used for
* the `rn-cli`. The configuration file is a JS file named `rn-cli.config.js`. * the `rn-cli`. The configuration file is a JS file named `rn-cli.config.js`.
@ -25,7 +39,11 @@ const RN_CLI_CONFIG = 'rn-cli.config.js';
* error will be thrown. * error will be thrown.
*/ */
const Config = { const Config = {
get(cwd, defaultConfig, pathToConfig) { get(
cwd: string,
defaultConfig?: ConfigT | null,
pathToConfig?: string | null,
): ConfigT {
let baseConfig; let baseConfig;
// Handle the legacy code path where pathToConfig is unspecified // Handle the legacy code path where pathToConfig is unspecified
@ -36,12 +54,15 @@ const Config = {
`Can't find "${RN_CLI_CONFIG}" file in any parent folder of "${cwd}"` `Can't find "${RN_CLI_CONFIG}" file in any parent folder of "${cwd}"`
); );
} }
// $FlowFixMe nope
baseConfig = require(configPath); baseConfig = require(configPath);
} else if (pathToConfig == null) { } else if (pathToConfig == null) {
assert(defaultConfig, 'Must have a default config if config is missing'); assert(defaultConfig, 'Must have a default config if config is missing');
} else { } else {
baseConfig = path.isAbsolute(pathToConfig) ? baseConfig = path.isAbsolute(pathToConfig) ?
// $FlowFixMe nope
require(pathToConfig) : require(pathToConfig) :
// $FlowFixMe nope
require(path.join(cwd, pathToConfig)); require(path.join(cwd, pathToConfig));
} }
@ -52,7 +73,7 @@ const Config = {
}; };
}, },
findConfigPath(cwd) { findConfigPath(cwd: string): ?string {
const parentDir = findParentDirectory(cwd, RN_CLI_CONFIG); const parentDir = findParentDirectory(cwd, RN_CLI_CONFIG);
return parentDir ? path.join(parentDir, RN_CLI_CONFIG) : null; return parentDir ? path.join(parentDir, RN_CLI_CONFIG) : null;
}, },

View File

@ -1,5 +1,6 @@
{ {
"rules": { "rules": {
"extra-arrow-initializer": 0 "extra-arrow-initializer": 0,
"no-console-disallow": 0
} }
} }

View File

@ -1,16 +0,0 @@
/**
* Copyright (c) 2015-present, Facebook, Inc.
* All rights reserved.
*
* This source code is licensed under the BSD-style license found in the
* LICENSE file in the root directory of this source tree. An additional grant
* of patent rights can be found in the PATENTS file in the same directory.
*/
'use strict';
module.exports = [
'bmp', 'gif', 'jpg', 'jpeg', 'png', 'psd', 'svg', 'webp', // Image formats
'm4v', 'mov', 'mp4', 'mpeg', 'mpg', 'webm', // Video formats
'aac', 'aiff', 'caf', 'm4a', 'mp3', 'wav', // Audio formats
'html', 'pdf', // Document formats
];

49
packager/defaults.js Normal file
View File

@ -0,0 +1,49 @@
/**
* Copyright (c) 2015-present, Facebook, Inc.
* All rights reserved.
*
* This source code is licensed under the BSD-style license found in the
* LICENSE file in the root directory of this source tree. An additional grant
* of patent rights can be found in the PATENTS file in the same directory.
*
* @flow
*/
'use strict';
exports.assetExts = [
'bmp', 'gif', 'jpg', 'jpeg', 'png', 'psd', 'svg', 'webp', // Image formats
'm4v', 'mov', 'mp4', 'mpeg', 'mpg', 'webm', // Video formats
'aac', 'aiff', 'caf', 'm4a', 'mp3', 'wav', // Audio formats
'html', 'pdf', // Document formats
];
exports.moduleSystem = require.resolve('./react-packager/src/Resolver/polyfills/require.js');
exports.platforms = ['ios', 'android', 'windows', 'web'];
exports.polyfills = [
require.resolve('./react-packager/src/Resolver/polyfills/polyfills.js'),
require.resolve('./react-packager/src/Resolver/polyfills/console.js'),
require.resolve('./react-packager/src/Resolver/polyfills/error-guard.js'),
require.resolve('./react-packager/src/Resolver/polyfills/Number.es6.js'),
require.resolve('./react-packager/src/Resolver/polyfills/String.prototype.es6.js'),
require.resolve('./react-packager/src/Resolver/polyfills/Array.prototype.es6.js'),
require.resolve('./react-packager/src/Resolver/polyfills/Array.es6.js'),
require.resolve('./react-packager/src/Resolver/polyfills/Object.es7.js'),
require.resolve('./react-packager/src/Resolver/polyfills/babelHelpers.js'),
];
exports.providesModuleNodeModules = [
'react-native',
'react-native-windows',
// Parse requires AsyncStorage. They will
// change that to require('react-native') which
// should work after this release and we can
// remove it from here.
'parse',
];
exports.runBeforeMainModule = [
// Ensures essential globals are available and are patched correctly.
'InitializeCore',
];

View File

@ -9,9 +9,10 @@
'use strict'; 'use strict';
jest.unmock('../'); jest.unmock('../');
jest.unmock('../../../../defaults');
jest.mock('path'); jest.mock('path');
const {join: pathJoin} = require.requireActual('path');
const DependencyGraph = jest.fn(); const DependencyGraph = jest.fn();
jest.setMock('../../node-haste', DependencyGraph); jest.setMock('../../node-haste', DependencyGraph);
let Module; let Module;
@ -219,7 +220,11 @@ describe('Resolver', function() {
'polyfills/Object.es7.js', 'polyfills/Object.es7.js',
], ],
}, },
]); ].map(({id, file, dependencies}) => ({
id: pathJoin(__dirname, '..', id),
file: pathJoin(__dirname, '..', file),
dependencies: dependencies.map((d => pathJoin(__dirname, '..', d))),
})));
}); });
}); });
@ -295,7 +300,7 @@ describe('Resolver', function() {
'polyfills/Array.es6.js', 'polyfills/Array.es6.js',
'polyfills/Object.es7.js', 'polyfills/Object.es7.js',
'polyfills/babelHelpers.js', 'polyfills/babelHelpers.js',
] ].map(d => pathJoin(__dirname, '..', d))
}, },
]); ]);
}); });

View File

@ -9,11 +9,12 @@
'use strict'; 'use strict';
const path = require('path');
const Activity = require('../Activity'); const Activity = require('../Activity');
const DependencyGraph = require('../node-haste'); const DependencyGraph = require('../node-haste');
const declareOpts = require('../lib/declareOpts'); const declareOpts = require('../lib/declareOpts');
const Promise = require('promise'); const defaults = require('../../../defaults');
const pathJoin = require('path').join;
const validateOpts = declareOpts({ const validateOpts = declareOpts({
projectRoots: { projectRoots: {
@ -74,7 +75,7 @@ const getDependenciesValidateOpts = declareOpts({
}, },
unbundle: { unbundle: {
type: 'boolean', type: 'boolean',
default: false default: false,
}, },
recursive: { recursive: {
type: 'boolean', type: 'boolean',
@ -96,16 +97,8 @@ class Resolver {
return filepath.indexOf('__tests__') !== -1 || return filepath.indexOf('__tests__') !== -1 ||
(opts.blacklistRE && opts.blacklistRE.test(filepath)); (opts.blacklistRE && opts.blacklistRE.test(filepath));
}, },
providesModuleNodeModules: [ providesModuleNodeModules: defaults.providesModuleNodeModules,
'react-native', platforms: defaults.platforms,
'react-native-windows',
// Parse requires AsyncStorage. They will
// change that to require('react-native') which
// should work after this release and we can
// remove it from here.
'parse',
],
platforms: ['ios', 'android', 'windows', 'web'],
preferNativePlatform: true, preferNativePlatform: true,
fileWatcher: opts.fileWatcher, fileWatcher: opts.fileWatcher,
cache: opts.cache, cache: opts.cache,
@ -160,14 +153,14 @@ class Resolver {
const opts = getDependenciesValidateOpts(options); const opts = getDependenciesValidateOpts(options);
const prelude = opts.dev const prelude = opts.dev
? path.join(__dirname, 'polyfills/prelude_dev.js') ? pathJoin(__dirname, 'polyfills/prelude_dev.js')
: path.join(__dirname, 'polyfills/prelude.js'); : pathJoin(__dirname, 'polyfills/prelude.js');
const moduleSystem = path.join(__dirname, 'polyfills/require.js'); const moduleSystem = defaults.moduleSystem;
return [ return [
prelude, prelude,
moduleSystem moduleSystem,
].map(moduleName => this._depGraph.createPolyfill({ ].map(moduleName => this._depGraph.createPolyfill({
file: moduleName, file: moduleName,
id: moduleName, id: moduleName,
@ -176,17 +169,7 @@ class Resolver {
} }
_getPolyfillDependencies() { _getPolyfillDependencies() {
const polyfillModuleNames = [ const polyfillModuleNames = defaults.polyfills.concat(this._polyfillModuleNames);
path.join(__dirname, 'polyfills/polyfills.js'),
path.join(__dirname, 'polyfills/console.js'),
path.join(__dirname, 'polyfills/error-guard.js'),
path.join(__dirname, 'polyfills/Number.es6.js'),
path.join(__dirname, 'polyfills/String.prototype.es6.js'),
path.join(__dirname, 'polyfills/Array.prototype.es6.js'),
path.join(__dirname, 'polyfills/Array.es6.js'),
path.join(__dirname, 'polyfills/Object.es7.js'),
path.join(__dirname, 'polyfills/babelHelpers.js'),
].concat(this._polyfillModuleNames);
return polyfillModuleNames.map( return polyfillModuleNames.map(
(polyfillModuleName, idx) => this._depGraph.createPolyfill({ (polyfillModuleName, idx) => this._depGraph.createPolyfill({
@ -242,7 +225,7 @@ class Resolver {
code, code,
meta = {}, meta = {},
dev = true, dev = true,
minify = false minify = false,
}) { }) {
if (module.isJSON()) { if (module.isJSON()) {
code = `module.exports = ${code}`; code = `module.exports = ${code}`;

View File

@ -19,7 +19,7 @@ const Promise = require('promise');
const SourceMapConsumer = require('source-map').SourceMapConsumer; const SourceMapConsumer = require('source-map').SourceMapConsumer;
const declareOpts = require('../lib/declareOpts'); const declareOpts = require('../lib/declareOpts');
const defaultAssetExts = require('../../../defaultAssetExts'); const defaults = require('../../../defaults');
const mime = require('mime-types'); const mime = require('mime-types');
const path = require('path'); const path = require('path');
const url = require('url'); const url = require('url');
@ -81,7 +81,7 @@ const validateOpts = declareOpts({
}, },
assetExts: { assetExts: {
type: 'array', type: 'array',
default: defaultAssetExts, default: defaults.assetExts,
}, },
transformTimeoutInterval: { transformTimeoutInterval: {
type: 'number', type: 'number',
@ -128,10 +128,7 @@ const bundleOpts = declareOpts({
}, },
runBeforeMainModule: { runBeforeMainModule: {
type: 'array', type: 'array',
default: [ default: defaults.runBeforeMainModule,
// Ensures essential globals are available and are patched correctly.
'InitializeCore'
],
}, },
unbundle: { unbundle: {
type: 'boolean', type: 'boolean',
@ -147,7 +144,7 @@ const bundleOpts = declareOpts({
}, },
isolateModuleIDs: { isolateModuleIDs: {
type: 'boolean', type: 'boolean',
default: false default: false,
}, },
resolutionResponse: { resolutionResponse: {
type: 'object', type: 'object',
@ -487,7 +484,7 @@ class Server {
'Accept-Ranges': 'bytes', 'Accept-Ranges': 'bytes',
'Content-Length': chunksize, 'Content-Length': chunksize,
'Content-Range': `bytes ${dataStart}-${dataEnd}/${data.length}`, 'Content-Range': `bytes ${dataStart}-${dataEnd}/${data.length}`,
'Content-Type': mime.lookup(path.basename(assetPath[1])) 'Content-Type': mime.lookup(path.basename(assetPath[1])),
}); });
return data.slice(dataStart, dataEnd + 1); return data.slice(dataStart, dataEnd + 1);
@ -585,7 +582,7 @@ class Server {
...options, ...options,
resolutionResponse: response.copy({ resolutionResponse: response.copy({
dependencies: changedModules, dependencies: changedModules,
}) }),
}).then(updateBundle => { }).then(updateBundle => {
const oldModules = bundle.getModules(); const oldModules = bundle.getModules();
const newModules = updateBundle.getModules(); const newModules = updateBundle.getModules();