@blackcode_sa/metaestetics-api 1.14.16 → 1.14.17

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/dist/index.d.mts CHANGED
@@ -8321,6 +8321,23 @@ declare class AuthService extends BaseService {
8321
8321
  private googleProvider;
8322
8322
  private userService;
8323
8323
  constructor(db: Firestore, auth: Auth, app: FirebaseApp, userService: UserService);
8324
+ /**
8325
+ * Waits for Firebase Auth state to settle after sign-in.
8326
+ *
8327
+ * In React Native with AsyncStorage persistence, there's a critical issue:
8328
+ * 1. signInWithCredential() sets auth.currentUser in memory immediately
8329
+ * 2. But AsyncStorage persistence happens asynchronously
8330
+ * 3. If AsyncStorage reads an old NULL value, it can OVERWRITE the current auth state
8331
+ * 4. This causes auth.currentUser to become NULL even after it was set
8332
+ *
8333
+ * This method uses onAuthStateChanged to wait for the auth state to be SET and STABLE.
8334
+ * It ensures the auth state persists through AsyncStorage operations.
8335
+ *
8336
+ * @param expectedUid - The UID we expect to see in auth.currentUser
8337
+ * @param timeoutMs - Maximum time to wait (default 5 seconds)
8338
+ * @returns Promise that resolves when auth state is ready and stable
8339
+ */
8340
+ private waitForAuthStateToSettle;
8324
8341
  /**
8325
8342
  * Registruje novog korisnika sa email-om i lozinkom
8326
8343
  */
package/dist/index.d.ts CHANGED
@@ -8321,6 +8321,23 @@ declare class AuthService extends BaseService {
8321
8321
  private googleProvider;
8322
8322
  private userService;
8323
8323
  constructor(db: Firestore, auth: Auth, app: FirebaseApp, userService: UserService);
8324
+ /**
8325
+ * Waits for Firebase Auth state to settle after sign-in.
8326
+ *
8327
+ * In React Native with AsyncStorage persistence, there's a critical issue:
8328
+ * 1. signInWithCredential() sets auth.currentUser in memory immediately
8329
+ * 2. But AsyncStorage persistence happens asynchronously
8330
+ * 3. If AsyncStorage reads an old NULL value, it can OVERWRITE the current auth state
8331
+ * 4. This causes auth.currentUser to become NULL even after it was set
8332
+ *
8333
+ * This method uses onAuthStateChanged to wait for the auth state to be SET and STABLE.
8334
+ * It ensures the auth state persists through AsyncStorage operations.
8335
+ *
8336
+ * @param expectedUid - The UID we expect to see in auth.currentUser
8337
+ * @param timeoutMs - Maximum time to wait (default 5 seconds)
8338
+ * @returns Promise that resolves when auth state is ready and stable
8339
+ */
8340
+ private waitForAuthStateToSettle;
8324
8341
  /**
8325
8342
  * Registruje novog korisnika sa email-om i lozinkom
8326
8343
  */
package/dist/index.js CHANGED
@@ -15402,6 +15402,73 @@ ${stackTrace}`);
15402
15402
  console.log("[AUTH] AuthService initialized");
15403
15403
  console.log("[AUTH] Initial auth.currentUser:", ((_a = this.auth.currentUser) == null ? void 0 : _a.uid) || "NULL");
15404
15404
  }
15405
+ /**
15406
+ * Waits for Firebase Auth state to settle after sign-in.
15407
+ *
15408
+ * In React Native with AsyncStorage persistence, there's a critical issue:
15409
+ * 1. signInWithCredential() sets auth.currentUser in memory immediately
15410
+ * 2. But AsyncStorage persistence happens asynchronously
15411
+ * 3. If AsyncStorage reads an old NULL value, it can OVERWRITE the current auth state
15412
+ * 4. This causes auth.currentUser to become NULL even after it was set
15413
+ *
15414
+ * This method uses onAuthStateChanged to wait for the auth state to be SET and STABLE.
15415
+ * It ensures the auth state persists through AsyncStorage operations.
15416
+ *
15417
+ * @param expectedUid - The UID we expect to see in auth.currentUser
15418
+ * @param timeoutMs - Maximum time to wait (default 5 seconds)
15419
+ * @returns Promise that resolves when auth state is ready and stable
15420
+ */
15421
+ async waitForAuthStateToSettle(expectedUid, timeoutMs = 5e3) {
15422
+ var _a, _b, _c;
15423
+ if (((_a = this.auth.currentUser) == null ? void 0 : _a.uid) === expectedUid) {
15424
+ console.log("[AUTH] Auth state appears set, waiting for stability...");
15425
+ await new Promise((resolve) => setTimeout(resolve, 200));
15426
+ if (((_b = this.auth.currentUser) == null ? void 0 : _b.uid) === expectedUid) {
15427
+ console.log("[AUTH] \u2705 Auth state stable for:", expectedUid);
15428
+ return;
15429
+ }
15430
+ }
15431
+ console.log("[AUTH] Waiting for auth state to settle for:", expectedUid);
15432
+ console.log("[AUTH] Current auth.currentUser:", ((_c = this.auth.currentUser) == null ? void 0 : _c.uid) || "NULL");
15433
+ return new Promise((resolve, reject) => {
15434
+ const startTime = Date.now();
15435
+ let resolved = false;
15436
+ const unsubscribe = (0, import_auth8.onAuthStateChanged)(this.auth, (user) => {
15437
+ if (resolved) return;
15438
+ const currentUid = (user == null ? void 0 : user.uid) || null;
15439
+ console.log("[AUTH] onAuthStateChanged fired:", currentUid || "NULL");
15440
+ if (currentUid === expectedUid) {
15441
+ setTimeout(() => {
15442
+ var _a2;
15443
+ if (resolved) return;
15444
+ if (((_a2 = this.auth.currentUser) == null ? void 0 : _a2.uid) === expectedUid) {
15445
+ resolved = true;
15446
+ unsubscribe();
15447
+ clearTimeout(timeout);
15448
+ const elapsed = Date.now() - startTime;
15449
+ console.log(`[AUTH] \u2705 Auth state settled and stable after ${elapsed}ms for:`, expectedUid);
15450
+ resolve();
15451
+ } else {
15452
+ console.warn("[AUTH] \u26A0\uFE0F Auth state became NULL after being set, waiting more...");
15453
+ }
15454
+ }, 300);
15455
+ } else if (currentUid === null && Date.now() - startTime > 1e3) {
15456
+ console.error("[AUTH] \u274C Auth state became NULL after being set!");
15457
+ console.error("[AUTH] This indicates AsyncStorage persistence issue");
15458
+ }
15459
+ });
15460
+ const timeout = setTimeout(() => {
15461
+ var _a2, _b2;
15462
+ if (resolved) return;
15463
+ resolved = true;
15464
+ unsubscribe();
15465
+ console.error("[AUTH] \u274C Timeout waiting for auth state to settle");
15466
+ console.error("[AUTH] Expected UID:", expectedUid);
15467
+ console.error("[AUTH] Actual auth.currentUser:", ((_a2 = this.auth.currentUser) == null ? void 0 : _a2.uid) || "NULL");
15468
+ reject(new Error(`Timeout waiting for auth state to settle. Expected: ${expectedUid}, Got: ${((_b2 = this.auth.currentUser) == null ? void 0 : _b2.uid) || "NULL"}`));
15469
+ }, timeoutMs);
15470
+ });
15471
+ }
15405
15472
  /**
15406
15473
  * Registruje novog korisnika sa email-om i lozinkom
15407
15474
  */
@@ -16154,6 +16221,9 @@ ${stackTrace}`);
16154
16221
  const credential = import_auth8.GoogleAuthProvider.credential(idToken);
16155
16222
  const { user: firebaseUser } = await (0, import_auth8.signInWithCredential)(this.auth, credential);
16156
16223
  console.log("[AUTH] Firebase user signed in:", firebaseUser.uid);
16224
+ console.log("[AUTH] Waiting for auth state to settle after sign-in...");
16225
+ await this.waitForAuthStateToSettle(firebaseUser.uid);
16226
+ console.log("[AUTH] \u2705 Auth state settled, proceeding with Firestore queries");
16157
16227
  const existingUser = await this.userService.getUserById(firebaseUser.uid);
16158
16228
  if (existingUser) {
16159
16229
  console.log("[AUTH] Existing user found, returning profile:", existingUser.uid);
@@ -16179,7 +16249,7 @@ ${stackTrace}`);
16179
16249
  * @returns Object containing user, practitioner (if exists), and draft profiles (if any)
16180
16250
  */
16181
16251
  async signUpPractitionerWithGoogle(idToken) {
16182
- var _a, _b, _c;
16252
+ var _a, _b, _c, _d;
16183
16253
  try {
16184
16254
  console.log("[AUTH] Starting practitioner Google Sign-In/Sign-Up");
16185
16255
  let email;
@@ -16213,6 +16283,9 @@ ${stackTrace}`);
16213
16283
  console.log("[AUTH] User exists with Google provider, signing in");
16214
16284
  const credential2 = import_auth8.GoogleAuthProvider.credential(idToken);
16215
16285
  const { user: firebaseUser2 } = await (0, import_auth8.signInWithCredential)(this.auth, credential2);
16286
+ console.log("[AUTH] Waiting for auth state to settle after sign-in...");
16287
+ await this.waitForAuthStateToSettle(firebaseUser2.uid);
16288
+ console.log("[AUTH] \u2705 Auth state settled, proceeding with Firestore queries");
16216
16289
  let existingUser2 = null;
16217
16290
  try {
16218
16291
  existingUser2 = await this.userService.getUserById(firebaseUser2.uid);
@@ -16224,6 +16297,13 @@ ${stackTrace}`);
16224
16297
  errorType: (_a = userError == null ? void 0 : userError.constructor) == null ? void 0 : _a.name,
16225
16298
  isAuthError: userError instanceof AuthError
16226
16299
  });
16300
+ if (!this.auth.currentUser || this.auth.currentUser.uid !== firebaseUser2.uid) {
16301
+ console.error("[AUTH] \u274C auth.currentUser became NULL before draft profile query!");
16302
+ console.error("[AUTH] Expected UID:", firebaseUser2.uid);
16303
+ console.error("[AUTH] Actual auth.currentUser:", ((_b = this.auth.currentUser) == null ? void 0 : _b.uid) || "NULL");
16304
+ console.log("[AUTH] Waiting for auth state to recover...");
16305
+ await this.waitForAuthStateToSettle(firebaseUser2.uid, 2e3);
16306
+ }
16227
16307
  const practitionerService2 = new PractitionerService(this.db, this.auth, this.app);
16228
16308
  const draftProfiles3 = await practitionerService2.getDraftProfilesByEmail(normalizedEmail);
16229
16309
  console.log("[AUTH] Draft profiles check result:", {
@@ -16245,7 +16325,7 @@ ${stackTrace}`);
16245
16325
  );
