finally working terminal

This commit is contained in:
Ishaan Dey 2024-04-29 02:19:27 -04:00
parent bce9d11b3b
commit 29cd17cd3d
6 changed files with 72 additions and 38 deletions

View File

@ -13,6 +13,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
}; };
Object.defineProperty(exports, "__esModule", { value: true }); Object.defineProperty(exports, "__esModule", { value: true });
const fs_1 = __importDefault(require("fs")); const fs_1 = __importDefault(require("fs"));
const os_1 = __importDefault(require("os"));
const path_1 = __importDefault(require("path")); const path_1 = __importDefault(require("path"));
const express_1 = __importDefault(require("express")); const express_1 = __importDefault(require("express"));
const dotenv_1 = __importDefault(require("dotenv")); const dotenv_1 = __importDefault(require("dotenv"));
@ -20,7 +21,7 @@ const http_1 = require("http");
const socket_io_1 = require("socket.io"); const socket_io_1 = require("socket.io");
const zod_1 = require("zod"); const zod_1 = require("zod");
const utils_1 = require("./utils"); const utils_1 = require("./utils");
const terminal_1 = require("./terminal"); const node_pty_1 = require("node-pty");
dotenv_1.default.config(); dotenv_1.default.config();
const app = (0, express_1.default)(); const app = (0, express_1.default)();
const port = process.env.PORT || 4000; 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); yield (0, utils_1.renameFile)(fileId, newFileId, file.data);
})); }));
socket.on("createTerminal", ({ id }) => { socket.on("createTerminal", ({ id }) => {
console.log("creating terminal (" + id + ")"); console.log("creating terminal, id=" + id);
terminals[id] = new terminal_1.Pty(socket, id, `/projects/${data.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}`); console.log(`Received data for terminal ${id}: ${data}`);
// pty.write(data)
if (!terminals[id]) { if (!terminals[id]) {
console.log("terminal not found"); console.log("terminal not found");
console.log("terminals", terminals); console.log("terminals", terminals);
return; return;
} }
console.log(`Writing to terminal ${id}`); try {
terminals[id].write(data); terminals[id].write(data);
}
catch (e) {
console.log("Error writing to terminal", e);
}
}); });
socket.on("disconnect", () => { }); socket.on("disconnect", () => { });
})); }));

View File

@ -9,13 +9,11 @@ const os_1 = __importDefault(require("os"));
class Pty { class Pty {
constructor(socket, id, cwd) { constructor(socket, id, cwd) {
this.socket = socket; this.socket = socket;
this.shell = os_1.default.platform() === "win32" ? "cmd.exe" : "bash";
this.id = id; 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", name: "xterm",
cols: 100, cols: 100,
cwd: cwd, cwd: cwd,
// env: process.env as { [key: string]: string },
}); });
this.ptyProcess.onData((data) => { this.ptyProcess.onData((data) => {
console.log("onData", data); console.log("onData", data);

View File

@ -1,4 +1,5 @@
import fs from "fs" import fs from "fs"
import os from "os"
import path from "path" import path from "path"
import express, { Express, NextFunction, Request, Response } from "express" import express, { Express, NextFunction, Request, Response } from "express"
import dotenv from "dotenv" import dotenv from "dotenv"
@ -9,6 +10,7 @@ import { z } from "zod"
import { User } from "./types" import { User } from "./types"
import { createFile, getSandboxFiles, renameFile, saveFile } from "./utils" import { createFile, getSandboxFiles, renameFile, saveFile } from "./utils"
import { Pty } from "./terminal" import { Pty } from "./terminal"
import { IPty, spawn } from "node-pty"
dotenv.config() 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, "..") const dirName = path.join(__dirname, "..")
@ -149,12 +151,30 @@ io.on("connection", async (socket) => {
}) })
socket.on("createTerminal", ({ id }: { id: string }) => { socket.on("createTerminal", ({ id }: { id: string }) => {
console.log("creating terminal (" + id + ")") console.log("creating terminal, id=" + id)
terminals[id] = new Pty(socket, id, `/projects/${data.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}`) console.log(`Received data for terminal ${id}: ${data}`)
// pty.write(data)
if (!terminals[id]) { if (!terminals[id]) {
console.log("terminal not found") console.log("terminal not found")
@ -162,8 +182,11 @@ io.on("connection", async (socket) => {
return return
} }
console.log(`Writing to terminal ${id}`) try {
terminals[id].write(data) terminals[id].write(data)
} catch (e) {
console.log("Error writing to terminal", e)
}
}) })
socket.on("disconnect", () => {}) socket.on("disconnect", () => {})

View File

@ -5,20 +5,21 @@ import os from "os"
export class Pty { export class Pty {
socket: Socket socket: Socket
ptyProcess: IPty ptyProcess: IPty
shell: string
id: string id: string
constructor(socket: Socket, id: string, cwd: string) { constructor(socket: Socket, id: string, cwd: string) {
this.socket = socket this.socket = socket
this.shell = os.platform() === "win32" ? "cmd.exe" : "bash"
this.id = id this.id = id
this.ptyProcess = spawn(this.shell, [], { this.ptyProcess = spawn(
name: "xterm", os.platform() === "win32" ? "cmd.exe" : "bash",
cols: 100, [],
cwd: cwd, {
// env: process.env as { [key: string]: string }, name: "xterm",
}) cols: 100,
cwd: cwd,
}
)
this.ptyProcess.onData((data) => { this.ptyProcess.onData((data) => {
console.log("onData", data) console.log("onData", data)

View File

@ -5,7 +5,6 @@ import { FitAddon } from "@xterm/addon-fit"
import { useEffect, useRef, useState } from "react" import { useEffect, useRef, useState } from "react"
import { Socket } from "socket.io-client" import { Socket } from "socket.io-client"
import { decodeTerminalResponse } from "@/lib/utils"
export default function EditorTerminal({ socket }: { socket: Socket }) { export default function EditorTerminal({ socket }: { socket: Socket }) {
const terminalRef = useRef(null) const terminalRef = useRef(null)
@ -36,9 +35,11 @@ export default function EditorTerminal({ socket }: { socket: Socket }) {
}, 500) }, 500)
} }
const onTerminalResponse = (data: Buffer) => { const onTerminalResponse = (response: { data: string }) => {
console.log("received data", decodeTerminalResponse(data)) // const res = Buffer.from(response.data, "base64").toString("utf-8")
term.write(decodeTerminalResponse(data)) const res = response.data
console.log("terminal response", res)
term.write(res)
} }
socket.on("connect", onConnect) socket.on("connect", onConnect)
@ -54,15 +55,10 @@ export default function EditorTerminal({ socket }: { socket: Socket }) {
} }
const disposable = term.onData((data) => { const disposable = term.onData((data) => {
console.log("sending data", data) console.log("sending data", data)
socket.emit("terminalData", { socket.emit("terminalData", "testId", data)
id: "testId",
data,
})
}) })
socket.emit("terminalData", { socket.emit("terminalData", "\n")
data: "\n",
})
return () => { return () => {
socket.off("connect", onConnect) socket.off("connect", onConnect)

View File

@ -16,10 +16,6 @@ export function processFileType(file: string) {
return "plaintext" return "plaintext"
} }
export function decodeTerminalResponse(buffer: Buffer): string {
return buffer.toString("utf-8")
}
export function validateName( export function validateName(
newName: string, newName: string,
oldName: string, oldName: string,