react-native/local-cli/upgrade/upgrade.js

175 lines
5.0 KiB
JavaScript

/**
* Copyright (c) 2015-present, Facebook, Inc.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
* @format
*/
'use strict';
const chalk = require('chalk');
const copyProjectTemplateAndReplace = require('../generator/copyProjectTemplateAndReplace');
const fs = require('fs');
const path = require('path');
const printRunInstructions = require('../generator/printRunInstructions');
const semver = require('semver');
const yarn = require('../util/yarn');
/**
* Migrate application to a new version of React Native.
* See http://facebook.github.io/react-native/docs/upgrading.html
*
* IMPORTANT: Assumes the cwd() is the project directory.
* The code here must only be invoked via the CLI:
* $ cd MyAwesomeApp
* $ react-native upgrade
*/
function validateAndUpgrade() {
const projectDir = process.cwd();
const packageJSON = JSON.parse(
fs.readFileSync(path.resolve(projectDir, 'package.json'), 'utf8'),
);
warn(
'You should consider using the new upgrade tool based on Git. It ' +
'makes upgrades easier by resolving most conflicts automatically.\n' +
'To use it:\n' +
'- Go back to the old version of React Native\n' +
'- Run "npm install -g react-native-git-upgrade"\n' +
'- Run "react-native-git-upgrade"\n' +
'See https://facebook.github.io/react-native/docs/upgrading.html',
);
const projectName = packageJSON.name;
if (!projectName) {
warn(
'Your project needs to have a name, declared in package.json, ' +
'such as "name": "AwesomeApp". Please add a project name. Aborting.',
);
return;
}
const version = packageJSON.dependencies['react-native'];
if (!version) {
warn(
'Your "package.json" file doesn\'t seem to declare "react-native" as ' +
'a dependency. Nothing to upgrade. Aborting.',
);
return;
}
if (version === 'latest' || version === '*') {
warn(
'Some major releases introduce breaking changes.\n' +
'Please use a caret version number in your "package.json" file \n' +
'to avoid breakage. Use e.g. react-native: ^0.38.0. Aborting.',
);
return;
}
const installed = JSON.parse(
fs.readFileSync(
path.resolve(projectDir, 'node_modules/react-native/package.json'),
'utf8',
),
);
if (!semver.satisfies(installed.version, version)) {
warn(
'react-native version in "package.json" doesn\'t match ' +
'the installed version in "node_modules".\n' +
'Try running "npm install" to fix this. Aborting.',
);
return;
}
const v = version.replace(/^(~|\^|=)/, '').replace(/x/i, '0');
if (!semver.valid(v)) {
warn(
"A valid version number for 'react-native' is not specified in your " +
"'package.json' file. Aborting.",
);
return;
}
console.log(
'Upgrading project to react-native v' +
installed.version +
'\n' +
'Check out the release notes and breaking changes: ' +
'https://github.com/facebook/react-native/releases/tag/v' +
semver.major(v) +
'.' +
semver.minor(v) +
'.0',
);
// >= v0.21.0, we require react to be a peer dependency
if (semver.gte(v, '0.21.0') && !packageJSON.dependencies.react) {
warn(
'Your "package.json" file doesn\'t seem to have "react" as a dependency.\n' +
'"react" was changed from a dependency to a peer dependency in react-native v0.21.0.\n' +
'Therefore, it\'s necessary to include "react" in your project\'s dependencies.\n' +
'Please run "npm install --save react", then re-run "react-native upgrade".\n',
);
return;
}
if (semver.satisfies(v, '~0.26.0')) {
warn(
'React Native 0.26 introduced some breaking changes to the native files on iOS. You can\n' +
'perform them manually by checking the release notes or use "rnpm" ' +
'to do it automatically.\n' +
'Just run:\n' +
'"npm install -g rnpm && npm install rnpm-plugin-upgrade@0.26 --save-dev", ' +
'then run "rnpm upgrade".',
);
}
return new Promise(resolve => {
upgradeProjectFiles(projectDir, projectName);
console.log(
'Successfully upgraded this project to react-native v' +
installed.version,
);
resolve();
});
}
/**
* Once all checks passed, upgrade the project files.
*/
function upgradeProjectFiles(projectDir, projectName) {
// Just overwrite
copyProjectTemplateAndReplace(
path.resolve(
'node_modules',
'react-native',
'local-cli',
'templates',
'HelloWorld',
),
projectDir,
projectName,
{upgrade: true},
);
}
function warn(message) {
console.warn(chalk.yellow(message));
}
const upgradeCommand = {
name: 'upgrade',
description:
"upgrade your app's template files to the latest version; run this after " +
'updating the react-native version in your package.json and running npm install',
func: validateAndUpgrade,
};
module.exports = upgradeCommand;