Files
trace/src/routes/public-failures.mjs
T

72 lines
2.2 KiB
JavaScript
Raw Normal View History

// The read-only, unauthenticated projection of published incidents —
// consumed by goonk's /failures page at build and runtime. Never touches
// an incident until it has been explicitly published (see
// routes/incidents.mjs's publish/unpublish action); an unpublished
// incident is invisible here regardless of how much of it is filled in.
import { publicIncident, publicDetail, publicMarkdown } from '../views.mjs';
const jsonHeaders = {
'content-type': 'application/json; charset=utf-8',
'access-control-allow-origin': '*',
'cache-control': 'public, max-age=60',
};
export function createPublicFailuresRoutes(db) {
async function handle(req, res, path) {
if (req.method !== 'GET') return false;
if (path === '/api/v1/public/failures') {
const rows = db
.prepare("SELECT * FROM incidents WHERE published_at<>'' ORDER BY detected_at DESC")
.all();
res.writeHead(200, jsonHeaders).end(
JSON.stringify({
schemaVersion: 1,
generatedAt: new Date().toISOString(),
failures: rows.map(publicIncident),
}),
);
return true;
}
const md = path.match(/^\/api\/v1\/public\/failures\/([^/]+)\.md$/);
if (md) {
const x = db
.prepare("SELECT * FROM incidents WHERE public_slug=? AND published_at<>''")
.get(decodeURIComponent(md[1]));
if (!x) {
res.writeHead(404).end('Not found');
return true;
}
res
.writeHead(200, { ...jsonHeaders, 'content-type': 'text/markdown; charset=utf-8' })
.end(publicMarkdown(x));
return true;
}
const detail = path.match(/^\/api\/v1\/public\/failures\/([^/]+)$/);
if (detail) {
const x = db
.prepare("SELECT * FROM incidents WHERE public_slug=? AND published_at<>''")
.get(decodeURIComponent(detail[1]));
if (!x) {
res
.writeHead(404, {
'content-type': 'application/json; charset=utf-8',
'access-control-allow-origin': '*',
})
.end('{"error":"not_found"}');
return true;
}
res
.writeHead(200, jsonHeaders)
.end(JSON.stringify({ schemaVersion: 1, failure: publicDetail(x) }));
return true;
}
return false;
}
return { handle };
}