source: frontend/node_modules/react-scripts/scripts/init.js

Last change on this file was 9af201e, checked in by MBK <marija.karapandzova@…>, 11 days ago

Fix frontend appearance

  • Property mode set to 100644
File size: 11.3 KB
Line 
1// @remove-file-on-eject
2/**
3 * Copyright (c) 2015-present, Facebook, Inc.
4 *
5 * This source code is licensed under the MIT license found in the
6 * LICENSE file in the root directory of this source tree.
7 */
8'use strict';
9
10// Makes the script crash on unhandled rejections instead of silently
11// ignoring them. In the future, promise rejections that are not handled will
12// terminate the Node.js process with a non-zero exit code.
13process.on('unhandledRejection', err => {
14 throw err;
15});
16
17const fs = require('fs-extra');
18const path = require('path');
19const chalk = require('react-dev-utils/chalk');
20const execSync = require('child_process').execSync;
21const spawn = require('react-dev-utils/crossSpawn');
22const { defaultBrowsers } = require('react-dev-utils/browsersHelper');
23const os = require('os');
24const verifyTypeScriptSetup = require('./utils/verifyTypeScriptSetup');
25
26function isInGitRepository() {
27 try {
28 execSync('git rev-parse --is-inside-work-tree', { stdio: 'ignore' });
29 return true;
30 } catch (e) {
31 return false;
32 }
33}
34
35function isInMercurialRepository() {
36 try {
37 execSync('hg --cwd . root', { stdio: 'ignore' });
38 return true;
39 } catch (e) {
40 return false;
41 }
42}
43
44function tryGitInit() {
45 try {
46 execSync('git --version', { stdio: 'ignore' });
47 if (isInGitRepository() || isInMercurialRepository()) {
48 return false;
49 }
50
51 execSync('git init', { stdio: 'ignore' });
52 return true;
53 } catch (e) {
54 console.warn('Git repo not initialized', e);
55 return false;
56 }
57}
58
59function tryGitCommit(appPath) {
60 try {
61 execSync('git add -A', { stdio: 'ignore' });
62 execSync('git commit -m "Initialize project using Create React App"', {
63 stdio: 'ignore',
64 });
65 return true;
66 } catch (e) {
67 // We couldn't commit in already initialized git repo,
68 // maybe the commit author config is not set.
69 // In the future, we might supply our own committer
70 // like Ember CLI does, but for now, let's just
71 // remove the Git files to avoid a half-done state.
72 console.warn('Git commit not created', e);
73 console.warn('Removing .git directory...');
74 try {
75 // unlinkSync() doesn't work on directories.
76 fs.removeSync(path.join(appPath, '.git'));
77 } catch (removeErr) {
78 // Ignore.
79 }
80 return false;
81 }
82}
83
84module.exports = function (
85 appPath,
86 appName,
87 verbose,
88 originalDirectory,
89 templateName
90) {
91 const appPackage = require(path.join(appPath, 'package.json'));
92 const useYarn = fs.existsSync(path.join(appPath, 'yarn.lock'));
93
94 if (!templateName) {
95 console.log('');
96 console.error(
97 `A template was not provided. This is likely because you're using an outdated version of ${chalk.cyan(
98 'create-react-app'
99 )}.`
100 );
101 console.error(
102 `Please note that global installs of ${chalk.cyan(
103 'create-react-app'
104 )} are no longer supported.`
105 );
106 console.error(
107 `You can fix this by running ${chalk.cyan(
108 'npm uninstall -g create-react-app'
109 )} or ${chalk.cyan(
110 'yarn global remove create-react-app'
111 )} before using ${chalk.cyan('create-react-app')} again.`
112 );
113 return;
114 }
115
116 const templatePath = path.dirname(
117 require.resolve(`${templateName}/package.json`, { paths: [appPath] })
118 );
119
120 const templateJsonPath = path.join(templatePath, 'template.json');
121
122 let templateJson = {};
123 if (fs.existsSync(templateJsonPath)) {
124 templateJson = require(templateJsonPath);
125 }
126
127 const templatePackage = templateJson.package || {};
128
129 // This was deprecated in CRA v5.
130 if (templateJson.dependencies || templateJson.scripts) {
131 console.log();
132 console.log(
133 chalk.red(
134 'Root-level `dependencies` and `scripts` keys in `template.json` were deprecated for Create React App 5.\n' +
135 'This template needs to be updated to use the new `package` key.'
136 )
137 );
138 console.log('For more information, visit https://cra.link/templates');
139 }
140
141 // Keys to ignore in templatePackage
142 const templatePackageBlacklist = [
143 'name',
144 'version',
145 'description',
146 'keywords',
147 'bugs',
148 'license',
149 'author',
150 'contributors',
151 'files',
152 'browser',
153 'bin',
154 'man',
155 'directories',
156 'repository',
157 'peerDependencies',
158 'bundledDependencies',
159 'optionalDependencies',
160 'engineStrict',
161 'os',
162 'cpu',
163 'preferGlobal',
164 'private',
165 'publishConfig',
166 ];
167
168 // Keys from templatePackage that will be merged with appPackage
169 const templatePackageToMerge = ['dependencies', 'scripts'];
170
171 // Keys from templatePackage that will be added to appPackage,
172 // replacing any existing entries.
173 const templatePackageToReplace = Object.keys(templatePackage).filter(key => {
174 return (
175 !templatePackageBlacklist.includes(key) &&
176 !templatePackageToMerge.includes(key)
177 );
178 });
179
180 // Copy over some of the devDependencies
181 appPackage.dependencies = appPackage.dependencies || {};
182
183 // Setup the script rules
184 const templateScripts = templatePackage.scripts || {};
185 appPackage.scripts = Object.assign(
186 {
187 start: 'react-scripts start',
188 build: 'react-scripts build',
189 test: 'react-scripts test',
190 eject: 'react-scripts eject',
191 },
192 templateScripts
193 );
194
195 // Update scripts for Yarn users
196 if (useYarn) {
197 appPackage.scripts = Object.entries(appPackage.scripts).reduce(
198 (acc, [key, value]) => ({
199 ...acc,
200 [key]: value.replace(/(npm run |npm )/, 'yarn '),
201 }),
202 {}
203 );
204 }
205
206 // Setup the eslint config
207 appPackage.eslintConfig = {
208 extends: 'react-app',
209 };
210
211 // Setup the browsers list
212 appPackage.browserslist = defaultBrowsers;
213
214 // Add templatePackage keys/values to appPackage, replacing existing entries
215 templatePackageToReplace.forEach(key => {
216 appPackage[key] = templatePackage[key];
217 });
218
219 fs.writeFileSync(
220 path.join(appPath, 'package.json'),
221 JSON.stringify(appPackage, null, 2) + os.EOL
222 );
223
224 const readmeExists = fs.existsSync(path.join(appPath, 'README.md'));
225 if (readmeExists) {
226 fs.renameSync(
227 path.join(appPath, 'README.md'),
228 path.join(appPath, 'README.old.md')
229 );
230 }
231
232 // Copy the files for the user
233 const templateDir = path.join(templatePath, 'template');
234 if (fs.existsSync(templateDir)) {
235 fs.copySync(templateDir, appPath);
236 } else {
237 console.error(
238 `Could not locate supplied template: ${chalk.green(templateDir)}`
239 );
240 return;
241 }
242
243 // modifies README.md commands based on user used package manager.
244 if (useYarn) {
245 try {
246 const readme = fs.readFileSync(path.join(appPath, 'README.md'), 'utf8');
247 fs.writeFileSync(
248 path.join(appPath, 'README.md'),
249 readme.replace(/(npm run |npm )/g, 'yarn '),
250 'utf8'
251 );
252 } catch (err) {
253 // Silencing the error. As it fall backs to using default npm commands.
254 }
255 }
256
257 const gitignoreExists = fs.existsSync(path.join(appPath, '.gitignore'));
258 if (gitignoreExists) {
259 // Append if there's already a `.gitignore` file there
260 const data = fs.readFileSync(path.join(appPath, 'gitignore'));
261 fs.appendFileSync(path.join(appPath, '.gitignore'), data);
262 fs.unlinkSync(path.join(appPath, 'gitignore'));
263 } else {
264 // Rename gitignore after the fact to prevent npm from renaming it to .npmignore
265 // See: https://github.com/npm/npm/issues/1862
266 fs.moveSync(
267 path.join(appPath, 'gitignore'),
268 path.join(appPath, '.gitignore'),
269 []
270 );
271 }
272
273 // Initialize git repo
274 let initializedGit = false;
275
276 if (tryGitInit()) {
277 initializedGit = true;
278 console.log();
279 console.log('Initialized a git repository.');
280 }
281
282 let command;
283 let remove;
284 let args;
285
286 if (useYarn) {
287 command = 'yarnpkg';
288 remove = 'remove';
289 args = ['add'];
290 } else {
291 command = 'npm';
292 remove = 'uninstall';
293 args = [
294 'install',
295 '--no-audit', // https://github.com/facebook/create-react-app/issues/11174
296 '--save',
297 verbose && '--verbose',
298 ].filter(e => e);
299 }
300
301 // Install additional template dependencies, if present.
302 const dependenciesToInstall = Object.entries({
303 ...templatePackage.dependencies,
304 ...templatePackage.devDependencies,
305 });
306 if (dependenciesToInstall.length) {
307 args = args.concat(
308 dependenciesToInstall.map(([dependency, version]) => {
309 return `${dependency}@${version}`;
310 })
311 );
312 }
313
314 // Install react and react-dom for backward compatibility with old CRA cli
315 // which doesn't install react and react-dom along with react-scripts
316 if (!isReactInstalled(appPackage)) {
317 args = args.concat(['react', 'react-dom']);
318 }
319
320 // Install template dependencies, and react and react-dom if missing.
321 if ((!isReactInstalled(appPackage) || templateName) && args.length > 1) {
322 console.log();
323 console.log(`Installing template dependencies using ${command}...`);
324
325 const proc = spawn.sync(command, args, { stdio: 'inherit' });
326 if (proc.status !== 0) {
327 console.error(`\`${command} ${args.join(' ')}\` failed`);
328 return;
329 }
330 }
331
332 if (args.find(arg => arg.includes('typescript'))) {
333 console.log();
334 verifyTypeScriptSetup();
335 }
336
337 // Remove template
338 console.log(`Removing template package using ${command}...`);
339 console.log();
340
341 const proc = spawn.sync(command, [remove, templateName], {
342 stdio: 'inherit',
343 });
344 if (proc.status !== 0) {
345 console.error(`\`${command} ${args.join(' ')}\` failed`);
346 return;
347 }
348
349 // Create git commit if git repo was initialized
350 if (initializedGit && tryGitCommit(appPath)) {
351 console.log();
352 console.log('Created git commit.');
353 }
354
355 // Display the most elegant way to cd.
356 // This needs to handle an undefined originalDirectory for
357 // backward compatibility with old global-cli's.
358 let cdpath;
359 if (originalDirectory && path.join(originalDirectory, appName) === appPath) {
360 cdpath = appName;
361 } else {
362 cdpath = appPath;
363 }
364
365 // Change displayed command to yarn instead of yarnpkg
366 const displayedCommand = useYarn ? 'yarn' : 'npm';
367
368 console.log();
369 console.log(`Success! Created ${appName} at ${appPath}`);
370 console.log('Inside that directory, you can run several commands:');
371 console.log();
372 console.log(chalk.cyan(` ${displayedCommand} start`));
373 console.log(' Starts the development server.');
374 console.log();
375 console.log(
376 chalk.cyan(` ${displayedCommand} ${useYarn ? '' : 'run '}build`)
377 );
378 console.log(' Bundles the app into static files for production.');
379 console.log();
380 console.log(chalk.cyan(` ${displayedCommand} test`));
381 console.log(' Starts the test runner.');
382 console.log();
383 console.log(
384 chalk.cyan(` ${displayedCommand} ${useYarn ? '' : 'run '}eject`)
385 );
386 console.log(
387 ' Removes this tool and copies build dependencies, configuration files'
388 );
389 console.log(
390 ' and scripts into the app directory. If you do this, you can’t go back!'
391 );
392 console.log();
393 console.log('We suggest that you begin by typing:');
394 console.log();
395 console.log(chalk.cyan(' cd'), cdpath);
396 console.log(` ${chalk.cyan(`${displayedCommand} start`)}`);
397 if (readmeExists) {
398 console.log();
399 console.log(
400 chalk.yellow(
401 'You had a `README.md` file, we renamed it to `README.old.md`'
402 )
403 );
404 }
405 console.log();
406 console.log('Happy hacking!');
407};
408
409function isReactInstalled(appPackage) {
410 const dependencies = appPackage.dependencies || {};
411
412 return (
413 typeof dependencies.react !== 'undefined' &&
414 typeof dependencies['react-dom'] !== 'undefined'
415 );
416}
Note: See TracBrowser for help on using the repository browser.