eject.js 4.13 KB
Newer Older
eanplatter's avatar
eanplatter committed
1
2
3
4
5
6
7
8
9
10
11
12
13
/**
 * 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.
 */

var fs = require('fs');
var path = require('path');
var rl = require('readline');
var rimrafSync = require('rimraf').sync;
Dan Abramov's avatar
Dan Abramov committed
14
var spawnSync = require('cross-spawn').sync;
15
var paths = require('../config/paths');
eanplatter's avatar
eanplatter committed
16
17
18
19
20
21
22
23
24
25
26
27

var prompt = function(question, cb) {
  var rlInterface = rl.createInterface({
    input: process.stdin,
    output: process.stdout,
  });
  rlInterface.question(question + '\n', function(answer) {
    rlInterface.close();
    cb(answer);
  })
}

Dan Abramov's avatar
Dan Abramov committed
28
29
30
31
32
33
prompt('Are you sure you want to eject? This action is permanent. [y/N]', function(answer) {
  var shouldEject = answer && (
    answer.toLowerCase() === 'y' ||
    answer.toLowerCase() === 'yes'
  );
  if (!shouldEject) {
Tyler McGinnis's avatar
Tyler McGinnis committed
34
    console.log('Close one! Eject aborted.');
eanplatter's avatar
eanplatter committed
35
36
37
38
39
    process.exit(1);
  }

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

41
42
  var ownPath = path.join(__dirname, '..');
  var appPath = path.join(ownPath, '..', '..');
eanplatter's avatar
eanplatter committed
43
  var files = [
44
45
    path.join('config', 'babel.dev.js'),
    path.join('config', 'babel.prod.js'),
Dan Abramov's avatar
Dan Abramov committed
46
47
    path.join('config', 'flow', 'css.js.flow'),
    path.join('config', 'flow', 'file.js.flow'),
48
    path.join('config', 'eslint.js'),
49
    path.join('config', 'paths.js'),
50
    path.join('config', 'polyfills.js'),
51
52
53
    path.join('config', 'webpack.config.dev.js'),
    path.join('config', 'webpack.config.prod.js'),
    path.join('scripts', 'build.js'),
54
55
    path.join('scripts', 'start.js'),
    path.join('scripts', 'openChrome.applescript')
eanplatter's avatar
eanplatter committed
56
57
  ];

58
  // Ensure that the app folder is clean and we won't override any files
eanplatter's avatar
eanplatter committed
59
  files.forEach(function(file) {
60
    if (fs.existsSync(path.join(appPath, file))) {
Dan Abramov's avatar
Dan Abramov committed
61
62
63
64
65
66
67
68
      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
69
70
  });

71
  // Copy the files over
72
73
74
  fs.mkdirSync(path.join(appPath, 'config'));
  fs.mkdirSync(path.join(appPath, 'config', 'flow'));
  fs.mkdirSync(path.join(appPath, 'scripts'));
75

eanplatter's avatar
eanplatter committed
76
  files.forEach(function(file) {
77
    console.log('Copying ' + file + ' to ' + appPath);
78
    var content = fs
79
      .readFileSync(path.join(ownPath, file), 'utf8')
80
81
82
83
84
      // Remove license header from JS
      .replace(/^\/\*\*(\*(?!\/)|[^*])*\*\//, '')
      // Remove license header from AppleScript
      .replace(/^--.*\n/gm, '')
      .trim() + '\n';
85
    fs.writeFileSync(path.join(appPath, file), content);
eanplatter's avatar
eanplatter committed
86
87
88
  });
  console.log();

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

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

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

  console.log('Updating scripts');
105
106
  Object.keys(appPackage.scripts).forEach(function (key) {
    appPackage.scripts[key] = 'node ./scripts/' + key + '.js'
eanplatter's avatar
eanplatter committed
107
  });
108
  delete appPackage.scripts['eject'];
eanplatter's avatar
eanplatter committed
109

110
  // explicitly specify ESLint config path for editor plugins
111
  appPackage.eslintConfig = {
112
113
114
    extends: './config/eslint.js',
  };

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

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

Dan Abramov's avatar
Dan Abramov committed
128
129
130
  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
131
});