feat: add real-time server log streaming via WebSocket

This commit is contained in:
plenarius
2026-04-20 19:55:58 -04:00
parent dc45098cd1
commit 695c5d4fb7
@@ -1,5 +1,6 @@
import fs from "fs/promises"; import fs from "fs/promises";
import path from "path"; import path from "path";
import chokidar from "chokidar";
import { getWorkspacePath } from "./workspace.service.js"; import { getWorkspacePath } from "./workspace.service.js";
import { getDockerClient } from "./docker.service.js"; import { getDockerClient } from "./docker.service.js";
import { broadcast } from "./ws.service.js"; import { broadcast } from "./ws.service.js";
@@ -210,3 +211,45 @@ export async function seedDatabase(cdKey: string, playerName: string): Promise<v
}); });
await dmExec.start({}); await dmExec.start({});
} }
let logWatcher: ReturnType<typeof chokidar.watch> | null = null;
export function startLogStreaming(): void {
const logPath = path.join(getWorkspacePath(), "logs/nwserverLog1.txt");
if (logWatcher) logWatcher.close();
logWatcher = chokidar.watch(logPath, {
persistent: true,
usePolling: true,
interval: 1000,
});
let lastSize = 0;
logWatcher.on("change", async () => {
try {
const stats = await fs.stat(logPath);
if (stats.size > lastSize) {
const fd = await fs.open(logPath, "r");
const buffer = Buffer.alloc(stats.size - lastSize);
await fd.read(buffer, 0, buffer.length, lastSize);
await fd.close();
lastSize = stats.size;
const newLines = buffer.toString("utf-8");
broadcast("log", "server", { text: newLines });
} else if (stats.size < lastSize) {
lastSize = 0;
}
} catch {
/* log file may not exist yet */
}
});
}
export function stopLogStreaming(): void {
if (logWatcher) {
logWatcher.close();
logWatcher = null;
}
}