浅析node命令行工具库cac

1,277 阅读3分钟

简介

这是个用于构建cli类型的app的命令行工具库,学习一下维护一个npm库需要做哪些事情

快速上手

// 创建一个cac实例
const cac = new CAC()

// 注册选项,可用尖括号代表必填参数,方括号可选参数
cac.option('--type [type]', 'Choose a project type', {default: 'node'})

// 注册命令,...同展开操作符,可填多个文件
cac.command('lint [...files]', 'lint files').action((files, options) => {
   // lint files
})

// 注册命令选项
cac.command('rm <dir>', 'Remove a dir')
  .option('-r, --recursive', 'Remove recursively')
  .action((dir, options) => {
    console.log('remove ' + dir + (options.recursive ? ' recursively' : ''))
  })
  
// 获取命令行输入参数 
cac.parse()

实现思路

主要是有CAC、Command、Option三个类,对外提供CAC类。

通过cac类实现command、option的注册

通过面向对象的思想,将option挂在cammand实例上,option收集到cac实例中

用户调用时,通过cac.parse()方法,获取到用户命令行输入,解析得到command name、option和参数,遍历查找comamnd实现对应命令的调用

在调用每个类的方法时,都会返回this,实现连续的api调用,和jquery的方式一致

核心实现说明

Snipaste_2022-07-10_14-24-27.png

Option类

接收三个参数

  public rawName: string,
  public description: string,
  config?: OptionConfig

rawName 定义option 名称,用字符串解析的方式,解析出名称 + 参数,将相关解析结果都记录为自身属性

Command类

实现命令注册,通过输入命令名称 + 参数的字符串模版

在this上存放解析出的各种参数,获得一个command对象后,cac实例会将command对象push收集到自己的coomands数组中

//  constructor
    this.options = []
    this.aliasNames = []
    this.name = removeBrackets(rawName) // 解析去掉括号后的参数名、别名
    this.args = findAllBrackets(rawName) // 解析出所有的参数,识别参数的特殊形式,如展开参数,
    this.examples = []

action

命令对应的行为,command类上带有action的注册方法,传入一个接收了自定义参数和options的回调函数,会在命令执行时执行,同时触发command:${commandName}事件

Cac类继承了nodejs的EventEmitter类的事件订阅on方法和事件触发emit方法,用户可自行通过 cac.on(() => {})注册事件

Brackets 的实现

字符串模版解析中,有尖括号和方括号,用来区分可选和必选参数

实际实现中,主要通过以下正则匹配

const ANGLED_BRACKET_RE_GLOBAL = /<([^>]+)>/g
const SQUARE_BRACKET_RE_GLOBAL = /\[([^\]]+)\]/g

// 将解析出的参数用以下对象形式描述
{
      required: match[0].startsWith('<'),
      value,
      variadic
}

解析出所有的尖括号和方括号参数后,返回参数数据,存放到command实例上,在parse调用时再做处理

Negated Options 是如何实现的?

解析出对应的点嵌套的option,存到对象中

目录及文件分析

  • src存放的是核心代码。通常有一个index文件提供对外导出,utils工具函数,其余的项目核心代码
  • examples存放示例代码
  • scripts 存放脚本代码
  • 根目录下还有一系列的项目配置文件

.editorconfig

  • 主流编辑器支持通过此文件定义文件格式,设置文件的换行、缩进

.gitattributes

  • 执行git操作时,可以对文件格式进行统一,可以使不同的用户在拉取到代码时有着统一的格式

README

依次由logo、introduction、features、目录、安装方式、使用方式、更详细的API说明、项目相关的荣誉说明(star、引用)、作者信息简介

rollup.config.js

导出了三个配置,分别对应cjs、ts、esm

circle.yml

类似Jenkins的构建工具,支持github