API 开发

本文档将指导您如何在 Codofly Template 中创建 API 端点。

API Routes 基础

目录结构

app/api/
├── users/
│   ├── route.ts            # GET/POST /api/users
│   └── [id]/
│       └── route.ts        # GET/PUT/DELETE /api/users/[id]
├── chats/
│   └── route.ts            # GET/POST /api/chats
└── auth/
    └── login/
        └── route.ts        # POST /api/auth/login

创建 API 端点

基础示例

title="app/api/users/route.ts"
import { NextRequest, NextResponse } from 'next/server'
import { prisma } from '@/lib/prisma'

// GET /api/users
export async function GET() {
  const users = await prisma.user.findMany()
  return NextResponse.json({ data: users })
}

// POST /api/users
export async function POST(request: NextRequest) {
  const body = await request.json()
  const user = await prisma.user.create({ data: body })
  return NextResponse.json({ data: user }, { status: 201 })
}

动态路由

title="app/api/users/[id]/route.ts"
export async function GET(
  request: NextRequest,
  { params }: { params: { id: string } }
) {
  const user = await prisma.user.findUnique({
    where: { id: params.id }
  })
  
  if (!user) {
    return NextResponse.json({ error: '用户未找到' }, { status: 404 })
  }
  
  return NextResponse.json({ data: user })
}

export async function PUT(
  request: NextRequest,
  { params }: { params: { id: string } }
) {
  const body = await request.json()
  const user = await prisma.user.update({
    where: { id: params.id },
    data: body
  })
  return NextResponse.json({ data: user })
}

export async function DELETE(
  request: NextRequest,
  { params }: { params: { id: string } }
) {
  await prisma.user.delete({ where: { id: params.id } })
  return NextResponse.json({ success: true })
}

数据库操作

Prisma 基础用法

title="lib/db-operations.ts"
import { prisma } from '@/lib/prisma'

// 查询操作
export async function getUsers() {
  return await prisma.user.findMany({
    include: { chats: true }
  })
}

// 创建操作
export async function createUser(data: any) {
  return await prisma.user.create({
    data: {
      email: data.email,
      name: data.name
    }
  })
}

// 更新操作
export async function updateUser(id: string, data: any) {
  return await prisma.user.update({
    where: { id },
    data
  })
}

认证中间件

保护 API 路由

title="lib/auth-middleware.ts"
import { getServerSession } from 'next-auth'
import { authOptions } from '@/lib/auth'
import { NextRequest, NextResponse } from 'next/server'

export async function withAuth(handler: Function) {
  return async (request: NextRequest, context: any) => {
    const session = await getServerSession(authOptions)
    
    if (!session) {
      return NextResponse.json(
        { error: '未授权访问' },
        { status: 401 }
      )
    }

    return handler(request, context)
  }
}

使用认证中间件

title="app/api/protected/route.ts"
import { withAuth } from '@/lib/auth-middleware'

export const GET = withAuth(async (request: NextRequest) => {
  // 需要认证的 API 逻辑
  return NextResponse.json({ message: '受保护的内容' })
})

错误处理

统一错误响应

title="lib/api-response.ts"
import { NextResponse } from 'next/server'

export function successResponse(data: any, status = 200) {
  return NextResponse.json({
    success: true,
    data
  }, { status })
}

export function errorResponse(message: string, status = 500) {
  return NextResponse.json({
    success: false,
    error: message
  }, { status })
}

错误处理示例

title="app/api/users/route.ts"
import { successResponse, errorResponse } from '@/lib/api-response'

export async function GET() {
  try {
    const users = await prisma.user.findMany()
    return successResponse(users)
  } catch (error) {
    console.error('获取用户失败:', error)
    return errorResponse('服务器错误')
  }
}

export async function POST(request: NextRequest) {
  try {
    const body = await request.json()
    
    // 验证数据
    if (!body.email || !body.name) {
      return errorResponse('邮箱和姓名为必填项', 400)
    }

    const user = await prisma.user.create({ data: body })
    return successResponse(user, 201)
  } catch (error) {
    if (error.code === 'P2002') {
      return errorResponse('邮箱已存在', 409)
    }
    return errorResponse('创建用户失败')
  }
}

常见场景

聊天 API 示例

title="app/api/chats/route.ts"
export async function GET(request: NextRequest) {
  const session = await getServerSession(authOptions)
  
  const chats = await prisma.chat.findMany({
    where: { userId: session.user.id },
    include: { messages: true },
    orderBy: { updatedAt: 'desc' }
  })
  
  return successResponse(chats)
}

export async function POST(request: NextRequest) {
  const session = await getServerSession(authOptions)
  const { title } = await request.json()
  
  const chat = await prisma.chat.create({
    data: {
      title,
      userId: session.user.id
    }
  })
  
  return successResponse(chat, 201)
}

文件上传

title="app/api/upload/route.ts"
export async function POST(request: NextRequest) {
  const formData = await request.formData()
  const file = formData.get('file') as File
  
  if (!file) {
    return errorResponse('未找到文件', 400)
  }
  
  // 保存文件逻辑
  const buffer = Buffer.from(await file.arrayBuffer())
  const filename = `${Date.now()}-${file.name}`
  
  // 返回文件URL
  return successResponse({ 
    url: `/uploads/${filename}`,
    filename 
  })
}

最佳实践

  1. 使用 TypeScript 确保类型安全
  2. 统一响应格式 便于前端处理
  3. 添加错误处理 提供有意义的错误信息
  4. 验证输入数据 防止无效数据
  5. 使用中间件 处理认证和权限

查看 数据库功能 了解更多 Prisma 使用方法。