@umituz/react-native-firebase 1.13.22 → 1.13.24

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.22",
3
+ "version": "1.13.24",
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",
@@ -42,9 +42,16 @@ export interface AccountDeletionOptions {
42
42
  export async function deleteCurrentUser(
43
43
  options: AccountDeletionOptions = { autoReauthenticate: true }
44
44
  ): Promise<AccountDeletionResult> {
45
+ if (__DEV__) {
46
+ console.log("[deleteCurrentUser] Starting with options:", options);
47
+ }
48
+
45
49
  const auth = getFirebaseAuth();
46
50
 
47
51
  if (!auth) {
52
+ if (__DEV__) {
53
+ console.log("[deleteCurrentUser] ❌ Firebase Auth not initialized");
54
+ }
48
55
  return {
49
56
  success: false,
50
57
  error: {
@@ -58,6 +65,9 @@ export async function deleteCurrentUser(
58
65
  const user = auth.currentUser;
59
66
 
60
67
  if (!user) {
68
+ if (__DEV__) {
69
+ console.log("[deleteCurrentUser] ❌ No user signed in");
70
+ }
61
71
  return {
62
72
  success: false,
63
73
  error: {
@@ -69,6 +79,9 @@ export async function deleteCurrentUser(
69
79
  }
70
80
 
71
81
  if (user.isAnonymous) {
82
+ if (__DEV__) {
83
+ console.log("[deleteCurrentUser] ❌ Cannot delete anonymous user");
84
+ }
72
85
  return {
73
86
  success: false,
74
87
  error: {
@@ -79,18 +92,47 @@ export async function deleteCurrentUser(
79
92
  };
80
93
  }
81
94
 
95
+ if (__DEV__) {
96
+ const provider = getUserAuthProvider(user);
97
+ console.log("[deleteCurrentUser] User info:", {
98
+ uid: user.uid,
99
+ provider,
100
+ providerData: user.providerData?.map(p => p.providerId),
101
+ });
102
+ }
103
+
82
104
  // First attempt to delete
83
105
  try {
106
+ if (__DEV__) {
107
+ console.log("[deleteCurrentUser] Attempting to delete user...");
108
+ }
84
109
  await deleteUser(user);
110
+ if (__DEV__) {
111
+ console.log("[deleteCurrentUser] ✅ User deleted successfully");
112
+ }
85
113
  return { success: true };
86
114
  } catch (error) {
87
115
  const firebaseError = error as { code?: string; message?: string };
88
116
  const requiresReauth = firebaseError.code === "auth/requires-recent-login";
89
117
 
118
+ if (__DEV__) {
119
+ console.log("[deleteCurrentUser] First delete attempt failed:", {
120
+ code: firebaseError.code,
121
+ message: firebaseError.message,
122
+ requiresReauth,
123
+ });
124
+ }
125
+
90
126
  // If reauthentication is required and autoReauthenticate is enabled
91
127
  if (requiresReauth && options.autoReauthenticate) {
128
+ if (__DEV__) {
129
+ console.log("[deleteCurrentUser] Attempting auto-reauthentication...");
130
+ }
92
131
  const reauthResult = await attemptReauthenticationAndDelete(user, options);
93
132
  if (reauthResult) {
133
+ if (__DEV__) {
134
+ console.log("[deleteCurrentUser] Auto-reauth result:", reauthResult);
135
+ }
94
136
  return reauthResult;
95
137
  }
96
138
  }
@@ -117,17 +159,38 @@ async function attemptReauthenticationAndDelete(
117
159
  ): Promise<AccountDeletionResult | null> {
118
160
  const provider = getUserAuthProvider(user);
119
161
 
162
+ if (__DEV__) {
163
+ console.log("[attemptReauthenticationAndDelete] Provider:", provider);
164
+ }
165
+
120
166
  // Handle Apple reauthentication
121
167
  if (provider === "apple.com") {
168
+ if (__DEV__) {
169
+ console.log("[attemptReauthenticationAndDelete] Attempting Apple reauthentication...");
170
+ }
171
+
122
172
  const reauthResult = await reauthenticateWithApple(user);
123
173
 
174
+ if (__DEV__) {
175
+ console.log("[attemptReauthenticationAndDelete] Apple reauth result:", reauthResult);
176
+ }
177
+
124
178
  if (reauthResult.success) {
125
179
  // Retry deletion after successful reauthentication
126
180
  try {
181
+ if (__DEV__) {
182
+ console.log("[attemptReauthenticationAndDelete] Deleting user after Apple reauth...");
183
+ }
127
184
  await deleteUser(user);
185
+ if (__DEV__) {
186
+ console.log("[attemptReauthenticationAndDelete] ✅ User deleted after Apple reauth");
187
+ }
128
188
  return { success: true };
129
189
  } catch (deleteError) {
130
190
  const firebaseError = deleteError as { code?: string; message?: string };
191
+ if (__DEV__) {
192
+ console.log("[attemptReauthenticationAndDelete] ❌ Delete failed after Apple reauth:", firebaseError);
193
+ }
131
194
  return {
132
195
  success: false,
133
196
  error: {
@@ -139,6 +202,9 @@ async function attemptReauthenticationAndDelete(
139
202
  }
140
203
  } else {
141
204
  // Reauthentication failed
205
+ if (__DEV__) {
206
+ console.log("[attemptReauthenticationAndDelete] ❌ Apple reauth failed");
207
+ }
142
208
  return {
143
209
  success: false,
144
210
  error: {
@@ -0,0 +1,26 @@
1
+ /**
2
+ * Quota Metrics Types
3
+ */
4
+
5
+ export interface QuotaMetrics {
6
+ readCount: number;
7
+ writeCount: number;
8
+ deleteCount: number;
9
+ lastResetDate: string;
10
+ }
11
+
12
+ export interface QuotaLimits {
13
+ dailyReadLimit: number;
14
+ dailyWriteLimit: number;
15
+ dailyDeleteLimit: number;
16
+ }
17
+
18
+ export interface QuotaStatus {
19
+ metrics: QuotaMetrics;
20
+ limits: QuotaLimits;
21
+ readPercentage: number;
22
+ writePercentage: number;
23
+ deletePercentage: number;
24
+ isNearLimit: boolean;
25
+ isOverLimit: boolean;
26
+ }
@@ -0,0 +1,28 @@
1
+ /**
2
+ * Request Log Types
3
+ */
4
+
5
+ export type RequestType = 'read' | 'write' | 'delete' | 'listener';
6
+
7
+ export interface RequestLog {
8
+ id: string;
9
+ type: RequestType;
10
+ collection: string;
11
+ documentId?: string;
12
+ cached: boolean;
13
+ success: boolean;
14
+ error?: string;
15
+ duration?: number;
16
+ timestamp: number;
17
+ }
18
+
19
+ export interface RequestStats {
20
+ totalRequests: number;
21
+ readRequests: number;
22
+ writeRequests: number;
23
+ deleteRequests: number;
24
+ listenerRequests: number;
25
+ cachedRequests: number;
26
+ failedRequests: number;
27
+ averageDuration: number;
28
+ }
@@ -1,17 +1,6 @@
1
1
  /**
2
2
  * React Native Firestore Module
3
3
  * Domain-Driven Design (DDD) Architecture
4
- *
5
- * This is the SINGLE SOURCE OF TRUTH for all Firestore operations.
6
- * ALL imports from the Firestore module MUST go through this file.
7
- *
8
- * Architecture:
9
- * - domain: Errors, Constants, Entities, Services
10
- * - infrastructure: Firestore client, BaseRepository, utilities
11
- * - utils: Date utilities, timestamp conversion, query builders
12
- *
13
- * This module is designed to be used across hundreds of apps.
14
- * It provides a consistent interface for Firestore operations.
15
4
  */
16
5
 
17
6
  // =============================================================================
@@ -98,16 +87,6 @@ export {
98
87
  createDocumentMapper,
99
88
  } from './utils/document-mapper.helper';
100
89
 
101
- // =============================================================================
102
- // UTILS - Quota Error Detection
103
- // =============================================================================
104
-
105
- export {
106
- isQuotaError,
107
- isRetryableError,
108
- getQuotaErrorMessage,
109
- } from './utils/quota-error-detector.util';
110
-
111
90
  // =============================================================================
112
91
  // UTILS - Path Resolver
113
92
  // =============================================================================
@@ -148,6 +127,16 @@ export type {
148
127
 
149
128
  export { QuotaCalculator } from './domain/services/QuotaCalculator';
150
129
 
130
+ // =============================================================================
131
+ // UTILS - Quota Error Detection
132
+ // =============================================================================
133
+
134
+ export {
135
+ isQuotaError,
136
+ isRetryableError,
137
+ getQuotaErrorMessage,
138
+ } from './utils/quota-error-detector.util';
139
+
151
140
  // =============================================================================
152
141
  // INFRASTRUCTURE LAYER - Middleware
153
142
  // =============================================================================
@@ -166,11 +155,6 @@ export {
166
155
  // INFRASTRUCTURE LAYER - Services
167
156
  // =============================================================================
168
157
 
169
- export {
170
- QuotaMonitorService,
171
- quotaMonitorService,
172
- } from './infrastructure/services/QuotaMonitorService';
173
-
174
158
  export {
175
159
  RequestLoggerService,
176
160
  requestLoggerService,
@@ -0,0 +1,103 @@
1
+ /**
2
+ * Quota Tracking Middleware
3
+ * Tracks Firestore operations for quota monitoring
4
+ */
5
+
6
+ declare const __DEV__: boolean;
7
+
8
+ interface OperationInfo {
9
+ type: 'read' | 'write' | 'delete';
10
+ collection: string;
11
+ count: number;
12
+ cached: boolean;
13
+ }
14
+
15
+ export class QuotaTrackingMiddleware {
16
+ private readCount = 0;
17
+ private writeCount = 0;
18
+ private deleteCount = 0;
19
+
20
+ /**
21
+ * Track a Firestore operation
22
+ */
23
+ async trackOperation<T>(
24
+ info: OperationInfo,
25
+ operation: () => Promise<T>
26
+ ): Promise<T> {
27
+ const result = await operation();
28
+
29
+ switch (info.type) {
30
+ case 'read':
31
+ if (!info.cached) {
32
+ this.readCount += info.count;
33
+ }
34
+ break;
35
+ case 'write':
36
+ this.writeCount += info.count;
37
+ break;
38
+ case 'delete':
39
+ this.deleteCount += info.count;
40
+ break;
41
+ }
42
+
43
+ if (__DEV__) {
44
+ console.log(`[QuotaTracking] ${info.type}: ${info.collection} (${info.count})`);
45
+ }
46
+
47
+ return result;
48
+ }
49
+
50
+ /**
51
+ * Track read operation
52
+ */
53
+ trackRead(collection: string, count: number = 1, cached: boolean = false): void {
54
+ if (!cached) {
55
+ this.readCount += count;
56
+ }
57
+ if (__DEV__) {
58
+ console.log(`[QuotaTracking] read: ${collection} (${count})`);
59
+ }
60
+ }
61
+
62
+ /**
63
+ * Track write operation
64
+ */
65
+ trackWrite(collection: string, _documentId?: string, count: number = 1): void {
66
+ this.writeCount += count;
67
+ if (__DEV__) {
68
+ console.log(`[QuotaTracking] write: ${collection} (${count})`);
69
+ }
70
+ }
71
+
72
+ /**
73
+ * Track delete operation
74
+ */
75
+ trackDelete(collection: string, _documentId?: string, count: number = 1): void {
76
+ this.deleteCount += count;
77
+ if (__DEV__) {
78
+ console.log(`[QuotaTracking] delete: ${collection} (${count})`);
79
+ }
80
+ }
81
+
82
+ /**
83
+ * Get current counts
84
+ */
85
+ getCounts(): { reads: number; writes: number; deletes: number } {
86
+ return {
87
+ reads: this.readCount,
88
+ writes: this.writeCount,
89
+ deletes: this.deleteCount,
90
+ };
91
+ }
92
+
93
+ /**
94
+ * Reset counts
95
+ */
96
+ reset(): void {
97
+ this.readCount = 0;
98
+ this.writeCount = 0;
99
+ this.deleteCount = 0;
100
+ }
101
+ }
102
+
103
+ export const quotaTrackingMiddleware = new QuotaTrackingMiddleware();
@@ -0,0 +1,59 @@
1
+ /**
2
+ * Quota Error Detection Utilities
3
+ */
4
+
5
+ const QUOTA_ERROR_CODES = [
6
+ 'resource-exhausted',
7
+ 'quota-exceeded',
8
+ 'RESOURCE_EXHAUSTED',
9
+ ];
10
+
11
+ const QUOTA_ERROR_MESSAGES = [
12
+ 'quota',
13
+ 'exceeded',
14
+ 'limit',
15
+ 'too many requests',
16
+ ];
17
+
18
+ /**
19
+ * Check if error is a Firestore quota error
20
+ */
21
+ export function isQuotaError(error: unknown): boolean {
22
+ if (!error) return false;
23
+
24
+ const errorObj = error as Record<string, unknown>;
25
+ const code = errorObj.code as string | undefined;
26
+ const message = errorObj.message as string | undefined;
27
+
28
+ if (code && QUOTA_ERROR_CODES.some((c) => code.includes(c))) {
29
+ return true;
30
+ }
31
+
32
+ if (message) {
33
+ const lowerMessage = message.toLowerCase();
34
+ return QUOTA_ERROR_MESSAGES.some((m) => lowerMessage.includes(m));
35
+ }
36
+
37
+ return false;
38
+ }
39
+
40
+ /**
41
+ * Check if error is retryable
42
+ */
43
+ export function isRetryableError(error: unknown): boolean {
44
+ if (!error) return false;
45
+
46
+ const errorObj = error as Record<string, unknown>;
47
+ const code = errorObj.code as string | undefined;
48
+
49
+ const retryableCodes = ['unavailable', 'deadline-exceeded', 'aborted'];
50
+
51
+ return code ? retryableCodes.some((c) => code.includes(c)) : false;
52
+ }
53
+
54
+ /**
55
+ * Get user-friendly quota error message
56
+ */
57
+ export function getQuotaErrorMessage(): string {
58
+ return 'Daily quota exceeded. Please try again tomorrow or upgrade your plan.';
59
+ }