diff --git a/backend/server/dist/index.js b/backend/server/dist/index.js index d35a61b..e13479f 100644 --- a/backend/server/dist/index.js +++ b/backend/server/dist/index.js @@ -13,6 +13,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) { }; Object.defineProperty(exports, "__esModule", { value: true }); const fs_1 = __importDefault(require("fs")); +const os_1 = __importDefault(require("os")); const path_1 = __importDefault(require("path")); const express_1 = __importDefault(require("express")); const dotenv_1 = __importDefault(require("dotenv")); @@ -20,7 +21,7 @@ const http_1 = require("http"); const socket_io_1 = require("socket.io"); const zod_1 = require("zod"); const utils_1 = require("./utils"); -const terminal_1 = require("./terminal"); +const node_pty_1 = require("node-pty"); dotenv_1.default.config(); const app = (0, express_1.default)(); const port = process.env.PORT || 4000; @@ -132,18 +133,37 @@ io.on("connection", (socket) => __awaiter(void 0, void 0, void 0, function* () { yield (0, utils_1.renameFile)(fileId, newFileId, file.data); })); socket.on("createTerminal", ({ id }) => { - console.log("creating terminal (" + id + ")"); - terminals[id] = new terminal_1.Pty(socket, id, `/projects/${data.id}`); + console.log("creating terminal, id=" + id); + const pty = (0, node_pty_1.spawn)(os_1.default.platform() === "win32" ? "cmd.exe" : "bash", [], { + name: "xterm", + cols: 100, + cwd: path_1.default.join(dirName, "projects", data.id), + }); + pty.onData((data) => { + console.log(data); + socket.emit("terminalResponse", { + // data: Buffer.from(data, "utf-8").toString("base64"), + data, + }); + }); + pty.onExit((code) => console.log("exit :(", code)); + terminals[id] = pty; }); - socket.on("terminalData", ({ id, data }) => { + socket.on("terminalData", (id, data) => { + // socket.on("terminalData", (data: string) => { console.log(`Received data for terminal ${id}: ${data}`); + // pty.write(data) if (!terminals[id]) { console.log("terminal not found"); console.log("terminals", terminals); return; } - console.log(`Writing to terminal ${id}`); - terminals[id].write(data); + try { + terminals[id].write(data); + } + catch (e) { + console.log("Error writing to terminal", e); + } }); socket.on("disconnect", () => { }); })); diff --git a/backend/server/dist/terminal.js b/backend/server/dist/terminal.js index 301f8f5..93f4e90 100644 --- a/backend/server/dist/terminal.js +++ b/backend/server/dist/terminal.js @@ -9,13 +9,11 @@ const os_1 = __importDefault(require("os")); class Pty { constructor(socket, id, cwd) { this.socket = socket; - this.shell = os_1.default.platform() === "win32" ? "cmd.exe" : "bash"; this.id = id; - this.ptyProcess = (0, node_pty_1.spawn)(this.shell, [], { + this.ptyProcess = (0, node_pty_1.spawn)(os_1.default.platform() === "win32" ? "cmd.exe" : "bash", [], { name: "xterm", cols: 100, cwd: cwd, - // env: process.env as { [key: string]: string }, }); this.ptyProcess.onData((data) => { console.log("onData", data); diff --git a/backend/server/src/index.ts b/backend/server/src/index.ts index 62097a5..37f4b09 100644 --- a/backend/server/src/index.ts +++ b/backend/server/src/index.ts @@ -1,4 +1,5 @@ import fs from "fs" +import os from "os" import path from "path" import express, { Express, NextFunction, Request, Response } from "express" import dotenv from "dotenv" @@ -9,6 +10,7 @@ import { z } from "zod" import { User } from "./types" import { createFile, getSandboxFiles, renameFile, saveFile } from "./utils" import { Pty } from "./terminal" +import { IPty, spawn } from "node-pty" dotenv.config() @@ -22,7 +24,7 @@ const io = new Server(httpServer, { }, }) -const terminals: { [id: string]: Pty } = {} +const terminals: { [id: string]: IPty } = {} const dirName = path.join(__dirname, "..") @@ -149,12 +151,30 @@ io.on("connection", async (socket) => { }) socket.on("createTerminal", ({ id }: { id: string }) => { - console.log("creating terminal (" + id + ")") - terminals[id] = new Pty(socket, id, `/projects/${data.id}`) + console.log("creating terminal, id=" + id) + const pty = spawn(os.platform() === "win32" ? "cmd.exe" : "bash", [], { + name: "xterm", + cols: 100, + cwd: path.join(dirName, "projects", data.id), + }) + + pty.onData((data) => { + console.log(data) + socket.emit("terminalResponse", { + // data: Buffer.from(data, "utf-8").toString("base64"), + data, + }) + }) + + pty.onExit((code) => console.log("exit :(", code)) + + terminals[id] = pty }) - socket.on("terminalData", ({ id, data }: { id: string; data: string }) => { + socket.on("terminalData", (id: string, data: string) => { + // socket.on("terminalData", (data: string) => { console.log(`Received data for terminal ${id}: ${data}`) + // pty.write(data) if (!terminals[id]) { console.log("terminal not found") @@ -162,8 +182,11 @@ io.on("connection", async (socket) => { return } - console.log(`Writing to terminal ${id}`) - terminals[id].write(data) + try { + terminals[id].write(data) + } catch (e) { + console.log("Error writing to terminal", e) + } }) socket.on("disconnect", () => {}) diff --git a/backend/server/src/terminal.ts b/backend/server/src/terminal.ts index b118850..8717e75 100644 --- a/backend/server/src/terminal.ts +++ b/backend/server/src/terminal.ts @@ -5,20 +5,21 @@ import os from "os" export class Pty { socket: Socket ptyProcess: IPty - shell: string id: string constructor(socket: Socket, id: string, cwd: string) { this.socket = socket - this.shell = os.platform() === "win32" ? "cmd.exe" : "bash" this.id = id - this.ptyProcess = spawn(this.shell, [], { - name: "xterm", - cols: 100, - cwd: cwd, - // env: process.env as { [key: string]: string }, - }) + this.ptyProcess = spawn( + os.platform() === "win32" ? "cmd.exe" : "bash", + [], + { + name: "xterm", + cols: 100, + cwd: cwd, + } + ) this.ptyProcess.onData((data) => { console.log("onData", data) diff --git a/frontend/components/editor/terminal.tsx b/frontend/components/editor/terminal.tsx index ced83c1..257a9a1 100644 --- a/frontend/components/editor/terminal.tsx +++ b/frontend/components/editor/terminal.tsx @@ -5,7 +5,6 @@ import { FitAddon } from "@xterm/addon-fit" import { useEffect, useRef, useState } from "react" import { Socket } from "socket.io-client" -import { decodeTerminalResponse } from "@/lib/utils" export default function EditorTerminal({ socket }: { socket: Socket }) { const terminalRef = useRef(null) @@ -36,9 +35,11 @@ export default function EditorTerminal({ socket }: { socket: Socket }) { }, 500) } - const onTerminalResponse = (data: Buffer) => { - console.log("received data", decodeTerminalResponse(data)) - term.write(decodeTerminalResponse(data)) + const onTerminalResponse = (response: { data: string }) => { + // const res = Buffer.from(response.data, "base64").toString("utf-8") + const res = response.data + console.log("terminal response", res) + term.write(res) } socket.on("connect", onConnect) @@ -54,15 +55,10 @@ export default function EditorTerminal({ socket }: { socket: Socket }) { } const disposable = term.onData((data) => { console.log("sending data", data) - socket.emit("terminalData", { - id: "testId", - data, - }) + socket.emit("terminalData", "testId", data) }) - socket.emit("terminalData", { - data: "\n", - }) + socket.emit("terminalData", "\n") return () => { socket.off("connect", onConnect) diff --git a/frontend/lib/utils.ts b/frontend/lib/utils.ts index f7a6a5e..6a4244b 100644 --- a/frontend/lib/utils.ts +++ b/frontend/lib/utils.ts @@ -16,10 +16,6 @@ export function processFileType(file: string) { return "plaintext" } -export function decodeTerminalResponse(buffer: Buffer): string { - return buffer.toString("utf-8") -} - export function validateName( newName: string, oldName: string,