index.js 4.64 KB
Newer Older
1
2
3
4
5
6
7
8
9
10
11
#!/usr/bin/env node

/**
 * 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.
 */

Christopher Chedeau's avatar
Christopher Chedeau committed
12
13
14
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//   /!\ DO NOT MODIFY THIS FILE /!\
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
15
16
17
18
19
20
21
22
23
//
// create-react-app is installed globally on people's computers. This means
// that it is extremely difficult to have them upgrade the version and
// because there's only one global version installed, it is very prone to
// breaking changes.
//
// The only job of create-react-app is to init the repository and then
// forward all the commands to the local version of create-react-app.
//
Christopher Chedeau's avatar
Christopher Chedeau committed
24
// If you need to add a new command, please add it to the scripts/ folder.
25
26
//
// The only reason to modify this file is to add more warnings and
Christopher Chedeau's avatar
Christopher Chedeau committed
27
// troubleshooting information for the `create-react-app` command.
28
29
30
31
//
// Do not make breaking changes! We absolutely don't want to have to
// tell people to update their global version of create-react-app.
//
Christopher Chedeau's avatar
Christopher Chedeau committed
32
33
34
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//   /!\ DO NOT MODIFY THIS FILE /!\
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
35
36
37
38
39
40
41
42

'use strict';

var fs = require('fs');
var path = require('path');
var spawn = require('child_process').spawn;
var chalk = require('chalk');
var semver = require('semver');
Christopher Chedeau's avatar
Christopher Chedeau committed
43
44
var argv = require('minimist')(process.argv.slice(2));

45
/**
Christopher Chedeau's avatar
Christopher Chedeau committed
46
47
 * Arguments:
 *   --version - to print current version
48
 *   --verbose - to print logs while init
Christopher Chedeau's avatar
Christopher Chedeau committed
49
50
51
52
53
 *   --scripts-version <alternative package>
 *     Example of valid values:
 *     - a specific npm version: "0.22.0-rc1"
 *     - a .tgz archive from any npm repo: "https://registry.npmjs.org/create-react-app-scripts/-/create-react-app-scripts-0.20.0.tgz"
 *     - a package prepared with `npm pack`: "/Users/home/vjeux/create-react-app/create-react-app-scripts-0.22.0.tgz"
54
55
56
57
58
59
60
61
62
 */
var commands = argv._;
if (commands.length === 0) {
  console.error(
    'Usage: create-react-app <project-name> [--verbose]'
  );
  process.exit(1);
}

Christopher Chedeau's avatar
Christopher Chedeau committed
63
64
if (argv.version) {
  console.log('create-react-app version: ' + require('./package.json').version);
65
66
67
68
69
70
71
72
  process.exit();
}

createApp(commands[0], argv.verbose, argv['scripts-version']);

function createApp(name, verbose, version) {
  if (fs.existsSync(name)) {
    console.log('Directory `' + name + '` already exists. Aborting.');
Christopher Chedeau's avatar
Christopher Chedeau committed
73
    process.exit(1);
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
  }

  var root = path.resolve(name);
  var appName = path.basename(root);

  console.log(
    'This will walk you through creating a new React app in',
    root
  );

  fs.mkdirSync(root);

  var packageJson = {
    name: appName,
    version: '0.0.1',
    private: true,
  };
  fs.writeFileSync(path.join(root, 'package.json'), JSON.stringify(packageJson));
  process.chdir(root);

  console.log('Installing create-react-app-scripts package from npm...');

  run(root, appName, version, verbose);
}

function run(root, appName, version, verbose) {
  var args = [
    'install',
    verbose && '--verbose',
103
    '--save-dev',
104
105
106
107
108
109
110
111
112
113
114
115
116
117
    '--save-exact',
    getInstallPackage(version),
  ].filter(function(e) { return e; });
  var proc = spawn('npm', args, {stdio: 'inherit'});
  proc.on('close', function (code) {
    if (code !== 0) {
      console.error('`npm ' + args.join(' ') + '` failed');
      return;
    }

    var scriptsPath = path.resolve(
      process.cwd(),
      'node_modules',
      'create-react-app-scripts',
118
      'scripts',
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
      'init.js'
    );
    var init = require(scriptsPath);
    init(root, appName);
  });
}

function getInstallPackage(version) {
  var packageToInstall = 'create-react-app-scripts';
  var validSemver = semver.valid(version);
  if (validSemver) {
    packageToInstall += '@' + validSemver;
  } else if (version) {
    // for tar.gz or alternative paths
    packageToInstall = version;
  }
  return packageToInstall;
}

function checkNodeVersion() {
  var packageJsonPath = path.resolve(
    process.cwd(),
    'node_modules',
    'create-react-app-scripts',
    'package.json'
  );
  var packageJson = require(packageJsonPath);
  if (!packageJson.engines || !packageJson.engines.node) {
    return;
  }
Christopher Chedeau's avatar
Christopher Chedeau committed
149

150
151
152
  if (!semver.satisfies(process.version, packageJson.engines.node)) {
    console.error(
      chalk.red(
Christopher Chedeau's avatar
Christopher Chedeau committed
153
154
        'You are currently running Node %s but create-react-app requires %s.' +
        ' Please use a supported version of Node.\n'
155
156
157
158
159
160
      ),
      process.version,
      packageJson.engines.node
    );
  }
}