import express from "express"; import cors from "cors"; import { createServer } from "http"; import path from "path"; import { fileURLToPath } from "url"; import { WebSocketServer } from "ws"; import { initWebSocket, getClientCount } from "./services/ws.service.js"; import workspaceRouter from "./routes/workspace.js"; import dockerRouter from "./routes/docker.js"; import editorRouter from "./routes/editor.js"; import terminalRouter from "./routes/terminal.js"; import buildRouter from "./routes/build.js"; import serverRouter from "./routes/server.js"; import { attachWebSocket, createTerminalSession } from "./services/terminal.service.js"; import { attachLspWebSocket } from "./services/lsp.service.js"; const __dirname = path.dirname(fileURLToPath(import.meta.url)); const app = express(); const server = createServer(app); app.use(cors()); app.use(express.json()); initWebSocket(server); app.get("/api/health", (_req, res) => { res.json({ status: "ok", wsClients: getClientCount(), uptime: process.uptime(), }); }); app.use("/api/workspace", workspaceRouter); app.use("/api/docker", dockerRouter); app.use("/api/editor", editorRouter); app.use("/api/terminal", terminalRouter); app.use("/api/build", buildRouter); app.use("/api/server", serverRouter); const frontendDist = path.resolve(__dirname, "../../frontend/dist"); app.use(express.static(frontendDist)); app.get("*path", (_req, res) => { res.sendFile(path.join(frontendDist, "index.html")); }); server.on("upgrade", (request, socket, head) => { const url = new URL(request.url || "", `http://${request.headers.host}`); if (url.pathname === "/ws/lsp") { const lspWss = new WebSocketServer({ noServer: true }); lspWss.handleUpgrade(request, socket, head, (ws) => { attachLspWebSocket(ws); }); return; } const termMatch = url.pathname.match(/^\/ws\/terminal\/(.+)$/); if (termMatch) { const sessionId = termMatch[1]; const termWss = new WebSocketServer({ noServer: true }); termWss.handleUpgrade(request, socket, head, (ws) => { if (!attachWebSocket(sessionId, ws)) { createTerminalSession(sessionId); attachWebSocket(sessionId, ws); } }); } }); const PORT = parseInt(process.env.PORT || "3000", 10); server.listen(PORT, "0.0.0.0", () => { console.log(`Layonara Forge listening on http://0.0.0.0:${PORT}`); });