Compare commits

..

3 Commits

Author SHA1 Message Date
Chris Wanstrath
06b73f90eb fix restarting subprocs 2025-10-20 15:35:16 -07:00
Chris Wanstrath
6bc692c558 also root 2025-10-20 15:19:08 -07:00
Chris Wanstrath
38e081f2cf don't just assume a dir in NOSE_DIR is a project 2025-10-20 15:17:47 -07:00
2 changed files with 25 additions and 10 deletions

View File

@ -5,7 +5,7 @@ import { join } from "path"
import { readdirSync, type Dirent } from "fs"
import { sessionGet } from "./session"
import { DEFAULT_PROJECT, NOSE_DIR } from "./config"
import { isDir } from "./utils"
import { isDir, isFile } from "./utils"
export function projectName(): string {
const state = sessionGet()
@ -16,7 +16,7 @@ export function projectName(): string {
export function projects(): string[] {
return readdirSync(NOSE_DIR, { withFileTypes: true })
.filter(file => file.isDirectory())
.filter(dir => dir.isDirectory() && isProject(join(NOSE_DIR, dir.name)))
.map(dir => dir.name)
.sort()
}
@ -35,3 +35,7 @@ export function projectBin(name = projectName()): string {
export function projectFiles(name = projectName()): Dirent[] {
return readdirSync(projectDir(name), { recursive: true, withFileTypes: true })
}
function isProject(path: string): boolean {
return join(NOSE_DIR, "root") === path || isFile(join(path, "index.ts")) || isFile(join(path, "index.tsx")) || isDir(join(path, "pub"))
}

View File

@ -14,7 +14,13 @@ import { apps, isApp, appDir, isStaticApp, webappLog } from "./utils"
export type Handler = (r: Context) => string | Child | Response | Promise<Response>
export type App = Hono | Handler
const processes = new Map<string, { port: string, proc: ReturnType<typeof Bun.spawn> }>()
type ProcInfo = {
port: string,
proc: ReturnType<typeof Bun.spawn>,
killed?: boolean
}
const processes = new Map<string, ProcInfo>()
const restarting = new Set<string>()
const STARTING_PORT = 10000
let nextPort = STARTING_PORT
@ -67,8 +73,9 @@ async function startApp(name: string): Promise<string | undefined> {
stderr: "inherit",
})
processes.set(name, { port, proc })
proc.exited.then(() => restartApp(name))
const info: ProcInfo = { port, proc }
processes.set(name, info)
proc.exited.then(code => !info.killed && code !== 0 ? restartApp(name) : {})
await Bun.sleep(100) // give it time before first request
@ -89,13 +96,15 @@ export async function shutdownWebapps() {
wwwWatcher?.close()
nextPort = STARTING_PORT
for (const [name, { port, proc }] of processes) {
for (const [name, proc] of processes) {
webappLog(name, "Shutting down")
try { proc.kill() } catch { }
try {
proc.killed = true
proc.proc.kill()
} catch { }
}
processes.clear()
process.exit(0)
}
async function restartApp(name: string) {
@ -107,7 +116,10 @@ async function restartApp(name: string) {
webappLog(name, "restarting")
const existing = processes.get(name)
if (existing) {
try { existing.proc.kill() } catch { }
try {
existing.killed = true
existing.proc.kill()
} catch { }
processes.delete(name)
}
@ -121,7 +133,6 @@ async function startSubprocs() {
await Promise.all(list.map(app => startApp(app)))
}
let wwwWatcher: any
function startWatcher() {
if (!expectDir(NOSE_DIR)) return