From 499a18d22b5c3c279d1e21f5fd2ef5dbc2795e9e Mon Sep 17 00:00:00 2001 From: Yun Dong Date: Tue, 6 Aug 2019 16:09:24 +0800 Subject: [PATCH] feat: support cli api --- packages/rax-cli/bin/rax.js | 209 +++++++++++++++++++++++++++++++- packages/rax-cli/src/index.js | 222 +++------------------------------- 2 files changed, 219 insertions(+), 212 deletions(-) diff --git a/packages/rax-cli/bin/rax.js b/packages/rax-cli/bin/rax.js index 696727771e..0724a4d168 100755 --- a/packages/rax-cli/bin/rax.js +++ b/packages/rax-cli/bin/rax.js @@ -2,6 +2,14 @@ // Update notifications const updateNotifier = require('update-notifier'); +const fs = require('fs'); +const path = require('path'); +const execSync = require('child_process').execSync; +const spawn = require('cross-spawn'); +const inquirer = require('inquirer'); +const argv = require('minimist')(process.argv.slice(2)); + +const cli = require('../src/'); const pkg = require('../package.json'); updateNotifier({pkg: pkg}).notify(); @@ -25,10 +33,6 @@ if (!semver.satisfies(process.version, '>=8')) { process.exit(1); } -const path = require('path'); -const init = require('../src/'); -const argv = require('minimist')(process.argv.slice(2)); - const RAX_PACKAGE_JSON_PATH = path.resolve( process.cwd(), 'node_modules', @@ -68,6 +72,165 @@ switch (commands[0]) { break; } +function init(name, verbose) { + Promise.resolve(fs.existsSync(name)) + .then(function(dirExists) { + if (dirExists) { + return createAfterConfirmation(name, verbose); + } else { + return; + } + }) + .then(function() { + return askProjectInformaction(name, verbose); + }) + .then(function(answers) { + return createProject(name, verbose, answers); + }) + .catch(function(err) { + console.error('Error occured', err.stack); + process.exit(1); + }); +} + +function createAfterConfirmation(name) { + const property = { + type: 'confirm', + name: 'continueWhileDirectoryExists', + message: 'Directory ' + name + ' already exists. Continue?', + default: false + }; + + return inquirer.prompt(property).then(function(answers) { + if (answers && answers.continueWhileDirectoryExists) { + return true; + } else { + console.log('Project initialization canceled.'); + process.exit(1); + } + }); +} + +function askProjectInformaction(name) { + const questions = [ + { + type: 'list', + name: 'projectType', + message: 'What\'s your project type?', + choices: [ + { + name: 'App (Build application that works multi-platform)', + value: 'app' + }, + { + name: 'Component (Build component for application include web)', + value: 'component' + }, + { + name: 'API (Build universal API library)', + value: 'api' + } + ], + default: 'app' + }, + { + type: 'checkbox', + name: 'projectTargets', + when: function(answers) { + return answers.projectType === 'app'; + }, + validate: function(targets) { + if (targets && targets.length > 0) return true; + return 'Choose at least one of target.'; + }, + message: 'Do you want to build to these targets?', + choices: [ + { + name: 'web', + value: 'web' + }, + { + name: 'weex', + value: 'weex' + }, + { + name: 'miniapp', + value: 'miniapp' + } + ], + default: false + }, + { + type: 'checkbox', + name: 'projectFeatures', + when: function(answers) { + return answers.projectType === 'app' && answers.projectTargets.includes('web'); + }, + message: 'Do you want to enable these features?', + choices: [ + { + name: 'server sider rendering (ssr)', + value: 'ssr' + } + ], + default: false + }, + { + type: 'input', + name: 'projectAuthor', + message: 'What\'s author\'s name?', + default: 'rax' + }, + { + type: 'confirm', + name: 'autoInstallModules', + message: 'Do you want to install dependences automatically after initialization?', + default: 'y' + } + ]; + return inquirer.prompt(questions); +} + +function createProject(name, verbose, userAnswers) { + const pkgManager = shouldUseYarn() ? 'yarn' : 'npm'; + const root = path.resolve(name); + const projectName = name; + const autoInstallModules = userAnswers.autoInstallModules; + + console.log( + 'Creating a new Rax project in', + root + ); + + if (!fs.existsSync(root)) { + fs.mkdirSync(root); + } + process.chdir(root); + + cli.init({ + root: root, + projectName: projectName, + projectType: userAnswers.projectType, + projectFeatures: userAnswers.projectFeatures || [], + projectAuthor: userAnswers.projectAuthor || '', + projectTargets: userAnswers.projectTargets || [], + verbose: verbose, + }).then(function(directory) { + if (autoInstallModules) { + return install(directory, verbose); + } else { + return false; + } + }).then(function(isAutoInstalled) { + console.log(chalk.white.bold('To run your app:')); + console.log(chalk.white(' cd ' + projectName)); + if (!isAutoInstalled) { + console.log(chalk.white(' ' + (pkgManager === 'npm' ? 'npm install' : 'yarn'))); + } + console.log(chalk.white(' ' + pkgManager + ' start')); + }); +} + function checkForVersionArgument() { if (argv._.length === 0 && (argv.v || argv.version)) { console.log('rax-cli: ' + require('../package.json').version); @@ -79,3 +242,41 @@ function checkForVersionArgument() { process.exit(); } } + +function shouldUseYarn() { + try { + execSync('yarn --version', {stdio: 'ignore'}); + return true; + } catch (e) { + return false; + } +} + +/** + * run npm/yarn install + * @param directory - the cwd directory + * @param verbose - enable verbose mode + * @returns {Promise} + */ +function install(directory, verbose) { + console.log(chalk.white.bold('Install dependencies:')); + + const pkgManager = shouldUseYarn() ? 'yarn' : 'npm'; + const args = ['install']; + if (verbose) { + args.push('--verbose'); + } + + return new Promise(function(resolve) { + const proc = spawn(pkgManager, args, {stdio: 'inherit', cwd: directory}); + + proc.on('close', function(code) { + if (code !== 0) { + console.error('`' + pkgManager + ' install` failed'); + resolve(false); + } else { + resolve(true); + } + }); + }); +} diff --git a/packages/rax-cli/src/index.js b/packages/rax-cli/src/index.js index 78bbbe6757..926e04a8e1 100755 --- a/packages/rax-cli/src/index.js +++ b/packages/rax-cli/src/index.js @@ -1,212 +1,18 @@ -const inquirer = require('inquirer'); -const path = require('path'); -const execSync = require('child_process').execSync; -const spawn = require('cross-spawn'); -const chalk = require('chalk'); -const fs = require('fs'); - const generate = require('./generator'); -function createAfterConfirmation(name) { - const property = { - type: 'confirm', - name: 'continueWhileDirectoryExists', - message: 'Directory ' + name + ' already exists. Continue?', - default: false - }; - - return inquirer.prompt(property).then(function(answers) { - if (answers && answers.continueWhileDirectoryExists) { - return true; - } else { - console.log('Project initialization canceled.'); - process.exit(1); - } - }); -} - -function askProjectInformaction(name) { - const questions = [ - { - type: 'list', - name: 'projectType', - message: 'What\'s your project type?', - choices: [ - { - name: 'App (Build application that works multi-platform)', - value: 'app' - }, - { - name: 'Component (Build component for application include web)', - value: 'component' - }, - { - name: 'API (Build universal API library)', - value: 'api' - } - ], - default: 'app' - }, - { - type: 'checkbox', - name: 'projectTargets', - when: function(answers) { - return answers.projectType === 'app'; - }, - validate: function(targets) { - if (targets && targets.length > 0) return true; - return 'Choose at least one of target.'; - }, - message: 'Do you want to build to these targets?', - choices: [ - { - name: 'web', - value: 'web' - }, - { - name: 'weex', - value: 'weex' - }, - { - name: 'miniapp', - value: 'miniapp' - } - ], - default: false - }, - { - type: 'checkbox', - name: 'projectFeatures', - when: function(answers) { - return answers.projectType === 'app' && answers.projectTargets.includes('web'); - }, - message: 'Do you want to enable these features?', - choices: [ - { - name: 'server sider rendering (ssr)', - value: 'ssr' - } - ], - default: false - }, - { - type: 'input', - name: 'projectAuthor', - message: 'What\'s author\'s name?', - default: 'rax' - }, - { - type: 'confirm', - name: 'autoInstallModules', - message: 'Do you want to install dependences automatically after initialization?', - default: 'y' - } - ]; - return inquirer.prompt(questions); -} - -function createProject(name, verbose, userAnswers) { - const pkgManager = shouldUseYarn() ? 'yarn' : 'npm'; - const root = path.resolve(name); - const projectName = userAnswers.projectName; - const autoInstallModules = userAnswers.autoInstallModules; - - console.log( - 'Creating a new Rax project in', - root - ); - - if (!fs.existsSync(root)) { - fs.mkdirSync(root); +module.exports = { + /** + * The entry of init. + * @param {Object} args - describe the init arguements + * @param {String} args.root - The absolute path of project directory + * @param {String} args.projectName - Kebabcased project name + * @param {String} args.projectType - Kebabcased project type + * @param {String} args.projectAuthor - The name of project author + * @param {String} args.projectTargets- The build targets of project + * @param {String} args.projectFeatures- The features of project + * @return {Promise} + */ + init(args) { + return generate(args); } - process.chdir(root); - - generate({ - root: root, - directoryName: name, - projectName: projectName, - projectType: userAnswers.projectType, - projectFeatures: userAnswers.projectFeatures || [], - projectAuthor: userAnswers.projectAuthor || '', - projectTargets: userAnswers.projectTargets || [], - verbose: verbose, - }).then(function(directory) { - if (autoInstallModules) { - return install(directory, verbose); - } else { - return false; - } - }).then(function(isAutoInstalled) { - console.log(chalk.white.bold('To run your app:')); - console.log(chalk.white(' cd ' + projectName)); - if (!isAutoInstalled) { - console.log(chalk.white(' ' + (pkgManager === 'npm' ? 'npm install' : 'yarn'))); - } - console.log(chalk.white(' ' + pkgManager + ' start')); - }); -} - -function shouldUseYarn() { - try { - execSync('yarn --version', {stdio: 'ignore'}); - return true; - } catch (e) { - return false; - } -} - -/** - * run npm/yarn install - * @param directory - the cwd directory - * @param verbose - enable verbose mode - * @returns {Promise} - */ -function install(directory, verbose) { - console.log(chalk.white.bold('Install dependencies:')); - - const pkgManager = shouldUseYarn() ? 'yarn' : 'npm'; - const args = ['install']; - if (verbose) { - args.push('--verbose'); - } - - return new Promise(function(resolve) { - const proc = spawn(pkgManager, args, {stdio: 'inherit', cwd: directory}); - - proc.on('close', function(code) { - if (code !== 0) { - console.error('`' + pkgManager + ' install` failed'); - resolve(false); - } else { - resolve(true); - } - }); - }); -} - -/** - * The entry of init. - * @param {String} name - The name of project - * @param {Boolean} verbose - argv.verbose - * @return {Promise} - */ -module.exports = function init(name, verbose) { - return Promise.resolve(fs.existsSync(name)) - .then(function(dirExists) { - if (dirExists) { - return createAfterConfirmation(name, verbose); - } else { - return; - } - }) - .then(function() { - return askProjectInformaction(name, verbose); - }) - .then(function(answers) { - return createProject(name, verbose, answers); - }) - .catch(function(err) { - console.error('Error occured', err.stack); - process.exit(1); - }); };