This commit is contained in:
Stefan ATZLESBERGER
2026-04-16 14:24:53 +02:00
parent f111274262
commit d1ca72450f
10 changed files with 1105 additions and 38 deletions
+108
View File
@@ -2,6 +2,13 @@ import { serve } from "bun";
import index from "./index.html";
import { getDb } from "./server/db";
import { createSnippet, deleteSnippet, getSnippetById, listSnippets, updateSnippet } from "./server/snippets";
import {
createTagTreeNode,
deleteTagTreeNode,
listTagTreeNodes,
suggestTagTreeItems,
updateTagTreeNode,
} from "./server/tagTree";
getDb();
@@ -45,6 +52,107 @@ const server = serve({
},
},
"/api/tag-suggestions": {
async GET(req) {
const url = new URL(req.url);
const q = url.searchParams.get("q") ?? "";
const database = getDb();
return Response.json({ items: suggestTagTreeItems(database, q) });
},
},
"/api/tag-tree": {
async GET() {
return Response.json(listTagTreeNodes());
},
async POST(req) {
const body = await readJson(req);
if (!body || typeof body !== "object") {
return Response.json({ error: "Invalid JSON body" }, { status: 400 });
}
const o = body as Record<string, unknown>;
try {
const node = createTagTreeNode({
name: typeof o.name === "string" ? o.name : "",
parent_id:
o.parent_id === null || o.parent_id === undefined
? null
: typeof o.parent_id === "number"
? o.parent_id
: Number(o.parent_id),
color: o.color === null || o.color === undefined ? null : String(o.color),
label_prefix:
o.label_prefix === null || o.label_prefix === undefined
? null
: typeof o.label_prefix === "string"
? o.label_prefix
: String(o.label_prefix),
});
return Response.json(node, { status: 201 });
} catch (e) {
const msg = e instanceof Error ? e.message : "Fehler";
return Response.json({ error: msg }, { status: 400 });
}
},
},
"/api/tag-tree/:id": {
async PATCH(req) {
const id = Number(req.params.id);
if (!Number.isFinite(id)) {
return Response.json({ error: "Invalid id" }, { status: 400 });
}
const body = await readJson(req);
if (!body || typeof body !== "object") {
return Response.json({ error: "Invalid JSON body" }, { status: 400 });
}
const o = body as Record<string, unknown>;
const patch: {
name?: string;
parent_id?: number | null;
color?: string | null;
label_prefix?: string | null;
} = {};
if ("name" in o && typeof o.name === "string") patch.name = o.name;
if ("parent_id" in o) {
patch.parent_id =
o.parent_id === null ? null : typeof o.parent_id === "number" ? o.parent_id : Number(o.parent_id);
}
if ("color" in o) {
patch.color = o.color === null || o.color === undefined ? null : String(o.color);
}
if ("label_prefix" in o) {
patch.label_prefix =
o.label_prefix === null || o.label_prefix === undefined
? null
: typeof o.label_prefix === "string"
? o.label_prefix
: String(o.label_prefix);
}
try {
const node = updateTagTreeNode(id, patch);
if (!node) {
return Response.json({ error: "Not found" }, { status: 404 });
}
return Response.json(node);
} catch (e) {
const msg = e instanceof Error ? e.message : "Fehler";
return Response.json({ error: msg }, { status: 400 });
}
},
async DELETE(req) {
const id = Number(req.params.id);
if (!Number.isFinite(id)) {
return Response.json({ error: "Invalid id" }, { status: 400 });
}
const ok = deleteTagTreeNode(id);
if (!ok) {
return Response.json({ error: "Not found" }, { status: 404 });
}
return new Response(null, { status: 204 });
},
},
"/api/snippets/:id": {
async GET(req) {
const id = Number(req.params.id);