react-query-firebase 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (130) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +44 -0
  3. package/dist/src/FirebaseContext.d.ts +13 -0
  4. package/dist/src/FirebaseContext.js +3 -0
  5. package/dist/src/FirebaseContextProvider.d.ts +28 -0
  6. package/dist/src/FirebaseContextProvider.js +46 -0
  7. package/dist/src/analytics/index.d.ts +1 -0
  8. package/dist/src/analytics/index.js +1 -0
  9. package/dist/src/analytics/useLogEvent.d.ts +10 -0
  10. package/dist/src/analytics/useLogEvent.js +14 -0
  11. package/dist/src/auth/index.d.ts +9 -0
  12. package/dist/src/auth/index.js +9 -0
  13. package/dist/src/auth/mutation-keys.d.ts +7 -0
  14. package/dist/src/auth/mutation-keys.js +19 -0
  15. package/dist/src/auth/useAuthStateReady.d.ts +1 -0
  16. package/dist/src/auth/useAuthStateReady.js +14 -0
  17. package/dist/src/auth/useCreateUserWitEmailAndPasswordMutation.d.ts +8 -0
  18. package/dist/src/auth/useCreateUserWitEmailAndPasswordMutation.js +12 -0
  19. package/dist/src/auth/useCurrentUser.d.ts +1 -0
  20. package/dist/src/auth/useCurrentUser.js +15 -0
  21. package/dist/src/auth/useSendEmailVerificationMutation.d.ts +7 -0
  22. package/dist/src/auth/useSendEmailVerificationMutation.js +10 -0
  23. package/dist/src/auth/useSignInWitEmailAndPasswordMutation.d.ts +8 -0
  24. package/dist/src/auth/useSignInWitEmailAndPasswordMutation.js +12 -0
  25. package/dist/src/auth/useSignInWitRedirectMutation.d.ts +8 -0
  26. package/dist/src/auth/useSignInWitRedirectMutation.js +12 -0
  27. package/dist/src/auth/useSignOutMutation.d.ts +3 -0
  28. package/dist/src/auth/useSignOutMutation.js +12 -0
  29. package/dist/src/auth/useUpdateProfileMutation.d.ts +8 -0
  30. package/dist/src/auth/useUpdateProfileMutation.js +10 -0
  31. package/dist/src/firestore/index.d.ts +14 -0
  32. package/dist/src/firestore/index.js +14 -0
  33. package/dist/src/firestore/useAddDocMutation.d.ts +12 -0
  34. package/dist/src/firestore/useAddDocMutation.js +15 -0
  35. package/dist/src/firestore/useBatchWrite.d.ts +8 -0
  36. package/dist/src/firestore/useBatchWrite.js +14 -0
  37. package/dist/src/firestore/useCollectionReference.d.ts +7 -0
  38. package/dist/src/firestore/useCollectionReference.js +13 -0
  39. package/dist/src/firestore/useCompositeFilter.d.ts +20 -0
  40. package/dist/src/firestore/useCompositeFilter.js +26 -0
  41. package/dist/src/firestore/useCountQuery.d.ts +10 -0
  42. package/dist/src/firestore/useCountQuery.js +17 -0
  43. package/dist/src/firestore/useDeleteDocMutation.d.ts +11 -0
  44. package/dist/src/firestore/useDeleteDocMutation.js +16 -0
  45. package/dist/src/firestore/useDocReference.d.ts +7 -0
  46. package/dist/src/firestore/useDocReference.js +21 -0
  47. package/dist/src/firestore/useDocReferences.d.ts +7 -0
  48. package/dist/src/firestore/useDocReferences.js +15 -0
  49. package/dist/src/firestore/useGetDocData.d.ts +10 -0
  50. package/dist/src/firestore/useGetDocData.js +10 -0
  51. package/dist/src/firestore/useInfiniteQuery.d.ts +11 -0
  52. package/dist/src/firestore/useInfiniteQuery.js +21 -0
  53. package/dist/src/firestore/useQuery.d.ts +11 -0
  54. package/dist/src/firestore/useQuery.js +20 -0
  55. package/dist/src/firestore/useRunTransaction.d.ts +8 -0
  56. package/dist/src/firestore/useRunTransaction.js +12 -0
  57. package/dist/src/firestore/useSetDocMutation.d.ts +11 -0
  58. package/dist/src/firestore/useSetDocMutation.js +16 -0
  59. package/dist/src/firestore/useUpdateDocMutation.d.ts +12 -0
  60. package/dist/src/firestore/useUpdateDocMutation.js +18 -0
  61. package/dist/src/firestore/utils/getDocData.d.ts +4 -0
  62. package/dist/src/firestore/utils/getDocData.js +8 -0
  63. package/dist/src/firestore/utils/getDocRef.d.ts +8 -0
  64. package/dist/src/firestore/utils/getDocRef.js +14 -0
  65. package/dist/src/firestore/utils/getDocSnap.d.ts +4 -0
  66. package/dist/src/firestore/utils/getDocSnap.js +9 -0
  67. package/dist/src/index.d.ts +10 -0
  68. package/dist/src/index.js +10 -0
  69. package/dist/src/remoteConfig/index.d.ts +2 -0
  70. package/dist/src/remoteConfig/index.js +2 -0
  71. package/dist/src/remoteConfig/useFetchAndActivate.d.ts +4 -0
  72. package/dist/src/remoteConfig/useFetchAndActivate.js +22 -0
  73. package/dist/src/remoteConfig/useGetValue.d.ts +1 -0
  74. package/dist/src/remoteConfig/useGetValue.js +9 -0
  75. package/dist/src/useAnalytics.d.ts +1 -0
  76. package/dist/src/useAnalytics.js +6 -0
  77. package/dist/src/useAuth.d.ts +1 -0
  78. package/dist/src/useAuth.js +6 -0
  79. package/dist/src/useFirebase.d.ts +1 -0
  80. package/dist/src/useFirebase.js +6 -0
  81. package/dist/src/useFirestore.d.ts +1 -0
  82. package/dist/src/useFirestore.js +6 -0
  83. package/dist/src/useRemoteConfig.d.ts +1 -0
  84. package/dist/src/useRemoteConfig.js +6 -0
  85. package/package.json +57 -0
  86. package/src/FirebaseContext.ts +18 -0
  87. package/src/FirebaseContextProvider.tsx +91 -0
  88. package/src/analytics/index.ts +1 -0
  89. package/src/analytics/useLogEvent.ts +27 -0
  90. package/src/auth/index.ts +9 -0
  91. package/src/auth/mutation-keys.ts +19 -0
  92. package/src/auth/useAuthStateReady.ts +19 -0
  93. package/src/auth/useCreateUserWitEmailAndPasswordMutation.ts +26 -0
  94. package/src/auth/useCurrentUser.ts +19 -0
  95. package/src/auth/useIdToken.ts +35 -0
  96. package/src/auth/useReauthenticateWitCredentialMutation.ts +23 -0
  97. package/src/auth/useReauthenticateWitRedirectMutation.ts +29 -0
  98. package/src/auth/useSendEmailVerificationMutation.ts +22 -0
  99. package/src/auth/useSignInWitEmailAndPasswordMutation.ts +27 -0
  100. package/src/auth/useSignInWitRedirectMutation.ts +27 -0
  101. package/src/auth/useSignOutMutation.ts +18 -0
  102. package/src/auth/useUpdateProfileMutation.ts +23 -0
  103. package/src/firestore/index.ts +14 -0
  104. package/src/firestore/useAddDocMutation.ts +51 -0
  105. package/src/firestore/useBatchWrite.ts +24 -0
  106. package/src/firestore/useCollectionReference.ts +26 -0
  107. package/src/firestore/useCompositeFilter.ts +68 -0
  108. package/src/firestore/useCountQuery.ts +51 -0
  109. package/src/firestore/useDeleteDocMutation.ts +40 -0
  110. package/src/firestore/useDocReference.ts +44 -0
  111. package/src/firestore/useDocReferences.ts +28 -0
  112. package/src/firestore/useGetDocData.ts +33 -0
  113. package/src/firestore/useInfiniteQuery.ts +84 -0
  114. package/src/firestore/useQuery.ts +58 -0
  115. package/src/firestore/useRunTransaction.ts +24 -0
  116. package/src/firestore/useSetDocMutation.ts +43 -0
  117. package/src/firestore/useUpdateDocMutation copy.ts +51 -0
  118. package/src/firestore/useUpdateDocMutation.ts +55 -0
  119. package/src/firestore/utils/getDocData.ts +25 -0
  120. package/src/firestore/utils/getDocRef.ts +35 -0
  121. package/src/firestore/utils/getDocSnap.ts +25 -0
  122. package/src/index.ts +10 -0
  123. package/src/remoteConfig/index.ts +2 -0
  124. package/src/remoteConfig/useFetchAndActivate.ts +27 -0
  125. package/src/remoteConfig/useGetValue.ts +10 -0
  126. package/src/useAnalytics.ts +8 -0
  127. package/src/useAuth.ts +8 -0
  128. package/src/useFirebase.ts +8 -0
  129. package/src/useFirestore.ts +7 -0
  130. package/src/useRemoteConfig.ts +7 -0
