eject.js 4.01 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;
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
    '.babelrc',
33
    '.eslintrc',
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

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

77
78
  var ownPackage = require(path.join(ownPath, 'package.json'));
  var appPackage = require(path.join(appPath, 'package.json'));
eanplatter's avatar
eanplatter committed
79

80
81
82
  var ownPackageName = ownPackage.name;
  console.log('Removing dependency: ' + ownPackageName);
  delete appPackage.devDependencies[ownPackageName];
eanplatter's avatar
eanplatter committed
83

84
  Object.keys(ownPackage.dependencies).forEach(function (key) {
Dan Abramov's avatar
Dan Abramov committed
85
    // For some reason optionalDependencies end up in dependencies after install
86
    if (ownPackage.optionalDependencies[key]) {
Dan Abramov's avatar
Dan Abramov committed
87
88
89
      return;
    }
    console.log('Adding dependency: ' + key);
90
    appPackage.devDependencies[key] = ownPackage.dependencies[key];
eanplatter's avatar
eanplatter committed
91
92
93
  });

  console.log('Updating scripts');
Dan Abramov's avatar
Dan Abramov committed
94
  delete appPackage.scripts['eject'];
95
  Object.keys(appPackage.scripts).forEach(function (key) {
Dan Abramov's avatar
Dan Abramov committed
96
    appPackage.scripts[key] = appPackage.scripts[key]
97
98
99
100
      .replace(
        new RegExp(ownPackageName + ' (\w+)', 'g'),
        'node scripts/$1.js'
      );
eanplatter's avatar
eanplatter committed
101
102
  });

Dan Abramov's avatar
Dan Abramov committed
103
  // Add Jest config
Christoph Pojer's avatar
Christoph Pojer committed
104
  appPackage.jest = createJestConfig(
105
106
107
    filePath => path.join('<rootDir>', filePath),
    null,
    true
Christoph Pojer's avatar
Christoph Pojer committed
108
109
  );

eanplatter's avatar
eanplatter committed
110
111
  console.log('Writing package.json');
  fs.writeFileSync(
112
113
    path.join(appPath, 'package.json'),
    JSON.stringify(appPackage, null, 2)
eanplatter's avatar
eanplatter committed
114
115
116
117
  );
  console.log();

  console.log('Running npm install...');
118
  rimrafSync(ownPath);
eanplatter's avatar
eanplatter committed
119
  spawnSync('npm', ['install'], {stdio: 'inherit'});
Dan Abramov's avatar
Dan Abramov committed
120
  console.log('Ejected successfully!');
eanplatter's avatar
eanplatter committed
121
122
  console.log();

Dan Abramov's avatar
Dan Abramov committed
123
124
125
  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
126
});