narrow Message types
This commit is contained in:
parent
24a17f2b46
commit
2b66107866
|
|
@ -11,13 +11,15 @@ export async function dispatchMessage(ws: any, msg: Message) {
|
||||||
console.log("<- receive", msg)
|
console.log("<- receive", msg)
|
||||||
switch (msg.type) {
|
switch (msg.type) {
|
||||||
case "input":
|
case "input":
|
||||||
await inputMessage(ws, msg as InputMessage); break
|
await inputMessage(ws, msg); break
|
||||||
|
|
||||||
case "save-file":
|
case "save-file":
|
||||||
await saveFileMessage(ws, msg as SaveFileMessage); break
|
await saveFileMessage(ws, msg); break
|
||||||
|
|
||||||
case "ui:mode":
|
case "session:update":
|
||||||
setState("ui:mode", msg.data); break
|
for (const key of Object.keys(msg.data))
|
||||||
|
setState(key, msg.data[key]);
|
||||||
|
break
|
||||||
|
|
||||||
default:
|
default:
|
||||||
send(ws, { type: "error", data: `unknown message: ${msg.type}` })
|
send(ws, { type: "error", data: `unknown message: ${msg.type}` })
|
||||||
|
|
|
||||||
|
|
@ -58,7 +58,6 @@ function closeBrowser() {
|
||||||
iframe.style.pointerEvents = "none"
|
iframe.style.pointerEvents = "none"
|
||||||
iframe.tabIndex = -1
|
iframe.tabIndex = -1
|
||||||
iframe.classList.remove("fullscreen", "active")
|
iframe.classList.remove("fullscreen", "active")
|
||||||
iframe.style.border = "2px solid var(--c64-light-blue)"
|
|
||||||
scrollback.append(iframe)
|
scrollback.append(iframe)
|
||||||
|
|
||||||
controls.style.display = "none"
|
controls.style.display = "none"
|
||||||
|
|
|
||||||
|
|
@ -22,7 +22,7 @@ export const browserCommands: Record<string, (...args: string[]) => void | Promi
|
||||||
mode: (mode?: string) => {
|
mode: (mode?: string) => {
|
||||||
if (!mode) {
|
if (!mode) {
|
||||||
mode = document.body.dataset.mode === "tall" ? "cinema" : "tall"
|
mode = document.body.dataset.mode === "tall" ? "cinema" : "tall"
|
||||||
send({ type: "ui:mode", data: mode })
|
send({ type: "session:update", data: { "ui:mode": mode } })
|
||||||
}
|
}
|
||||||
|
|
||||||
content.style.display = ""
|
content.style.display = ""
|
||||||
|
|
|
||||||
|
|
@ -1,3 +1,4 @@
|
||||||
|
import type { SaveFileMessage } from "../shared/types"
|
||||||
import { scrollback } from "./dom"
|
import { scrollback } from "./dom"
|
||||||
import { send } from "./websocket"
|
import { send } from "./websocket"
|
||||||
import { focusInput } from "./focus"
|
import { focusInput } from "./focus"
|
||||||
|
|
@ -49,10 +50,10 @@ function keydownHandler(e: KeyboardEvent) {
|
||||||
} else if ((e.ctrlKey && e.key === "s") || (e.ctrlKey && e.key === "Enter")) {
|
} else if ((e.ctrlKey && e.key === "s") || (e.ctrlKey && e.key === "Enter")) {
|
||||||
e.preventDefault()
|
e.preventDefault()
|
||||||
send({
|
send({
|
||||||
id: editor.dataset.path,
|
id: editor.dataset.path || "/tmp.txt",
|
||||||
type: "save-file",
|
type: "save-file",
|
||||||
data: editor.value
|
data: editor.value
|
||||||
})
|
} as SaveFileMessage)
|
||||||
} else if (e.key === "{") {
|
} else if (e.key === "{") {
|
||||||
if (editor.selectionStart !== editor.selectionEnd) {
|
if (editor.selectionStart !== editor.selectionEnd) {
|
||||||
insertAroundSelection(editor, '{', '}')
|
insertAroundSelection(editor, '{', '}')
|
||||||
|
|
|
||||||
|
|
@ -133,6 +133,7 @@ function handleInputClick(e: MouseEvent) {
|
||||||
|
|
||||||
export function handleOutput(msg: Message) {
|
export function handleOutput(msg: Message) {
|
||||||
const result = msg.data as CommandResult
|
const result = msg.data as CommandResult
|
||||||
setStatus(msg.id!, result.status)
|
const id = "id" in msg ? msg.id || "" : ""
|
||||||
addOutput(msg.id!, result.output)
|
setStatus(id, result.status)
|
||||||
|
addOutput(id, result.output)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,7 @@
|
||||||
////
|
////
|
||||||
// The shell runs on the server and processes input, returning output.
|
// The shell runs on the server and processes input, returning output.
|
||||||
|
|
||||||
|
import type { InputMessage } from "../shared/types"
|
||||||
import { addInput, setStatus, addOutput } from "./scrollback"
|
import { addInput, setStatus, addOutput } from "./scrollback"
|
||||||
import { send } from "./websocket"
|
import { send } from "./websocket"
|
||||||
import { randomId } from "../shared/utils"
|
import { randomId } from "../shared/utils"
|
||||||
|
|
@ -27,7 +28,7 @@ export async function runCommand(input: string) {
|
||||||
if (result) addOutput(id, result)
|
if (result) addOutput(id, result)
|
||||||
setStatus(id, "ok")
|
setStatus(id, "ok")
|
||||||
} else {
|
} else {
|
||||||
send({ id, type: "input", data: input })
|
send({ id, type: "input", data: input } as InputMessage)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,25 +1,25 @@
|
||||||
import type { Message, CommandOutput } from "@/shared/types"
|
import type { StreamMessage } from "@/shared/types"
|
||||||
import { addOutput, appendOutput, replaceOutput } from "./scrollback"
|
import { addOutput, appendOutput, replaceOutput } from "./scrollback"
|
||||||
|
|
||||||
export function handleStreamStart(msg: Message) {
|
export function handleStreamStart(msg: StreamMessage) {
|
||||||
const id = msg.id!
|
const id = msg.id
|
||||||
|
|
||||||
const status = document.querySelector(`[data-id="${id}"].input .status`)
|
const status = document.querySelector(`[data-id="${id}"].input .status`)
|
||||||
if (!status) return
|
if (!status) return
|
||||||
|
|
||||||
addOutput(id, msg.data as CommandOutput)
|
addOutput(id, msg.data)
|
||||||
|
|
||||||
status.classList.remove("yellow")
|
status.classList.remove("yellow")
|
||||||
status.classList.add("purple")
|
status.classList.add("purple")
|
||||||
}
|
}
|
||||||
|
|
||||||
export function handleStreamAppend(msg: Message) {
|
export function handleStreamAppend(msg: StreamMessage) {
|
||||||
appendOutput(msg.id!, msg.data as CommandOutput)
|
appendOutput(msg.id, msg.data)
|
||||||
}
|
}
|
||||||
|
|
||||||
export function handleStreamReplace(msg: Message) {
|
export function handleStreamReplace(msg: StreamMessage) {
|
||||||
replaceOutput(msg.id!, msg.data as CommandOutput)
|
replaceOutput(msg.id, msg.data)
|
||||||
}
|
}
|
||||||
|
|
||||||
export function handleStreamEnd(_msg: Message) {
|
export function handleStreamEnd(_msg: StreamMessage) {
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -9,7 +9,7 @@ import { addErrorMessage } from "./scrollback"
|
||||||
const MAX_RETRIES = 5
|
const MAX_RETRIES = 5
|
||||||
let retries = 0
|
let retries = 0
|
||||||
let connected = false
|
let connected = false
|
||||||
let msgQueue: Message[] = []
|
let msgQueue: Omit<Message, "session">[] = []
|
||||||
|
|
||||||
let ws: WebSocket | null = null
|
let ws: WebSocket | null = null
|
||||||
|
|
||||||
|
|
@ -30,14 +30,15 @@ export function startConnection() {
|
||||||
}
|
}
|
||||||
|
|
||||||
// send any message
|
// send any message
|
||||||
export function send(msg: Message) {
|
export function send(msg: Omit<Message, "session">) {
|
||||||
if (!connected) {
|
if (!connected) {
|
||||||
msgQueue.push(msg)
|
msgQueue.push(msg)
|
||||||
startConnection()
|
startConnection()
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!msg.session) msg.session = sessionId
|
if (!(msg as any).session) (msg as any).session = sessionId
|
||||||
|
|
||||||
ws?.readyState === 1 && ws.send(JSON.stringify(msg))
|
ws?.readyState === 1 && ws.send(JSON.stringify(msg))
|
||||||
console.log("-> send", msg)
|
console.log("-> send", msg)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,19 +1,13 @@
|
||||||
export type Message = {
|
export type Message =
|
||||||
session?: string
|
| ErrorMessage
|
||||||
id?: string
|
|
||||||
type: MessageType
|
|
||||||
data?: CommandResult | CommandOutput
|
|
||||||
}
|
|
||||||
| InputMessage
|
| InputMessage
|
||||||
|
| OutputMessage
|
||||||
| SaveFileMessage
|
| SaveFileMessage
|
||||||
| SessionStartMessage
|
| SessionStartMessage
|
||||||
| SessionUpdateMessage
|
| SessionUpdateMessage
|
||||||
| GameStartMessage
|
| GameStartMessage
|
||||||
|
| StreamMessage
|
||||||
export type MessageType = "error" | "input" | "output" | "commands" | "save-file"
|
| CommandsMessage
|
||||||
| "game:start"
|
|
||||||
| "stream:start" | "stream:end" | "stream:append" | "stream:replace"
|
|
||||||
| "ui:mode"
|
|
||||||
|
|
||||||
export type CommandOutput = string | string[]
|
export type CommandOutput = string | string[]
|
||||||
| { text: string, script?: string }
|
| { text: string, script?: string }
|
||||||
|
|
@ -26,6 +20,22 @@ export type CommandResult = {
|
||||||
output: CommandOutput
|
output: CommandOutput
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export type ErrorMessage = {
|
||||||
|
type: "error"
|
||||||
|
data: string
|
||||||
|
}
|
||||||
|
|
||||||
|
export type CommandsMessage = {
|
||||||
|
type: "commands"
|
||||||
|
data: string[]
|
||||||
|
}
|
||||||
|
|
||||||
|
export type OutputMessage = {
|
||||||
|
type: "output"
|
||||||
|
id?: string
|
||||||
|
data: CommandResult
|
||||||
|
}
|
||||||
|
|
||||||
export type InputMessage = {
|
export type InputMessage = {
|
||||||
type: "input"
|
type: "input"
|
||||||
id: string
|
id: string
|
||||||
|
|
@ -56,6 +66,14 @@ export type SessionUpdateMessage = {
|
||||||
}
|
}
|
||||||
|
|
||||||
export type GameStartMessage = {
|
export type GameStartMessage = {
|
||||||
|
type: "game:start"
|
||||||
id: string
|
id: string
|
||||||
data: string
|
data: string
|
||||||
|
}
|
||||||
|
|
||||||
|
export type StreamMessage = {
|
||||||
|
type: "stream:start" | "stream:end" | "stream:append" | "stream:replace"
|
||||||
|
id: string
|
||||||
|
session: string
|
||||||
|
data: CommandOutput
|
||||||
}
|
}
|
||||||
|
|
@ -2,7 +2,7 @@ import { send as sendWs } from "./websocket"
|
||||||
import { sessionGet } from "./session"
|
import { sessionGet } from "./session"
|
||||||
import { processExecOutput } from "./shell"
|
import { processExecOutput } from "./shell"
|
||||||
import type { Child } from "hono/jsx"
|
import type { Child } from "hono/jsx"
|
||||||
import type { CommandOutput, Message } from "./shared/types"
|
import type { CommandOutput, StreamMessage } from "./shared/types"
|
||||||
|
|
||||||
type StreamFn = (output: Child) => Promise<void>
|
type StreamFn = (output: Child) => Promise<void>
|
||||||
type StreamFns = { replace: StreamFn, append: StreamFn }
|
type StreamFns = { replace: StreamFn, append: StreamFn }
|
||||||
|
|
@ -16,7 +16,7 @@ export async function stream(initOrFn: StreamParamFn | string | any, fn?: Stream
|
||||||
const taskId = state.taskId
|
const taskId = state.taskId
|
||||||
const session = state.sessionId
|
const session = state.sessionId
|
||||||
|
|
||||||
const send = (msg: Message) => {
|
const send = (msg: Omit<StreamMessage, "id" | "session">) => {
|
||||||
sendWs(state.ws, { ...msg, id: taskId, session })
|
sendWs(state.ws, { ...msg, id: taskId, session })
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue
Block a user