nose-pluto/app/src/dns.ts
Chris Wanstrath dedb19bd81 fun
2025-09-26 11:30:25 -07:00

54 lines
1.4 KiB
TypeScript

////
// Publishes webapps as subdomains on your local network
import { watch } from "fs"
import { apps } from "./webapp"
import { expectDir } from "./utils"
import { NOSE_WWW } from "./config"
export const dnsEntries: Record<string, any> = {}
const { stdout: ipRaw } = await Bun.$`hostname -I | awk '{print $1}'`.quiet()
const { stdout: hostRaw } = await Bun.$`hostname`.quiet()
const ip = ipRaw.toString().trim()
const host = hostRaw.toString().trim()
let dnsInit = false
export async function initDNS() {
dnsInit = true
apps().forEach(publishAppDNS)
const signals = ["SIGINT", "SIGTERM"]
signals.forEach(sig =>
process.on(sig, () => {
for (const name in dnsEntries)
dnsEntries[name].kill("SIGTERM")
process.exit(0)
})
)
}
export function publishAppDNS(app: string) {
if (!dnsInit) throw "publishAppDNS() must be called after initDNS()"
if (process.env.NODE_ENV !== "production") return
if (!dnsEntries[app])
dnsEntries[app] = Bun.spawn(["avahi-publish", "-a", `${app}.${host}.local`, "-R", ip])
return dnsEntries[app]
}
// exit process with error if no WWW dir
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]
}
})