Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

如何写个CLI?(例子:如何用CLI创建初始化项目) #65

Open
aermin opened this issue May 18, 2019 · 0 comments
Open

如何写个CLI?(例子:如何用CLI创建初始化项目) #65

aermin opened this issue May 18, 2019 · 0 comments

Comments

@aermin
Copy link
Owner

aermin commented May 18, 2019

前言

去年刚好负责团队一个repo的cli,然后写了一些后,这周又回来继续写个cli的功能,生成一个初始化的项目的cli,虽说没难度,但是如果当初写cli有做笔记的话现在来写会更省时省事些。所以现在做个笔记吧

使用的库

commander.js: node.js命令行接口的工具
Inquirer.js: 让命令行跟用户交互,通用化地收集交互数据
chalk: 用来给命令加颜色

用例子上手

首先创建这个cli的项目

image

最后要的效果是执行node bin/init.js init my-app 创建一个项目

image

核心代码

bin/init.js

#!/usr/bin/env node          // 表明这是一个可执行的应用

const commander = require('commander');
const packageJson = require('../package');
const { run } = require('../src/run');

commander
.command('init') // 
.version(packageJson.version) // 
.arguments('<project-directory>') // my-app
.usage('<project-directory> [options]')
.action(run)

commander.parse(process.argv)

run.js

const fs = require('fs');
const path = require('path');
const inquirer = require('inquirer');
const chalk = require('chalk');

// 把模板文件中的变量替换掉
function compile({
  keys,
  values,
  template,
}) {
  const renderTemplate = new Function(...keys, `return \`${template}\``);
  return renderTemplate(...values);
}

// 用inquier 来制用户交互,并拿到交互结果的一个object
async function getPromptAnswers() {
    const answers = await inquirer.prompt([
      {
        type: 'input',
        name: 'projectVersion',
        message: 'project version:',
        default: '1.0.0',
      },
      {
          type: 'input',
          name: 'description',
          message: 'description:',
      },
      {
        type: 'input',
        name: 'license',
        message: 'license:',
        default: 'MIT',
      }
    ]);
    return answers;
}

// export给commander中的action,接受命令行的一些参数,执行你想要做的事情,这里是执行了读取template创建project的代码
async function run(projectName,  cmd) {
  try {
   // 目录是否已存在,存在就throw error,这边用了chalk这个库来给error加颜色
    const directoryExist = fs.existsSync(path.join(process.cwd(), projectName));
    if (directoryExist) throw chalk.red('directory exist!');
    fs.mkdirSync(path.join(process.cwd(), projectName));
    fs.mkdirSync(path.join(process.cwd(), `${projectName}/src`));

   // 取模板-> 解析 -> 写入文件
    const e2eConfigTemplate = fs.readFileSync(path.join(__dirname, './e2eConfigTemplate.js'), 'utf-8').toString();
    const configObj = {
      projectName
    }
    const e2eConfigResult = compile({
      template: e2eConfigTemplate,
      keys: Object.keys(configObj),
      values: Object.values(configObj),
    });
    fs.writeFileSync(path.join(process.cwd(), `${projectName}/e2e.config.js`), e2eConfigResult, 'ascii');

    const packageTemplate = fs.readFileSync(path.join(__dirname, './packageTemplate.js'), 'utf-8').toString();
    const promptAnswers = await getPromptAnswers();
    const packageObj = {
      projectName,
      mainFile : 'index.js',
      teesVersion : "^1.0.0-alpha.31",
      ...promptAnswers
    }
    const result = compile({
      template: packageTemplate,
      keys: Object.keys(packageObj),
      values: Object.values(packageObj),
    });
    fs.writeFileSync(path.join(process.cwd(), `${projectName}/package.json`), result, 'ascii');
    console.log(chalk.green('Init project successfully!'));
  } catch (error) {
    throw error;
  }
}

module.exports = {
  run,
};

完整代码看github仓库

@aermin aermin changed the title 如何写个CLI,有具体例子 如何写个CLI?(例子:如何用CLI创建初始化项目) May 18, 2019
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

1 participant