"use strict"; var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { if (k2 === undefined) k2 = k; var desc = Object.getOwnPropertyDescriptor(m, k); if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { desc = { enumerable: true, get: function() { return m[k]; } }; } Object.defineProperty(o, k2, desc); }) : (function(o, m, k, k2) { if (k2 === undefined) k2 = k; o[k2] = m[k]; })); var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { Object.defineProperty(o, "default", { enumerable: true, value: v }); }) : function(o, v) { o["default"] = v; }); var __importStar = (this && this.__importStar) || (function () { var ownKeys = function(o) { ownKeys = Object.getOwnPropertyNames || function (o) { var ar = []; for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k; return ar; }; return ownKeys(o); }; return function (mod) { if (mod && mod.__esModule) return mod; var result = {}; if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]); __setModuleDefault(result, mod); return result; }; })(); Object.defineProperty(exports, "__esModule", { value: true }); exports.createReportingRouter = createReportingRouter; const express_1 = require("express"); const path = __importStar(require("path")); const fs = __importStar(require("fs")); const ReportWorker_1 = require("../../../../jobs/workers/ReportWorker"); function createReportingRouter(deps) { const router = (0, express_1.Router)(); // POST /api/reports — create and enqueue report router.post('/', async (req, res) => { const { title, format, filters } = req.body; if (!title || !format) { res.status(400).json({ error: 'title and format are required' }); return; } const result = await deps.generateReport.execute({ title, format: format, filters: filters ? { sessionId: filters.sessionId, startDate: filters.startDate ? new Date(filters.startDate) : undefined, endDate: filters.endDate ? new Date(filters.endDate) : undefined, severity: filters.severity, } : undefined, }); if (!result.ok) { res.status(400).json({ error: result.error }); return; } // Enqueue background job await deps.jobQueue.enqueue(ReportWorker_1.REPORT_JOB_TYPE, { reportId: result.value.reportId, format: format, filters: filters, }); res.status(201).json(result.value); }); // GET /api/reports — list all reports router.get('/', async (_req, res) => { const reports = await deps.reportRepository.findAll(); res.json(reports.map(r => ({ id: r.id.toString(), title: r.title, format: r.format.value, status: r.status.value, totalFindings: r.totalFindings, createdAt: r.createdAt.toISOString(), completedAt: r.completedAt?.toISOString() ?? null, }))); }); // GET /api/reports/:id — report detail router.get('/:id', async (req, res) => { const report = await deps.reportRepository.findById(req.params['id']); if (!report) { res.status(404).json({ error: 'Report not found' }); return; } res.json({ id: report.id.toString(), title: report.title, format: report.format.value, status: report.status.value, filters: report.filters, totalFindings: report.totalFindings, errorMessage: report.errorMessage, createdAt: report.createdAt.toISOString(), completedAt: report.completedAt?.toISOString() ?? null, }); }); // GET /api/reports/:id/download — download the generated file router.get('/:id/download', async (req, res) => { const report = await deps.reportRepository.findById(req.params['id']); if (!report) { res.status(404).json({ error: 'Report not found' }); return; } if (report.status.value !== 'ready' || !report.filePath) { res.status(409).json({ error: 'Report is not ready yet', status: report.status.value }); return; } if (!fs.existsSync(report.filePath)) { res.status(410).json({ error: 'Report file no longer exists' }); return; } const ext = path.extname(report.filePath); const contentTypes = { '.html': 'text/html', '.json': 'application/json', '.pdf': 'application/pdf', }; const contentType = contentTypes[ext] ?? 'application/octet-stream'; const filename = `report-${report.id.toString()}${ext}`; res.setHeader('Content-Type', contentType); res.setHeader('Content-Disposition', `attachment; filename="${filename}"`); fs.createReadStream(report.filePath).pipe(res); }); return router; }