@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.158",
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 db: Firestore | null,
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
- if (!this.db) return null;
26
- return collection(this.db, "users", userId, this.collectionName);
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
- if (!this.db) return null;
39
- return doc(this.db, "users", userId, this.collectionName, documentId);
40
+ const db = this.getDb();
41
+ if (!db) return null;
42
+ return doc(db, "users", userId, this.collectionName, documentId);
40
43
  }
41
44
  }