diff --git a/.gitignore b/.gitignore index bcd22bdb..dc87e483 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,4 @@ node_modules/ build .DS_Store +*.tgz diff --git a/global-cli/index.js b/global-cli/index.js new file mode 100644 index 00000000..94e97219 --- /dev/null +++ b/global-cli/index.js @@ -0,0 +1,159 @@ +#!/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 /!\ +// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +// 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. +// +// 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 init` command. +// +// Do not make breaking changes! We absolutely don't want to have to +// tell people to update their global version of create-react-app. +// +// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// /!\ DO NOT MODIFY THIS FILE /!\ +// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +'use strict'; + +var fs = require('fs'); +var path = require('path'); +var exec = require('child_process').exec; +var spawn = require('child_process').spawn; +var chalk = require('chalk'); +var semver = require('semver'); +/** + * Used arguments: + * -v --version - to print current version of create-react-app and create-react-app-scripts dependency + * --verbose - to print logs while init + * --scripts-version - override default (https://registry.npmjs.org/create-react-app-scripts@latest), + * package to install, examples: + * - "0.22.0-rc1" - A new app will be created using a specific version of React CLI from npm repo + * - "https://registry.npmjs.org/create-react-app-scripts/-/create-react-app-scripts-0.20.0.tgz" - a .tgz archive from any npm repo + * - "/Users/home/create-react-app/create-react-app-scripts-0.22.0.tgz" - for package prepared with `npm pack`, useful for e2e tests + */ +var argv = require('minimist')(process.argv.slice(2)); + +var commands = argv._; +if (commands.length === 0) { + console.error( + 'Usage: create-react-app [--verbose]' + ); + process.exit(1); +} + +if (argv.v || argv.version) { + console.log('create-react-app: ' + require('./package.json').version); + 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.'); + process.exit(); + } + + 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', + '--save', + '--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', + '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; + } + if (!semver.satisfies(process.version, packageJson.engines.node)) { + console.error( + chalk.red( + 'You are currently running Node %s but React CLI requires %s. ' + + 'Please use a supported version of Node.\n' + ), + process.version, + packageJson.engines.node + ); + } +} diff --git a/global-cli/package.json b/global-cli/package.json new file mode 100644 index 00000000..7b25ed00 --- /dev/null +++ b/global-cli/package.json @@ -0,0 +1,12 @@ +{ + "name": "create-react-app", + "version": "1.0.0", + "bin": { + "create-react-app": "index.js" + }, + "dependencies": { + "chalk": "^1.1.1", + "minimist": "^1.2.0", + "semver": "^5.0.3" + } +} diff --git a/init.js b/init.js new file mode 100644 index 00000000..77fd8fac --- /dev/null +++ b/init.js @@ -0,0 +1,3 @@ +module.exports = function(root, appName) { + console.log('Creating the app', appName, 'at', root); +}; diff --git a/package.json b/package.json index 948e7235..da5d86de 100644 --- a/package.json +++ b/package.json @@ -1,5 +1,6 @@ { - "name": "react-getting-started", + "name": "create-react-app-scripts", + "version": "0.0.1", "scripts": { "start": "cross-env NODE_ENV=development node devServer.js", "build": "rimraf build && cross-env NODE_ENV=production webpack --config webpack.config.prod.js"