关于 api-design
api-design 是面向开发者的 API 设计与实现技能,适用于 REST、GraphQL、tRPC 和 HTTP 端点。它提供从发现项目现有模式、验证请求到文档、类型同步及契约检查的工作流。
主要功能
- 01梳理现有路由与项目约定
- 02设计输入验证与错误响应
- 03实现 REST、GraphQL 或 tRPC 端点
- 04生成 OpenAPI 文档
- 05同步前后端类型
- 06检查 API 契约
适用场景
- 01创建 API 端点或路由
- 02为请求添加验证与中间件
- 03生成 API 文档
- 04从 REST 迁移到 tRPC 等范式
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ mgd34msu/ goodvibes-plugin --skill api-design安装后在 Claude Code 中输入/api-design确认已加载。
附带文件references/api-style-guide.mdscripts/api-checklist.sh
详细介绍
资源
scripts/
api-checklist.sh
references/
api-style-guide.md
API 设计
本技能将指导你使用 GoodVibes 精准度和项目引擎工具设计并实现 API 端点。在构建 REST API、GraphQL 解析器、tRPC 程序或任何 HTTP 端点时,使用此工作流。
何时使用此技能
在以下情况加载此技能:
- 构建新的 API 端点或路由
- 实现请求验证或中间件
- 设计错误响应格式
- 生成 API 文档
- 同步前端和后端之间的类型
- 在不同 API 范式之间迁移(REST 到 tRPC 等)
触发语句:“创建 API”“构建端点”“实现路由”“添加验证”“GraphQL 解析器”“tRPC 程序”。
核心工作流
阶段 1:发现
开始实现之前,先了解现有模式。
步骤 1.1:梳理现有路由
使用 get_api_routes 发现项目中的所有 API 端点。
mcp__plugin_goodvibes_project-engine__get_api_routes:
project_root: "." # or specific path
可了解的信息:
- 路由文件的位置和命名约定
- 使用中的 HTTP 方法(GET、POST、PUT、DELETE、PATCH)
- 路由结构(扁平或嵌套)
- 框架模式(Next.js App Router、Express、Fastify、tRPC)
步骤 1.2:发现模式
使用 discover 查找中间件、验证、错误处理和身份验证模式。
discover:
queries:
- id: middleware
type: grep
pattern: "(middleware|use\\()"
glob: "**/*.{ts,js}"
- id: validation
type: grep
pattern: "(z\\.|yup\\.|joi\\.|validator\\.)"
glob: "**/*.{ts,js}"
- id: error_handlers
type: grep
pattern: "(catch|try|Error|throw)"
glob: "src/api/**/*.{ts,js}"
- id: auth_patterns
type: grep
pattern: "(auth|jwt|session|bearer|getServerSession)"
glob: "**/*.{ts,js}"
verbosity: files_only
可了解的信息:
- 使用中的验证库(Zod、Yup、Joi)
- 错误处理模式
- 身份验证中间件
- 现有路由结构
步骤 1.3:阅读关键文件
阅读 2-3 个具有代表性的路由文件,了解实现模式。
precision_read:
files:
- path: "src/api/users/route.ts" # or discovered route
extract: content
- path: "src/lib/validation.ts" # or discovered validation file
extract: outline
verbosity: standard
阶段 2:决策
选择适合需求的 API 范式。完整的决策树请参阅 references/api-style-guide.md。
快速决策指南
参阅 references/api-style-guide.md,查看 REST、GraphQL、tRPC 和 Server Actions 之间的决策树。
阶段 3:实现
步骤 3.1:定义验证模式
使用项目的验证库创建请求验证。
Zod 示例:
import { z } from 'zod';
export const createUserSchema = z.object({
email: z.string().email(),
name: z.string().min(2).max(100),
role: z.enum(['user', 'admin']).default('user'),
});
export type CreateUserInput = z.infer<typeof createUserSchema>;
最佳实践:
- 验证所有输入(请求体、查询参数、标头)
- 使用严格的模式(不允许未知键)
- 提供清晰的错误消息
- 导出推断出的类型以供复用
步骤 3.2:实现路由处理程序
遵循项目约定编写路由处理程序。
Next.js App Router 示例:
import { NextRequest, NextResponse } from 'next/server';
import { createUserSchema } from './schema';
import { db } from '@/lib/db';
import { getServerSession } from '@/lib/auth';
export async function POST(request: NextRequest) {
// 1. Authentication
const session = await getServerSession();
if (!session) {
return NextResponse.json(
{ error: 'Unauthorized' },
{ status: 401 }
);
}
// 2. Parse and validate input
const body = await request.json();
const result = createUserSchema.safeParse(body);
if (!result.success) {
return NextResponse.json(
{ error: 'Validation failed', details: result.error.flatten() },
{ status: 400 }
);
}
// 3. Authorization check
if (session.user.role !== 'admin') {
return NextResponse.json(
{ error: 'Forbidden' },
{ status: 403 }
);
}
// 4. Business logic
try {
const user = await db.user.create({
data: result.data,
});
return NextResponse.json(user, { status: 201 });
} catch (error) {
console.error('Failed to create user:', error);
return NextResponse.json(
{ error: 'Internal server error' },
{ status: 500 }
);
}
}
tRPC 示例:
import { z } from 'zod';
import { protectedProcedure, router } from '../trpc';
export const userRouter = router({
create: protectedProcedure
.input(
z.object({
email: z.string().email(),
name: z.string().min(2).max(100),
})
)
.mutation(async ({ ctx, input }) => {
if (ctx.session.user.role !== 'admin') {
throw new TRPCError({ code: 'FORBIDDEN' });
}
return await ctx.db.user.create({
data: input,
});
}),
});
步骤 3.3:使用精准工具编写
使用 precision_write 创建路由文件、验证模式和类型。
precision_write:
files:
- path: "src/app/api/users/route.ts"
content: |
import { NextRequest, NextResponse } from 'next/server';
// ... [full handler implementation]
- path: "src/app/api/users/schema.ts"
content: |
import { z } from 'zod';
export const createUserSchema = z.object({ ... });
verbosity: count_only
阶段 4:错误处理
标准错误响应格式
确保所有端点的错误响应保持一致。
interface APIError {
error: string; // Human-readable message
code?: string; // Machine-readable error code
details?: unknown; // Validation errors or additional context
trace_id?: string; // For debugging in production
}
HTTP 状态码指南:
200- 成功201- 已创建(POST)204- 无内容(DELETE)400- 错误请求(验证错误)401- 未经授权(未通过身份验证)403- 禁止访问(未获授权)404- 未找到409- 冲突(资源重复)500- 内部服务器错误
错误处理模式
try {
// Business logic
} catch (error) {
// Log for debugging (never expose to client)
console.error('Operation failed:', error);
// User-facing error
return NextResponse.json(
{ error: 'Failed to process request' },
{ status: 500 }
);
}
切勿暴露:
- 生产环境中的堆栈跟踪
- 数据库错误消息
- 文件路径或内部结构
- 密钥或凭据
阶段 5:文档
步骤 5.1:生成 OpenAPI 规范
对于 REST API,自动生成 OpenAPI 文档。
mcp__plugin_goodvibes_project-engine__generate_openapi:
project_root: "."
output_path: "docs/openapi.yaml"
生成的内容:
- 路由路径和 HTTP 方法
- 请求/响应模式
- 身份验证要求
- 请求/响应示例
如果工具不存在或运行失败,请手动记录端点:
# In a routes.md file
POST /api/users
Description: Create a new user
Auth: Required (admin)
Body: { email: string, name: string, role?: 'user' | 'admin' }
Response 201: User object
Response 400: Validation error
Response 401: Unauthorized
Response 403: Forbidden
步骤 5.2:添加 JSDoc 注释
使用 JSDoc 记录路由处理程序。
/**
* Create a new user.
*
* @requires Authentication (admin role)
* @body {CreateUserInput} User data
* @returns {User} Created user object
* @throws {401} Unauthorized - Not authenticated
* @throws {403} Forbidden - Not an admin
* @throws {400} Bad Request - Validation failed
*/
export async function POST(request: NextRequest) {
// ...
}
阶段 6:类型安全
步骤 6.1:同步前端/后端类型
使用 sync_api_types 检查类型是否一致。
mcp__plugin_goodvibes_project-engine__sync_api_types:
backend_dir: "src/app/api"
frontend_dir: "src/lib/api-client"
检查内容:
- 前端和后端的请求类型是否一致
- 响应类型是否一致
- 是否存在不匹配的字段名或类型
- 所有端点是否都有对应的客户端代码
步骤 6.2:导出 API 类型
公开类型,供客户端使用。
// src/types/api.ts
export type { CreateUserInput, User } from '@/app/api/users/schema';
对于 tRPC,类型会自动推断:
// Client code
import { trpc } from '@/lib/trpc';
const user = await trpc.user.create.mutate({
email: '[email protected]',
name: 'Test User',
}); // Fully typed!
阶段 7:验证
第 7.1 步:验证 API 契约
使用 validate_api_contract 验证响应是否符合规范。
mcp__plugin_goodvibes_analysis-engine__validate_api_contract:
spec_path: "docs/openapi.yaml"
implementation_dir: "src/app/api"
验证内容:
- 响应架构是否符合 OpenAPI 规范
- 状态码是否正确
- 是否包含必需字段
- 类型是否准确
如果该工具不存在,请手动测试:
# Use curl or httpie to test endpoints
curl -X POST http://localhost:3000/api/users \
-H "Content-Type: application/json" \
-d '{"email":"[email protected]","name":"Test"}'
第 7.2 步:运行类型检查
验证 TypeScript 是否编译通过。
precision_exec:
commands:
- cmd: "npm run typecheck"
expect:
exit_code: 0
stderr_empty: true
verbosity: minimal
第 7.3 步:运行 API 检查清单脚本
使用验证脚本确保质量。
bash scripts/api-checklist.sh .
完整的验证套件请参阅 scripts/api-checklist.sh。
中间件模式
参照 references/api-style-guide.md 中的模式,实现身份验证、CORS 和速率限制中间件。对于 CORS 来源等安全敏感配置,请始终使用环境变量。
测试
为 API 端点编写测试,并使用有意义的断言覆盖成功场景、验证错误和身份验证失败。测试模式请参阅 references/api-style-guide.md。
常见反模式
不要:
- 不经验证就信任客户端输入
- 向客户端暴露数据库错误
- 将 GET 用于修改操作
- 为不同端点返回不同格式的响应
- 跳过身份验证检查
- 忽略授权(资源所有权)
- 在路由处理程序中使用
any类型 - 硬编码敏感值(API 密钥、机密)
- 出错时返回 200
应该:
- 使用严格的架构验证所有输入
- 使用一致的错误响应格式
- 遵循 HTTP 语义(GET = 读取,POST = 创建等)
- 实现恰当的身份验证和授权
- 对所有 API 代码使用 TypeScript
- 从环境变量中加载机密
- 返回恰当的状态码
- 记录错误以便调试(不要暴露错误)
快速参考
发现阶段:
get_api_routes: { project_root: "." }
discover: { queries: [middleware, validation, auth], verbosity: files_only }
precision_read: { files: [route examples], extract: content }
实现阶段:
precision_write: { files: [route, schema, types], verbosity: count_only }
验证阶段:
generate_openapi: { project_root: ".", output_path: "docs/openapi.yaml" }
validate_api_contract: { spec_path: "docs/openapi.yaml" }
sync_api_types: { backend_dir: "src/api", frontend_dir: "src/lib" }
precision_exec: { commands: [{ cmd: "npm run typecheck" }] }
实现后:
bash scripts/api-checklist.sh .
详细的决策树和特定框架的模式请参阅 references/api-style-guide.md。