feat: categories table, API, category field in articles

This commit is contained in:
Alexey Pavlov
2026-05-31 14:43:27 +03:00
parent b48c1854a2
commit e5e7e9ef98
4 changed files with 35 additions and 7 deletions
+2
View File
@@ -10,6 +10,7 @@ const articlesRoutes = require('./src/routes/articles');
const statsRoutes = require('./src/routes/stats'); const statsRoutes = require('./src/routes/stats');
const notesRoutes = require('./src/routes/notes'); const notesRoutes = require('./src/routes/notes');
const seriesRoutes = require('./src/routes/series'); const seriesRoutes = require('./src/routes/series');
const categoriesRoutes = require('./src/routes/categories');
// Start queue worker // Start queue worker
require('./src/workers/generation'); require('./src/workers/generation');
@@ -42,6 +43,7 @@ app.use('/api/articles', articlesRoutes);
app.use('/api/stats', statsRoutes); app.use('/api/stats', statsRoutes);
app.use('/api/notes', notesRoutes); app.use('/api/notes', notesRoutes);
app.use('/api/series', seriesRoutes); app.use('/api/series', seriesRoutes);
app.use('/api/categories', categoriesRoutes);
app.get('/health', (req, res) => { app.get('/health', (req, res) => {
res.json({ ok: true, service: 'zeropost-engine', time: new Date() }); res.json({ ok: true, service: 'zeropost-engine', time: new Date() });
+1 -1
View File
@@ -57,7 +57,7 @@ router.get('/admin', async (req, res) => {
const limit = Math.min(parseInt(req.query.limit) || 100, 200); const limit = Math.min(parseInt(req.query.limit) || 100, 200);
const offset = parseInt(req.query.offset) || 0; const offset = parseInt(req.query.offset) || 0;
const { rows } = await query( const { rows } = await query(
`SELECT id, slug, title, excerpt, cover_url, tags, author, reading_time, `SELECT id, slug, title, excerpt, cover_url, tags, category, author, reading_time,
status, seo_title, seo_descr, views, published_at, created_at, updated_at status, seo_title, seo_descr, views, published_at, created_at, updated_at
FROM articles ORDER BY created_at DESC LIMIT $1 OFFSET $2`, FROM articles ORDER BY created_at DESC LIMIT $1 OFFSET $2`,
[limit, offset] [limit, offset]
+28
View File
@@ -0,0 +1,28 @@
const express = require('express');
const router = express.Router();
const { query } = require('../config/db');
// GET /api/categories
router.get('/', async (_, res) => {
try {
const { rows } = await query('SELECT * FROM categories ORDER BY sort_order');
res.json(rows);
} catch (err) { res.status(500).json({ error: err.message }); }
});
// GET /api/categories/:slug/articles
router.get('/:slug/articles', async (req, res) => {
try {
const limit = Math.min(parseInt(req.query.limit) || 20, 100);
const offset = parseInt(req.query.offset) || 0;
const { rows } = await query(
`SELECT id,slug,title,excerpt,cover_url,tags,category,author,reading_time,published_at
FROM articles WHERE status='published' AND category=$1
ORDER BY published_at DESC LIMIT $2 OFFSET $3`,
[req.params.slug, limit, offset]
);
res.json(rows);
} catch (err) { res.status(500).json({ error: err.message }); }
});
module.exports = router;
+4 -6
View File
@@ -31,14 +31,12 @@ function estimateReadingTime(text) {
/** /**
* Список опубликованных статей. * Список опубликованных статей.
*/ */
async function listArticles({ limit = 20, offset = 0, tag = null } = {}) { async function listArticles({ limit = 20, offset = 0, tag = null, category = null } = {}) {
let sql = `SELECT id, slug, title, excerpt, cover_url, tags, author, reading_time, published_at let sql = `SELECT id, slug, title, excerpt, cover_url, tags, category, author, reading_time, published_at
FROM articles WHERE status='published'`; FROM articles WHERE status='published'`;
const params = []; const params = [];
if (tag) { if (tag) { sql += ` AND tags ?? ${params.length + 1}`; params.push(tag); }
sql += ` AND tags ?? $${params.length + 1}`; if (category) { sql += ` AND category=${params.length + 1}`; params.push(category); }
params.push(tag);
}
sql += ` ORDER BY published_at DESC LIMIT $${params.length + 1} OFFSET $${params.length + 2}`; sql += ` ORDER BY published_at DESC LIMIT $${params.length + 1} OFFSET $${params.length + 2}`;
params.push(limit, offset); params.push(limit, offset);
const { rows } = await query(sql, params); const { rows } = await query(sql, params);