@umituz/react-native-auth 3.6.41 → 3.6.43

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-auth",
3
- "version": "3.6.41",
3
+ "version": "3.6.43",
4
4
  "description": "Authentication service for React Native apps - Secure, type-safe, and production-ready. Provider-agnostic design with dependency injection, configurable validation, and comprehensive error handling.",
5
5
  "main": "./src/index.ts",
6
6
  "types": "./src/index.ts",
package/src/init/index.ts CHANGED
@@ -6,5 +6,4 @@
6
6
  export {
7
7
  createAuthInitModule,
8
8
  type AuthInitModuleConfig,
9
- type InitModule,
10
9
  } from './createAuthInitModule';
@@ -16,6 +16,10 @@ import type { AuthListenerOptions } from "../../types/auth-store.types";
16
16
  declare const __DEV__: boolean;
17
17
 
18
18
  let listenerInitialized = false;
19
+ // Reference counter for multiple subscribers
20
+ let listenerRefCount = 0;
21
+ // Actual unsubscribe function from Firebase
22
+ let firebaseUnsubscribe: (() => void) | null = null;
19
23
 
20
24
  /**
21
25
  * Initialize Firebase auth listener
@@ -33,11 +37,29 @@ export function initializeAuthListener(
33
37
  });
34
38
  }
35
39
 
40
+ // If already initialized, increment ref count and return unsubscribe that decrements
36
41
  if (listenerInitialized) {
42
+ listenerRefCount++;
37
43
  if (__DEV__) {
38
- console.log("[AuthListener] Already initialized, skipping");
44
+ console.log("[AuthListener] Already initialized, incrementing ref count:", listenerRefCount);
39
45
  }
40
- return () => {};
46
+ // Return function that decrements ref count
47
+ return () => {
48
+ listenerRefCount--;
49
+ if (__DEV__) {
50
+ console.log("[AuthListener] Ref count decremented:", listenerRefCount);
51
+ }
52
+ // Only cleanup when all subscribers unsubscribe
53
+ if (listenerRefCount <= 0 && firebaseUnsubscribe) {
54
+ if (__DEV__) {
55
+ console.log("[AuthListener] Last subscriber, cleaning up");
56
+ }
57
+ firebaseUnsubscribe();
58
+ firebaseUnsubscribe = null;
59
+ listenerInitialized = false;
60
+ listenerRefCount = 0;
61
+ }
62
+ };
41
63
  }
42
64
 
43
65
  const auth = getFirebaseAuth();
@@ -64,8 +86,9 @@ export function initializeAuthListener(
64
86
  }
65
87
 
66
88
  listenerInitialized = true;
89
+ listenerRefCount = 1;
67
90
 
68
- const unsubscribe = onIdTokenChanged(auth, (user) => {
91
+ firebaseUnsubscribe = onIdTokenChanged(auth, (user) => {
69
92
  if (__DEV__) {
70
93
  console.log("[AuthListener] onIdTokenChanged:", {
71
94
  uid: user?.uid ?? null,
@@ -79,18 +102,40 @@ export function initializeAuthListener(
79
102
  if (__DEV__) {
80
103
  console.log("[AuthListener] No user, auto signing in anonymously...");
81
104
  }
105
+ // Set loading state while attempting sign-in
106
+ store.setLoading(true);
107
+
82
108
  void (async () => {
83
- try {
84
- await anonymousAuthService.signInAnonymously(auth);
85
- if (__DEV__) {
86
- console.log("[AuthListener] Anonymous sign-in successful");
109
+ const MAX_RETRIES = 2;
110
+ const RETRY_DELAY_MS = 1000;
111
+
112
+ for (let attempt = 0; attempt <= MAX_RETRIES; attempt++) {
113
+ try {
114
+ await anonymousAuthService.signInAnonymously(auth);
115
+ if (__DEV__) {
116
+ console.log("[AuthListener] Anonymous sign-in successful");
117
+ }
118
+ // Success - the listener will fire again with the new user
119
+ return;
120
+ } catch (error) {
121
+ if (__DEV__) {
122
+ console.warn(`[AuthListener] Anonymous sign-in attempt ${attempt + 1} failed:`, error);
123
+ }
124
+
125
+ // If not last attempt, wait and retry
126
+ if (attempt < MAX_RETRIES) {
127
+ await new Promise(resolve => setTimeout(resolve, RETRY_DELAY_MS));
128
+ continue;
129
+ }
130
+
131
+ // Last attempt failed - set error state
132
+ if (__DEV__) {
133
+ console.error("[AuthListener] All anonymous sign-in attempts failed");
134
+ }
135
+ store.setFirebaseUser(null);
136
+ store.setLoading(false);
137
+ store.setInitialized(true);
87
138
  }
88
- } catch (error) {
89
- if (__DEV__) {
90
- console.warn("[AuthListener] Anonymous sign-in failed:", error);
91
- }
92
- store.setFirebaseUser(null);
93
- store.setInitialized(true);
94
139
  }
95
140
  })();
96
141
  return;
@@ -110,11 +155,20 @@ export function initializeAuthListener(
110
155
  });
111
156
 
112
157
  return () => {
158
+ listenerRefCount--;
113
159
  if (__DEV__) {
114
- console.log("[AuthListener] Unsubscribing");
160
+ console.log("[AuthListener] Unsubscribing, ref count:", listenerRefCount);
161
+ }
162
+ // Only cleanup when all subscribers unsubscribe
163
+ if (listenerRefCount <= 0 && firebaseUnsubscribe) {
164
+ if (__DEV__) {
165
+ console.log("[AuthListener] Last subscriber, cleaning up listener");
166
+ }
167
+ firebaseUnsubscribe();
168
+ firebaseUnsubscribe = null;
169
+ listenerInitialized = false;
170
+ listenerRefCount = 0;
115
171
  }
116
- unsubscribe();
117
- listenerInitialized = false;
118
172
  };
119
173
  }
120
174
 
@@ -122,7 +176,12 @@ export function initializeAuthListener(
122
176
  * Reset listener state (for testing)
123
177
  */
124
178
  export function resetAuthListener(): void {
179
+ if (firebaseUnsubscribe) {
180
+ firebaseUnsubscribe();
181
+ firebaseUnsubscribe = null;
182
+ }
125
183
  listenerInitialized = false;
184
+ listenerRefCount = 0;
126
185
  }
127
186
 
128
187
  /**