eject.js 4.85 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.
 */

10
var createJestConfig = require('../utils/createJestConfig');
eanplatter's avatar
eanplatter committed
11
12
var fs = require('fs');
var path = require('path');
13
var prompt = require('react-dev-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;
16
17
18
var chalk = require('chalk');
var green = chalk.green;
var cyan = chalk.cyan;
eanplatter's avatar
eanplatter committed
19

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

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

31
32
  var ownPath = path.join(__dirname, '..');
  var appPath = path.join(ownPath, '..', '..');
eanplatter's avatar
eanplatter committed
33
  var files = [
34
    path.join('config', 'env.js'),
35
    path.join('config', 'paths.js'),
36
    path.join('config', 'polyfills.js'),
37
38
    path.join('config', 'webpack.config.dev.js'),
    path.join('config', 'webpack.config.prod.js'),
Christoph Pojer's avatar
Christoph Pojer committed
39
40
    path.join('config', 'jest', 'CSSStub.js'),
    path.join('config', 'jest', 'FileStub.js'),
41
    path.join('scripts', 'build.js'),
42
    path.join('scripts', 'start.js'),
43
    path.join('scripts', 'test.js')
eanplatter's avatar
eanplatter committed
44
45
  ];

46
  // Ensure that the app folder is clean and we won't override any files
eanplatter's avatar
eanplatter committed
47
  files.forEach(function(file) {
48
    if (fs.existsSync(path.join(appPath, file))) {
Dan Abramov's avatar
Dan Abramov committed
49
50
51
52
53
54
55
56
      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
57
58
  });

59
  // Copy the files over
60
  fs.mkdirSync(path.join(appPath, 'config'));
Christoph Pojer's avatar
Christoph Pojer committed
61
  fs.mkdirSync(path.join(appPath, 'config', 'jest'));
62
  fs.mkdirSync(path.join(appPath, 'scripts'));
63

64
65
  console.log();
  console.log('Copying files to ' + cyan(appPath));
eanplatter's avatar
eanplatter committed
66
  files.forEach(function(file) {
67
    console.log('  Copying ' + cyan(file));
68
    var content = fs
69
      .readFileSync(path.join(ownPath, file), 'utf8')
70
71
72
73
      // 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, '')
74
      .trim() + '\n';
75
    fs.writeFileSync(path.join(appPath, file), content);
eanplatter's avatar
eanplatter committed
76
77
78
  });
  console.log();

79
80
  var ownPackage = require(path.join(ownPath, 'package.json'));
  var appPackage = require(path.join(appPath, 'package.json'));
81
82
  var babelConfig = JSON.parse(fs.readFileSync(path.join(ownPath, '.babelrc'), 'utf8'));
  var eslintConfig = JSON.parse(fs.readFileSync(path.join(ownPath, '.eslintrc'), 'utf8'));
eanplatter's avatar
eanplatter committed
83

84
  console.log(cyan('Updating dependencies...'));
85
  var ownPackageName = ownPackage.name;
86
  console.log('  Removing dependency: ' + cyan(ownPackageName));
87
  delete appPackage.devDependencies[ownPackageName];
eanplatter's avatar
eanplatter committed
88

89
  Object.keys(ownPackage.dependencies).forEach(function (key) {
Dan Abramov's avatar
Dan Abramov committed
90
    // For some reason optionalDependencies end up in dependencies after install
91
    if (ownPackage.optionalDependencies[key]) {
Dan Abramov's avatar
Dan Abramov committed
92
93
      return;
    }
94
    console.log('  Adding dependency: ' + cyan(key));
95
    appPackage.devDependencies[key] = ownPackage.dependencies[key];
eanplatter's avatar
eanplatter committed
96
  });
97
98
  console.log();
  console.log(cyan('Updating scripts...'));
Dan Abramov's avatar
Dan Abramov committed
99
  delete appPackage.scripts['eject'];
100
  Object.keys(appPackage.scripts).forEach(function (key) {
Dan Abramov's avatar
Dan Abramov committed
101
    appPackage.scripts[key] = appPackage.scripts[key]
102
      .replace(/react-scripts (\w+)/g, 'node scripts/$1.js');
103
104
105
106
107
108
    console.log(
      '  Replacing ' +
      cyan('\"react-scripts ' +  key + '\"') +
      ' with ' +
      cyan('\"' + appPackage.scripts[key] + '\"')
    );
eanplatter's avatar
eanplatter committed
109
110
  });

111
112
  console.log();
  console.log(cyan('Adding configuration to ') + 'package.json' + cyan('...'));
Dan Abramov's avatar
Dan Abramov committed
113
  // Add Jest config
114
  console.log('  Adding ' + cyan('Jest') + ' configuration');
Christoph Pojer's avatar
Christoph Pojer committed
115
  appPackage.jest = createJestConfig(
116
117
118
    filePath => path.join('<rootDir>', filePath),
    null,
    true
Christoph Pojer's avatar
Christoph Pojer committed
119
120
  );

121
  // Add Babel config
122
123

  console.log('  Adding ' + cyan('Babel') + ' preset');
124
125
126
  appPackage.babel = babelConfig;

  // Add ESlint config
127
  console.log('  Adding ' + cyan('ESLint') +' configuration');
128
129
  appPackage.eslintConfig = eslintConfig;

eanplatter's avatar
eanplatter committed
130
  fs.writeFileSync(
131
132
    path.join(appPath, 'package.json'),
    JSON.stringify(appPackage, null, 2)
eanplatter's avatar
eanplatter committed
133
134
135
  );
  console.log();

136
  console.log(cyan('Running npm install...'));
137
  rimrafSync(ownPath);
eanplatter's avatar
eanplatter committed
138
  spawnSync('npm', ['install'], {stdio: 'inherit'});
139
  console.log(green('Ejected successfully!'));
eanplatter's avatar
eanplatter committed
140
141
  console.log();

142
143
144
145
  console.log(green('Please consider sharing why you ejected in this survey:'));
  console.log(green('  http://goo.gl/forms/Bi6CZjk1EqsdelXk1'));
  console.log()
})