project-standalo-sonic-cloud/app/api/search/route.ts

77 lines
2.1 KiB
TypeScript

import { NextRequest, NextResponse } from 'next/server'
import { searchEntities } from '@/lib/search'
export async function GET(request: NextRequest) {
try {
const { searchParams } = new URL(request.url)
const query = searchParams.get('q')
const type = searchParams.get('type')
const limit = parseInt(searchParams.get('limit') || '20')
const offset = parseInt(searchParams.get('offset') || '0')
if (!query || query.trim().length === 0) {
return NextResponse.json(
{ error: 'Search query is required' },
{ status: 400 }
)
}
// Validate parameters
if (limit < 1 || limit > 100) {
return NextResponse.json(
{ error: 'Limit must be between 1 and 100' },
{ status: 400 }
)
}
if (offset < 0) {
return NextResponse.json(
{ error: 'Offset must be non-negative' },
{ status: 400 }
)
}
if (type && !['song', 'album', 'artist', 'playlist'].includes(type)) {
return NextResponse.json(
{ error: 'Invalid type. Must be one of: song, album, artist, playlist' },
{ status: 400 }
)
}
// Perform search using the search index
const { results, total } = await searchEntities(
query.trim(),
type || undefined,
limit,
offset
)
// Group results by entity type for easier frontend consumption
const groupedResults = {
songs: results.filter(r => r.entityType === 'song').map(r => r.entity),
albums: results.filter(r => r.entityType === 'album').map(r => r.entity),
artists: results.filter(r => r.entityType === 'artist').map(r => r.entity),
playlists: results.filter(r => r.entityType === 'playlist').map(r => r.entity),
}
return NextResponse.json(
{
query,
type,
results: groupedResults,
total,
limit,
offset,
hasMore: offset + limit < total,
},
{ status: 200 }
)
} catch (error) {
console.error('Search error:', error)
return NextResponse.json(
{ error: 'Failed to perform search' },
{ status: 500 }
)
}
}