← back to Norma
app/api/pulse/stats/route.ts
48 lines
/**
* GET /api/pulse/stats
* Returns aggregate stats for the Pulse feed from news_items.
*/
import { NextRequest, NextResponse } from 'next/server';
import { query } from '@/lib/db';
export async function GET(request: NextRequest) {
// Public endpoint — aggregate stats for the Pulse feed (no PII)
try {
const result = await query(`
SELECT
COUNT(*) AS total_articles,
COUNT(DISTINCT outlet) AS sources,
COUNT(DISTINCT ARRAY_TO_STRING(tags, ',')) AS unique_tags,
MIN(published_at) AS earliest,
MAX(published_at) AS latest,
COUNT(*) FILTER (WHERE published_at > NOW() - INTERVAL '24 hours') AS last_24h,
COUNT(*) FILTER (WHERE published_at > NOW() - INTERVAL '7 days') AS last_7d
FROM news_items
`);
const stats = result.rows[0];
// Category breakdown
const categories = await query(`
SELECT source_type AS category, COUNT(*) AS count
FROM news_items
GROUP BY source_type
ORDER BY count DESC
`);
return NextResponse.json({
total_articles: parseInt(stats.total_articles, 10),
sources: parseInt(stats.sources, 10),
last_24h: parseInt(stats.last_24h, 10),
last_7d: parseInt(stats.last_7d, 10),
earliest: stats.earliest,
latest: stats.latest,
categories: categories.rows,
});
} catch (err) {
console.error('[api/pulse/stats] error:', (err as Error).message);
return NextResponse.json({ error: 'Failed to fetch stats' }, { status: 500 });
}
}