1
- import { FirebaseApp } from 'firebase/app'
1
+ import type { FirebaseApp } from 'firebase/app'
2
2
import { getAuth , onIdTokenChanged , User } from 'firebase/auth'
3
3
import { inject , InjectionKey , Ref } from 'vue'
4
+ import { useFirebaseApp } from '../app'
5
+ import type { _Nullable } from '../shared'
4
6
5
7
export const AuthUserInjectSymbol : InjectionKey < Ref < User | null | undefined > > =
6
8
Symbol ( 'user' )
@@ -14,23 +16,67 @@ export function useCurrentUser() {
14
16
return inject ( AuthUserInjectSymbol ) !
15
17
}
16
18
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
+
17
64
export function setupOnAuthStateChanged (
18
- user : Ref < User | null | undefined > ,
65
+ user : Ref < _Nullable < User > > ,
19
66
app ?: FirebaseApp
20
67
) {
21
68
const auth = getAuth ( app )
22
- let resolve ! : ( value : User | null ) => void
23
- const isReady = new Promise ( ( _resolve ) => {
24
- resolve = _resolve
25
- } )
26
69
27
70
// onAuthStateChanged doesn't trigger in all scenarios like when the user goes links an existing account and their
28
71
// data is updated
29
72
// https://github.com/firebase/firebase-js-sdk/issues/4227
30
73
onIdTokenChanged ( auth , ( userData ) => {
74
+ const userOrPromise = _getCurrentUserState ( )
31
75
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
+ }
33
81
} )
34
-
35
- return { isReady }
36
82
}
0 commit comments