16246
16326
  }
16247
16327
  console.log("[AUTH] Draft profiles found, creating User document IMMEDIATELY after sign-in");
16248
- console.log("[AUTH] auth.currentUser at User creation time:", ((_b = this.auth.currentUser) == null ? void 0 : _b.uid) || "NULL");
16328
+ console.log("[AUTH] auth.currentUser at User creation time:", ((_c = this.auth.currentUser) == null ? void 0 : _c.uid) || "NULL");
16249
16329
  try {
16250
16330
  const newUser = await this.userService.createUser(firebaseUser2, ["practitioner" /* PRACTITIONER */], {
16251
16331
  skipProfileCreation: true
@@ -16313,6 +16393,9 @@ ${stackTrace}`);
16313
16393
  }
16314
16394
  throw error;
16315
16395
  }
16396
+ console.log("[AUTH] Waiting for auth state to settle after sign-in...");
16397
+ await this.waitForAuthStateToSettle(firebaseUser.uid);
16398
+ console.log("[AUTH] \u2705 Auth state settled, proceeding with Firestore queries");
16316
16399
  let existingUser = null;
16317
16400
  try {
16318
16401
  const existingUserDoc = await this.userService.getUserById(firebaseUser.uid);
@@ -16382,7 +16465,7 @@ ${stackTrace}`);
16382
16465
  };
16383
16466
  } catch (error) {
16384
16467
  console.error("[AUTH] Error in signUpPractitionerWithGoogle:", error);
16385
- console.error("[AUTH] Error type:", (_c = error == null ? void 0 : error.constructor) == null ? void 0 : _c.name);
16468
+ console.error("[AUTH] Error type:", (_d = error == null ? void 0 : error.constructor) == null ? void 0 : _d.name);
16386
16469
  console.error("[AUTH] Error instanceof AuthError:", error instanceof AuthError);
16387
16470
  console.error("[AUTH] Error code:", error == null ? void 0 : error.code);
16388
16471
  console.error("[AUTH] Error message:", error == null ? void 0 : error.message);
package/dist/index.mjs CHANGED
@@ -15489,6 +15489,73 @@ ${stackTrace}`);
15489
15489
  console.log("[AUTH] AuthService initialized");
15490
15490
  console.log("[AUTH] Initial auth.currentUser:", ((_a = this.auth.currentUser) == null ? void 0 : _a.uid) || "NULL");
15491
15491
  }
15492
+ /**
15493
+ * Waits for Firebase Auth state to settle after sign-in.
15494
+ *
15495
+ * In React Native with AsyncStorage persistence, there's a critical issue:
15496
+ * 1. signInWithCredential() sets auth.currentUser in memory immediately
15497
+ * 2. But AsyncStorage persistence happens asynchronously
15498
+ * 3. If AsyncStorage reads an old NULL value, it can OVERWRITE the current auth state
15499
+ * 4. This causes auth.currentUser to become NULL even after it was set
15500
+ *
15501
+ * This method uses onAuthStateChanged to wait for the auth state to be SET and STABLE.
15502
+ * It ensures the auth state persists through AsyncStorage operations.
15503
+ *
15504
+ * @param expectedUid - The UID we expect to see in auth.currentUser
15505
+ * @param timeoutMs - Maximum time to wait (default 5 seconds)
15506
+ * @returns Promise that resolves when auth state is ready and stable
15507
+ */
15508
+ async waitForAuthStateToSettle(expectedUid, timeoutMs = 5e3) {
15509
+ var _a, _b, _c;
15510
+ if (((_a = this.auth.currentUser) == null ? void 0 : _a.uid) === expectedUid) {
15511
+ console.log("[AUTH] Auth state appears set, waiting for stability...");
15512
+ await new Promise((resolve) => setTimeout(resolve, 200));
15513
+ if (((_b = this.auth.currentUser) == null ? void 0 : _b.uid) === expectedUid) {
15514
+ console.log("[AUTH] \u2705 Auth state stable for:", expectedUid);
15515
+ return;
15516
+ }
15517
+ }
15518
+ console.log("[AUTH] Waiting for auth state to settle for:", expectedUid);
15519
+ console.log("[AUTH] Current auth.currentUser:", ((_c = this.auth.currentUser) == null ? void 0 : _c.uid) || "NULL");
15520
+ return new Promise((resolve, reject) => {
15521
+ const startTime = Date.now();
15522
+ let resolved = false;
15523
+ const unsubscribe = onAuthStateChanged(this.auth, (user) => {
15524
+ if (resolved) return;
15525
+ const currentUid = (user == null ? void 0 : user.uid) || null;
15526
+ console.log("[AUTH] onAuthStateChanged fired:", currentUid || "NULL");
15527
+ if (currentUid === expectedUid) {
15528
+ setTimeout(() => {
15529
+ var _a2;
15530
+ if (resolved) return;
15531
+ if (((_a2 = this.auth.currentUser) == null ? void 0 : _a2.uid) === expectedUid) {
15532
+ resolved = true;
15533
+ unsubscribe();
15534
+ clearTimeout(timeout);
15535
+ const elapsed = Date.now() - startTime;
15536
+ console.log(`[AUTH] \u2705 Auth state settled and stable after ${elapsed}ms for:`, expectedUid);
15537
+ resolve();
15538
+ } else {
15539
+ console.warn("[AUTH] \u26A0\uFE0F Auth state became NULL after being set, waiting more...");
15540
+ }
15541
+ }, 300);
15542
+ } else if (currentUid === null && Date.now() - startTime > 1e3) {
15543
+ console.error("[AUTH] \u274C Auth state became NULL after being set!");
15544
+ console.error("[AUTH] This indicates AsyncStorage persistence issue");
15545
+ }
15546
+ });
15547
+ const timeout = setTimeout(() => {
15548
+ var _a2, _b2;
15549
+ if (resolved) return;
15550
+ resolved = true;
15551
+ unsubscribe();
15552
+ console.error("[AUTH] \u274C Timeout waiting for auth state to settle");
15553
+ console.error("[AUTH] Expected UID:", expectedUid);
15554
+ console.error("[AUTH] Actual auth.currentUser:", ((_a2 = this.auth.currentUser) == null ? void 0 : _a2.uid) || "NULL");
15555
+ reject(new Error(`Timeout waiting for auth state to settle. Expected: ${expectedUid}, Got: ${((_b2 = this.auth.currentUser) == null ? void 0 : _b2.uid) || "NULL"}`));
15556
+ }, timeoutMs);
15557
+ });
15558
+ }
15492
15559
  /**
15493
15560
  * Registruje novog korisnika sa email-om i lozinkom
15494
15561
  */
@@ -16241,6 +16308,9 @@ ${stackTrace}`);
16241
16308
  const credential = GoogleAuthProvider.credential(idToken);
