Files
Autonomous-Bug-Explorer/dist/modules/findings/infrastructure/http/FindingsController.js

133 lines
5.5 KiB
JavaScript

"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.createFindingsRouter = createFindingsRouter;
const express_1 = require("express");
const MarkdownExporter_1 = require("../exporters/MarkdownExporter");
const JSONExporter_1 = require("../exporters/JSONExporter");
const PlaywrightScriptExporter_1 = require("../exporters/PlaywrightScriptExporter");
const path_1 = __importDefault(require("path"));
function createFindingsRouter(deps) {
const router = (0, express_1.Router)();
const markdownExporter = new MarkdownExporter_1.MarkdownExporter();
const jsonExporter = new JSONExporter_1.JSONExporter();
const playwrightExporter = new PlaywrightScriptExporter_1.PlaywrightScriptExporter();
// GET /api/findings — list findings with filters
router.get('/', async (req, res) => {
const { sessionId, severity, type, status, search } = req.query;
const result = await deps.listFindings.execute({ sessionId, severity, type, status, search });
if (!result.ok) {
res.status(500).json({ error: result.error });
return;
}
const { findings, total } = result.value;
res.json({
findings: findings.map(f => toDTO(f)),
total,
});
});
// GET /api/findings/stats — aggregate stats
router.get('/stats', async (req, res) => {
const { sessionId } = req.query;
const result = await deps.findingStats.execute({ sessionId });
if (!result.ok) {
res.status(500).json({ error: result.error });
return;
}
res.json(result.value);
});
// GET /api/findings/:id — finding detail (includes actionTrace)
router.get('/:id', async (req, res) => {
const findingId = req.params['id'];
const result = await deps.getFinding.execute({ findingId });
if (!result.ok) {
res.status(404).json({ error: result.error });
return;
}
const f = result.value;
res.json({ ...toDTO(f), actionTrace: f.actionTrace });
});
// PATCH /api/findings/:id/status — update status
router.patch('/:id/status', async (req, res) => {
const findingId = req.params['id'];
const { action } = req.body;
if (!action || !['resolve', 'close', 'investigate'].includes(action)) {
res.status(400).json({ error: 'action must be one of: resolve, close, investigate' });
return;
}
const result = await deps.resolveFinding.execute({ findingId, action });
if (!result.ok) {
res.status(404).json({ error: result.error });
return;
}
res.json(result.value);
});
// POST /api/findings/:id/enrich — trigger AI enrichment
router.post('/:id/enrich', async (req, res) => {
const findingId = req.params['id'];
const result = await deps.enrichFinding.execute({ findingId });
if (!result.ok) {
res.status(422).json({ error: result.error });
return;
}
res.json(result.value);
});
// GET /api/findings/:id/export/markdown — download as Markdown
router.get('/:id/export/markdown', async (req, res) => {
const findingId = req.params['id'];
const result = await deps.getFinding.execute({ findingId });
if (!result.ok) {
res.status(404).json({ error: result.error });
return;
}
const outputDir = path_1.default.join(process.cwd(), 'reports', findingId);
const filePath = await markdownExporter.export(result.value, outputDir);
res.download(filePath, `finding-${findingId}.md`);
});
// GET /api/findings/:id/export/json — download as JSON
router.get('/:id/export/json', async (req, res) => {
const findingId = req.params['id'];
const result = await deps.getFinding.execute({ findingId });
if (!result.ok) {
res.status(404).json({ error: result.error });
return;
}
const outputDir = path_1.default.join(process.cwd(), 'reports', findingId);
const filePath = await jsonExporter.export(result.value, outputDir);
res.download(filePath, `finding-${findingId}.json`);
});
// GET /api/findings/:id/export/playwright — download Playwright script
router.get('/:id/export/playwright', async (req, res) => {
const findingId = req.params['id'];
const result = await deps.getFinding.execute({ findingId });
if (!result.ok) {
res.status(404).json({ error: result.error });
return;
}
const script = playwrightExporter.generate(result.value);
res.setHeader('Content-Type', 'text/javascript');
res.setHeader('Content-Disposition', `attachment; filename="finding-${findingId}.spec.js"`);
res.send(script);
});
return router;
}
function toDTO(f) {
return {
id: f.id.toString(),
sessionId: f.sessionId,
type: f.type.value,
severity: f.severity.value,
description: f.description,
status: f.status.value,
browser: f.browser,
browserVersion: f.browserVersion,
actionTraceLength: f.actionTrace.length,
evidence: f.evidence.toJSON(),
aiEnrichment: f.aiEnrichment ?? null,
createdAt: f.createdAt.toISOString(),
resolvedAt: f.resolvedAt?.toISOString() ?? null,
};
}