为 Hono 构建 CLI 适配器

发布: (2026年1月3日 GMT+8 09:24)
4 min read
原文: Dev.to

Source: Dev.to

Overview

hono-cli-adapter 让你可以直接从 CLI 调用 Hono 应用。
业务逻辑仍然保留在 Hono 中,这样你可以使用 Postman 或 Insomnia 进行调试,发布相同的代码作为 CLI,并且避免任何 stdout 写入——CLI 控制所有输出。
额外好处:通过切换入口点即可实现简易的 MCP 服务器支持。

调试 CLI 工具非常繁琐:运行、修改参数、再次运行——没有请求历史,也没有便捷的检查方式。
使用 hono-cli-adapter,你的 CLI 逻辑仍然位于 HTTP 端点后面,但实际上并不需要真实的 HTTP 服务器。该库会把 CLI 参数转换为 HTTP 请求并直接调用你的 Hono 应用的 app.fetch()

Why Hono?

  • Web‑tool friendly – 在构建时使用 Postman/Insomnia。保存请求、检查响应、快速迭代。
  • MCP ready – 切换入口点即可同时支持本地和远程 MCP 服务器。相同的业务逻辑,不同的传输方式。
  • Testable – 你的 Hono 应用是唯一的真相来源,能够独立进行测试。

Installation

npm install hono-cli-adapter

Basic Usage

创建一个 CLI 脚本(例如 my-cli.js):

#!/usr/bin/env node
import { cli } from 'hono-cli-adapter';
import { app } from './app.js';

await cli(app);

赋予可执行权限:

chmod +x my-cli.js

Running commands

# Call /hello/:name route
node my-cli.js hello Taro
# → "Hello, Taro!"

# List available routes
node my-cli.js --list

# Show help
node my-cli.js --help

CLI 参数会转化为 URL 路径和查询参数,然后调用 app.fetch()

Design Constraints

1. Thin CLI, fat Hono

所有业务逻辑都在 Hono 中;CLI 只负责标志和输出。这保证了 CLI 与 HTTP 之间的行为一致性,并且使 Hono 应用本身可以独立进行完整测试。

2. No side effects

库永远不会向 stdout 写入。你自行决定如何格式化输出:

const { code, lines } = await runCli(app, process);
for (const l of lines) console.log(l); // 或 JSON.stringify,管道到其他地方
process.exit(code);

3. POST‑only

CLI 命令触发动作,默认使用 POST。若有需要,后续可以添加 GET 支持。

Environment Variable Precedence

三层优先级,后者覆盖前者:

  1. process.env(基础)
  2. options.env(适配器配置)
  3. --env 标志(最高优先级)
await cli(app, process, { env: { API_URL: 'https://dev.example.com' } });

node my-cli.js do-thing --env API_KEY=secret-123

Passing JSON Body

-- 之后的 token 会被转为 JSON 请求体:

node my-cli.js create-user -- name=Taro email=taro@example.com
# Sends: { "name": "Taro", "email": "taro@example.com" }

Transforming Requests per Command

await adaptAndFetch(app, process.argv.slice(2), {
  beforeFetch: {
    upload: async (req, argv) => {
      if (argv.file) {
        const buf = await fs.readFile(argv.file);
        const headers = new Headers(req.headers);
        headers.set('content-type', 'application/octet-stream');
        return new Request(req, { body: buf, headers });
      }
    }
  }
});

Enriching --help with OpenAPI

await runCli(app, process, { openapi: myOpenApiSpec });

生成的帮助信息会显示参数类型、必选/可选标志以及描述。它与 hono-openapi 配合得很好。

Implementation Notes

  • listPostRoutes 检查 Hono 内部的路由结构。这在 Hono 重大更新时可能失效;在生产环境中,建议自行维护路由列表。
  • ESM only – 不支持 CommonJS。需要 Node 18+。

Conclusion

Hono + CLI 是一种值得更多关注的模式。你在开发期间可以使用 Web 工具,轻松获得 MCP 支持,并拥有可测试的核心——而且无需重复业务逻辑。

Check it out on GitHub:

Back to Blog

相关文章

阅读更多 »

V8 覆盖限制及其规避方法

V8 原生覆盖 – 对 React JSX 的盲点与解决方案 V8 原生覆盖功能强大:它可与任何打包工具配合使用,开销极小,并且能够收集……