@umituz/react-native-auth 3.6.51 → 3.6.52

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.
Files changed (29) hide show
  1. package/package.json +1 -1
  2. package/src/infrastructure/adapters/StorageProviderAdapter.ts +5 -6
  3. package/src/infrastructure/adapters/UIProviderAdapter.ts +6 -13
  4. package/src/infrastructure/providers/FirebaseAuthProvider.ts +1 -4
  5. package/src/infrastructure/repositories/AuthRepository.ts +16 -15
  6. package/src/infrastructure/services/AnonymousModeService.ts +16 -7
  7. package/src/infrastructure/services/AuthEventService.ts +4 -2
  8. package/src/infrastructure/services/AuthService.ts +2 -3
  9. package/src/infrastructure/services/UserDocumentService.ts +6 -6
  10. package/src/infrastructure/services/initializeAuth.ts +27 -3
  11. package/src/infrastructure/types/UI.types.ts +1 -2
  12. package/src/infrastructure/utils/AuthErrorMapper.ts +0 -5
  13. package/src/infrastructure/utils/AuthValidation.ts +0 -1
  14. package/src/infrastructure/utils/UserMapper.ts +5 -5
  15. package/src/infrastructure/utils/authStateHandler.ts +4 -2
  16. package/src/infrastructure/utils/userDocumentBuilder.util.ts +1 -1
  17. package/src/init/createAuthInitModule.ts +5 -7
  18. package/src/presentation/components/AccountActions.tsx +4 -2
  19. package/src/presentation/components/AuthBottomSheet.tsx +0 -2
  20. package/src/presentation/hooks/useAppleAuth.ts +1 -2
  21. package/src/presentation/hooks/useAuth.ts +4 -1
  22. package/src/presentation/hooks/useAuthBottomSheet.ts +3 -5
  23. package/src/presentation/hooks/useGoogleAuth.ts +4 -2
  24. package/src/presentation/hooks/useLoginForm.ts +4 -2
  25. package/src/presentation/hooks/useRegisterForm.ts +3 -3
  26. package/src/presentation/hooks/useSocialLogin.ts +1 -2
  27. package/src/presentation/stores/authModalStore.ts +1 -1
  28. package/src/presentation/stores/authStore.ts +2 -2
  29. package/src/presentation/stores/initializeAuthListener.ts +5 -7
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@umituz/react-native-auth",
3
- "version": "3.6.51",
3
+ "version": "3.6.52",
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",
@@ -9,11 +9,10 @@ import type { IStorageProvider } from "../types/Storage.types";
9
9
  * Interface that describes the shape of common storage implementations
10
10
  * to avoid using 'any' and resolve lint errors.
11
11
  */
