1- import { FirebaseApp } from 'firebase/app'
1+ import type { FirebaseApp } from 'firebase/app'
22import { getAuth , onIdTokenChanged , User } from 'firebase/auth'
33import { inject , InjectionKey , Ref } from 'vue'
4+ import { useFirebaseApp } from '../app'
5+ import type { _Nullable } from '../shared'
46
57export const AuthUserInjectSymbol : InjectionKey < Ref < User | null | undefined > > =
68 Symbol ( 'user' )
@@ -14,23 +16,67 @@ export function useCurrentUser() {
1416 return inject ( AuthUserInjectSymbol ) !
1517}
1618
19+ // @internal
20+ type _UserState =
21+ // state 1 waiting for the initial load
22+ | [ Promise < _Nullable < User > > , ( user : Ref < _Nullable < User > > ) => void ]
23+ // state 2 loaded
24+ | Ref < _Nullable < User > >
25+
26+ const initialUserMap = new WeakMap < FirebaseApp , _UserState > ( )
27+
28+ // @internal
29+ function _getCurrentUserState ( ) {
30+ const firebaseApp = useFirebaseApp ( )
31+ if ( ! initialUserMap . has ( firebaseApp ) ) {
32+ let resolve ! : ( resolvedUser : _Nullable < User > ) => void
33+ const promise = new Promise < _Nullable < User > > ( ( _resolve ) => {
34+ resolve = _resolve
35+ } )
36+
37+ const userState : _UserState = [
38+ promise ,
39+ ( user : Ref < _Nullable < User > > ) => {
40+ initialUserMap . set ( firebaseApp , user )
41+ // resolve the actual promise
42+ resolve ( user . value )
43+ } ,
44+ ]
45+
46+ initialUserMap . set ( firebaseApp , userState )
47+ }
48+
49+ return initialUserMap . get ( firebaseApp ) !
50+ }
51+
52+ /**
53+ * Returns a promise that resolves the current user once the user is loaded. Must be called after the firebase app is
54+ * initialized.
55+ */
56+ export function getCurrentUser ( ) : Promise < _Nullable < User > > {
57+ const userOrPromise = _getCurrentUserState ( )
58+
59+ return Array . isArray ( userOrPromise )
60+ ? userOrPromise [ 0 ]
61+ : Promise . resolve ( userOrPromise . value )
62+ }
63+
1764export function setupOnAuthStateChanged (
18- user : Ref < User | null | undefined > ,
65+ user : Ref < _Nullable < User > > ,
1966 app ?: FirebaseApp
2067) {
2168 const auth = getAuth ( app )
22- let resolve ! : ( value : User | null ) => void
23- const isReady = new Promise ( ( _resolve ) => {
24- resolve = _resolve
25- } )
2669
2770 // onAuthStateChanged doesn't trigger in all scenarios like when the user goes links an existing account and their
2871 // data is updated
2972 // https://github.com/firebase/firebase-js-sdk/issues/4227
3073 onIdTokenChanged ( auth , ( userData ) => {
74+ const userOrPromise = _getCurrentUserState ( )
3175 user . value = userData
32- resolve ( userData )
76+ // setup the initial user
77+ // afterwards, this will never be an array
78+ if ( Array . isArray ( userOrPromise ) ) {
79+ userOrPromise [ 1 ] ( user )
80+ }
3381 } )
34-
35- return { isReady }
3682}
0 commit comments