/** * GET /api/v1/libs/search * * Search libraries by name. Compatible with context7's * GET /api/v2/libs/search interface. * * Query parameters: * libraryName (required) — library name to search for * query (optional) — user's question for relevance ranking * limit (optional) — max results, default 10, max 50 * type (optional) — "json" (default) or "txt" */ import { json } from '@sveltejs/kit'; import type { RequestHandler } from './$types'; import { getClient } from '$lib/server/db/client'; import { dtoJsonResponse } from '$lib/server/api/dto-response'; import { SearchService } from '$lib/server/search/search.service'; import { formatLibrarySearchJson } from '$lib/server/api/formatters'; import { CORS_HEADERS } from '$lib/server/api/formatters'; function getService(): SearchService { return new SearchService(getClient()); } export const GET: RequestHandler = ({ url }) => { const libraryName = url.searchParams.get('libraryName'); if (!libraryName || !libraryName.trim()) { return new Response( JSON.stringify({ error: 'libraryName is required', code: 'MISSING_PARAMETER' }), { status: 400, headers: { 'Content-Type': 'application/json', ...CORS_HEADERS } } ); } const query = url.searchParams.get('query') ?? undefined; const limitRaw = parseInt(url.searchParams.get('limit') ?? '10', 10); const limit = Math.min(isNaN(limitRaw) || limitRaw < 1 ? 10 : limitRaw, 50); try { const service = getService(); const results = service.searchRepositories({ libraryName, query, limit }); const body = formatLibrarySearchJson(results); return dtoJsonResponse(body, { headers: CORS_HEADERS }); } catch (err) { const message = err instanceof Error ? err.message : 'Internal server error'; return new Response(JSON.stringify({ error: message, code: 'INTERNAL_ERROR' }), { status: 500, headers: { 'Content-Type': 'application/json', ...CORS_HEADERS } }); } }; export const OPTIONS: RequestHandler = () => { return new Response(null, { status: 204, headers: CORS_HEADERS }); };