12
- interface StorageLike {
12
+ export interface StorageLike {
13
13
  getString?: (
14
14
  key: string,
15
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
16
- defaultValue?: any
15
+ defaultValue?: string | null
17
16
  ) => Promise<{ value: string | null } | null>;
18
17
  getItem?: (key: string) => Promise<string | null>;
19
18
  setString?: (key: string, value: string) => Promise<void>;
@@ -24,8 +23,8 @@ interface StorageLike {
24
23
  export class StorageProviderAdapter implements IStorageProvider {
25
24
  private storage: StorageLike;
26
25
 
27
- constructor(storage: unknown) {
28
- this.storage = storage as StorageLike;
26
+ constructor(storage: StorageLike) {
27
+ this.storage = storage;
29
28
  }
30
29
 
31
30
  async get(key: string): Promise<string | null> {
@@ -62,6 +61,6 @@ export class StorageProviderAdapter implements IStorageProvider {
62
61
  }
63
62
  }
64
63
 
65
- export function createStorageProvider(storage: unknown): IStorageProvider {
64
+ export function createStorageProvider(storage: StorageLike): IStorageProvider {
66
65
  return new StorageProviderAdapter(storage);
67
66
  }
@@ -8,13 +8,10 @@ import type { IUIProvider } from "../types/UI.types";
8
8
 
9
9
  export class UIProviderAdapter implements IUIProvider {
10
10
  private theme: DesignTokens | null = null;
11
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
12
- private localization: any = null;
11
+ private localization: Record<string, unknown> | null = null;
13
12
 
14
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
15
- constructor(theme?: DesignTokens, localization?: any) {
13
+ constructor(theme?: DesignTokens, localization?: Record<string, unknown>) {
16
14
  this.theme = theme || null;
17
- // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
18
15
  this.localization = localization || null;
19
16
  }
20
17
 
@@ -22,8 +19,7 @@ export class UIProviderAdapter implements IUIProvider {
22
19
  return this.theme;
23
20
  }
24
21
 
25
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
26
- getLocalization(): any {
22
+ getLocalization(): Record<string, unknown> | null {
27
23
  return this.localization;
28
24
  }
29
25
 
@@ -31,9 +27,7 @@ export class UIProviderAdapter implements IUIProvider {
31
27
  this.theme = theme;
32
28
  }
33
29
 
34
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
35
- updateLocalization(localization: any): void {
36
- // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
30
+ updateLocalization(localization: Record<string, unknown>): void {
37
31
  this.localization = localization;
38
32
  }
39
33
  }
@@ -43,8 +37,7 @@ export class UIProviderAdapter implements IUIProvider {
43
37
  */
44
38
  export function createUIProvider(
45
39
  theme?: DesignTokens,
46
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
47
- localization?: any
40
+ localization?: Record<string, unknown>
48
41
  ): IUIProvider {
49
42
  return new UIProviderAdapter(theme, localization);
50
- }
43
+ }
@@ -14,7 +14,6 @@ import {
14
14
  type Auth,
15
15
  } from "firebase/auth";
16
16
 
17
- declare const __DEV__: boolean;
18
17
  import type {
19
18
  IAuthProvider,
20
19
  AuthCredentials,
@@ -37,8 +36,6 @@ export class FirebaseAuthProvider implements IAuthProvider {
37
36
  if (!this.auth) {
38
37
  throw new Error("Firebase Auth instance must be provided");
39
38
  }
40
- // Satisfy require-await
41
- await Promise.resolve();
42
39
  }
43
40
 
44
41
  setAuth(auth: Auth): void {
@@ -169,7 +166,7 @@ export class FirebaseAuthProvider implements IAuthProvider {
169
166
  onAuthStateChange(callback: (user: AuthUser | null) => void): () => void {
170
167
  if (!this.auth) {
171
168
  callback(null);
172
- return () => { };
169
+ return () => {};
173
170
  }
174
171
 
175
172
  return onAuthStateChanged(this.auth, (user) => {
@@ -20,6 +20,7 @@ import {
20
20
  validateDisplayName,
21
21
  } from "../utils/AuthValidation";
22
22
  import type { AuthConfig } from "../../domain/value-objects/AuthConfig";
23
+ import { sanitizeEmail, sanitizeName, sanitizePassword } from "../utils/validation/sanitization";
23
24
 
24
25
  export class AuthRepository implements IAuthRepository {
25
26
  private provider: IAuthProvider;
@@ -31,50 +32,50 @@ export class AuthRepository implements IAuthRepository {
31
32
  }
32
33
 
33
34
  async signUp(params: SignUpParams): Promise<AuthUser> {
35
+ const email = sanitizeEmail(params.email);
36
+ const password = sanitizePassword(params.password);
37
+ const displayName = params.displayName ? sanitizeName(params.displayName) : undefined;
38
+
34
39
  // Validate email
35
- const emailResult = validateEmail(params.email);
40
+ const emailResult = validateEmail(email);
36
41
  if (!emailResult.isValid) {
37
42
  throw new AuthInvalidEmailError(emailResult.error);
38
43
  }
39
44
 
40
45
  // Validate display name if provided
41
- if (params.displayName) {
42
- const nameResult = validateDisplayName(params.displayName);
46
+ if (displayName) {
47
+ const nameResult = validateDisplayName(displayName);
43
48
  if (!nameResult.isValid) {
44
49
  throw new AuthValidationError(nameResult.error || "Invalid name", "displayName");
45
50
  }
46
51
  }
47
52
 
48
53
  // Validate password strength for registration
49
- const passwordResult = validatePasswordForRegister(params.password, this.config.password);
54
+ const passwordResult = validatePasswordForRegister(password, this.config.password);
50
55
  if (!passwordResult.isValid) {
51
56
  throw new AuthWeakPasswordError(passwordResult.error);
52
57
  }
53
58
 
54
- return this.provider.signUp({
55
- email: params.email,
56
- password: params.password,
57
- displayName: params.displayName,
58
- });
59
+ return this.provider.signUp({ email, password, displayName });
59
60
  }
60
61
 
61
62
  async signIn(params: SignInParams): Promise<AuthUser> {
63
+ const email = sanitizeEmail(params.email);
64
+ const password = sanitizePassword(params.password);
65
+
62
66
  // Validate email format
63
- const emailResult = validateEmail(params.email);
67
+ const emailResult = validateEmail(email);
64
68
  if (!emailResult.isValid) {
65
69
  throw new AuthInvalidEmailError(emailResult.error);
66
70
  }
67
71
 
68
72
  // For login, only check if password is provided (no strength requirements)
69
- const passwordResult = validatePasswordForLogin(params.password);
73
+ const passwordResult = validatePasswordForLogin(password);
70
74
  if (!passwordResult.isValid) {
71
75
  throw new AuthValidationError(passwordResult.error || "Password is required", "password");
72
76
  }
73
77
 
74
- return this.provider.signIn({
75
- email: params.email,
76
- password: params.password,
77
- });
78
+ return this.provider.signIn({ email, password });
78
79
  }
79
80
 
80
81
  async signOut(): Promise<void> {
@@ -21,7 +21,10 @@ export class AnonymousModeService {
21
21
  const value = await storageProvider.get(this.storageKey);
22
22
  this.isAnonymousMode = value === "true";
23
23
  return this.isAnonymousMode;
24
- } catch {
24
+ } catch (error) {
25
+ if (__DEV__) {
26
+ console.warn("[AnonymousModeService] Storage load failed:", error);
27
+ }
25
28
  return false;
26
29
  }
27
30
  }
@@ -29,16 +32,20 @@ export class AnonymousModeService {
29
32
  private async save(storageProvider: IStorageProvider): Promise<void> {
30
33
  try {
31
34
  await storageProvider.set(this.storageKey, this.isAnonymousMode.toString());
32
- } catch {
33
- // Silently fail storage operations
35
+ } catch (err) {
36
+ if (__DEV__) {
37
+ console.error("[AnonymousModeService] Storage save failed:", err);
38
+ }
34
39
  }
35
40
  }
36
41
 
37
42
  async clear(storageProvider: IStorageProvider): Promise<void> {
38
43
  try {
39
44
  await storageProvider.remove(this.storageKey);
40
- } catch {
41
- // Silently fail storage operations
45
+ } catch (err) {
46
+ if (__DEV__) {
47
+ console.error("[AnonymousModeService] Storage clear failed:", err);
48
+ }
42
49
  }
43
50
  this.isAnonymousMode = false;
44
51
  }
@@ -48,8 +55,10 @@ export class AnonymousModeService {
48
55
  if (provider?.getCurrentUser()) {
49
56
  try {
50
57
  await provider.signOut();
51
- } catch {
52
- // Ignore sign out errors when switching to anonymous mode
58
+ } catch (error) {
59
+ if (__DEV__) {
60
+ console.warn("[AnonymousModeService] Sign out failed during mode switch:", error);
61
+ }
53
62
  }
54
63
  }
55
64
 
@@ -88,8 +88,10 @@ export class AuthEventService {
88
88
  eventListeners.forEach((listener) => {
89
89
  try {
90
90
  listener(payload);
91
- } catch {
92
- // Silent fail for listener errors
91
+ } catch (err) {
92
+ if (__DEV__) {
93
+ console.error("[AuthEventService] Listener error:", err);
94
+ }
93
95
  }
94
96
  });
95
97
  }
@@ -45,10 +45,9 @@ export class AuthService implements IAuthService {
45
45
  let provider: IAuthProvider;
46
46
 
47
47
  if ("currentUser" in providerOrAuth) {
48
- // eslint-disable-next-line @typescript-eslint/no-explicit-any, @typescript-eslint/no-unsafe-argument
49
- const firebaseProvider = new FirebaseAuthProvider(providerOrAuth as any);
48
+ const firebaseProvider = new FirebaseAuthProvider(providerOrAuth as Auth);
50
49
  await firebaseProvider.initialize();
51
- provider = firebaseProvider as unknown as IAuthProvider;
50
+ provider = firebaseProvider;
52
51
  } else {
53
52
  provider = providerOrAuth;
54
53
  await provider.initialize();
@@ -24,8 +24,6 @@ export type {
24
24
  UserDocumentExtras,
25
25
  } from "./UserDocument.types";
26
26
 
27
- declare const __DEV__: boolean;
28
-
29
27
  let userDocumentConfig: UserDocumentConfig = {};
30
28
 
31
29
  export function configureUserDocumentService(config: UserDocumentConfig): void {
@@ -37,7 +35,7 @@ export async function ensureUserDocument(
37
35
  extras?: UserDocumentExtras,
38
36
  ): Promise<boolean> {
39
37
  const db = getFirestore();
40
- if (!db || !user.uid) return false;
38
+ if (!db || !user.uid || user.uid.trim().length === 0) return false;
41
39
 
42
40
  try {
43
41
  let allExtras = extras || {};
@@ -60,8 +58,7 @@ export async function ensureUserDocument(
60
58
  await setDoc(userRef, docData, { merge: true });
61
59
  return true;
62
60
  } catch (error) {
63
- if (typeof __DEV__ !== "undefined" && __DEV__) {
64
- // eslint-disable-next-line no-console
61
+ if (__DEV__) {
65
62
  console.error("[UserDocumentService] Failed:", error);
66
63
  }
67
64
  return false;
@@ -80,7 +77,10 @@ export async function markUserDeleted(userId: string): Promise<boolean> {
80
77
  updatedAt: serverTimestamp(),
81
78
  }, { merge: true });
82
79
  return true;
83
- } catch {
80
+ } catch (error) {
81
+ if (__DEV__) {
82
+ console.error("[UserDocumentService] markUserDeleted failed:", error);
83
+ }
84
84
  return false;
85
85
  }
86
86
  }
@@ -27,6 +27,7 @@ export interface InitializeAuthOptions {
27
27
  }
28
28
 
29
29
  let isInitialized = false;
30
+ let initializationPromise: Promise<{ success: boolean; auth: Auth | null }> | null = null;
30
31
  const conversionState: { current: ConversionState } = {
31
32
  current: { previousUserId: null, wasAnonymous: false },
32
33
  };
@@ -40,6 +41,21 @@ export async function initializeAuth(
40
41
  if (isInitialized) {
41
42
  return { success: true, auth: getFirebaseAuth() };
42
43
  }
44
+ // Prevent race condition: return existing promise if initialization is in progress
45
+ if (initializationPromise) {
46
+ return initializationPromise;
47
+ }
48
+ initializationPromise = doInitializeAuth(options);
49
+ try {
50
+ return await initializationPromise;
51
+ } finally {
52
+ initializationPromise = null;
53
+ }
54
+ }
55
+
56
+ async function doInitializeAuth(
57
+ options: InitializeAuthOptions
58
+ ): Promise<{ success: boolean; auth: Auth | null }> {
43
59
 
44
60
  const {
45
61
  userCollection = "users",
@@ -63,8 +79,10 @@ export async function initializeAuth(
63
79
 
64
80
  try {
65
81
  await initializeAuthService(auth, authConfig, storageProvider);
66
- } catch {
67
- // Continue without email/password auth
82
+ } catch (error) {
83
+ if (__DEV__) {
84
+ console.warn("[initializeAuth] Auth service init failed, continuing:", error);
85
+ }
68
86
  }
69
87
 
70
88
  const handleAuthStateChange = createAuthStateHandler(conversionState, {
@@ -74,7 +92,13 @@ export async function initializeAuth(
74
92
 
75
93
  initializeAuthListener({
76
94
  autoAnonymousSignIn,
77
- onAuthStateChange: (user) => void handleAuthStateChange(user),
95
+ onAuthStateChange: (user) => {
96
+ handleAuthStateChange(user).catch((err) => {
97
+ if (__DEV__) {
98
+ console.error("[initializeAuth] Auth state change handler error:", err);
99
+ }
100
+ });
101
+ },
78
102
  });
79
103
 
80
104
  isInitialized = true;
@@ -7,6 +7,5 @@ import type { DesignTokens } from "@umituz/react-native-design-system";
7
7
 
8
8
  export interface IUIProvider {
9
9
  getTheme(): DesignTokens | null;
10
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
11
- getLocalization(): any;
10
+ getLocalization(): Record<string, unknown> | null;
12
11
  }
@@ -49,11 +49,6 @@ export function mapFirebaseAuthError(error: unknown): Error {
49
49
  return new AuthWrongPasswordError();
50
50
 
51
51
  case "auth/invalid-credential":
52
- return new AuthError(
53
- "Invalid email or password. Please check your credentials.",
54
- "AUTH_INVALID_CREDENTIAL"
55
- );
56
-
57
52
  case "auth/invalid-login-credentials":
58
53
  return new AuthError(
59
54
  "Invalid email or password. Please check your credentials.",
@@ -33,7 +33,6 @@ export function validatePasswordForLogin(password: string): ValidationResult {
33
33
  export function validatePasswordForRegister(
34
34
  password: string,
35
35
  config: PasswordConfig,
36
- _validationConfig: ValidationConfig = DEFAULT_VAL_CONFIG
37
36
  ): PasswordStrengthResult {
38
37
  const req: PasswordRequirements = {
39
38
  hasMinLength: password.length >= config.minLength,
@@ -6,7 +6,7 @@
6
6
  import type { AuthUser, AuthProviderType } from "../../domain/entities/AuthUser";
7
7
 
8
8
  interface ProviderData {
9
- providerId: string;
9
+ providerId: string | null;
10
10
  }
11
11
 
12
12
  interface FirebaseUserLike {
@@ -16,7 +16,7 @@ interface FirebaseUserLike {
16
16
  isAnonymous: boolean;
17
17
  emailVerified: boolean;
18
18
  photoURL: string | null;
19
- providerData?: ProviderData[];
19
+ providerData?: (ProviderData | null)[];
20
20
  }
21
21
 
22
22
  /**
@@ -32,13 +32,13 @@ function extractProvider(user: FirebaseUserLike): AuthProviderType {
32
32
  return "unknown";
33
33
  }
34
34
 
35
- const googleProvider = providerData.find((p) => p.providerId === "google.com");
35
+ const googleProvider = providerData.find((p) => p?.providerId === "google.com");
36
36
  if (googleProvider) return "google.com";
37
37
 
38
- const appleProvider = providerData.find((p) => p.providerId === "apple.com");
38
+ const appleProvider = providerData.find((p) => p?.providerId === "apple.com");
39
39
  if (appleProvider) return "apple.com";
40
40
 
41
- const passwordProvider = providerData.find((p) => p.providerId === "password");
41
+ const passwordProvider = providerData.find((p) => p?.providerId === "password");
42
42
  if (passwordProvider) return "password";
43
43
 
44
44
  return "unknown";
@@ -36,8 +36,10 @@ export function createAuthStateHandler(
36
36
  if (conversion.isConversion && onUserConverted && state.current.previousUserId) {
37
37
  try {
38
38
  await onUserConverted(state.current.previousUserId, currentUserId);
39
- } catch {
40
- // Migration failed but don't block user flow
39
+ } catch (error) {
40
+ if (__DEV__) {
41
+ console.warn("[AuthStateHandler] User conversion callback failed:", error);
42
+ }
41
43
  }
42
44
  }
43
45
 
@@ -16,7 +16,7 @@ export function getSignUpMethod(user: UserDocumentUser): string | undefined {
16
16
  if (user.isAnonymous) return "anonymous";
17
17
  if (user.email) {
18
18
  const providerData = (
19
- user as unknown as { providerData?: { providerId: string }[] }
19
+ user as unknown as { providerData?: { providerId: string | null }[] }
20
20
  ).providerData;
21
21
  if (providerData && providerData.length > 0) {
22
22
  const providerId = providerData[0]?.providerId;
@@ -7,8 +7,6 @@ import type { InitModule } from '@umituz/react-native-design-system';
7
7
  import { initializeAuth } from '../infrastructure/services/initializeAuth';
8
8
  import type { InitializeAuthOptions } from '../infrastructure/services/initializeAuth';
9
9
 
10
- declare const __DEV__: boolean;
11
-
12
10
  export interface AuthInitModuleConfig {
13
11
  /**
14
12
  * Firestore collection name for user documents
@@ -104,7 +102,7 @@ export function createAuthInitModule(
104
102
  collectExtras,
105
103
  storageProvider,
106
104
  onUserConverted: async (anonymousId: string, authenticatedId: string) => {
107
- if (typeof __DEV__ !== 'undefined' && __DEV__) {
105
+ if (__DEV__) {
108
106
  console.log('[createAuthInitModule] User converted:', {
109
107
  anonymousId: anonymousId.slice(0, 8),
110
108
  authenticatedId: authenticatedId.slice(0, 8),
@@ -115,11 +113,11 @@ export function createAuthInitModule(
115
113
  if (onRestorePurchases) {
116
114
  try {
117
115
  await onRestorePurchases();
118
- if (typeof __DEV__ !== 'undefined' && __DEV__) {
116
+ if (__DEV__) {
119
117
  console.log('[createAuthInitModule] Purchases restored');
120
118
  }
121
119
  } catch (error) {
122
- if (typeof __DEV__ !== 'undefined' && __DEV__) {
120
+ if (__DEV__) {
123
121
  console.error('[createAuthInitModule] Restore failed:', error);
124
122
  }
125
123
  }
@@ -132,13 +130,13 @@ export function createAuthInitModule(
132
130
  },
133
131
  });
134
132
 
135
- if (typeof __DEV__ !== 'undefined' && __DEV__) {
133
+ if (__DEV__) {
136
134
  console.log('[createAuthInitModule] Auth initialized');
137
135
  }
138
136
 
139
137
  return true;
140
138
  } catch (error) {
141
- if (typeof __DEV__ !== 'undefined' && __DEV__) {
139
+ if (__DEV__) {
142
140
  console.error('[createAuthInitModule] Error:', error);
143
141
  }
144
142
  return false;
@@ -59,8 +59,10 @@ export const AccountActions: React.FC<AccountActionsProps> = ({ config }) => {
59
59
  onPress: async () => {
60
60
  try {
61
61
  await onLogout();
62
- } catch {
63
- // Silent error handling
62
+ } catch (error) {
63
+ if (__DEV__) {
64
+ console.error("[AccountActions] Logout failed:", error);
65
+ }
64
66
  }
65
67
  },
66
68
  },
@@ -13,8 +13,6 @@ import { RegisterForm, type RegisterFormTranslations } from "./RegisterForm";
13
13
  import { SocialLoginButtons, type SocialLoginButtonsTranslations } from "./SocialLoginButtons";
14
14
  import { styles } from "./AuthBottomSheet.styles";
15
15
 
16
- declare const __DEV__: boolean;
17
-
18
16
  export interface AuthBottomSheetTranslations {
19
17
  close: string;
20
18
  signIn: string;
@@ -36,8 +36,7 @@ export function useAppleAuth(): UseAppleAuthResult {
36
36
  return { success: false, error: "Apple Sign-In is not available" };
37
37
  }
38
38
 
39
- const result = await signInWithApple();
40
- return result;
39
+ return signInWithApple();
41
40
  }, [appleAvailable, signInWithApple]);
42
41
 
43
42
  return {
@@ -141,7 +141,10 @@ export function useAuth(): UseAuthResult {
141
141
  setLoading(true);
142
142
  await anonymousModeMutation.mutateAsync();
143
143
  setIsAnonymous(true);
144
- } catch {
144
+ } catch (error) {
145
+ if (__DEV__) {
146
+ console.warn("[useAuth] continueAnonymously failed:", error);
147
+ }
145
148
  setIsAnonymous(true);
146
149
  } finally {
147
150
  setLoading(false);
@@ -7,8 +7,6 @@ import { useGoogleAuth, type GoogleAuthConfig } from "./useGoogleAuth";
7
7
  import { useAppleAuth } from "./useAppleAuth";
8
8
  import type { SocialAuthProvider } from "../../domain/value-objects/AuthConfig";
9
9
 
10
- declare const __DEV__: boolean;
11
-
12
10
  export interface SocialAuthConfiguration {
13
11
  google?: GoogleAuthConfig;
14
12
  apple?: { enabled: boolean };
@@ -92,7 +90,7 @@ export function useAuthBottomSheet(params: UseAuthBottomSheetParams = {}) {
92
90
  const justAuthenticated = !prevIsAuthenticatedRef.current && isAuthenticated;
93
91
  const justConvertedFromAnonymous = prevIsAnonymousRef.current && !isAnonymous && isAuthenticated;
94
92
 
95
- if (typeof __DEV__ !== "undefined" && __DEV__) {
93
+ if (__DEV__) {
96
94
  console.log("[useAuthBottomSheet] Auth state effect:", {
97
95
  isAuthenticated,
98
96
  isAnonymous,
@@ -106,7 +104,7 @@ export function useAuthBottomSheet(params: UseAuthBottomSheetParams = {}) {
106
104
  }
107
105
 
108
106
  if ((justAuthenticated || justConvertedFromAnonymous) && isVisible && !isAnonymous) {
109
- if (typeof __DEV__ !== "undefined" && __DEV__) {
107
+ if (__DEV__) {
110
108
  console.log("[useAuthBottomSheet] Auto-closing due to successful authentication transition", {
111
109
  justAuthenticated,
112
110
  justConvertedFromAnonymous,
@@ -119,7 +117,7 @@ export function useAuthBottomSheet(params: UseAuthBottomSheetParams = {}) {
119
117
  onAuthSuccess?.();
120
118
  // Execute callback with delay to ensure auth state has propagated
121
119
  setTimeout(() => {
122
- if (typeof __DEV__ !== "undefined" && __DEV__) {
120
+ if (__DEV__) {
123
121
  console.log("[useAuthBottomSheet] Executing pending callback after auth");
124
122
  }
125
123
  executePendingCallback();
@@ -71,8 +71,10 @@ export function useGoogleAuth(config?: GoogleAuthConfig): UseGoogleAuthResult {
71
71
  if (idToken) {
72
72
  setIsLoading(true);
73
73
  signInWithGoogleToken(idToken)
74
- .catch(() => {
75
- // Silent error handling
74
+ .catch((error) => {
75
+ if (__DEV__) {
76
+ console.error("[useGoogleAuth] Firebase sign-in failed:", error);
77
+ }
76
78
  })
77
79
  .finally(() => {
78
80
  setIsLoading(false);
@@ -100,8 +100,10 @@ export function useLoginForm(config?: UseLoginFormConfig): UseLoginFormResult {
100
100
  const handleContinueAnonymously = useCallback(async () => {
101
101
  try {
102
102
  await continueAnonymously();
103
- } catch {
104
- // Silent fail
103
+ } catch (error) {
104
+ if (__DEV__) {
105
+ console.warn("[useLoginForm] Continue anonymously failed:", error);
106
+ }
105
107
  }
106
108
  }, [continueAnonymously]);
107
109
 
@@ -122,19 +122,19 @@ export function useRegisterForm(config?: UseRegisterFormConfig): UseRegisterForm
122
122
 
123
123
  const emailResult = validateEmail(email.trim());
124
124
  if (!emailResult.isValid && emailResult.error) {
125
- setFieldErrors((prev) => ({ ...prev, email: getErrorMessage(emailResult.error as string) }));
125
+ setFieldErrors((prev) => ({ ...prev, email: getErrorMessage(emailResult.error!) }));
126
126
  return;
127
127
  }
128
128
 
129
129
  const passwordResult = validatePasswordForRegister(password, DEFAULT_PASSWORD_CONFIG);
130
130
  if (!passwordResult.isValid && passwordResult.error) {
131
- setFieldErrors((prev) => ({ ...prev, password: getErrorMessage(passwordResult.error as string) }));
131
+ setFieldErrors((prev) => ({ ...prev, password: getErrorMessage(passwordResult.error!) }));
132
132
  return;
133
133
  }
134
134
 
135
135
  const confirmResult = validatePasswordConfirmation(password, confirmPassword);
136
136
  if (!confirmResult.isValid && confirmResult.error) {
137
- setFieldErrors((prev) => ({ ...prev, confirmPassword: getErrorMessage(confirmResult.error as string) }));
137
+ setFieldErrors((prev) => ({ ...prev, confirmPassword: getErrorMessage(confirmResult.error!) }));
138
138
  return;
139
139
  }
140
140
 
@@ -80,8 +80,7 @@ export function useSocialLogin(config?: UseSocialLoginConfig): UseSocialLoginRes
80
80
  return { success: false, error: "Apple Sign-In is not available" };
81
81
  }
82
82
 
83
- const result = await firebaseSignInWithApple();
84
- return result;
83
+ return firebaseSignInWithApple();
85
84
  }, [appleAvailable, firebaseSignInWithApple]);
86
85
 
87
86
  return {
@@ -53,7 +53,7 @@ export const useAuthModalStore = createStore<AuthModalState, AuthModalActions>({
53
53
  callback?: () => void | Promise<void>,
54
54
  mode: AuthModalMode = "login",
55
55
  ) => {
56
- if (typeof __DEV__ !== "undefined" && __DEV__) {
56
+ if (__DEV__) {
57
57
  console.log("[authModalStore] showAuthModal called:", {
58
58
  mode,
59
59
  hasCallback: !!callback,
@@ -72,7 +72,7 @@ export const useAuthStore = createStore<AuthState, AuthActions>({
72
72
  initialized: state.initialized,
73
73
  }),
74
74
  migrate: (persistedState: unknown, version: number) => {
75
- const state = persistedState as Partial<AuthState>;
75
+ const state = (persistedState && typeof persistedState === "object" ? persistedState : {}) as Partial<AuthState>;
76
76
  if (version < 2) {
77
77
  return {
78
78
  ...initialAuthState,
@@ -80,7 +80,7 @@ export const useAuthStore = createStore<AuthState, AuthActions>({
80
80
  initialized: state.initialized ?? false,
81
81
  };
82
82
  }
83
- return { ...initialAuthState, ...state } as AuthState;
83
+ return { ...initialAuthState, ...state };
84
84
  },
85
85
  actions: (set, get) => ({
86
86
  setFirebaseUser: (firebaseUser) => {
@@ -13,7 +13,8 @@ import { useAuthStore } from "./authStore";
13
13
  import { getAuthService } from "../../infrastructure/services/AuthService";
14
14
  import type { AuthListenerOptions } from "../../types/auth-store.types";
15
15
 
16
- declare const __DEV__: boolean;
16
+ const MAX_ANONYMOUS_RETRIES = 2;
17
+ const ANONYMOUS_RETRY_DELAY_MS = 1000;
17
18
 
18
19
  let listenerInitialized = false;
19
20
  // Reference counter for multiple subscribers
@@ -106,10 +107,7 @@ export function initializeAuthListener(
106
107
  store.setLoading(true);
107
108
 
108
109
  void (async () => {
109
- const MAX_RETRIES = 2;
110
- const RETRY_DELAY_MS = 1000;
111
-
112
- for (let attempt = 0; attempt <= MAX_RETRIES; attempt++) {
110
+ for (let attempt = 0; attempt <= MAX_ANONYMOUS_RETRIES; attempt++) {
113
111
  try {
114
112
  await anonymousAuthService.signInAnonymously(auth);
115
113
  if (__DEV__) {
@@ -123,8 +121,8 @@ export function initializeAuthListener(
123
121
  }
124
122
 
125
123
  // If not last attempt, wait and retry
126
- if (attempt < MAX_RETRIES) {
127
- await new Promise(resolve => setTimeout(resolve, RETRY_DELAY_MS));
124
+ if (attempt < MAX_ANONYMOUS_RETRIES) {
125
+ await new Promise(resolve => setTimeout(resolve, ANONYMOUS_RETRY_DELAY_MS));
128
126
  continue;
129
127
  }
130
128