UNPKG

6.65 kBJavaScriptView Raw
1// @remove-file-on-eject
2/**
3 * Copyright (c) 2015-present, Facebook, Inc.
4 * All rights reserved.
5 *
6 * This source code is licensed under the BSD-style license found in the
7 * LICENSE file in the root directory of this source tree. An additional grant
8 * of patent rights can be found in the PATENTS file in the same directory.
9 */
10'use strict';
11
12// Makes the script crash on unhandled rejections instead of silently
13// ignoring them. In the future, promise rejections that are not handled will
14// terminate the Node.js process with a non-zero exit code.
15process.on('unhandledRejection', err => {
16 throw err;
17});
18
19const fs = require('fs-extra');
20const path = require('path');
21const spawn = require('cross-spawn');
22const chalk = require('chalk');
23const electronCheck = require('./utils/electronCheck');
24
25module.exports = function(
26 appPath,
27 appName,
28 verbose,
29 originalDirectory,
30 template,
31) {
32 electronCheck().then(function() {
33 const ownPackageName = require(path.join(__dirname, '..', 'package.json'))
34 .name;
35 const ownPath = path.join(appPath, 'node_modules', ownPackageName);
36 const appPackage = require(path.join(appPath, 'package.json'));
37 const useYarn = fs.existsSync(path.join(appPath, 'yarn.lock'));
38
39 // Copy over some of the devDependencies
40 appPackage.dependencies = appPackage.dependencies || {};
41 appPackage.devDependencies = appPackage.devDependencies || {};
42
43 // Setup the script rules
44 appPackage.scripts = {
45 start: 'react-scripts start',
46 build: 'react-scripts build',
47 test: 'react-scripts test --env=jsdom',
48 eject: 'react-scripts eject',
49 };
50
51 fs.writeFileSync(
52 path.join(appPath, 'package.json'),
53 JSON.stringify(appPackage, null, 2),
54 );
55
56 const readmeExists = fs.existsSync(path.join(appPath, 'README.md'));
57 if (readmeExists) {
58 fs.renameSync(
59 path.join(appPath, 'README.md'),
60 path.join(appPath, 'README.old.md'),
61 );
62 }
63
64 // Copy the files for the user
65 const templatePath = template
66 ? path.resolve(originalDirectory, template)
67 : path.join(ownPath, 'template');
68 if (fs.existsSync(templatePath)) {
69 fs.copySync(templatePath, appPath);
70 } else {
71 console.error(
72 `Could not locate supplied template: ${chalk.green(templatePath)}`,
73 );
74 return;
75 }
76
77 // Rename gitignore after the fact to prevent npm from renaming it to .npmignore
78 // See: https://github.com/npm/npm/issues/1862
79 fs.move(
80 path.join(appPath, 'gitignore'),
81 path.join(appPath, '.gitignore'),
82 [],
83 err => {
84 if (err) {
85 // Append if there's already a `.gitignore` file there
86 if (err.code === 'EEXIST') {
87 const data = fs.readFileSync(path.join(appPath, 'gitignore'));
88 fs.appendFileSync(path.join(appPath, '.gitignore'), data);
89 fs.unlinkSync(path.join(appPath, 'gitignore'));
90 } else {
91 throw err;
92 }
93 }
94 },
95 );
96
97 let command;
98 let args;
99
100 if (useYarn) {
101 command = 'yarnpkg';
102 args = ['add'];
103 } else {
104 command = 'npm';
105 args = ['install', '--save', verbose && '--verbose'].filter(e => e);
106 }
107 args.push('react', 'react-dom');
108
109 // Install additional template dependencies, if present
110 const templateDependenciesPath = path.join(
111 appPath,
112 '.template.dependencies.json',
113 );
114 if (fs.existsSync(templateDependenciesPath)) {
115 const templateDependencies = require(templateDependenciesPath)
116 .dependencies;
117 args = args.concat(
118 Object.keys(templateDependencies).map(key => {
119 return `${key}@${templateDependencies[key]}`;
120 }),
121 );
122 fs.unlinkSync(templateDependenciesPath);
123 }
124
125 // Install react and react-dom for backward compatibility with old CRA cli
126 // which doesn't install react and react-dom along with react-scripts
127 // or template is presetend (via --internal-testing-template)
128 if (!isReactInstalled(appPackage) || template) {
129 console.log(`Installing react and react-dom using ${command}...`);
130 console.log();
131
132 const proc = spawn.sync(command, args, { stdio: 'inherit' });
133 if (proc.status !== 0) {
134 console.error(`\`${command} ${args.join(' ')}\` failed`);
135 return;
136 }
137 }
138
139 // Display the most elegant way to cd.
140 // This needs to handle an undefined originalDirectory for
141 // backward compatibility with old global-cli's.
142 let cdpath;
143 if (
144 originalDirectory && path.join(originalDirectory, appName) === appPath
145 ) {
146 cdpath = appName;
147 } else {
148 cdpath = appPath;
149 }
150
151 // Change displayed command to yarn instead of yarnpkg
152 const displayedCommand = useYarn ? 'yarn' : 'npm';
153
154 console.log();
155 console.log(`Success! Created ${appName} at ${appPath}`);
156 console.log('Inside that directory, you can run several commands:');
157 console.log(
158 chalk.yellow(
159 `The main electron process is started in "main_process/index.js"`,
160 ),
161 );
162
163 console.log();
164 console.log(chalk.cyan(` ${displayedCommand} start`));
165 console.log(
166 ' Starts the development server. The main electron process directs the webview request the client scripts from the dev server.',
167 );
168 console.log();
169 console.log(
170 chalk.cyan(` ${displayedCommand} ${useYarn ? '' : 'run '}build`),
171 );
172 console.log(' Bundles the app into static files for production.');
173 console.log();
174 console.log(chalk.cyan(` ${displayedCommand} test`));
175 console.log(' Starts the test runner.');
176 console.log();
177 console.log(
178 chalk.cyan(` ${displayedCommand} ${useYarn ? '' : 'run '}eject`),
179 );
180 console.log(
181 ' Removes this tool and copies build dependencies, configuration files',
182 );
183 console.log(
184 ' and scripts into the app directory. If you do this, you can’t go back!',
185 );
186 console.log();
187 console.log('We suggest that you begin by typing:');
188 console.log();
189 console.log(chalk.cyan(' cd'), cdpath);
190 console.log(` ${chalk.cyan(`${displayedCommand} start`)}`);
191 if (readmeExists) {
192 console.log();
193 console.log(
194 chalk.yellow(
195 'You had a `README.md` file, we renamed it to `README.old.md`',
196 ),
197 );
198 }
199 console.log();
200 console.log('Happy hacking!');
201 });
202};
203
204function isReactInstalled(appPackage) {
205 const dependencies = appPackage.dependencies || {};
206
207 return (
208 typeof dependencies.react !== 'undefined' &&
209 typeof dependencies['react-dom'] !== 'undefined'
210 );
211}