@bunli/ core (中文(简体) )
Bun的最小,型式安全的CLI框架.
安装
bun add @bunli/core
快速启动
import { defineCommand, option } from "@bunli/core";
import { z } from "zod";
export default defineCommand({
name: "greet",
description: "A friendly greeting",
options: {
name: option(z.string().min(1), { description: "Name to greet", short: "n" }),
excited: option(z.coerce.boolean().default(false), {
description: "Add excitement",
short: "e",
argumentKind: "flag",
}),
},
handler: async ({ flags }) => {
const greeting = `Hello, ${flags.name}${flags.excited ? "!" : "."}`;
console.log(greeting);
},
});
特征
- 🚀 类型安全 - 有自动类型推论的全类型脚本支持
- ⚡ 快点 - 由Bun的本地速度供电
- 📦 零配置 - 工作在盒子外 合理默认
- 🎯 最小 API - 学一次,到处用
- 🔌 广泛 - 自定义功能插件系统
- 🧪 可测试 - 包括一等测试设施
核心概念
图标
以自动类型推论定义命令 :
import { defineCommand } from "@bunli/core";
export default defineCommand({
name: "build",
description: "Build the project",
handler: async () => {
console.log("Building...");
},
});
选项
使用 option 用于标准Schema验证的助手 :
import { defineCommand, option } from "@bunli/core";
import { z } from "zod";
export default defineCommand({
name: "deploy",
description: "Deploy the application",
options: {
env: option(z.enum(["dev", "staging", "prod"]), { description: "Target environment" }),
force: option(z.coerce.boolean().default(false), {
description: "Force deployment",
short: "f",
argumentKind: "flag",
}),
},
handler: async ({ flags }) => {
// TypeScript knows:
// flags.env is 'dev' | 'staging' | 'prod'
// flags.force is boolean
},
});
多国司令国
创建具有多个命令的复杂 CLI :
import { createCLI, defineCommand } from "@bunli/core";
const build = defineCommand({
name: "build",
description: "Build the project",
handler: async () => {},
});
const deploy = defineCommand({
name: "deploy",
description: "Deploy the project",
handler: async () => {},
});
const test = defineCommand({
name: "test",
description: "Run tests",
handler: async () => {},
});
const cli = await createCLI({
name: "my-tool",
version: "1.0.0",
description: "My awesome CLI tool",
});
cli.command(build);
cli.command(deploy);
cli.command(test);
await cli.run();
TUI 渲染器缓冲模式
使用时 command.render,通过 tui.renderer.bufferMode数字 :
import { defineConfig } from "@bunli/core";
export default defineConfig({
tui: {
renderer: {
bufferMode: "alternate", // or 'standard'
},
},
});
默认策略 :
'standard'默认- 设定
'alternate'明确用于全屏/屏蔽终端流量
API 参考
defineCommand(config)
创建完整类型推断的命令定义.
option(schema, config)
创建带有 schema 验证的打字选项.
对于布尔风格的旗帜,设置 argumentKind: 'flag'。 。 。 .
verbose: option(z.boolean().default(false), {
short: "v",
description: "Verbose output",
argumentKind: "flag",
});
旗帜解析合同 :
--verbose设置值为true--verbose=true财务报告和审定财务报表--verbose=false两者都有效--verbose build不消耗build;仍为位置
使用默认值计划,如果您希望旗子是可选的,并在处理器中强烈打入.
createCLI(config)
创建多命令 CLI 应用程序.
defineConfig(config)
定义您的 CLI 共享配置 .
插件系统
Bunli 提供了强大的插件系统,具有编译时间类型安全性:
基本插件
import type { BunliPlugin } from "@bunli/core/plugin";
interface MyPluginStore {
apiKey: string;
isAuthenticated: boolean;
}
const myPlugin: BunliPlugin<MyPluginStore> = {
name: "my-plugin",
version: "1.0.0",
// Define the plugin's store
store: {
apiKey: "",
isAuthenticated: false,
},
// Lifecycle hooks
setup(context) {
// One-time initialization
context.updateConfig({ description: "Enhanced by my plugin" });
},
configResolved(config) {
// Called after all configuration is resolved
},
beforeCommand(context) {
// Called before each command - context.store is type-safe!
const apiKey = process.env.API_KEY || "";
context.setStoreValue("apiKey", apiKey);
context.setStoreValue("isAuthenticated", apiKey.length > 0);
},
afterCommand(context) {
// Called after each command with results
if (context.error) {
console.error("Command failed:", context.error);
}
},
};
插件厂
使用 createPlugin 为了更好的人造工程学:
import { createPlugin } from "@bunli/core/plugin";
type AuthOptions = {
provider: "github" | "gitlab";
};
type User = {
name: string;
};
type AuthStore = {
token: string;
user: User | null;
};
async function loadToken() {
return "token";
}
async function fetchUser(_token: string): Promise<User> {
return { name: "octocat" };
}
export const authPlugin = createPlugin<AuthOptions, AuthStore>((options) => ({
name: `auth-${options.provider}`,
store: {
token: "",
user: null,
},
async beforeCommand(context) {
const token = await loadToken();
context.setStoreValue("token", token);
context.setStoreValue("user", await fetchUser(token));
},
}));
使用带有类型安全的插件
const cli = await createCLI({
name: "my-cli",
version: "1.0.0",
plugins: [authPlugin({ provider: "github" }), myPlugin],
});
// In your commands, the store is fully typed!
cli.command({
name: "deploy",
description: "Deploy the application",
handler: async ({ context }) => {
// TypeScript knows about all plugin stores!
if (!context || !context.getStoreValue("isAuthenticated")) {
throw new Error("Not authenticated");
}
console.log(`Deploying as ${context.getStoreValue("user")?.name}`);
},
});
插件开发工具
Bunli 为插件的开发和测试提供公用设施:
import {
createTestPlugin,
composePlugins,
testPluginHooks,
assertPluginBehavior,
} from "@bunli/core/plugin";
// Create a test plugin
const testPlugin = createTestPlugin(
{ count: 0, message: "" },
{
beforeCommand(context) {
const count = context.getStoreValue("count");
context.setStoreValue("count", count + 1);
console.log(`Count: ${context.getStoreValue("count")}`);
},
},
);
// Compose multiple plugins
const composedPlugin = composePlugins(
testPlugin,
createTestPlugin({ enabled: true }, { name: "metrics" }),
);
// Test plugin behavior
const results = await testPluginHooks(testPlugin, {
config: { name: "test-cli", version: "1.0.0" },
store: { count: 0, message: "test" },
});
assertPluginBehavior(results, {
beforeCommandShouldSucceed: true,
});
模块增强
插件可以扩展 Bunli 的接口 :
declare module "@bunli/core/plugin" {
interface EnvironmentInfo {
isCI: boolean;
ciProvider?: string;
}
}
生成的帮助
Bunli 自动为您的命令生成类型安全助手 。 这些是自动装入的 generated: true 在您的 CLI 配置中 :
const cli = await createCLI({
name: "my-cli",
version: "1.0.0",
generated: true, // Auto-load generated types
});
可用的助手
import {
listCommands,
getCommandApi,
getTypedFlags,
validateCommand,
findCommandByName,
findCommandsByDescription,
getCommandNames,
} from "./.bunli/commands.gen";
// List all available commands
const commands = listCommands();
// Result: ['build', 'dev', 'test', ...]
// Get command metadata
const buildMeta = getCommandApi("build");
console.log(buildMeta.description); // "Build the project"
console.log(buildMeta.options); // { outdir: {...}, watch: {...} }
// Get typed flags for a command
const flags = getTypedFlags("build");
// flags.outdir is typed as string | undefined
// flags.watch is typed as boolean | undefined
// Validate command arguments at runtime
const result = validateCommand("build", { outdir: "dist", watch: true });
if (result.success) {
console.log("Valid arguments:", result.data);
} else {
console.error("Validation errors:", result.errors);
}
// Find commands by name or description
const buildCmd = findCommandByName("build");
const devCommands = findCommandsByDescription("development");
const allNames = getCommandNames();
IDE 自动导入支持
配置 TypeScript 路径映射以更好地支持 IDE :
// tsconfig.json
{
"compilerOptions": {
"paths": {
"~commands/*": ["./.bunli/commands.gen.ts"]
}
}
}
然后使用自动进口:
// These will show up in IDE auto-complete
import { listCommands } from "~commands/helpers";
import { getCommandApi } from "~commands/api";
生成的帮助为您的 CLI 命令提供全类型安全及运行时间回溯 。 当你修改命令定义时它们会自动更新.
运行时间验证
Bunli 为动态类型检查提供运行时间验证工具:
import {
validateValue,
validateValues,
isValueOfType,
createValidator,
createBatchValidator,
} from "@bunli/core";
import { z } from "zod";
// Validate a single value
const result = await validateValue("hello", z.string().min(1), {
option: "message",
command: "greet",
});
// Validate multiple values
const validated = await validateValues(
{ name: "John", age: 25 },
{
name: z.string(),
age: z.number(),
},
"user",
);
// Check value types
const value: unknown = "hello";
if (isValueOfType(value, "string")) {
console.log("Value is a string");
}
// Create reusable validators
const nameValidator = createValidator(z.string().min(1));
const userValidator = createBatchValidator({
name: z.string(),
age: z.number(),
});
类型公用事业
Bunli 输出高级类型Script类型公用设备,用于复杂类型操作,在与生成类型合作时尤其有用 :
import type {
UnionToIntersection,
MergeAll,
Expand,
DeepPartial,
Constrain,
IsAny,
} from "@bunli/core";
关键公用事业
连接到接口 - 将联盟类型转换为相交类型:
type Example = UnionToIntersection<{ a: string } | { b: number }>;
// Result: { a: string } & { b: number }
合并全部 - 合并多个对象类型:
type Example = MergeAll<[{ a: string }, { b: number }, { c: boolean }]>;
// Result: { a: string; b: number; c: boolean }
扩展 - 扩展复杂类型,以更好地了解情报:
type Example = Expand<{ nested: { deep: { value: string } } }>;
// Shows full type structure in IDE
深边 - 使所有属性循环:
type Example = DeepPartial<{ user: { name: string; age: number } }>;
// Result: { user?: { name?: string; age?: number } }
约束 - 有后退的束缚类型:
type Example = Constrain<string, "a" | "b" | "c", "a">;
// Result: 'a' | 'b' | 'c' (or 'a' if string doesn't match)
生成类型的使用
这些公用事业在生成的命令类型方面特别有效:
import { getCommandApi, listCommands } from "./commands.gen";
import { UnionToIntersection, MergeAll } from "@bunli/core";
// Get all command options as a union
type AllCommandOptions = UnionToIntersection<
ReturnType<typeof getCommandApi>[keyof CommandRegistry]["options"]
>;
// Merge all command metadata
type AllCommands = MergeAll<Array<{ name: string; description: string }>>;
当与生成的用于创建CLI包装器、文件生成器和指令分析工具的种类相结合时,这些公用事业特别强大.
相关软件包
- @bunli/生成器 - 从命令生成类型脚本定义
- @bunli/图利 - 共同利用公用设施促进国家综合发展
- @bunli/测试 - 测试CLI应用程序的公用事业
文档
许可证
麻省理工学院阿里亚实验室股份有限公司.