@@ -0,0 +1,27 @@
1
+ import { logEvent } from "firebase/analytics";
2
+ import { useAnalytics } from "../useAnalytics";
3
+ import { useCallback, useMemo } from "react";
4
+
5
+ type UseLogEventOptions = {
6
+ eventName: string;
7
+ eventParams?: {
8
+ [key: string]: unknown;
9
+ };
10
+ };
11
+
12
+ export const useLogEvent = ({ eventName, eventParams }: UseLogEventOptions) => {
13
+ const analytics = useAnalytics();
14
+
15
+ const logEventCallback = useCallback(() => {
16
+ if (analytics) {
17
+ logEvent(analytics, eventName, eventParams);
18
+ }
19
+ }, [eventName, eventParams]);
20
+
21
+ return useMemo(
22
+ () => ({
23
+ logEvent: logEventCallback
24
+ }),
25
+ [logEventCallback]
26
+ );
27
+ };
@@ -0,0 +1,9 @@
1
+ export * from "./mutation-keys";
2
+ export * from "./useCreateUserWitEmailAndPasswordMutation";
3
+ export * from "./useSendEmailVerificationMutation";
4
+ export * from "./useSignInWitEmailAndPasswordMutation";
5
+ export * from "./useCurrentUser";
6
+ export * from "./useAuthStateReady";
7
+ export * from "./useSignInWitRedirectMutation";
8
+ export * from "./useUpdateProfileMutation";
9
+ export * from "./useSignOutMutation";
@@ -0,0 +1,19 @@
1
+ export const CREATE_USER_WITH_EMAIL_AND_PASSWORD_MUTATION_KEY = [
2
+ "FIREBASE",
3
+ "AUTH",
4
+ "CREATE_USER_WITH_EMAIL_AND_PASSWORD_MUTATION"
5
+ ] as const;
6
+ export const SEND_EMAIL_VERIFICATION_MUTATION_KEY = ["FIREBASE", "AUTH", "SEND_EMAIL_VERIFICATION_MUTATION"] as const;
7
+ export const SIGN_IN_WITH_EMAIL_AND_PASSWORD_MUTATION_KEY = [
8
+ "FIREBASE",
9
+ "AUTH",
10
+ "SIGN_IN_WITH_EMAIL_AND_PASSWORD_MUTATION"
11
+ ] as const;
12
+ export const SIGN_IN_WITH_REDIRECT_MUTATION_KEY = ["FIREBASE", "AUTH", "SIGN_IN_WITH_REDIRECT_MUTATION"] as const;
13
+ export const SIGN_OUT_MUTATION_KEY = ["FIREBASE", "AUTH", "SIGN_OUT"] as const;
14
+ export const REAUTHENTICATE_WITH_REDIRECT_MUTATION_KEY = ["FIREBASE", "AUTH", "REAUTHENTICATE_WITH_REDIRECT"] as const;
15
+ export const REAUTHENTICATE_WITH_CREDENTIAL_MUTATION_KEY = [
16
+ "FIREBASE",
17
+ "AUTH",
18
+ "REAUTHENTICATE_WITH_CREDENTIAL"
19
+ ] as const;
@@ -0,0 +1,19 @@
1
+ import { useAuth } from "../useAuth";
2
+ import { useCallback, useEffect, useState } from "react";
3
+
4
+ export const useAuthStateReady = () => {
5
+ const firebaseAuth = useAuth();
6
+
7
+ const [isAuthStateReady, setIsAuthStateReady] = useState(false);
8
+
9
+ const callback = useCallback(async () => {
10
+ await firebaseAuth.authStateReady();
11
+ setIsAuthStateReady(true);
12
+ }, [isAuthStateReady]);
13
+
14
+ useEffect(() => {
15
+ callback();
16
+ }, [callback]);
17
+
18
+ return isAuthStateReady;
19
+ };
@@ -0,0 +1,26 @@
1
+ import { useMutation, UseMutationOptions } from "@tanstack/react-query";
2
+ import { createUserWithEmailAndPassword, UserCredential } from "firebase/auth";
3
+ import { useAuth } from "../useAuth";
4
+ import { FirebaseError } from "firebase/app";
5
+ import { CREATE_USER_WITH_EMAIL_AND_PASSWORD_MUTATION_KEY } from "./mutation-keys";
6
+
7
+ export type UseCreateUserWitEmailAndPasswordMutationVariables = {
8
+ email: string;
9
+ password: string;
10
+ };
11
+
12
+ export const useCreateUserWitEmailAndPasswordMutation = <TContext = unknown>(
13
+ options: Omit<
14
+ UseMutationOptions<UserCredential, FirebaseError, UseCreateUserWitEmailAndPasswordMutationVariables, TContext>,
15
+ "mutationKey" | "mutationFn"
16
+ > = {}
17
+ ) => {
18
+ const firebaseAuth = useAuth();
19
+
20
+ return useMutation({
21
+ ...options,
22
+ mutationFn: async ({ email, password }: UseCreateUserWitEmailAndPasswordMutationVariables) =>
23
+ await createUserWithEmailAndPassword(firebaseAuth, email, password),
24
+ mutationKey: CREATE_USER_WITH_EMAIL_AND_PASSWORD_MUTATION_KEY
25
+ });
26
+ };
@@ -0,0 +1,19 @@
1
+ import { useAuth } from "../useAuth";
2
+ import { useEffect, useState } from "react";
3
+
4
+ export const useCurrentUser = () => {
5
+ const firebaseAuth = useAuth();
6
+
7
+ const [currentUser, setCurrentUser] = useState(firebaseAuth.currentUser);
8
+
9
+ useEffect(() => {
10
+ const unsubscribe = firebaseAuth.onAuthStateChanged((user) => {
11
+ setCurrentUser(user);
12
+ });
13
+ return () => {
14
+ unsubscribe();
15
+ };
16
+ }, [currentUser?.uid ?? ""]);
17
+
18
+ return currentUser;
19
+ };
@@ -0,0 +1,35 @@
1
+ import { useCallback, useEffect, useState } from "react";
2
+ import { useCurrentUser } from "./useCurrentUser";
3
+
4
+ export const useIdToken = () => {
5
+ const currentUser = useCurrentUser();
6
+ const [idToken, setIdToken] = useState("");
7
+
8
+ const callback = useCallback(async () => {
9
+ if (!currentUser) {
10
+ setIdToken("");
11
+ return;
12
+ }
13
+
14
+ const idToken = await currentUser.getIdToken();
15
+ setIdToken(idToken);
16
+ }, [currentUser, idToken]);
17
+
18
+ const refresh = useCallback(async () => {
19
+ if (!currentUser) {
20
+ return;
21
+ }
22
+
23
+ const idToken = await currentUser.getIdToken(true);
24
+ setIdToken(idToken);
25
+ }, [currentUser, idToken]);
26
+
27
+ useEffect(() => {
28
+ callback();
29
+ }, [currentUser?.uid ?? ""]);
30
+
31
+ return {
32
+ idToken,
33
+ refresh
34
+ };
35
+ };
@@ -0,0 +1,23 @@
1
+ import { useMutation, UseMutationOptions } from "@tanstack/react-query";
2
+ import { reauthenticateWithCredential, User, AuthCredential, UserCredential } from "firebase/auth";
3
+ import { REAUTHENTICATE_WITH_CREDENTIAL_MUTATION_KEY } from "./mutation-keys";
4
+ import { FirebaseError } from "firebase/app";
5
+
6
+ export type UseReauthenticateWitCredentialMutationVariables = {
7
+ credential: AuthCredential;
8
+ user: User;
9
+ };
10
+
11
+ export const useReauthenticateWitCredentialMutation = <TContext = unknown>(
12
+ options: Omit<
13
+ UseMutationOptions<UserCredential, FirebaseError, UseReauthenticateWitCredentialMutationVariables, TContext>,
14
+ "mutationKey" | "mutationFn"
15
+ > = {}
16
+ ) => {
17
+ return useMutation({
18
+ ...options,
19
+ mutationFn: async ({ credential, user }: UseReauthenticateWitCredentialMutationVariables) =>
20
+ reauthenticateWithCredential(user, credential),
21
+ mutationKey: REAUTHENTICATE_WITH_CREDENTIAL_MUTATION_KEY
22
+ });
23
+ };
@@ -0,0 +1,29 @@
1
+ import { useMutation, UseMutationOptions } from "@tanstack/react-query";
2
+ import { reauthenticateWithRedirect, AuthProvider, PopupRedirectResolver, User } from "firebase/auth";
3
+
4
+ import { REAUTHENTICATE_WITH_REDIRECT_MUTATION_KEY } from "./mutation-keys";
5
+ import { FirebaseError } from "firebase/app";
6
+
7
+ export type UseReauthenticateWitRedirectMutationVariables = {
8
+ authProvider: AuthProvider;
9
+ popupRedirectResolver?: PopupRedirectResolver;
10
+ user: User;
11
+ };
12
+
13
+ export const useReauthenticateWitRedirectMutation = <TContext = unknown>(
14
+ options: Omit<
15
+ UseMutationOptions<void, FirebaseError, UseReauthenticateWitRedirectMutationVariables, TContext>,
16
+ "mutationKey" | "mutationFn"
17
+ > = {}
18
+ ) => {
19
+ return useMutation({
20
+ ...options,
21
+ mutationFn: async ({
22
+ authProvider,
23
+ user,
24
+ popupRedirectResolver
25
+ }: UseReauthenticateWitRedirectMutationVariables) =>
26
+ reauthenticateWithRedirect(user, authProvider, popupRedirectResolver),
27
+ mutationKey: REAUTHENTICATE_WITH_REDIRECT_MUTATION_KEY
28
+ });
29
+ };
@@ -0,0 +1,22 @@
1
+ import { useMutation, UseMutationOptions } from "@tanstack/react-query";
2
+ import { sendEmailVerification, User } from "firebase/auth";
3
+
4
+ import { SEND_EMAIL_VERIFICATION_MUTATION_KEY } from "./mutation-keys";
5
+ import { FirebaseError } from "firebase/app";
6
+
7
+ export type UseSendEmailVerificationMutationVariables = {
8
+ user: User;
9
+ };
10
+
11
+ export const useSendEmailVerificationMutation = <TContext = unknown>(
12
+ options: Omit<
13
+ UseMutationOptions<void, FirebaseError, UseSendEmailVerificationMutationVariables, TContext>,
14
+ "queryKey" | "queryFn"
15
+ > = {}
16
+ ) => {
17
+ return useMutation({
18
+ ...options,
19
+ mutationFn: async ({ user }) => await sendEmailVerification(user),
20
+ mutationKey: SEND_EMAIL_VERIFICATION_MUTATION_KEY
21
+ });
22
+ };
@@ -0,0 +1,27 @@
1
+ import { useMutation, UseMutationOptions } from "@tanstack/react-query";
2
+ import { signInWithEmailAndPassword, UserCredential } from "firebase/auth";
3
+
4
+ import { useAuth } from "../useAuth";
5
+ import { SIGN_IN_WITH_EMAIL_AND_PASSWORD_MUTATION_KEY } from "./mutation-keys";
6
+ import { FirebaseError } from "firebase/app";
7
+
8
+ export type UseSignInWitEmailAndPasswordMutationVariables = {
9
+ email: string;
10
+ password: string;
11
+ };
12
+
13
+ export const useSignInWitEmailAndPasswordMutation = <TContext = unknown>(
14
+ options: Omit<
15
+ UseMutationOptions<UserCredential, FirebaseError, UseSignInWitEmailAndPasswordMutationVariables, TContext>,
16
+ "mutationKey" | "mutationFn"
17
+ > = {}
18
+ ) => {
19
+ const firebaseAuth = useAuth();
20
+
21
+ return useMutation({
22
+ ...options,
23
+ mutationFn: async ({ email, password }: UseSignInWitEmailAndPasswordMutationVariables) =>
24
+ signInWithEmailAndPassword(firebaseAuth, email, password),
25
+ mutationKey: SIGN_IN_WITH_EMAIL_AND_PASSWORD_MUTATION_KEY
26
+ });
27
+ };
@@ -0,0 +1,27 @@
1
+ import { useMutation, UseMutationOptions } from "@tanstack/react-query";
2
+ import { signInWithRedirect, AuthProvider, PopupRedirectResolver } from "firebase/auth";
3
+
4
+ import { useAuth } from "../useAuth";
5
+ import { SIGN_IN_WITH_REDIRECT_MUTATION_KEY } from "./mutation-keys";
6
+ import { FirebaseError } from "firebase/app";
7
+
8
+ export type UseSignInWitRedirectMutationVariables = {
9
+ authProvider: AuthProvider;
10
+ popupRedirectResolver?: PopupRedirectResolver;
11
+ };
12
+
13
+ export const useSignInWitRedirectMutation = <TContext = unknown>(
14
+ options: Omit<
15
+ UseMutationOptions<void, FirebaseError, UseSignInWitRedirectMutationVariables, TContext>,
16
+ "mutationKey" | "mutationFn"
17
+ > = {}
18
+ ) => {
19
+ const firebaseAuth = useAuth();
20
+
21
+ return useMutation({
22
+ ...options,
23
+ mutationFn: async ({ authProvider, popupRedirectResolver }: UseSignInWitRedirectMutationVariables) =>
24
+ signInWithRedirect(firebaseAuth, authProvider, popupRedirectResolver),
25
+ mutationKey: SIGN_IN_WITH_REDIRECT_MUTATION_KEY
26
+ });
27
+ };
@@ -0,0 +1,18 @@
1
+ import { useMutation, UseMutationOptions } from "@tanstack/react-query";
2
+ import { signOut } from "firebase/auth";
3
+
4
+ import { SIGN_OUT_MUTATION_KEY } from "./mutation-keys";
5
+ import { FirebaseError } from "firebase/app";
6
+ import { useAuth } from "../useAuth";
7
+
8
+ export const useSignOutMutation = <TContext = unknown>(
9
+ options: Omit<UseMutationOptions<void, FirebaseError, void, TContext>, "queryKey" | "queryFn"> = {}
10
+ ) => {
11
+ const firebaseAuth = useAuth();
12
+
13
+ return useMutation({
14
+ ...options,
15
+ mutationFn: async () => await signOut(firebaseAuth),
16
+ mutationKey: SIGN_OUT_MUTATION_KEY
17
+ });
18
+ };
@@ -0,0 +1,23 @@
1
+ import { useMutation, UseMutationOptions } from "@tanstack/react-query";
2
+ import { updateProfile, User } from "firebase/auth";
3
+ import { FirebaseError } from "firebase/app";
4
+ import { CREATE_USER_WITH_EMAIL_AND_PASSWORD_MUTATION_KEY } from "./mutation-keys";
5
+
6
+ export type UseUpdateProfileMutationVariables = {
7
+ displayName?: string;
8
+ user: User;
9
+ };
10
+
11
+ export const useUpdateProfileMutation = <TContext = unknown>(
12
+ options: Omit<
13
+ UseMutationOptions<void, FirebaseError, UseUpdateProfileMutationVariables, TContext>,
14
+ "mutationKey" | "mutationFn"
15
+ > = {}
16
+ ) => {
17
+ return useMutation({
18
+ ...options,
19
+ mutationFn: async ({ displayName, user }: UseUpdateProfileMutationVariables) =>
20
+ await updateProfile(user, { displayName }),
21
+ mutationKey: CREATE_USER_WITH_EMAIL_AND_PASSWORD_MUTATION_KEY
22
+ });
23
+ };
@@ -0,0 +1,14 @@
1
+ export * from "./useAddDocMutation";
2
+ export * from "./useBatchWrite";
3
+ export * from "./useCollectionReference";
4
+ export * from "./useCompositeFilter";
5
+ export * from "./useCountQuery";
6
+ export * from "./useDeleteDocMutation";
7
+ export * from "./useDocReference";
8
+ export * from "./useDocReferences";
9
+ export * from "./useGetDocData";
10
+ export * from "./useInfiniteQuery";
11
+ export * from "./useQuery";
12
+ export * from "./useRunTransaction";
13
+ export * from "./useSetDocMutation";
14
+ export * from "./useUpdateDocMutation";
@@ -0,0 +1,51 @@
1
+ import { useMutation, UseMutationOptions } from "@tanstack/react-query";
2
+ import {
3
+ DocumentData,
4
+ addDoc,
5
+ WithFieldValue,
6
+ CollectionReference,
7
+ getDoc,
8
+ FirestoreDataConverter
9
+ } from "firebase/firestore";
10
+
11
+ import { FirebaseError } from "firebase/app";
12
+ import { useMemo } from "react";
13
+
14
+ export type UseAddDocMutationValues<AppModelType> = {
15
+ data: WithFieldValue<AppModelType>;
16
+ };
17
+
18
+ export type UseAddDocMutationOptions<
19
+ AppModelType extends DocumentData = DocumentData,
20
+ DbModelType extends DocumentData = DocumentData,
21
+ TContext = unknown
22
+ > = {
23
+ reference: CollectionReference<AppModelType, DbModelType>;
24
+ converter?: FirestoreDataConverter<AppModelType, DbModelType>;
25
+ options?: Omit<
26
+ UseMutationOptions<AppModelType, FirebaseError, UseAddDocMutationValues<AppModelType>, TContext>,
27
+ "mutationFn" | "mutationKey"
28
+ >;
29
+ };
30
+
31
+ export const useAddDocMutation = <
32
+ AppModelType extends DocumentData = DocumentData,
33
+ DbModelType extends DocumentData = DocumentData,
34
+ TContext = unknown
35
+ >({
36
+ reference,
37
+ converter,
38
+ options = {}
39
+ }: UseAddDocMutationOptions<AppModelType, DbModelType, TContext>) => {
40
+ const mutationKey = useMemo(() => [reference.path], [reference.path]);
41
+
42
+ return useMutation({
43
+ ...options,
44
+ mutationFn: async ({ data }) => {
45
+ const docRef = await addDoc<AppModelType, DbModelType>(reference, data);
46
+ const docSnap = await getDoc(converter ? docRef.withConverter(converter) : docRef);
47
+ return docSnap.data() as AppModelType;
48
+ },
49
+ mutationKey
50
+ });
51
+ };
@@ -0,0 +1,24 @@
1
+ import { useMutation, UseMutationOptions } from "@tanstack/react-query";
2
+ import { writeBatch, WriteBatch } from "firebase/firestore";
3
+
4
+ import { FirebaseError } from "firebase/app";
5
+ import { useFirestore } from "../useFirestore";
6
+
7
+ export type UseBatchWriteVariables = (batch: WriteBatch) => Promise<void> | void;
8
+
9
+ export type UseBatchWriteOptions<TContext = unknown> = {
10
+ options?: Omit<UseMutationOptions<void, FirebaseError, UseBatchWriteVariables, TContext>, "mutationFn">;
11
+ };
12
+
13
+ export const useBatchWrite = <TContext = unknown>({ options = {} }: UseBatchWriteOptions<TContext> = {}) => {
14
+ const db = useFirestore();
15
+
16
+ return useMutation({
17
+ ...options,
18
+ mutationFn: async (batchWriteFn) => {
19
+ const batch = writeBatch(db);
20
+ await batchWriteFn(batch);
21
+ return batch.commit();
22
+ }
23
+ });
24
+ };
@@ -0,0 +1,26 @@
1
+ import { collection, CollectionReference, DocumentData, DocumentReference } from "firebase/firestore";
2
+
3
+ import { useMemo } from "react";
4
+ import { useFirestore } from "../useFirestore";
5
+
6
+ export type UseCollectionReferenceOptions<AppModelType, DbModelType extends DocumentData = DocumentData> = {
7
+ reference?: CollectionReference<AppModelType, DbModelType> | DocumentReference<AppModelType, DbModelType>;
8
+ path: string;
9
+ pathSegments?: string[];
10
+ };
11
+
12
+ export const useCollectionReference = <AppModelType, DbModelType extends DocumentData = DocumentData>({
13
+ path,
14
+ reference,
15
+ pathSegments
16
+ }: UseCollectionReferenceOptions<AppModelType, DbModelType>) => {
17
+ const db = useFirestore();
18
+
19
+ return useMemo(() => {
20
+ return !reference
21
+ ? collection(db, path || "", ...(pathSegments || []))
22
+ : reference.type === "collection"
23
+ ? collection(reference, path, ...(pathSegments || []))
24
+ : collection(reference, path, ...(pathSegments || []));
25
+ }, [path, reference?.path, pathSegments]);
26
+ };
@@ -0,0 +1,68 @@
1
+ import {
2
+ DocumentData,
3
+ QueryCompositeFilterConstraint,
4
+ QueryFilterConstraint,
5
+ WhereFilterOp,
6
+ and,
7
+ documentId,
8
+ or,
9
+ where
10
+ } from "firebase/firestore";
11
+ import { useMemo } from "react";
12
+
13
+ type CompositeFilterDocumentData = DocumentData;
14
+
15
+ export type QueryElement<DbModelType extends CompositeFilterDocumentData = CompositeFilterDocumentData> =
16
+ Partial<QueryCompositeFilterConstraint> & {
17
+ children?: QueryElement[];
18
+ field?: keyof (DbModelType & { documentId?: string[] });
19
+ value?: DbModelType[keyof DbModelType];
20
+ op?: WhereFilterOp;
21
+ };
22
+
23
+ export type CompositeFilter<DbModelType extends CompositeFilterDocumentData = CompositeFilterDocumentData> =
24
+ QueryCompositeFilterConstraint & {
25
+ children: QueryElement<DbModelType & { documentId?: string[] }>[];
26
+ };
27
+
28
+ export type UseCompositeFilter<DbModelType extends CompositeFilterDocumentData = CompositeFilterDocumentData> = {
29
+ query?: CompositeFilter<DbModelType>;
30
+ };
31
+
32
+ const buildCompositeQuery = <DbModelType extends CompositeFilterDocumentData = CompositeFilterDocumentData>(
33
+ query: QueryElement<DbModelType>
34
+ ): QueryFilterConstraint | null => {
35
+ if (query.children) {
36
+ const queryConstraints = query.children
37
+ .map((subQuery) => buildCompositeQuery(subQuery))
38
+ .filter<QueryFilterConstraint>((constraint) => !!constraint);
39
+
40
+ if (queryConstraints.length <= 0) {
41
+ return null;
42
+ }
43
+
44
+ return (query as CompositeFilter).type === "or" ? or(...queryConstraints) : and(...queryConstraints);
45
+ }
46
+
47
+ if (query.field && query.op) {
48
+ return where(query.field === "documentId" ? documentId() : (query.field as string), query.op, query.value);
49
+ }
50
+
51
+ return null;
52
+ };
53
+
54
+ export const useCompositeFilter = <DbModelType extends CompositeFilterDocumentData = CompositeFilterDocumentData>({
55
+ query
56
+ }: UseCompositeFilter<DbModelType>) => {
57
+ return useMemo(() => {
58
+ const queryConstraints =
59
+ query?.children?.map?.((subQuery) => buildCompositeQuery(subQuery))?.filter<QueryFilterConstraint>?.(
60
+ (constraint) => !!constraint
61
+ ) ?? [];
62
+
63
+ if (queryConstraints.length <= 0) {
64
+ return undefined;
65
+ }
66
+ return query?.type === "or" ? or(...queryConstraints) : and(...queryConstraints);
67
+ }, [query]);
68
+ };
@@ -0,0 +1,51 @@
1
+ import {
2
+ DocumentData,
3
+ getCountFromServer,
4
+ Query,
5
+ query,
6
+ QueryCompositeFilterConstraint,
7
+ QueryConstraint,
8
+ QueryNonFilterConstraint
9
+ } from "firebase/firestore";
10
+
11
+ import {
12
+ UseQueryResult,
13
+ useQuery as useReactQuery,
14
+ UseQueryOptions as UseReactQueryOptions
15
+ } from "@tanstack/react-query";
16
+
17
+ type UseCountQueryOptions<
18
+ AppModelType extends DocumentData = DocumentData,
19
+ DbModelType extends DocumentData = DocumentData
20
+ > = {
21
+ options: Omit<UseReactQueryOptions<number, Error, number>, "queryFn"> &
22
+ Required<Pick<UseReactQueryOptions<number, Error, number>, "queryKey">>;
23
+ query: Query<AppModelType, DbModelType>;
24
+ queryConstraints?: QueryConstraint[] | QueryNonFilterConstraint[];
25
+ compositeFilter?: QueryCompositeFilterConstraint;
26
+ };
27
+
28
+ export const useCountQuery = <
29
+ AppModelType extends DocumentData = DocumentData,
30
+ DbModelType extends DocumentData = DocumentData
31
+ >({
32
+ options,
33
+ query: queryReference,
34
+ queryConstraints = [],
35
+ compositeFilter
36
+ }: UseCountQueryOptions<AppModelType, DbModelType>): UseQueryResult<number> => {
37
+ return useReactQuery({
38
+ ...options,
39
+ queryFn: async () => {
40
+ const queryToExecute = compositeFilter
41
+ ? query(queryReference, compositeFilter, ...(queryConstraints as QueryNonFilterConstraint[]))
42
+ : query(queryReference, ...queryConstraints);
43
+
44
+ const querySnapshot = await getCountFromServer(queryToExecute);
45
+ if (querySnapshot) {
46
+ return querySnapshot.data().count;
47
+ }
48
+ return 0;
49
+ }
50
+ });
51
+ };
@@ -0,0 +1,40 @@
1
+ import { useMutation, UseMutationOptions } from "@tanstack/react-query";
2
+ import { DocumentData, deleteDoc, WithFieldValue, DocumentReference } from "firebase/firestore";
3
+
4
+ import { FirebaseError } from "firebase/app";
5
+ import { useMemo } from "react";
6
+
7
+ export type UseDeleteDocMutationValues<AppModelType> = {
8
+ data: WithFieldValue<AppModelType>;
9
+ };
10
+
11
+ export type UseDeleteDocMutationOptions<
12
+ AppModelType extends DocumentData = DocumentData,
13
+ DbModelType extends DocumentData = DocumentData,
14
+ TContext = unknown
15
+ > = {
16
+ reference: DocumentReference<AppModelType, DbModelType> | null;
17
+ options?: Omit<UseMutationOptions<void, FirebaseError, void, TContext>, "mutationFn" | "mutationKey">;
18
+ };
19
+
20
+ export const useDeleteDocMutation = <
21
+ AppModelType extends DocumentData = DocumentData,
22
+ DbModelType extends DocumentData = DocumentData,
23
+ TContext = unknown
24
+ >({
25
+ reference,
26
+ options = {}
27
+ }: UseDeleteDocMutationOptions<AppModelType, DbModelType, TContext>) => {
28
+ const mutationKey = useMemo(() => [reference?.path], [reference?.path]);
29
+
30
+ return useMutation({
31
+ ...options,
32
+ mutationFn: async () => {
33
+ if (!reference) {
34
+ throw new Error("Reference is undefined");
35
+ }
36
+ await deleteDoc<AppModelType, DbModelType>(reference);
37
+ },
38
+ mutationKey
39
+ });
40
+ };
@@ -0,0 +1,44 @@
1
+ import { doc, CollectionReference, DocumentData, DocumentReference, Firestore } from "firebase/firestore";
2
+
3
+ import { useEffect, useRef } from "react";
4
+ import { useFirestore } from "../useFirestore";
5
+
6
+ export type UseDocReferenceOptions<AppModelType, DbModelType extends DocumentData = DocumentData> = {
7
+ reference?: CollectionReference<AppModelType, DbModelType> | DocumentReference<AppModelType, DbModelType>;
8
+ path?: string;
9
+ pathSegments?: string[];
10
+ };
11
+
12
+ const getDocReference = <AppModelType, DbModelType extends DocumentData = DocumentData>(
13
+ db: Firestore,
14
+ { path, pathSegments, reference }: UseDocReferenceOptions<AppModelType, DbModelType>
15
+ ) => {
16
+ if (!path) {
17
+ return null;
18
+ }
19
+
20
+ return (
21
+ !reference
22
+ ? doc(db, path || "", ...(pathSegments || []))
23
+ : reference.type === "collection"
24
+ ? doc(reference, path, ...(pathSegments || []))
25
+ : doc(reference, path, ...(pathSegments || []))
26
+ ) as DocumentReference<AppModelType, DbModelType>;
27
+ };
28
+
29
+ export const useDocReference = <AppModelType, DbModelType extends DocumentData = DocumentData>({
30
+ path,
31
+ reference,
32
+ pathSegments
33
+ }: UseDocReferenceOptions<AppModelType, DbModelType>) => {
34
+ const db = useFirestore();
35
+ const ref = useRef<DocumentReference<AppModelType, DbModelType> | null>(
36
+ getDocReference(db, { path, pathSegments, reference })
37
+ );
38
+
39
+ useEffect(() => {
40
+ ref.current = getDocReference(db, { path, pathSegments, reference });
41
+ }, [path, reference, pathSegments]);
42
+
43
+ return ref.current;
44
+ };