UNPKG

5.18 kBJavaScriptView Raw
1/**
2 * Copyright (c) 2015-present, Facebook, Inc.
3 * All rights reserved.
4 *
5 * This source code is licensed under the BSD-style license found in the
6 * LICENSE file in the root directory of this source tree. An additional grant
7 * of patent rights can be found in the PATENTS file in the same directory.
8 */
9
10var fs = require('fs-extra');
11var path = require('path');
12var spawn = require('cross-spawn');
13var chalk = require('chalk');
14
15module.exports = function(appPath, appName, verbose, originalDirectory, template) {
16 var ownPackageName = require(path.join(__dirname, '..', 'package.json')).name;
17 var ownPath = path.join(appPath, 'node_modules', ownPackageName);
18 var appPackage = require(path.join(appPath, 'package.json'));
19 var useYarn = fs.existsSync(path.join(appPath, 'yarn.lock'));
20
21 // Copy over some of the devDependencies
22 appPackage.dependencies = appPackage.dependencies || {};
23 appPackage.devDependencies = appPackage.devDependencies || {};
24
25 // Setup the script rules
26 appPackage.scripts = {
27 'start': 'react-scripts start',
28 'build': 'react-scripts build',
29 'test': 'react-scripts test --env=jsdom',
30 'eject': 'react-scripts eject'
31 };
32
33 fs.writeFileSync(
34 path.join(appPath, 'package.json'),
35 JSON.stringify(appPackage, null, 2)
36 );
37
38 var readmeExists = fs.existsSync(path.join(appPath, 'README.md'));
39 if (readmeExists) {
40 fs.renameSync(path.join(appPath, 'README.md'), path.join(appPath, 'README.old.md'));
41 }
42
43 // Copy the files for the user
44 var templatePath = template ? path.resolve(originalDirectory, template) : path.join(ownPath, 'template');
45 if (fs.existsSync(templatePath)) {
46 fs.copySync(templatePath, appPath);
47 } else {
48 console.error('Could not locate supplied template: ' + chalk.green(templatePath));
49 return;
50 }
51
52 // Rename gitignore after the fact to prevent npm from renaming it to .npmignore
53 // See: https://github.com/npm/npm/issues/1862
54 fs.move(path.join(appPath, 'gitignore'), path.join(appPath, '.gitignore'), [], function (err) {
55 if (err) {
56 // Append if there's already a `.gitignore` file there
57 if (err.code === 'EEXIST') {
58 var data = fs.readFileSync(path.join(appPath, 'gitignore'));
59 fs.appendFileSync(path.join(appPath, '.gitignore'), data);
60 fs.unlinkSync(path.join(appPath, 'gitignore'));
61 } else {
62 throw err;
63 }
64 }
65 });
66
67 // Run yarn or npm for react and react-dom
68 // TODO: having to do two npm/yarn installs is bad, can we avoid it?
69 var command;
70 var args;
71
72 if (useYarn) {
73 command = 'yarnpkg';
74 args = ['add'];
75 } else {
76 command = 'npm';
77 args = [
78 'install',
79 '--save',
80 verbose && '--verbose'
81 ].filter(function(e) { return e; });
82 }
83 args.push('react', 'react-dom', '@types/node', '@types/react', '@types/react-dom', '@types/jest');
84
85 // Install additional template dependencies, if present
86 var templateDependenciesPath = path.join(appPath, '.template.dependencies.json');
87 if (fs.existsSync(templateDependenciesPath)) {
88 var templateDependencies = require(templateDependenciesPath).dependencies;
89 args = args.concat(Object.keys(templateDependencies).map(function (key) {
90 return key + '@' + templateDependencies[key];
91 }));
92 fs.unlinkSync(templateDependenciesPath);
93 }
94
95 console.log('Installing react and react-dom using ' + command + '...');
96 console.log();
97
98 var proc = spawn(command, args, {stdio: 'inherit'});
99 proc.on('close', function (code) {
100 if (code !== 0) {
101 console.error('`' + command + ' ' + args.join(' ') + '` failed');
102 return;
103 }
104
105 // Display the most elegant way to cd.
106 // This needs to handle an undefined originalDirectory for
107 // backward compatibility with old global-cli's.
108 var cdpath;
109 if (originalDirectory &&
110 path.join(originalDirectory, appName) === appPath) {
111 cdpath = appName;
112 } else {
113 cdpath = appPath;
114 }
115
116 console.log();
117 console.log('Success! Created ' + appName + ' at ' + appPath);
118 console.log('Inside that directory, you can run several commands:');
119 console.log();
120 console.log(chalk.cyan(' ' + command + ' start'));
121 console.log(' Starts the development server.');
122 console.log();
123 console.log(chalk.cyan(' ' + command + ' run build'));
124 console.log(' Bundles the app into static files for production.');
125 console.log();
126 console.log(chalk.cyan(' ' + command + ' test'));
127 console.log(' Starts the test runner.');
128 console.log();
129 console.log(chalk.cyan(' ' + command + ' run eject'));
130 console.log(' Removes this tool and copies build dependencies, configuration files');
131 console.log(' and scripts into the app directory. If you do this, you can’t go back!');
132 console.log();
133 console.log('We suggest that you begin by typing:');
134 console.log();
135 console.log(chalk.cyan(' cd'), cdpath);
136 console.log(' ' + chalk.cyan(command + ' start'));
137 if (readmeExists) {
138 console.log();
139 console.log(chalk.yellow('You had a `README.md` file, we renamed it to `README.old.md`'));
140 }
141 console.log();
142 console.log('Happy hacking!');
143 });
144};