@umituz/react-native-firebase 1.13.51 → 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.
|
|
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",
|
|
@@ -50,7 +50,8 @@
|
|
|
50
50
|
"firebase-admin": "^13.6.0",
|
|
51
51
|
"react": "19.1.0",
|
|
52
52
|
"react-native": "0.81.5",
|
|
53
|
-
"typescript": "~5.9.2"
|
|
53
|
+
"typescript": "~5.9.2",
|
|
54
|
+
"zustand": "^5.0.3"
|
|
54
55
|
},
|
|
55
56
|
"optionalDependencies": {
|
|
56
57
|
"firebase-admin": "^13.0.2"
|
package/src/auth/index.ts
CHANGED
|
@@ -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:
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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 (!
|
|
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 !==
|
|
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
|
// =============================================================================
|
package/src/storage/deleter.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Firebase Storage Deleter
|
|
3
|
-
* Handles
|
|
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
|
+
}
|
package/src/storage/index.ts
CHANGED
|
@@ -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";
|