Skip to content

Commit

Permalink
build: deprecate link all behavior (react-native-community#85)
Browse files Browse the repository at this point in the history
* build: deprecate link all behavior

* Link project assets too

This reverts previous behaviour

* Fix small issue

* Add URL to an issue
  • Loading branch information
Esemesek authored Jan 15, 2019
1 parent 38502ce commit 664fa66
Show file tree
Hide file tree
Showing 4 changed files with 178 additions and 80 deletions.
93 changes: 13 additions & 80 deletions packages/local-cli/link/link.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,102 +11,31 @@
import type { ContextT } from '../core/types.flow';

const log = require('npmlog');
const { isEmpty, pick } = require('lodash');
const chalk = require('chalk');
const { pick } = require('lodash');
const promiseWaterfall = require('./promiseWaterfall');
const getDependencyConfig = require('./getDependencyConfig');
const pollParams = require('./pollParams');
const commandStub = require('./commandStub');
const promisify = require('./promisify');
const getProjectConfig = require('./getProjectConfig');
const linkDependency = require('./linkDependency');
const linkAssets = require('./linkAssets');
const linkAll = require('./linkAll');

const findReactNativeScripts = require('../util/findReactNativeScripts');

const getPlatforms = require('../core/getPlatforms');

log.heading = 'rnpm-link';

const linkDependency = async (platforms, project, dependency) => {
const params = await pollParams(dependency.params);

Object.keys(platforms || {}).forEach(platform => {
if (!project[platform] || !dependency.config[platform]) {
return;
}

const linkConfig =
platforms[platform] &&
platforms[platform].linkConfig &&
platforms[platform].linkConfig();
if (!linkConfig || !linkConfig.isInstalled || !linkConfig.register) {
return;
}

const isInstalled = linkConfig.isInstalled(
project[platform],
dependency.name,
dependency.config[platform]
);

if (isInstalled) {
log.info(
chalk.grey(
`Platform '${platform}' module ${dependency.name} is already linked`
)
);
return;
}

log.info(`Linking ${dependency.name} ${platform} dependency`);

linkConfig.register(
dependency.name,
// $FlowFixMe: We check if dependency.config[platform] exists on line 42
dependency.config[platform],
params,
// $FlowFixMe: We check if project[platform] exists on line 42
project[platform]
);

log.info(
`Platform '${platform}' module ${
dependency.name
} has been successfully linked`
);
});
};

const linkAssets = (platforms, project, dependency) => {
if (isEmpty(dependency.assets)) {
return;
}

Object.keys(platforms || {}).forEach(platform => {
const linkConfig =
platforms[platform] &&
platforms[platform].linkConfig &&
platforms[platform].linkConfig();

if (!linkConfig || !linkConfig.copyAssets || !project[platform]) {
return;
}

log.info(`Linking assets to ${platform} project`);
// $FlowFixMe: We check for existence of project[platform] on line 97.
linkConfig.copyAssets(dependency.assets, project[platform]);
});

log.info('Assets have been successfully linked to your project');
};

type FlagsType = {
platforms: Array<string>,
};

/**
* Links specified package.
* Updates project and links all dependencies to it.
*
* @param args [packageName]
* @param args If optional argument [packageName] is provided,
* only that package is processed.
*/
function link([rawPackageName]: Array<string>, ctx: ContextT, opts: FlagsType) {
let platforms;
Expand All @@ -130,14 +59,18 @@ function link([rawPackageName]: Array<string>, ctx: ContextT, opts: FlagsType) {
);
if (!hasProjectConfig && findReactNativeScripts()) {
throw new Error(
'`react-native link <package>` can not be used in Create React Native App projects. ' +
'`react-native link [package]` can not be used in Create React Native App projects. ' +
'If you need to include a library that relies on custom native code, ' +
'you might have to eject first. ' +
'See https://github.com/react-community/create-react-native-app/blob/master/EJECTING.md ' +
'for more information.'
);
}

if (rawPackageName === undefined) {
return linkAll(ctx, platforms, project);
}

// Trim the version / tag out of the package name (eg. package@latest)
const packageName = rawPackageName.replace(/^(.+?)(@.+?)$/gi, '$1');

Expand All @@ -162,7 +95,7 @@ function link([rawPackageName]: Array<string>, ctx: ContextT, opts: FlagsType) {
module.exports = {
func: link,
description: 'scope link command to certain platforms (comma-separated)',
name: 'link <packageName>',
name: 'link [packageName]',
options: [
{
command: '--platforms [list]',
Expand Down
63 changes: 63 additions & 0 deletions packages/local-cli/link/linkAll.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
// @flow

import type { ContextT, PlatformsT, ProjectConfigT } from '../core/types.flow';

const log = require('npmlog');
const { uniqBy, flatten } = require('lodash');
const path = require('path');
const getAssets = require('../core/getAssets');
const getProjectDependencies = require('./getProjectDependencies');
const getDependencyConfig = require('./getDependencyConfig');
const promiseWaterfall = require('./promiseWaterfall');
const commandStub = require('./commandStub');
const promisify = require('./promisify');
const linkAssets = require('./linkAssets');
const linkDependency = require('./linkDependency');

log.heading = 'rnpm-link';

const dedupeAssets = assets => uniqBy(assets, asset => path.basename(asset));

function linkAll(
context: ContextT,
platforms: PlatformsT,
project: ProjectConfigT
) {
log.warn(
'Running `react-native link` without package name is deprecated and will be removed ' +
'in next release. If you are using `react-native link` to link your project assets, ' +
' let us know about your use case here: https://goo.gl/RKTeoc'
);

const projectAssets = getAssets(context.root);
const dependencies = getProjectDependencies(context.root);
const depenendenciesConfig = dependencies.map(dependnecy =>
getDependencyConfig(context, platforms, dependnecy)
);

const assets = dedupeAssets(
depenendenciesConfig.reduce(
(acc, dependency) => acc.concat(dependency.assets),
projectAssets
)
);

const tasks = flatten(
depenendenciesConfig.map(config => [
() => promisify(config.commands.prelink || commandStub),
() => linkDependency(platforms, project, config),
() => promisify(config.commands.postlink || commandStub),
() => linkAssets(platforms, project, assets),
])
);

return promiseWaterfall(tasks).catch(err => {
log.error(
`Something went wrong while linking. Error: ${err.message} \n` +
'Please file an issue here: https://github.com/facebook/react-native/issues'
);
throw err;
});
}

module.exports = linkAll;
37 changes: 37 additions & 0 deletions packages/local-cli/link/linkAssets.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
// @flow

import type { PlatformsT, ProjectConfigT } from '../core/types.flow';

const log = require('npmlog');
const { isEmpty } = require('lodash');

log.heading = 'rnpm-link';

const linkAssets = (
platforms: PlatformsT,
project: ProjectConfigT,
dependency: *
) => {
if (isEmpty(dependency.assets)) {
return;
}

Object.keys(platforms || {}).forEach(platform => {
const linkConfig =
platforms[platform] &&
platforms[platform].linkConfig &&
platforms[platform].linkConfig();

if (!linkConfig || !linkConfig.copyAssets || !project[platform]) {
return;
}

log.info(`Linking assets to ${platform} project`);
// $FlowFixMe: We check for existence of project[platform]
linkConfig.copyAssets(dependency.assets, project[platform]);
});

log.info('Assets have been successfully linked to your project');
};

module.exports = linkAssets;
65 changes: 65 additions & 0 deletions packages/local-cli/link/linkDependency.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
// @flow

import type { PlatformsT, ProjectConfigT } from '../core/types.flow';

const log = require('npmlog');
const chalk = require('chalk');
const pollParams = require('./pollParams');

log.heading = 'rnpm-link';

const linkDependency = async (
platforms: PlatformsT,
project: ProjectConfigT,
dependency: *
) => {
const params = await pollParams(dependency.params);

Object.keys(platforms || {}).forEach(platform => {
if (!project[platform] || !dependency.config[platform]) {
return;
}

const linkConfig =
platforms[platform] &&
platforms[platform].linkConfig &&
platforms[platform].linkConfig();
if (!linkConfig || !linkConfig.isInstalled || !linkConfig.register) {
return;
}

const isInstalled = linkConfig.isInstalled(
project[platform],
dependency.name,
dependency.config[platform]
);

if (isInstalled) {
log.info(
chalk.grey(
`Platform '${platform}' module ${dependency.name} is already linked`
)
);
return;
}

log.info(`Linking ${dependency.name} ${platform} dependency`);

linkConfig.register(
dependency.name,
// $FlowFixMe: We check if dependency.config[platform] exists on line 42
dependency.config[platform],
params,
// $FlowFixMe: We check if project[platform] exists on line 42
project[platform]
);

log.info(
`Platform '${platform}' module ${
dependency.name
} has been successfully linked`
);
});
};

module.exports = linkDependency;

0 comments on commit 664fa66

Please sign in to comment.