Spaces:
Configuration error
Configuration error
| import { NextResponse } from 'next/server' | |
| import prisma from '@/lib/prisma' | |
| import { getAuthUser } from '@/lib/auth' | |
| import { createCollectionSchema, updateCollectionSchema, parseBody } from '@/lib/validations' | |
| import { checkRateLimit, getClientIdentifier, getRateLimitHeaders } from '@/lib/rate-limit' | |
| import type { Prisma } from '@prisma/client' | |
| export const dynamic = 'force-dynamic' | |
| // Get user's collections — with pagination | |
| export async function GET(req: Request) { | |
| try { | |
| const { searchParams } = new URL(req.url) | |
| const userId = searchParams.get('userId') | |
| const isPublic = searchParams.get('public') === 'true' | |
| const limit = Math.min(parseInt(searchParams.get('limit') || '20'), 100) | |
| const offset = Math.max(parseInt(searchParams.get('offset') || '0'), 0) | |
| if (!userId) { | |
| return NextResponse.json([], { status: 200 }) | |
| } | |
| const where: Prisma.CollectionWhereInput = { userId } | |
| if (isPublic) { | |
| where.isPublic = true | |
| } | |
| const [collections, total] = await Promise.all([ | |
| prisma.collection.findMany({ | |
| where, | |
| include: { | |
| prompts: { | |
| include: { | |
| prompt: { | |
| select: { | |
| id: true, | |
| slug: true, | |
| title: true, | |
| description: true, | |
| category: true, | |
| }, | |
| }, | |
| }, | |
| }, | |
| user: { | |
| select: { | |
| name: true, | |
| username: true, | |
| image: true, | |
| }, | |
| }, | |
| }, | |
| orderBy: { updatedAt: 'desc' }, | |
| take: limit, | |
| skip: offset, | |
| }), | |
| prisma.collection.count({ where }), | |
| ]) | |
| return NextResponse.json({ collections, total, hasMore: offset + collections.length < total }) | |
| } catch (error) { | |
| console.error('Get collections error:', error) | |
| return NextResponse.json( | |
| { error: 'Failed to fetch collections' }, | |
| { status: 500 } | |
| ) | |
| } | |
| } | |
| // Create new collection — requires auth | |
| export async function POST(req: Request) { | |
| try { | |
| const authUser = await getAuthUser() | |
| if (!authUser) { | |
| return NextResponse.json({ error: 'Authentication required' }, { status: 401 }) | |
| } | |
| // Rate limit | |
| const identifier = getClientIdentifier(req, authUser.id) | |
| const rateLimit = await checkRateLimit(`collections:${identifier}`, true) | |
| if (!rateLimit.success) { | |
| return NextResponse.json({ error: rateLimit.error }, { status: 429 }) | |
| } | |
| const body = await req.json() | |
| const parsed = parseBody(createCollectionSchema, body) | |
| if (!parsed.success) return parsed.response | |
| const { name, description, isPublic } = parsed.data | |
| const collection = await prisma.collection.create({ | |
| data: { | |
| name, | |
| description: description || null, | |
| userId: authUser.id, | |
| isPublic: isPublic || false, | |
| }, | |
| }) | |
| return NextResponse.json(collection) | |
| } catch (error) { | |
| console.error('Create collection error:', error) | |
| return NextResponse.json( | |
| { error: 'Failed to create collection' }, | |
| { status: 500 } | |
| ) | |
| } | |
| } | |
| // Update collection — requires auth + ownership | |
| export async function PATCH(req: Request) { | |
| try { | |
| const authUser = await getAuthUser() | |
| if (!authUser) { | |
| return NextResponse.json({ error: 'Authentication required' }, { status: 401 }) | |
| } | |
| const body = await req.json() | |
| const parsed = parseBody(updateCollectionSchema, body) | |
| if (!parsed.success) return parsed.response | |
| const { id, name, description, isPublic } = parsed.data | |
| // Verify ownership | |
| const existing = await prisma.collection.findUnique({ | |
| where: { id }, | |
| select: { userId: true }, | |
| }) | |
| if (!existing || existing.userId !== authUser.id) { | |
| return NextResponse.json({ error: 'Not found or not authorized' }, { status: 403 }) | |
| } | |
| const collection = await prisma.collection.update({ | |
| where: { id }, | |
| data: { | |
| ...(name && { name }), | |
| ...(description !== undefined && { description }), | |
| ...(isPublic !== undefined && { isPublic }), | |
| }, | |
| }) | |
| return NextResponse.json(collection) | |
| } catch (error) { | |
| console.error('Update collection error:', error) | |
| return NextResponse.json( | |
| { error: 'Failed to update collection' }, | |
| { status: 500 } | |
| ) | |
| } | |
| } | |
| // Delete collection — requires auth + ownership | |
| export async function DELETE(req: Request) { | |
| try { | |
| const authUser = await getAuthUser() | |
| if (!authUser) { | |
| return NextResponse.json({ error: 'Authentication required' }, { status: 401 }) | |
| } | |
| const { searchParams } = new URL(req.url) | |
| const id = searchParams.get('id') | |
| if (!id) { | |
| return NextResponse.json( | |
| { error: 'Collection ID is required' }, | |
| { status: 400 } | |
| ) | |
| } | |
| // Verify ownership | |
| const existing = await prisma.collection.findUnique({ | |
| where: { id }, | |
| select: { userId: true }, | |
| }) | |
| if (!existing || existing.userId !== authUser.id) { | |
| return NextResponse.json({ error: 'Not found or not authorized' }, { status: 403 }) | |
| } | |
| await prisma.collection.delete({ where: { id } }) | |
| return NextResponse.json({ success: true }) | |
| } catch (error) { | |
| console.error('Delete collection error:', error) | |
| return NextResponse.json( | |
| { error: 'Failed to delete collection' }, | |
| { status: 500 } | |
| ) | |
| } | |
| } | |