@umituz/react-native-auth 4.3.43 → 4.3.45

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@umituz/react-native-auth",
3
- "version": "4.3.43",
3
+ "version": "4.3.45",
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",
@@ -5,8 +5,6 @@
5
5
 
6
6
  import type { IStorageProvider } from "../types/Storage.types";
7
7
 
8
- declare const __DEV__: boolean;
9
-
10
8
  /**
11
9
  * Interface that describes the shape of common storage implementations
12
10
  * to avoid using 'any' and resolve lint errors.
@@ -30,25 +28,18 @@ export class StorageProviderAdapter implements IStorageProvider {
30
28
  }
31
29
 
32
30
  async get(key: string): Promise<string | null> {
33
- try {
34
- if (typeof this.storage.getString === "function") {
35
- const result = await this.storage.getString(key, null);
36
- if (!result) return null;
37
- return result.value ?? result.data ?? null;
38
- } else if (typeof this.storage.getItem === "function") {
39
- const result = await this.storage.getItem(key);
40
- if (!result) return null;
41
- if (typeof result === "string") return result;
42
- if (result.data != null) return String(result.data);
43
- return null;
44
- } else {
45
- throw new Error("Unsupported storage implementation");
46
- }
47
- } catch (error) {
48
- if (typeof __DEV__ !== "undefined" && __DEV__) {
49
- console.warn("[StorageProviderAdapter] get failed for key:", key, error);
50
- }
31
+ if (typeof this.storage.getString === "function") {
32
+ const result = await this.storage.getString(key, null);
33
+ if (!result) return null;
34
+ return result.value ?? result.data ?? null;
35
+ } else if (typeof this.storage.getItem === "function") {
36
+ const result = await this.storage.getItem(key);
37
+ if (!result) return null;
38
+ if (typeof result === "string") return result;
39
+ if (result.data != null) return String(result.data);
51
40
  return null;
41
+ } else {
42
+ throw new Error("Unsupported storage implementation");
52
43
  }
53
44
  }
54
45
 
@@ -19,8 +19,8 @@ export class AnonymousModeService {
19
19
  const value = await storageProvider.get(this.storageKey);
20
20
  this.isAnonymousMode = value === "true";
21
21
  return this.isAnonymousMode;
22
- } catch {
23
- // On error, reset to false to maintain consistency
22
+ } catch (error) {
23
+ console.error('[AnonymousModeService] Failed to load state:', error instanceof Error ? error.message : String(error));
24
24
  this.isAnonymousMode = false;
25
25
  return false;
26
26
  }
@@ -30,7 +30,8 @@ export class AnonymousModeService {
30
30
  try {
31
31
  await storageProvider.set(this.storageKey, value.toString());
32
32
  return true;
33
- } catch {
33
+ } catch (error) {
34
+ console.error('[AnonymousModeService] Failed to save state:', error instanceof Error ? error.message : String(error));
34
35
  return false;
35
36
  }
36
37
  }
@@ -40,9 +41,8 @@ export class AnonymousModeService {
40
41
  await storageProvider.remove(this.storageKey);
41
42
  this.isAnonymousMode = false;
42
43
  return true;
43
- } catch {
44
- // Don't update memory state if storage operation failed
45
- // This maintains consistency between storage and memory
44
+ } catch (error) {
45
+ console.error('[AnonymousModeService] Failed to clear state:', error instanceof Error ? error.message : String(error));
46
46
  return false;
47
47
  }
48
48
  }
@@ -91,8 +91,8 @@ export function createAuthInitModule(
91
91
  if (onRestorePurchases) {
92
92
  try {
93
93
  await onRestorePurchases();
94
- } catch {
95
- // Silently fail - purchase restoration errors are handled elsewhere
94
+ } catch (error) {
95
+ console.error('[AuthInitModule] Purchase restoration failed:', error instanceof Error ? error.message : String(error));
96
96
  }
97
97
  }
98
98
 
@@ -104,8 +104,9 @@ export function createAuthInitModule(
104
104
  });
105
105
 
106
106
  return true;
107
- } catch {
108
- return false;
107
+ } catch (error) {
108
+ console.error('[AuthInitModule] Auth initialization failed:', error instanceof Error ? error.message : String(error));
109
+ throw error;
109
110
  }
110
111
  },
111
112
  };
@@ -57,8 +57,8 @@ export const AccountActions: React.FC<AccountActionsProps> = ({ config }) => {
57
57
  onPress: async () => {
58
58
  try {
59
59
  await onLogout();
60
- } catch {
61
- // Silently fail - logout error handling is managed elsewhere
60
+ } catch (error) {
61
+ console.error('[AccountActions] Logout failed:', error instanceof Error ? error.message : String(error));
62
62
  }
63
63
  },
64
64
  },
@@ -18,7 +18,7 @@ export function useRegisterFormHandlers(
18
18
  clearFieldError(setFieldErrors, "displayName");
19
19
  clearLocalError();
20
20
  },
21
- [updateField, clearLocalError]
21
+ [updateField, clearLocalError, setFieldErrors]
22
22
  );
23
23
 
24
24
  const handleEmailChange = useCallback(
@@ -27,7 +27,7 @@ export function useRegisterFormHandlers(
27
27
  clearFieldError(setFieldErrors, "email");
28
28
  clearLocalError();
29
29
  },
30
- [updateField, clearLocalError]
30
+ [updateField, clearLocalError, setFieldErrors]
31
31
  );
32
32
 
33
33
  const handlePasswordChange = useCallback(
@@ -36,7 +36,7 @@ export function useRegisterFormHandlers(
36
36
  clearFieldErrors(setFieldErrors, ["password", "confirmPassword"]);
37
37
  clearLocalError();
38
38
  },
39
- [updateField, clearLocalError]
39
+ [updateField, clearLocalError, setFieldErrors]
40
40
  );
41
41
 
42
42
  const handleConfirmPasswordChange = useCallback(
@@ -45,7 +45,7 @@ export function useRegisterFormHandlers(
45
45
  clearFieldError(setFieldErrors, "confirmPassword");
46
46
  clearLocalError();
47
47
  },
48
- [updateField, clearLocalError]
48
+ [updateField, clearLocalError, setFieldErrors]
49
49
  );
50
50
 
51
51
  return {
@@ -1,4 +1,4 @@
1
- import React, { useCallback, useEffect, useState } from "react";
1
+ import React, { useCallback, useEffect, useMemo, useState } from "react";
2
2
  import { useAppDesignTokens } from "@umituz/react-native-design-system/theme";
3
3
  import { StackNavigator, type StackNavigatorConfig, type StackScreenProps } from "@umituz/react-native-design-system/molecules";
4
4
  import { storageRepository, unwrap } from "@umituz/react-native-design-system/storage";
@@ -52,30 +52,32 @@ export const AuthNavigator: React.FC<AuthNavigatorProps> = ({
52
52
  void checkInitialRoute();
53
53
  }, []);
54
54
 
55
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
55
+ // Memoize nested translation objects to prevent screen wrapper recreation
56
+ const loginTranslations = useMemo(() => translations.login, [translations.login]);
57
+ const registerTranslations = useMemo(() => translations.register, [translations.register]);
58
+
56
59
  const LoginScreenWrapper = useCallback(
57
- (props: any) => (
60
+ (props: StackScreenProps<AuthStackParamList, 'Login'>) => (
58
61
  <LoginScreen
59
62
  {...props}
60
- translations={translations.login}
63
+ translations={loginTranslations}
61
64
  />
62
65
  ),
63
- [translations.login]
66
+ [loginTranslations]
64
67
  );
65
68
 
66
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
67
69
  const RegisterScreenWrapper = useCallback(
68
- (props: any) => (
70
+ (props: StackScreenProps<AuthStackParamList, 'Register'>) => (
69
71
  <RegisterScreen
70
72
  {...props}
71
- translations={translations.register}
73
+ translations={registerTranslations}
72
74
  termsUrl={termsUrl}
73
75
  privacyUrl={privacyUrl}
74
76
  onTermsPress={onTermsPress}
75
77
  onPrivacyPress={onPrivacyPress}
76
78
  />
77
79
  ),
78
- [translations.register, termsUrl, privacyUrl, onTermsPress, onPrivacyPress]
80
+ [registerTranslations, termsUrl, privacyUrl, onTermsPress, onPrivacyPress]
79
81
  );
80
82
 
81
83
  if (initialRouteName === undefined) {
@@ -73,8 +73,8 @@ export function AuthProvider({ children, ErrorFallback = DefaultErrorFallback }:
73
73
  if (unsubscribe) {
74
74
  try {
75
75
  unsubscribe();
76
- } catch {
77
- // Silently fail - cleanup errors are handled elsewhere
76
+ } catch (error) {
77
+ console.error('[AuthProvider] Cleanup failed:', error instanceof Error ? error.message : String(error));
78
78
  }
79
79
  }
80
80
  };
@@ -32,7 +32,6 @@ export function initializeAuthListener(
32
32
 
33
33
  // Atomic check-and-set to prevent race conditions
34
34
  if (!startInitialization()) {
35
- // Either already initializing or initialized - handle accordingly
36
35
  if (isListenerInitialized()) {
37
36
  const unsubscribe = handleExistingInitialization();
38
37
  return unsubscribe || handleInitializationInProgress();
@@ -40,12 +39,6 @@ export function initializeAuthListener(
40
39
  return handleInitializationInProgress();
41
40
  }
42
41
 
43
- // If already initialized, increment ref count and return unsubscribe
44
- if (isListenerInitialized()) {
45
- const unsubscribe = handleExistingInitialization();
46
- return unsubscribe || (() => {});
47
- }
48
-
49
42
  const auth = getFirebaseAuth();
50
43
  const store = useAuthStore.getState();
51
44
 
@@ -3,7 +3,7 @@
3
3
  * Provides reusable form field state management with automatic error clearing
4
4
  */
