Skip to content

Commit a40bfa7

Browse files
rozelefacebook-github-bot
authored andcommitted
Enable platforms to configure CLI commands
Summary: This change adds hooks via the `package.json` for a platform plugin to specify hooks for generating platform configurations. This change also adds hooks to allow platform plugins to participate in `link` and `unlink` commands. The goal is to move platform-specific code for platform plugins into their own repositories / node_modules. <!-- Thank you for sending the PR! We appreciate you spending the time to work on these changes. Help us understand your motivation by explaining why you decided to make this change. You can learn more about contributing to React Native here: http://facebook.github.io/react-native/docs/contributing.html Happy contributing! --> We need to be able to configure the CLI commands for plugin platforms (e.g., react-native-windows) in their own repositories. (Write your test plan here. If you changed any code, please provide us with clear instructions on how you verified your changes work. Bonus points for screenshots and videos!) - All jest tests, including new tests, pass. - `link` and `unlink` commands are successful on iOS and Android. (If this PR adds or changes functionality, please take some time to update the docs at https://github.com/facebook/react-native-website, and link to your PR here.) microsoft/react-native-windows#1601 <!-- Help reviewers and the release process by writing your own release notes **INTERNAL and MINOR tagged notes will not be included in the next version's final release notes.** CATEGORY [----------] TYPE [ CLI ] [-------------] LOCATION [ DOCS ] [ BREAKING ] [-------------] [ GENERAL ] [ BUGFIX ] [-{Component}-] [ INTERNAL ] [ ENHANCEMENT ] [ {File} ] [ IOS ] [ FEATURE ] [ {Directory} ] |-----------| [ ANDROID ] [ MINOR ] [ {Framework} ] - | {Message} | [----------] [-------------] [-------------] |-----------| [CATEGORY] [TYPE] [LOCATION] - MESSAGE EXAMPLES: [IOS] [BREAKING] [FlatList] - Change a thing that breaks other things [ANDROID] [BUGFIX] [TextInput] - Did a thing to TextInput [CLI] [FEATURE] [local-cli/info/info.js] - CLI easier to do things with [DOCS] [BUGFIX] [GettingStarted.md] - Accidentally a thing/word [GENERAL] [ENHANCEMENT] [Yoga] - Added new yoga thing/position [INTERNAL] [FEATURE] [./scripts] - Added thing to script that nobody will see --> [CLI][FEATURE][local-cli/core/index.js] - Allow platform plugins to contribute to the RNConfig. [CLI][FEATURE][local-cli/link/link.js] - Allow platform plugins to participate in the `link` command. [CLI][FEATURE][local-cli/link/unlink.js] - Allow platform plugins to participate in the `unlink` command. Closes #17745 Differential Revision: D6883558 Pulled By: hramos fbshipit-source-id: ea32fe21cedd4cc02c5c0d48229f2cdb2ac8142b
1 parent 79a63d0 commit a40bfa7

22 files changed

+236
-497
lines changed

local-cli/core/__tests__/findPlugins.spec.js

Lines changed: 20 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -27,33 +27,45 @@ describe('findPlugins', () => {
2727
jest.mock(pjsonPath, () => ({
2828
dependencies: {'rnpm-plugin-test': '*'},
2929
}));
30-
expect(findPlugins([ROOT])).toHaveLength(1);
31-
expect(findPlugins([ROOT])[0]).toBe('rnpm-plugin-test');
30+
31+
expect(findPlugins([ROOT])).toHaveProperty('commands');
32+
expect(findPlugins([ROOT])).toHaveProperty('platforms');
33+
expect(findPlugins([ROOT]).commands).toHaveLength(1);
34+
expect(findPlugins([ROOT]).commands[0]).toBe('rnpm-plugin-test');
35+
expect(findPlugins([ROOT]).platforms).toHaveLength(0);
3236
});
3337

3438
it('returns an empty array if there are no plugins in this folder', () => {
3539
jest.mock(pjsonPath, () => ({}));
36-
expect(findPlugins([ROOT])).toHaveLength(0);
40+
expect(findPlugins([ROOT])).toHaveProperty('commands');
41+
expect(findPlugins([ROOT])).toHaveProperty('platforms');
42+
expect(findPlugins([ROOT]).commands).toHaveLength(0);
43+
expect(findPlugins([ROOT]).platforms).toHaveLength(0);
3744
});
3845

