123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418 |
- 'use strict';
- process.on('unhandledRejection', err => {
- throw err;
- });
- const fs = require('fs-extra');
- const path = require('path');
- const chalk = require('react-dev-utils/chalk');
- const execSync = require('child_process').execSync;
- const spawn = require('react-dev-utils/crossSpawn');
- const { defaultBrowsers } = require('react-dev-utils/browsersHelper');
- const os = require('os');
- const verifyTypeScriptSetup = require('./utils/verifyTypeScriptSetup');
- function isInGitRepository() {
- try {
- execSync('git rev-parse --is-inside-work-tree', { stdio: 'ignore' });
- return true;
- } catch (e) {
- return false;
- }
- }
- function isInMercurialRepository() {
- try {
- execSync('hg --cwd . root', { stdio: 'ignore' });
- return true;
- } catch (e) {
- return false;
- }
- }
- function tryGitInit() {
- try {
- execSync('git --version', { stdio: 'ignore' });
- if (isInGitRepository() || isInMercurialRepository()) {
- return false;
- }
- execSync('git init', { stdio: 'ignore' });
- return true;
- } catch (e) {
- console.warn('Git repo not initialized', e);
- return false;
- }
- }
- function tryGitCommit(appPath) {
- try {
- execSync('git add -A', { stdio: 'ignore' });
- execSync('git commit -m "Initialize project using Create React App"', {
- stdio: 'ignore',
- });
- return true;
- } catch (e) {
-
-
-
-
-
- console.warn('Git commit not created', e);
- console.warn('Removing .git directory...');
- try {
-
- fs.removeSync(path.join(appPath, '.git'));
- } catch (removeErr) {
-
- }
- return false;
- }
- }
- module.exports = function (
- appPath,
- appName,
- verbose,
- originalDirectory,
- templateName
- ) {
- const appPackage = require(path.join(appPath, 'package.json'));
- const useYarn = fs.existsSync(path.join(appPath, 'yarn.lock'));
- if (!templateName) {
- console.log('');
- console.error(
- `A template was not provided. This is likely because you're using an outdated version of ${chalk.cyan(
- 'create-react-app'
- )}.`
- );
- console.error(
- `Please note that global installs of ${chalk.cyan(
- 'create-react-app'
- )} are no longer supported.`
- );
- console.error(
- `You can fix this by running ${chalk.cyan(
- 'npm uninstall -g create-react-app'
- )} or ${chalk.cyan(
- 'yarn global remove create-react-app'
- )} before using ${chalk.cyan('create-react-app')} again.`
- );
- return;
- }
- const templatePath = path.dirname(
- require.resolve(`${templateName}/package.json`, { paths: [appPath] })
- );
- const templateJsonPath = path.join(templatePath, 'template.json');
- let templateJson = {};
- if (fs.existsSync(templateJsonPath)) {
- templateJson = require(templateJsonPath);
- }
- const templatePackage = templateJson.package || {};
-
-
- if (templateJson.dependencies || templateJson.scripts) {
- console.log();
- console.log(
- chalk.yellow(
- 'Root-level `dependencies` and `scripts` keys in `template.json` are deprecated.\n' +
- 'This template should be updated to use the new `package` key.'
- )
- );
- console.log('For more information, visit https://cra.link/templates');
- }
- if (templateJson.dependencies) {
- templatePackage.dependencies = templateJson.dependencies;
- }
- if (templateJson.scripts) {
- templatePackage.scripts = templateJson.scripts;
- }
-
- const templatePackageBlacklist = [
- 'name',
- 'version',
- 'description',
- 'keywords',
- 'bugs',
- 'license',
- 'author',
- 'contributors',
- 'files',
- 'browser',
- 'bin',
- 'man',
- 'directories',
- 'repository',
- 'peerDependencies',
- 'bundledDependencies',
- 'optionalDependencies',
- 'engineStrict',
- 'os',
- 'cpu',
- 'preferGlobal',
- 'private',
- 'publishConfig',
- ];
-
- const templatePackageToMerge = ['dependencies', 'scripts'];
-
-
- const templatePackageToReplace = Object.keys(templatePackage).filter(key => {
- return (
- !templatePackageBlacklist.includes(key) &&
- !templatePackageToMerge.includes(key)
- );
- });
-
- appPackage.dependencies = appPackage.dependencies || {};
-
- const templateScripts = templatePackage.scripts || {};
- appPackage.scripts = Object.assign(
- {
- start: 'react-scripts start',
- build: 'react-scripts build',
- test: 'react-scripts test',
- eject: 'react-scripts eject',
- },
- templateScripts
- );
-
- if (useYarn) {
- appPackage.scripts = Object.entries(appPackage.scripts).reduce(
- (acc, [key, value]) => ({
- ...acc,
- [key]: value.replace(/(npm run |npm )/, 'yarn '),
- }),
- {}
- );
- }
-
- appPackage.eslintConfig = {
- extends: 'react-app',
- };
-
- appPackage.browserslist = defaultBrowsers;
-
- templatePackageToReplace.forEach(key => {
- appPackage[key] = templatePackage[key];
- });
- fs.writeFileSync(
- path.join(appPath, 'package.json'),
- JSON.stringify(appPackage, null, 2) + os.EOL
- );
- const readmeExists = fs.existsSync(path.join(appPath, 'README.md'));
- if (readmeExists) {
- fs.renameSync(
- path.join(appPath, 'README.md'),
- path.join(appPath, 'README.old.md')
- );
- }
-
- const templateDir = path.join(templatePath, 'template');
- if (fs.existsSync(templateDir)) {
- fs.copySync(templateDir, appPath);
- } else {
- console.error(
- `Could not locate supplied template: ${chalk.green(templateDir)}`
- );
- return;
- }
-
- if (useYarn) {
- try {
- const readme = fs.readFileSync(path.join(appPath, 'README.md'), 'utf8');
- fs.writeFileSync(
- path.join(appPath, 'README.md'),
- readme.replace(/(npm run |npm )/g, 'yarn '),
- 'utf8'
- );
- } catch (err) {
-
- }
- }
- const gitignoreExists = fs.existsSync(path.join(appPath, '.gitignore'));
- if (gitignoreExists) {
-
- const data = fs.readFileSync(path.join(appPath, 'gitignore'));
- fs.appendFileSync(path.join(appPath, '.gitignore'), data);
- fs.unlinkSync(path.join(appPath, 'gitignore'));
- } else {
-
-
- fs.moveSync(
- path.join(appPath, 'gitignore'),
- path.join(appPath, '.gitignore'),
- []
- );
- }
-
- let initializedGit = false;
- if (tryGitInit()) {
- initializedGit = true;
- console.log();
- console.log('Initialized a git repository.');
- }
- let command;
- let remove;
- let args;
- if (useYarn) {
- command = 'yarnpkg';
- remove = 'remove';
- args = ['add'];
- } else {
- command = 'npm';
- remove = 'uninstall';
- args = ['install', '--save', verbose && '--verbose'].filter(e => e);
- }
-
- const dependenciesToInstall = Object.entries({
- ...templatePackage.dependencies,
- ...templatePackage.devDependencies,
- });
- if (dependenciesToInstall.length) {
- args = args.concat(
- dependenciesToInstall.map(([dependency, version]) => {
- return `${dependency}@${version}`;
- })
- );
- }
-
-
- if (!isReactInstalled(appPackage)) {
- args = args.concat(['react', 'react-dom']);
- }
-
- if ((!isReactInstalled(appPackage) || templateName) && args.length > 1) {
- console.log();
- console.log(`Installing template dependencies using ${command}...`);
- const proc = spawn.sync(command, args, { stdio: 'inherit' });
- if (proc.status !== 0) {
- console.error(`\`${command} ${args.join(' ')}\` failed`);
- return;
- }
- }
- if (args.find(arg => arg.includes('typescript'))) {
- console.log();
- verifyTypeScriptSetup();
- }
-
- console.log(`Removing template package using ${command}...`);
- console.log();
- const proc = spawn.sync(command, [remove, templateName], {
- stdio: 'inherit',
- });
- if (proc.status !== 0) {
- console.error(`\`${command} ${args.join(' ')}\` failed`);
- return;
- }
-
- if (initializedGit && tryGitCommit(appPath)) {
- console.log();
- console.log('Created git commit.');
- }
-
-
-
- let cdpath;
- if (originalDirectory && path.join(originalDirectory, appName) === appPath) {
- cdpath = appName;
- } else {
- cdpath = appPath;
- }
-
- const displayedCommand = useYarn ? 'yarn' : 'npm';
- console.log();
- console.log(`Success! Created ${appName} at ${appPath}`);
- console.log('Inside that directory, you can run several commands:');
- console.log();
- console.log(chalk.cyan(` ${displayedCommand} start`));
- console.log(' Starts the development server.');
- console.log();
- console.log(
- chalk.cyan(` ${displayedCommand} ${useYarn ? '' : 'run '}build`)
- );
- console.log(' Bundles the app into static files for production.');
- console.log();
- console.log(chalk.cyan(` ${displayedCommand} test`));
- console.log(' Starts the test runner.');
- console.log();
- console.log(
- chalk.cyan(` ${displayedCommand} ${useYarn ? '' : 'run '}eject`)
- );
- console.log(
- ' Removes this tool and copies build dependencies, configuration files'
- );
- console.log(
- ' and scripts into the app directory. If you do this, you can’t go back!'
- );
- console.log();
- console.log('We suggest that you begin by typing:');
- console.log();
- console.log(chalk.cyan(' cd'), cdpath);
- console.log(` ${chalk.cyan(`${displayedCommand} start`)}`);
- if (readmeExists) {
- console.log();
- console.log(
- chalk.yellow(
- 'You had a `README.md` file, we renamed it to `README.old.md`'
- )
- );
- }
- console.log();
- console.log('Happy hacking!');
- };
- function isReactInstalled(appPackage) {
- const dependencies = appPackage.dependencies || {};
- return (
- typeof dependencies.react !== 'undefined' &&
- typeof dependencies['react-dom'] !== 'undefined'
- );
- }
|