77 lines
2.6 KiB
JavaScript
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}`)
|
|
);
|
|
});
|
|
})();
|