Skip to content

Commit a40bfa7

Browse files
rozelefacebook-github-bot
authored andcommittedFeb 8, 2018
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

+20-8
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

+23-9
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

+42-12
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

-30
This file was deleted.

‎local-cli/core/windows/findPackageClassName.js

-30
This file was deleted.

‎local-cli/core/windows/findProject.js

-27
This file was deleted.

‎local-cli/core/windows/findWindowsSolution.js

-60
This file was deleted.

‎local-cli/core/windows/generateGUID.js

-10
This file was deleted.

‎local-cli/core/windows/index.js

-114
This file was deleted.

‎local-cli/link/__tests__/link.spec.js

+63-1
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@ describe('link', () => {
3939

4040
it('should accept a name of a dependency to link', (done) => {
4141
const config = {
42+
getPlatformConfig: () => ({ios: {}, android: {}}),
4243
getProjectConfig: () => ({ assets: [] }),
4344
getDependencyConfig: sinon.stub().returns({ assets: [], commands: {} }),
4445
};
@@ -54,6 +55,7 @@ describe('link', () => {
5455

5556
it('should read dependencies from package.json when name not provided', (done) => {
5657
const config = {
58+
getPlatformConfig: () => ({ios: {}, android: {}}),
5759
getProjectConfig: () => ({ assets: [] }),
5860
getDependencyConfig: sinon.stub().returns({ assets: [], commands: {} }),
5961
};
@@ -80,6 +82,7 @@ describe('link', () => {
8082
const registerNativeModule = sinon.stub();
8183
const dependencyConfig = {android: {}, ios: {}, assets: [], commands: {}};
8284
const config = {
85+
getPlatformConfig: () => ({ios: {}, android: {}}),
8386
getProjectConfig: () => ({android: {}, ios: {}, assets: []}),
8487
getDependencyConfig: sinon.stub().returns(dependencyConfig),
8588
};
@@ -116,6 +119,7 @@ describe('link', () => {
116119
const registerNativeModule = sinon.stub();
117120
const dependencyConfig = {ios: {}, android: {}, assets: [], commands: {}};
118121
const config = {
122+
getPlatformConfig: () => ({ios: {}, android: {}}),
119123
getProjectConfig: () => ({ ios: {}, android: {}, assets: [] }),
120124
getDependencyConfig: sinon.stub().returns(dependencyConfig),
121125
};
@@ -148,6 +152,62 @@ describe('link', () => {
148152
});
149153
});
150154

155+
it('should register native modules for plugins', (done) => {
156+
const registerNativeModule = sinon.stub();
157+
const dependencyConfig = {ios: {}, android: {}, test: {}, assets: [], commands: {}};
158+
const linkPluginConfig = { isInstalled: () => false, register: registerNativeModule };
159+
const config = {
160+
getPlatformConfig: () => ({ ios: {}, android: {}, test: { linkConfig: () => linkPluginConfig }}),
161+
getProjectConfig: () => ({ ios: {}, android: {}, test: {}, assets: [] }),
162+
getDependencyConfig: sinon.stub().returns(dependencyConfig),
163+
};
164+
165+
jest.setMock(
166+
'../ios/isInstalled.js',
167+
sinon.stub().returns(true)
168+
);
169+
170+
jest.setMock(
171+
'../android/isInstalled.js',
172+
sinon.stub().returns(true)
173+
);
174+
175+
const link = require('../link').func;
176+
177+
link(['react-native-blur'], config).then(() => {
178+
expect(registerNativeModule.calledOnce).toBeTruthy();
179+
done();
180+
});
181+
});
182+
183+
it('should not register native modules for plugins when already installed', (done) => {
184+
const registerNativeModule = sinon.stub();
185+
const dependencyConfig = {ios: {}, android: {}, test: {}, assets: [], commands: {}};
186+
const linkPluginConfig = { isInstalled: () => true, register: registerNativeModule};
187+
const config = {
188+
getPlatformConfig: () => ({ ios: {}, android: {}, test: { linkConfig: () => linkPluginConfig }}),
189+
getProjectConfig: () => ({ ios: {}, android: {}, test: {}, assets: [] }),
190+
getDependencyConfig: sinon.stub().returns(dependencyConfig),
191+
};
192+
193+
jest.setMock(
194+
'../ios/isInstalled.js',
195+
sinon.stub().returns(true)
196+
);
197+
198+
jest.setMock(
199+
'../android/isInstalled.js',
200+
sinon.stub().returns(true)
201+
);
202+
203+
const link = require('../link').func;
204+
205+
link(['react-native-blur'], config).then(() => {
206+
expect(registerNativeModule.callCount).toEqual(0);
207+
done();
208+
});
209+
});
210+
151211
it('should run prelink and postlink commands at the appropriate times', (done) => {
152212
const registerNativeModule = sinon.stub();
153213
const prelink = sinon.stub().yieldsAsync();
@@ -164,6 +224,7 @@ describe('link', () => {
164224
);
165225

166226
const config = {
227+
getPlatformConfig: () => ({ ios: {}}),
167228
getProjectConfig: () => ({ ios: {}, assets: [] }),
168229
getDependencyConfig: sinon.stub().returns({
169230
ios: {}, assets: [], commands: { prelink, postlink },
@@ -181,7 +242,7 @@ describe('link', () => {
181242

182243
it('should copy assets from both project and dependencies projects', (done) => {
183244
const dependencyAssets = ['Fonts/Font.ttf'];
184-
const dependencyConfig = {assets: dependencyAssets, commands: {}};
245+
const dependencyConfig = {assets: dependencyAssets, ios: {}, commands: {}};
185246
const projectAssets = ['Fonts/FontC.ttf'];
186247
const copyAssets = sinon.stub();
187248

@@ -191,6 +252,7 @@ describe('link', () => {
191252
);
192253

193254
const config = {
255+
getPlatformConfig: () => ({ ios: {} }),
194256
getProjectConfig: () => ({ ios: {}, assets: projectAssets }),
195257
getDependencyConfig: sinon.stub().returns(dependencyConfig),
196258
};

‎local-cli/link/link.js

+56-33
Original file line numberDiff line numberDiff line change
@@ -27,11 +27,9 @@ const chalk = require('chalk');
2727
const isEmpty = require('lodash').isEmpty;
2828
const promiseWaterfall = require('./promiseWaterfall');
2929
const registerDependencyAndroid = require('./android/registerNativeModule');
30-
const registerDependencyWindows = require('./windows/registerNativeModule');
3130
const registerDependencyIOS = require('./ios/registerNativeModule');
3231
const registerDependencyPods = require('./pods/registerNativeModule');
3332
const isInstalledAndroid = require('./android/isInstalled');
34-
const isInstalledWindows = require('./windows/isInstalled');
3533
const isInstalledIOS = require('./ios/isInstalled');
3634
const isInstalledPods = require('./pods/isInstalled');
3735
const copyAssetsAndroid = require('./android/copyAssets');
@@ -76,31 +74,40 @@ const linkDependencyAndroid = (androidProject, dependency) => {
7674
});
7775
};
7876

79-
const linkDependencyWindows = (windowsProject, dependency) => {
80-
81-
if (!windowsProject || !dependency.config.windows) {
82-
return null;
83-
}
84-
85-
const isInstalled = isInstalledWindows(windowsProject, dependency.config.windows);
86-
87-
if (isInstalled) {
88-
log.info(chalk.grey(`Windows module ${dependency.name} is already linked`));
89-
return null;
90-
}
91-
92-
return pollParams(dependency.config.params).then(params => {
93-
log.info(`Linking ${dependency.name} windows dependency`);
94-
95-
registerDependencyWindows(
96-
dependency.name,
97-
dependency.config.windows,
98-
params,
99-
windowsProject
100-
);
101-
102-
log.info(`Windows module ${dependency.name} has been successfully linked`);
103-
});
77+
const linkDependencyPlatforms = (platforms, project, dependency) => {
78+
const ignorePlatforms = ['android', 'ios'];
79+
Object.keys(platforms || {})
80+
.filter(platform => ignorePlatforms.indexOf(platform) < 0)
81+
.forEach(platform => {
82+
if (!project[platform] || !dependency.config[platform]) {
83+
return null;
84+
}
85+
86+
const linkConfig = platforms[platform] && platforms[platform].linkConfig && platforms[platform].linkConfig();
87+
if (!linkConfig || !linkConfig.isInstalled || !linkConfig.register) {
88+
return null;
89+
}
90+
91+
const isInstalled = linkConfig.isInstalled(project[platform], dependency.config[platform]);
92+
93+
if (isInstalled) {
94+
log.info(chalk.grey(`Platform '${platform}' module ${dependency.name} is already linked`));
95+
return null;
96+
}
97+
98+
return pollParams(dependency.config.params).then(params => {
99+
log.info(`Linking ${dependency.name} ${platform} dependency`);
100+
101+
linkConfig.register(
102+
dependency.name,
103+
dependency.config[platform],
104+
params,
105+
project[platform]
106+
);
107+
108+
log.info(`Platform '${platform}' module ${dependency.name} has been successfully linked`);
109+
});
110+
});
104111
};
105112

106113
const linkDependencyIOS = (iOSProject, dependency) => {
@@ -124,7 +131,7 @@ const linkDependencyIOS = (iOSProject, dependency) => {
124131
log.info(`iOS module ${dependency.name} has been successfully linked`);
125132
};
126133

127-
const linkAssets = (project, assets) => {
134+
const linkAssets = (platforms, project, assets) => {
128135
if (isEmpty(assets)) {
129136
return;
130137
}
@@ -139,6 +146,19 @@ const linkAssets = (project, assets) => {
139146
copyAssetsAndroid(assets, project.android.assetsPath);
140147
}
141148

149+
const ignorePlatforms = ['android', 'ios'];
150+
Object.keys(platforms || {})
151+
.filter(platform => ignorePlatforms.indexOf(platform) < 0)
152+
.forEach(platform => {
153+
const linkConfig = platforms[platform] && platforms[platform].linkConfig && platforms[platform].linkConfig();
154+
if (!linkConfig || !linkConfig.copyAssets) {
155+
return;
156+
}
157+
158+
log.info(`Linking assets to ${platform} project`);
159+
linkConfig.copyAssets(assets, project[platform]);
160+
});
161+
142162
log.info('Assets have been successfully linked to your project');
143163
};
144164

@@ -150,9 +170,11 @@ const linkAssets = (project, assets) => {
150170
* @param config CLI config, see local-cli/core/index.js
151171
*/
152172
function link(args: Array<string>, config: RNConfig) {
153-
var project;
173+
let project;
174+
let platforms;
154175
try {
155176
project = config.getProjectConfig();
177+
platforms = config.getPlatformConfig();
156178
} catch (err) {
157179
log.error(
158180
'ERRPACKAGEJSON',
@@ -161,7 +183,8 @@ function link(args: Array<string>, config: RNConfig) {
161183
return Promise.reject(err);
162184
}
163185

164-
if (!project.android && !project.ios && !project.windows && findReactNativeScripts()) {
186+
const hasProjectConfig = Object.keys(platforms).reduce((acc, key) => acc || key in project, false);
187+
if (!hasProjectConfig && findReactNativeScripts()) {
165188
throw new Error(
166189
'`react-native link` can not be used in Create React Native App projects. ' +
167190
'If you need to include a library that relies on custom native code, ' +
@@ -183,19 +206,19 @@ function link(args: Array<string>, config: RNConfig) {
183206
);
184207

185208
const assets = dedupeAssets(dependencies.reduce(
186-
(assets, dependency) => assets.concat(dependency.config.assets),
209+
(acc, dependency) => acc.concat(dependency.config.assets),
187210
project.assets
188211
));
189212

190213
const tasks = flatten(dependencies.map(dependency => [
191214
() => promisify(dependency.config.commands.prelink || commandStub),
192215
() => linkDependencyAndroid(project.android, dependency),
193216
() => linkDependencyIOS(project.ios, dependency),
194-
() => linkDependencyWindows(project.windows, dependency),
217+
() => linkDependencyPlatforms(platforms, project, dependency),
195218
() => promisify(dependency.config.commands.postlink || commandStub),
196219
]));
197220

198-
tasks.push(() => linkAssets(project, assets));
221+
tasks.push(() => linkAssets(platforms, project, assets));
199222

200223
return promiseWaterfall(tasks).catch(err => {
201224
log.error(

‎local-cli/link/unlink.js

+32-17
Original file line numberDiff line numberDiff line change
@@ -2,11 +2,9 @@ const log = require('npmlog');
22

33
const getProjectDependencies = require('./getProjectDependencies');
44
const unregisterDependencyAndroid = require('./android/unregisterNativeModule');
5-
const unregisterDependencyWindows = require('./windows/unregisterNativeModule');
65
const unregisterDependencyIOS = require('./ios/unregisterNativeModule');
76
const unregisterDependencyPods = require('./pods/unregisterNativeModule');
87
const isInstalledAndroid = require('./android/isInstalled');
9-
const isInstalledWindows = require('./windows/isInstalled');
108
const isInstalledIOS = require('./ios/isInstalled');
119
const isInstalledPods = require('./pods/isInstalled');
1210
const unlinkAssetsAndroid = require('./android/unlinkAssets');
@@ -42,23 +40,38 @@ const unlinkDependencyAndroid = (androidProject, dependency, packageName) => {
4240
log.info(`Android module ${packageName} has been successfully unlinked`);
4341
};
4442

45-
const unlinkDependencyWindows = (windowsProject, dependency, packageName) => {
46-
if (!windowsProject || !dependency.windows) {
47-
return;
48-
}
43+
const unlinkDependencyPlatforms = (platforms, project, dependency, packageName) => {
4944

50-
const isInstalled = isInstalledWindows(windowsProject, dependency.windows);
45+
const ignorePlatforms = ['android', 'ios'];
46+
Object.keys(platforms || {})
47+
.filter(platform => ignorePlatforms.indexOf(platform) < 0)
48+
.forEach(platform => {
49+
if (!project[platform] || !dependency[platform]) {
50+
return null;
51+
}
5152

52-
if (!isInstalled) {
53-
log.info(`Windows module ${packageName} is not installed`);
54-
return;
55-
}
53+
const linkConfig = platforms[platform] && platforms[platform].linkConfig && platforms[platform].linkConfig();
54+
if (!linkConfig || !linkConfig.isInstalled || !linkConfig.unregister) {
55+
return null;
56+
}
57+
58+
const isInstalled = linkConfig.isInstalled(project[platform], dependency[platform]);
59+
60+
if (!isInstalled) {
61+
log.info(`Platform '${platform}' module ${packageName} is not installed`);
62+
return;
63+
}
5664

57-
log.info(`Unlinking ${packageName} windows dependency`);
65+
log.info(`Unlinking ${packageName} ${platform} dependency`);
5866

59-
unregisterDependencyWindows(packageName, dependency.windows, windowsProject);
67+
linkConfig.unregister(
68+
packageName,
69+
dependency[platform],
70+
project[platform]
71+
);
6072

61-
log.info(`Windows module ${packageName} has been successfully unlinked`);
73+
log.info(`Platform '${platform}' module ${dependency.name} has been successfully unlinked`);
74+
});
6275
};
6376

6477
const unlinkDependencyIOS = (iOSProject, dependency, packageName, iOSDependencies) => {
@@ -94,10 +107,12 @@ const unlinkDependencyIOS = (iOSProject, dependency, packageName, iOSDependencie
94107
function unlink(args, config) {
95108
const packageName = args[0];
96109

97-
var project;
98-
var dependency;
110+
let platforms;
111+
let project;
112+
let dependency;
99113

100114
try {
115+
platforms = config.getPlatformConfig();
101116
project = config.getProjectConfig();
102117
} catch (err) {
103118
log.error(
@@ -125,7 +140,7 @@ function unlink(args, config) {
125140
() => promisify(dependency.commands.preunlink || commandStub),
126141
() => unlinkDependencyAndroid(project.android, dependency, packageName),
127142
() => unlinkDependencyIOS(project.ios, dependency, packageName, iOSDependencies),
128-
() => unlinkDependencyWindows(project.windows, dependency, packageName),
143+
() => unlinkDependencyPlatforms(platforms, project, dependency, packageName),
129144
() => promisify(dependency.commands.postunlink || commandStub)
130145
];
131146

‎local-cli/link/windows/isInstalled.js

-8
This file was deleted.

‎local-cli/link/windows/patches/applyParams.js

-23
This file was deleted.

‎local-cli/link/windows/patches/applyPatch.js

-11
This file was deleted.

‎local-cli/link/windows/patches/makePackagePatch.js

-10
This file was deleted.

‎local-cli/link/windows/patches/makeProjectPatch.js

-14
This file was deleted.

‎local-cli/link/windows/patches/makeSolutionPatch.js

-12
This file was deleted.

‎local-cli/link/windows/patches/makeUsingPatch.js

-6
This file was deleted.

‎local-cli/link/windows/patches/revokePatch.js

-9
This file was deleted.

‎local-cli/link/windows/registerNativeModule.js

-26
This file was deleted.

‎local-cli/link/windows/unregisterNativeModule.js

-27
This file was deleted.

0 commit comments

Comments
 (0)
Please sign in to comment.