← 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 });
  }
}