From e2ca8cb3b1e9ed9488e4d66c8ce6c9822512f174 Mon Sep 17 00:00:00 2001 From: Claude Date: Mon, 16 Feb 2026 09:20:10 +0000 Subject: [PATCH] fix: migrate auth preferences from Dexie to localStorage MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit One-time migration preserves existing user preferences: reads from Dexie relayAuthPreferences table, writes to localStorage, injects into the running manager, then clears the Dexie table. Skips if localStorage already has data (idempotent). Removes the DexieAuthStorage adapter — sync/async impedance mismatch made it fragile. localStorage is the right fit for the sync getItem/setItem interface. https://claude.ai/code/session_01XqrjeQVtJKw9uC1XAw6rqd --- src/services/relay-auth.ts | 52 +++++++++++++++++++++++++++++++++++--- 1 file changed, 48 insertions(+), 4 deletions(-) diff --git a/src/services/relay-auth.ts b/src/services/relay-auth.ts index d832c63..10da6b5 100644 --- a/src/services/relay-auth.ts +++ b/src/services/relay-auth.ts @@ -1,9 +1,52 @@ import { map } from "rxjs/operators"; import { RelayAuthManager } from "relay-auth-manager"; -import type { AuthSigner } from "relay-auth-manager"; +import type { AuthSigner, AuthPreference } from "relay-auth-manager"; import { canAccountSign } from "@/hooks/useAccount"; import pool from "./relay-pool"; import accountManager from "./accounts"; +import db from "./db"; + +const STORAGE_KEY = "relay-auth-preferences"; + +/** + * One-time migration: move auth preferences from Dexie to localStorage. + * Runs in the background on first load. After migration, Dexie rows are + * cleared so it doesn't run again. + */ +function migrateFromDexie() { + // Skip if localStorage already has preferences (already migrated) + if (localStorage.getItem(STORAGE_KEY)) return; + + db.relayAuthPreferences + .toArray() + .then((rows) => { + if (rows.length === 0) return; + + const prefs: Record = {}; + for (const row of rows) { + if ( + row.preference === "always" || + row.preference === "never" || + row.preference === "ask" + ) { + prefs[row.url] = row.preference; + } + } + + localStorage.setItem(STORAGE_KEY, JSON.stringify(prefs)); + + // Inject into the already-running manager + for (const [url, pref] of Object.entries(prefs)) { + relayAuthManager.setPreference(url, pref as AuthPreference); + } + + // Clean up Dexie table + db.relayAuthPreferences.clear(); + }) + .catch(() => { + // Ignore migration errors — user just re-answers prompts + }); +} /** * Singleton RelayAuthManager instance for Grimoire. @@ -23,10 +66,11 @@ const relayAuthManager = new RelayAuthManager({ }), ), - // Use localStorage for preference persistence storage: localStorage, - - // Use "relay-auth-preferences" key (default) + storageKey: STORAGE_KEY, }); +// Run one-time migration from Dexie → localStorage +migrateFromDexie(); + export default relayAuthManager;