From 1c4533dad8d8b00f1be0198495603e2b7e6bce56 Mon Sep 17 00:00:00 2001 From: empyrical Date: Thu, 30 Aug 2018 16:19:38 -0700 Subject: [PATCH] Add support for out-of-tree platform plugins (#20825) Summary: This pull request adds the ability for a platform developer to provide a `"haste"` key under the `"rnpm"` key in their `package.json` which allows the packager to pick up that platform's javascript files. The intent is to remove the need to have custom platforms hardcoded in. This is inspired by the `"jest": { "haste": {} }` key used by jest. For example, React Native Dom would have an entry like: ```json { "rnpm": { "haste": { "providesModuleNodeModules": [ "react-native-dom" ], "platforms": [ "dom" ] } } } ``` Support for more keys (path blacklists perhaps?) could be added in the future. This succeeds #20662, as per a discussion I had with matthargett. I've got an open discussion over here as well: https://github.com/react-native-community/discussions-and-proposals/issues/21 Pull Request resolved: https://github.com/facebook/react-native/pull/20825 Differential Revision: D9596429 Pulled By: hramos fbshipit-source-id: a02f0da0bea8870bdc45d55e23da8ccbc36249f2 --- core/findPlugins.js | 67 +++++++++++++++++++++++++++++++++------------ core/index.js | 18 ++++++++---- 2 files changed, 62 insertions(+), 23 deletions(-) diff --git a/core/findPlugins.js b/core/findPlugins.js index 595577ba8..6c23c5d9f 100644 --- a/core/findPlugins.js +++ b/core/findPlugins.js @@ -47,11 +47,37 @@ const findPlatformsInPackage = pjson => { return path.join(pjson.name, pjson.rnpm.platform); }; +const getEmptyPluginConfig = () => ({ + commands: [], + platforms: [], + haste: { + platforms: [], + providesModuleNodeModules: [], + }, +}); + +const findHasteConfigInPackageAndConcat = (pjson, haste) => { + if (!pjson.rnpm || !pjson.rnpm.haste) { + return; + } + let pkgHaste = pjson.rnpm.haste; + + if (pkgHaste.platforms) { + haste.platforms = haste.platforms.concat(pkgHaste.platforms); + } + + if (pkgHaste.providesModuleNodeModules) { + haste.providesModuleNodeModules = haste.providesModuleNodeModules.concat( + pkgHaste.providesModuleNodeModules, + ); + } +}; + const findPluginInFolder = folder => { const pjson = readPackage(folder); if (!pjson) { - return {commands: [], platforms: []}; + return getEmptyPluginConfig(); } const deps = union( @@ -59,24 +85,23 @@ const findPluginInFolder = folder => { Object.keys(pjson.devDependencies || {}), ); - return deps.reduce( - (acc, pkg) => { - let commands = acc.commands; - let platforms = acc.platforms; - if (isRNPMPlugin(pkg)) { - commands = commands.concat(pkg); - } - if (isReactNativePlugin(pkg)) { - const pkgJson = readPackage(path.join(folder, 'node_modules', pkg)); - if (pkgJson) { - commands = commands.concat(findPluginsInReactNativePackage(pkgJson)); - platforms = platforms.concat(findPlatformsInPackage(pkgJson)); - } + return deps.reduce((acc, pkg) => { + let commands = acc.commands; + let platforms = acc.platforms; + let haste = acc.haste; + if (isRNPMPlugin(pkg)) { + commands = commands.concat(pkg); + } + if (isReactNativePlugin(pkg)) { + const pkgJson = readPackage(path.join(folder, 'node_modules', pkg)); + if (pkgJson) { + commands = commands.concat(findPluginsInReactNativePackage(pkgJson)); + platforms = platforms.concat(findPlatformsInPackage(pkgJson)); + findHasteConfigInPackageAndConcat(pkgJson, haste); } - return {commands: commands, platforms: platforms}; - }, - {commands: [], platforms: []}, - ); + } + return {commands: commands, platforms: platforms, haste: haste}; + }, getEmptyPluginConfig()); }; /** @@ -89,5 +114,11 @@ module.exports = function findPlugins(folders) { return { commands: uniq(flatten(plugins.map(p => p.commands))), platforms: uniq(flatten(plugins.map(p => p.platforms))), + haste: { + platforms: uniq(flatten(plugins.map(p => p.haste.platforms))), + providesModuleNodeModules: uniq( + flatten(plugins.map(p => p.haste.providesModuleNodeModules)), + ), + }, }; }; diff --git a/core/index.js b/core/index.js index 702770625..2e66b662b 100644 --- a/core/index.js +++ b/core/index.js @@ -70,11 +70,11 @@ const defaultConfig = { hasteImplModulePath: require.resolve('../../jest/hasteImpl'), getPlatforms(): Array { - return ['ios', 'android', 'windows', 'web', 'dom']; + return ['ios', 'android', 'native', ...plugins.haste.platforms]; }, getProvidesModuleNodeModules(): Array { - return ['react-native', 'react-native-windows', 'react-native-dom']; + return ['react-native', ...plugins.haste.providesModuleNodeModules]; }, }; @@ -132,9 +132,17 @@ async function getCliConfig(): Promise { ); config.transformer.assetRegistryPath = ASSET_REGISTRY_PATH; - config.resolver.hasteImplModulePath = config.resolver.hasteImplModulePath || defaultConfig.hasteImplModulePath; - config.resolver.platforms = config.resolver.platforms || defaultConfig.getPlatforms(); - config.resolver.providesModuleNodeModules = config.resolver.providesModuleNodeModules || defaultConfig.getProvidesModuleNodeModules(); + config.resolver.hasteImplModulePath = + config.resolver.hasteImplModulePath || defaultConfig.hasteImplModulePath; + config.resolver.platforms = config.resolver.platforms + ? config.resolver.platforms.concat(defaultConfig.getPlatforms()) + : defaultConfig.getPlatforms(); + config.resolver.providesModuleNodeModules = config.resolver + .providesModuleNodeModules + ? config.resolver.providesModuleNodeModules.concat( + defaultConfig.getProvidesModuleNodeModules(), + ) + : defaultConfig.getProvidesModuleNodeModules(); return {...defaultRNConfig, ...config}; }