Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Ship a yarn.lock - WIP #1629

Closed
wants to merge 4 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
158 changes: 112 additions & 46 deletions packages/create-react-app/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,8 @@ var path = require('path');
var execSync = require('child_process').execSync;
var spawn = require('cross-spawn');
var semver = require('semver');
var https = require('https');
var request = require('request');

var projectName;

Expand Down Expand Up @@ -145,12 +147,14 @@ function shouldUseYarn() {
}
}

function install(dependencies, verbose, callback) {
function install(dependencies, verbose, useYarnLock, callback) {
var command;
var args;
if (shouldUseYarn()) {
command = 'yarnpkg';
args = [ 'add', '--exact'].concat(dependencies);

// If the yarn.lock exists, just run `yarnpkg`.
args = useYarnLock ? [] : ['add', '--exact'].concat(dependencies);
} else {
checkNpmVersion();
command = 'npm';
Expand All @@ -173,58 +177,100 @@ function run(root, appName, version, verbose, originalDirectory, template) {

var allDependencies = ['react', 'react-dom', packageToInstall];

var installDependencies = function(yarnLockExists) {
install(allDependencies, verbose, yarnLockExists, function(code, command, args) {
if (code !== 0) {
console.log();
console.error('Aborting installation.', chalk.cyan(command + ' ' + args.join(' ')), 'has failed.');
// On 'exit' we will delete these files from target directory.
var knownGeneratedFiles = [
'package.json', 'npm-debug.log', 'yarn-error.log', 'yarn-debug.log', 'node_modules'
];
var currentFiles = fs.readdirSync(path.join(root));
currentFiles.forEach(function (file) {
knownGeneratedFiles.forEach(function (fileToMatch) {
// This will catch `(npm-debug|yarn-error|yarn-debug).log*` files
// and the rest of knownGeneratedFiles.
if ((fileToMatch.match(/.log/g) && file.indexOf(fileToMatch) === 0) || file === fileToMatch) {
console.log('Deleting generated file...', chalk.cyan(file));
fs.removeSync(path.join(root, file));
}
});
});
var remainingFiles = fs.readdirSync(path.join(root));
if (!remainingFiles.length) {
// Delete target folder if empty
console.log('Deleting', chalk.cyan(appName + '/'), 'from', chalk.cyan(path.resolve(root, '..')));
fs.removeSync(path.join(root));
}
console.log('Done.');
process.exit(1);
}

checkNodeVersion(packageName);

// Since react-scripts has been installed with --save
// We need to move it into devDependencies and rewrite package.json
if (!yarnLockExists) {
moveReactScriptsToDev(packageName);
}

var scriptsPath = path.resolve(
process.cwd(),
'node_modules',
packageName,
'scripts',
'init.js'
);
var init = require(scriptsPath);
init(root, appName, verbose, originalDirectory, template);
});
}

console.log('Installing packages. This might take a couple minutes.');
console.log(
'Installing ' + chalk.cyan('react') + ', ' + chalk.cyan('react-dom') +
', and ' + chalk.cyan(packageName) + '...'
);
console.log();

install(allDependencies, verbose, function(code, command, args) {
if (code !== 0) {
console.log();
console.error('Aborting installation.', chalk.cyan(command + ' ' + args.join(' ')), 'has failed.');
// On 'exit' we will delete these files from target directory.
var knownGeneratedFiles = [
'package.json', 'npm-debug.log', 'yarn-error.log', 'yarn-debug.log', 'node_modules'
];
var currentFiles = fs.readdirSync(path.join(root));
currentFiles.forEach(function (file) {
knownGeneratedFiles.forEach(function (fileToMatch) {
// This will catch `(npm-debug|yarn-error|yarn-debug).log*` files
// and the rest of knownGeneratedFiles.
if ((fileToMatch.match(/.log/g) && file.indexOf(fileToMatch) === 0) || file === fileToMatch) {
console.log('Deleting generated file...', chalk.cyan(file));
fs.removeSync(path.join(root, file));
}
});
});
var remainingFiles = fs.readdirSync(path.join(root));
if (!remainingFiles.length) {
// Delete target folder if empty
console.log('Deleting', chalk.cyan(appName + '/'), 'from', chalk.cyan(path.resolve(root, '..')));
fs.removeSync(path.join(root));
// Try to download the yarn.lock file.
if (shouldUseYarn()) {
var releaseRequest = request({
uri: 'https://api.github.com/repos/facebookincubator/create-react-app/releases/latest',
method: 'GET',
headers: {
'User-Agent': 'create-react-app'
}
console.log('Done.');
process.exit(1);
}

checkNodeVersion(packageName);

// Since react-scripts has been installed with --save
// We need to move it into devDependencies and rewrite package.json
moveReactScriptsToDev(packageName);

var scriptsPath = path.resolve(
process.cwd(),
'node_modules',
packageName,
'scripts',
'init.js'
);
var init = require(scriptsPath);
init(root, appName, verbose, originalDirectory, template);
});
}, function(err, response, releasesBody) {
var yarnLockUrl = JSON.parse(releasesBody).assets.reduce(function(acc, asset) {
return asset.name === 'yarn.lock' ? asset.browser_download_url : acc;
}, "");

// TODO: We'll want to copy the package.json && yarn.lock,
// `yarn install` will change the lockfile if the deps don't
// satisfy versions in the package.json.

if (!yarnLockUrl) {
installDependencies(false);

return;
}

var yarnLockRequest = request(yarnLockUrl, function(err, response, body) {
fs.writeFileSync('yarn.lock', body); // TODO: Async

// Success. Write the package.json dependencies manually.
writePackageJsonFromYarnLock(packageName, packageToInstall);
installDependencies(true);
}).on('error', function(err) {
fs.unlink(dest);
installDependencies(false);
});
});
} else {
installDependencies(false);
}
}

function getInstallPackage(version) {
Expand Down Expand Up @@ -352,6 +398,26 @@ function moveReactScriptsToDev(packageName) {
fs.writeFileSync(packagePath, JSON.stringify(packageJson, null, 2));
}

// TODO: Get rid of most this - we'll copy a package.json
// Will need to write the name, though.
function writePackageJsonFromYarnLock(packageName, packageVersion) {
var packagePath = path.join(process.cwd(), 'package.json');
var packageJson = require(packagePath);

packageJson.devDependencies = packageJson.devDependencies || {};
packageJson.devDependencies[packageName] = packageVersion;

var reactVersion = 'latest';
var reactDomVersion = 'latest';

packageJson.dependencies = {
'react': reactVersion,
'react-dom': reactDomVersion
};

fs.writeFileSync(packagePath, JSON.stringify(packageJson, null, 2));
}

// If project only contains files generated by GH, it’s safe.
// We also special case IJ-based products .idea because it integrates with CRA:
// https://github.com/facebookincubator/create-react-app/pull/368#issuecomment-243446094
Expand Down
1 change: 1 addition & 0 deletions packages/create-react-app/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
"commander": "^2.9.0",
"cross-spawn": "^4.0.0",
"fs-extra": "^1.0.0",
"request": "^2.79.0",
"semver": "^5.0.3"
}
}