@umituz/react-native-firebase 1.13.158 → 1.13.159
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.159",
|
|
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",
|
|
@@ -0,0 +1,173 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Google OAuth Service
|
|
3
|
+
* Handles Google OAuth flow using expo-auth-session
|
|
4
|
+
* This service is optional and requires expo-auth-session to be installed
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
import type { Auth } from "firebase/auth";
|
|
8
|
+
import type { GoogleAuthResult } from "./google-auth.types";
|
|
9
|
+
import { googleAuthService } from "./google-auth.service";
|
|
10
|
+
|
|
11
|
+
// Conditional imports - these packages are optional
|
|
12
|
+
let ExpoAuthSession: any = null;
|
|
13
|
+
let ExpoWebBrowser: any = null;
|
|
14
|
+
let isExpoAuthAvailable = false;
|
|
15
|
+
|
|
16
|
+
try {
|
|
17
|
+
ExpoAuthSession = require("expo-auth-session/providers/google");
|
|
18
|
+
ExpoWebBrowser = require("expo-web-browser");
|
|
19
|
+
isExpoAuthAvailable = true;
|
|
20
|
+
|
|
21
|
+
// Complete auth session if available
|
|
22
|
+
if (ExpoWebBrowser?.maybeCompleteAuthSession) {
|
|
23
|
+
ExpoWebBrowser.maybeCompleteAuthSession();
|
|
24
|
+
}
|
|
25
|
+
} catch (error) {
|
|
26
|
+
// expo-auth-session not available - this is fine if not using Google OAuth
|
|
27
|
+
console.info("expo-auth-session is not installed. Google OAuth will not be available.");
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
export interface GoogleOAuthConfig {
|
|
31
|
+
iosClientId?: string;
|
|
32
|
+
webClientId?: string;
|
|
33
|
+
androidClientId?: string;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
export interface GoogleOAuthHookResult {
|
|
37
|
+
request: any;
|
|
38
|
+
response: any;
|
|
39
|
+
promptAsync: (() => Promise<any>) | null;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
const PLACEHOLDER_CLIENT_ID = "000000000000-placeholder.apps.googleusercontent.com";
|
|
43
|
+
|
|
44
|
+
function validateGoogleConfig(config?: GoogleOAuthConfig): boolean {
|
|
45
|
+
if (!config) return false;
|
|
46
|
+
return !!(
|
|
47
|
+
(config.iosClientId && config.iosClientId !== PLACEHOLDER_CLIENT_ID) ||
|
|
48
|
+
(config.webClientId && config.webClientId !== PLACEHOLDER_CLIENT_ID) ||
|
|
49
|
+
(config.androidClientId && config.androidClientId !== PLACEHOLDER_CLIENT_ID)
|
|
50
|
+
);
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
/**
|
|
54
|
+
* Google OAuth Service
|
|
55
|
+
* Provides OAuth flow using expo-auth-session
|
|
56
|
+
*/
|
|
57
|
+
export class GoogleOAuthService {
|
|
58
|
+
/**
|
|
59
|
+
* Check if expo-auth-session is available
|
|
60
|
+
*/
|
|
61
|
+
isAvailable(): boolean {
|
|
62
|
+
return isExpoAuthAvailable;
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
/**
|
|
66
|
+
* Check if Google OAuth is configured
|
|
67
|
+
*/
|
|
68
|
+
isConfigured(config?: GoogleOAuthConfig): boolean {
|
|
69
|
+
return validateGoogleConfig(config);
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
/**
|
|
73
|
+
* Create auth request hook
|
|
74
|
+
* This mimics the behavior of expo-auth-session's useAuthRequest hook
|
|
75
|
+
*/
|
|
76
|
+
createAuthRequest(config?: GoogleOAuthConfig): GoogleOAuthHookResult {
|
|
77
|
+
if (!isExpoAuthAvailable || !ExpoAuthSession?.useAuthRequest) {
|
|
78
|
+
return {
|
|
79
|
+
request: null,
|
|
80
|
+
response: null,
|
|
81
|
+
promptAsync: null,
|
|
82
|
+
};
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
try {
|
|
86
|
+
const [request, response, promptAsync] = ExpoAuthSession.useAuthRequest({
|
|
87
|
+
iosClientId: config?.iosClientId || PLACEHOLDER_CLIENT_ID,
|
|
88
|
+
webClientId: config?.webClientId || PLACEHOLDER_CLIENT_ID,
|
|
89
|
+
androidClientId: config?.androidClientId || PLACEHOLDER_CLIENT_ID,
|
|
90
|
+
});
|
|
91
|
+
|
|
92
|
+
return {
|
|
93
|
+
request: request ?? null,
|
|
94
|
+
response: response ?? null,
|
|
95
|
+
promptAsync: promptAsync ?? null,
|
|
96
|
+
};
|
|
97
|
+
} catch (error) {
|
|
98
|
+
console.error("Failed to create Google auth request:", error);
|
|
99
|
+
return {
|
|
100
|
+
request: null,
|
|
101
|
+
response: null,
|
|
102
|
+
promptAsync: null,
|
|
103
|
+
};
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
/**
|
|
108
|
+
* Sign in with Google using OAuth flow
|
|
109
|
+
*/
|
|
110
|
+
async signInWithOAuth(
|
|
111
|
+
auth: Auth,
|
|
112
|
+
config?: GoogleOAuthConfig,
|
|
113
|
+
promptAsync?: () => Promise<any>
|
|
114
|
+
): Promise<GoogleAuthResult> {
|
|
115
|
+
if (!isExpoAuthAvailable) {
|
|
116
|
+
return {
|
|
117
|
+
success: false,
|
|
118
|
+
error: "expo-auth-session is not available. Please install expo-auth-session and expo-web-browser.",
|
|
119
|
+
code: "unavailable",
|
|
120
|
+
};
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
if (!this.isConfigured(config)) {
|
|
124
|
+
return {
|
|
125
|
+
success: false,
|
|
126
|
+
error: "Google Sign-In is not configured. Please provide valid client IDs.",
|
|
127
|
+
code: "not-configured",
|
|
128
|
+
};
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
if (!promptAsync) {
|
|
132
|
+
return {
|
|
133
|
+
success: false,
|
|
134
|
+
error: "Google Sign-In not ready. No promptAsync function provided.",
|
|
135
|
+
code: "not-ready",
|
|
136
|
+
};
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
try {
|
|
140
|
+
const result = await promptAsync();
|
|
141
|
+
|
|
142
|
+
if (result.type === "success" && result.authentication?.idToken) {
|
|
143
|
+
// Use the existing google auth service to sign in with the token
|
|
144
|
+
return await googleAuthService.signInWithIdToken(
|
|
145
|
+
auth,
|
|
146
|
+
result.authentication.idToken
|
|
147
|
+
);
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
if (result.type === "cancel") {
|
|
151
|
+
return {
|
|
152
|
+
success: false,
|
|
153
|
+
error: "Google Sign-In was cancelled",
|
|
154
|
+
code: "cancelled",
|
|
155
|
+
};
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
return {
|
|
159
|
+
success: false,
|
|
160
|
+
error: "Google Sign-In failed",
|
|
161
|
+
code: "failed",
|
|
162
|
+
};
|
|
163
|
+
} catch (error) {
|
|
164
|
+
return {
|
|
165
|
+
success: false,
|
|
166
|
+
error: error instanceof Error ? error.message : "Google sign-in failed",
|
|
167
|
+
code: "error",
|
|
168
|
+
};
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
export const googleOAuthService = new GoogleOAuthService();
|
|
@@ -4,38 +4,41 @@ import { collection, doc } from "firebase/firestore";
|
|
|
4
4
|
/**
|
|
5
5
|
* Resolves Firestore paths for user collections
|
|
6
6
|
* Standard pattern: users/{userId}/{collectionName}
|
|
7
|
-
*
|
|
7
|
+
*
|
|
8
|
+
* Uses lazy initialization to support Firebase initialization after module load
|
|
8
9
|
* This class is designed to be used across hundreds of apps.
|
|
9
10
|
* All user data MUST be under users/{userId}/ for consistency.
|
|
10
11
|
*/
|
|
11
12
|
export class FirestorePathResolver {
|
|
12
13
|
constructor(
|
|
13
14
|
private readonly collectionName: string,
|
|
14
|
-
private readonly
|
|
15
|
+
private readonly getDb: () => Firestore | null,
|
|
15
16
|
) { }
|
|
16
17
|
|
|
17
18
|
/**
|
|
18
19
|
* Get collection reference for a user
|
|
19
20
|
* Pattern: users/{userId}/{collectionName}
|
|
20
|
-
*
|
|
21
|
+
*
|
|
21
22
|
* @param userId User identifier
|
|
22
23
|
* @returns CollectionReference or null if db not initialized
|
|
23
24
|
*/
|
|
24
25
|
getUserCollection(userId: string): CollectionReference<DocumentData> | null {
|
|
25
|
-
|
|
26
|
-
|
|
26
|
+
const db = this.getDb();
|
|
27
|
+
if (!db) return null;
|
|
28
|
+
return collection(db, "users", userId, this.collectionName);
|
|
27
29
|
}
|
|
28
30
|
|
|
29
31
|
/**
|
|
30
32
|
* Get document reference for a specific item
|
|
31
33
|
* Pattern: users/{userId}/{collectionName}/{documentId}
|
|
32
|
-
*
|
|
34
|
+
*
|
|
33
35
|
* @param userId User identifier
|
|
34
36
|
* @param documentId Document identifier
|
|
35
37
|
* @returns DocumentReference or null if db not initialized
|
|
36
38
|
*/
|
|
37
39
|
getDocRef(userId: string, documentId: string): DocumentReference<DocumentData> | null {
|
|
38
|
-
|
|
39
|
-
|
|
40
|
+
const db = this.getDb();
|
|
41
|
+
if (!db) return null;
|
|
42
|
+
return doc(db, "users", userId, this.collectionName, documentId);
|
|
40
43
|
}
|
|
41
44
|
}
|