@umituz/react-native-firebase 2.4.86 → 2.4.87

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.
@@ -2,43 +2,177 @@
2
2
  description: Sets up or updates the @umituz/react-native-firebase package in a React Native app.
3
3
  ---
4
4
 
5
- # Firebase Infrastructure Setup Skill
5
+ # Firebase Infrastructure Setup Workflow
6
6
 
7
- When this workflow/skill is invoked, follow these explicit instructions to configure `@umituz/react-native-firebase`.
7
+ This workflow provides automated setup for `@umituz/react-native-firebase` integration.
8
+
9
+ ## Quick Start
10
+
11
+ Just invoke this workflow when you want to:
12
+ - Install @umituz/react-native-firebase in a new project
13
+ - Update existing installation to latest version
14
+ - Configure Firebase credentials and initialization
15
+ - Set up optimal cost-saving configurations
8
16
 
9
17
  ## Step 1: Check and Update `package.json`
10
- - Analyze the project's `package.json`.
11
- - Check if `@umituz/react-native-firebase` exists.
12
- - If missing: Install with `npm install @umituz/react-native-firebase`.
13
- - If outdated: Update it to the latest version.
18
+
19
+ Analyze the project's `package.json`:
20
+ - Check if `@umituz/react-native-firebase` exists in dependencies
21
+ - Check version (current: 2.4.86)
22
+ - If missing: Run `npm install @umituz/react-native-firebase`
23
+ - If outdated: Run `npm install @umituz/react-native-firebase@latest`
14
24
 
15
25
  ## Step 2: Install Peer Dependencies
16
- Check and install any missing peer dependencies (use `npx expo install` for Expo packages to ensure compatibility):
17
- - `firebase`
18
- - `@gorhom/portal`
19
- - `@tanstack/react-query`
20
- - `@umituz/react-native-design-system`
21
- - `expo-apple-authentication`, `expo-auth-session`, `expo-crypto`, `expo-web-browser`
26
+
27
+ Install required peer dependencies:
28
+
29
+ ### Core Dependencies
30
+ ```bash
31
+ # Firebase SDK
32
+ npm install firebase
33
+
34
+ # State Management
35
+ npm install @umituz/react-native-design-system
36
+
37
+ # Query Library
38
+ npm install @tanstack/react-query
39
+ ```
40
+
41
+ ### React Navigation (if using)
42
+ ```bash
43
+ npm install @gorhom/portal
44
+ ```
45
+
46
+ ### Authentication Dependencies (if using social auth)
47
+ ```bash
48
+ # For Expo projects
49
+ npx expo install expo-apple-authentication expo-auth-session expo-crypto expo-web-browser
50
+
51
+ # For bare React Native
52
+ npm install @react-native-firebase/app @react-native-firebase/auth
53
+ ```
22
54
 
23
55
  ## Step 3: Check Environment Variables
24
- - Ensure that Firebase credentials (like `FIREBASE_API_KEY`, `FIREBASE_PROJECT_ID`, etc.) are defined in the project's `.env.example` and `.env` files. If they are missing, prompt the user to add them or scaffold the keys.
56
+
57
+ Verify Firebase credentials are configured. Check for these environment variables:
58
+
59
+ **Required:**
60
+ - `EXPO_PUBLIC_FIREBASE_API_KEY`
61
+ - `EXPO_PUBLIC_FIREBASE_AUTH_DOMAIN`
62
+ - `EXPO_PUBLIC_FIREBASE_PROJECT_ID`
63
+
64
+ **Optional:**
65
+ - `EXPO_PUBLIC_FIREBASE_STORAGE_BUCKET`
66
+ - `EXPO_PUBLIC_FIREBASE_MESSAGING_SENDER_ID`
67
+ - `EXPO_PUBLIC_FIREBASE_APP_ID`
68
+
69
+ Check if `.env` or `.env.example` exists. If not, create `.env.example`:
70
+ ```env
71
+ # Firebase Configuration
72
+ EXPO_PUBLIC_FIREBASE_API_KEY=your_api_key_here
73
+ EXPO_PUBLIC_FIREBASE_AUTH_DOMAIN=your-project.firebaseapp.com
74
+ EXPO_PUBLIC_FIREBASE_PROJECT_ID=your-project-id
75
+ EXPO_PUBLIC_FIREBASE_STORAGE_BUCKET=your-project.appspot.com
76
+ EXPO_PUBLIC_FIREBASE_MESSAGING_SENDER_ID=your_sender_id
77
+ EXPO_PUBLIC_FIREBASE_APP_ID=your_app_id
78
+ ```
25
79
 
26
80
  ## Step 4: Setup Initialization Logic
