@umituz/react-native-auth 3.6.72 → 3.6.74
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +1 -1
- package/src/domain/value-objects/AuthConfig.ts +9 -56
- package/src/index.ts +15 -111
- package/src/infrastructure/adapters/StorageProviderAdapter.ts +1 -4
- package/src/infrastructure/providers/FirebaseAuthProvider.ts +5 -32
- package/src/infrastructure/repositories/AuthRepository.ts +0 -5
- package/src/infrastructure/services/AnonymousModeService.ts +6 -20
- package/src/infrastructure/services/AuthEventService.ts +2 -4
- package/src/infrastructure/services/initializeAuth.ts +2 -11
- package/src/infrastructure/utils/AuthErrorMapper.ts +0 -4
- package/src/infrastructure/utils/authStateHandler.ts +2 -4
- package/src/infrastructure/utils/listener/anonymousSignInHandler.ts +2 -22
- package/src/infrastructure/utils/listener/listenerLifecycle.util.ts +144 -0
- package/src/infrastructure/utils/listener/listenerState.util.ts +125 -0
- package/src/init/createAuthInitModule.ts +3 -22
- package/src/presentation/components/AccountActions.tsx +11 -43
- package/src/presentation/components/AuthBottomSheet.tsx +1 -17
- package/src/presentation/components/ProfileSection.tsx +78 -108
- package/src/presentation/components/RegisterForm.tsx +6 -28
- package/src/presentation/hooks/useAccountManagement.ts +0 -7
- package/src/presentation/hooks/useAuth.ts +2 -4
- package/src/presentation/hooks/useAuthBottomSheet.ts +23 -79
- package/src/presentation/hooks/useGoogleAuth.ts +0 -3
- package/src/presentation/hooks/useLoginForm.ts +26 -30
- package/src/presentation/hooks/useProfileEdit.ts +56 -64
- package/src/presentation/hooks/useRegisterForm.ts +41 -44
- package/src/presentation/providers/AuthProvider.tsx +2 -7
- package/src/presentation/stores/authModalStore.ts +0 -7
- package/src/presentation/stores/authStore.ts +1 -28
- package/src/presentation/stores/initializeAuthListener.ts +30 -160
- package/src/presentation/utils/accountDeleteHandler.util.ts +0 -51
- package/src/presentation/utils/authTransition.util.ts +72 -0
- package/src/presentation/utils/form/formFieldState.util.ts +82 -0
- package/src/presentation/utils/form/formValidation.util.ts +173 -0
- package/src/presentation/utils/socialAuthHandler.util.ts +106 -0
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@umituz/react-native-auth",
|
|
3
|
-
"version": "3.6.
|
|
3
|
+
"version": "3.6.74",
|
|
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",
|
|
@@ -7,9 +7,6 @@ export interface PasswordConfig {
|
|
|
7
7
|
minLength: number;
|
|
8
8
|
}
|
|
9
9
|
|
|
10
|
-
/**
|
|
11
|
-
* Social authentication provider configuration
|
|
12
|
-
*/
|
|
13
10
|
export interface SocialProviderConfig {
|
|
14
11
|
enabled: boolean;
|
|
15
12
|
}
|
|
@@ -20,21 +17,13 @@ export interface GoogleAuthConfig extends SocialProviderConfig {
|
|
|
20
17
|
androidClientId?: string;
|
|
21
18
|
}
|
|
22
19
|
|
|
23
|
-
export interface AppleAuthConfig extends SocialProviderConfig {
|
|
24
|
-
// Apple Sign In doesn't require additional config for basic usage
|
|
25
|
-
}
|
|
20
|
+
export interface AppleAuthConfig extends SocialProviderConfig {}
|
|
26
21
|
|
|
27
|
-
/**
|
|
28
|
-
* Social authentication configuration
|
|
29
|
-
*/
|
|
30
22
|
export interface SocialAuthConfig {
|
|
31
23
|
google?: GoogleAuthConfig;
|
|
32
24
|
apple?: AppleAuthConfig;
|
|
33
25
|
}
|
|
34
26
|
|
|
35
|
-
/**
|
|
36
|
-
* Supported social auth providers
|
|
37
|
-
*/
|
|
38
27
|
export type SocialAuthProvider = "google" | "apple";
|
|
39
28
|
|
|
40
29
|
export interface AuthConfig {
|
|
@@ -42,23 +31,16 @@ export interface AuthConfig {
|
|
|
42
31
|
social?: SocialAuthConfig;
|
|
43
32
|
}
|
|
44
33
|
|
|
45
|
-
export const DEFAULT_PASSWORD_CONFIG: PasswordConfig = {
|
|
46
|
-
minLength: 6,
|
|
47
|
-
};
|
|
48
|
-
|
|
34
|
+
export const DEFAULT_PASSWORD_CONFIG: PasswordConfig = { minLength: 6 };
|
|
49
35
|
export const DEFAULT_SOCIAL_CONFIG: SocialAuthConfig = {
|
|
50
36
|
google: { enabled: false },
|
|
51
37
|
apple: { enabled: false },
|
|
52
38
|
};
|
|
53
|
-
|
|
54
39
|
export const DEFAULT_AUTH_CONFIG: AuthConfig = {
|
|
55
40
|
password: DEFAULT_PASSWORD_CONFIG,
|
|
56
41
|
social: DEFAULT_SOCIAL_CONFIG,
|
|
57
42
|
};
|
|
58
43
|
|
|
59
|
-
/**
|
|
60
|
-
* Configuration validation error
|
|
61
|
-
*/
|
|
62
44
|
export class AuthConfigValidationError extends Error {
|
|
63
45
|
constructor(message: string, public readonly field: string) {
|
|
64
46
|
super(message);
|
|
@@ -66,58 +48,29 @@ export class AuthConfigValidationError extends Error {
|
|
|
66
48
|
}
|
|
67
49
|
}
|
|
68
50
|
|
|
69
|
-
/**
|
|
70
|
-
* Validate authentication configuration
|
|
71
|
-
* @throws {AuthConfigValidationError} if configuration is invalid
|
|
72
|
-
*/
|
|
73
51
|
export function validateAuthConfig(config: Partial<AuthConfig>): void {
|
|
74
|
-
// Validate password config
|
|
75
52
|
if (config.password) {
|
|
76
53
|
if (typeof config.password.minLength !== "number") {
|
|
77
|
-
throw new AuthConfigValidationError(
|
|
78
|
-
"Password minLength must be a number",
|
|
79
|
-
"password.minLength"
|
|
80
|
-
);
|
|
54
|
+
throw new AuthConfigValidationError("Password minLength must be a number", "password.minLength");
|
|
81
55
|
}
|
|
82
56
|
if (config.password.minLength < 4) {
|
|
83
|
-
throw new AuthConfigValidationError(
|
|
84
|
-
"Password minLength must be at least 4 characters",
|
|
85
|
-
"password.minLength"
|
|
86
|
-
);
|
|
57
|
+
throw new AuthConfigValidationError("Password minLength must be at least 4 characters", "password.minLength");
|
|
87
58
|
}
|
|
88
59
|
if (config.password.minLength > 128) {
|
|
89
|
-
throw new AuthConfigValidationError(
|
|
90
|
-
"Password minLength must not exceed 128 characters",
|
|
91
|
-
"password.minLength"
|
|
92
|
-
);
|
|
60
|
+
throw new AuthConfigValidationError("Password minLength must not exceed 128 characters", "password.minLength");
|
|
93
61
|
}
|
|
94
62
|
}
|
|
95
63
|
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
if (
|
|
99
|
-
|
|
100
|
-
if (googleConfig.enabled) {
|
|
101
|
-
// At least one client ID should be provided if enabled
|
|
102
|
-
if (!googleConfig.webClientId && !googleConfig.iosClientId && !googleConfig.androidClientId) {
|
|
103
|
-
throw new AuthConfigValidationError(
|
|
104
|
-
"At least one Google client ID (web, iOS, or Android) must be provided when Google Sign-In is enabled",
|
|
105
|
-
"social.google"
|
|
106
|
-
);
|
|
107
|
-
}
|
|
108
|
-
}
|
|
64
|
+
if (config.social?.google?.enabled) {
|
|
65
|
+
const googleConfig = config.social.google;
|
|
66
|
+
if (!googleConfig.webClientId && !googleConfig.iosClientId && !googleConfig.androidClientId) {
|
|
67
|
+
throw new AuthConfigValidationError("At least one Google client ID must be provided when Google Sign-In is enabled", "social.google");
|
|
109
68
|
}
|
|
110
69
|
}
|
|
111
70
|
}
|
|
112
71
|
|
|
113
|
-
/**
|
|
114
|
-
* Sanitize and merge auth config with defaults
|
|
115
|
-
* Ensures valid configuration values
|
|
116
|
-
*/
|
|
117
72
|
export function sanitizeAuthConfig(config: Partial<AuthConfig> = {}): AuthConfig {
|
|
118
|
-
// Validate first
|
|
119
73
|
validateAuthConfig(config);
|
|
120
|
-
|
|
121
74
|
return {
|
|
122
75
|
password: {
|
|
123
76
|
minLength: config.password?.minLength ?? DEFAULT_PASSWORD_CONFIG.minLength,
|
package/src/index.ts
CHANGED
|
@@ -10,97 +10,30 @@
|
|
|
10
10
|
// =============================================================================
|
|
11
11
|
|
|
12
12
|
export type { AuthUser, AuthProviderType } from './domain/entities/AuthUser';
|
|
13
|
-
export {
|
|
14
|
-
AuthError,
|
|
15
|
-
AuthInitializationError,
|
|
16
|
-
AuthConfigurationError,
|
|
17
|
-
AuthValidationError,
|
|
18
|
-
AuthNetworkError,
|
|
19
|
-
AuthUserNotFoundError,
|
|
20
|
-
AuthWrongPasswordError,
|
|
21
|
-
AuthEmailAlreadyInUseError,
|
|
22
|
-
AuthWeakPasswordError,
|
|
23
|
-
AuthInvalidEmailError,
|
|
24
|
-
} from './domain/errors/AuthError';
|
|
25
|
-
|
|
26
|
-
export type {
|
|
27
|
-
AuthConfig,
|
|
28
|
-
PasswordConfig,
|
|
29
|
-
SocialAuthConfig,
|
|
30
|
-
SocialProviderConfig,
|
|
31
|
-
GoogleAuthConfig,
|
|
32
|
-
AppleAuthConfig,
|
|
33
|
-
SocialAuthProvider,
|
|
34
|
-
} from './domain/value-objects/AuthConfig';
|
|
35
|
-
export {
|
|
36
|
-
DEFAULT_AUTH_CONFIG,
|
|
37
|
-
DEFAULT_PASSWORD_CONFIG,
|
|
38
|
-
DEFAULT_SOCIAL_CONFIG,
|
|
39
|
-
} from './domain/value-objects/AuthConfig';
|
|
40
|
-
|
|
41
13
|
export type { UserProfile, UpdateProfileParams } from './domain/entities/UserProfile';
|
|
14
|
+
export { AuthError, AuthInitializationError, AuthConfigurationError, AuthValidationError, AuthNetworkError, AuthUserNotFoundError, AuthWrongPasswordError, AuthEmailAlreadyInUseError, AuthWeakPasswordError, AuthInvalidEmailError } from './domain/errors/AuthError';
|
|
15
|
+
export type { AuthConfig, PasswordConfig, SocialAuthConfig, SocialProviderConfig, GoogleAuthConfig, AppleAuthConfig, SocialAuthProvider } from './domain/value-objects/AuthConfig';
|
|
16
|
+
export { DEFAULT_AUTH_CONFIG, DEFAULT_PASSWORD_CONFIG, DEFAULT_SOCIAL_CONFIG } from './domain/value-objects/AuthConfig';
|
|
42
17
|
|
|
43
18
|
// =============================================================================
|
|
44
19
|
// APPLICATION LAYER
|
|
45
20
|
// =============================================================================
|
|
46
21
|
|
|
47
|
-
export type {
|
|
48
|
-
IAuthProvider,
|
|
49
|
-
AuthCredentials,
|
|
50
|
-
SignUpCredentials,
|
|
51
|
-
SocialSignInResult,
|
|
52
|
-
} from './application/ports/IAuthProvider';
|
|
22
|
+
export type { IAuthProvider, AuthCredentials, SignUpCredentials, SocialSignInResult } from './application/ports/IAuthProvider';
|
|
53
23
|
|
|
54
24
|
// =============================================================================
|
|
55
25
|
// INFRASTRUCTURE LAYER
|
|
56
26
|
// =============================================================================
|
|
57
27
|
|
|
58
28
|
export { FirebaseAuthProvider } from './infrastructure/providers/FirebaseAuthProvider';
|
|
59
|
-
export {
|
|
60
|
-
AuthService,
|
|
61
|
-
initializeAuthService,
|
|
62
|
-
getAuthService,
|
|
63
|
-
resetAuthService,
|
|
64
|
-
} from './infrastructure/services/AuthService';
|
|
29
|
+
export { AuthService, initializeAuthService, getAuthService, resetAuthService } from './infrastructure/services/AuthService';
|
|
65
30
|
export type { IStorageProvider } from './infrastructure/types/Storage.types';
|
|
66
|
-
export {
|
|
67
|
-
|
|
68
|
-
StorageProviderAdapter,
|
|
69
|
-
} from './infrastructure/adapters/StorageProviderAdapter';
|
|
70
|
-
export {
|
|
71
|
-
initializeAuth,
|
|
72
|
-
isAuthInitialized,
|
|
73
|
-
resetAuthInitialization,
|
|
74
|
-
} from './infrastructure/services/initializeAuth';
|
|
31
|
+
export { createStorageProvider, StorageProviderAdapter } from './infrastructure/adapters/StorageProviderAdapter';
|
|
32
|
+
export { initializeAuth, isAuthInitialized, resetAuthInitialization } from './infrastructure/services/initializeAuth';
|
|
75
33
|
export type { InitializeAuthOptions } from './infrastructure/services/initializeAuth';
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
// =============================================================================
|
|
80
|
-
|
|
81
|
-
export {
|
|
82
|
-
validateEmail,
|
|
83
|
-
validatePasswordForLogin,
|
|
84
|
-
validatePasswordForRegister,
|
|
85
|
-
validatePasswordConfirmation,
|
|
86
|
-
validateDisplayName,
|
|
87
|
-
} from './infrastructure/utils/AuthValidation';
|
|
88
|
-
export type {
|
|
89
|
-
ValidationResult,
|
|
90
|
-
PasswordStrengthResult,
|
|
91
|
-
PasswordRequirements,
|
|
92
|
-
} from './infrastructure/utils/AuthValidation';
|
|
93
|
-
|
|
94
|
-
export {
|
|
95
|
-
SECURITY_LIMITS,
|
|
96
|
-
sanitizeWhitespace,
|
|
97
|
-
sanitizeEmail,
|
|
98
|
-
sanitizePassword,
|
|
99
|
-
sanitizeName,
|
|
100
|
-
sanitizeText,
|
|
101
|
-
containsDangerousChars,
|
|
102
|
-
isWithinLengthLimit,
|
|
103
|
-
} from './infrastructure/utils/validation/sanitization';
|
|
34
|
+
export { validateEmail, validatePasswordForLogin, validatePasswordForRegister, validatePasswordConfirmation, validateDisplayName } from './infrastructure/utils/AuthValidation';
|
|
35
|
+
export type { ValidationResult, PasswordStrengthResult, PasswordRequirements } from './infrastructure/utils/AuthValidation';
|
|
36
|
+
export { SECURITY_LIMITS, sanitizeWhitespace, sanitizeEmail, sanitizePassword, sanitizeName, sanitizeText, containsDangerousChars, isWithinLengthLimit } from './infrastructure/utils/validation/sanitization';
|
|
104
37
|
export type { SecurityLimitKey } from './infrastructure/utils/validation/sanitization';
|
|
105
38
|
|
|
106
39
|
// =============================================================================
|
|
@@ -109,37 +42,26 @@ export type { SecurityLimitKey } from './infrastructure/utils/validation/sanitiz
|
|
|
109
42
|
|
|
110
43
|
export { useAuth } from './presentation/hooks/useAuth';
|
|
111
44
|
export type { UseAuthResult } from './presentation/hooks/useAuth';
|
|
112
|
-
|
|
113
45
|
export { useLoginForm } from './presentation/hooks/useLoginForm';
|
|
114
46
|
export type { UseLoginFormConfig, UseLoginFormResult } from './presentation/hooks/useLoginForm';
|
|
115
|
-
|
|
116
47
|
export { useRegisterForm } from './presentation/hooks/useRegisterForm';
|
|
117
48
|
export type { UseRegisterFormConfig, UseRegisterFormResult } from './presentation/hooks/useRegisterForm';
|
|
118
|
-
|
|
119
49
|
export { useAuthRequired } from './presentation/hooks/useAuthRequired';
|
|
120
50
|
export { useRequireAuth, useUserId } from './presentation/hooks/useRequireAuth';
|
|
121
|
-
|
|
122
51
|
export { useUserProfile } from './presentation/hooks/useUserProfile';
|
|
123
52
|
export type { UserProfileData, UseUserProfileParams } from './presentation/hooks/useUserProfile';
|
|
124
|
-
|
|
125
53
|
export { useAccountManagement } from './presentation/hooks/useAccountManagement';
|
|
126
54
|
export type { UseAccountManagementReturn } from './presentation/hooks/useAccountManagement';
|
|
127
|
-
|
|
128
55
|
export { useProfileUpdate } from './presentation/hooks/useProfileUpdate';
|
|
129
56
|
export type { UseProfileUpdateReturn } from './presentation/hooks/useProfileUpdate';
|
|
130
|
-
|
|
131
57
|
export { useProfileEdit } from './presentation/hooks/useProfileEdit';
|
|
132
58
|
export type { ProfileEditFormState, UseProfileEditReturn } from './presentation/hooks/useProfileEdit';
|
|
133
|
-
|
|
134
59
|
export { useSocialLogin } from './presentation/hooks/useSocialLogin';
|
|
135
60
|
export type { UseSocialLoginConfig, UseSocialLoginResult } from './presentation/hooks/useSocialLogin';
|
|
136
|
-
|
|
137
61
|
export { useGoogleAuth } from './presentation/hooks/useGoogleAuth';
|
|
138
62
|
export type { UseGoogleAuthResult } from './presentation/hooks/useGoogleAuth';
|
|
139
|
-
|
|
140
63
|
export { useAppleAuth } from './presentation/hooks/useAppleAuth';
|
|
141
64
|
export type { UseAppleAuthResult } from './presentation/hooks/useAppleAuth';
|
|
142
|
-
|
|
143
65
|
export { useAuthBottomSheet } from './presentation/hooks/useAuthBottomSheet';
|
|
144
66
|
export type { SocialAuthConfiguration } from './presentation/hooks/useAuthBottomSheet';
|
|
145
67
|
|
|
@@ -149,22 +71,16 @@ export type { SocialAuthConfiguration } from './presentation/hooks/useAuthBottom
|
|
|
149
71
|
|
|
150
72
|
export { AuthProvider } from './presentation/providers/AuthProvider';
|
|
151
73
|
export type { ErrorFallbackProps } from './presentation/providers/AuthProvider';
|
|
152
|
-
|
|
153
74
|
export { LoginScreen } from './presentation/screens/LoginScreen';
|
|
154
75
|
export type { LoginScreenProps } from './presentation/screens/LoginScreen';
|
|
155
|
-
|
|
156
76
|
export { RegisterScreen } from './presentation/screens/RegisterScreen';
|
|
157
77
|
export type { RegisterScreenProps } from './presentation/screens/RegisterScreen';
|
|
158
|
-
|
|
159
78
|
export { AccountScreen } from './presentation/screens/AccountScreen';
|
|
160
79
|
export type { AccountScreenProps, AccountScreenConfig } from './presentation/screens/AccountScreen';
|
|
161
|
-
|
|
162
80
|
export { EditProfileScreen } from './presentation/screens/EditProfileScreen';
|
|
163
81
|
export type { EditProfileScreenProps } from './presentation/screens/EditProfileScreen';
|
|
164
|
-
|
|
165
82
|
export { AuthNavigator } from './presentation/navigation/AuthNavigator';
|
|
166
83
|
export type { AuthStackParamList } from './presentation/navigation/AuthNavigator';
|
|
167
|
-
|
|
168
84
|
export { AuthBottomSheet } from './presentation/components/AuthBottomSheet';
|
|
169
85
|
export { ProfileSection } from './presentation/components/ProfileSection';
|
|
170
86
|
export type { ProfileSectionProps, ProfileSectionConfig } from './presentation/components/ProfileSection';
|
|
@@ -175,27 +91,15 @@ export type { ProfileSectionProps, ProfileSectionConfig } from './presentation/c
|
|
|
175
91
|
|
|
176
92
|
export { useAuthStore } from './presentation/stores/authStore';
|
|
177
93
|
export { useAuthModalStore } from './presentation/stores/authModalStore';
|
|
178
|
-
export {
|
|
179
|
-
|
|
180
|
-
resetAuthListener,
|
|
181
|
-
isAuthListenerInitialized,
|
|
182
|
-
} from './presentation/stores/initializeAuthListener';
|
|
183
|
-
export type { AuthState, AuthActions, UserType } from './types/auth-store.types';
|
|
184
|
-
export type { AuthListenerOptions } from './types/auth-store.types';
|
|
94
|
+
export { initializeAuthListener, resetAuthListener, isAuthListenerInitialized } from './presentation/stores/initializeAuthListener';
|
|
95
|
+
export type { AuthState, AuthActions, UserType, AuthListenerOptions } from './types/auth-store.types';
|
|
185
96
|
export * from './presentation/stores/auth.selectors';
|
|
186
97
|
|
|
187
98
|
// =============================================================================
|
|
188
|
-
// UTILITIES
|
|
189
|
-
// =============================================================================
|
|
190
|
-
|
|
191
|
-
export {
|
|
192
|
-
getAuthErrorLocalizationKey,
|
|
193
|
-
resolveErrorMessage,
|
|
194
|
-
} from './presentation/utils/getAuthErrorMessage';
|
|
195
|
-
|
|
196
|
-
// =============================================================================
|
|
197
|
-
// INIT MODULE
|
|
99
|
+
// UTILITIES & INIT
|
|
198
100
|
// =============================================================================
|
|
199
101
|
|
|
102
|
+
export { getAuthErrorLocalizationKey, resolveErrorMessage } from './presentation/utils/getAuthErrorMessage';
|
|
200
103
|
export { createAuthInitModule } from './init';
|
|
201
104
|
export type { AuthInitModuleConfig } from './init/createAuthInitModule';
|
|
105
|
+
|
|
@@ -37,10 +37,7 @@ export class StorageProviderAdapter implements IStorageProvider {
|
|
|
37
37
|
} else {
|
|
38
38
|
throw new Error("Unsupported storage implementation");
|
|
39
39
|
}
|
|
40
|
-
} catch
|
|
41
|
-
if (__DEV__) {
|
|
42
|
-
console.warn("[StorageProviderAdapter] Failed to get value for key:", key, error);
|
|
43
|
-
}
|
|
40
|
+
} catch {
|
|
44
41
|
return null;
|
|
45
42
|
}
|
|
46
43
|
}
|
|
@@ -81,22 +81,11 @@ export class FirebaseAuthProvider implements IAuthProvider {
|
|
|
81
81
|
|
|
82
82
|
// Convert anonymous user to permanent account
|
|
83
83
|
if (currentUser && isAnonymous) {
|
|
84
|
-
if (__DEV__) {
|
|
85
|
-
console.log("[FirebaseAuthProvider] Converting anonymous user to authenticated:", {
|
|
86
|
-
anonymousId: currentUser.uid.slice(0, 8),
|
|
87
|
-
});
|
|
88
|
-
}
|
|
89
|
-
|
|
90
84
|
// Reload user to refresh token before linking (prevents token-expired errors)
|
|
91
85
|
try {
|
|
92
86
|
await currentUser.reload();
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
}
|
|
96
|
-
} catch (reloadError) {
|
|
97
|
-
if (__DEV__) {
|
|
98
|
-
console.log("[FirebaseAuthProvider] Reload failed, proceeding with link:", reloadError);
|
|
99
|
-
}
|
|
87
|
+
} catch {
|
|
88
|
+
// Reload failed, proceed with link anyway
|
|
100
89
|
}
|
|
101
90
|
|
|
102
91
|
const credential = EmailAuthProvider.credential(
|
|
@@ -105,19 +94,8 @@ export class FirebaseAuthProvider implements IAuthProvider {
|
|
|
105
94
|
);
|
|
106
95
|
|
|
107
96
|
userCredential = await linkWithCredential(currentUser, credential);
|
|
108
|
-
|
|
109
|
-
if (__DEV__) {
|
|
110
|
-
console.log("[FirebaseAuthProvider] Anonymous user converted successfully:", {
|
|
111
|
-
userId: userCredential.user.uid.slice(0, 8),
|
|
112
|
-
sameUser: currentUser.uid === userCredential.user.uid,
|
|
113
|
-
});
|
|
114
|
-
}
|
|
115
97
|
} else {
|
|
116
98
|
// Create new user
|
|
117
|
-
if (__DEV__) {
|
|
118
|
-
console.log("[FirebaseAuthProvider] Creating new user account");
|
|
119
|
-
}
|
|
120
|
-
|
|
121
99
|
userCredential = await createUserWithEmailAndPassword(
|
|
122
100
|
this.auth,
|
|
123
101
|
credentials.email.trim(),
|
|
@@ -130,14 +108,9 @@ export class FirebaseAuthProvider implements IAuthProvider {
|
|
|
130
108
|
await updateProfile(userCredential.user, {
|
|
131
109
|
displayName: credentials.displayName.trim(),
|
|
132
110
|
});
|
|
133
|
-
} catch
|
|
134
|
-
//
|
|
135
|
-
//
|
|
136
|
-
const errorMessage = error instanceof Error ? error.message : "Unknown error";
|
|
137
|
-
console.warn(
|
|
138
|
-
`[FirebaseAuthProvider] Account created but display name update failed: ${errorMessage}. ` +
|
|
139
|
-
"User can update their display name later from profile settings."
|
|
140
|
-
);
|
|
111
|
+
} catch {
|
|
112
|
+
// Silently fail - the account was created successfully,
|
|
113
|
+
// only the display name update failed. User can update it later.
|
|
141
114
|
}
|
|
142
115
|
}
|
|
143
116
|
|
|
@@ -36,11 +36,6 @@ export class AuthRepository implements IAuthRepository {
|
|
|
36
36
|
const password = sanitizePassword(params.password);
|
|
37
37
|
const displayName = params.displayName ? sanitizeName(params.displayName) : undefined;
|
|
38
38
|
|
|
39
|
-
// Log if display name was sanitized
|
|
40
|
-
if (__DEV__ && params.displayName && displayName && params.displayName !== displayName) {
|
|
41
|
-
console.warn("[AuthRepository] Display name was sanitized during sign up. Original:", params.displayName, "Sanitized:", displayName);
|
|
42
|
-
}
|
|
43
|
-
|
|
44
39
|
// Validate email
|
|
45
40
|
const emailResult = validateEmail(email);
|
|
46
41
|
if (!emailResult.isValid) {
|
|
@@ -21,10 +21,7 @@ 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
|
|
25
|
-
if (__DEV__) {
|
|
26
|
-
console.warn("[AnonymousModeService] Storage load failed:", error);
|
|
27
|
-
}
|
|
24
|
+
} catch {
|
|
28
25
|
return false;
|
|
29
26
|
}
|
|
30
27
|
}
|
|
@@ -33,10 +30,7 @@ export class AnonymousModeService {
|
|
|
33
30
|
try {
|
|
34
31
|
await storageProvider.set(this.storageKey, this.isAnonymousMode.toString());
|
|
35
32
|
return true;
|
|
36
|
-
} catch
|
|
37
|
-
if (__DEV__) {
|
|
38
|
-
console.error("[AnonymousModeService] Storage save failed:", err);
|
|
39
|
-
}
|
|
33
|
+
} catch {
|
|
40
34
|
return false;
|
|
41
35
|
}
|
|
42
36
|
}
|
|
@@ -46,10 +40,7 @@ export class AnonymousModeService {
|
|
|
46
40
|
await storageProvider.remove(this.storageKey);
|
|
47
41
|
this.isAnonymousMode = false;
|
|
48
42
|
return true;
|
|
49
|
-
} catch
|
|
50
|
-
if (__DEV__) {
|
|
51
|
-
console.error("[AnonymousModeService] Storage clear failed:", err);
|
|
52
|
-
}
|
|
43
|
+
} catch {
|
|
53
44
|
this.isAnonymousMode = false;
|
|
54
45
|
return false;
|
|
55
46
|
}
|
|
@@ -60,18 +51,13 @@ export class AnonymousModeService {
|
|
|
60
51
|
if (provider?.getCurrentUser()) {
|
|
61
52
|
try {
|
|
62
53
|
await provider.signOut();
|
|
63
|
-
} catch
|
|
64
|
-
|
|
65
|
-
console.warn("[AnonymousModeService] Sign out failed during mode switch:", error);
|
|
66
|
-
}
|
|
54
|
+
} catch {
|
|
55
|
+
// Silently fail - sign out errors are handled elsewhere
|
|
67
56
|
}
|
|
68
57
|
}
|
|
69
58
|
|
|
70
59
|
this.isAnonymousMode = true;
|
|
71
|
-
|
|
72
|
-
if (!saved && __DEV__) {
|
|
73
|
-
console.warn("[AnonymousModeService] Anonymous mode enabled but not persisted to storage. Mode will be lost on app restart.");
|
|
74
|
-
}
|
|
60
|
+
await this.save(storageProvider);
|
|
75
61
|
emitAnonymousModeEnabled();
|
|
76
62
|
}
|
|
77
63
|
|
|
@@ -92,10 +92,8 @@ export class AuthEventService {
|
|
|
92
92
|
eventListeners.forEach((listener) => {
|
|
93
93
|
try {
|
|
94
94
|
listener(payload);
|
|
95
|
-
} catch
|
|
96
|
-
|
|
97
|
-
console.error("[AuthEventService] Listener error:", err);
|
|
98
|
-
}
|
|
95
|
+
} catch {
|
|
96
|
+
// Silently fail - listener errors should not break the event system
|
|
99
97
|
}
|
|
100
98
|
});
|
|
101
99
|
}
|
|
@@ -65,9 +65,8 @@ async function doInitializeAuth(
|
|
|
65
65
|
let authServiceInitFailed = false;
|
|
66
66
|
try {
|
|
67
67
|
await initializeAuthService(auth, authConfig, storageProvider);
|
|
68
|
-
} catch
|
|
68
|
+
} catch {
|
|
69
69
|
authServiceInitFailed = true;
|
|
70
|
-
console.warn("[initializeAuth] Auth service init failed, continuing:", error);
|
|
71
70
|
}
|
|
72
71
|
|
|
73
72
|
const handleAuthStateChange = createAuthStateHandler(conversionState, {
|
|
@@ -78,18 +77,10 @@ async function doInitializeAuth(
|
|
|
78
77
|
initializeAuthListener({
|
|
79
78
|
autoAnonymousSignIn,
|
|
80
79
|
onAuthStateChange: (user) => {
|
|
81
|
-
handleAuthStateChange(user)
|
|
82
|
-
if (__DEV__) {
|
|
83
|
-
console.error("[initializeAuth] Auth state change handler error:", err);
|
|
84
|
-
}
|
|
85
|
-
});
|
|
80
|
+
void handleAuthStateChange(user);
|
|
86
81
|
},
|
|
87
82
|
});
|
|
88
83
|
|
|
89
|
-
if (authServiceInitFailed) {
|
|
90
|
-
console.warn("[initializeAuth] Auth service initialization failed. Some auth features may not work.");
|
|
91
|
-
}
|
|
92
|
-
|
|
93
84
|
isInitialized = true;
|
|
94
85
|
return { success: !authServiceInitFailed, auth };
|
|
95
86
|
}
|
|
@@ -122,10 +122,6 @@ export function mapFirebaseAuthError(error: unknown): Error {
|
|
|
122
122
|
);
|
|
123
123
|
|
|
124
124
|
default:
|
|
125
|
-
// Log unknown errors in development for debugging
|
|
126
|
-
if (__DEV__ && code) {
|
|
127
|
-
console.warn(`[AuthErrorMapper] Unknown Firebase Auth code: ${code}`, error);
|
|
128
|
-
}
|
|
129
125
|
return new AuthError(message, code || "AUTH_UNKNOWN_ERROR");
|
|
130
126
|
}
|
|
131
127
|
}
|
|
@@ -35,10 +35,8 @@ export function createAuthStateHandler(
|
|
|
35
35
|
if (conversion.isConversion && onUserConverted && state.current.previousUserId) {
|
|
36
36
|
try {
|
|
37
37
|
await onUserConverted(state.current.previousUserId, currentUserId);
|
|
38
|
-
} catch
|
|
39
|
-
|
|
40
|
-
console.warn("[AuthStateHandler] User conversion callback failed:", error);
|
|
41
|
-
}
|
|
38
|
+
} catch {
|
|
39
|
+
// Silently fail - conversion callback errors are handled elsewhere
|
|
42
40
|
}
|
|
43
41
|
}
|
|
44
42
|
|
|
@@ -72,17 +72,8 @@ async function performAnonymousSignIn(
|
|
|
72
72
|
for (let attempt = 0; attempt < maxRetries; attempt++) {
|
|
73
73
|
try {
|
|
74
74
|
await anonymousAuthService.signInAnonymously(auth);
|
|
75
|
-
|
|
76
|
-
if (__DEV__) {
|
|
77
|
-
console.log("[AnonymousSignInHandler] Anonymous sign-in successful");
|
|
78
|
-
}
|
|
79
|
-
|
|
80
75
|
return;
|
|
81
76
|
} catch (error) {
|
|
82
|
-
if (__DEV__) {
|
|
83
|
-
console.warn(`[AnonymousSignInHandler] Attempt ${attempt + 1}/${maxRetries} failed:`, error);
|
|
84
|
-
}
|
|
85
|
-
|
|
86
77
|
// If not last attempt, wait and retry
|
|
87
78
|
if (attempt < maxRetries - 1) {
|
|
88
79
|
await new Promise(resolve => setTimeout(resolve, retryDelay));
|
|
@@ -110,9 +101,6 @@ export function createAnonymousSignInHandler(
|
|
|
110
101
|
): () => Promise<void> {
|
|
111
102
|
return async () => {
|
|
112
103
|
if (!auth) {
|
|
113
|
-
if (__DEV__) {
|
|
114
|
-
console.warn("[AnonymousSignInHandler] No auth instance");
|
|
115
|
-
}
|
|
116
104
|
store.setFirebaseUser(null);
|
|
117
105
|
store.setLoading(false);
|
|
118
106
|
store.setInitialized(true);
|
|
@@ -125,21 +113,13 @@ export function createAnonymousSignInHandler(
|
|
|
125
113
|
auth,
|
|
126
114
|
{
|
|
127
115
|
onSignInStart: () => {
|
|
128
|
-
|
|
129
|
-
console.log("[AnonymousSignInHandler] Starting anonymous sign-in");
|
|
130
|
-
}
|
|
116
|
+
// Sign-in starting
|
|
131
117
|
},
|
|
132
118
|
onSignInSuccess: () => {
|
|
133
|
-
if (__DEV__) {
|
|
134
|
-
console.log("[AnonymousSignInHandler] Anonymous sign-in successful");
|
|
135
|
-
}
|
|
136
119
|
// Listener will be triggered again with the new user
|
|
137
120
|
store.setFirebaseUser(null);
|
|
138
121
|
},
|
|
139
|
-
onSignInFailure: (
|
|
140
|
-
if (__DEV__) {
|
|
141
|
-
console.error("[AnonymousSignInHandler] All attempts failed:", error);
|
|
142
|
-
}
|
|
122
|
+
onSignInFailure: () => {
|
|
143
123
|
store.setFirebaseUser(null);
|
|
144
124
|
store.setLoading(false);
|
|
145
125
|
store.setInitialized(true);
|