87 lines
2.4 KiB
TypeScript
87 lines
2.4 KiB
TypeScript
////
|
|
// The shell runs on the server and processes input, returning output.
|
|
|
|
import type { Message, CommandResult, CommandOutput } from "../shared/types.js"
|
|
import { addInput, setStatus, addOutput, appendOutput, replaceOutput } from "./scrollback.js"
|
|
import { send } from "./websocket.js"
|
|
import { randomId } from "../shared/utils.js"
|
|
import { addToHistory } from "./history.js"
|
|
import { browserCommands, cacheCommands } from "./commands.js"
|
|
|
|
export function runCommand(input: string) {
|
|
if (!input.trim()) return
|
|
|
|
const id = randomId()
|
|
|
|
addToHistory(input)
|
|
addInput(id, input)
|
|
|
|
const [cmd = "", ...args] = input.split(" ")
|
|
|
|
if (browserCommands[cmd]) {
|
|
const result = browserCommands[cmd]()
|
|
if (typeof result === "string")
|
|
addOutput(id, result)
|
|
setStatus(id, "ok")
|
|
} else {
|
|
send({ id, type: "input", data: input })
|
|
}
|
|
}
|
|
|
|
// message received from server
|
|
export function handleMessage(msg: Message) {
|
|
switch (msg.type) {
|
|
case "output":
|
|
handleOutput(msg); break
|
|
case "commands":
|
|
cacheCommands(msg.data as string[]); break
|
|
case "error":
|
|
console.error(msg.data); break
|
|
case "stream:start":
|
|
handleStreamStart(msg); break
|
|
case "stream:end":
|
|
handleStreamEnd(msg); break
|
|
case "stream:append":
|
|
handleStreamAppend(msg); break
|
|
case "stream:replace":
|
|
handleStreamReplace(msg); break
|
|
default:
|
|
console.error("unknown message type", msg)
|
|
}
|
|
}
|
|
|
|
function handleOutput(msg: Message) {
|
|
const result = msg.data as CommandResult
|
|
setStatus(msg.id!, result.status)
|
|
addOutput(msg.id!, result.output)
|
|
}
|
|
|
|
function handleStreamStart(msg: Message) {
|
|
const id = msg.id!
|
|
|
|
const status = document.querySelector(`[data-id="${id}"].input .status`)
|
|
if (!status) return
|
|
|
|
addOutput(id, msg.data as CommandOutput)
|
|
|
|
status.classList.remove("yellow")
|
|
status.classList.add("purple")
|
|
}
|
|
|
|
function handleStreamAppend(msg: Message) {
|
|
appendOutput(msg.id!, msg.data as CommandOutput)
|
|
}
|
|
|
|
function handleStreamReplace(msg: Message) {
|
|
replaceOutput(msg.id!, msg.data as CommandOutput)
|
|
}
|
|
|
|
function handleStreamEnd(msg: Message) {
|
|
const id = msg.id!
|
|
|
|
const status = document.querySelector(`[data-id="${id}"].input .status`)
|
|
if (!status) return
|
|
|
|
status.classList.remove("purple")
|
|
status.classList.remove("green")
|
|
} |