27
- - Locate the main entry point (e.g. `App.tsx`, `index.js`, or a dedicated config file).
28
- - Check if Firebase is initialized.
29
- - If not, import and implement the initialization boilerplate from `@umituz/react-native-firebase`:
30
- ```typescript
31
- import { autoInitializeFirebase } from '@umituz/react-native-firebase';
32
-
33
- // Call initialization logic early in the app lifecycle
34
- ```
35
-
36
- // turbo
37
- ## Step 5: Native Setup (If bare React Native)
38
- If the project structure indicates an iOS build folder is present, run:
81
+
82
+ Locate the main entry point (usually `App.tsx`, `index.js`, `app/_layout.tsx` for Expo Router).
83
+
84
+ Check if Firebase is initialized. If not, add initialization:
85
+
86
+ ```typescript
87
+ import { autoInitializeFirebase } from '@umituz/react-native-firebase';
88
+
89
+ // Call initialization early in app lifecycle
90
+ useEffect(() => {
91
+ autoInitializeFirebase();
92
+ }, []);
93
+ ```
94
+
95
+ For Expo Router (app/_layout.tsx):
96
+ ```typescript
97
+ import { autoInitializeFirebase } from '@umituz/react-native-firebase';
98
+
99
+ export default function RootLayout() {
100
+ // Initialize Firebase when app starts
101
+ autoInitializeFirebase();
102
+
103
+ return (
104
+ <Stack>
105
+ <Stack.Screen name="(tabs)" options={{ headerShown: false }}>
106
+ {/* your screens */}
107
+ </Stack.Screen>
108
+ </Stack>
109
+ );
110
+ }
111
+ ```
112
+
113
+ ## Step 5: Native Setup (Bare React Native Only)
114
+
115
+ If the project has an `ios/` folder (bare React Native):
39
116
  ```bash
40
117
  cd ios && pod install
118
+ cd ..
119
+ ```
120
+
121
+ For Android, no additional setup needed beyond Step 4.
122
+
123
+ ## Step 6: Verify Setup
124
+
125
+ Run the app and verify:
126
+ - No Firebase initialization errors
127
+ - Firestore queries work
128
+ - Authentication works (if configured)
129
+ - Quota tracking is active (check __DEV__ logs)
130
+
131
+ ## Step 7: Enable Cost Optimizations (Recommended)
132
+
133
+ For production apps, enable smart cost-saving features:
134
+
135
+ ```typescript
136
+ import { useSmartFirestoreSnapshot } from '@umituz/react-native-firebase';
137
+
138
+ // Instead of useFirestoreSnapshot, use the smart version
139
+ const { data } = useSmartFirestoreSnapshot({
140
+ queryKey: ['my-data'],
141
+ subscribe: (onData) => onSnapshot(collection(db, 'data'), (snap) => {
142
+ onData(snap.docs.map(d => d.data()));
143
+ }),
144
+ backgroundStrategy: 'suspend', // Saves battery and data when app backgrounds
145
+ });
41
146
  ```
42
147
 
