@oishi/cli-core v3.1.0
@oishi/cli-core
说明
这是一个整合了 commander 和 inquirer,用作创建脚本的底层框架。
使用该框架创建的命令行工具,一份配置通行交互式命令行和命令式命令行。
API
CliCore
框架的核心壳,用来创建声明初始命令行。
如下,创建一个空壳子,框架会自动注入 help 和 version 等指令。
import { CliCore } from "@oishi/cli-core";
const cli = new CliCore({
name: "cli",
description: "常用命令行合集",
version: "0.0.1",
commands: [],
});
cli.execute();使用,cli -h 和 cli --version 查看信息。
# 查看帮助
$ cli -h
Usage: cli [options]
常用命令行合集
Options:
-V, --version output the version number
-i, --interactive 交互式命令行 (default: false)
-h, --help display help for commandinteractive
框架会自动注入 interactive 选项,当运行 cli -i 时,框架将会自动生成交互式命令行。
CliCommand
子命令对象,用来创建命令行的子命令集。
如下,创建一个最简单的命令行,我们希望程序给我们打个招呼,使用 cli say xxx 调用。
import { CliCommand } from "@oishi/cli-core";
interface IArgs {
name: string;
}
interface IOpts {}
const say = new CliCommand<IArgs, IOpts>({
command: "say",
description: "say hello",
arguments: {
name: { description: "请输入您的名称" },
},
options: {},
action({ data, logger, helper }) {
logger.info(`hello ${data.name}`);
},
});创建完 CliCommand 之后,加入到 CliCore 的 commands 中即可。
import { CliCore } from "@oishi/cli-core";
const cli = new CliCore({
name: "cli",
description: "常用命令行合集",
version: "0.0.1",
commands: [say],
});
cli.execute();如下调用,命令行将会输入对应信息。
# 执行指令
$ cli say jsjzh
20XX-XX-XXTXX:XX:XX.XXXZ [cli] info: hello jsjzhcommand
required
子命令的名称,必传,接受字符串,比如传入了 say,则可以使用 cli say 调用。
description
required
子命令的描述,必传,接受字符串,传入的讯息将在 cli say -h 时显示。
arguments
optional
interface IArguments {
description: string;
default?: any | [any, string];
choices?: string[];
optional?: boolean;
multiple?: boolean;
}子命令的参数,这个和下面的 options 有些不同,该处参数一般为必填,且不用带前缀说明。
例子如下。
...
arguments: {
name: { description: "请输入您的名称" }
}
...如下,只需要直接输入 xxx 即可。
$ cli say xxxoptions
optional
interface IOptions {
description: string;
default?: any | [any, string];
alias?: string;
choices?: string[];
optional?: boolean;
multiple?: boolean;
}子命令的参数,需要携带前缀说明。
如果同上面的 arguments 的例子一样,options 也想要一个 name 的参数,该如何写呢?
例子如下。
...
options: {
name: { description: "请输入您的名称" }
}
...如下,需要增加前缀 --name 才行。
$ cli say --name xxxcommands
optional
子命令的命令集,CliCommand 支持嵌套方式,且命令行的命中模式为优先匹配命令集,直接说有些难理解,请看如下的例子。
const child = new CliCommand({
command: "child",
description: "child",
action({ data, logger, helper }) {
logger.info(`child`);
},
});
const parent = new CliCommand({
command: "parent",
commands: [child],
description: "parent",
arguments: {
name: { description: "请输入您的名称" },
},
options: {},
action({ data, logger, helper }) {
logger.info(`hello ${data.name}`);
},
});如上,在 parent 接收一个 arguments 时,parent 还有一个 commands,那程序如果运行 cli parent child,程序将如何匹配?
答案是优先匹配子命令集,将 cli parent child 传入的 child 当做是子命令集的触发,也就是会输出 child。
所以,即使 parent 的参数中有 arguments,但如果传入的 arguments 和其子命令集的 command 重复,将会命中子命令集的任务。
Arguments
arguments 的对象描述如下
interface IArguments {
description: string;
default?: any | [any, string];
choices?: string[];
optional?: boolean;
multiple?: boolean;
}- default 表示默认值,当没有传入值时,框架会传入默认值。
- choices 表示可以输入的值,交互式的呈现是
listorcheckbox(若开启multiple) 选择,命令式的呈现是对输入进行验证。 - optional 表示该参数是否可选,默认参数都为必选。若配置为
true,则交互式会跳过生成该条交互命令。 - multiple 与
choices配合使用,表示多选,输入的值会以数组的形式传入。
Options
interface IOptions {
description: string;
default?: any | [any, string];
alias?: string;
choices?: string[];
optional?: boolean;
multiple?: boolean;
}- alias 表示短缀,如
--build设置alias为b,则可使用-b调用。 - default 表示默认值,当没有传入值时,框架会传入默认值。
- choices 表示可以输入的值,交互式的呈现是
listorcheckbox(若开启 multiple) 选择,命令式的呈现是对输入进行验证。 - optional 表示该参数是否可选,默认参数都为必选。若配置为
true,则交互式会跳过生成该条交互命令。 - multiple 与
choices配合使用,表示多选,输入的值会以数组的形式传入。
Logger
如下为日志的严重程度,error 为 0,是最大 P0 级错误日志。
enum levels {
error = 0,
warn = 1,
info = 2,
http = 3,
verbose = 4,
debug = 5,
silly = 6,
}CliCommand 的 action 中接收一个 logger 方法,该方法是包装的 winston,该日志工具会以天为维度,记录 warn 和 error 等级的内容到 ~/logs/oishi/${cli} 中,文件最大为 20mb,会以滑动窗口的方式滚动记录最近 14 天的日志。
...
action({ data, logger, helper }) {
logger.warn(`hello ${data.name}`);
}
...Helper
框架提供了几个常用的工具。
runPrompt
创建交互式命令行。
const prompt = helper.runPrompt();
prompt.addInput({ name: "name", message: "请输入你的名字" });
prompt.execute((answers) => {
console.log(answers);
});runCron
创建定时任务。
helper.runCron({
cronTime: "* * * * * *",
onTick() {
console.log("hello wrold");
},
});runCmd
创建命令行运行工具。
const run = helper.runCmd();
run("echo hello world");runTask
创建任务链,方便管理任务顺序。
await helper
.runTask({ hasTip: true })
.add({
title: "切换 registry 至 npm 源",
async task() {
run("npm set registry=https://registry.npmjs.org/");
},
})
.add({
title: "执行项目构建和发布",
async task() {
run("npm run build");
run("npm publish");
},
})
.add({
title: "切换 registry 至国内镜像",
async task() {
run("npm set registry=https://registry.npmmirror.com/");
},
})
.run();待办
- choices 和 default 允许传入 name value 的方式
- 类型转换有问题,因为命令行解析的结果都是字符串,无法通过 ts 传入值来修改获取值
- 后续 logger 可能可以支持自定义 winston transports
- 添加更多的 inquirer 的输入类型支持
- 命令运行时互相调用
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago