From d7aa2977620d2bb2f3738bab15f2c7943c95b7df Mon Sep 17 00:00:00 2001 From: David Aurelio Date: Sat, 22 Oct 2016 06:07:01 -0700 Subject: [PATCH] Break out defaults, add flow for Config MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 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 --- local-cli/.eslintrc | 3 +- local-cli/bundle/buildBundle.js | 9 ++-- local-cli/cliEntry.js | 5 +- local-cli/commands.js | 9 ++-- local-cli/server/runServer.js | 11 +++-- local-cli/util/Config.js | 25 +++++++++- packager/.eslintrc | 3 +- packager/defaultAssetExts.js | 16 ------ packager/defaults.js | 49 +++++++++++++++++++ .../src/Resolver/__tests__/Resolver-test.js | 11 +++-- packager/react-packager/src/Resolver/index.js | 41 +++++----------- packager/react-packager/src/Server/index.js | 15 +++--- 12 files changed, 121 insertions(+), 76 deletions(-) delete mode 100644 packager/defaultAssetExts.js create mode 100644 packager/defaults.js diff --git a/local-cli/.eslintrc b/local-cli/.eslintrc index f05efed9e1..58ef8ed610 100644 --- a/local-cli/.eslintrc +++ b/local-cli/.eslintrc @@ -1,5 +1,6 @@ { "rules": { - "extra-arrow-initializer": 0 + "extra-arrow-initializer": 0, + "no-console-disallow": 0 } } diff --git a/local-cli/bundle/buildBundle.js b/local-cli/bundle/buildBundle.js index 829dc59718..327a9564e0 100644 --- a/local-cli/bundle/buildBundle.js +++ b/local-cli/bundle/buildBundle.js @@ -8,12 +8,13 @@ */ 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 path = require('path'); -const Promise = require('promise'); const saveAssets = require('./saveAssets'); -const Server = require('../../packager/react-packager/src/Server'); -const defaultAssetExts = require('../../packager/defaultAssetExts'); +const defaultAssetExts = require('../../packager/defaults').assetExts; function saveBundle(output, bundle, args) { return Promise.resolve( @@ -38,7 +39,7 @@ function buildBundle(args, config, output = outputBundle, packagerInstance) { // bundle command and close it down afterwards. var shouldClosePackager = false; if (!packagerInstance) { - let assetExts = (config.getAssetExts && config.getAssetExts()) || []; + const assetExts = (config.getAssetExts && config.getAssetExts()) || []; const transformModulePath = args.transformer ? path.resolve(args.transformer) : diff --git a/local-cli/cliEntry.js b/local-cli/cliEntry.js index 4acacd3d93..9ed389d5dc 100644 --- a/local-cli/cliEntry.js +++ b/local-cli/cliEntry.js @@ -24,7 +24,8 @@ const minimist = require('minimist'); const path = require('path'); 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); @@ -93,7 +94,7 @@ function printUnknownCommand(cmdName) { ].join('\n')); } -const addCommand = (command: Command, config: Config) => { +const addCommand = (command: Command, config: ConfigT) => { const options = command.options || []; const cmd = commander diff --git a/local-cli/commands.js b/local-cli/commands.js index 1a2b677e25..1dcac57fc9 100644 --- a/local-cli/commands.js +++ b/local-cli/commands.js @@ -10,19 +10,20 @@ */ 'use strict'; -const Config = require('./util/Config'); const getUserCommands = require('./core/getCommands'); +import type {ConfigT} from './util/Config'; + export type Command = { name: string, description?: string, usage?: string, - func: (argv: Array, config: Config, args: Object) => ?Promise, + func: (argv: Array, config: ConfigT, args: Object) => ?Promise, options?: Array<{ command: string, description?: string, parse?: (val: string) => any, - default?: (config: Config) => any | any, + default?: (config: ConfigT) => any | any, }>, examples?: Array<{ desc: string, @@ -60,7 +61,7 @@ const undocumentedCommands = [ func: () => { console.log([ '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')); }, }, diff --git a/local-cli/server/runServer.js b/local-cli/server/runServer.js index 54cfd49d72..2490aecd99 100644 --- a/local-cli/server/runServer.js +++ b/local-cli/server/runServer.js @@ -8,24 +8,25 @@ */ 'use strict'; +const ReactPackager = require('../../packager/react-packager'); + const attachHMRServer = require('./util/attachHMRServer'); const connect = require('connect'); +const copyToClipBoardMiddleware = require('./middleware/copyToClipBoardMiddleware'); const cpuProfilerMiddleware = require('./middleware/cpuProfilerMiddleware'); const getDevToolsMiddleware = require('./middleware/getDevToolsMiddleware'); +const heapCaptureMiddleware = require('./middleware/heapCaptureMiddleware.js'); const http = require('http'); +const indexPageMiddleware = require('./middleware/indexPage'); const jscProfilerMiddleware = require('./middleware/jscProfilerMiddleware'); const loadRawBodyMiddleware = require('./middleware/loadRawBodyMiddleware'); const messageSocket = require('./util/messageSocket.js'); const openStackFrameInEditorMiddleware = require('./middleware/openStackFrameInEditorMiddleware'); -const copyToClipBoardMiddleware = require('./middleware/copyToClipBoardMiddleware'); const path = require('path'); -const ReactPackager = require('../../packager/react-packager'); const statusPageMiddleware = require('./middleware/statusPageMiddleware.js'); -const indexPageMiddleware = require('./middleware/indexPage'); const systraceProfileMiddleware = require('./middleware/systraceProfileMiddleware.js'); -const heapCaptureMiddleware = require('./middleware/heapCaptureMiddleware.js'); const webSocketProxy = require('./util/webSocketProxy.js'); -const defaultAssetExts = require('../../packager/defaultAssetExts'); +const defaultAssetExts = require('../../packager/defaults').assetExts; function runServer(args, config, readyCallback) { var wsProxy = null; diff --git a/local-cli/util/Config.js b/local-cli/util/Config.js index f92d9ba0cf..649dddcd62 100644 --- a/local-cli/util/Config.js +++ b/local-cli/util/Config.js @@ -5,6 +5,8 @@ * 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'; @@ -14,6 +16,18 @@ const path = require('path'); const RN_CLI_CONFIG = 'rn-cli.config.js'; +export type ConfigT = { + extraNodeModules?: {[id: string]: string}, + getAssetExts?: () => Array, + getTransformModulePath?: () => string, + getTransformOptionsModulePath?: () => string, + transformVariants?: () => {[name: string]: Object}, + + getAssetRoots(): Array, + getBlacklistRE(): RegExp, + getProjectRoots(): Array, +}; + /** * 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`. @@ -25,7 +39,11 @@ const RN_CLI_CONFIG = 'rn-cli.config.js'; * error will be thrown. */ const Config = { - get(cwd, defaultConfig, pathToConfig) { + get( + cwd: string, + defaultConfig?: ConfigT | null, + pathToConfig?: string | null, + ): ConfigT { let baseConfig; // 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}"` ); } + // $FlowFixMe nope baseConfig = require(configPath); } else if (pathToConfig == null) { assert(defaultConfig, 'Must have a default config if config is missing'); } else { baseConfig = path.isAbsolute(pathToConfig) ? + // $FlowFixMe nope require(pathToConfig) : + // $FlowFixMe nope require(path.join(cwd, pathToConfig)); } @@ -52,7 +73,7 @@ const Config = { }; }, - findConfigPath(cwd) { + findConfigPath(cwd: string): ?string { const parentDir = findParentDirectory(cwd, RN_CLI_CONFIG); return parentDir ? path.join(parentDir, RN_CLI_CONFIG) : null; }, diff --git a/packager/.eslintrc b/packager/.eslintrc index f05efed9e1..58ef8ed610 100644 --- a/packager/.eslintrc +++ b/packager/.eslintrc @@ -1,5 +1,6 @@ { "rules": { - "extra-arrow-initializer": 0 + "extra-arrow-initializer": 0, + "no-console-disallow": 0 } } diff --git a/packager/defaultAssetExts.js b/packager/defaultAssetExts.js deleted file mode 100644 index 0d53ace608..0000000000 --- a/packager/defaultAssetExts.js +++ /dev/null @@ -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 -]; diff --git a/packager/defaults.js b/packager/defaults.js new file mode 100644 index 0000000000..2841558a90 --- /dev/null +++ b/packager/defaults.js @@ -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', +]; diff --git a/packager/react-packager/src/Resolver/__tests__/Resolver-test.js b/packager/react-packager/src/Resolver/__tests__/Resolver-test.js index c6166548be..17a6de6ecb 100644 --- a/packager/react-packager/src/Resolver/__tests__/Resolver-test.js +++ b/packager/react-packager/src/Resolver/__tests__/Resolver-test.js @@ -9,9 +9,10 @@ 'use strict'; jest.unmock('../'); +jest.unmock('../../../../defaults'); jest.mock('path'); - +const {join: pathJoin} = require.requireActual('path'); const DependencyGraph = jest.fn(); jest.setMock('../../node-haste', DependencyGraph); let Module; @@ -219,7 +220,11 @@ describe('Resolver', function() { '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/Object.es7.js', 'polyfills/babelHelpers.js', - ] + ].map(d => pathJoin(__dirname, '..', d)) }, ]); }); diff --git a/packager/react-packager/src/Resolver/index.js b/packager/react-packager/src/Resolver/index.js index cefecd599a..6f4fb98b58 100644 --- a/packager/react-packager/src/Resolver/index.js +++ b/packager/react-packager/src/Resolver/index.js @@ -9,11 +9,12 @@ 'use strict'; -const path = require('path'); const Activity = require('../Activity'); const DependencyGraph = require('../node-haste'); + const declareOpts = require('../lib/declareOpts'); -const Promise = require('promise'); +const defaults = require('../../../defaults'); +const pathJoin = require('path').join; const validateOpts = declareOpts({ projectRoots: { @@ -74,7 +75,7 @@ const getDependenciesValidateOpts = declareOpts({ }, unbundle: { type: 'boolean', - default: false + default: false, }, recursive: { type: 'boolean', @@ -96,16 +97,8 @@ class Resolver { return filepath.indexOf('__tests__') !== -1 || (opts.blacklistRE && opts.blacklistRE.test(filepath)); }, - 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', - ], - platforms: ['ios', 'android', 'windows', 'web'], + providesModuleNodeModules: defaults.providesModuleNodeModules, + platforms: defaults.platforms, preferNativePlatform: true, fileWatcher: opts.fileWatcher, cache: opts.cache, @@ -160,14 +153,14 @@ class Resolver { const opts = getDependenciesValidateOpts(options); const prelude = opts.dev - ? path.join(__dirname, 'polyfills/prelude_dev.js') - : path.join(__dirname, 'polyfills/prelude.js'); + ? pathJoin(__dirname, 'polyfills/prelude_dev.js') + : pathJoin(__dirname, 'polyfills/prelude.js'); - const moduleSystem = path.join(__dirname, 'polyfills/require.js'); + const moduleSystem = defaults.moduleSystem; return [ prelude, - moduleSystem + moduleSystem, ].map(moduleName => this._depGraph.createPolyfill({ file: moduleName, id: moduleName, @@ -176,17 +169,7 @@ class Resolver { } _getPolyfillDependencies() { - const 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); + const polyfillModuleNames = defaults.polyfills.concat(this._polyfillModuleNames); return polyfillModuleNames.map( (polyfillModuleName, idx) => this._depGraph.createPolyfill({ @@ -242,7 +225,7 @@ class Resolver { code, meta = {}, dev = true, - minify = false + minify = false, }) { if (module.isJSON()) { code = `module.exports = ${code}`; diff --git a/packager/react-packager/src/Server/index.js b/packager/react-packager/src/Server/index.js index 3778289e6d..d5da01dd1d 100644 --- a/packager/react-packager/src/Server/index.js +++ b/packager/react-packager/src/Server/index.js @@ -19,7 +19,7 @@ const Promise = require('promise'); const SourceMapConsumer = require('source-map').SourceMapConsumer; const declareOpts = require('../lib/declareOpts'); -const defaultAssetExts = require('../../../defaultAssetExts'); +const defaults = require('../../../defaults'); const mime = require('mime-types'); const path = require('path'); const url = require('url'); @@ -81,7 +81,7 @@ const validateOpts = declareOpts({ }, assetExts: { type: 'array', - default: defaultAssetExts, + default: defaults.assetExts, }, transformTimeoutInterval: { type: 'number', @@ -128,10 +128,7 @@ const bundleOpts = declareOpts({ }, runBeforeMainModule: { type: 'array', - default: [ - // Ensures essential globals are available and are patched correctly. - 'InitializeCore' - ], + default: defaults.runBeforeMainModule, }, unbundle: { type: 'boolean', @@ -147,7 +144,7 @@ const bundleOpts = declareOpts({ }, isolateModuleIDs: { type: 'boolean', - default: false + default: false, }, resolutionResponse: { type: 'object', @@ -487,7 +484,7 @@ class Server { 'Accept-Ranges': 'bytes', 'Content-Length': chunksize, '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); @@ -585,7 +582,7 @@ class Server { ...options, resolutionResponse: response.copy({ dependencies: changedModules, - }) + }), }).then(updateBundle => { const oldModules = bundle.getModules(); const newModules = updateBundle.getModules();