Skip to content

Commit b9de015

Browse files
committed
Merge branch 'master' into redbox
2 parents 4a0286f + 5c8a8ae commit b9de015

File tree

17 files changed

+506
-100
lines changed

17 files changed

+506
-100
lines changed

CHANGELOG.md

Lines changed: 227 additions & 31 deletions
Large diffs are not rendered by default.

appveyor.yml

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
environment:
2+
matrix:
3+
- nodejs_version: 6
4+
test_suite: "simple"
5+
- nodejs_version: 6
6+
test_suite: "installs"
7+
- nodejs_version: 6
8+
test_suite: "kitchensink"
9+
- nodejs_version: 4
10+
test_suite: "simple"
11+
- nodejs_version: 4
12+
test_suite: "installs"
13+
- nodejs_version: 4
14+
test_suite: "kitchensink"
15+
16+
cache:
17+
- node_modules
18+
- packages\react-scripts\node_modules
19+
20+
clone_depth: 50
21+
22+
matrix:
23+
fast_finish: true
24+
25+
platform:
26+
- x64
27+
28+
install:
29+
- ps: Install-Product node $env:nodejs_version $env:platform
30+
31+
build: off
32+
33+
test_script:
34+
- node --version
35+
- npm --version
36+
- sh tasks/e2e-%test_suite%.sh

packages/babel-preset-react-app/index.js

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -30,9 +30,7 @@ const plugins = [
3030
regenerator: true,
3131
// Resolve the Babel runtime relative to the config.
3232
moduleName: path.dirname(require.resolve('babel-runtime/package'))
33-
}],
34-
// Enables parsing of import()
35-
require.resolve('babel-plugin-syntax-dynamic-import')
33+
}]
3634
];
3735

3836
// This is similar to how `env` works in Babel:
@@ -77,7 +75,10 @@ if (env === 'test') {
7775
// JSX, Flow
7876
require.resolve('babel-preset-react')
7977
],
80-
plugins: plugins
78+
plugins: plugins.concat([
79+
// Compiles import() to a deferred require()
80+
require.resolve('babel-plugin-dynamic-import-node')
81+
])
8182
};
8283
} else {
8384
module.exports = {
@@ -97,6 +98,8 @@ if (env === 'test') {
9798
// Async functions are converted to generators by babel-preset-latest
9899
async: false
99100
}],
101+
// Adds syntax support for import()
102+
require.resolve('babel-plugin-syntax-dynamic-import'),
100103
])
101104
};
102105

