serve command source

This commit is contained in:
Chris Wanstrath 2025-09-27 16:47:09 -07:00
parent 2c726c5bd2
commit d320b2d74e
3 changed files with 34 additions and 28 deletions

View File

@ -3,6 +3,8 @@
import { Glob } from "bun" import { Glob } from "bun"
import { watch } from "fs" import { watch } from "fs"
import { join } from "path"
import { isFile } from "./utils"
import { sendAll } from "./websocket" import { sendAll } from "./websocket"
import { expectDir } from "./utils" import { expectDir } from "./utils"
import { NOSE_SYS_BIN, NOSE_BIN } from "./config" import { NOSE_SYS_BIN, NOSE_BIN } from "./config"
@ -29,4 +31,24 @@ export async function findCommands(path: string): Promise<string[]> {
} }
return list return list
}
export function commandPath(cmd: string): string | undefined {
return [
join(NOSE_SYS_BIN, cmd + ".ts"),
join(NOSE_SYS_BIN, cmd + ".tsx"),
join(NOSE_BIN, cmd + ".ts"),
join(NOSE_BIN, cmd + ".tsx")
].find((path: string) => isFile(path))
}
export function commandExists(cmd: string): boolean {
return commandPath(cmd) !== undefined
}
export async function commandSource(name: string): Promise<string> {
const path = commandPath(name)
if (!path) return ""
return Bun.file(path).text()
} }

View File

@ -9,9 +9,9 @@ import color from "kleur"
import type { Message } from "./shared/types" import type { Message } from "./shared/types"
import { NOSE_ICON, NOSE_BIN, NOSE_WWW } from "./config" import { NOSE_ICON, NOSE_BIN, NOSE_WWW } from "./config"
import { transpile, isFile, tilde } from "./utils" import { transpile, isFile, tilde } from "./utils"
import { apps, serveApp } from "./webapp" import { serveApp } from "./webapp"
import { initDNS } from "./dns" import { initDNS } from "./dns"
import { commands } from "./commands" import { commands, commandSource, commandPath } from "./commands"
import { send, addWebsocket, removeWebsocket, closeWebsockets } from "./websocket" import { send, addWebsocket, removeWebsocket, closeWebsockets } from "./websocket"
import { Layout } from "./html/layout" import { Layout } from "./html/layout"
@ -76,16 +76,15 @@ app.use("*", async (c, next) => {
return next() return next()
}) })
app.get("/apps", c => { app.get("/command/:name", async c => {
const url = new URL(c.req.url) const name = c.req.param("name")
const domain = url.hostname const path = commandPath(name)
let port = url.port if (!path) return c.text("Command not found", 404)
port = port && port !== "80" ? `:${port}` : "" return new Response(await transpile(path), {
headers: {
return c.html(<> "Content-Type": "text/javascript"
<h1>apps</h1> }
<ul>{apps().map(app => <li><a href={`http://${app}.${domain}${port}`}>{app}</a></li>)}</ul> })
</>)
}) })
app.get("/", c => c.html(<Layout><Terminal /></Layout>)) app.get("/", c => c.html(<Layout><Terminal /></Layout>))

View File

@ -2,11 +2,9 @@
// Runs commands and such on the server. // Runs commands and such on the server.
// This is the "shell" - the "terminal" is the browser UI. // This is the "shell" - the "terminal" is the browser UI.
import { join } from "path"
import type { CommandResult, CommandOutput } from "./shared/types" import type { CommandResult, CommandOutput } from "./shared/types"
import type { Session } from "./session" import type { Session } from "./session"
import { NOSE_SYS_BIN, NOSE_BIN } from "./config" import { commandExists, commandPath } from "./commands"
import { isFile } from "./utils"
import { ALS } from "./session" import { ALS } from "./session"
const sessions: Map<string, Session> = new Map() const sessions: Map<string, Session> = new Map()
@ -69,19 +67,6 @@ function getState(sessionId: string, taskId: string, ws?: any): Session {
return state return state
} }
function commandPath(cmd: string): string | undefined {
return [
join(NOSE_SYS_BIN, cmd + ".ts"),
join(NOSE_SYS_BIN, cmd + ".tsx"),
join(NOSE_BIN, cmd + ".ts"),
join(NOSE_BIN, cmd + ".tsx")
].find((path: string) => isFile(path))
}
function commandExists(cmd: string): boolean {
return commandPath(cmd) !== undefined
}
function errorMessage(error: Error | any): string { function errorMessage(error: Error | any): string {
if (!(error instanceof Error)) if (!(error instanceof Error))
return String(error) return String(error)