← back to Norma

app/api/pulse/articles/route.ts

74 lines

/**
 * GET /api/pulse/articles
 * Returns news articles for the Pulse feed.
 * Reads directly from news_items table (no external agent needed).
 */

import { NextRequest, NextResponse } from 'next/server';
import { requireRole } from '@/lib/require-role';
import { query } from '@/lib/db';

export async function GET(request: NextRequest) {
  const auth = requireRole(request, 'admin', 'staff', 'pulse');
  if (auth instanceof NextResponse) return auth;

  try {
    const url = new URL(request.url);
    const limit = parseInt(url.searchParams.get('limit') || '50', 10);
    const category = url.searchParams.get('category');
    const offset = parseInt(url.searchParams.get('offset') || '0', 10);

    let whereClause = 'WHERE 1=1';
    const params: (string | number)[] = [];
    let paramIdx = 1;

    if (category && category !== 'all') {
      whereClause += ` AND source_type = $${paramIdx}`;
      params.push(category);
      paramIdx++;
    }

    params.push(limit, offset);

    const result = await query(
      `SELECT
        id,
        headline AS title,
        url,
        author_name AS author,
        summary,
        published_at,
        sentiment,
        COALESCE(sentiment_score, relevance_score) AS sentiment_score,
        petition_potential,
        petition_angle,
        tags AS topics,
        geo_state,
        outlet AS feed_name,
        COALESCE(source_type, 'news') AS feed_category,
        NULL AS feed_station
      FROM news_items
      ${whereClause}
      ORDER BY published_at DESC NULLS LAST
      LIMIT $${paramIdx} OFFSET $${paramIdx + 1}`,
      params
    );

    // Get total count
    const countResult = await query(
      `SELECT COUNT(*) AS total FROM news_items ${whereClause}`,
      params.slice(0, paramIdx - 1)
    );

    return NextResponse.json({
      articles: result.rows,
      total: parseInt(countResult.rows[0]?.total || '0', 10),
      limit,
      offset,
    });
  } catch (err) {
    console.error('[api/pulse/articles] error:', (err as Error).message);
    return NextResponse.json({ error: 'Failed to fetch articles' }, { status: 500 });
  }
}