API 接口
定义新路由
创建新 API 端点、校验与 OpenAPI 元数据的逐步指南。
本指南介绍如何在 MuseMVP 中添加新的 API 路由,遵循现有的校验、中间件与 OpenAPI 文档模式。
逐步流程
在 src/backend/database/ 中添加或更新数据库 schema 与 query 函数。
在 src/backend/api/routes/ 中创建新 Hono 路由或扩展现有路由。
在 src/backend/api/app.ts 中注册路由。
在 src/backend/api-client/ 中添加 API client hooks 供前端使用。
1. 定义路由处理器
创建新路由文件或扩展现有文件。使用 Zod 做校验,describeRoute 做 OpenAPI 元数据。
// src/backend/api/routes/example/router.ts
import { Hono } from "hono";
import { describeRoute, resolver, validator } from "hono-openapi";
import { z } from "zod";
import { authMiddleware } from "@/backend/api/middleware/auth";
const querySchema = z.object({
limit: z.string().optional().default("10").transform(Number),
offset: z.string().optional().default("0").transform(Number),
});
const responseSchema = z.object({
items: z.array(z.object({ id: z.string(), name: z.string() })),
total: z.number(),
});
export const exampleRouter = new Hono()
.basePath("/example")
.use(authMiddleware)
.get(
"/",
validator("query", querySchema),
describeRoute({
tags: ["Example"],
summary: "List items",
responses: {
200: {
description: "Items returned",
content: {
"application/json": {
schema: resolver(responseSchema),
},
},
},
},
}),
async (c) => {
const { limit, offset } = c.req.valid("query");
const user = c.get("user");
// 调用 query 层...
return c.json({ items: [], total: 0 });
},
);2. 注册路由
在 src/backend/api/app.ts 中添加新路由:
import { exampleRouter } from "./routes/example/router";
const appRouter = app
.route("/", authRouter)
.route("/", exampleRouter) // 添加此行
// ... 其他路由3. 校验模式
| 位置 | 用途 | 示例 |
|---|---|---|
validator("query", schema) | 查询参数 | 分页、搜索 |
validator("json", schema) | JSON 请求体 | 创建/更新 payload |
validator("form", schema) | 表单数据 | 联系表单、文件上传 |
validator("param", schema) | 路径参数 | /conversations/:id |
4. 中间件选项
| 中间件 | 使用场景 |
|---|---|
authMiddleware | 需要已登录用户;设置 c.get("user") 和 c.get("session") |
adminMiddleware | 需要 admin 角色;用于仅管理员端点 |
localeMiddleware | 从请求/cookie 设置 c.get("locale") 用于 i18n |
5. API Client Hook
创建调用新端点的 TanStack Query hook:
// src/backend/api-client/example/use-example.ts
import { useQuery } from "@tanstack/react-query";
import { apiClient } from "@/backend/api-client/api-client";
export function useExample(params?: { limit?: number; offset?: number }) {
return useQuery({
queryKey: ["example", params],
queryFn: async () => {
const res = await apiClient.example.$get({ query: params });
if (!res.ok) throw new Error("Fetch failed");
return res.json();
},
});
}参考实现
src/backend/api/routes/admin/users.ts
src/backend/api/routes/contact/router.ts
src/backend/api/routes/aichat/router.ts
- 管理路由:
admin/users.ts—adminMiddleware、query 校验、describeRoute - 公开路由:
contact/router.ts—localeMiddleware、表单校验 - 鉴权路由:
aichat/router.ts—authMiddleware、param + json 校验