diff --git a/package.json b/package.json index f268bbc..587d8d1 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "autonomy-studio-launcher", - "version": "1.0.11", + "version": "1.0.12", "description": "Autonomy Studio v2 Frontend", "main": "./out/main/index.js", "author": { diff --git a/src/main/index.ts b/src/main/index.ts index a87235b..9f87050 100644 --- a/src/main/index.ts +++ b/src/main/index.ts @@ -294,6 +294,48 @@ function installDebPackage(debPath: string): Promise { }) } +function createCleanChildEnv(extraEnv?: NodeJS.ProcessEnv): NodeJS.ProcessEnv { + const env = { ...process.env, ...extraEnv } + + delete env.APPIMAGE + delete env.APPDIR + delete env.OWD + delete env.ARGV0 + delete env.ELECTRON_RENDERER_URL + delete env.VITE_DEV_SERVER_URL + + return env +} + +function stopChildApps( + appProcesses: Map, + appWindows: Map, +): void { + for (const child of appProcesses.values()) { + if (!child.killed) { + child.kill('SIGTERM') + setTimeout(() => { + if (!child.killed) child.kill('SIGKILL') + }, 1500).unref() + } + } + appProcesses.clear() + + for (const win of appWindows.values()) { + if (!win.isDestroyed()) win.close() + } + appWindows.clear() +} + +function relaunchFromCleanProcess(): void { + const child = spawn('/bin/sh', ['-lc', 'sleep 1; exec "$LAUNCHER_PATH" >/dev/null 2>&1'], { + detached: true, + stdio: 'ignore', + env: createCleanChildEnv({ LAUNCHER_PATH: process.execPath }), + }) + child.unref() +} + function runCommand(command: string, args: string[], timeoutMs = 30000, extraEnv?: NodeJS.ProcessEnv): Promise<{ stdout: string; stderr: string }> { return new Promise((resolve, reject) => { const child = spawn(command, args, { @@ -775,20 +817,12 @@ function createWindow(): void { await installDebPackage(debPath) if (!is.dev) { - for (const child of appProcesses.values()) { - child.kill() - } - appProcesses.clear() - - for (const win of appWindows.values()) { - if (!win.isDestroyed()) win.close() - } - appWindows.clear() + stopChildApps(appProcesses, appWindows) setImmediate(() => { - app.relaunch() + relaunchFromCleanProcess() app.quit() - setTimeout(() => app.exit(0), 1000) + setTimeout(() => app.exit(0), 1000).unref() }) } @@ -881,7 +915,7 @@ function createWindow(): void { : [...launchUrlArg, ...authLaunchArgs, ...(authProtocolUrl ? [authProtocolUrl] : [])] const execBin = useDevLauncher ? 'npm' : spawnPath - const childEnv = { ...process.env } + const childEnv = createCleanChildEnv() if (useDevLauncher && url) { childEnv.ATNMY_APP_URL = url } @@ -894,9 +928,6 @@ function createWindow(): void { childEnv.ATNMY_AUDIENCE_APP = audienceApp } - delete childEnv.ELECTRON_RENDERER_URL - delete childEnv.VITE_DEV_SERVER_URL - const logPath = useDevLauncher ? join(app.getPath('temp'), `autonomy-studio-${appName.replace(/[^a-z0-9_-]+/gi, '-').toLowerCase()}.dev.log`) : undefined const logFd = logPath ? openSync(logPath, 'a') : undefined if (logPath) { diff --git a/src/renderer/src/App.tsx b/src/renderer/src/App.tsx index 065a116..293756d 100644 --- a/src/renderer/src/App.tsx +++ b/src/renderer/src/App.tsx @@ -32,16 +32,18 @@ function App(): React.JSX.Element { }, []) const handleLogout = useCallback((): void => { + const accessToken = authSession?.accessToken void fetch(`${LAUNCHER_API_BASE_URL}/api/auth/logout`, { method: 'POST', credentials: 'include', keepalive: true, + headers: accessToken ? { Authorization: `Bearer ${accessToken}` } : undefined, }).catch(() => undefined) window.launcherTailscale?.logout().catch(() => undefined) window.localStorage.removeItem(AUTH_SESSION_KEY) window.sessionStorage.removeItem(AUTH_SESSION_KEY) setAuthSession(null) - }, []) + }, [authSession?.accessToken]) useEffect(() => { if (!authSession?.accessToken) return