UNPKG

5.67 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 createJestConfig = require('../utils/createJestConfig');
11var fs = require('fs-extra');
12var path = require('path');
13var paths = require('../config/paths');
14var prompt = require('react-dev-utils/prompt');
15var spawnSync = require('cross-spawn').sync;
16var chalk = require('chalk');
17var green = chalk.green;
18var cyan = chalk.cyan;
19
20prompt(
21 'Are you sure you want to eject? This action is permanent.',
22 false
23).then(shouldEject => {
24 if (!shouldEject) {
25 console.log(cyan('Close one! Eject aborted.'));
26 process.exit(1);
27 }
28
29 console.log('Ejecting...');
30
31 var ownPath = path.join(__dirname, '..');
32 var appPath = path.join(ownPath, '..', '..');
33
34 function verifyAbsent(file) {
35 if (fs.existsSync(path.join(appPath, file))) {
36 console.error(
37 '`' + file + '` already exists in your app folder. We cannot ' +
38 'continue as you would lose all the changes in that file or directory. ' +
39 'Please move or delete it (maybe make a copy for backup) and run this ' +
40 'command again.'
41 );
42 process.exit(1);
43 }
44 }
45
46 var folders = [
47 'config',
48 path.join('config', 'jest'),
49 'scripts'
50 ];
51
52 var files = [
53 path.join('config', 'env.js'),
54 path.join('config', 'paths.js'),
55 path.join('config', 'polyfills.js'),
56 path.join('config', 'webpack.config.dev.js'),
57 path.join('config', 'webpack.config.prod.js'),
58 path.join('config', 'jest', 'cssTransform.js'),
59 path.join('config', 'jest', 'fileTransform.js'),
60 path.join('scripts', 'build.js'),
61 path.join('scripts', 'start.js'),
62 path.join('scripts', 'test.js'),
63 path.join('config', 'jest', 'typescriptTransform.js'),
64 path.join('tslint.json'),
65 path.join('config', 'webpackConfigHelper.js')
66 ];
67
68 // Ensure that the app folder is clean and we won't override any files
69 folders.forEach(verifyAbsent);
70 files.forEach(verifyAbsent);
71
72 // Copy the files over
73 folders.forEach(function(folder) {
74 fs.mkdirSync(path.join(appPath, folder))
75 });
76
77 console.log();
78 console.log(cyan('Copying files into ' + appPath));
79 files.forEach(function(file) {
80 console.log(' Adding ' + cyan(file) + ' to the project');
81 var content = fs
82 .readFileSync(path.join(ownPath, file), 'utf8')
83 // Remove dead code from .js files on eject
84 .replace(/\/\/ @remove-on-eject-begin([\s\S]*?)\/\/ @remove-on-eject-end/mg, '')
85 // Remove dead code from .applescript files on eject
86 .replace(/-- @remove-on-eject-begin([\s\S]*?)-- @remove-on-eject-end/mg, '')
87 .trim() + '\n';
88 fs.writeFileSync(path.join(appPath, file), content);
89 });
90 console.log();
91
92 var ownPackage = require(path.join(ownPath, 'package.json'));
93 var appPackage = require(path.join(appPath, 'package.json'));
94 var babelConfig = JSON.parse(fs.readFileSync(path.join(ownPath, '.babelrc'), 'utf8'));
95 var eslintConfig = JSON.parse(fs.readFileSync(path.join(ownPath, '.eslintrc'), 'utf8'));
96
97 console.log(cyan('Updating the dependencies'));
98 var ownPackageName = ownPackage.name;
99 if (appPackage.devDependencies[ownPackageName]) {
100 console.log(' Removing ' + cyan(ownPackageName) + ' from devDependencies');
101 delete appPackage.devDependencies[ownPackageName];
102 }
103 if (appPackage.dependencies[ownPackageName]) {
104 console.log(' Removing ' + cyan(ownPackageName) + ' from dependencies');
105 delete appPackage.dependencies[ownPackageName];
106 }
107
108 Object.keys(ownPackage.dependencies).forEach(function (key) {
109 // For some reason optionalDependencies end up in dependencies after install
110 if (ownPackage.optionalDependencies[key]) {
111 return;
112 }
113 console.log(' Adding ' + cyan(key) + ' to devDependencies');
114 appPackage.devDependencies[key] = ownPackage.dependencies[key];
115 });
116 console.log();
117 console.log(cyan('Updating the scripts'));
118 delete appPackage.scripts['eject'];
119 Object.keys(appPackage.scripts).forEach(function (key) {
120 appPackage.scripts[key] = appPackage.scripts[key]
121 .replace(/react-scripts (\w+)/g, 'node scripts/$1.js');
122 console.log(
123 ' Replacing ' +
124 cyan('"react-scripts ' + key + '"') +
125 ' with ' +
126 cyan('"node scripts/' + key + '.js"')
127 );
128 });
129
130 console.log();
131 console.log(cyan('Configuring package.json'));
132 // Add Jest config
133 console.log(' Adding ' + cyan('Jest') + ' configuration');
134 appPackage.jest = createJestConfig(
135 filePath => path.join('<rootDir>', filePath),
136 null,
137 true
138 );
139
140 // Add Babel config
141
142 console.log(' Adding ' + cyan('Babel') + ' preset');
143 appPackage.babel = babelConfig;
144
145 // Add ESlint config
146 console.log(' Adding ' + cyan('ESLint') +' configuration');
147 appPackage.eslintConfig = eslintConfig;
148
149 fs.writeFileSync(
150 path.join(appPath, 'package.json'),
151 JSON.stringify(appPackage, null, 2) + '\n'
152 );
153 console.log();
154
155 if (fs.existsSync(paths.yarnLockFile)) {
156 console.log(cyan('Running yarn...'));
157 fs.removeSync(ownPath);
158 spawnSync('yarnpkg', [], {stdio: 'inherit'});
159 } else {
160 console.log(cyan('Running npm install...'));
161 fs.removeSync(ownPath);
162 spawnSync('npm', ['install'], {stdio: 'inherit'});
163 }
164 console.log(green('Ejected successfully!'));
165 console.log();
166
167 console.log(green('Please consider sharing why you ejected in this survey:'));
168 console.log(green(' http://goo.gl/forms/Bi6CZjk1EqsdelXk1'));
169 console.log()
170})