5
5
 
6
- import { useCallback, useState } from "react";
6
+ import { useCallback, useRef, useState } from "react";
7
7
 
8
8
  interface UseFormFieldOptions {
9
9
  clearLocalError?: () => void;
@@ -24,18 +24,25 @@ export function useFormFields<T extends Record<string, string>>(
24
24
 
25
25
  const [fields, setFields] = useState<T>(initialFields);
26
26
 
27
+ // Capture the initial fields only once so resetFields has a stable dep
28
+ const initialFieldsRef = useRef(initialFields);
29
+
30
+ // Use the function ref directly to avoid re-creating updateField when options object reference changes
31
+ const clearLocalErrorRef = useRef(options?.clearLocalError);
32
+ clearLocalErrorRef.current = options?.clearLocalError;
33
+
27
34
  const updateField = useCallback(
28
35
  (field: FieldKey, value: string) => {
29
36
  setFields((prev) => ({ ...prev, [field]: value }));
30
37
  // Note: setFieldErrors is handled externally by form hooks
31
- options?.clearLocalError?.();
38
+ clearLocalErrorRef.current?.();
32
39
  },
33
- [options]
40
+ [] // No deps - uses refs internally
34
41
  );
35
42
 
36
43
  const resetFields = useCallback(() => {
37
- setFields(initialFields);
38
- }, [initialFields]);
44
+ setFields(initialFieldsRef.current);
45
+ }, []); // No deps - always resets to original initial values
39
46
 
40
47
  return {
41
48
  fields,