From d5e0dbd2dbaea21e314eac55f3cf3eb6c249a400 Mon Sep 17 00:00:00 2001 From: Chris Wanstrath <2+defunkt@users.noreply.github.com> Date: Wed, 8 Oct 2025 13:15:39 -0700 Subject: [PATCH] subdomain sites get priority --- src/server.tsx | 105 +++++++++++++++++++++++-------------------------- 1 file changed, 50 insertions(+), 55 deletions(-) diff --git a/src/server.tsx b/src/server.tsx index ba4fbec..203ea7e 100644 --- a/src/server.tsx +++ b/src/server.tsx @@ -3,7 +3,6 @@ import { Hono } from "hono" import { serveStatic, upgradeWebSocket, websocket } from "hono/bun" -import { prettyJSON } from "hono/pretty-json" import color from "kleur" import type { Message } from "./shared/types" @@ -34,13 +33,7 @@ import { initCommands } from "./commands" const app = new Hono() -app.use("*", prettyJSON()) - -app.use('/*', serveStatic({ root: './public' })) -app.use('/img/*', serveStatic({ root: './public' })) -app.use('/vendor/*', serveStatic({ root: './public' })) -app.use('/css/*', serveStatic({ root: './src' })) - +// console logging app.use("*", async (c, next) => { const start = Date.now() await next() @@ -49,6 +42,31 @@ app.use("*", async (c, next) => { console.log(fn(`${c.res.status} ${c.req.method} ${c.req.url} (${end - start}ms)`)) }) +// subdomain route needs to go first +app.use("*", async (c, next) => { + const url = new URL(c.req.url) + const localhost = url.hostname.endsWith("localhost") + const domains = url.hostname.split(".") + let subdomain = "" + + if (domains.length > (localhost ? 1 : 2)) + subdomain = domains[0]! + + if (subdomain) { + const app = serveApp(c, subdomain) + return await app + } + + return next() +}) + +// static files +app.use('/*', serveStatic({ root: './public' })) +app.use('/img/*', serveStatic({ root: './public' })) +app.use('/vendor/*', serveStatic({ root: './public' })) +app.use('/css/*', serveStatic({ root: './src' })) + +// blue screen of death error page if NOSE_DIR isn't found app.use("*", async (c, next) => { const error = fatal ? fatal : !isDir(NOSE_DIR) ? `NOSE_DIR doesn't exist: ${NOSE_DIR}` : undefined @@ -59,25 +77,23 @@ app.use("*", async (c, next) => { } }) -app.on("GET", ["/js/:path{.+}", "/shared/:path{.+}"], async c => { - let path = "./src/" + c.req.path.replace("..", ".") +// only transpile browser JS on the fly in dev mode +if (process.env.NODE_ENV !== "production") + app.on("GET", ["/js/:path{.+}", "/shared/:path{.+}"], async c => { + let path = "./src/" + c.req.path.replace("..", ".") - // path must end in .js or .ts - if (!path.endsWith(".js") && !path.endsWith(".ts")) path += ".ts" + // path must end in .js or .ts + if (!path.endsWith(".js") && !path.endsWith(".ts")) path += ".ts" - const ts = path.replace(".js", ".ts") - if (isFile(ts)) { - return new Response(await transpile(ts), { headers: { "Content-Type": "text/javascript" } }) - } else if (isFile(path)) { - return new Response(Bun.file(path), { headers: { "Content-Type": "text/javascript" } }) - } else { - return c.text("File not found", 404) - } -}) - -// -// app routes -// + const ts = path.replace(".js", ".ts") + if (isFile(ts)) { + return new Response(await transpile(ts), { headers: { "Content-Type": "text/javascript" } }) + } else if (isFile(path)) { + return new Response(Bun.file(path), { headers: { "Content-Type": "text/javascript" } }) + } else { + return c.text("File not found", 404) + } + }) // inject browser-nav.js into NOSE apps when loaded in a NOSE iframe app.use("*", async (c, next) => { @@ -112,23 +128,7 @@ app.use("*", async (c, next) => { }) }) -app.use("*", async (c, next) => { - const url = new URL(c.req.url) - const localhost = url.hostname.endsWith("localhost") - const domains = url.hostname.split(".") - let subdomain = "" - - if (domains.length > (localhost ? 1 : 2)) - subdomain = domains[0]! - - if (subdomain) { - const app = serveApp(c, subdomain) - return await app - } - - return next() -}) - +// source code of commands - used to load and eval() browser commands app.get("/source/:name", async c => { const name = c.req.param("name") const sessionId = c.req.query("session") || "0" @@ -142,6 +142,7 @@ app.get("/source/:name", async c => { }) }) +// call a command's GET or POST function, if one exists app.on(["GET", "POST"], ["/cmd/:name"], async c => { const sessionId = c.req.header("X-Session") || "0" const cmd = c.req.param("name") @@ -158,12 +159,10 @@ app.on(["GET", "POST"], ["/cmd/:name"], async c => { } }) +// the terminal app.get("/", c => c.html()) -// -// websocket -// - +// the main websocket app.get("/ws", c => { const _sessionId = c.req.query("session") const url = new URL(c.req.url) @@ -229,16 +228,17 @@ if (process.env.BUN_HOT) { } // -// production mode +// server start // if (process.env.NODE_ENV === "production") { initDNS() } -// -// server start -// +await initNoseDir() +initCommands() +initWebapps() +initSneakers() console.log(color.cyan(NOSE_ICON)) console.log(color.blue(" NOSE_BIN:"), color.yellow(tilde(NOSE_BIN))) @@ -246,11 +246,6 @@ console.log(color.blue(" NOSE_DATA:"), color.yellow(tilde(NOSE_DATA))) console.log(color.blue(" NOSE_DIR:"), color.yellow(tilde(NOSE_DIR))) console.log(color.blue("NOSE_ROOT_BIN:"), color.yellow(tilde(NOSE_ROOT_BIN))) -await initNoseDir() -initCommands() -initWebapps() -initSneakers() - export default { port: process.env.PORT || 3000, hostname: "0.0.0.0",