name: api-endpoint-creation description: Next.js 15+ 结合 Supabase 和工作区验证的 API 端点创建模式
API 端点创建技能
Next.js 15+ API 路由模式
使用时机:在 src/app/api/ 目录下创建新的 API 端点时
标准模式
import { NextRequest } from 'next/server';
import { getSupabaseServer } from '@/lib/supabase';
import { validateUserAndWorkspace } from '@/lib/api-helpers';
import { successResponse, errorResponse } from '@/lib/api-helpers';
import { withErrorBoundary } from '@/lib/error-boundary';
export const GET = withErrorBoundary(async (req: NextRequest) => {
// 1. 从查询参数中提取 workspace_id
const workspaceId = req.nextUrl.searchParams.get("workspaceId");
if (!workspaceId) {
return errorResponse("workspaceId 为必填项", 400);
}
// 2. 验证用户是否有权访问该工作区
await validateUserAndWorkspace(req, workspaceId);
// 3. 获取 Supabase 客户端(服务器端)
const supabase = getSupabaseServer();
// 4. 使用 workspace_id 过滤器进行查询(强制要求)
const { data, error } = await supabase
.from("your_table")
.select("*")
.eq("workspace_id", workspaceId);
if (error) {
return errorResponse(error.message, 500);
}
// 5. 返回成功响应
return successResponse(data);
});
POST 端点模式
export const POST = withErrorBoundary(async (req: NextRequest) => {
const workspaceId = req.nextUrl.searchParams.get("workspaceId");
if (!workspaceId) {
return errorResponse("workspaceId 为必填项", 400);
}
const user = await validateUserAndWorkspace(req, workspaceId);
const supabase = getSupabaseServer();
// 解析请求体
const body = await req.json();
const { name, data } = body;
// 验证
if (!name) {
return errorResponse("name 为必填项", 400);
}
// 插入数据并包含 workspace_id
const { data: result, error } = await supabase
.from("your_table")
.insert({
workspace_id: workspaceId,
name,
data,
created_by: user.id
})
.select()
.single();
if (error) {
return errorResponse(error.message, 500);
}
return successResponse(result, 201);
});
必需导入项
import { NextRequest } from 'next/server';
import { getSupabaseServer } from '@/lib/supabase';
import { validateUserAndWorkspace } from '@/lib/api-helpers';
import { successResponse, errorResponse } from '@/lib/api-helpers';
import { withErrorBoundary } from '@/lib/error-boundary';
检查清单
- [ ] 使用 withErrorBoundary 包装器
- [ ] 验证来自查询参数的 workspace_id
- [ ] 调用 validateUserAndWorkspace
- [ ] 使用 getSupabaseServer() 进行数据库访问
- [ ] 所有查询都必须通过 workspace_id 进行过滤
- [ ] 返回 successResponse 或 errorResponse
- [ ] 正确处理错误
- [ ] 添加 TypeScript 类型
标准:每个 API 路由都必须验证工作区并按 workspace_id 进行过滤