Compare commits

..

No commits in common. "df700ffe912ff2bd77e995c4525448b774213bb6" and "ff6f71daf8d96cab4669f588e4d8499e33bd6fd7" have entirely different histories.

3 changed files with 59 additions and 55 deletions

View File

@ -12,6 +12,4 @@ export const DEFAULT_PROJECT = "root"
export const NOSE_ROOT_BIN = join(NOSE_DIR, DEFAULT_PROJECT, "bin") export const NOSE_ROOT_BIN = join(NOSE_DIR, DEFAULT_PROJECT, "bin")
export const NOSE_STARTED = Date.now() export const NOSE_STARTED = Date.now()
export const GIT_SHA = (await $`git rev-parse --short HEAD`.text()).trim() export const GIT_SHA = (await $`git rev-parse --short HEAD`.text()).trim()
; (globalThis as any).GIT_SHA = GIT_SHA

View File

@ -3,6 +3,7 @@
import { Hono } from "hono" import { Hono } from "hono"
import { serveStatic, upgradeWebSocket, websocket } from "hono/bun" import { serveStatic, upgradeWebSocket, websocket } from "hono/bun"
import { prettyJSON } from "hono/pretty-json"
import color from "kleur" import color from "kleur"
import type { Message } from "./shared/types" import type { Message } from "./shared/types"
@ -33,7 +34,13 @@ import { initCommands } from "./commands"
const app = new Hono() const app = new Hono()
// console logging 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' }))
app.use("*", async (c, next) => { app.use("*", async (c, next) => {
const start = Date.now() const start = Date.now()
await next() await next()
@ -42,31 +49,6 @@ app.use("*", async (c, next) => {
console.log(fn(`${c.res.status} ${c.req.method} ${c.req.url} (${end - start}ms)`)) 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) => { app.use("*", async (c, next) => {
const error = fatal ? fatal : !isDir(NOSE_DIR) ? `NOSE_DIR doesn't exist: ${NOSE_DIR}` : undefined const error = fatal ? fatal : !isDir(NOSE_DIR) ? `NOSE_DIR doesn't exist: ${NOSE_DIR}` : undefined
@ -77,8 +59,6 @@ app.use("*", async (c, next) => {
} }
}) })
// 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 => { app.on("GET", ["/js/:path{.+}", "/shared/:path{.+}"], async c => {
let path = "./src/" + c.req.path.replace("..", ".") let path = "./src/" + c.req.path.replace("..", ".")
@ -95,6 +75,10 @@ if (process.env.NODE_ENV !== "production")
} }
}) })
//
// app routes
//
// inject browser-nav.js into NOSE apps when loaded in a NOSE iframe // inject browser-nav.js into NOSE apps when loaded in a NOSE iframe
app.use("*", async (c, next) => { app.use("*", async (c, next) => {
await next() await next()
@ -128,7 +112,23 @@ app.use("*", async (c, next) => {
}) })
}) })
// source code of commands - used to load and eval() browser commands 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()
})
app.get("/source/:name", async c => { app.get("/source/:name", async c => {
const name = c.req.param("name") const name = c.req.param("name")
const sessionId = c.req.query("session") || "0" const sessionId = c.req.query("session") || "0"
@ -142,7 +142,6 @@ 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 => { app.on(["GET", "POST"], ["/cmd/:name"], async c => {
const sessionId = c.req.header("X-Session") || "0" const sessionId = c.req.header("X-Session") || "0"
const cmd = c.req.param("name") const cmd = c.req.param("name")
@ -159,10 +158,12 @@ app.on(["GET", "POST"], ["/cmd/:name"], async c => {
} }
}) })
// the terminal
app.get("/", c => c.html(<Layout><Terminal /></Layout>)) app.get("/", c => c.html(<Layout><Terminal /></Layout>))
// the main websocket //
// websocket
//
app.get("/ws", c => { app.get("/ws", c => {
const _sessionId = c.req.query("session") const _sessionId = c.req.query("session")
const url = new URL(c.req.url) const url = new URL(c.req.url)
@ -228,17 +229,16 @@ if (process.env.BUN_HOT) {
} }
// //
// server start // production mode
// //
if (process.env.NODE_ENV === "production") { if (process.env.NODE_ENV === "production") {
initDNS() initDNS()
} }
await initNoseDir() //
initCommands() // server start
initWebapps() //
initSneakers()
console.log(color.cyan(NOSE_ICON)) console.log(color.cyan(NOSE_ICON))
console.log(color.blue(" NOSE_BIN:"), color.yellow(tilde(NOSE_BIN))) console.log(color.blue(" NOSE_BIN:"), color.yellow(tilde(NOSE_BIN)))
@ -246,6 +246,11 @@ 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_DIR:"), color.yellow(tilde(NOSE_DIR)))
console.log(color.blue("NOSE_ROOT_BIN:"), color.yellow(tilde(NOSE_ROOT_BIN))) console.log(color.blue("NOSE_ROOT_BIN:"), color.yellow(tilde(NOSE_ROOT_BIN)))
await initNoseDir()
initCommands()
initWebapps()
initSneakers()
export default { export default {
port: process.env.PORT || 3000, port: process.env.PORT || 3000,
hostname: "0.0.0.0", hostname: "0.0.0.0",

View File

@ -3,6 +3,7 @@
import type { Child } from "hono/jsx" import type { Child } from "hono/jsx"
import { type Context, Hono } from "hono" import { type Context, Hono } from "hono"
import { renderToString } from "hono/jsx/dom/server"
import { join } from "path" import { join } from "path"
import { readdirSync, watch } from "fs" import { readdirSync, watch } from "fs"
import { sendAll } from "./websocket" import { sendAll } from "./websocket"
@ -78,13 +79,13 @@ async function loadApp(path: string): Promise<App | undefined> {
return mod.default as App return mod.default as App
} }
export async function toResponse(source: string | Child | Response): Promise<Response> { export function toResponse(source: string | Child | Response): Response {
if (source instanceof Response) if (source instanceof Response)
return source return source
else if (typeof source === "string") else if (typeof source === "string")
return new Response(source) return new Response(source)
else else
return new Response(await source?.toString(), { return new Response(renderToString(source), {
headers: { headers: {
"Content-Type": "text/html; charset=utf-8" "Content-Type": "text/html; charset=utf-8"
} }