From ea4e57b60261d18dae3f36c126baec694e1670b0 Mon Sep 17 00:00:00 2001 From: Christian Byrne Date: Thu, 18 Sep 2025 11:18:05 -0700 Subject: [PATCH] Move VueFire persistence configuration to initialization (#5614) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Currently, we set persistence method in the auth store setup. This creates pattern of using the default on init (indexed DB) up until the firebase store is initialized and `setPersistence` is called. For devices that don't support indexed DB or have the connection aggresively terminated or cleared, like [Safari](https://comfy-org.sentry.io/issues/6879071102/?project=4509681221369857&query=is%3Aunresolved&referrer=issue-stream), this can create problems with maintaing auth persistence. Fix by setting persistence method in the initialization in main.ts ┆Issue is synchronized with this [Notion page](https://www.notion.so/PR-5614-Move-VueFire-persistence-configuration-to-initialization-2716d73d3650817480e0c8feb1f37b9a) by [Unito](https://www.unito.io) --------- Co-authored-by: Claude --- src/main.ts | 21 +++++++++++++++++-- src/stores/firebaseAuthStore.ts | 4 ---- .../tests/store/firebaseAuthStore.test.ts | 7 ------- 3 files changed, 19 insertions(+), 13 deletions(-) diff --git a/src/main.ts b/src/main.ts index b15d4067f..267de4f44 100644 --- a/src/main.ts +++ b/src/main.ts @@ -2,6 +2,11 @@ import { definePreset } from '@primevue/themes' import Aura from '@primevue/themes/aura' import * as Sentry from '@sentry/vue' import { initializeApp } from 'firebase/app' +import { + browserLocalPersistence, + browserSessionPersistence, + indexedDBLocalPersistence +} from 'firebase/auth' import { createPinia } from 'pinia' import 'primeicons/primeicons.css' import PrimeVue from 'primevue/config' @@ -9,7 +14,7 @@ import ConfirmationService from 'primevue/confirmationservice' import ToastService from 'primevue/toastservice' import Tooltip from 'primevue/tooltip' import { createApp } from 'vue' -import { VueFire, VueFireAuth } from 'vuefire' +import { VueFire, VueFireAuthWithDependencies } from 'vuefire' import { FIREBASE_CONFIG } from '@/config/firebase' import '@/lib/litegraph/public/css/litegraph.css' @@ -66,6 +71,18 @@ app .use(i18n) .use(VueFire, { firebaseApp, - modules: [VueFireAuth()] + modules: [ + // Configure Firebase Auth persistence: localStorage first, IndexedDB last. + // Localstorage is preferred to IndexedDB for mobile Safari compatibility. + VueFireAuthWithDependencies({ + dependencies: { + persistence: [ + browserLocalPersistence, + browserSessionPersistence, + indexedDBLocalPersistence + ] + } + }) + ] }) .mount('#vue-app') diff --git a/src/stores/firebaseAuthStore.ts b/src/stores/firebaseAuthStore.ts index 8225b1f33..f2c75417c 100644 --- a/src/stores/firebaseAuthStore.ts +++ b/src/stores/firebaseAuthStore.ts @@ -6,12 +6,10 @@ import { GoogleAuthProvider, type User, type UserCredential, - browserLocalPersistence, createUserWithEmailAndPassword, deleteUser, onAuthStateChanged, sendPasswordResetEmail, - setPersistence, signInWithEmailAndPassword, signInWithPopup, signOut, @@ -80,8 +78,6 @@ export const useFirebaseAuthStore = defineStore('firebaseAuth', () => { // Retrieves the Firebase Auth instance. Returns `null` on the server. // When using this function on the client in TypeScript, you can force the type with `useFirebaseAuth()!`. const auth = useFirebaseAuth()! - // Set persistence to localStorage (works in both browser and Electron) - void setPersistence(auth, browserLocalPersistence) onAuthStateChanged(auth, (user) => { currentUser.value = user diff --git a/tests-ui/tests/store/firebaseAuthStore.test.ts b/tests-ui/tests/store/firebaseAuthStore.test.ts index ffe7a8d99..fee66d3f7 100644 --- a/tests-ui/tests/store/firebaseAuthStore.test.ts +++ b/tests-ui/tests/store/firebaseAuthStore.test.ts @@ -148,13 +148,6 @@ describe('useFirebaseAuthStore', () => { expect(store.loading).toBe(false) }) - it('should set persistence to local storage on initialization', () => { - expect(firebaseAuth.setPersistence).toHaveBeenCalledWith( - mockAuth, - firebaseAuth.browserLocalPersistence - ) - }) - it('should properly clean up error state between operations', async () => { // First, cause an error const mockError = new Error('Invalid password')