fix(sidebar): preserve one-time links across connection reloads

Closes #6647
This commit is contained in:
t8y2 committed 2026-08-19 05:51:01 +00:00
1 parent 81d22b32c7
commit 2196b743b0
2 files changed
+44 -2

No files matched your search

@@ -18,9 +18,15 @@ function installApiMocks() {
connectDb: vi.fn().mockResolvedValue("preview-1"),
disconnectDb: vi.fn().mockResolvedValue(undefined),
deleteSchemaCachePrefix: vi.fn().mockResolvedValue(undefined),
loadConnections: vi.fn().mockResolvedValue([]),
loadEditorSettings: vi.fn().mockResolvedValue(null),
loadPinnedTreeNodeIds: vi.fn().mockResolvedValue([]),
loadSchemaCache: vi.fn().mockResolvedValue(null),
loadTunnelProfiles: vi.fn().mockResolvedValue([]),
saveConnections: vi.fn().mockResolvedValue(undefined),
saveEditorSettings: vi.fn().mockResolvedValue(undefined),
saveSidebarLayout: vi.fn().mockResolvedValue(undefined),
loadSidebarLayout: vi.fn().mockResolvedValue(null),
connectionDatabaseInfo: vi.fn().mockResolvedValue(undefined),
listInstalledAgents: vi.fn().mockResolvedValue([]),
sessionCredentialStatus: vi.fn().mockResolvedValue(false),
@@ -77,6 +83,36 @@ describe("connectionStore one_time runtime cleanup", () => {
expect(disconnectDb).toHaveBeenCalledWith("preview-1");
});
it("initFromDisk preserves an open one_time connection during a persisted-list reload", async () => {
installApiMocks();
const { loadConnections } = await import("@/lib/backend/api");
vi.mocked(loadConnections).mockResolvedValue([
previewConnection({ id: "saved-1", name: "Saved", one_time: false }),
]);
const { useConnectionStore } = await import("@/stores/connectionStore");
const store = useConnectionStore();
store.connections = [previewConnection({ id: "deeplink-1", name: "Deeplink", one_time: true })];
await store.initFromDisk();
expect(store.connections.map((connection) => connection.id)).toEqual(["saved-1", "deeplink-1"]);
expect(store.getConfig("deeplink-1")).toMatchObject({ name: "Deeplink", one_time: true });
});
it("does not retain a stale saved connection removed from persisted storage", async () => {
installApiMocks();
const { loadConnections } = await import("@/lib/backend/api");
vi.mocked(loadConnections).mockResolvedValue([]);
const { useConnectionStore } = await import("@/stores/connectionStore");
const store = useConnectionStore();
store.connections = [previewConnection({ id: "removed-1", name: "Removed", one_time: false })];
await store.initFromDisk();
expect(store.getConfig("removed-1")).toBeUndefined();
expect(store.connections).toEqual([]);
});
it("removeConnection leaves saved connections to the save_connections sync", async () => {
installApiMocks();
const { useConnectionStore } = await import("@/stores/connectionStore");
+8 -2
View File
@@ -8035,8 +8035,14 @@ export const useConnectionStore = defineStore("connection", () => {
const [pinnedOrder, saved] = await Promise.all([loadPinnedTreeNodeOrder(), api.loadConnections(), tunnelProfileStore.init()]);
setPinnedTreeNodeOrder(pinnedOrder);
await migrateTimeoutInheritance(saved);
connections.value = saved.map(normalizeConnection);
if (connections.value.some((connection, index) => (connection.connect_timeout_inherit === true && connection.connect_timeout_secs !== saved[index]?.connect_timeout_secs) || (connection.query_timeout_inherit === true && connection.query_timeout_secs !== saved[index]?.query_timeout_secs))) {
const loadedConnections = saved.map(normalizeConnection);
const loadedIds = new Set(loadedConnections.map((connection) => connection.id));
// One-time deep-link connections are intentionally filtered from disk
// persistence. Keep them in the live list when an unrelated disk reload
// (for example, the scheduled-backup poll) completes while they are open.
const runtimeOneTimeConnections = connections.value.filter((connection) => connection.one_time === true && !loadedIds.has(connection.id));
connections.value = [...loadedConnections, ...runtimeOneTimeConnections];
if (loadedConnections.some((connection, index) => (connection.connect_timeout_inherit === true && connection.connect_timeout_secs !== saved[index]?.connect_timeout_secs) || (connection.query_timeout_inherit === true && connection.query_timeout_secs !== saved[index]?.query_timeout_secs))) {
await persistConnections();
}
syncTimeoutInheritanceBackup();