43
- ## Step 6: Summary
44
- Output what was done: the packages that were updated, the environment keys that were checked/added, and the files modified to include initialization logic.
148
+ ## Troubleshooting
149
+
150
+ **Issue:** "Firebase not initialized"
151
+ - **Solution:** Make sure `autoInitializeFirebase()` is called in app entry point
152
+ - **Solution:** Verify environment variables are set correctly
153
+
154
+ **Issue:** "Module not found: @umituz/react-native-design-system"
155
+ - **Solution:** Run `npm install @umituz/react-native-design-system`
156
+
157
+ **Issue:** "Expo router not found"
158
+ - **Solution:** This package works with any navigation, adjust import paths as needed
159
+
160
+ ## Step 8: Summary
161
+
162
+ After setup, provide user with:
163
+ 1. ✅ Packages installed/updated: [list versions]
164
+ 2. ✅ Environment variables configured: [list keys]
165
+ 3. ✅ Initialization added to: [file path]
166
+ 4. ✅ Cost optimizations enabled: [smart snapshot, persistent cache, etc.]
167
+ 5. ✅ Next steps: [initialize auth, setup Firestore, etc.]
168
+
169
+ ## Additional Resources
170
+
171
+ - Documentation: See README.md for detailed API reference
172
+ - Examples: Check `/examples` folder (if exists)
173
+ - Support: Report issues on GitHub
174
+
175
+ ---
176
+ **Last Updated:** 2025-03-18
177
+ **Package Version:** 2.4.86
178
+ **Platform:** React Native (Expo & Bare)
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@umituz/react-native-firebase",
3
- "version": "2.4.86",
3
+ "version": "2.4.87",
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",
@@ -96,6 +96,7 @@ export {
96
96
  export {
97
97
  QueryDeduplicationMiddleware,
98
98
  queryDeduplicationMiddleware,
99
+ syncDeduplicationWithQuota,
99
100
  useDeduplicationWithQuota,
100
101
  } from './infrastructure/middleware/QueryDeduplicationMiddleware';
101
102
  export type {
@@ -30,9 +30,9 @@ const DEFAULT_CLEANUP_INTERVAL_MS = 15000; // 15s (was 3s)
30
30
  * Quota-based window adjustment thresholds
31
31
  */
32
32
  const QUOTA_THRESHOLDS = {
33
- HIGH_USAGE: 0.80, // 80% - extend window to 30s
33
+ HIGH_USAGE: 0.80, // 80% - extend window to 60s (1 min)
34
34
  MEDIUM_USAGE: 0.60, // 60% - extend window to 20s
35
- NORMAL: 0.60, // < 60% - use default 10s
35
+ NORMAL: 0.50, // < 50% - use default 10s
36
36
  } as const;
37
37
 
38
38
  /**
@@ -280,15 +280,21 @@ export const queryDeduplicationMiddleware = new QueryDeduplicationMiddleware({
280
280
  });
281
281
 
282
282
  /**
283
- * Hook to integrate deduplication with quota tracking
283
+ * Helper function to integrate deduplication with quota tracking
284
284
  * Automatically adjusts window based on quota usage
285
285
  *
286
+ * Note: This is NOT a React hook, but a helper function.
287
+ * Call this from your own hook or effect as needed.
288
+ *
286
289
  * @example
287
290
  * ```typescript
288
- * useDeduplicationWithQuota(queryDeduplicationMiddleware, quotaMiddleware);
291
+ * // In your own hook or component:
292
+ * useEffect(() => {
293
+ * syncDeduplicationWithQuota(queryDeduplicationMiddleware, quotaMiddleware, quotaLimits);
294
+ * }, [quotaMiddleware.getCounts().reads]);
289
295
  * ```
290
296
  */
291
- export function useDeduplicationWithQuota(
297
+ export function syncDeduplicationWithQuota(
292
298
  deduplication: QueryDeduplicationMiddleware,
293
299
  quotaMiddleware: { getCounts: () => { reads: number; writes: number; deletes: number } },
294
300
  quotaLimits: { dailyReadLimit: number }
@@ -298,3 +304,9 @@ export function useDeduplicationWithQuota(
298
304
  const quotaPercentage = counts.reads / quotaLimits.dailyReadLimit;
299
305
  deduplication.adjustWindowForQuota(quotaPercentage);
300
306
  }
307
+
308
+ /**
309
+ * @deprecated Use syncDeduplicationWithQuota instead (not a hook)
310
+ * This will be removed in a future version
311
+ */
312
+ export const useDeduplicationWithQuota = syncDeduplicationWithQuota;
@@ -173,6 +173,8 @@ export function useSmartFirestoreSnapshot<TData>(
173
173
  * Handle app state changes (foreground/background)
174
174
  */
175
175
  useEffect(() => {
176
+ const timers: ReturnType<typeof setTimeout>[] = [];
177
+
176
178
  const handleAppStateChange = (nextAppState: AppStateStatus) => {
177
179
  const isBackgrounded = nextAppState.match(/inactive|background/);
178
180
 
@@ -190,12 +192,13 @@ export function useSmartFirestoreSnapshot<TData>(
190
192
 
191
193
  switch (backgroundStrategy) {
192
194
  case 'suspend':
193
- // Suspend immediately
194
- setTimeout(() => suspendListener(), 0);
195
+ // Suspend immediately - track timer for cleanup
196
+ const suspendTimer = setTimeout(() => suspendListener(), 0);
197
+ timers.push(suspendTimer);
195
198
  break;
196
199
 
197
200
  case 'timeout':
198
- // Suspend after timeout
201
+ // Suspend after timeout - timer stored in state for cleanup
199
202
  const timer = setTimeout(() => {
200
203
  suspendListener();
201
204
  }, backgroundTimeout);
@@ -215,10 +218,11 @@ export function useSmartFirestoreSnapshot<TData>(
215
218
  console.log(`[SmartSnapshot] App entering foreground for query:`, queryKey);
216
219
  }
217
220
 
218
- // Resume listener (with optional delay)
219
- setTimeout(() => {
221
+ // Resume listener (with optional delay) - track timer for cleanup
222
+ const resumeTimer = setTimeout(() => {
220
223
  resumeListener();
221
224
  }, resumeDelay);
225
+ timers.push(resumeTimer);
222
226
 
223
227
  return { ...prev, isBackgrounded: false, suspendTimer: null };
224
228
  }
@@ -231,6 +235,8 @@ export function useSmartFirestoreSnapshot<TData>(
231
235
 
232
236
  return () => {
233
237
  subscription.remove();
238
+ // Clean up any pending timers
239
+ timers.forEach(timer => clearTimeout(timer));
234
240
  };
235
241
  }, [queryKey, backgroundStrategy, backgroundTimeout, resumeDelay, suspendListener, resumeListener]);
236
242
 
@@ -343,9 +349,13 @@ export function useSmartListenerControl() {
343
349
  return () => subscription.remove();
344
350
  }, []);
345
351
 
352
+ // Compute background status once to avoid duplicate regex matching
353
+ const isBackgrounded = appState.match(/inactive|background/);
354
+ const isForegrounded = !isBackgrounded;
355
+
346
356
  return {
347
- isBackgrounded: appState.match(/inactive|background/),
348
- isForegrounded: !appState.match(/inactive|background/),
357
+ isBackgrounded,
358
+ isForegrounded,
349
359
  appState,
350
360
  };
351
361
  }