搭建自己的脚手架(三)---注册命令

84 阅读3分钟

开启掘金成长之旅!这是我参与「掘金日新计划 · 2 月更文挑战」的第 15天,点击查看活动详情

前言

紧接上一篇搭建自己的脚手架(二)---启动阶段以后,我们的准备工作已经ok了,这篇开始我们要开始注册命令行命令

如果有些同学还没使用过commanderinquire库,可以参考我的这篇文章使用commander和inquire创建我们的专属秘书,熟练以后,在来看这篇文章,效果更佳

注册脚手架命令和选项

一个脚手架必写的命令和选项有哪些?

  • init命令:主要是为了初始化项目
  • 帮助信息选项:提供帮助信息,对用户进行友好提示
  • debug选项:用户可以开启debug模式---,方便用户调试

接下来我们先写一下注册函数,并把他添加到core函数中

core/cli/lib/index.js

const { program } = require("commander"); 
function registerCommand(){}

async function core() {
  try {
    // 命令启动前的检查
    await prepare();
    registerCommand();
  } catch (error) {
    log.error(error);
  }
}

书写帮助信息和选项

core/cli/lib/index.js

function registerCommand(){
   program
    .usage("<command> [option]")  // 帮助信息首行内容
    .version(pkg.version) // 定义版本号
    .option('-d,--debug', 'whether to enable debug modal', false); // 添加选项
}
 

创建init项目命令

 program
    .command('init <projectName>')
    .option('-f, --force', 'whether to force init project', false)
    .action((projectName, options) => {
      console.log("projectName:",projectName,'options:',options);
    })

监听debug 选项

 program.on('option:debug', () => {
    if (params.debug) {
      process.env.LOG_LEVEL = 'verbose';
    } else {
      process.env.LOG_LEVEL = 'info';
    }
    // 设置log等级
    log.level = process.env.LOG_LEVEL;
    log.verbose('debug');
  })

未注册的命令进行兜底

 program.on('command:*', (obj) => {
    const commands = program.commands.map((cmd) => cmd.name());
    log.info('未知的命令 ' + obj[0]);
    if (commands.length > 0) {
      log.info('支持的命令 ' + commands.join(','));
    }
  })

这时我们的命令基本就注册好了,接下来就是完善的工作了,比如init后要进行项目创建的工作,因为要创建的内容比较多,所以我们分出一个包来进行写业务

实现init初始化功能

lerna create @wson-koa2-cli/init commands

创建好以后,我们初始化一下

commands/init/lib/index.js

'use strict';


function init(projectName, options) {
    console.log('init', projectName, options);
}

module.exports = init;

然后我们把core/cli/lib/index.js中的注册的init命令的action属性的回调函数换一下

 program
    .command('init <projectName>')
    .option('-f, --force', 'whether to force init project', false)
    .action(init)

判断当前目录是否存在

async function init(projectName, options) {
    // 当前命令行所在的目录
    const cwd = process.cwd();
    // 需要创建的目录地址
    const targetDir = path.join(cwd, projectName);
    // 目录是否已经存在?
    if (fs.existsSync(targetDir)) {
        // 是否要强制创建
        if (options.force) {
            await fs.remove(targetDir)
        } else {
            // 询问用户是否确定要覆盖目录
        }
    }
}

询问是否覆盖

// 是否要强制创建
        if (options.force) {
            await fs.remove(targetDir)
        } else {
            // 询问用户是否确定要覆盖目录
            inquirer.prompt([
                {
                    name: 'isOverwrite',
                    type: 'confirm',
                    message: '当前目录已经存在,是否需要覆盖?'
                }
            ]).then(async(answer) => {
                if (answer.isOverwrite) {
                  // 移除已存在的目录
                  console.log(`\r\nRemoving...`);
                  await fs.remove(targetDir);
                }  
            })
        }

接下来我们创建一个目录,然后测试一下

image.png

good没有问题

如果不存在则创建项目名称

完整的init代码如下

'use strict';
const fs = require('fs-extra');
const path = require('path');
const inquirer = require('inquirer');
const Generator = require('./generator');


async function init(projectName, options) {
    // 当前命令行所在的目录
    const cwd = process.cwd();
    // 需要创建的目录地址
    const targetDir = path.join(cwd, projectName);
    // 目录是否已经存在?
    if (fs.existsSync(targetDir)) {
        // 是否要强制创建
        if (options.force) {
            await fs.remove(targetDir)
        } else {
            // 询问用户是否确定要覆盖目录
            inquirer.prompt([
                {
                    name: 'isOverwrite',
                    type: 'confirm',
                    message: '当前目录已经存在,是否需要覆盖?'
                }
            ]).then(async(answer) => {
                if (answer.isOverwrite) {
                  // 移除已存在的目录
                  console.log(`\r\nRemoving...`);
                  await fs.remove(targetDir);
                }  
            })
        }
    } else {
        // 如果不存在的话创建目录
        fs.mkdirSync(targetDir);
    }
   
}

参考