概述
oclif是用于在Node.js中构建CLI的框架,可以通用化以构建任何自定义CLI。它既设计用于带有几个标志选项的单命令CLI,也设计用于具有多命令的非常复杂的CLI。接下来让我来给大家介绍下oclif框架吧!!!
特性
首先,先介绍一下oclif的特性。
- 标志/参数解析: 通过简单的写法定义标志选项和参数,灵活处理用户输入,以使用户能够以他们期望的方式使用CLI。
- 超高速: 运行oclif CLI命令的开销几乎没有。此外,只有仅需要执行的命令被node加载。 因此,包含许多命令的大型CLI将与使用单个命令的小型CLI一样快地加载。
- CLI生成器: 快速初始化一个项目模版,快速进行开发。
- 自动文档: 默认情况下,您可以传递
--help给CLI以获取帮助,例如标志选项和参数信息。每当发布CLI的npm软件包时,此信息也将自动放置在README.md中。 - 插件: 使用插件,CLI的用户可以使用新功能对其进行扩展,CLI可以拆分为模块化组件,并且可以在多个CLI之间共享功能。
- 钩子: 使用生命周期挂钩可在CLI启动时或在自定义触发器上运行功能。每当需要在CLI的各个组件之间共享自定义功能时,请使用此功能。
- TypeScript: 支持TS,在初始化项目的时候可以选择JS或者TS,oclif的框架内部代码也是使用TS。
- 方便调试: 不用编译,就可以在直接使用。
安装
建议全局安装,这样子在任何地方都可以使用oclif命令了。
# 建议全局安装
npm i oclif -g
单命令
首先,执行 oclif single myls初始化一个项目。根据询问选择自己适合的选项,如果不确定,直接回车就可以了。通过这个项目,我们来简单模拟一下ls的指令。
项目目录结构
编写
index.ts,代码如下
import { Command, flags } from '@oclif/command'
import * as fs from 'fs'
class Myls extends Command {
static description = 'a cli to simulate the cli ls'
static examples = [
'myls',
'myls -f',
'myls -d',
]
static usage = 'myls [-f, -d]'
static flags = {
version: flags.version({ char: 'v' }),
help: flags.help({ char: 'h' }),
file: flags.boolean({ char: 'f', description: 'show all files under the dir', default: false }),
dir: flags.boolean({ char: 'd', description: 'show all directories under the dir', default: false }),
}
static args = []
async run() {
const { flags } = this.parse(Myls)
const { file, dir } = flags
const currentPath = process.cwd()
const dirs = fs.readdirSync(currentPath)
if(dirs.length === 0) this.warn('there is nothing under the path')
if(file && !dir) {
let noFile = true
for(let d of dirs) {
if(fs.statSync(`${currentPath}/${d}`).isFile()) {
noFile = false
this.log(d)
}
noFile && this.warn('no file.')
}
this.exit()
}
if(dir && !file) {
let noDir = true
for(let d of dirs) {
if(fs.statSync(`${currentPath}/${d}`).isDirectory()) {
noDir = false
this.log(d)
}
}
noDir && this.warn('no directory.')
this.exit()
}
for(const d of dirs) {
this.log(d)
}
}
}
export = Myls
基类Command
用oclif命令行创建项目之后,默认会下载很多依赖,具体可以查看package.json文件。首先需要从 @oclif/command引入Command,这是所有命令的基类,所有的命令都应该直接或者间接地继承自它。这个类封装了很多好用的静态属性和方法。
静态属性
- description:这个属性是对于这个命令的简明描述。那你为什么用到它呢?运行命令
myls --help。 - hidden:当你设置为true的时候,在你执行
myls --help,你将看不到它的存在。 - examples:它是一个数组,你可以把怎么使用这个命令的例子写在这里。
- usage:它是一个字符串,这条命令的基本使用,可以填写一条常用的命令在这里。
run方法
它是Command的实例函数,当你使用命令myls的时候,实际上就是去调用这个函数。如果你再这个函数里面只打印了一行内容,其他的什么也你不做,在你的终端上试一试,它就会按你写的打印。
async run() {
console.log('running myls command')
}
//在终端执行命令 myls 打印如下
running myls command
命令参数
参数是传递给命令的位置参数。mycli one two像这样传入参数。所有的参数在一个静态属性args中定义,每个参数名字和每个参数值是一一对应的关系。
| 参数名字 | 参数值 | 描述 | ||
|---|---|---|---|---|
args | firstArg | one | 它是一个对象,有this.parse()解析而出,注意不要和静态属性的args混为一谈。它的格式由静态属性的args定义。 | |
secondArg | two |
| 参数下标 | 参数值 | 描述 | |
|---|---|---|---|
argv | 0 | one | 它是一个数组,命令参数会依次的传入到这个数组。它也是有this.parse()解析而出。 |
| 1 | two |
import {Command, flags} from '@oclif/command'
class MyCLI extends Command {
static flags = {
version: flags.version({ char: 'v' }),
help: flags.help({ char: 'h' }),
}
static args = [
{name: 'firstArg'},
{name: 'secondArg'},
]
async run() {
const {args} = this.parse(MyCLI)
console.log(`${args.firstArg}, ${args.secondArg}`)
const {argv} = this.parse(MyCLI)
console.log(`${argv[0]}, ${argv[1]}`)
}
}
export = MyCLI
命令参数的选项配置
命令标志
标志选项是传递给命令的非位置参数。标志可以是带有参数的选项标志,也可以是不带参数的布尔标志。一个选项标志必须有一个参数。所有的标志在一个静态属性flags中定义,每个标志名字都可配置其相应的缩写。首先从oclif的API中引入flags,这个flags提供了很多函数可以定义不同类型的标志参数。有些可以直接从调用的函数名看出标志参数的类型。
// 简略版
import { Command, flags } from '@oclif/command'
class MyCLI extends Command {
static flags = {
version: flags.version({ char: 'v' }),
help: flags.help({ char: 'h' }),
force: flags.boolean({ char: 'f', default: true }),
id: flags.integer({ char: 'i', options: ['1', '2', '3', '4'] }),
name: flags.string({char: 'n', multiple: true}),
age: age()
}
}
命令标志的选项配置
常用命令
oclif single <NAME>:在当前目录中创建一个单命令项目oclif multi <NAME>:在当前目录中创建一个多命令项目oclif command <NAME>:添加一条命令oclif hook <NAME> --event=<hook>:新建一个钩子oclif plugin <pluginName>:新建一个插件