39-
it('returns an empty array if there is no package.json in the supplied folder', () => {
40-
expect(Array.isArray(findPlugins(['fake-path']))).toBeTruthy();
41-
expect(findPlugins(['fake-path'])).toHaveLength(0);
46+
it('returns an object with empty arrays if there is no package.json in the supplied folder', () => {
47+
expect(findPlugins(['fake-path'])).toHaveProperty('commands');
48+
expect(findPlugins(['fake-path'])).toHaveProperty('platforms');
49+
expect(findPlugins(['fake-path']).commands).toHaveLength(0);
50+
expect(findPlugins(['fake-path']).platforms).toHaveLength(0);
4251
});
4352

4453
it('returns plugins from both dependencies and dev dependencies', () => {
4554
jest.mock(pjsonPath, () => ({
4655
dependencies: {'rnpm-plugin-test': '*'},
4756
devDependencies: {'rnpm-plugin-test-2': '*'},
4857
}));
49-
expect(findPlugins([ROOT])).toHaveLength(2);
58+
expect(findPlugins([ROOT])).toHaveProperty('commands');
59+
expect(findPlugins([ROOT])).toHaveProperty('platforms');
60+
expect(findPlugins([ROOT]).commands).toHaveLength(2);
61+
expect(findPlugins([ROOT]).platforms).toHaveLength(0);
5062
});
5163

5264
it('returns unique list of plugins', () => {
5365
jest.mock(pjsonPath, () => ({
5466
dependencies: {'rnpm-plugin-test': '*'},
5567
devDependencies: {'rnpm-plugin-test': '*'},
5668
}));
57-
expect(findPlugins([ROOT])).toHaveLength(1);
69+
expect(findPlugins([ROOT]).commands).toHaveLength(1);
5870
});
5971
});

local-cli/core/findPlugins.js

Lines changed: 23 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -37,11 +37,19 @@ const findPluginsInReactNativePackage = (pjson) => {
3737
return path.join(pjson.name, pjson.rnpm.plugin);
3838
};
3939

