From d66b3f9f5f67ab61889caa075da9a9c04dcebae6 Mon Sep 17 00:00:00 2001 From: Chris Wanstrath Date: Sat, 20 Sep 2025 18:32:22 -0700 Subject: [PATCH] groovin --- src/js/shell.ts | 16 ++++++++++++++-- src/js/websocket.ts | 2 +- src/server.tsx | 15 +++++++++++---- src/shared/message.ts | 6 ------ src/shared/types.ts | 11 +++++++++++ src/shell.ts | 7 ++----- 6 files changed, 39 insertions(+), 18 deletions(-) delete mode 100644 src/shared/message.ts create mode 100644 src/shared/types.ts diff --git a/src/js/shell.ts b/src/js/shell.ts index 32cbf9a..0fcc951 100644 --- a/src/js/shell.ts +++ b/src/js/shell.ts @@ -4,6 +4,8 @@ import { addInput, setStatus, addOutput } from "./scrollback.js" import { send } from "./websocket.js" import { randomID } from "../shared/utils.js" +import type { Message, CommandResult } from "../shared/types.js" +import type { CompoundAssignmentOperator } from "typescript" export function runCommand(input: string) { const id = randomID() @@ -15,6 +17,16 @@ export function runCommand(input: string) { // message received from server export function handleMessage(e: MessageEvent) { const data = JSON.parse(e.data) - addOutput(data.id, data.data) - setStatus(data.id, "ok") + console.log("-> receive", data) + if (data.type === "output") { + handleOutput(data) + } else { + console.error("unknown message type", data) + } +} + +function handleOutput(msg: Message) { + const result = msg.data as CommandResult + setStatus(msg.id, result.status) + addOutput(msg.id, result.output) } diff --git a/src/js/websocket.ts b/src/js/websocket.ts index 369b2f3..5a1d520 100644 --- a/src/js/websocket.ts +++ b/src/js/websocket.ts @@ -1,7 +1,7 @@ //// // The terminal communicates with the shell via websockets. -import type { Message } from "../shared/message.js" +import type { Message } from "../shared/types.js" import { sessionID } from "./session.js" import { handleMessage } from "./shell.js" diff --git a/src/server.tsx b/src/server.tsx index dc871b1..9fada4c 100644 --- a/src/server.tsx +++ b/src/server.tsx @@ -7,7 +7,7 @@ import { NOSE_ICON, NOSE_DIR, NOSE_BIN, NOSE_WWW } from "./config" import { transpile, isFile, tilde } from "./utils" import { apps, serveApp, publishDNS } from "./webapp" import { runCommand } from "./shell" -import type { Message } from "./shared/message" +import type { Message } from "./shared/types" import { Layout } from "./components/layout" import { Terminal } from "./components/terminal" @@ -52,22 +52,28 @@ app.on("GET", ["/js/:path{.+}", "/shared/:path{.+}"], async c => { // websocket // +const connections: any[] = [] + app.get("/ws", upgradeWebSocket((c) => { return { + onOpen(_e, ws) { + connections.push(ws) + }, onMessage(event, ws) { - console.log(`Message from client: ${event.data}`) let data: Message | undefined try { data = JSON.parse(event.data.toString()) } catch (e) { console.error("JSON parsing error", e) + ws.send(JSON.stringify({ type: "error", data: "json parsing error" })) + return } if (!data) return - const result = runCommand(data.data) - ws.send(JSON.stringify({ id: data.id, data: result })) + const result = runCommand(data.data as string) + ws.send(JSON.stringify({ id: data.id, type: "output", data: result })) }, onClose: () => console.log('Connection closed'), } @@ -119,6 +125,7 @@ if (process.env.BUN_HOT) { // @ts-ignore globalThis.__hot_reload_cleanup = () => { + connections.forEach(conn => conn?.close()) } for (const sig of ["SIGINT", "SIGTERM"] as const) { diff --git a/src/shared/message.ts b/src/shared/message.ts deleted file mode 100644 index 6d47721..0000000 --- a/src/shared/message.ts +++ /dev/null @@ -1,6 +0,0 @@ -export type Message = { - session?: string - id: string - type: "input" | "output" - data: any -} diff --git a/src/shared/types.ts b/src/shared/types.ts new file mode 100644 index 0000000..3d83a3c --- /dev/null +++ b/src/shared/types.ts @@ -0,0 +1,11 @@ +export type Message = { + session?: string + id: string + type: "input" | "output" + data: string | CommandResult +} + +export type CommandResult = { + status: "ok" | "error" + output: string +} \ No newline at end of file diff --git a/src/shell.ts b/src/shell.ts index 6af23ab..5d2bc50 100644 --- a/src/shell.ts +++ b/src/shell.ts @@ -1,11 +1,8 @@ //// // runs commands and such. -type CommandResult = { - type: "ok" | "error" - data: any -} +import type { CommandResult } from "./shared/types" export function runCommand(input: string): CommandResult { - return { type: "ok", data: "command: " + input } + return { status: "ok", output: "command: " + input } } \ No newline at end of file