布罗克利
用 TypeScript 或 JavaScript 构建 CLI 的现代类型安全方式
以 滴水队
import { command, string, boolean, run } from "@drizzle-team/brocli";
const push = command({
name: "push",
options: {
dialect: string().enum("postgresql", "mysql", "sqlite"),
databaseSchema: string().required(),
databaseUrl: string().required(),
strict: boolean().default(false),
},
handler: (opts) => {
...
},
});
run([push]); // parse shell arguments and run command
为什么?
Brocli是用来解决我们在建设过程中遇到的挑战 滴入外科手术 生成和运行 SQL 计划迁移的 CLI 同伴 :
- 明确、直接和可发现的API
- 在验证中构建的已打入的选项( 参数)
- 跨命令重复使用选项(或选项集)的能力
- 变形器钩子将运行时配置消耗从命令业务逻辑中解开
--version, (中文(简体) ),-v作为字符串或回调- 在命令之前/ 之后运行常见内容的命令钩
- 明确的全球通路
- 可检验性,我们最重要的部分 移动不突破
- 主题, 简单的 API 到样式全局/ 命令帮助
- 消除道克漂移的 Docs 生成 API
通过实例学习
如果你需要 API 引用 - 看这里,此实例列表 意思是成为英雄的零 让你学会布洛克利
带有位置参数的简单回声命令 :
import { run, command, positional } from "@drizzle-team/brocli";
const echo = command({
name: "echo",
options: {
text: positional().desc("Text to echo").default("echo"),
},
handler: (opts) => {
console.log(opts.text);
},
});
run([echo])
~ bun run index.ts echo
echo
~ bun run index.ts echo text
text
打印版本为 --version -v数字 :
...
run([echo], {
version: "1.0.0",
);
~ bun run index.ts --version
1.0.0
版本接受 async 回调, 供您在必要时在打印 cli 版本前做任何 io :
import { run, command, positional } from "@drizzle-team/brocli";
const version = async () => {
// you can run async here, for example fetch version of runtime-dependend library
const envVersion = process.env.CLI_VERSION;
console.log(chalk.gray(envVersion), "\n");
};
const echo = command({ ... });
run([echo], {
version: version,
);
API 参考
command → namecommand → desccommand → shortDesccommand → aliasescommand → optionscommand → transformcommand → handlercommand → helpcommand → hiddencommand → metadata
布罗克利 command 声明有:
name - 命令名称,将列在 help
desc - 可选描述,将在命令中列出 help
shortDesc - 可选的简短描述,将在所有命令/所有子命令中列出 help
aliases - 命令名称别名
hidden - 隐藏命令的旗帜 help
help - 命令帮助文本或召回以动态配置打印帮助文本
options - 拟解析并提供给 transform 或者说 handler
transform - 可选钩子,在处理器前调用以修改 CLI 参数
handler - 使用任意一种类型调用 options 或者说 transform 参数, 运行命令业务逻辑的地方
metadata - 文件生成流程的可选元信息
name, (中文(简体) ), desc, (中文(简体) ), shortDesc 财务报告和审定财务报表 metadata 提供给文件生成步骤
import { command, string, boolean } from "@drizzle-team/brocli";
const push = command({
name: "push",
options: {
dialect: string().enum("postgresql", "mysql", "sqlite"),
databaseSchema: string().required(),
databaseUrl: string().required(),
strict: boolean().default(false),
},
transform: (opts) => {
},
handler: (opts) => {
...
},
});
import { command } from "@drizzle-team/brocli";
const cmd = command({
name: "cmd",
options: {
dialect: string().enum("postgresql", "mysql", "sqlite"),
schema: string().required(),
url: string().required(),
},
handler: (opts) => {
...
},
});
选项构建器
初始构建器功能 :
-
string(name?: string)- 将选项定义为字符串类型选项,该选项要求将数据传递为--option=value或者说--option valuename- cli 参数中通过选项的名称
如果没有指定,则默认为此选项的密钥
: 警告: - 不得包含=字符,不包含--help, (中文(简体) ),-h, (中文(简体) ),--version, (中文(简体) ),-v并每个命令独有
: speech balloon: - 将自动前缀-如果有一个角色长,--如果更长
如果您想要在多字符名上只设置单个连字符作为前缀 - 只需在其中指定名称 :string('-longname')
-
number(name?: string)- 将选项定义为数字类型选项,其中要求将数据传递为--option=value或者说--option valuename- cli 参数中通过选项的名称
如果没有指定,则默认为此选项的密钥
: 警告: - 不得包含=字符,不包含--help, (中文(简体) ),-h, (中文(简体) ),--version, (中文(简体) ),-v并每个命令独有
: speech balloon: - 将自动前缀-如果有一个角色长,--如果更长
如果您想要在多字符名上只设置单个连字符作为前缀 - 只需在其中指定名称 :number('-longname')
-
boolean(name?: string)- 将选项定义为布尔类型选项,它要求将数据传递为--optionname- cli 参数中通过选项的名称
如果没有指定,则默认为此选项的密钥
: 警告: - 不得包含=字符,不包含--help, (中文(简体) ),-h, (中文(简体) ),--version, (中文(简体) ),-v并每个命令独有
: speech balloon: - 将自动前缀-如果有一个角色长,--如果更长
如果您想要在多字符名上只设置单个连字符作为前缀 - 只需在其中指定名称 :boolean('-longname')
-
positional(displayName?: string)- 将选项定义为一个位置类型选项,它要求在命令后通过数据,作为command valuedisplayName- cli 参数中通过选项的名称
如果没有指定,则默认为此选项的密钥
: 警告: - 不消耗起始于
扩展名 :
-
.alias(...aliases: string[])- 定义选项的别名aliases- cli 参数中通过选项的别名
: 警告: - 不得包含=字符,不包含--help, (中文(简体) ),-h, (中文(简体) ),--version, (中文(简体) ),-v并每个命令独有
: speech balloon: - 将自动前缀-如果有一个角色长,--如果更长
如果您希望在多字符别名上只使用单个连字符作为前缀——只需在其中指定别名:.alias('-longname')
-
.desc(description: string)- 定义要显示在help命令 -
.required()- 根据需要设置选项, 这意味着如果 cli 参数中不存在错误, 应用程序将打印出错误 -
.default(value: string | boolean)- 设置选项的默认值, 如果在 cli 参数中不存在的话, 选项将被指定给它 -
.hidden()- 设置为隐藏的选项 - 选项将被省略help命令 -
.enum(values: [string, ...string[]])- 将字符串的值限制在此处指定之一values- 允许的enum值
-
.int()- 确保数字是一个整数 -
.min(value: number)- 指定数字允许的最小值value- 允许的最小值
: 警告: - 不限制默认值
-
.max(value: number)- 指定数字允许的最大值value- 允许的最大值
: 警告: - 不限制默认值
创建处理器
通常,你可以写 处理器右在 command() 函数,但可能存在一些情况,您需要单独定义您的处理器.
对于这种情况,你会想 推断类型 options 那将会是 传入你的操作器.
你可以使用它来做 TypeOf 类型 :
import { string, boolean, type TypeOf } from '@drizzle-team/brocli'
const commandOptions = {
opt1: string(),
opt2: boolean('flag').alias('f'),
// And so on...
}
export const commandHandler = (options: TypeOf<typeof commandOptions>) => {
// Your logic goes here...
}
或者通过使用 handler(options, myHandler () => {...})
import { string, boolean, handler } from '@drizzle-team/brocli'
const commandOptions = {
opt1: string(),
opt2: boolean('flag').alias('f'),
// And so on...
}
export const commandHandler = handler(commandOptions, (options) => {
// Your logic goes here...
});
定义命令
要定义命令, 使用 command() 函数 :
import { command, type Command, string, boolean, type TypeOf } from '@drizzle-team/brocli'
const commandOptions = {
opt1: string(),
opt2: boolean('flag').alias('f'),
// And so on...
}
const commands: Command[] = []
commands.push(command({
name: 'command',
aliases: ['c', 'cmd'],
desc: 'Description goes here',
shortDesc: 'Short description'
hidden: false,
options: commandOptions,
transform: (options) => {
// Preprocess options here...
return processedOptions
},
handler: (processedOptions) => {
// Your logic goes here...
},
help: () => 'This command works like this: ...',
subcommands: [
command(
// You can define subcommands like this
)
]
}));
参数:
-
name- 以 cli 参数搜索命令的名称
: 警告: - 决不能从-字符,等于[true, (中文(简体) ),false, (中文(简体) ),0, (中文(简体) ),1(对大小写不敏感),每个命令集独有 -
aliases- 以克力克搜索命令的别名
: 警告: - 决不能从-字符,等于[true, (中文(简体) ),false, (中文(简体) ),0, (中文(简体) ),1(对大小写不敏感),每个命令集独有 -
desc- 用于显示命令的说明help命令 -
shortDesc- 要显示的命令的简短描述help命令 -
hidden- 设置命令为隐藏 - 如果true中,命令将被省略help命令 -
options- 包含命令选项的对象string财务报告和审定财务报表boolean函数 -
transform- 预处理选项的可选功能,然后将其传递给处理器
: 警告: - 返回类型变异处理器输入类型 -
handler- 函数,在选项解析成功时执行
: 警告: - 如果您的命令没有子命令, 必须在场
如果命令有子命令但没有处理器, 此命令的帮助将被调用, 而不是处理器 -
help- 函数或字符串,当需要帮助时会执行或打印此命令
:警告: - 如果通过,将流行于主题commandHelp事件 -
subcommands- 命令的子命令
: 警告: - 命令不能有子命令和positional选项同时 -
metadata- 您想要附加到命令中供以后用于 docs 生成步骤的任何数据
运行命令
定义命令后,您需要执行 run 启动命令执行的函数
import { command, type Command, run, string, boolean, type TypeOf } from '@drizzle-team/brocli'
const commandOptions = {
opt1: string(),
opt2: boolean('flag').alias('f'),
// And so on...
}
const commandHandler = (options: TypeOf<typeof commandOptions>) => {
// Your logic goes here...
}
const commands: Command[] = []
commands.push(command({
name: 'command',
aliases: ['c', 'cmd'],
desc: 'Description goes here',
hidden: false,
options: commandOptions,
handler: commandHandler,
}));
// And so on...
run(commands, {
name: 'mysoft',
description: 'MySoft CLI',
omitKeysOfUndefinedOptions: true,
argSource: customEnvironmentArgvStorage,
version: '1.0.0',
help: () => {
console.log('Command list:');
commands.forEach(c => console.log('This command does ... and has options ...'));
},
theme: async (event) => {
if (event.type === 'commandHelp') {
await myCustomUniversalCommandHelp(event.command);
return true;
}
if (event.type === 'unknownError') {
console.log('Something went wrong...');
return true;
}
return false;
},
globals: {
flag: boolean('gflag').description('Global flag').default(false)
},
hook: (event, command, globals) => {
if(event === 'before') console.log(`Command '${command.name}' started with flag ${globals.flag}`)
if(event === 'after') console.log(`Command '${command.name}' succesfully finished it's work with flag ${globals.flag}`)
}
})
参数:
-
name- 名字用来引用你的cli申请.
用于打印使用示例的主题,例如:
app do-task --help结果Usage: app do-task <positional> [flags] ...
默认 :undefined -
description- 描述你的应用
用于主题,例如:
myapp --help结果
MyApp CLI
Usage: myapp [command]...
默认 : undefined
-
omitKeysOfUndefinedOptions- 确定是否将未定义的选项传递到转换和处理器的旗帜
默认 :false -
argSource- 环境中数组参数的位置
: 警告 : - 此存储的前两个项将被忽略, 因为它们通常包含可执行和执行的文件路径
默认 :process.argv -
version- 用于打印应用程序版本的字符串或处理器
: 警告 : - 如果通过, 将流行于主题的版本事件 -
help- 用于打印应用程序全局帮助的字符串或处理器
:警告: - 如果通过,将流行于主题globalHelp事件 -
theme(event: BroCliEvent)- 用于自定义各种事件所打印信件的函数
返回 :
true|Promise<true>如果您认为已处理的事件
false|Promise<false>重定向到默认主题 -
globals- 可在hook
: 警告: - 位置不允许进入globals
:警告: - 名称和别名不得与命令选项相重叠 -
hook(event: EventType, command: Command, options: TypeOf<typeof globals>)- 用于在每个命令前后执行代码的函数transform财务报告和审定财务报表handler执行
其他职能
-
commandsInfo(commands: Command[])- 简化命令集的表述
可用于生成文件 -
test(command: Command, args: string)- 用指定参数测试命令的行为
: 警告: - 如果命令已经transform但是,它会被调用handler不会 -
getCommandNameWithParents(command: Command)- 获得父命令名称的子命令名称
国 际
单位 BroCLI,命令不一定是第一个论据,相反,它可能以任何顺序通过.
为了让这个可能,蜂窝,在命令之前通过的选择应该有明确的价值,即使它是一面旗帜: --verbose true <command-name> (不适用于保留的旗帜:[ --help | -h | --version | -v)
选项在严格模式下解析,这意味着拥有任何未识别的选项会导致出错.