59 lines
2.0 KiB
TypeScript

import { Router, Request, Response } from "express";
import { pool } from "../db/client";
export const newsRouter = Router();
// GET /api/news?page=1&limit=10&category=&source=
newsRouter.get("/", async (req: Request, res: Response) => {
try {
const page = Math.max(1, parseInt(String(req.query.page || "1"), 10));
const limit = Math.min(50, Math.max(1, parseInt(String(req.query.limit || "10"), 10)));
const offset = (page - 1) * limit;
const category = req.query.category ? String(req.query.category) : null;
const source = req.query.source ? String(req.query.source) : null;
const conditions: string[] = [];
const values: unknown[] = [];
let idx = 1;
if (category) { conditions.push(`category = $${idx++}`); values.push(category); }
if (source) { conditions.push(`source ILIKE $${idx++}`); values.push(`%${source}%`); }
const where = conditions.length ? `WHERE ${conditions.join(" AND ")}` : "";
const countRes = await pool.query(
`SELECT COUNT(*) AS total FROM news_articles ${where}`,
values
);
const total = parseInt(countRes.rows[0].total, 10);
const rows = await pool.query(
`SELECT id, title, summary, source, source_url, published_at,
category, relevance_score, tags, content_hash
FROM news_articles
${where}
ORDER BY published_at DESC NULLS LAST
LIMIT $${idx} OFFSET $${idx + 1}`,
[...values, limit, offset]
);
// distinct categories for filter UI
const catRes = await pool.query(
"SELECT DISTINCT category FROM news_articles WHERE category IS NOT NULL ORDER BY category"
) as { rows: { category: string }[] };
res.json({
success: true,
articles: rows.rows,
total,
page,
limit,
pages: Math.ceil(total / limit),
categories: catRes.rows.map((r) => r.category),
});
} catch (err) {
console.error("News route error:", err);
res.status(500).json({ success: false, error: "Internal server error" });
}
});