@bunli/core

中文文档
0.9.1发布于 2026/04/09MITTypeScriptES Module近 30 天下载 13万

Bun 最小、 类型安全的 CLI 框架

中文使用文档
文档目录27 节
  1. 安装
  2. 快速启动
  3. 特征
  4. 核心概念
  5. 图标
  6. 选项
  7. 多国司令国
  8. TUI 渲染器缓冲模式
  9. API 参考
  10. defineCommand(config)
  11. option(schema, config)
  12. createCLI(config)
  13. defineConfig(config)
  14. 插件系统
  15. 基本插件
  16. 插件厂
  17. 使用带有类型安全的插件
  18. 插件开发工具
  19. 模块增强
  20. 生成的帮助
  21. 运行时间验证
  22. 类型公用事业
  23. 关键公用事业
  24. 生成类型的使用
  25. 相关软件包
  26. 文档
  27. 许可证

@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/core 共发布 20 个版本,首次发布于 2025/06/18;过去 12 个月发布了 16 个版本。

版本发布日期距今
0.9.1latest2026/04/096 个月前
0.9.02026/03/287 个月前
0.8.22026/03/058 个月前
0.8.12026/03/058 个月前
0.8.02026/03/048 个月前
0.7.02026/03/018 个月前

关于 @bunli/core 的常见问题

@bunli/core 是什么?

Bun 最小、 类型安全的 CLI 框架

如何安装 @bunli/core?

在项目目录运行 npm install @bunli/core,或使用 pnpm add / yarn add / bun add。

@bunli/core 支持 TypeScript 吗?

支持。包内自带 TypeScript 类型声明(package.json 声明了 types 入口),安装后即可获得类型提示,无需再安装 @types 包。

@bunli/core 支持 ESM 还是 CommonJS?

以 ES Module 形式发布,推荐使用 import 引入。在 CommonJS 项目中,Node.js 20.19+ / 22.12+ 可以直接 require() 不含顶层 await 的 ES Module,更早的版本需要改用动态 import()。

@bunli/core 可以商用吗?

@bunli/core 使用 MIT 许可。宽松许可:允许商业使用、修改和再分发,通常只需在分发时保留原版权与许可声明。以上为概括,不构成法律意见,请以许可原文为准。

@bunli/core 的下载量有多少?

根据 npm 官方下载统计,@bunli/core 在 2026/10/09 – 2026/11/07 这 30 天内被下载 130,049 次,日均约 4,335 次。下载量会把 CI 构建、镜像同步和作为其他包依赖的安装一并计入,适合横向比较热度,不能直接等同于使用人数。

@bunli/core 还在维护吗?

最新版本 0.9.1 发布于 2026/04/09(6 个月前);至今共发布 20 个版本,其中过去 12 个月发布了 16 个;首次发布于 2025/06/18。发布频率只是参考信号:功能稳定的工具可能很少需要更新,建议结合源码仓库的 issue 和提交记录判断。