eject.js 4.58 KB
Newer Older
eanplatter's avatar
eanplatter committed
1
2
3
4
5
6
7
8
9
/**
 * Copyright (c) 2015-present, Facebook, Inc.
 * All rights reserved.
 *
 * This source code is licensed under the BSD-style license found in the
 * LICENSE file in the root directory of this source tree. An additional grant
 * of patent rights can be found in the PATENTS file in the same directory.
 */

Dan Abramov's avatar
Dan Abramov committed
10
var createJestConfig = require('./utils/createJestConfig');
eanplatter's avatar
eanplatter committed
11
12
var fs = require('fs');
var path = require('path');
Christoph Pojer's avatar
Christoph Pojer committed
13
var prompt = require('./utils/prompt');
eanplatter's avatar
eanplatter committed
14
var rimrafSync = require('rimraf').sync;
Dan Abramov's avatar
Dan Abramov committed
15
var spawnSync = require('cross-spawn').sync;
eanplatter's avatar
eanplatter committed
16

17
18
19
20
prompt(
  'Are you sure you want to eject? This action is permanent.',
  false
).then(shouldEject => {
Dan Abramov's avatar
Dan Abramov committed
21
  if (!shouldEject) {
Tyler McGinnis's avatar
Tyler McGinnis committed
22
    console.log('Close one! Eject aborted.');
eanplatter's avatar
eanplatter committed
23
24
25
26
27
    process.exit(1);
  }

  console.log('Ejecting...');
  console.log();
Dan Abramov's avatar
Dan Abramov committed
28

29
30
  var ownPath = path.join(__dirname, '..');
  var appPath = path.join(ownPath, '..', '..');
eanplatter's avatar
eanplatter committed
31
  var files = [
32
    '.eslintrc',
33
34
    path.join('config', 'babel.dev.js'),
    path.join('config', 'babel.prod.js'),
Dan Abramov's avatar
Dan Abramov committed
35
36
    path.join('config', 'flow', 'css.js.flow'),
    path.join('config', 'flow', 'file.js.flow'),
37
    path.join('config', 'paths.js'),
38
    path.join('config', 'env.js'),
39
    path.join('config', 'polyfills.js'),
40
41
    path.join('config', 'webpack.config.dev.js'),
    path.join('config', 'webpack.config.prod.js'),
Christoph Pojer's avatar
Christoph Pojer committed
42
43
44
    path.join('config', 'jest', 'CSSStub.js'),
    path.join('config', 'jest', 'FileStub.js'),
    path.join('config', 'jest', 'transform.js'),
45
    path.join('scripts', 'build.js'),
46
    path.join('scripts', 'start.js'),
47
    path.join('scripts', 'utils', 'checkRequiredFiles.js'),
48
    path.join('scripts', 'utils', 'chrome.applescript'),
49
50
    path.join('scripts', 'utils', 'getClientEnvironment.js'),
    path.join('scripts', 'utils', 'InterpolateHtmlPlugin.js'),
51
52
    path.join('scripts', 'utils', 'prompt.js'),
    path.join('scripts', 'utils', 'WatchMissingNodeModulesPlugin.js')
eanplatter's avatar
eanplatter committed
53
54
  ];

55
  // Ensure that the app folder is clean and we won't override any files
eanplatter's avatar
eanplatter committed
56
  files.forEach(function(file) {
57
    if (fs.existsSync(path.join(appPath, file))) {
Dan Abramov's avatar
Dan Abramov committed
58
59
60
61
62
63
64
65
      console.error(
        '`' + file + '` already exists in your app folder. We cannot ' +
        'continue as you would lose all the changes in that file or directory. ' +
        'Please delete it (maybe make a copy for backup) and run this ' +
        'command again.'
      );
      process.exit(1);
    }
eanplatter's avatar
eanplatter committed
66
67
  });

68
  // Copy the files over
69
70
  fs.mkdirSync(path.join(appPath, 'config'));
  fs.mkdirSync(path.join(appPath, 'config', 'flow'));
Christoph Pojer's avatar
Christoph Pojer committed
71
  fs.mkdirSync(path.join(appPath, 'config', 'jest'));
72
  fs.mkdirSync(path.join(appPath, 'scripts'));
73
  fs.mkdirSync(path.join(appPath, 'scripts', 'utils'));
74

eanplatter's avatar
eanplatter committed
75
  files.forEach(function(file) {
76
    console.log('Copying ' + file + ' to ' + appPath);
77
    var content = fs
78
      .readFileSync(path.join(ownPath, file), 'utf8')
79
80
81
82
      // Remove dead code from .js files on eject
      .replace(/\/\/ @remove-on-eject-begin([\s\S]*?)\/\/ @remove-on-eject-end/mg, '')
      // Remove dead code from .applescript files on eject
      .replace(/-- @remove-on-eject-begin([\s\S]*?)-- @remove-on-eject-end/mg, '')
83
      .trim() + '\n';
84
    fs.writeFileSync(path.join(appPath, file), content);
eanplatter's avatar
eanplatter committed
85
86
87
  });
  console.log();

88
89
  var ownPackage = require(path.join(ownPath, 'package.json'));
  var appPackage = require(path.join(appPath, 'package.json'));
eanplatter's avatar
eanplatter committed
90

91
  console.log('Removing dependency: react-scripts');
92
  delete appPackage.devDependencies['react-scripts'];
eanplatter's avatar
eanplatter committed
93

94
  Object.keys(ownPackage.dependencies).forEach(function (key) {
Dan Abramov's avatar
Dan Abramov committed
95
    // For some reason optionalDependencies end up in dependencies after install
96
    if (ownPackage.optionalDependencies[key]) {
Dan Abramov's avatar
Dan Abramov committed
97
98
99
      return;
    }
    console.log('Adding dependency: ' + key);
100
    appPackage.devDependencies[key] = ownPackage.dependencies[key];
eanplatter's avatar
eanplatter committed
101
102
103
  });

  console.log('Updating scripts');
Dan Abramov's avatar
Dan Abramov committed
104
  delete appPackage.scripts['eject'];
105
  Object.keys(appPackage.scripts).forEach(function (key) {
Dan Abramov's avatar
Dan Abramov committed
106
    appPackage.scripts[key] = appPackage.scripts[key]
107
      .replace(/react-scripts test/g, 'jest --watch')
Dan Abramov's avatar
Dan Abramov committed
108
      .replace(/react-scripts (\w+)/g, 'node scripts/$1.js');
eanplatter's avatar
eanplatter committed
109
110
  });

Dan Abramov's avatar
Dan Abramov committed
111
  // Add Jest config
Christoph Pojer's avatar
Christoph Pojer committed
112
113
114
115
  appPackage.jest = createJestConfig(
    filePath => path.join('<rootDir>', filePath)
  );

eanplatter's avatar
eanplatter committed
116
117
  console.log('Writing package.json');
  fs.writeFileSync(
118
119
    path.join(appPath, 'package.json'),
    JSON.stringify(appPackage, null, 2)
eanplatter's avatar
eanplatter committed
120
121
122
123
  );
  console.log();

  console.log('Running npm install...');
124
  rimrafSync(ownPath);
eanplatter's avatar
eanplatter committed
125
  spawnSync('npm', ['install'], {stdio: 'inherit'});
Dan Abramov's avatar
Dan Abramov committed
126
  console.log('Ejected successfully!');
eanplatter's avatar
eanplatter committed
127
128
  console.log();

Dan Abramov's avatar
Dan Abramov committed
129
130
131
  console.log('Please consider sharing why you ejected in this survey:');
  console.log('  http://goo.gl/forms/Bi6CZjk1EqsdelXk1');
  console.log();
eanplatter's avatar
eanplatter committed
132
});