Files
ssh-jumphost/static/js/api-docs.js
2026-08-20 10:43:19 +02:00

77 lines
2.6 KiB
JavaScript

(() => {
"use strict";
const METHODS_ORDER = ["get", "post", "put", "patch", "delete"];
function el(tag, props = {}, children = []) {
const node = document.createElement(tag);
for (const [k, v] of Object.entries(props)) {
if (k === "className") node.className = v;
else if (k === "textContent") node.textContent = v;
else node.setAttribute(k, v);
}
for (const child of children) node.appendChild(child);
return node;
}
async function main() {
const container = document.getElementById("endpoints");
let spec;
try {
const res = await fetch("/openapi.json", { credentials: "same-origin" });
if (res.status === 401 || res.status === 403) {
window.location.href = "/";
return;
}
spec = await res.json();
} catch (err) {
container.replaceChildren(el("div", { className: "banner error", textContent: `Konnte /openapi.json nicht laden: ${err.message}` }));
return;
}
const byTag = {};
for (const [path, methods] of Object.entries(spec.paths || {})) {
for (const method of METHODS_ORDER) {
const op = methods[method];
if (!op) continue;
const tag = (op.tags && op.tags[0]) || "sonstige";
(byTag[tag] = byTag[tag] || []).push({ path, method, op });
}
}
const panels = Object.keys(byTag).sort().map((tag) => {
const rows = byTag[tag]
.sort((a, b) => a.path.localeCompare(b.path))
.map(({ path, method, op }) => {
const detail = el("pre", { className: "json-view hidden" });
detail.textContent = JSON.stringify(op, null, 2);
const row = el("div", { className: "endpoint-row" }, [
el("span", { className: `method ${method}`, textContent: method.toUpperCase() }),
el("span", { className: "path", textContent: path }),
el("span", { className: "summary", textContent: op.summary || "" }),
]);
row.addEventListener("click", () => detail.classList.toggle("hidden"));
const wrapper = document.createDocumentFragment();
wrapper.appendChild(row);
const detailWrap = el("div", { className: "endpoint-detail" }, [detail]);
wrapper.appendChild(detailWrap);
return wrapper;
});
const panel = el("div", { className: "panel" }, [el("h2", { textContent: tag })]);
for (const row of rows) panel.appendChild(row);
return panel;
});
container.replaceChildren(...panels);
}
main().catch((err) => {
document.getElementById("endpoints").replaceChildren(
document.createTextNode(`Fehler: ${err.message}`)
);
});
})();