40+
const findPlatformsInPackage = (pjson) => {
41+
if (!pjson.rnpm || !pjson.rnpm.platform) {
42+
return [];
43+
}
44+
45+
return path.join(pjson.name, pjson.rnpm.platform);
46+
};
47+
4048
const findPluginInFolder = (folder) => {
4149
const pjson = readPackage(folder);
4250

4351
if (!pjson) {
44-
return [];
52+
return {commands: [], platforms: []};
4553
}
4654

4755
const deps = union(
@@ -51,27 +59,33 @@ const findPluginInFolder = (folder) => {
5159

5260
return deps.reduce(
5361
(acc, pkg) => {
62+
let commands = acc.commands;
63+
let platforms = acc.platforms;
5464
if (isRNPMPlugin(pkg)) {
55-
return acc.concat(pkg);
65+
commands = commands.concat(pkg);
5666
}
5767
if (isReactNativePlugin(pkg)) {
5868
const pkgJson = readPackage(path.join(folder, 'node_modules', pkg));
59-
if (!pkgJson) {
60-
return acc;
69+
if (pkgJson) {
70+
commands = commands.concat(findPluginsInReactNativePackage(pkgJson));
71+
platforms = platforms.concat(findPlatformsInPackage(pkgJson));
6172
}
62-
return acc.concat(findPluginsInReactNativePackage(pkgJson));
6373
}
64-
return acc;
74+
return {commands: commands, platforms: platforms};
6575
},
66-
[]
76+
{commands: [], platforms: []}
6777
);
6878
};
6979

7080
/**
7181
* Find plugins in package.json of the given folder
7282
* @param {String} folder Path to the folder to get the package.json from
73-
* @type {Array} Array of plugins or an empty array if no package.json found
83+
* @type {Object} Object of commands and platform plugins
7484
*/
7585
module.exports = function findPlugins(folders) {
76-
return uniq(flatten(folders.map(findPluginInFolder)));
86+
const plugins = folders.map(findPluginInFolder);
87+
return {
88+
commands: uniq(flatten(plugins.map(p => p.commands))),
89+
platforms: uniq(flatten(plugins.map(p => p.platforms)))
90+
};
7791
};

local-cli/core/index.js

Lines changed: 42 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,6 @@ const Config = require('../util/Config');
1515
const findPlugins = require('./findPlugins');
1616
const findAssets = require('./findAssets');
1717
const ios = require('./ios');
18-
const windows = require('./windows');
1918
const wrapCommands = require('./wrapCommands');
2019

2120
/* $FlowFixMe(>=0.54.0 site=react_native_oss) This comment suppresses an error
@@ -33,6 +32,10 @@ import type {ConfigT} from 'metro';
3332

3433
export type RNConfig = {
3534
...ConfigT,
35+
/**
36+
* Returns an object with all platform configurations.
37+
*/
38+
getPlatformConfig(): Object,
3639
/**
3740
* Returns an array of project commands used by the CLI to load
3841
*/
@@ -55,10 +58,21 @@ const attachPackage = (command, pkg) => Array.isArray(command)
5558
? command.map(cmd => attachPackage(cmd, pkg))
5659
: { ...command, pkg };
5760

61+
const appRoot = process.cwd();
62+
const plugins = findPlugins([appRoot]);
63+
const pluginPlatforms = plugins
64+
.platforms
65+
.reduce((acc, pathToPlatforms) => {
66+
// $FlowFixMe non-literal require
67+
return Object.assign(acc, require(path.join(appRoot, 'node_modules', pathToPlatforms)));
68+
},
69+
{});
70+
5871
const defaultRNConfig = {
72+
5973
getProjectCommands(): Array<CommandT> {
60-
const appRoot = process.cwd();
61-
const plugins = findPlugins([appRoot])
74+
const commands = plugins
75+
.commands
6276
.map(pathToCommands => {
6377
const name = pathToCommands.split(path.sep)[0];
6478

@@ -70,35 +84,51 @@ const defaultRNConfig = {
7084
);
7185
});
7286

73-
return flatten(plugins);
87+
return flatten(commands);
88+
},
89+
90+
getPlatformConfig(): Object {
91+
return {
92+
ios,
93+
android,
94+
...pluginPlatforms
95+
};
7496
},
7597

7698
getProjectConfig(): Object {
99+
const platforms = this.getPlatformConfig();
77100
const folder = process.cwd();
78101
const rnpm = getRNPMConfig(folder);
79102

80-
return Object.assign({}, rnpm, {
81-
ios: ios.projectConfig(folder, rnpm.ios || {}),
82-
android: android.projectConfig(folder, rnpm.android || {}),
83-
windows: windows.projectConfig(folder, rnpm.windows || {}),
103+
let config = Object.assign({}, rnpm, {
84104
assets: findAssets(folder, rnpm.assets),
85105
});
106+
107+
Object.keys(platforms).forEach(key => {
108+
config[key] = platforms[key].projectConfig(folder, rnpm[key] || {});
109+
});
110+
111+
return config;
86112
},
87113

88114
getDependencyConfig(packageName: string) {
115+
const platforms = this.getPlatformConfig();
89116
const folder = path.join(process.cwd(), 'node_modules', packageName);
90117
const rnpm = getRNPMConfig(
91118
path.join(process.cwd(), 'node_modules', packageName)
92119
);
93120

94-
return Object.assign({}, rnpm, {
95-
ios: ios.dependencyConfig(folder, rnpm.ios || {}),
96-
android: android.dependencyConfig(folder, rnpm.android || {}),
97-
windows: windows.dependencyConfig(folder, rnpm.windows || {}),
121+
let config = Object.assign({}, rnpm, {
98122
assets: findAssets(folder, rnpm.assets),
99123
commands: wrapCommands(rnpm.commands),
100124
params: rnpm.params || [],
101125
});
126+
127+
Object.keys(platforms).forEach(key => {
128+
config[key] = platforms[key].dependencyConfig(folder, rnpm[key] || {});
129+
});
130+
131+
return config;
102132
},
103133
};
104134

local-cli/core/windows/findNamespace.js

Lines changed: 0 additions & 30 deletions
This file was deleted.

local-cli/core/windows/findPackageClassName.js

Lines changed: 0 additions & 30 deletions
This file was deleted.

local-cli/core/windows/findProject.js

Lines changed: 0 additions & 27 deletions
This file was deleted.

local-cli/core/windows/findWindowsSolution.js

Lines changed: 0 additions & 60 deletions
This file was deleted.

local-cli/core/windows/generateGUID.js

Lines changed: 0 additions & 10 deletions
This file was deleted.

0 commit comments

Comments
 (0)