nose-pluto/src/shell.ts
2025-09-20 19:21:16 -07:00

54 lines
1.3 KiB
TypeScript

////
// runs commands and such.
import type { CommandResult } from "./shared/types"
import { join } from "path"
import { NOSE_BIN } from "./config"
import { isFile } from "./utils"
export async function runCommand(input: string): Promise<CommandResult> {
const [cmd = "", ...args] = input.split(" ")
if (!commandExists(cmd)) {
return { status: "error", output: `${cmd} not found` }
}
let status: "ok" | "error" = "ok"
let output = ""
try {
[status, output] = await exec(cmd, args)
} catch (err) {
status = "error"
output = errorMessage(err)
}
return { status, output }
}
async function exec(cmd: string, args: string[]): Promise<["ok" | "error", string]> {
const module = await import(commandPath(cmd) + "?t+" + Date.now())
if (!module || !module.default) {
return ["error", `${cmd} has no default export`]
}
return ["ok", await module.default(...args)]
}
function commandPath(cmd: string): string {
return join(NOSE_BIN, cmd + ".ts")
}
function commandExists(cmd: string): boolean {
return isFile(commandPath(cmd))
}
function errorMessage(error: Error | any): string {
if (!(error instanceof Error))
return String(error)
let msg = `${error.name}: ${error.message}`
if (error.stack) msg += `\n${error.stack}`
return msg
}