tpmjs/apps/web/src/app/api/stats/route.ts
Ajax Davis 9abff1f203 feat: add reusable ToolHealthBadge and ToolHealthBanner components
- Create ToolHealthBadge component in @tpmjs/ui for broken tool indicator
- Create ToolHealthBanner component in @tpmjs/ui for detailed health warnings
- Integrate both components into playground ToolsSidebar:
  - Badge shows in tool cards in left sidebar
  - Banner shows in tool detail modal
- Update search-registry to include health fields in API responses
- Add package.json exports for new health components

These components provide consistent UI for displaying broken tool status
across the application (tool search, tool detail pages, playground).

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-12-04 19:12:07 +10:00

89 lines
2.2 KiB
TypeScript

import { prisma } from '@tpmjs/db';
import { NextResponse } from 'next/server';
export const runtime = 'nodejs';
export const dynamic = 'force-dynamic';
/**
* GET /api/stats
* Get aggregated statistics about tools in the registry
*
* Returns:
* - totalTools: Total number of tools
* - officialTools: Number of official tools (with tpmjs-tool keyword)
* - categories: Breakdown by category with counts
* - recentTools: Count of tools added in last 7 days
* - totalDownloads: Sum of all npm downloads
*/
export async function GET() {
try {
// Run all aggregations in parallel
const [totalTools, officialTools, recentCount, packages] = await Promise.all([
// Total tools count
prisma.tool.count(),
// Official tools count (isOfficial is at package level)
prisma.tool.count({
where: {
package: { isOfficial: true },
},
}),
// Recent tools (last 7 days)
prisma.tool.count({
where: {
createdAt: {
gte: new Date(Date.now() - 7 * 24 * 60 * 60 * 1000),
},
},
}),
// Get all packages with their tool counts and download stats
prisma.package.findMany({
select: {
category: true,
npmDownloadsLastMonth: true,
_count: {
select: { tools: true },
},
},
}),
]);
// Calculate stats from packages
const categories: Record<string, number> = {};
let totalDownloads = 0;
for (const pkg of packages) {
// Count tools by category
if (pkg.category) {
categories[pkg.category] = (categories[pkg.category] || 0) + pkg._count.tools;
}
// Sum downloads
totalDownloads += pkg.npmDownloadsLastMonth || 0;
}
return NextResponse.json({
success: true,
data: {
totalTools,
officialTools,
categories,
recentTools: recentCount,
totalDownloads,
},
});
} catch (error) {
console.error('Error fetching stats:', error);
return NextResponse.json(
{
success: false,
error: 'Failed to fetch stats',
message: error instanceof Error ? error.message : 'Unknown error',
},
{ status: 500 }
);
}
}