16242
16309
  const { user: firebaseUser } = await signInWithCredential(this.auth, credential);
16243
16310
  console.log("[AUTH] Firebase user signed in:", firebaseUser.uid);
16311
+ console.log("[AUTH] Waiting for auth state to settle after sign-in...");
16312
+ await this.waitForAuthStateToSettle(firebaseUser.uid);
16313
+ console.log("[AUTH] \u2705 Auth state settled, proceeding with Firestore queries");
16244
16314
  const existingUser = await this.userService.getUserById(firebaseUser.uid);
16245
16315
  if (existingUser) {
16246
16316
  console.log("[AUTH] Existing user found, returning profile:", existingUser.uid);
@@ -16266,7 +16336,7 @@ ${stackTrace}`);
16266
16336
  * @returns Object containing user, practitioner (if exists), and draft profiles (if any)
16267
16337
  */
16268
16338
  async signUpPractitionerWithGoogle(idToken) {
16269
- var _a, _b, _c;
16339
+ var _a, _b, _c, _d;
16270
16340
  try {
16271
16341
  console.log("[AUTH] Starting practitioner Google Sign-In/Sign-Up");
16272
16342
  let email;
@@ -16300,6 +16370,9 @@ ${stackTrace}`);
16300
16370
  console.log("[AUTH] User exists with Google provider, signing in");
