This commit is contained in:
Chris Wanstrath 2026-01-27 14:53:05 -08:00
parent 1ec012338f
commit fa459c45eb
5 changed files with 43 additions and 21 deletions

View File

@ -6,7 +6,8 @@
[x] scans for apps/**/package.json, scripts.toes [x] scans for apps/**/package.json, scripts.toes
[x] runs that for each, giving it a PORT [x] runs that for each, giving it a PORT
[x] has GET / page that shows all the running apps/status/port [x] has GET / page that shows all the running apps/status/port
[ ] watch each app and restart it on update [x] watch each app and restart it on update
[x] watches for and adds/removes apps
## cli ## cli

View File

@ -4,7 +4,7 @@
"type": "module", "type": "module",
"private": true, "private": true,
"scripts": { "scripts": {
"toes": "bun start", "toes": "bun run --watch index.tsx",
"start": "bun run index.tsx", "start": "bun run index.tsx",
"dev": "bun run --hot index.tsx" "dev": "bun run --hot index.tsx"
}, },

View File

@ -2,9 +2,6 @@ import { Hype } from 'hype'
const app = new Hype const app = new Hype
app.get('/', c => c.html(<h1>Hi there!</h1>)) app.get('/', c => c.html(<h1>My Profile!!!</h1>))
const apps = () => {
}
export default app.defaults export default app.defaults

View File

@ -4,7 +4,7 @@
"type": "module", "type": "module",
"private": true, "private": true,
"scripts": { "scripts": {
"toes": "bun start", "toes": "bun run --watch index.tsx",
"start": "bun run index.tsx", "start": "bun run index.tsx",
"dev": "bun run --hot index.tsx" "dev": "bun run --hot index.tsx"
}, },

View File

@ -1,6 +1,6 @@
import { Subprocess } from 'bun' import type { Subprocess } from 'bun'
import { Hype } from 'hype' import { Hype } from 'hype'
import { readdirSync, readFileSync } from 'fs' import { existsSync, readdirSync, readFileSync, watch } from 'fs'
import { join } from 'path' import { join } from 'path'
const APPS_DIR = join(process.env.DATA_DIR ?? '.', 'apps') const APPS_DIR = join(process.env.DATA_DIR ?? '.', 'apps')
@ -20,7 +20,7 @@ const info = (app: string, ...msg: string[]) =>
console.log('🐾', `${app}:`, ...msg) console.log('🐾', `${app}:`, ...msg)
const log = (app: string, ...msg: string[]) => const log = (app: string, ...msg: string[]) =>
console.log('🐾', `${app}»`, ...msg) console.log(`<${app}>`, ...msg)
const appNames = () => { const appNames = () => {
return readdirSync(APPS_DIR, { withFileTypes: true }) return readdirSync(APPS_DIR, { withFileTypes: true })
@ -67,16 +67,20 @@ const loadApp = (dir: string) => {
} }
} }
const runApp = (dir: string, port: number) => { const runApp = async (dir: string, port: number) => {
const pkg = loadApp(dir) const pkg = loadApp(dir)
if (!pkg.scripts?.toes) return if (!pkg.scripts?.toes) return
const cwd = join(APPS_DIR, dir) const cwd = join(APPS_DIR, dir)
const cmd = ['bun', 'run', 'toes']
const needsInstall = !existsSync(join(cwd, 'node_modules'))
if (needsInstall) info(dir, 'Installing dependencies...')
const install = Bun.spawn(['bun', 'install'], { cwd, stdout: 'pipe', stderr: 'pipe' })
await install.exited
info(dir, `Starting on port ${port}...`) info(dir, `Starting on port ${port}...`)
const proc = Bun.spawn(cmd, { const proc = Bun.spawn(['bun', 'run', 'toes'], {
cwd, cwd,
env: { ...process.env, PORT: String(port) }, env: { ...process.env, PORT: String(port) },
stdout: 'pipe', stdout: 'pipe',
@ -124,9 +128,27 @@ const stopApp = (dir: string) => {
} }
} }
console.log('🐾 Toes!') const watchAppsDir = () => {
runApps() watch(APPS_DIR, (event, filename) => {
console.log('apps dir')
if (!filename) return
if (isApp(filename) && !runningApps.has(filename)) {
const port = getPort()
runApp(filename, port)
}
if (runningApps.has(filename) && !isApp(filename))
stopApp(filename)
})
}
const startup = () => {
console.log('🐾 Toes!')
runApps()
watchAppsDir()
}
const app = new Hype() const app = new Hype()
@ -139,5 +161,7 @@ app.get('/', c => {
) )
}) })
startup()
export { getRunningApps, stopApp } export { getRunningApps, stopApp }
export default app.defaults export default app.defaults