react-native/react-native-cli/index.js

229 lines
5.5 KiB
JavaScript
Raw Normal View History

#!/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.
*/
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// /!\ DO NOT MODIFY THIS FILE /!\
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
// react-native-cli 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 react-native-cli is to init the repository and then
// forward all the commands to the local version of react-native.
//
// If you need to add a new command, please add it to local-cli/.
//
// The only reason to modify this file is to add more warnings and
// troubleshooting information for the `react-native init` command.
//
// Do not make breaking changes! We absolutely don't want to have to
// tell people to update their global version of react-native-cli.
//
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// /!\ DO NOT MODIFY THIS FILE /!\
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
2015-09-06 21:06:33 +00:00
'use strict';
var fs = require('fs');
var path = require('path');
var exec = require('child_process').exec;
2015-10-02 08:51:45 +00:00
var spawn = require('child_process').spawn;
var chalk = require('chalk');
2015-09-06 21:06:33 +00:00
var prompt = require('prompt');
var semver = require('semver');
var CLI_MODULE_PATH = function() {
return path.resolve(
process.cwd(),
'node_modules',
'react-native',
'cli.js'
);
};
var REACT_NATIVE_PACKAGE_JSON_PATH = function() {
return path.resolve(
process.cwd(),
'node_modules',
'react-native',
'package.json'
);
};
2015-09-06 21:06:33 +00:00
checkForVersionArgument();
var cli;
var cliPath = CLI_MODULE_PATH();
if (fs.existsSync(cliPath)) {
cli = require(cliPath);
}
if (cli) {
cli.run();
} else {
var args = process.argv.slice(2);
if (args.length === 0) {
console.error(
'You did not pass any commands, did you mean to run `react-native init`?'
);
process.exit(1);
}
switch (args[0]) {
case 'init':
if (args[1]) {
2015-10-02 08:51:45 +00:00
var verbose = process.argv.indexOf('--verbose') >= 0;
init(args[1], verbose);
} else {
console.error(
2015-10-02 08:51:45 +00:00
'Usage: react-native init <ProjectName> [--verbose]'
);
process.exit(1);
}
break;
default:
console.error(
'Command `%s` unrecognized. ' +
'Did you mean to run this inside a react-native project?',
args[0]
);
process.exit(1);
break;
}
}
2015-05-15 08:21:38 +00:00
function validatePackageName(name) {
if (!name.match(/^[$A-Z_][0-9A-Z_$]*$/i)) {
console.error(
'"%s" is not a valid name for a project. Please use a valid identifier ' +
'name (alphanumeric).',
name
);
process.exit(1);
}
if (name === 'React') {
console.error(
2015-05-23 22:59:33 +00:00
'"%s" is not a valid name for a project. Please do not use the ' +
'reserved word "React".',
name
);
process.exit(1);
}
2015-05-15 08:21:38 +00:00
}
2015-10-02 08:51:45 +00:00
function init(name, verbose) {
2015-05-15 08:21:38 +00:00
validatePackageName(name);
if (fs.existsSync(name)) {
2015-10-02 08:51:45 +00:00
createAfterConfirmation(name, verbose);
} else {
2015-10-02 08:51:45 +00:00
createProject(name, verbose);
}
}
2015-10-02 08:51:45 +00:00
function createAfterConfirmation(name, verbose) {
2015-05-18 17:25:17 +00:00
prompt.start();
2015-05-18 17:25:17 +00:00
var property = {
name: 'yesno',
2015-12-12 12:10:36 +00:00
message: 'Directory ' + name + ' already exists. Continue?',
2015-05-18 17:25:17 +00:00
validator: /y[es]*|n[o]?/,
warning: 'Must respond yes or no',
default: 'no'
};
2015-05-18 17:25:17 +00:00
prompt.get(property, function (err, result) {
if (result.yesno[0] === 'y') {
2015-10-02 08:51:45 +00:00
createProject(name, verbose);
2015-05-18 17:25:17 +00:00
} else {
console.log('Project initialization canceled');
process.exit();
}
});
}
2015-10-02 08:51:45 +00:00
function createProject(name, verbose) {
var root = path.resolve(name);
var projectName = path.basename(root);
console.log(
'This will walk you through creating a new React Native project in',
root
);
if (!fs.existsSync(root)) {
fs.mkdirSync(root);
}
var packageJson = {
name: projectName,
version: '0.0.1',
private: true,
scripts: {
start: 'react-native start'
}
};
fs.writeFileSync(path.join(root, 'package.json'), JSON.stringify(packageJson));
process.chdir(root);
console.log('Installing react-native package from npm...');
2015-10-02 08:51:45 +00:00
run(root, projectName, verbose);
2015-10-02 08:51:45 +00:00
}
function run(root, projectName, verbose) {
var args = ['install', '--save'];
if (verbose){
args.push('--verbose');
}
args.push('react-native');
var proc = spawn('npm', args, {stdio: 'inherit'});
2015-10-02 08:51:45 +00:00
proc.on('close', function (code) {
if (code !== 0) {
console.error('`npm install --save react-native` failed');
return;
}
checkNodeVersion();
2015-09-06 21:06:33 +00:00
cli = require(CLI_MODULE_PATH());
2015-10-02 08:51:45 +00:00
cli.init(root, projectName);
});
}
2015-09-06 21:06:33 +00:00
function checkNodeVersion() {
var packageJson = require(REACT_NATIVE_PACKAGE_JSON_PATH());
if (!packageJson.engines || !packageJson.engines.node) {
return;
}
if (!semver.satisfies(process.version, packageJson.engines.node)) {
console.error(chalk.red(
'You are currently running Node %s but React Native requires %s. ' +
'Please use a supported version of Node.\n' +
'See https://facebook.github.io/react-native/docs/getting-started.html'
),
process.version,
packageJson.engines.node);
}
}
2015-09-06 21:06:33 +00:00
function checkForVersionArgument() {
if (process.argv.indexOf('-v') >= 0 || process.argv.indexOf('--version') >= 0) {
var pjson = require('./package.json');
console.log(pjson.version);
process.exit();
}
}