@blackcode_sa/metaestetics-api 1.14.15 → 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
@@ -8323,14 +8323,21 @@ declare class AuthService extends BaseService {
8323
8323
  constructor(db: Firestore, auth: Auth, app: FirebaseApp, userService: UserService);
8324
8324
  /**
8325
8325
  * Waits for Firebase Auth state to settle after sign-in.
8326
- * In React Native with Firebase JS SDK, auth.currentUser doesn't update synchronously
8327
- * after signInWithCredential. This causes Firestore permission issues.
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.
8328
8335
  *
8329
8336
  * @param expectedUid - The UID we expect to see in auth.currentUser
8330
- * @param timeoutMs - Maximum time to wait (default 10 seconds)
8331
- * @returns Promise that resolves when auth state is ready
8337
+ * @param timeoutMs - Maximum time to wait (default 5 seconds)
8338
+ * @returns Promise that resolves when auth state is ready and stable
8332
8339
  */
8333
- private waitForAuthState;
8340
+ private waitForAuthStateToSettle;
8334
8341
  /**
8335
8342
  * Registruje novog korisnika sa email-om i lozinkom
8336
8343
  */
package/dist/index.d.ts CHANGED
@@ -8323,14 +8323,21 @@ declare class AuthService extends BaseService {
8323
8323
  constructor(db: Firestore, auth: Auth, app: FirebaseApp, userService: UserService);
8324
8324
  /**
8325
8325
  * Waits for Firebase Auth state to settle after sign-in.
8326
- * In React Native with Firebase JS SDK, auth.currentUser doesn't update synchronously
8327
- * after signInWithCredential. This causes Firestore permission issues.
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.
8328
8335
  *
8329
8336
  * @param expectedUid - The UID we expect to see in auth.currentUser
8330
- * @param timeoutMs - Maximum time to wait (default 10 seconds)
8331
- * @returns Promise that resolves when auth state is ready
8337
+ * @param timeoutMs - Maximum time to wait (default 5 seconds)
8338
+ * @returns Promise that resolves when auth state is ready and stable
8332
8339
  */
8333
- private waitForAuthState;
8340
+ private waitForAuthStateToSettle;
8334
8341
  /**
8335
8342
  * Registruje novog korisnika sa email-om i lozinkom
8336
8343
  */
package/dist/index.js CHANGED
@@ -15388,44 +15388,85 @@ var AuthService = class extends BaseService {
15388
15388
  super(db, auth, app);
15389
15389
  this.googleProvider = new import_auth8.GoogleAuthProvider();
15390
15390
  this.userService = userService || new UserService(db, auth, app);
15391
- if (!this.auth.__authServiceId) {
15392
- this.auth.__authServiceId = "auth-service-" + Date.now();
15393
- }
15394
- console.log("[AUTH] AuthService constructor - auth ID:", this.auth.__authServiceId);
15395
- console.log("[AUTH] AuthService constructor - userService.auth ID:", ((_a = this.userService.auth) == null ? void 0 : _a.__authServiceId) || "NOT SET");
15391
+ (0, import_auth8.onAuthStateChanged)(this.auth, (user) => {
15392
+ var _a2, _b;
15393
+ const timestamp = (/* @__PURE__ */ new Date()).toISOString();
15394
+ const stackTrace = ((_a2 = new Error().stack) == null ? void 0 : _a2.split("\n").slice(2, 5).join("\n")) || "N/A";
15395
+ console.log(`[AUTH STATE CHANGE] ${timestamp}`);
15396
+ console.log(`[AUTH STATE CHANGE] User: ${(user == null ? void 0 : user.uid) || "NULL"} (email: ${(user == null ? void 0 : user.email) || "N/A"})`);
15397
+ console.log(`[AUTH STATE CHANGE] auth.currentUser: ${((_b = this.auth.currentUser) == null ? void 0 : _b.uid) || "NULL"}`);
15398
+ console.log(`[AUTH STATE CHANGE] Stack trace (first 3 frames):
15399
+ ${stackTrace}`);
15400
+ console.log("[AUTH STATE CHANGE] ---");
15401
+ });
15402
+ console.log("[AUTH] AuthService initialized");
15403
+ console.log("[AUTH] Initial auth.currentUser:", ((_a = this.auth.currentUser) == null ? void 0 : _a.uid) || "NULL");
15396
15404
  }
15397
15405
  /**
15398
15406
  * Waits for Firebase Auth state to settle after sign-in.
15399
- * In React Native with Firebase JS SDK, auth.currentUser doesn't update synchronously
15400
- * after signInWithCredential. This causes Firestore permission issues.
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.
15401
15416
  *
15402
15417
  * @param expectedUid - The UID we expect to see in auth.currentUser
15403
- * @param timeoutMs - Maximum time to wait (default 10 seconds)
15404
- * @returns Promise that resolves when auth state is ready
15418
+ * @param timeoutMs - Maximum time to wait (default 5 seconds)
15419
+ * @returns Promise that resolves when auth state is ready and stable
15405
15420
  */
15406
- waitForAuthState(expectedUid, timeoutMs = 1e4) {
15407
- return new Promise((resolve, reject) => {
15408
- var _a;
15409
- if (((_a = this.auth.currentUser) == null ? void 0 : _a.uid) === expectedUid) {
15410
- console.log("[AUTH] Auth state already settled for:", expectedUid);
15411
- resolve();
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);
15412
15428
  return;
15413
15429
  }
15414
- console.log("[AUTH] Waiting for auth state to settle for:", expectedUid);
15415
- const timeout = setTimeout(() => {
15416
- unsubscribe();
15417
- console.error("[AUTH] Timeout waiting for auth state");
15418
- reject(new Error("Timeout waiting for auth state to settle"));
15419
- }, timeoutMs);
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;
15420
15436
  const unsubscribe = (0, import_auth8.onAuthStateChanged)(this.auth, (user) => {
15421
- console.log("[AUTH] Auth state changed:", (user == null ? void 0 : user.uid) || "null");
15422
- if ((user == null ? void 0 : user.uid) === expectedUid) {
15423
- clearTimeout(timeout);
15424
- unsubscribe();
15425
- console.log("[AUTH] Auth state settled successfully for:", expectedUid);
15426
- resolve();
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");
15427
15458
  }
15428
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);
15429
15470
  });
15430
15471
  }
15431
15472
  /**
@@ -16180,6 +16221,9 @@ var AuthService = class extends BaseService {
16180
16221
  const credential = import_auth8.GoogleAuthProvider.credential(idToken);
16181
16222
  const { user: firebaseUser } = await (0, import_auth8.signInWithCredential)(this.auth, credential);
16182
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");
16183
16227
  const existingUser = await this.userService.getUserById(firebaseUser.uid);
16184
16228
  if (existingUser) {
16185
16229
  console.log("[AUTH] Existing user found, returning profile:", existingUser.uid);
@@ -16205,7 +16249,7 @@ var AuthService = class extends BaseService {
16205
16249
  * @returns Object containing user, practitioner (if exists), and draft profiles (if any)
16206
16250
  */
16207
16251
  async signUpPractitionerWithGoogle(idToken) {
16208
- var _a, _b, _c;
16252
+ var _a, _b, _c, _d;
16209
16253
  try {
16210
16254
  console.log("[AUTH] Starting practitioner Google Sign-In/Sign-Up");
16211
16255
  let email;
@@ -16239,6 +16283,9 @@ var AuthService = class extends BaseService {
16239
16283
  console.log("[AUTH] User exists with Google provider, signing in");
16240
16284
  const credential2 = import_auth8.GoogleAuthProvider.credential(idToken);
16241
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");
16242
16289
  let existingUser2 = null;
16243
16290
  try {
16244
16291
  existingUser2 = await this.userService.getUserById(firebaseUser2.uid);
@@ -16250,6 +16297,13 @@ var AuthService = class extends BaseService {
16250
16297
  errorType: (_a = userError == null ? void 0 : userError.constructor) == null ? void 0 : _a.name,
16251
16298
  isAuthError: userError instanceof AuthError
16252
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
+ }
16253
16307
  const practitionerService2 = new PractitionerService(this.db, this.auth, this.app);
16254
16308
  const draftProfiles3 = await practitionerService2.getDraftProfilesByEmail(normalizedEmail);
16255
16309
  console.log("[AUTH] Draft profiles check result:", {
@@ -16271,7 +16325,7 @@ var AuthService = class extends BaseService {
16271
16325
  );
16272
16326
  }
16273
16327
  console.log("[AUTH] Draft profiles found, creating User document IMMEDIATELY after sign-in");
16274
- 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");
16275
16329
  try {
16276
16330
  const newUser = await this.userService.createUser(firebaseUser2, ["practitioner" /* PRACTITIONER */], {
16277
16331
  skipProfileCreation: true
@@ -16339,6 +16393,9 @@ var AuthService = class extends BaseService {
16339
16393
  }
16340
16394
  throw error;
16341
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");
16342
16399
  let existingUser = null;
16343
16400
  try {
16344
16401
  const existingUserDoc = await this.userService.getUserById(firebaseUser.uid);
@@ -16408,7 +16465,7 @@ var AuthService = class extends BaseService {
16408
16465
  };
16409
16466
  } catch (error) {
16410
16467
  console.error("[AUTH] Error in signUpPractitionerWithGoogle:", error);
16411
- 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);
16412
16469
  console.error("[AUTH] Error instanceof AuthError:", error instanceof AuthError);
16413
16470
  console.error("[AUTH] Error code:", error == null ? void 0 : error.code);
16414
16471
  console.error("[AUTH] Error message:", error == null ? void 0 : error.message);
package/dist/index.mjs CHANGED
@@ -15475,44 +15475,85 @@ var AuthService = class extends BaseService {
15475
15475
  super(db, auth, app);
15476
15476
  this.googleProvider = new GoogleAuthProvider();
15477
15477
  this.userService = userService || new UserService(db, auth, app);
15478
- if (!this.auth.__authServiceId) {
15479
- this.auth.__authServiceId = "auth-service-" + Date.now();
15480
- }
15481
- console.log("[AUTH] AuthService constructor - auth ID:", this.auth.__authServiceId);
15482
- console.log("[AUTH] AuthService constructor - userService.auth ID:", ((_a = this.userService.auth) == null ? void 0 : _a.__authServiceId) || "NOT SET");
15478
+ onAuthStateChanged(this.auth, (user) => {
15479
+ var _a2, _b;
15480
+ const timestamp = (/* @__PURE__ */ new Date()).toISOString();
15481
+ const stackTrace = ((_a2 = new Error().stack) == null ? void 0 : _a2.split("\n").slice(2, 5).join("\n")) || "N/A";
15482
+ console.log(`[AUTH STATE CHANGE] ${timestamp}`);
15483
+ console.log(`[AUTH STATE CHANGE] User: ${(user == null ? void 0 : user.uid) || "NULL"} (email: ${(user == null ? void 0 : user.email) || "N/A"})`);
15484
+ console.log(`[AUTH STATE CHANGE] auth.currentUser: ${((_b = this.auth.currentUser) == null ? void 0 : _b.uid) || "NULL"}`);
15485
+ console.log(`[AUTH STATE CHANGE] Stack trace (first 3 frames):
15486
+ ${stackTrace}`);
15487
+ console.log("[AUTH STATE CHANGE] ---");
15488
+ });
15489
+ console.log("[AUTH] AuthService initialized");
15490
+ console.log("[AUTH] Initial auth.currentUser:", ((_a = this.auth.currentUser) == null ? void 0 : _a.uid) || "NULL");
15483
15491
  }
15484
15492
  /**
15485
15493
  * Waits for Firebase Auth state to settle after sign-in.
15486
- * In React Native with Firebase JS SDK, auth.currentUser doesn't update synchronously
15487
- * after signInWithCredential. This causes Firestore permission issues.
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.
15488
15503
  *
15489
15504
  * @param expectedUid - The UID we expect to see in auth.currentUser
15490
- * @param timeoutMs - Maximum time to wait (default 10 seconds)
15491
- * @returns Promise that resolves when auth state is ready
15505
+ * @param timeoutMs - Maximum time to wait (default 5 seconds)
15506
+ * @returns Promise that resolves when auth state is ready and stable
15492
15507
  */
15493
- waitForAuthState(expectedUid, timeoutMs = 1e4) {
15494
- return new Promise((resolve, reject) => {
15495
- var _a;
15496
- if (((_a = this.auth.currentUser) == null ? void 0 : _a.uid) === expectedUid) {
15497
- console.log("[AUTH] Auth state already settled for:", expectedUid);
15498
- resolve();
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);
15499
15515
  return;
15500
15516
  }
15501
- console.log("[AUTH] Waiting for auth state to settle for:", expectedUid);
15502
- const timeout = setTimeout(() => {
15503
- unsubscribe();
15504
- console.error("[AUTH] Timeout waiting for auth state");
15505
- reject(new Error("Timeout waiting for auth state to settle"));
15506
- }, timeoutMs);
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;
15507
15523
  const unsubscribe = onAuthStateChanged(this.auth, (user) => {
15508
- console.log("[AUTH] Auth state changed:", (user == null ? void 0 : user.uid) || "null");
15509
- if ((user == null ? void 0 : user.uid) === expectedUid) {
15510
- clearTimeout(timeout);
15511
- unsubscribe();
15512
- console.log("[AUTH] Auth state settled successfully for:", expectedUid);
15513
- resolve();
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");
15514
15545
  }
15515
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);
15516
15557
  });
15517
15558
  }
15518
15559
  /**
@@ -16267,6 +16308,9 @@ var AuthService = class extends BaseService {
16267
16308
  const credential = GoogleAuthProvider.credential(idToken);
16268
16309
  const { user: firebaseUser } = await signInWithCredential(this.auth, credential);
16269
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");
16270
16314
  const existingUser = await this.userService.getUserById(firebaseUser.uid);
16271
16315
  if (existingUser) {
16272
16316
  console.log("[AUTH] Existing user found, returning profile:", existingUser.uid);
@@ -16292,7 +16336,7 @@ var AuthService = class extends BaseService {
16292
16336
  * @returns Object containing user, practitioner (if exists), and draft profiles (if any)
16293
16337
  */
16294
16338
  async signUpPractitionerWithGoogle(idToken) {
16295
- var _a, _b, _c;
16339
+ var _a, _b, _c, _d;
16296
16340
  try {
16297
16341
  console.log("[AUTH] Starting practitioner Google Sign-In/Sign-Up");
16298
16342
  let email;
@@ -16326,6 +16370,9 @@ var AuthService = class extends BaseService {
16326
16370
  console.log("[AUTH] User exists with Google provider, signing in");
16327
16371
  const credential2 = GoogleAuthProvider.credential(idToken);
16328
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");
16329
16376
  let existingUser2 = null;
16330
16377
  try {
16331
16378
  existingUser2 = await this.userService.getUserById(firebaseUser2.uid);
@@ -16337,6 +16384,13 @@ var AuthService = class extends BaseService {
16337
16384
  errorType: (_a = userError == null ? void 0 : userError.constructor) == null ? void 0 : _a.name,
16338
16385
  isAuthError: userError instanceof AuthError
16339
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
+ }
16340
16394
  const practitionerService2 = new PractitionerService(this.db, this.auth, this.app);
16341
16395
  const draftProfiles3 = await practitionerService2.getDraftProfilesByEmail(normalizedEmail);
16342
16396
  console.log("[AUTH] Draft profiles check result:", {
@@ -16358,7 +16412,7 @@ var AuthService = class extends BaseService {
16358
16412
  );
16359
16413
  }
16360
16414
  console.log("[AUTH] Draft profiles found, creating User document IMMEDIATELY after sign-in");
16361
- 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");
16362
16416
  try {
16363
16417
  const newUser = await this.userService.createUser(firebaseUser2, ["practitioner" /* PRACTITIONER */], {
16364
16418
  skipProfileCreation: true
@@ -16426,6 +16480,9 @@ var AuthService = class extends BaseService {
16426
16480
  }
16427
16481
  throw error;
16428
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");
16429
16486
  let existingUser = null;
16430
16487
  try {
16431
16488
  const existingUserDoc = await this.userService.getUserById(firebaseUser.uid);
@@ -16495,7 +16552,7 @@ var AuthService = class extends BaseService {
16495
16552
  };
16496
16553
  } catch (error) {
16497
16554
  console.error("[AUTH] Error in signUpPractitionerWithGoogle:", error);
16498
- 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);
16499
16556
  console.error("[AUTH] Error instanceof AuthError:", error instanceof AuthError);
16500
16557
  console.error("[AUTH] Error code:", error == null ? void 0 : error.code);
16501
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.15",
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",
@@ -92,53 +92,102 @@ export class AuthService extends BaseService {
92
92
  super(db, auth, app);
93
93
  this.userService = userService || new UserService(db, auth, app);
94
94
 
95
- // DEBUG: Tag the auth instances to track them
96
- // @ts-ignore
97
- if (!this.auth.__authServiceId) {
98
- // @ts-ignore
99
- this.auth.__authServiceId = 'auth-service-' + Date.now();
100
- }
101
- // @ts-ignore
102
- console.log('[AUTH] AuthService constructor - auth ID:', this.auth.__authServiceId);
103
- // @ts-ignore
104
- console.log('[AUTH] AuthService constructor - userService.auth ID:', (this.userService as any).auth?.__authServiceId || 'NOT SET');
95
+ // Initialize auth state change listener for debugging
96
+ // This helps track when auth.currentUser changes, which is critical for debugging
97
+ // the permission-denied issue during user document creation
98
+ onAuthStateChanged(this.auth, (user) => {
99
+ const timestamp = new Date().toISOString();
100
+ const stackTrace = new Error().stack?.split('\n').slice(2, 5).join('\n') || 'N/A';
101
+ console.log(`[AUTH STATE CHANGE] ${timestamp}`);
102
+ console.log(`[AUTH STATE CHANGE] User: ${user?.uid || 'NULL'} (email: ${user?.email || 'N/A'})`);
103
+ console.log(`[AUTH STATE CHANGE] auth.currentUser: ${this.auth.currentUser?.uid || 'NULL'}`);
104
+ console.log(`[AUTH STATE CHANGE] Stack trace (first 3 frames):\n${stackTrace}`);
105
+ console.log('[AUTH STATE CHANGE] ---');
106
+ });
107
+
108
+ // Log initial auth state
109
+ console.log('[AUTH] AuthService initialized');
110
+ console.log('[AUTH] Initial auth.currentUser:', this.auth.currentUser?.uid || 'NULL');
105
111
  }
106
112
 
107
113
  /**
108
114
  * Waits for Firebase Auth state to settle after sign-in.
109
- * In React Native with Firebase JS SDK, auth.currentUser doesn't update synchronously
110
- * after signInWithCredential. This causes Firestore permission issues.
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.
111
124
  *
112
125
  * @param expectedUid - The UID we expect to see in auth.currentUser
113
- * @param timeoutMs - Maximum time to wait (default 10 seconds)
114
- * @returns Promise that resolves when auth state is ready
126
+ * @param timeoutMs - Maximum time to wait (default 5 seconds)
127
+ * @returns Promise that resolves when auth state is ready and stable
115
128
  */
116
- private waitForAuthState(expectedUid: string, timeoutMs: number = 10000): Promise<void> {
117
- return new Promise((resolve, reject) => {
118
- // If already correct, resolve immediately
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
119
136
  if (this.auth.currentUser?.uid === expectedUid) {
120
- console.log('[AUTH] Auth state already settled for:', expectedUid);
121
- resolve();
137
+ console.log('[AUTH] Auth state stable for:', expectedUid);
122
138
  return;
123
139
  }
140
+ }
124
141
 
125
- console.log('[AUTH] Waiting for auth state to settle for:', expectedUid);
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;
126
148
 
127
- const timeout = setTimeout(() => {
128
- unsubscribe();
129
- console.error('[AUTH] Timeout waiting for auth state');
130
- reject(new Error('Timeout waiting for auth state to settle'));
131
- }, timeoutMs);
132
-
149
+ // Use onAuthStateChanged to wait for auth state to be SET
150
+ // This is more reliable than polling auth.currentUser
133
151
  const unsubscribe = onAuthStateChanged(this.auth, (user) => {
134
- console.log('[AUTH] Auth state changed:', user?.uid || 'null');
135
- if (user?.uid === expectedUid) {
136
- clearTimeout(timeout);
137
- unsubscribe();
138
- console.log('[AUTH] Auth state settled successfully for:', expectedUid);
139
- resolve();
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');
140
179
  }
141
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);
142
191
  });
143
192
  }
144
193
 
@@ -1131,6 +1180,13 @@ export class AuthService extends BaseService {
1131
1180
  const { user: firebaseUser } = await signInWithCredential(this.auth, credential);
1132
1181
  console.log('[AUTH] Firebase user signed in:', firebaseUser.uid);
1133
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
+
1134
1190
  // 4) Load our domain user document.
1135
1191
  const existingUser = await this.userService.getUserById(firebaseUser.uid);
1136
1192
  if (existingUser) {
@@ -1211,6 +1267,13 @@ export class AuthService extends BaseService {
1211
1267
  const credential = GoogleAuthProvider.credential(idToken);
1212
1268
  const { user: firebaseUser } = await signInWithCredential(this.auth, credential);
1213
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
+
1214
1277
  let existingUser: User | null = null;
1215
1278
  try {
1216
1279
  existingUser = await this.userService.getUserById(firebaseUser.uid);
@@ -1225,6 +1288,17 @@ export class AuthService extends BaseService {
1225
1288
  });
1226
1289
 
1227
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
+
1228
1302
  const practitionerService = new PractitionerService(this.db, this.auth, this.app);
1229
1303
  const draftProfiles = await practitionerService.getDraftProfilesByEmail(normalizedEmail);
1230
1304
 
@@ -1341,6 +1415,13 @@ export class AuthService extends BaseService {
1341
1415
  throw error;
1342
1416
  }
1343
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
+
1344
1425
  // Check for existing User document (in case user had email/password account that was just linked)
1345
1426
  let existingUser: User | null = null;
1346
1427
  try {