Skip to content

Commit 3e34301

Browse files
committed
feat(auth): rework auth hooks
1 parent 848f651 commit 3e34301

6 files changed

+134
-103
lines changed

packages/auth/src/index.ts

+5-2
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,6 @@
11
export * from "./useAuthUser";
2-
export * from "./useAuthQuery";
3-
export * from "./useAuthMutation";
2+
export * from "./useAuthIdToken";
3+
export * from "./useAuthFetchSignInMethodsForEmail";
4+
export * from "./useAuthGetRedirectResult";
5+
6+
export * from "./mutations";
File renamed without changes.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
import {
2+
QueryKey,
3+
useQuery,
4+
UseQueryOptions,
5+
UseQueryResult,
6+
} from "react-query";
7+
import { Auth, fetchSignInMethodsForEmail, AuthError } from "firebase/auth";
8+
9+
export function useAuthFetchSignInMethodsForEmail(
10+
key: QueryKey,
11+
auth: Auth,
12+
email: string,
13+
useQueryOptions?: Omit<UseQueryOptions<string[], AuthError>, "queryFn">
14+
): UseQueryResult<string[], AuthError> {
15+
return useQuery<string[], AuthError>({
16+
...useQueryOptions,
17+
queryKey: useQueryOptions?.queryKey ?? key,
18+
async queryFn() {
19+
return fetchSignInMethodsForEmail(auth, email);
20+
},
21+
});
22+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
import {
2+
QueryKey,
3+
useQuery,
4+
UseQueryOptions,
5+
UseQueryResult,
6+
} from "react-query";
7+
import {
8+
Auth,
9+
AuthError,
10+
UserCredential,
11+
getRedirectResult,
12+
PopupRedirectResolver,
13+
} from "firebase/auth";
14+
15+
export function useAuthGetRedirectResult(
16+
key: QueryKey,
17+
auth: Auth,
18+
resolver?: PopupRedirectResolver,
19+
useQueryOptions?: Omit<
20+
UseQueryOptions<UserCredential | null, AuthError>,
21+
"queryFn"
22+
>
23+
): UseQueryResult<UserCredential | null, AuthError> {
24+
return useQuery<UserCredential | null, AuthError>({
25+
...useQueryOptions,
26+
queryKey: useQueryOptions?.queryKey ?? key,
27+
async queryFn() {
28+
return getRedirectResult(auth, resolver);
29+
},
30+
});
31+
}

packages/auth/src/useAuthIdToken.ts

+76
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
import { useEffect, useRef } from "react";
2+
import {
3+
hashQueryKey,
4+
QueryKey,
5+
useQuery,
6+
useQueryClient,
7+
UseQueryOptions,
8+
UseQueryResult,
9+
} from "react-query";
10+
import { Auth, Unsubscribe, IdTokenResult, AuthError } from "firebase/auth";
11+
12+
import { Completer } from "../../utils/src";
13+
14+
const counts: { [key: string]: number } = {};
15+
const subscriptions: { [key: string]: Unsubscribe } = {};
16+
17+
export function useAuthIdToken<R = IdTokenResult | null>(
18+
key: QueryKey,
19+
auth: Auth,
20+
options?: {
21+
forceRefresh?: boolean;
22+
},
23+
useQueryOptions?: Omit<
24+
UseQueryOptions<IdTokenResult | null, AuthError, R>,
25+
"queryFn"
26+
>
27+
): UseQueryResult<R, AuthError> {
28+
const client = useQueryClient();
29+
const completer = useRef<Completer<IdTokenResult | null>>(new Completer());
30+
31+
const hashFn = useQueryOptions?.queryKeyHashFn || hashQueryKey;
32+
const hash = hashFn(key);
33+
34+
useEffect(() => {
35+
counts[hash] ??= 0;
36+
counts[hash]++;
37+
38+
// If there is only one instance of this query key, subscribe
39+
if (counts[hash] === 1) {
40+
subscriptions[hash] = auth.onIdTokenChanged(async (user) => {
41+
let token: IdTokenResult | null = null;
42+
43+
if (user) {
44+
token = await user.getIdTokenResult(options?.forceRefresh);
45+
}
46+
47+
// Set the data each time state changes.
48+
client.setQueryData<IdTokenResult | null>(key, token);
49+
50+
// Resolve the completer with the current data.
51+
if (!completer.current!.completed) {
52+
completer.current!.complete(token);
53+
}
54+
});
55+
} else {
56+
// Since there is already an active subscription, resolve the completer
57+
// with the cached data.
58+
completer.current!.complete(client.getQueryData(key) as IdTokenResult | null);
59+
}
60+
61+
return () => {
62+
counts[hash]--;
63+
64+
if (counts[hash] === 0) {
65+
subscriptions[hash]();
66+
delete subscriptions[hash];
67+
}
68+
};
69+
}, [hash, completer]);
70+
71+
return useQuery<IdTokenResult | null, AuthError, R>({
72+
...useQueryOptions,
73+
queryKey: useQueryOptions?.queryKey ?? key,
74+
queryFn: () => completer.current!.promise,
75+
});
76+
}

packages/auth/src/useAuthQuery.ts

-101
This file was deleted.

0 commit comments

Comments
 (0)