Move VueFire persistence configuration to initialization (#5614)

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 <noreply@anthropic.com>
This commit is contained in:
Christian Byrne
2025-09-18 11:18:05 -07:00
committed by GitHub
parent 4789d86fe8
commit ea4e57b602
3 changed files with 19 additions and 13 deletions

View File

@@ -2,6 +2,11 @@ import { definePreset } from '@primevue/themes'
import Aura from '@primevue/themes/aura' import Aura from '@primevue/themes/aura'
import * as Sentry from '@sentry/vue' import * as Sentry from '@sentry/vue'
import { initializeApp } from 'firebase/app' import { initializeApp } from 'firebase/app'
import {
browserLocalPersistence,
browserSessionPersistence,
indexedDBLocalPersistence
} from 'firebase/auth'
import { createPinia } from 'pinia' import { createPinia } from 'pinia'
import 'primeicons/primeicons.css' import 'primeicons/primeicons.css'
import PrimeVue from 'primevue/config' import PrimeVue from 'primevue/config'
@@ -9,7 +14,7 @@ import ConfirmationService from 'primevue/confirmationservice'
import ToastService from 'primevue/toastservice' import ToastService from 'primevue/toastservice'
import Tooltip from 'primevue/tooltip' import Tooltip from 'primevue/tooltip'
import { createApp } from 'vue' import { createApp } from 'vue'
import { VueFire, VueFireAuth } from 'vuefire' import { VueFire, VueFireAuthWithDependencies } from 'vuefire'
import { FIREBASE_CONFIG } from '@/config/firebase' import { FIREBASE_CONFIG } from '@/config/firebase'
import '@/lib/litegraph/public/css/litegraph.css' import '@/lib/litegraph/public/css/litegraph.css'
@@ -66,6 +71,18 @@ app
.use(i18n) .use(i18n)
.use(VueFire, { .use(VueFire, {
firebaseApp, 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') .mount('#vue-app')

View File

@@ -6,12 +6,10 @@ import {
GoogleAuthProvider, GoogleAuthProvider,
type User, type User,
type UserCredential, type UserCredential,
browserLocalPersistence,
createUserWithEmailAndPassword, createUserWithEmailAndPassword,
deleteUser, deleteUser,
onAuthStateChanged, onAuthStateChanged,
sendPasswordResetEmail, sendPasswordResetEmail,
setPersistence,
signInWithEmailAndPassword, signInWithEmailAndPassword,
signInWithPopup, signInWithPopup,
signOut, signOut,
@@ -80,8 +78,6 @@ export const useFirebaseAuthStore = defineStore('firebaseAuth', () => {
// Retrieves the Firebase Auth instance. Returns `null` on the server. // 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()!`. // When using this function on the client in TypeScript, you can force the type with `useFirebaseAuth()!`.
const auth = useFirebaseAuth()! const auth = useFirebaseAuth()!
// Set persistence to localStorage (works in both browser and Electron)
void setPersistence(auth, browserLocalPersistence)
onAuthStateChanged(auth, (user) => { onAuthStateChanged(auth, (user) => {
currentUser.value = user currentUser.value = user

View File

@@ -148,13 +148,6 @@ describe('useFirebaseAuthStore', () => {
expect(store.loading).toBe(false) 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 () => { it('should properly clean up error state between operations', async () => {
// First, cause an error // First, cause an error
const mockError = new Error('Invalid password') const mockError = new Error('Invalid password')