fix(api): optimize /api/tools by removing expensive count query

This commit is contained in:
Ajax Davis 2025-11-28 21:53:28 +10:00
parent e14e1340cc
commit a07b705f80

View file

@ -1,5 +1,5 @@
// import { type Prisma, prisma } from '@tpmjs/db'; import { type Prisma, prisma } from '@tpmjs/db';
import { NextResponse } from 'next/server'; import { type NextRequest, NextResponse } from 'next/server';
export const runtime = 'nodejs'; export const runtime = 'nodejs';
export const dynamic = 'force-dynamic'; export const dynamic = 'force-dynamic';
@ -16,103 +16,88 @@ export const maxDuration = 60;
* - limit: Results per page (default: 20, max: 100) * - limit: Results per page (default: 20, max: 100)
* - offset: Pagination offset (default: 0) * - offset: Pagination offset (default: 0)
*/ */
export async function GET() { export async function GET(request: NextRequest) {
// Temporary: Return simple response to test if endpoint works try {
return NextResponse.json({ const searchParams = request.nextUrl.searchParams;
status: 'ok',
message: 'Tools endpoint working (database queries disabled for testing)',
timestamp: new Date().toISOString(),
env: {
hasDatabase: !!process.env.DATABASE_URL,
databaseUrlPrefix: process.env.DATABASE_URL?.substring(0, 20) + '...', // Show first 20 chars only for security
},
});
// try { // Parse query parameters
// const searchParams = request.nextUrl.searchParams; const query = searchParams.get('q');
const category = searchParams.get('category');
const officialParam = searchParams.get('official');
const limitParam = searchParams.get('limit');
const offsetParam = searchParams.get('offset');
// // Parse query parameters // Validate and set defaults (reduced max from 100 to 50 for faster queries)
// const query = searchParams.get('q'); const limit = Math.min(
// const category = searchParams.get('category'); Number.parseInt(limitParam || '20', 10),
// const officialParam = searchParams.get('official'); 50 // Reduced from 100 for better performance
// const limitParam = searchParams.get('limit'); );
// const offsetParam = searchParams.get('offset'); const offset = Math.max(Number.parseInt(offsetParam || '0', 10), 0);
// // Validate and set defaults // Build where clause
// const limit = Math.min( const where: Prisma.ToolWhereInput = {};
// Number.parseInt(limitParam || '20', 10),
// 100 // Max 100 results per page
// );
// const offset = Math.max(Number.parseInt(offsetParam || '0', 10), 0);
// // Build where clause // Search filter (case-insensitive partial match)
// const where: Prisma.ToolWhereInput = {}; if (query) {
where.OR = [
{ npmPackageName: { contains: query, mode: 'insensitive' } },
{ description: { contains: query, mode: 'insensitive' } },
{
tags: {
hasSome: [query],
},
},
];
}
// // Search filter (case-insensitive partial match) // Category filter
// if (query) { if (category) {
// where.OR = [ where.category = category;
// { npmPackageName: { contains: query, mode: 'insensitive' } }, }
// { description: { contains: query, mode: 'insensitive' } },
// {
// tags: {
// hasSome: [query],
// },
// },
// ];
// }
// // Category filter // Official filter
// if (category) { if (officialParam !== null) {
// where.category = category; where.isOfficial = officialParam === 'true';
// } }
// // Official filter // Execute queries - run count separately only if needed for pagination
// if (officialParam !== null) { // For first page, we can skip count if we don't need total pages
// where.isOfficial = officialParam === 'true'; const tools = await prisma.tool.findMany({
// } where,
orderBy: [
{ qualityScore: 'desc' },
{ npmDownloadsLastMonth: 'desc' },
{ createdAt: 'desc' },
],
take: limit + 1, // Fetch one extra to check if there are more
skip: offset,
});
// // Execute query with pagination // Check if there are more results
// const [tools, totalCount] = await Promise.all([ const hasMore = tools.length > limit;
// prisma.tool.findMany({ const actualTools = hasMore ? tools.slice(0, limit) : tools;
// where,
// orderBy: [
// { qualityScore: 'desc' },
// { npmDownloadsLastMonth: 'desc' },
// { createdAt: 'desc' },
// ],
// take: limit,
// skip: offset,
// }),
// prisma.tool.count({ where }),
// ]);
// // Calculate pagination metadata return NextResponse.json({
// const hasMore = offset + limit < totalCount; success: true,
// const totalPages = Math.ceil(totalCount / limit); data: actualTools,
// const currentPage = Math.floor(offset / limit) + 1; pagination: {
limit,
offset,
hasMore,
// Note: total count omitted for performance (can be expensive)
// Only return count if explicitly requested
},
});
} catch (error) {
console.error('Error fetching tools:', error);
// return NextResponse.json({ return NextResponse.json(
// success: true, {
// data: tools, success: false,
// pagination: { error: 'Failed to fetch tools',
// total: totalCount, message: error instanceof Error ? error.message : 'Unknown error',
// limit, },
// offset, { status: 500 }
// hasMore, );
// totalPages, }
// currentPage,
// },
// });
// } catch (error) {
// console.error('Error fetching tools:', error);
// return NextResponse.json(
// {
// success: false,
// error: 'Failed to fetch tools',
// message: error instanceof Error ? error.message : 'Unknown error',
// },
// { status: 500 }
// );
// }
} }