@umituz/react-native-firebase 2.4.71 → 2.4.72

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.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@umituz/react-native-firebase",
3
- "version": "2.4.71",
3
+ "version": "2.4.72",
4
4
  "description": "Unified Firebase package for React Native apps - Auth and Firestore services using Firebase JS SDK (no native modules).",
5
5
  "main": "./src/index.ts",
6
6
  "types": "./src/index.ts",
@@ -128,19 +128,14 @@
128
128
  "default": "./src/index.ts"
129
129
  },
130
130
  "./auth": {
131
- "react-native": "./src/auth/index.ts",
132
- "types": "./src/auth/index.ts",
133
- "default": "./src/auth/index.ts"
131
+ "react-native": "./src/domains/auth/index.ts",
132
+ "types": "./src/domains/auth/index.ts",
133
+ "default": "./src/domains/auth/index.ts"
134
134
  },
135
135
  "./firestore": {
136
- "react-native": "./src/firestore/index.ts",
137
- "types": "./src/firestore/index.ts",
138
- "default": "./src/firestore/index.ts"
139
- },
140
- "./storage": {
141
- "react-native": "./src/storage/index.ts",
142
- "types": "./src/storage/index.ts",
143
- "default": "./src/storage/index.ts"
136
+ "react-native": "./src/domains/firestore/index.ts",
137
+ "types": "./src/domains/firestore/index.ts",
138
+ "default": "./src/domains/firestore/index.ts"
144
139
  },
145
140
  "./init": {
146
141
  "react-native": "./src/init/index.ts",
@@ -77,7 +77,10 @@ export async function deleteCurrentUser(
77
77
  };
78
78
  }
79
79
 
80
- await markUserDeleted(user.uid);
80
+ const marked = await markUserDeleted(user.uid);
81
+ if (!marked && __DEV__) {
82
+ console.warn('[AccountDeletion] Failed to mark user document as deleted before account removal');
83
+ }
81
84
  await deleteUser(user);
82
85
  return successResult();
83
86
  } catch (error: unknown) {
@@ -185,7 +188,10 @@ async function attemptReauth(user: User, options: AccountDeletionOptions, origin
185
188
  }
186
189
  }
187
190
 
188
- await markUserDeleted(currentUser.uid);
191
+ const marked = await markUserDeleted(currentUser.uid);
192
+ if (!marked && __DEV__) {
193
+ console.warn('[AccountDeletion] Failed to mark user document as deleted before account removal (reauth path)');
194
+ }
189
195
  await deleteUser(currentUser);
190
196
  return successResult();
191
197
  } catch (err: unknown) {
@@ -218,6 +224,10 @@ export async function deleteUserAccount(user: User | null): Promise<AccountDelet
218
224
  }
219
225
 
220
226
  try {
227
+ const marked = await markUserDeleted(user.uid);
228
+ if (!marked && __DEV__) {
229
+ console.warn('[AccountDeletion] Failed to mark user document as deleted (deleteUserAccount)');
230
+ }
221
231
  await deleteUser(user);
222
232
  return successResult();
223
233
  } catch (error: unknown) {
@@ -84,7 +84,10 @@ export async function markUserDeleted(userId: string): Promise<boolean> {
84
84
  updatedAt: serverTimestamp(),
85
85
  }, { merge: true });
86
86
  return true;
87
- } catch {
87
+ } catch (error) {
88
+ if (typeof __DEV__ !== "undefined" && __DEV__) {
89
+ console.error("[UserDocumentService] Failed to mark user deleted:", error);
90
+ }
88
91
  return false;
89
92
  }
90
93
  }
