This commit is contained in:
Chris Wanstrath 2025-09-29 21:44:11 -07:00
parent 35309db59b
commit 15a8ff29e6
8 changed files with 66 additions and 35 deletions

View File

@ -29,10 +29,10 @@
"baseUrl": ".",
"paths": {
"@utils": [
"../src/utils.tsx"
"/home/nose/.nose/src/utils.tsx"
],
"@/*": [
"../src/*"
"/home/nose/.nose/src/*"
]
},
}

View File

@ -8,6 +8,7 @@ User=nose
WorkingDirectory=/home/nose/.nose/
Environment=PORT=80
Environment=NODE_ENV=production
Environment=NOSE_DIR=/home/nose/nose/
ExecStart=/home/nose/.bun/bin/bun start
Restart=always
RestartSec=1

View File

@ -9,14 +9,9 @@ import { sendAll } from "./websocket"
import { expectDir } from "./utils"
import { NOSE_SYS_BIN, NOSE_BIN } from "./config"
const sysCmdWatcher = watch(NOSE_SYS_BIN, async (event, filename) =>
sendAll({ type: "commands", data: await commands() })
)
expectDir(NOSE_BIN)
const usrCmdWatcher = watch(NOSE_BIN, async (event, filename) => {
sendAll({ type: "commands", data: await commands() })
})
export function initCommands() {
startWatchers()
}
export async function commands(): Promise<string[]> {
return (await findCommands(NOSE_SYS_BIN)).concat(await findCommands(NOSE_BIN))
@ -46,9 +41,22 @@ 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()
}
let sysCmdWatcher
let usrCmdWatcher
function startWatchers() {
expectDir(NOSE_BIN)
sysCmdWatcher = watch(NOSE_SYS_BIN, async (event, filename) =>
sendAll({ type: "commands", data: await commands() })
)
usrCmdWatcher = watch(NOSE_BIN, async (event, filename) => {
sendAll({ type: "commands", data: await commands() })
})
}

View File

@ -1,11 +1,12 @@
import { resolve, join } from "path"
import { $ } from "bun"
import { resolve, join } from "path"
import { untilde } from "./utils"
export const NOSE_ICON = ` ͡° ͜ʖ ͡°`
export const NOSE_SYS_BIN = resolve("./bin")
export const NOSE_DIR = resolve(process.env.NOSE_DIR || "./nose")
export const NOSE_DIR = resolve(untilde(process.env.NOSE_DIR || "./nose"))
export const NOSE_BIN = join(NOSE_DIR, "bin")
export const NOSE_WWW = join(NOSE_DIR, "www")

View File

@ -19,6 +19,7 @@ export async function initDNS() {
if (process.env.NODE_ENV !== "production") return
dnsInit = true
startWatcher()
apps().forEach(publishAppDNS)
const signals = ["SIGINT", "SIGTERM"]
@ -41,10 +42,11 @@ export function publishAppDNS(app: string) {
return dnsEntries[app]
}
// exit process with error if no WWW dir
expectDir(NOSE_WWW)
let wwwWatcher
function startWatcher() {
expectDir(NOSE_WWW)
const wwwWatcher = watch(NOSE_WWW, (event, filename) => {
wwwWatcher = watch(NOSE_WWW, (event, filename) => {
const www = apps()
www.forEach(publishAppDNS)
for (const name in dnsEntries)
@ -52,4 +54,5 @@ const wwwWatcher = watch(NOSE_WWW, (event, filename) => {
dnsEntries[name].kill("SIGTERM")
delete dnsEntries[name]
}
})
})
}

View File

@ -1,2 +1,14 @@
import { NOSE_DIR } from "./config";
////
// Creates ~/nose if it doesn't exist
import { $ } from "bun"
import { NOSE_DIR } from "./config"
import { isDir } from "./utils"
// Make NOSE_DIR if it doesn't exist
export async function initNoseDir() {
if (isDir(NOSE_DIR)) return
await $`cp -r ./nose ${NOSE_DIR}`
}

View File

@ -18,6 +18,8 @@ import { Layout } from "./html/layout"
import { Terminal } from "./html/terminal"
import { dispatchMessage } from "./dispatch"
import { initSneakers, disconnectSneakers } from "./sneaker"
import { initNoseDir } from "./nosedir"
import { initCommands } from "./commands"
//
// Hono setup
@ -159,6 +161,8 @@ console.log(color.blue("NOSE_DIR:"), color.yellow(tilde(NOSE_DIR)))
console.log(color.blue("NOSE_BIN:"), color.yellow(tilde(NOSE_BIN)))
console.log(color.blue("NOSE_WWW:"), color.yellow(tilde(NOSE_WWW)))
await initNoseDir()
initCommands()
initSneakers()
export default {

View File

@ -3,16 +3,23 @@
import { statSync } from "fs"
import { basename } from "path"
import { stat } from "node:fs/promises"
import { stat } from "fs/promises"
import { NOSE_ICON } from "./config"
// Convert /Users/$USER or /home/$USER to ~ for simplicity
export function tilde(path: string): string {
return path.replace(new RegExp(`/(Users|home)/${process.env.USER}`), "~")
}
// Convert ~ to /Users/$USER or /home/$USER for simplicity
export function untilde(path: string): string {
const prefix = process.platform === 'darwin' ? 'Users' : 'home'
return path.replace("~", `/${prefix}/${process.env.USER}`)
}
// End the process with an instructive error if a directory doesn't exist.
export function expectDir(path: string) {
if (!isDir(path)) {
console.error(NOSE_ICON)
console.error(`No ${basename(path)} directory detected. Please run:`)
console.error("\tmkdir -p", path)
console.error(`No ${basename(path)} directory detected.`)
process.exit(1)
}
}
@ -70,11 +77,6 @@ export async function isBinaryFile(path: string): Promise<boolean> {
}
}
// Convert /Users/$USER or /home/$USER to ~ for simplicity
export function tilde(path: string): string {
return path.replace(new RegExp(`/(Users|home)/${process.env.USER}`), "~")
}
const transpiler = new Bun.Transpiler({ loader: 'tsx' })
const transpileCache: Record<string, string> = {}