packages/babel-preset-react-app/package.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "babel-preset-react-app",
3-
"version": "2.1.0",
3+
"version": "2.1.1",
44
"description": "Babel preset used by Create React App",
55
"repository": "facebookincubator/create-react-app",
66
"license": "BSD-3-Clause",
@@ -11,6 +11,7 @@
1111
"index.js"
1212
],
1313
"dependencies": {
14+
"babel-plugin-dynamic-import-node": "1.0.0",
1415
"babel-plugin-syntax-dynamic-import": "6.18.0",
1516
"babel-plugin-transform-class-properties": "6.22.0",
1617
"babel-plugin-transform-object-rest-spread": "6.22.0",

packages/create-react-app/index.js

Lines changed: 153 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@
3939
'use strict';
4040

4141
var chalk = require('chalk');
42+
var validateProjectName = require("validate-npm-package-name");
4243

4344
var currentNodeVersion = process.versions.node;
4445
if (currentNodeVersion.split('.')[0] < 4) {
@@ -58,6 +59,7 @@ var path = require('path');
5859
var execSync = require('child_process').execSync;
5960
var spawn = require('cross-spawn');
6061
var semver = require('semver');
62+
var dns = require('dns');
6163

6264
var projectName;
6365

@@ -97,6 +99,14 @@ if (typeof projectName === 'undefined') {
9799
process.exit(1);
98100
}
99101

102+
function printValidationResults(results) {
103+
if (typeof results !== 'undefined') {
104+
results.forEach(function (error) {
105+
console.error(chalk.red(' * ' + error));
106+
});
107+
}
108+
}
109+
100110
var hiddenProgram = new commander.Command()
101111
.option('--internal-testing-template <path-to-template>', '(internal usage only, DO NOT RELY ON THIS) ' +
102112
'use a non-standard application template')
@@ -145,25 +155,47 @@ function shouldUseYarn() {
145155
}
146156
}
147157

148-
function install(dependencies, verbose, callback) {
149-
var command;
150-
var args;
151-
if (shouldUseYarn()) {
152-
command = 'yarnpkg';
153-
args = [ 'add', '--exact'].concat(dependencies);
154-
} else {
155-
checkNpmVersion();
156-
command = 'npm';
157-
args = ['install', '--save', '--save-exact'].concat(dependencies);
158-
}
158+
function install(useYarn, dependencies, verbose, isOnline) {
159+
return new Promise(function(resolve, reject) {
160+
var command;
161+
var args;
162+
if (useYarn) {
163+
command = 'yarnpkg';
164+
args = [
165+
'add',
166+
'--exact',
167+
];
168+
if (!isOnline) {
169+
args.push('--offline');
170+
}
171+
[].push.apply(args, dependencies);
172+
173+
if (!isOnline) {
174+
console.log(chalk.yellow('You appear to be offline.'));
175+
console.log(chalk.yellow('Falling back to the local Yarn cache.'));
176+
console.log();
177+
}
178+
179+
} else {
180+
checkNpmVersion();
181+
command = 'npm';
182+
args = ['install', '--save', '--save-exact'].concat(dependencies);
183+
}
159184

160-
if (verbose) {
161-
args.push('--verbose');
162-
}
185+
if (verbose) {
186+
args.push('--verbose');
187+
}
163188

164-
var child = spawn(command, args, {stdio: 'inherit'});
165-
child.on('close', function(code) {
166-
callback(code, command, args);
189+
var child = spawn(command, args, {stdio: 'inherit'});
190+
child.on('close', function(code) {
191+
if (code !== 0) {
192+
reject({
193+
command: command + ' ' + args.join(' ')
194+
});
195+
return;
196+
}
197+
resolve();
198+
});
167199
});
168200
}
169201

@@ -179,29 +211,63 @@ function run(root, appName, version, verbose, originalDirectory, template) {
179211
', and ' + chalk.cyan(packageName) + '...'
180212
);
181213
console.log();
182-
183-
install(allDependencies, verbose, function(code, command, args) {
184-
if (code !== 0) {
185-
console.error(chalk.cyan(command + ' ' + args.join(' ')) + ' failed');
214+
215+
var useYarn = shouldUseYarn();
216+
checkIfOnline(useYarn)
217+
.then(function(isOnline) {
218+
return install(useYarn, allDependencies, verbose, isOnline);
219+
})
220+
.then(function() {
221+
checkNodeVersion(packageName);
222+
223+
// Since react-scripts has been installed with --save
224+
// we need to move it into devDependencies and rewrite package.json
225+
// also ensure react dependencies have caret version range
226+
fixDependencies(packageName);
227+
228+
var scriptsPath = path.resolve(
229+
process.cwd(),
230+
'node_modules',
231+
packageName,
232+
'scripts',
233+
'init.js'
234+
);
235+
var init = require(scriptsPath);
236+
init(root, appName, verbose, originalDirectory, template);
237+
})
238+
.catch(function(reason) {
239+
console.log();
240+
console.log('Aborting installation.');
241+
if (reason.command) {
242+
console.log(' ' + chalk.cyan(reason.command), 'has failed.')
243+
}
244+
console.log();
245+
246+
// On 'exit' we will delete these files from target directory.
247+
var knownGeneratedFiles = [
248+
'package.json', 'npm-debug.log', 'yarn-error.log', 'yarn-debug.log', 'node_modules'
249+
];
250+
var currentFiles = fs.readdirSync(path.join(root));
251+
currentFiles.forEach(function (file) {
252+
knownGeneratedFiles.forEach(function (fileToMatch) {
253+
// This will catch `(npm-debug|yarn-error|yarn-debug).log*` files
254+
// and the rest of knownGeneratedFiles.
255+
if ((fileToMatch.match(/.log/g) && file.indexOf(fileToMatch) === 0) || file === fileToMatch) {
256+
console.log('Deleting generated file...', chalk.cyan(file));
257+
fs.removeSync(path.join(root, file));
258+
}
259+
});
260+
});
261+
var remainingFiles = fs.readdirSync(path.join(root));
262+
if (!remainingFiles.length) {
263+
// Delete target folder if empty
264+
console.log('Deleting', chalk.cyan(appName + '/'), 'from', chalk.cyan(path.resolve(root, '..')));
265+
process.chdir(path.resolve(root, '..'));
266+
fs.removeSync(path.join(root));
267+
}
268+
console.log('Done.');
186269
process.exit(1);
187-
}
188-
189-
checkNodeVersion(packageName);
190-
191-
// Since react-scripts has been installed with --save
192-
// We need to move it into devDependencies and rewrite package.json
193-
moveReactScriptsToDev(packageName);
194-
195-
var scriptsPath = path.resolve(
196-
process.cwd(),
197-
'node_modules',
198-
packageName,
199-
'scripts',
200-
'init.js'
201-
);
202-
var init = require(scriptsPath);
203-
init(root, appName, verbose, originalDirectory, template);
204-
});
270+
});
205271
}
206272

207273
function getInstallPackage(version) {
@@ -280,11 +346,18 @@ function checkNodeVersion(packageName) {
280346
}
281347

282348
function checkAppName(appName) {
349+
var validationResult = validateProjectName(appName);
350+
if (!validationResult.validForNewPackages) {
351+
console.error('Could not create a project called ' + chalk.red('"' + appName + '"') + ' because of npm naming restrictions:');
352+
printValidationResults(validationResult.errors);
353+
printValidationResults(validationResult.warnings);
354+
process.exit(1);
355+
}
356+
283357
// TODO: there should be a single place that holds the dependencies
284358
var dependencies = ['react', 'react-dom'];
285359
var devDependencies = ['react-scripts'];
286360
var allDependencies = dependencies.concat(devDependencies).sort();
287-
288361
if (allDependencies.indexOf(appName) >= 0) {
289362
console.error(
290363
chalk.red(
@@ -302,7 +375,29 @@ function checkAppName(appName) {
302375
}
303376
}
304377

305-
function moveReactScriptsToDev(packageName) {
378+
function makeCaretRange(dependencies, name) {
379+
var version = dependencies[name];
380+
381+
if (typeof version === 'undefined') {
382+
console.error(
383+
chalk.red('Missing ' + name + ' dependency in package.json')
384+
);
385+
process.exit(1);
386+
}
387+
388+
var patchedVersion = '^' + version;
389+
390+
if (!semver.validRange(patchedVersion)) {
391+
console.error(
392+
'Unable to patch ' + name + ' dependency version because version ' + chalk.red(version) + ' will become invalid ' + chalk.red(patchedVersion)
393+
);
394+
patchedVersion = version;
395+
}
396+
397+
dependencies[name] = patchedVersion;
398+
}
399+
400+
function fixDependencies(packageName) {
306401
var packagePath = path.join(process.cwd(), 'package.json');
307402
var packageJson = require(packagePath);
308403

@@ -326,6 +421,9 @@ function moveReactScriptsToDev(packageName) {
326421
packageJson.devDependencies[packageName] = packageVersion;
327422
delete packageJson.dependencies[packageName];
328423

424+
makeCaretRange(packageJson.dependencies, 'react');
425+
makeCaretRange(packageJson.dependencies, 'react-dom');
426+
329427
fs.writeFileSync(packagePath, JSON.stringify(packageJson, null, 2));
330428
}
331429

@@ -341,3 +439,17 @@ function isSafeToCreateProjectIn(root) {
341439
return validFiles.indexOf(file) >= 0;
342440
});
343441
}
442+
443+
function checkIfOnline(useYarn) {
444+
if (!useYarn) {
445+
// Don't ping the Yarn registry.
446+
// We'll just assume the best case.
447+
return Promise.resolve(true);
448+
}
449+
450+
return new Promise(function(resolve) {
451+
dns.resolve('registry.yarnpkg.com', function(err) {
452+
resolve(err === null);
453+
});
454+
});
455+
}

packages/create-react-app/package.json

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "create-react-app",
3-
"version": "1.0.4",
3+
"version": "1.2.1",
44
"keywords": [
55
"react"
66
],
@@ -24,6 +24,7 @@
2424
"commander": "^2.9.0",
2525
"cross-spawn": "^4.0.0",
2626
"fs-extra": "^1.0.0",
27-
"semver": "^5.0.3"
27+
"semver": "^5.0.3",
28+
"validate-npm-package-name": "^3.0.0"
2829
}
2930
}

packages/eslint-config-react-app/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "eslint-config-react-app",
3-
"version": "0.5.1",
3+
"version": "0.5.2",
44
"description": "ESLint configuration used by Create React App",
55
"repository": "facebookincubator/create-react-app",
66
"license": "BSD-3-Clause",

packages/react-dev-utils/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "react-dev-utils",
3-
"version": "0.5.0",
3+
"version": "0.5.1",
44
"description": "Webpack utilities used by Create React App",
55
"repository": "facebookincubator/create-react-app",
66
"license": "BSD-3-Clause",

packages/react-scripts/config/webpack.config.dev.js

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -116,14 +116,13 @@ module.exports = {
116116
test: /\.(js|jsx)$/,
117117
enforce: 'pre',
118118
use: [{
119+
// @remove-on-eject-begin
120+
// Point ESLint to our predefined config.
119121
options: {
120-
// @remove-on-eject-begin
121-
// Point ESLint to our predefined config.
122122
configFile: path.join(__dirname, '../.eslintrc'),
123-
useEslintrc: false,
124-
// @remove-on-eject-end
125-
cache: true
123+
useEslintrc: false
126124
},
125+
// @remove-on-eject-end
127126
loader: 'eslint-loader'
128127
}],
129128
include: paths.appSrc

0 commit comments

Comments
 (0)