16301
16371
  const credential2 = GoogleAuthProvider.credential(idToken);
16302
16372
  const { user: firebaseUser2 } = await signInWithCredential(this.auth, credential2);
16373
+ console.log("[AUTH] Waiting for auth state to settle after sign-in...");
16374
+ await this.waitForAuthStateToSettle(firebaseUser2.uid);
16375
+ console.log("[AUTH] \u2705 Auth state settled, proceeding with Firestore queries");
16303
16376
  let existingUser2 = null;
16304
16377
  try {
16305
16378
  existingUser2 = await this.userService.getUserById(firebaseUser2.uid);
@@ -16311,6 +16384,13 @@ ${stackTrace}`);
16311
16384
  errorType: (_a = userError == null ? void 0 : userError.constructor) == null ? void 0 : _a.name,
16312
16385
  isAuthError: userError instanceof AuthError
16313
16386
  });
16387
+ if (!this.auth.currentUser || this.auth.currentUser.uid !== firebaseUser2.uid) {
16388
+ console.error("[AUTH] \u274C auth.currentUser became NULL before draft profile query!");
16389
+ console.error("[AUTH] Expected UID:", firebaseUser2.uid);
16390
+ console.error("[AUTH] Actual auth.currentUser:", ((_b = this.auth.currentUser) == null ? void 0 : _b.uid) || "NULL");
16391
+ console.log("[AUTH] Waiting for auth state to recover...");
16392
+ await this.waitForAuthStateToSettle(firebaseUser2.uid, 2e3);
16393
+ }
16314
16394
  const practitionerService2 = new PractitionerService(this.db, this.auth, this.app);
16315
16395
  const draftProfiles3 = await practitionerService2.getDraftProfilesByEmail(normalizedEmail);
16316
16396
  console.log("[AUTH] Draft profiles check result:", {
@@ -16332,7 +16412,7 @@ ${stackTrace}`);
16332
16412
  );
