feat: add SQL console endpoint for local MariaDB queries

This commit is contained in:
plenarius
2026-04-20 19:56:22 -04:00
parent 695c5d4fb7
commit e8cce96557
+70
View File
@@ -7,6 +7,7 @@ import {
generateServerConfig,
seedDatabase,
} from "../services/server.service.js";
import { getDockerClient } from "../services/docker.service.js";
const router = Router();
@@ -67,4 +68,73 @@ router.post("/seed-db", async (req, res) => {
}
});
router.post("/sql", async (req, res) => {
const { query, allowWrite } = req.body;
if (!query) return res.status(400).json({ error: "query required" });
const upperQuery = query.trim().toUpperCase();
if (
!allowWrite &&
(upperQuery.startsWith("DROP") ||
upperQuery.startsWith("TRUNCATE") ||
upperQuery.startsWith("ALTER"))
) {
return res
.status(400)
.json({ error: "Destructive query blocked. Set allowWrite: true to override." });
}
try {
const docker = getDockerClient();
const container = docker.getContainer("layonara-mariadb");
const exec = await container.exec({
Cmd: [
"mysql",
"-u",
"nwn",
`-p${process.env.MYSQL_PASSWORD || "forge"}`,
"nwn",
"-e",
query,
],
AttachStdout: true,
AttachStderr: true,
});
const stream = await exec.start({});
let output = "";
await new Promise<void>((resolve) => {
stream.on("data", (chunk: Buffer) => {
output += chunk.toString();
});
stream.on("end", resolve);
});
const lines = output
.trim()
.split("\n")
.filter((l) => l.trim());
if (lines.length === 0) {
res.json({ columns: [], rows: [] });
return;
}
const columns = lines[0].split("\t");
const rows = lines.slice(1).map((line) => {
const values = line.split("\t");
const row: Record<string, string> = {};
columns.forEach((col, i) => {
row[col] = values[i] || "";
});
return row;
});
res.json({ columns, rows });
} catch (err: any) {
res.status(500).json({ error: err.message });
}
});
export default router;