import { Router, Request, Response, NextFunction } from 'express'; import { pagesService } from './pages.service'; import { createLandingPageSchema, updateLandingPageSchema, listLandingPagesSchema } from './pages.schemas'; import { validate } from '../../middleware/validate'; import { authenticate } from '../../middleware/auth.middleware'; import { requireRole } from '../../middleware/rbac.middleware'; import { prisma } from '../../config/database'; import { CONTENT_ROLES } from '../../utils/roles'; const router = Router(); router.use(authenticate); router.use(requireRole(...CONTENT_ROLES)); // GET /api/pages/view-counts — landing page view counts (last 30d) router.get( '/view-counts', async (_req: Request, res: Response, next: NextFunction) => { try { const since = new Date(); since.setDate(since.getDate() - 30); const rows = await prisma.docsPageView.groupBy({ by: ['path'], where: { path: { startsWith: '/p/' }, createdAt: { gte: since }, }, _count: { id: true }, }); const counts: Record = {}; for (const row of rows) { // Extract slug from /p/:slug const slug = row.path.replace(/^\/p\//, ''); counts[slug] = row._count.id; } res.json(counts); } catch (err) { next(err); } } ); // POST /api/pages/sync — sync MkDocs overrides (must be before /:id routes) router.post( '/sync', async (_req: Request, res: Response, next: NextFunction) => { try { const result = await pagesService.syncOverrides(); res.json(result); } catch (err) { next(err); } } ); // POST /api/pages/validate — validate and repair MkDocs exports router.post( '/validate', async (_req: Request, res: Response, next: NextFunction) => { try { const result = await pagesService.validateExports(); res.json(result); } catch (err) { next(err); } } ); // GET /api/pages — list landing pages with pagination/filters router.get( '/', validate(listLandingPagesSchema, 'query'), async (req: Request, res: Response, next: NextFunction) => { try { const result = await pagesService.findAll(req.query as any); res.json(result); } catch (err) { next(err); } } ); // GET /api/pages/:id — get single landing page router.get( '/:id', async (req: Request, res: Response, next: NextFunction) => { try { const id = req.params.id as string; const page = await pagesService.findById(id); res.json(page); } catch (err) { next(err); } } ); // POST /api/pages — create landing page router.post( '/', validate(createLandingPageSchema), async (req: Request, res: Response, next: NextFunction) => { try { const page = await pagesService.create(req.body); res.status(201).json(page); } catch (err) { next(err); } } ); // PUT /api/pages/:id — update landing page router.put( '/:id', validate(updateLandingPageSchema), async (req: Request, res: Response, next: NextFunction) => { try { const id = req.params.id as string; const page = await pagesService.update(id, req.body); res.json(page); } catch (err) { next(err); } } ); // DELETE /api/pages/:id — delete landing page router.delete( '/:id', async (req: Request, res: Response, next: NextFunction) => { try { const id = req.params.id as string; await pagesService.delete(id); res.status(204).send(); } catch (err) { next(err); } } ); export { router as pagesAdminRouter };