81 lines
2.3 KiB
JavaScript
Executable File
81 lines
2.3 KiB
JavaScript
Executable File
// Coven Mirror frontend — vanilla JS, no build step needed.
|
|
// Talks to the REST + WebSocket API in pkg/web/server.go.
|
|
|
|
async function fetchJSON(url) {
|
|
const r = await fetch(url);
|
|
if (!r.ok) throw new Error(`${url}: ${r.status}`);
|
|
return r.json();
|
|
}
|
|
|
|
function renderGrid(elId, items, render) {
|
|
const el = document.getElementById(elId);
|
|
if (!items || items.length === 0) {
|
|
el.innerHTML = '<div class="card">No data</div>';
|
|
return;
|
|
}
|
|
el.innerHTML = items.map(render).join("");
|
|
}
|
|
|
|
async function loadGrimoire() {
|
|
try {
|
|
const data = await fetchJSON("/api/v1/spells");
|
|
renderGrid("spell-grid", data.spells || [], (s) =>
|
|
`<div class="card"><div class="label">Spell</div><div class="value">${s}</div></div>`
|
|
);
|
|
} catch (e) {
|
|
document.getElementById("spell-grid").innerHTML = `<div class="card">${e.message}</div>`;
|
|
}
|
|
}
|
|
|
|
async function loadNodes() {
|
|
try {
|
|
const nodes = await fetchJSON("/api/v1/cluster/nodes");
|
|
renderGrid("pulse-grid", nodes, (n) =>
|
|
`<div class="card">
|
|
<div class="label">${n.Role || "node"}</div>
|
|
<div class="value">${n.ID}</div>
|
|
<div class="label">Arch</div><div class="value">${n.Arch}</div>
|
|
</div>`
|
|
);
|
|
renderGrid("sanctum-map", nodes, (n) =>
|
|
`<div class="card" style="border-color:#10b981">
|
|
<div class="label">Sanctum</div>
|
|
<div class="value">${n.ID}</div>
|
|
<div class="hash">○ Warding strong</div>
|
|
</div>`
|
|
);
|
|
} catch (e) {
|
|
console.error(e);
|
|
}
|
|
}
|
|
|
|
function openLogStream(taskId) {
|
|
const ws = new WebSocket(`ws://${location.host}/api/v1/stream/${taskId}`);
|
|
ws.onmessage = (ev) => {
|
|
const bar = document.getElementById("progress");
|
|
bar.textContent = "⚡ " + ev.data;
|
|
};
|
|
}
|
|
|
|
document.getElementById("generate-sbom").addEventListener("click", async () => {
|
|
const out = document.getElementById("sbom-output");
|
|
out.textContent = "Forging SBOM...";
|
|
try {
|
|
const r = await fetch("/api/v1/spells");
|
|
const data = await r.json();
|
|
out.textContent = JSON.stringify(data, null, 2);
|
|
} catch (e) {
|
|
out.textContent = "Error: " + e.message;
|
|
}
|
|
});
|
|
|
|
// Initial load
|
|
loadGrimoire();
|
|
loadNodes();
|
|
|
|
// Heartbeat
|
|
setInterval(() => {
|
|
document.getElementById("status-text").textContent =
|
|
"Coven online · Ley-Lines stable · " + new Date().toLocaleTimeString();
|
|
}, 1000);
|