From 15a8ff29e62f75e7953b36fa45fcfd6b7bfaf241 Mon Sep 17 00:00:00 2001 From: Chris Wanstrath Date: Mon, 29 Sep 2025 21:44:11 -0700 Subject: [PATCH] nosedir --- nose/tsconfig.json | 4 ++-- scripts/nose-pluto.service | 1 + src/commands.ts | 26 +++++++++++++++++--------- src/config.ts | 5 +++-- src/dns.ts | 25 ++++++++++++++----------- src/nosedir.ts | 14 +++++++++++++- src/server.tsx | 4 ++++ src/utils.tsx | 22 ++++++++++++---------- 8 files changed, 66 insertions(+), 35 deletions(-) diff --git a/nose/tsconfig.json b/nose/tsconfig.json index 387adc1..bc29f9f 100644 --- a/nose/tsconfig.json +++ b/nose/tsconfig.json @@ -29,10 +29,10 @@ "baseUrl": ".", "paths": { "@utils": [ - "../src/utils.tsx" + "/home/nose/.nose/src/utils.tsx" ], "@/*": [ - "../src/*" + "/home/nose/.nose/src/*" ] }, } diff --git a/scripts/nose-pluto.service b/scripts/nose-pluto.service index 6589637..365b8b2 100644 --- a/scripts/nose-pluto.service +++ b/scripts/nose-pluto.service @@ -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 diff --git a/src/commands.ts b/src/commands.ts index 144d641..cffa15e 100644 --- a/src/commands.ts +++ b/src/commands.ts @@ -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 { 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 { 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() }) + }) } \ No newline at end of file diff --git a/src/config.ts b/src/config.ts index 7bd5a5d..69d982b 100644 --- a/src/config.ts +++ b/src/config.ts @@ -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") diff --git a/src/dns.ts b/src/dns.ts index 5e24683..d188d51 100644 --- a/src/dns.ts +++ b/src/dns.ts @@ -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,15 +42,17 @@ 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) => { - const www = apps() - www.forEach(publishAppDNS) - for (const name in dnsEntries) - if (!www.includes(name)) { - dnsEntries[name].kill("SIGTERM") - delete dnsEntries[name] - } -}) \ No newline at end of file + wwwWatcher = watch(NOSE_WWW, (event, filename) => { + const www = apps() + www.forEach(publishAppDNS) + for (const name in dnsEntries) + if (!www.includes(name)) { + dnsEntries[name].kill("SIGTERM") + delete dnsEntries[name] + } + }) +} \ No newline at end of file diff --git a/src/nosedir.ts b/src/nosedir.ts index cca6990..ca61e12 100644 --- a/src/nosedir.ts +++ b/src/nosedir.ts @@ -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}` +} diff --git a/src/server.tsx b/src/server.tsx index 1cf5ff1..c627c87 100644 --- a/src/server.tsx +++ b/src/server.tsx @@ -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 { diff --git a/src/utils.tsx b/src/utils.tsx index adce913..472d6be 100644 --- a/src/utils.tsx +++ b/src/utils.tsx @@ -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 { } } -// 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 = {}