diff --git a/src/server/api/apps.ts b/src/server/api/apps.ts index 6a3bdf8..51308bc 100644 --- a/src/server/api/apps.ts +++ b/src/server/api/apps.ts @@ -229,7 +229,7 @@ router.post('/:app/rename', async c => { if (!newName) return c.json({ ok: false, error: 'New name is required' }, 400) - const result = renameApp(appName, newName) + const result = await renameApp(appName, newName) if (!result.ok) return c.json(result, 400) return c.json({ ok: true, name: newName }) diff --git a/src/server/apps.ts b/src/server/apps.ts index b8096ee..95cb936 100644 --- a/src/server/apps.ts +++ b/src/server/apps.ts @@ -142,7 +142,7 @@ export function registerApp(dir: string) { } } -export function renameApp(oldName: string, newName: string): { ok: boolean, error?: string } { +export async function renameApp(oldName: string, newName: string): Promise<{ ok: boolean, error?: string }> { const app = _apps.get(oldName) if (!app) return { ok: false, error: 'App not found' } @@ -155,15 +155,13 @@ export function renameApp(oldName: string, newName: string): { ok: boolean, erro const oldPath = join(APPS_DIR, oldName) const newPath = join(APPS_DIR, newName) - // Stop the app if running + // Stop the app and wait for process to fully exit so the port is freed const wasRunning = app.state === 'running' if (wasRunning) { + const proc = app.proc clearTimers(app) app.proc?.kill() - app.proc = undefined - if (app.port) releasePort(app.port) - app.port = undefined - app.started = undefined + if (proc) await proc.exited } try { @@ -681,6 +679,10 @@ async function runApp(dir: string, port: number) { // Handle process exit proc.exited.then(code => { + // If the app has moved on (e.g. renamed and restarted), this is a + // stale exit handler — don't touch current app state or ports + if (app.proc && app.proc !== proc) return + // Clear all timers clearTimers(app)