sorcery-go/pkg/web/static/app.js

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);