16333
16413
  }
16334
16414
  console.log("[AUTH] Draft profiles found, creating User document IMMEDIATELY after sign-in");
16335
- console.log("[AUTH] auth.currentUser at User creation time:", ((_b = this.auth.currentUser) == null ? void 0 : _b.uid) || "NULL");
16415
+ console.log("[AUTH] auth.currentUser at User creation time:", ((_c = this.auth.currentUser) == null ? void 0 : _c.uid) || "NULL");
16336
16416
  try {
16337
16417
  const newUser = await this.userService.createUser(firebaseUser2, ["practitioner" /* PRACTITIONER */], {
16338
16418
  skipProfileCreation: true
@@ -16400,6 +16480,9 @@ ${stackTrace}`);
16400
16480
  }
16401
16481
  throw error;
16402
16482
  }
16483
+ console.log("[AUTH] Waiting for auth state to settle after sign-in...");
16484
+ await this.waitForAuthStateToSettle(firebaseUser.uid);
16485
+ console.log("[AUTH] \u2705 Auth state settled, proceeding with Firestore queries");
16403
16486
  let existingUser = null;
16404
16487
  try {
16405
16488
  const existingUserDoc = await this.userService.getUserById(firebaseUser.uid);
@@ -16469,7 +16552,7 @@ ${stackTrace}`);
16469
16552
  };
16470
16553
  } catch (error) {
16471
16554
  console.error("[AUTH] Error in signUpPractitionerWithGoogle:", error);
16472
- console.error("[AUTH] Error type:", (_c = error == null ? void 0 : error.constructor) == null ? void 0 : _c.name);
16555
+ console.error("[AUTH] Error type:", (_d = error == null ? void 0 : error.constructor) == null ? void 0 : _d.name);
16473
16556
  console.error("[AUTH] Error instanceof AuthError:", error instanceof AuthError);
16474
16557
  console.error("[AUTH] Error code:", error == null ? void 0 : error.code);
16475
16558
  console.error("[AUTH] Error message:", error == null ? void 0 : error.message);
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@blackcode_sa/metaestetics-api",
3
3
  "private": false,
4
- "version": "1.14.16",
4
+ "version": "1.14.17",
5
5
  "description": "Firebase authentication service with anonymous upgrade support",
6
6
  "main": "dist/index.js",
7
7
  "module": "dist/index.mjs",
@@ -110,6 +110,87 @@ export class AuthService extends BaseService {
110
110
  console.log('[AUTH] Initial auth.currentUser:', this.auth.currentUser?.uid || 'NULL');
111
111
  }
112
112
 
113
+ /**
114
+ * Waits for Firebase Auth state to settle after sign-in.
115
+ *
116
+ * In React Native with AsyncStorage persistence, there's a critical issue:
117
+ * 1. signInWithCredential() sets auth.currentUser in memory immediately
118
+ * 2. But AsyncStorage persistence happens asynchronously
119
+ * 3. If AsyncStorage reads an old NULL value, it can OVERWRITE the current auth state
120
+ * 4. This causes auth.currentUser to become NULL even after it was set
121
+ *
122
+ * This method uses onAuthStateChanged to wait for the auth state to be SET and STABLE.
123
+ * It ensures the auth state persists through AsyncStorage operations.
124
+ *
125
+ * @param expectedUid - The UID we expect to see in auth.currentUser
126
+ * @param timeoutMs - Maximum time to wait (default 5 seconds)
127
+ * @returns Promise that resolves when auth state is ready and stable
128
+ */
129
+ private async waitForAuthStateToSettle(expectedUid: string, timeoutMs: number = 5000): Promise<void> {
130
+ // If already correct, still wait a bit to ensure it's stable (not just set in memory)
131
+ if (this.auth.currentUser?.uid === expectedUid) {
132
+ console.log('[AUTH] Auth state appears set, waiting for stability...');
133
+ // Wait a small amount to ensure AsyncStorage persistence completes
134
+ await new Promise(resolve => setTimeout(resolve, 200));
135
+ // Check again after wait
136
+ if (this.auth.currentUser?.uid === expectedUid) {
137
+ console.log('[AUTH] ✅ Auth state stable for:', expectedUid);
138
+ return;
139
+ }
140
+ }
141
+
142
+ console.log('[AUTH] Waiting for auth state to settle for:', expectedUid);
143
+ console.log('[AUTH] Current auth.currentUser:', this.auth.currentUser?.uid || 'NULL');
144
+
145
+ return new Promise((resolve, reject) => {
146
+ const startTime = Date.now();
147
+ let resolved = false;
148
+
149
+ // Use onAuthStateChanged to wait for auth state to be SET
150
+ // This is more reliable than polling auth.currentUser
151
+ const unsubscribe = onAuthStateChanged(this.auth, (user) => {
152
+ if (resolved) return;
153
+
154
+ const currentUid = user?.uid || null;
155
+ console.log('[AUTH] onAuthStateChanged fired:', currentUid || 'NULL');
156
+
157
+ if (currentUid === expectedUid) {
158
+ // Auth state is set, but wait a bit more to ensure it's stable
159
+ // AsyncStorage might still be writing/reading
160
+ setTimeout(() => {
161
+ if (resolved) return;
162
+
163
+ // Final check - is it still set?
164
+ if (this.auth.currentUser?.uid === expectedUid) {
165
+ resolved = true;
166
+ unsubscribe();
167
+ clearTimeout(timeout);
168
+ const elapsed = Date.now() - startTime;
169
+ console.log(`[AUTH] ✅ Auth state settled and stable after ${elapsed}ms for:`, expectedUid);
170
+ resolve();
171
+ } else {
172
+ console.warn('[AUTH] ⚠️ Auth state became NULL after being set, waiting more...');
173
+ }
174
+ }, 300); // Wait 300ms for AsyncStorage to stabilize
175
+ } else if (currentUid === null && Date.now() - startTime > 1000) {
176
+ // Auth state became NULL after being set - this is the bug we're trying to fix
177
+ console.error('[AUTH] ❌ Auth state became NULL after being set!');
178
+ console.error('[AUTH] This indicates AsyncStorage persistence issue');
179
+ }
180
+ });
181
+
182
+ const timeout = setTimeout(() => {
183
+ if (resolved) return;
184
+ resolved = true;
185
+ unsubscribe();
186
+ console.error('[AUTH] ❌ Timeout waiting for auth state to settle');
187
+ console.error('[AUTH] Expected UID:', expectedUid);
188
+ console.error('[AUTH] Actual auth.currentUser:', this.auth.currentUser?.uid || 'NULL');
189
+ reject(new Error(`Timeout waiting for auth state to settle. Expected: ${expectedUid}, Got: ${this.auth.currentUser?.uid || 'NULL'}`));
190
+ }, timeoutMs);
191
+ });
192
+ }
193
+
113
194
  /**
114
195
  * Registruje novog korisnika sa email-om i lozinkom
115
196
  */
@@ -1099,6 +1180,13 @@ export class AuthService extends BaseService {
1099
1180
  const { user: firebaseUser } = await signInWithCredential(this.auth, credential);
1100
1181
  console.log('[AUTH] Firebase user signed in:', firebaseUser.uid);
1101
1182
 
1183
+ // CRITICAL: Wait for auth state to settle before making Firestore queries
1184
+ // In React Native with AsyncStorage persistence, auth.currentUser can be NULL
1185
+ // immediately after signInWithCredential due to async persistence race condition
1186
+ console.log('[AUTH] Waiting for auth state to settle after sign-in...');
1187
+ await this.waitForAuthStateToSettle(firebaseUser.uid);
1188
+ console.log('[AUTH] ✅ Auth state settled, proceeding with Firestore queries');
1189
+
1102
1190
  // 4) Load our domain user document.
1103
1191
  const existingUser = await this.userService.getUserById(firebaseUser.uid);
1104
1192
  if (existingUser) {
@@ -1179,6 +1267,13 @@ export class AuthService extends BaseService {
1179
1267
  const credential = GoogleAuthProvider.credential(idToken);
1180
1268
  const { user: firebaseUser } = await signInWithCredential(this.auth, credential);
1181
1269
 
1270
+ // CRITICAL: Wait for auth state to settle before making Firestore queries
1271
+ // In React Native with AsyncStorage persistence, auth.currentUser can be NULL
1272
+ // immediately after signInWithCredential due to async persistence race condition
1273
+ console.log('[AUTH] Waiting for auth state to settle after sign-in...');
1274
+ await this.waitForAuthStateToSettle(firebaseUser.uid);
1275
+ console.log('[AUTH] ✅ Auth state settled, proceeding with Firestore queries');
1276
+
1182
1277
  let existingUser: User | null = null;
1183
1278
  try {
1184
1279
  existingUser = await this.userService.getUserById(firebaseUser.uid);
@@ -1193,6 +1288,17 @@ export class AuthService extends BaseService {
1193
1288
  });
1194
1289
 
1195
1290
  // Check for draft profiles before signing out
1291
+ // CRITICAL: Verify auth.currentUser is still set before Firestore query
1292
+ // AsyncStorage persistence can cause it to become NULL even after being set
1293
+ if (!this.auth.currentUser || this.auth.currentUser.uid !== firebaseUser.uid) {
1294
+ console.error('[AUTH] ❌ auth.currentUser became NULL before draft profile query!');
1295
+ console.error('[AUTH] Expected UID:', firebaseUser.uid);
1296
+ console.error('[AUTH] Actual auth.currentUser:', this.auth.currentUser?.uid || 'NULL');
1297
+ console.log('[AUTH] Waiting for auth state to recover...');
1298
+ // Try to wait for it to come back
1299
+ await this.waitForAuthStateToSettle(firebaseUser.uid, 2000);
1300
+ }
1301
+
1196
1302
  const practitionerService = new PractitionerService(this.db, this.auth, this.app);
1197
1303
  const draftProfiles = await practitionerService.getDraftProfilesByEmail(normalizedEmail);
1198
1304
 
@@ -1309,6 +1415,13 @@ export class AuthService extends BaseService {
1309
1415
  throw error;
1310
1416
  }
1311
1417
 
1418
+ // CRITICAL: Wait for auth state to settle before making Firestore queries
1419
+ // In React Native with AsyncStorage persistence, auth.currentUser can be NULL
1420
+ // immediately after signInWithCredential due to async persistence race condition
1421
+ console.log('[AUTH] Waiting for auth state to settle after sign-in...');
1422
+ await this.waitForAuthStateToSettle(firebaseUser.uid);
1423
+ console.log('[AUTH] ✅ Auth state settled, proceeding with Firestore queries');
1424
+
1312
1425
  // Check for existing User document (in case user had email/password account that was just linked)
1313
1426
  let existingUser: User | null = null;
1314
1427
  try {