cloudaxe-opencode/packages/opencode/src/cli/cmd/tui/context/exit.tsx

61 lines
1.7 KiB
TypeScript
Raw Normal View History

2025-10-31 19:07:36 +00:00
import { useRenderer } from "@opentui/solid"
import { createSimpleContext } from "./helper"
import { FormatError, FormatUnknownError } from "@/cli/error"
import { win32FlushInputBuffer } from "../win32"
2026-02-02 05:13:47 +00:00
type Exit = ((reason?: unknown) => Promise<void>) & {
message: {
set: (value?: string) => () => void
clear: () => void
get: () => string | undefined
}
}
2025-10-31 19:07:36 +00:00
export const { use: useExit, provider: ExitProvider } = createSimpleContext({
name: "Exit",
2026-03-27 14:00:26 +00:00
init: (input: { onBeforeExit?: () => Promise<void>; onExit?: () => Promise<void> }) => {
2025-10-31 19:07:36 +00:00
const renderer = useRenderer()
2026-02-02 05:13:47 +00:00
let message: string | undefined
2026-03-08 22:14:41 +00:00
let task: Promise<void> | undefined
2026-02-02 05:13:47 +00:00
const store = {
set: (value?: string) => {
const prev = message
message = value
return () => {
message = prev
}
2026-02-02 05:13:47 +00:00
},
clear: () => {
message = undefined
},
get: () => message,
2025-10-31 19:07:36 +00:00
}
2026-02-02 05:13:47 +00:00
const exit: Exit = Object.assign(
2026-03-08 22:14:41 +00:00
(reason?: unknown) => {
if (task) return task
task = (async () => {
2026-03-27 14:00:26 +00:00
await input.onBeforeExit?.()
2026-03-08 22:14:41 +00:00
// Reset window title before destroying renderer
renderer.setTerminalTitle("")
renderer.destroy()
win32FlushInputBuffer()
if (reason) {
const formatted = FormatError(reason) ?? FormatUnknownError(reason)
if (formatted) {
process.stderr.write(formatted + "\n")
}
2026-02-02 05:13:47 +00:00
}
2026-03-08 22:14:41 +00:00
const text = store.get()
if (text) process.stdout.write(text + "\n")
await input.onExit?.()
})()
return task
2026-02-02 05:13:47 +00:00
},
{
message: store,
},
)
process.on("SIGHUP", () => exit())
2026-02-02 05:13:47 +00:00
return exit
2025-10-31 19:07:36 +00:00
},
})