From 39fb1042ad6069adbbe96a89da2a9b2bf8ea15db Mon Sep 17 00:00:00 2001 From: David Matejka Date: Fri, 26 Jun 2026 16:35:23 +0200 Subject: [PATCH] fix: persist toggled databases on the DATABASE_URL connection across reloads MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit After #16 removed the error when toggling extra databases on a server-managed (DATABASE_URL) connection, the toggle worked in-session but the databases vanished on page reload: each WebSocket gets a fresh in-memory app DB and the env connection is recreated from DATABASE_URL with no memory of what was activated. Remember the env connection's active databases in a process-scoped set, seed the connection config from it on session creation (so the fire-and-forget auto-connect reconnects them), and update it by wrapping the databases.activate/deactivate handlers — mirroring the existing connections.list wrap. Verified in a browser against a real Postgres: activate a second database, reload → it is still present; deactivate, reload → it is gone. Co-Authored-By: Claude Opus 4.8 (1M context) Claude-Session: https://claude.ai/code/session_01NxZYcCWNSKYkMqT3KYdwTB --- src/backend-web/session.ts | 30 +++++++++++++++++++++++++++++- 1 file changed, 29 insertions(+), 1 deletion(-) diff --git a/src/backend-web/session.ts b/src/backend-web/session.ts index 28cd9505..42ad1be4 100644 --- a/src/backend-web/session.ts +++ b/src/backend-web/session.ts @@ -35,6 +35,14 @@ export interface Session { const envConnection = parseEnvConnection() const sessions = new Map() +// Databases the user toggled on (Manage Databases…) for the DATABASE_URL +// connection, remembered across sessions. Each session gets a fresh in-memory +// app DB and the env connection is recreated from DATABASE_URL on every +// WebSocket, so without this the extra databases vanish on page reload. +// Process-scoped: shared by all sessions of the single shared env connection, +// and reset when the server restarts. +const envActiveDatabases = new Set() + export function getSessions(): Map { return sessions } @@ -64,9 +72,14 @@ export function createSession( // Auto-create env connection if DATABASE_URL is set if (envConnection) { + // Restore databases toggled on in an earlier session so they survive a + // page reload — the fire-and-forget auto-connect below reconnects them. + const config = envActiveDatabases.size > 0 + ? { ...envConnection.config, activeDatabases: [...envActiveDatabases] } + : envConnection.config appDb.createConnectionWithId(ENV_CONNECTION_ID, { name: envConnection.name, - config: envConnection.config, + config, }) serverManagedIds.add(ENV_CONNECTION_ID) @@ -76,6 +89,21 @@ export function createSession( const list = originalList() return list.map(conn => serverManagedIds.has(conn.id) ? { ...conn, serverManaged: true } : conn) } + + // Remember activate/deactivate on the env connection across sessions so a + // reload restores the same set of databases (see envActiveDatabases). + const originalActivate = handlers['databases.activate'] + ;(handlers as Record)['databases.activate'] = async (params: { connectionId: string; database: string }) => { + const result = await originalActivate(params) + if (params.connectionId === ENV_CONNECTION_ID) envActiveDatabases.add(params.database) + return result + } + const originalDeactivate = handlers['databases.deactivate'] + ;(handlers as Record)['databases.deactivate'] = async (params: { connectionId: string; database: string }) => { + const result = await originalDeactivate(params) + if (params.connectionId === ENV_CONNECTION_ID) envActiveDatabases.delete(params.database) + return result + } } const unsubSessionDead = connectionManager.onSessionDead((event) => {