00 / 00

API 开发

Hono.js 路由、中间件和 OpenAPI 文档

架构概览

API 层由两部分组成:

  • Hono 应用:挂载到 TanStack Start 的 /api/$ server route 下,处理 Better Auth、webhook、Drop 静态页等需要原始 Request 的入口。
  • oRPC 路由:放在 products/01mvp/packages/api/src/routers,提供类型安全的前后端调用,同时可以生成 OpenAPI 文档。

核心文件:

  • Hono 入口:products/01mvp/apps/web/src/server/hono.ts
  • TanStack Start 挂载点:products/01mvp/apps/web/src/routes/api/$.ts
  • oRPC 路由目录:products/01mvp/packages/api/src/routers/
  • oRPC 客户端:products/01mvp/packages/api/src/client/tanstack-start/orpc.ts

路由组织

普通业务接口优先写成 oRPC router;只有以下场景才直接写 Hono route:

  • Better Auth 的 /api/auth/*
  • 支付 webhook 这类需要原始请求体和签名校验的入口
  • Drop 静态页、特殊代理或需要直接控制 Response 的接口

创建新的 oRPC 接口

创建 router 文件:在 products/01mvp/packages/api/src/routers/ 下按功能拆分

// products/01mvp/packages/api/src/routers/example/index.ts
import { z } from "zod";

import { publicProcedure } from "#@/lib/procedures/factory";

export const exampleRouter = {
  hello: publicProcedure
    .route({ method: "GET", description: "Say hello" })
    .input(z.object({ name: z.string().default("01MVP") }))
    .handler(({ input }) => ({
      message: `Hello ${input.name}`,
    })),
};

挂载到总 router

// products/01mvp/packages/api/src/routers/index.ts
export const appRouter = {
  example: exampleRouter,
  // ...
};

前端调用

import { useQuery } from "@tanstack/react-query";
import { orpc } from "@01mvp/api/client/tanstack-start/orpc";

const hello = useQuery(
  orpc.example.hello.queryOptions({ input: { name: "Jackie" } }),
);

Hono 特殊路由

如果确实需要直接写 Hono route,把它挂在 products/01mvp/apps/web/src/server/hono.ts 里:

// products/01mvp/apps/web/src/server/hono.ts
app.get("/status/custom", (c) => {
  return c.json({ ok: true });
});

访问路径是 http://localhost:7001/api/status/custom

请求参数验证

普通业务接口使用 oRPC + Zod 做输入校验。前端调用时会复用同一套路由类型,减少手写 fetch 和重复类型定义。

OpenAPI 文档

启用 ENABLE_OPEN_API_DOCS=true 后,开发时访问 http://localhost:7001/api/docs 可以查看 OpenAPI 文档。生产环境默认关闭,避免把接口面板暴露给普通用户。

这篇文档有问题?