@umituz/react-native-firebase 1.13.52 → 1.13.53

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": "1.13.52",
3
+ "version": "1.13.53",
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",
package/src/auth/index.ts CHANGED
@@ -51,7 +51,6 @@ export {
51
51
  isCurrentUserAuthenticated,
52
52
  isCurrentUserAnonymous,
53
53
  verifyUserId,
54
- getSafeUserId,
55
54
  isValidUser,
56
55
  } from './infrastructure/services/auth-utils.service';
57
56
 
@@ -8,13 +8,6 @@
8
8
  import type { Auth, User } from 'firebase/auth';
9
9
  import { getFirebaseAuth } from '../config/FirebaseAuthClient';
10
10
 
11
- /**
12
- * Check if user is anonymous
13
- */
14
- function isAnonymousUser(user: User): boolean {
15
- return user.isAnonymous === true;
16
- }
17
-
18
11
  /**
19
12
  * Auth check result interface
20
13
  */
@@ -28,9 +21,10 @@ export interface AuthCheckResult {
28
21
  /**
29
22
  * Check authentication state
30
23
  * Returns comprehensive auth state information
24
+ * Optimized: Single traversal of auth state
31
25
  */
32
26
  export function checkAuthState(auth: Auth | null): AuthCheckResult {
33
- if (!auth) {
27
+ if (!auth || !auth.currentUser) {
34
28
  return {
35
29
  isAuthenticated: false,
36
30
  isAnonymous: false,
@@ -40,19 +34,9 @@ export function checkAuthState(auth: Auth | null): AuthCheckResult {
40
34
  }
41
35
 
42
36
  const currentUser = auth.currentUser;
43
-
44
- if (!currentUser) {
45
- return {
46
- isAuthenticated: false,
47
- isAnonymous: false,
48
- currentUser: null,
49
- userId: null,
50
- };
51
- }
52
-
53
37
  return {
54
38
  isAuthenticated: true,
55
- isAnonymous: isAnonymousUser(currentUser),
39
+ isAnonymous: currentUser.isAnonymous === true,
56
40
  currentUser,
57
41
  userId: currentUser.uid,
58
42
  };
@@ -62,28 +46,28 @@ export function checkAuthState(auth: Auth | null): AuthCheckResult {
62
46
  * Check if user is authenticated (including anonymous)
63
47
  */
64
48
  export function isAuthenticated(auth: Auth | null): boolean {
65
- return checkAuthState(auth).isAuthenticated;
49
+ return auth?.currentUser?.uid !== null && auth?.currentUser?.uid !== undefined;
66
50
  }
67
51
 
68
52
  /**
69
53
  * Check if user is anonymous
70
54
  */
71
55
  export function isAnonymous(auth: Auth | null): boolean {
72
- return checkAuthState(auth).isAnonymous;
56
+ return auth?.currentUser?.isAnonymous === true;
73
57
  }
74
58
 
75
59
  /**
76
60
  * Get current user ID (null if not authenticated)
77
61
  */
78
62
  export function getCurrentUserId(auth: Auth | null): string | null {
79
- return checkAuthState(auth).userId;
63
+ return auth?.currentUser?.uid ?? null;
80
64
  }
81
65
 
82
66
  /**
83
67
  * Get current user (null if not authenticated)
84
68
  */
85
69
  export function getCurrentUser(auth: Auth | null): User | null {
86
- return checkAuthState(auth).currentUser;
70
+ return auth?.currentUser ?? null;
87
71
  }
88
72
 
89
73
  /**
@@ -91,8 +75,7 @@ export function getCurrentUser(auth: Auth | null): User | null {
91
75
  * Convenience function that uses getFirebaseAuth()
92
76
  */
93
77
  export function getCurrentUserIdFromGlobal(): string | null {
94
- const auth = getFirebaseAuth();
95
- return getCurrentUserId(auth);
78
+ return getCurrentUserId(getFirebaseAuth());
96
79
  }
97
80
 
98
81
  /**
@@ -100,8 +83,7 @@ export function getCurrentUserIdFromGlobal(): string | null {
100
83
  * Convenience function that uses getFirebaseAuth()
101
84
  */
102
85
  export function getCurrentUserFromGlobal(): User | null {
103
- const auth = getFirebaseAuth();
104
- return getCurrentUser(auth);
86
+ return getCurrentUser(getFirebaseAuth());
105
87
  }
106
88
 
107
89
  /**
@@ -109,8 +91,7 @@ export function getCurrentUserFromGlobal(): User | null {
109
91
  * Convenience function that uses getFirebaseAuth()
110
92
  */
111
93
  export function isCurrentUserAuthenticated(): boolean {
112
- const auth = getFirebaseAuth();
113
- return isAuthenticated(auth);
94
+ return isAuthenticated(getFirebaseAuth());
114
95
  }
115
96
 
116
97
  /**
@@ -118,45 +99,23 @@ export function isCurrentUserAuthenticated(): boolean {
118
99
  * Convenience function that uses getFirebaseAuth()
119
100
  */
120
101
  export function isCurrentUserAnonymous(): boolean {
121
- const auth = getFirebaseAuth();
122
- return isAnonymous(auth);
102
+ return isAnonymous(getFirebaseAuth());
123
103
  }
124
104
 
125
105
  /**
126
106
  * Verify userId matches current authenticated user
127
107
  */
128
108
  export function verifyUserId(auth: Auth | null, userId: string): boolean {
129
- if (!auth || !userId) {
130
- return false;
131
- }
132
-
133
- try {
134
- const state = checkAuthState(auth);
135
- return state.isAuthenticated && state.userId === userId;
136
- } catch {
109
+ if (!userId) {
137
110
  return false;
138
111
  }
139
- }
140
-
141
- /**
142
- * Get safe user ID (null if not authenticated)
143
- */
144
- export function getSafeUserId(auth: Auth | null): string | null {
145
- if (!auth) {
146
- return null;
147
- }
148
-
149
- try {
150
- return getCurrentUserId(auth);
151
- } catch {
152
- return null;
153
- }
112
+ return auth?.currentUser?.uid === userId;
154
113
  }
155
114
 
156
115
  /**
157
116
  * Check if user exists and is valid
158
117
  */
159
118
  export function isValidUser(user: User | null | undefined): user is User {
160
- return user !== null && user !== undefined && typeof user.uid === 'string' && user.uid.length > 0;
119
+ return user?.uid !== undefined && user.uid.length > 0;
161
120
  }
162
121
 
@@ -0,0 +1,116 @@
1
+ /**
2
+ * Firebase Error Type Guards
3
+ * Single Responsibility: Provide type-safe error checking utilities
4
+ *
5
+ * Provides type guards for Firebase errors to ensure type safety
6
+ * when handling errors from Firebase SDK operations.
7
+ */
8
+
9
+ import type { FirestoreError } from 'firebase/firestore';
10
+ import type { AuthError } from 'firebase/auth';
11
+
12
+ /**
13
+ * Check if error is a Firebase Firestore error
14
+ */
15
+ export function isFirestoreError(error: unknown): error is FirestoreError {
16
+ return (
17
+ typeof error === 'object' &&
18
+ error !== null &&
19
+ 'code' in error &&
20
+ 'message' in error
21
+ );
22
+ }
23
+
24
+ /**
25
+ * Check if error is a Firebase Auth error
26
+ */
27
+ export function isAuthError(error: unknown): error is AuthError {
28
+ return (
29
+ typeof error === 'object' &&
30
+ error !== null &&
31
+ 'code' in error &&
32
+ 'message' in error
33
+ );
34
+ }
35
+
36
+ /**
37
+ * Check if error is a network error
38
+ */
39
+ export function isNetworkError(error: unknown): boolean {
40
+ if (!isFirestoreError(error) && !isAuthError(error)) {
41
+ return false;
42
+ }
43
+
44
+ const code = (error as FirestoreError | AuthError).code;
45
+ return (
46
+ code === 'unavailable' ||
47
+ code === 'network-request-failed' ||
48
+ code === 'timeout'
49
+ );
50
+ }
51
+
52
+ /**
53
+ * Check if error is a permission denied error
54
+ */
55
+ export function isPermissionDeniedError(error: unknown): boolean {
56
+ if (!isFirestoreError(error) && !isAuthError(error)) {
57
+ return false;
58
+ }
59
+
60
+ const code = (error as FirestoreError | AuthError).code;
61
+ return code === 'permission-denied' || code === 'unauthorized';
62
+ }
63
+
64
+ /**
65
+ * Check if error is a not found error
66
+ */
67
+ export function isNotFoundError(error: unknown): boolean {
68
+ if (!isFirestoreError(error)) {
69
+ return false;
70
+ }
71
+
72
+ return (error as FirestoreError).code === 'not-found';
73
+ }
74
+
75
+ /**
76
+ * Check if error is a quota exceeded error
77
+ */
78
+ export function isQuotaExceededError(error: unknown): boolean {
79
+ if (!isFirestoreError(error)) {
80
+ return false;
81
+ }
82
+
83
+ return (error as FirestoreError).code === 'resource-exhausted';
84
+ }
85
+
86
+ /**
87
+ * Get safe error message
88
+ * Returns error message or unknown error message
89
+ */
90
+ export function getSafeErrorMessage(error: unknown): string {
91
+ if (isFirestoreError(error) || isAuthError(error)) {
92
+ return error.message;
93
+ }
94
+
95
+ if (error instanceof Error) {
96
+ return error.message;
97
+ }
98
+
99
+ if (typeof error === 'string') {
100
+ return error;
101
+ }
102
+
103
+ return 'An unknown error occurred';
104
+ }
105
+
106
+ /**
107
+ * Get safe error code
108
+ * Returns error code or unknown error code
109
+ */
110
+ export function getSafeErrorCode(error: unknown): string {
111
+ if (isFirestoreError(error) || isAuthError(error)) {
112
+ return error.code;
113
+ }
114
+
115
+ return 'unknown';
116
+ }
package/src/index.ts CHANGED
@@ -44,6 +44,12 @@ export type {
44
44
  ServiceInitializationResult,
45
45
  } from './infrastructure/config/FirebaseClient';
46
46
 
47
+ // =============================================================================
48
+ // TYPE GUARDS
49
+ // =============================================================================
50
+
51
+ export * from './domain/guards/firebase-error.guard';
52
+
47
53
  // =============================================================================
48
54
  // AUTH MODULE
49
55
  // =============================================================================
@@ -1,6 +1,6 @@
1
1
  /**
2
2
  * Firebase Storage Deleter
3
- * Handles image deletion from Firebase Storage
3
+ * Handles single and batch deletion from Firebase Storage
4
4
  */
5
5
 
6
6
  import { getStorage, ref, deleteObject } from "firebase/storage";
@@ -9,6 +9,14 @@ import type { DeleteResult } from "./types";
9
9
 
10
10
  declare const __DEV__: boolean;
11
11
 
12
+ /**
13
+ * Batch delete result interface
14
+ */
15
+ export interface BatchDeleteResult {
16
+ successful: string[];
17
+ failed: Array<{ path: string; error: string }>;
18
+ }
19
+
12
20
  /**
13
21
  * Extract storage path from Firebase download URL
14
22
  */
@@ -74,7 +82,66 @@ export async function deleteStorageFile(
74
82
  }
75
83
 
76
84
  return { success: true, storagePath };
77
- } catch {
85
+ } catch (error) {
86
+ if (__DEV__) {
87
+ console.error("[StorageDeleter] Delete failed", {
88
+ storagePath,
89
+ error,
90
+ });
91
+ }
78
92
  return { success: false, storagePath };
79
93
  }
80
94
  }
95
+
96
+ /**
97
+ * Delete multiple files from Firebase Storage
98
+ * Processes deletions in parallel for better performance
99
+ *
100
+ * @param urlsOrPaths - Array of download URLs or storage paths
101
+ * @returns Batch delete result with successful and failed deletions
102
+ */
103
+ export async function deleteStorageFiles(
104
+ urlsOrPaths: string[]
105
+ ): Promise<BatchDeleteResult> {
106
+ if (__DEV__) {
107
+ console.log("[StorageDeleter] Batch delete", { count: urlsOrPaths.length });
108
+ }
109
+
110
+ const storage = getStorageInstance();
111
+ if (!storage) {
112
+ return {
113
+ successful: [],
114
+ failed: urlsOrPaths.map((path) => ({
115
+ path,
116
+ error: "Firebase Storage not initialized",
117
+ })),
118
+ };
119
+ }
120
+
121
+ const results = await Promise.allSettled(
122
+ urlsOrPaths.map((urlOrPath) => deleteStorageFile(urlOrPath))
123
+ );
124
+
125
+ const successful: string[] = [];
126
+ const failed: Array<{ path: string; error: string }> = [];
127
+
128
+ results.forEach((result, index) => {
129
+ if (result.status === "fulfilled" && result.value.success) {
130
+ successful.push(result.value.storagePath);
131
+ } else {
132
+ const errorMessage = result.status === "rejected"
133
+ ? String((result.reason as any)?.message ?? "Unknown error")
134
+ : "Delete operation failed";
135
+ failed.push({ path: urlsOrPaths[index]!, error: errorMessage });
136
+ }
137
+ });
138
+
139
+ if (__DEV__) {
140
+ console.log("[StorageDeleter] Batch delete complete", {
141
+ successful: successful.length,
142
+ failed: failed.length,
143
+ });
144
+ }
145
+
146
+ return { successful, failed };
147
+ }
@@ -3,5 +3,6 @@
3
3
  */
4
4
 
5
5
  export type { UploadResult, UploadOptions, DeleteResult } from "./types";
6
+ export type { BatchDeleteResult } from "./deleter";
6
7
  export { uploadBase64Image, uploadFile, getMimeType } from "./uploader";
7
- export { deleteStorageFile } from "./deleter";
8
+ export { deleteStorageFile, deleteStorageFiles } from "./deleter";