const express = require("express"); const bodyParser = require("body-parser"); const cors = require("cors"); const path = require("path"); const { exec } = require("child_process"); const fs = require("fs-extra"); const { handleTerminal } = require("./terminalManager"); const { isValidDirectoryName, createUserDirectory, deleteUserDirectory, logMessage } = require("./utils"); const app = express(); // Middleware app.use(bodyParser.json()); app.use(cors({ origin: "*", // For production, replace with specific allowed origins methods: ["GET", "POST"], })); app.use(express.static(path.join(__dirname, "../frontend"))); const userDirectories = "./userDirectories"; // Ensure userDirectories exists if (!fs.existsSync(userDirectories)) { fs.mkdirSync(userDirectories); } const runningProcesses = new Map(); // Tracks running processes // Root Route app.get("/", (req, res) => { res.sendFile(path.join(__dirname, "../frontend/index.html")); }); // Start Directory and Terminal app.post("/start", async (req, res) => { const { directoryName, password, repoURL } = req.body; try { // Validate input if (!directoryName || !password || !repoURL) { return res.status(400).send("Invalid inputs"); } if (!isValidDirectoryName(directoryName)) { return res.status(400).send("Invalid directory name format"); } if (runningProcesses.has(directoryName)) { return res.status(400).send("A process is already running for this directory."); } const userDir = path.join(userDirectories, directoryName); // Create user directory try { createUserDirectory(userDirectories, directoryName, password); } catch (err) { logMessage(`Failed to create directory: ${err.message}`); return res.status(500).send("Failed to create user directory"); } // Clone GitHub repository exec(`git clone ${repoURL} ${userDir}`, (cloneError, stdout, stderr) => { if (cloneError) { logMessage(`Error cloning repo: ${cloneError.message}`); logMessage(`STDERR: ${stderr}`); return res.status(500).send(`Error cloning repository: ${stderr}`); } logMessage(`Repository cloned successfully for ${directoryName}`); // Install dependencies exec(`yarn install --cwd ${userDir}`, (installError, installStdout, installStderr) => { if (installError) { logMessage(`Error installing dependencies: ${installError.message}`); logMessage(`STDERR: ${installStderr}`); return res.status(500).send(`Error installing dependencies: ${installStderr}`); } // Start the terminal process handleTerminal(directoryName, userDir); // Track the running process runningProcesses.set(directoryName, true); logMessage(`Successfully initialized directory: ${directoryName}`); res.send("Directory and terminal started successfully"); }); }); } catch (error) { logMessage(`Error: ${error.message}`); res.status(500).send("Internal Server Error"); } }); // Delete Directory app.post("/delete", async (req, res) => { const { directoryName, password } = req.body; try { if (!directoryName || !password) { return res.status(400).send("Invalid inputs"); } if (runningProcesses.has(directoryName)) { handleTerminal(directoryName, null, true); // Stop terminal runningProcesses.delete(directoryName); } deleteUserDirectory(userDirectories, directoryName, password); logMessage(`Directory ${directoryName} deleted successfully`); res.send("Directory deleted successfully"); } catch (error) { logMessage(`Error deleting directory: ${error.message}`); res.status(500).send(error.message); } }); // Stop Terminal app.post("/stop", (req, res) => { const { directoryName } = req.body; if (!directoryName) { return res.status(400).send("Invalid directory name"); } if (!runningProcesses.has(directoryName)) { return res.status(400).send("No process is running for this directory."); } handleTerminal(directoryName, null, true); // Stop terminal runningProcesses.delete(directoryName); logMessage(`Terminal for ${directoryName} stopped`); res.send("Terminal stopped successfully"); }); // Server Listener app.listen(7860, () => console.log("Server is running on port 7860"));