@@ -40,7 +40,7 @@ export function useFirestoreMutation<TData, TVars, TContext = unknown>(
40
40
 
41
41
  return useMutation<TData, Error, TVars, TContext>({
42
42
  ...rest,
43
- onSuccess: (data, variables, context) => {
43
+ onSuccess: (data, variables, _context) => {
44
44
  if (invalidateKeys?.length) {
45
45
  invalidateKeys.forEach((key) => {
46
46
  queryClient.invalidateQueries({ queryKey: key });
@@ -20,7 +20,7 @@
20
20
  * ```
21
21
  */
22
22
 
23
- import { useEffect, useRef } from 'react';
23
+ import { useEffect, useMemo, useRef } from 'react';
24
24
  import {
25
25
  useQuery,
26
26
  useQueryClient,
@@ -46,19 +46,22 @@ export function useFirestoreSnapshot<TData>(
46
46
  const queryClient = useQueryClient();
47
47
  const unsubscribeRef = useRef<(() => void) | null>(null);
48
48
 
49
+ // Stabilize queryKey to prevent unnecessary listener re-subscriptions
50
+ const stableKeyString = JSON.stringify(queryKey);
51
+ const stableQueryKey = useMemo(() => queryKey, [stableKeyString]);
52
+
49
53
  useEffect(() => {
50
54
  if (!enabled) return;
51
55
 
52
56
  unsubscribeRef.current = subscribe((data) => {
53
- queryClient.setQueryData(queryKey, data);
57
+ queryClient.setQueryData(stableQueryKey, data);
54
58
  });
55
59
 
56
60
  return () => {
57
61
  unsubscribeRef.current?.();
58
62
  unsubscribeRef.current = null;
59
63
  };
60
- // eslint-disable-next-line react-hooks/exhaustive-deps
61
- }, [enabled, queryClient, ...queryKey]);
64
+ }, [enabled, queryClient, stableQueryKey, subscribe]);
62
65
 
63
66
  return useQuery<TData, Error>({
64
67
  queryKey,
@@ -24,28 +24,40 @@ export async function withFirestore<T>(
24
24
 
25
25
  /**
26
26
  * Execute a Firestore operation that returns void
27
- * @throws {Error} if Firestore is not available
27
+ * Returns Result<void> for consistent error handling
28
28
  */
29
29
  export async function withFirestoreVoid(
30
30
  operation: (db: Firestore) => Promise<void>,
31
- ): Promise<void> {
31
+ ): Promise<Result<void>> {
32
32
  const db = getFirestore();
33
33
  if (!db) {
34
- throw new Error('[withFirestoreVoid] Firestore is not available');
34
+ return createNoDbErrorResult<void>();
35
+ }
36
+ try {
37
+ await operation(db);
38
+ return { success: true, data: undefined as void };
39
+ } catch (error) {
40
+ const message = error instanceof Error ? error.message : 'Operation failed';
41
+ return { success: false, error: { code: 'firestore/operation-failed', message } };
35
42
  }
36
- return operation(db);
37
43
  }
38
44
 
39
45
  /**
40
46
  * Execute a Firestore operation that returns boolean
41
- * @throws {Error} if Firestore is not available
47
+ * Returns Result<boolean> for consistent error handling
42
48
  */
43
49
  export async function withFirestoreBool(
44
50
  operation: (db: Firestore) => Promise<boolean>,
45
- ): Promise<boolean> {
51
+ ): Promise<Result<boolean>> {
46
52
  const db = getFirestore();
47
53
  if (!db) {
48
- throw new Error('[withFirestoreBool] Firestore is not available');
54
+ return createNoDbErrorResult<boolean>();
55
+ }
56
+ try {
57
+ const result = await operation(db);
58
+ return { success: true, data: result };
59
+ } catch (error) {
60
+ const message = error instanceof Error ? error.message : 'Operation failed';
61
+ return { success: false, error: { code: 'firestore/operation-failed', message } };
49
62
  }
50
- return operation(db);
51
63
  }
@@ -55,7 +55,8 @@ export class PaginationHelper<T> {
55
55
  * @returns Page limit
56
56
  */
57
57
  getLimit(params?: PaginationParams, defaultLimit: number = 10): number {
58
- return params?.limit ?? defaultLimit;
58
+ const limit = params?.limit ?? defaultLimit;
59
+ return Math.max(1, Math.floor(limit));
59
60
  }
60
61
 
61
62
  /**
@@ -11,6 +11,7 @@ import {
11
11
  import { getFirestore } from "../../infrastructure/config/FirestoreClient";
12
12
  import { hasCodeProperty } from "../../../../shared/domain/utils/type-guards.util";
13
13
  import { ERROR_MESSAGES } from "../../../../shared/domain/utils/error-handlers/error-messages";
14
+ import { isQuotaError } from "../../../../shared/domain/utils/error-handlers/error-checkers";
14
15
 
15
16
  /**
16
17
  * Execute a transaction with automatic DB instance check.
@@ -28,6 +29,11 @@ export async function runTransaction<T>(
28
29
  } catch (error) {
29
30
  const errorMessage = error instanceof Error ? error.message : 'Unknown error';
30
31
  const errorCode = hasCodeProperty(error) ? error.code : 'unknown';
32
+
33
+ if (isQuotaError(error)) {
34
+ throw new Error(`[runTransaction] ${ERROR_MESSAGES.FIRESTORE.QUOTA_EXCEEDED}: ${errorMessage} (Code: ${errorCode})`);
35
+ }
36
+
31
37
  throw new Error(`[runTransaction] Transaction failed: ${errorMessage} (Code: ${errorCode})`);
32
38
  }
33
39
  }
@@ -39,7 +39,7 @@ export interface FirebaseInitModuleConfig {
39
39
  export function createFirebaseInitModule(
40
40
  config: FirebaseInitModuleConfig = {}
41
41
  ): InitModule {
42
- const { authInitializer, critical = false } = config;
42
+ const { authInitializer, critical = true } = config;
43
43
 
44
44
  return {
45
45
  name: 'firebase',
@@ -6,6 +6,7 @@
6
6
  // Result types and helpers
7
7
  export type {
8
8
  Result,
9
+ FailureResult,
9
10
  } from './result/result-types';
10
11
 
11
12
  export {
@@ -13,6 +14,11 @@ export {
13
14
  failureResultFrom,
14
15
  } from './result/result-creators';
15
16
 
17
+ export {
18
+ isSuccess,
19
+ isFailure,
20
+ } from './result/result-helpers';
21
+
16
22
  // Async operation execution
17
23
  export {
18
24
  executeOperation,
@@ -3,7 +3,7 @@
3
3
  * Utility functions for working with Result type
4
4
  */
5
5
 
6
- import type { Result, SuccessResult } from './result-types';
6
+ import type { Result, SuccessResult, FailureResult } from './result-types';
7
7
 
8
8
  /**
9
9
  * Check if result is successful
@@ -11,3 +11,10 @@ import type { Result, SuccessResult } from './result-types';
11
11
  export function isSuccess<T>(result: Result<T>): result is SuccessResult<T> {
12
12
  return result.success === true && result.error === undefined;
13
13
  }
14
+
15
+ /**
16
+ * Check if result is a failure
17
+ */
18
+ export function isFailure<T>(result: Result<T>): result is FailureResult {
19
+ return result.success === false && result.error !== undefined;
20
+ }
@@ -26,8 +26,8 @@ export function isValidFirebaseAuthDomain(authDomain: string): boolean {
26
26
  return false;
27
27
  }
28
28
  return (
29
- authDomain.includes('.firebaseapp.com') ||
30
- authDomain.includes('.web.app')
29
+ authDomain.endsWith('.firebaseapp.com') ||
30
+ authDomain.endsWith('.web.app')
31
31
  );
32
32
  }
33
33
 
@@ -82,6 +82,7 @@ export async function initializeAllFirebaseServices(
82
82
  await options.authInitializer();
83
83
  authSuccess = true;
84
84
  } catch (error) {
85
+ authSuccess = false;
85
86
  authError = error instanceof Error ? error.message : 'Auth initialization failed';
86
87
  }
87
88
  }