@umituz/react-native-firebase 2.4.30 → 2.4.32

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 (55) hide show
  1. package/package.json +1 -1
  2. package/src/domains/account-deletion/application/ports/reauthentication.types.ts +0 -14
  3. package/src/domains/account-deletion/infrastructure/services/account-deletion.service.ts +0 -2
  4. package/src/domains/account-deletion/infrastructure/services/reauthentication.service.ts +0 -6
  5. package/src/domains/auth/domain/entities/AnonymousUser.ts +0 -13
  6. package/src/domains/auth/domain/utils/user-validation.util.ts +0 -19
  7. package/src/domains/auth/infrastructure/config/FirebaseAuthClient.ts +0 -1
  8. package/src/domains/auth/infrastructure/services/apple-auth.types.ts +0 -19
  9. package/src/domains/auth/infrastructure/services/base/base-auth.service.ts +0 -49
  10. package/src/domains/auth/infrastructure/services/google-auth.types.ts +0 -12
  11. package/src/domains/auth/infrastructure/services/user-document.service.ts +0 -6
  12. package/src/domains/auth/infrastructure/services/utils/auth-result-converter.util.ts +3 -3
  13. package/src/domains/auth/infrastructure/utils/auth-guard.util.ts +2 -48
  14. package/src/domains/auth/presentation/hooks/useGoogleOAuth.ts +1 -1
  15. package/src/domains/auth/presentation/hooks/utils/auth-state-change.handler.ts +2 -2
  16. package/src/domains/firestore/infrastructure/middleware/QueryDeduplicationMiddleware.ts +0 -1
  17. package/src/domains/firestore/infrastructure/repositories/BaseRepository.ts +1 -1
  18. package/src/domains/firestore/utils/deduplication/pending-query-manager.util.ts +1 -1
  19. package/src/domains/firestore/utils/deduplication/query-key-generator.util.ts +0 -16
  20. package/src/domains/firestore/utils/deduplication/timer-manager.util.ts +1 -1
  21. package/src/domains/firestore/utils/firestore-helper.ts +0 -3
  22. package/src/domains/firestore/utils/query/filters.util.ts +0 -10
  23. package/src/domains/firestore/utils/query-builder.ts +3 -3
  24. package/src/domains/firestore/utils/result/result.util.ts +2 -5
  25. package/src/init/index.ts +0 -2
  26. package/src/shared/domain/guards/firebase-error.guard.ts +3 -3
  27. package/src/shared/domain/utils/async-executor.util.ts +1 -10
  28. package/src/shared/domain/utils/error-handlers/error-checkers.ts +1 -37
  29. package/src/shared/domain/utils/error-handlers/error-messages.ts +0 -3
  30. package/src/shared/domain/utils/executors/basic-executors.util.ts +1 -22
  31. package/src/shared/domain/utils/id-generator.util.ts +0 -37
  32. package/src/shared/domain/utils/index.ts +0 -90
  33. package/src/shared/domain/utils/result/result-creators.ts +1 -1
  34. package/src/shared/domain/utils/result/result-helpers.ts +1 -48
  35. package/src/shared/domain/utils/service-config.util.ts +2 -21
  36. package/src/shared/domain/utils/type-guards.util.ts +1 -55
  37. package/src/shared/domain/utils/validators/firebase.validator.ts +0 -11
  38. package/src/shared/domain/utils/validators/string.validator.ts +0 -14
  39. package/src/shared/infrastructure/config/base/ClientStateManager.ts +1 -1
  40. package/src/shared/infrastructure/config/base/ServiceClientSingleton.ts +2 -2
  41. package/src/shared/infrastructure/config/initializers/FirebaseAppInitializer.ts +2 -92
  42. package/src/domains/auth/domain/errors/FirebaseAuthError.ts +0 -18
  43. package/src/domains/auth/infrastructure/services/auth-guard.service.ts +0 -101
  44. package/src/domains/auth/presentation/hooks/shared/auth-hooks.util.ts +0 -60
  45. package/src/domains/auth/presentation/hooks/shared/safe-state-hooks.util.ts +0 -76
  46. package/src/domains/auth/presentation/hooks/shared/state-hooks.util.ts +0 -97
  47. package/src/shared/domain/utils/credential.util.ts +0 -102
  48. package/src/shared/domain/utils/executors/advanced-executors.util.ts +0 -59
  49. package/src/shared/domain/utils/executors/batch-executors.util.ts +0 -42
  50. package/src/shared/domain/utils/validators/composite.validator.ts +0 -24
  51. package/src/shared/domain/utils/validators/generic.validator.ts +0 -59
  52. package/src/shared/domain/utils/validators/url.validator.ts +0 -36
  53. package/src/shared/domain/utils/validators/user-input.validator.ts +0 -54
  54. package/src/shared/domain/utils/validators/validation.util.ts +0 -63
  55. package/src/shared/infrastructure/config/validators/FirebaseConfigValidator.ts +0 -89
@@ -11,40 +11,3 @@
11
11
  export function generateUniqueId(): string {
12
12
  return `${Date.now()}-${Math.random().toString(36).substring(2, 11)}`;
13
13
  }
14
-
15
- /**
16
- * Generate a short random ID
17
- * Useful for temporary identifiers where uniqueness within scope is sufficient
18
- * @returns Random identifier string
19
- */
20
- export function generateShortId(length: number = 8): string {
21
- return Math.random().toString(36).substring(2, 2 + length);
22
- }
23
-
24
- /**
25
- * Generate a UUID-like ID
26
- * Format: xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx
27
- * @returns UUID-like identifier string
28
- */
29
- export function generateUUID(): string {
30
- return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, (c) => {
31
- const r = (Math.random() * 16) | 0;
32
- const v = c === 'x' ? r : (r & 0x3) | 0x8;
33
- return v.toString(16);
34
- });
35
- }
36
-
37
- /**
38
- * Generate a nanoid-like ID
39
- * Uses URL-safe characters for better compatibility
40
- * @param length - Length of the ID (default: 21)
41
- * @returns URL-safe unique identifier string
42
- */
43
- export function generateNanoId(length: number = 21): string {
44
- const chars = 'ModuleSymbhasOwnPr-0123456789ABCDEFGHNRVfgctiUvz_KqYTJkLxpZXIjQW';
45
- let result = '';
46
- for (let i = 0; i < length; i++) {
47
- result += chars.charAt(Math.floor(Math.random() * chars.length));
48
- }
49
- return result;
50
- }
@@ -6,112 +6,22 @@
6
6
  // Result types and helpers
7
7
  export type {
8
8
  Result,
9
- SuccessResult,
10
- FailureResult,
11
- ErrorInfo,
12
9
  } from './result/result-types';
13
10
 
14
11
  export {
15
12
  successResult,
16
- failureResult,
17
13
  failureResultFrom,
18
- failureResultFromError,
19
14
  } from './result/result-creators';
20
15
 
21
- export {
22
- isSuccess,
23
- isFailure,
24
- getDataOrDefault,
25
- mapResult,
26
- chainResults,
27
- } from './result/result-helpers';
28
-
29
16
  // Async operation execution
30
17
  export {
31
18
  executeOperation,
32
- executeOperationWithCode,
33
- executeVoidOperation,
34
19
  executeAuthOperation,
35
- executeAll,
36
- executeSequence,
37
- executeWithRetry,
38
- executeWithTimeout,
39
20
  } from './async-executor.util';
40
21
 
41
- // Service configuration
42
- export {
43
- ConfigurableService,
44
- createConfigurableService,
45
- type ConfigState,
46
- type IConfigurableService,
47
- } from './service-config.util';
48
-
49
- // Credential utilities
50
- export {
51
- generateGoogleCredential,
52
- generateAppleCredential,
53
- isAppleSignInAvailable,
54
- performAppleSignIn,
55
- isValidEmailPassword,
56
- type EmailPasswordCredential,
57
- type CredentialGenerator,
58
- } from './credential.util';
59
-
60
22
  // Error handling
61
23
  export { toErrorInfo } from './error-handlers/error-converters';
62
24
 
63
- export {
64
- hasErrorCode,
65
- isCancelledError,
66
- isQuotaErrorInfo,
67
- isNetworkError,
68
- isAuthError,
69
- isQuotaError,
70
- isRetryableError,
71
- } from './error-handlers/error-checkers';
72
-
73
25
  export {
74
26
  ERROR_MESSAGES,
75
- getQuotaErrorMessage,
76
- getRetryableErrorMessage,
77
27
  } from './error-handlers/error-messages';
78
-
79
- // Type guards
80
- export {
81
- hasCodeProperty,
82
- hasMessageProperty,
83
- hasCodeAndMessageProperties,
84
- } from './type-guards.util';
85
-
86
- // Validation
87
- export {
88
- isValidString,
89
- isEmptyString,
90
- isDefined,
91
- } from './validators/string.validator';
92
-
93
- export {
94
- isValidFirebaseApiKey,
95
- isValidFirebaseAuthDomain,
96
- isValidFirebaseProjectId,
97
- } from './validators/firebase.validator';
98
-
99
- export {
100
- isValidUrl,
101
- isValidHttpsUrl,
102
- } from './validators/url.validator';
103
-
104
- export { isValidEmail } from './validators/user-input.validator';
105
-
106
- export {
107
- isNonEmptyArray,
108
- isInRange,
109
- isPositive,
110
- isNonNegative,
111
- } from './validators/generic.validator';
112
-
113
- // ID generation
114
- export {
115
- generateUniqueId,
116
- generateShortId,
117
- } from './id-generator.util';
@@ -16,7 +16,7 @@ export function successResult<T = void>(data?: T): SuccessResult<T> {
16
16
  /**
17
17
  * Create a failure result with error information
18
18
  */
19
- export function failureResult(error: ErrorInfo): FailureResult {
19
+ function failureResult(error: ErrorInfo): FailureResult {
20
20
  return { success: false, error };
21
21
  }
22
22
 
@@ -3,8 +3,7 @@
3
3
  * Utility functions for working with Result type
4
4
  */
5
5
 
6
- import type { Result, SuccessResult, FailureResult } from './result-types';
7
- import { successResult } from './result-creators';
6
+ import type { Result, SuccessResult } from './result-types';
8
7
 
9
8
  /**
10
9
  * Check if result is successful
@@ -12,49 +11,3 @@ import { successResult } from './result-creators';
12
11
  export function isSuccess<T>(result: Result<T>): result is SuccessResult<T> {
13
12
  return result.success === true && result.error === undefined;
14
13
  }
15
-
16
- /**
17
- * Check if result is a failure
18
- */
19
- export function isFailure<T>(result: Result<T>): result is FailureResult {
20
- return result.success === false && result.error !== undefined;
21
- }
22
-
23
- /**
24
- * Get data from result or return default
25
- */
26
- export function getDataOrDefault<T>(result: Result<T>, defaultValue: T): T {
27
- return isSuccess(result) ? (result.data ?? defaultValue) : defaultValue;
28
- }
29
-
30
- /**
31
- * Map success result data to another type
32
- */
33
- export function mapResult<T, U>(
34
- result: Result<T>,
35
- mapper: (data: T) => U
36
- ): Result<U> {
37
- if (isSuccess(result) && result.data !== undefined) {
38
- return successResult(mapper(result.data));
39
- }
40
- // Return a new failure result to avoid type conflicts
41
- if (isFailure(result)) {
42
- return { success: false, error: result.error };
43
- }
44
- return successResult();
45
- }
46
-
47
- /**
48
- * Chain multiple results, stopping at first failure
49
- */
50
- export async function chainResults<T>(
51
- ...operations: (() => Promise<Result<T>>)[]
52
- ): Promise<Result<T>> {
53
- for (const operation of operations) {
54
- const result = await operation();
55
- if (isFailure(result)) {
56
- return result;
57
- }
58
- }
59
- return successResult();
60
- }
@@ -3,26 +3,16 @@ import { ERROR_MESSAGES } from './error-handlers/error-messages';
3
3
  /**
4
4
  * Configuration state management
5
5
  */
6
- export interface ConfigState<TConfig> {
6
+ interface ConfigState<TConfig> {
7
7
  config: TConfig | null;
8
8
  initialized: boolean;
9
9
  }
10
10
 
11
- /**
12
- * Configurable service interface
13
- */
14
- export interface IConfigurableService<TConfig> {
15
- configure(config: TConfig): void;
16
- isConfigured(): boolean;
17
- getConfig(): TConfig | null;
18
- reset(): void;
19
- }
20
-
21
11
  /**
22
12
  * Base class for configurable services
23
13
  * Provides configuration management pattern
24
14
  */
25
- export class ConfigurableService<TConfig = unknown> implements IConfigurableService<TConfig> {
15
+ export class ConfigurableService<TConfig = unknown> {
26
16
  protected configState: ConfigState<TConfig>;
27
17
  private customValidator?: (config: TConfig) => boolean;
28
18
 
@@ -81,12 +71,3 @@ export class ConfigurableService<TConfig = unknown> implements IConfigurableServ
81
71
  return this.configState.config;
82
72
  }
83
73
  }
84
-
85
- /**
86
- * Create a configurable service instance
87
- */
88
- export function createConfigurableService<TConfig>(
89
- validator?: (config: TConfig) => boolean
90
- ): ConfigurableService<TConfig> {
91
- return new ConfigurableService<TConfig>(validator);
92
- }
@@ -7,33 +7,11 @@
7
7
 
8
8
  /**
9
9
  * Type guard for non-null objects
10
- * Eliminates duplicate object checking pattern throughout the codebase
11
- *
12
- * @example
13
- * ```typescript
14
- * if (isObject(value)) {
15
- * // value is Record<string, unknown>
16
- * }
17
- * ```
18
10
  */
19
- export function isObject(value: unknown): value is Record<string, unknown> {
11
+ function isObject(value: unknown): value is Record<string, unknown> {
20
12
  return typeof value === 'object' && value !== null;
21
13
  }
22
14
 
23
- /**
24
- * Type guard for objects with a specific property
25
- *
26
- * @param value - Value to check
27
- * @param key - Property key to check for
28
- * @returns True if value is an object with the specified property
29
- */
30
- export function hasProperty<K extends string>(
31
- value: unknown,
32
- key: K
33
- ): value is Record<K, unknown> {
34
- return isObject(value) && key in value;
35
- }
36
-
37
15
  /**
38
16
  * Type guard for objects with a 'code' property of type string
39
17
  * Commonly used for Firebase errors and other error objects
@@ -57,35 +35,3 @@ export function hasMessageProperty(error: unknown): error is { message: string }
57
35
  typeof (error as { message: unknown }).message === 'string'
58
36
  );
59
37
  }
60
-
61
- /**
62
- * Type guard for objects with both 'code' and 'message' properties
63
- * Commonly used for Firebase error objects
64
- */
65
- export function hasCodeAndMessageProperties(error: unknown): error is { code: string; message: string } {
66
- return hasCodeProperty(error) && hasMessageProperty(error);
67
- }
68
-
69
- /**
70
- * Type guard for objects with a 'name' property of type string
71
- * Commonly used for Error objects
72
- */
73
- export function hasNameProperty(error: unknown): error is { name: string } {
74
- return (
75
- isObject(error) &&
76
- 'name' in error &&
77
- typeof (error as { name: unknown }).name === 'string'
78
- );
79
- }
80
-
81
- /**
82
- * Type guard for objects with a 'stack' property of type string
83
- * Commonly used for Error objects
84
- */
85
- export function hasStackProperty(error: unknown): error is { stack: string } {
86
- return (
87
- isObject(error) &&
88
- 'stack' in error &&
89
- typeof (error as { stack: unknown }).stack === 'string'
90
- );
91
- }
@@ -31,14 +31,3 @@ export function isValidFirebaseAuthDomain(authDomain: string): boolean {
31
31
  );
32
32
  }
33
33
 
34
- /**
35
- * Validate Firebase projectId format
36
- * Project IDs must be 6-30 characters, lowercase, alphanumeric, and may contain hyphens
37
- */
38
- export function isValidFirebaseProjectId(projectId: string): boolean {
39
- if (!isValidString(projectId)) {
40
- return false;
41
- }
42
- const pattern = /^[a-z0-9][a-z0-9-]{4,28}[a-z0-9]$/;
43
- return pattern.test(projectId);
44
- }
@@ -9,17 +9,3 @@
9
9
  export function isValidString(value: unknown): value is string {
10
10
  return typeof value === 'string' && value.trim().length > 0;
11
11
  }
12
-
13
- /**
14
- * Check if a string is empty or whitespace only
15
- */
16
- export function isEmptyString(value: unknown): boolean {
17
- return typeof value === 'string' && value.trim().length === 0;
18
- }
19
-
20
- /**
21
- * Check if value is defined (not null or undefined)
22
- */
23
- export function isDefined<T>(value: T | null | undefined): value is T {
24
- return value !== null && value !== undefined;
25
- }
@@ -7,7 +7,7 @@
7
7
  * @template TInstance - The service instance type (e.g., FirebaseApp, Firestore, Auth)
8
8
  */
9
9
 
10
- export interface ClientState<TInstance> {
10
+ interface ClientState<TInstance> {
11
11
  instance: TInstance | null;
12
12
  initializationError: string | null;
13
13
  isInitialized: boolean;
@@ -14,13 +14,13 @@
14
14
  * @template TConfig - The configuration type (optional)
15
15
  */
16
16
 
17
- export interface ServiceClientState<TInstance> {
17
+ interface ServiceClientState<TInstance> {
18
18
  instance: TInstance | null;
19
19
  initializationError: string | null;
20
20
  isInitialized: boolean;
21
21
  }
22
22
 
23
- export interface ServiceClientOptions<TInstance, TConfig = unknown> {
23
+ interface ServiceClientOptions<TInstance, TConfig = unknown> {
24
24
  serviceName: string;
25
25
  initializer?: (config?: TConfig) => TInstance | null;
26
26
  autoInitializer?: () => TInstance | null;
@@ -1,99 +1,9 @@
1
1
  /**
2
2
  * Firebase App Initializer
3
3
  *
4
- * Single Responsibility: Initialize Firebase App instance
4
+ * Single Responsibility: Expose Firebase App type
5
5
  */
6
6
 
7
- import {
8
- initializeApp,
9
- getApps,
10
- type FirebaseApp as FirebaseAppType,
11
- } from 'firebase/app';
12
- import type { FirebaseConfig } from '../../../domain/value-objects/FirebaseConfig';
13
- import { FirebaseInitializationError } from '../../../domain/errors/FirebaseError';
7
+ import type { FirebaseApp as FirebaseAppType } from 'firebase/app';
14
8
 
15
9
  export type FirebaseApp = FirebaseAppType;
16
-
17
- /**
18
- * Firebase configuration mapper
19
- */
20
- class FirebaseConfigMapper {
21
- /**
22
- * Map domain config to Firebase SDK config
23
- */
24
- static toFirebaseConfig(config: FirebaseConfig): Record<string, string | undefined> {
25
- return {
26
- apiKey: config.apiKey,
27
- authDomain: config.authDomain,
28
- projectId: config.projectId,
29
- storageBucket: config.storageBucket,
30
- messagingSenderId: config.messagingSenderId,
31
- appId: config.appId,
32
- };
33
- }
34
- }
35
-
36
- /**
37
- * Firebase App manager
38
- */
39
- class FirebaseAppManager {
40
- /**
41
- * Check if Firebase App is already initialized
42
- */
43
- static isInitialized(): boolean {
44
- try {
45
- const existingApps = getApps();
46
- return existingApps.length > 0;
47
- } catch {
48
- return false;
49
- }
50
- }
51
-
52
- /**
53
- * Get existing Firebase App instance
54
- */
55
- static getExistingApp(): FirebaseApp | null {
56
- try {
57
- const existingApps = getApps();
58
- return existingApps.length > 0 ? existingApps[0] ?? null : null;
59
- } catch {
60
- return null;
61
- }
62
- }
63
-
64
- /**
65
- * Create new Firebase App instance
66
- */
67
- static createApp(config: FirebaseConfig): FirebaseApp {
68
- try {
69
- const firebaseConfig = FirebaseConfigMapper.toFirebaseConfig(config);
70
- return initializeApp(firebaseConfig);
71
- } catch (error) {
72
- throw new FirebaseInitializationError(
73
- `Failed to initialize Firebase App: ${
74
- error instanceof Error ? error.message : 'Unknown error'
75
- }`,
76
- error
77
- );
78
- }
79
- }
80
- }
81
-
82
- /**
83
- * Initializes Firebase App
84
- */
85
- export class FirebaseAppInitializer {
86
- /**
87
- * Initialize or get existing Firebase App
88
- */
89
- static initialize(config: FirebaseConfig): FirebaseApp {
90
- // Return existing app if already initialized
91
- const existingApp = FirebaseAppManager.getExistingApp();
92
- if (existingApp) {
93
- return existingApp;
94
- }
95
-
96
- // Create new app
97
- return FirebaseAppManager.createApp(config);
98
- }
99
- }
@@ -1,18 +0,0 @@
1
- /**
2
- * Firebase Auth Error Classes
3
- * Custom error types for Firebase Auth operations
4
- */
5
-
6
- export class FirebaseAuthError extends Error {
7
- constructor(message: string) {
8
- super(message);
9
- this.name = 'FirebaseAuthError';
10
- }
11
- }
12
-
13
- export class FirebaseAuthInitializationError extends FirebaseAuthError {
14
- constructor(message: string) {
15
- super(message);
16
- this.name = 'FirebaseAuthInitializationError';
17
- }
18
- }
@@ -1,101 +0,0 @@
1
- /**
2
- * Auth Guard Service
3
- * Single Responsibility: Validate authenticated user access
4
- *
5
- * SOLID: Single Responsibility - Only handles auth validation
6
- * Generic implementation for all React Native apps
7
- */
8
-
9
- import {
10
- getCurrentUserId,
11
- getCurrentUser,
12
- } from './auth-utils.service';
13
- import { ERROR_MESSAGES } from '../../../../shared/domain/utils/error-handlers/error-messages';
14
- import { withAuth, withAuthSync } from '../utils/auth-guard.util';
15
-
16
- /**
17
- * Auth Guard Service
18
- * Provides authentication validation for protected operations
19
- */
20
- export class AuthGuardService {
21
- /**
22
- * Check if user is authenticated (not guest)
23
- * @throws Error if user is not authenticated
24
- */
25
- async requireAuthenticatedUser(): Promise<string> {
26
- const result = await withAuth(async (auth) => {
27
- const userId = getCurrentUserId(auth);
28
- if (!userId) {
29
- throw new Error(ERROR_MESSAGES.AUTH.NOT_AUTHENTICATED);
30
- }
31
-
32
- const currentUser = getCurrentUser(auth);
33
- if (!currentUser) {
34
- throw new Error(ERROR_MESSAGES.AUTH.NOT_AUTHENTICATED);
35
- }
36
-
37
- if (currentUser.isAnonymous) {
38
- throw new Error(ERROR_MESSAGES.AUTH.NON_ANONYMOUS_ONLY);
39
- }
40
-
41
- return userId;
42
- });
43
-
44
- if (!result.success) {
45
- throw new Error(result.error?.message || 'Authentication failed');
46
- }
47
-
48
- if (!result.data) {
49
- throw new Error('No user ID returned');
50
- }
51
-
52
- return result.data;
53
- }
54
-
55
- /**
56
- * Check if user is authenticated (not guest)
57
- * Returns null if not authenticated instead of throwing
58
- */
59
- async getAuthenticatedUserId(): Promise<string | null> {
60
- try {
61
- return await this.requireAuthenticatedUser();
62
- } catch {
63
- return null;
64
- }
65
- }
66
-
67
- /**
68
- * Check if current user is authenticated (not guest)
69
- */
70
- isAuthenticated(): boolean {
71
- const result = withAuthSync((auth) => {
72
- const currentUser = getCurrentUser(auth);
73
- if (!currentUser) {
74
- return false;
75
- }
76
-
77
- // User must not be anonymous
78
- return !currentUser.isAnonymous;
79
- });
80
-
81
- return result.success && result.data ? result.data : false;
82
- }
83
-
84
- /**
85
- * Check if current user is guest (anonymous)
86
- */
87
- isGuest(): boolean {
88
- const result = withAuthSync((auth) => {
89
- const currentUser = getCurrentUser(auth);
90
- if (!currentUser) {
91
- return false;
92
- }
93
-
94
- return currentUser.isAnonymous;
95
- });
96
-
97
- return result.success && result.data ? result.data : false;
98
- }
99
- }
100
-
101
- export const authGuardService = new AuthGuardService();
@@ -1,60 +0,0 @@
1
- /**
2
- * Auth-Specific Hooks
3
- * React hooks for Firebase Auth state management
4
- */
5
-
6
- import { useRef, useEffect } from 'react';
7
- import { onAuthStateChanged, type Auth, type User } from 'firebase/auth';
8
-
9
- /**
10
- * Create an auth state handler
11
- */
12
- export function createAuthStateHandler(
13
- setState: (user: User | null) => void,
14
- setLoading: (loading: boolean) => void,
15
- setError: (error: Error | null) => void
16
- ): (user: User | null) => void {
17
- return (user: User | null) => {
18
- try {
19
- setState(user);
20
- setError(null);
21
- } catch (err) {
22
- const error = err instanceof Error ? err : new Error('Auth state update failed');
23
- setError(error);
24
- } finally {
25
- setLoading(false);
26
- }
27
- };
28
- }
29
-
30
- /**
31
- * Hook for managing auth listener lifecycle
32
- */
33
- export function useAuthListener(
34
- auth: Auth | null,
35
- onAuthStateChange: (user: User | null) => void
36
- ): void {
37
- const unsubscribeRef = useRef<(() => void) | null>(null);
38
-
39
- useEffect(() => {
40
- // Cleanup previous listener
41
- if (unsubscribeRef.current) {
42
- unsubscribeRef.current();
43
- unsubscribeRef.current = null;
44
- }
45
-
46
- if (!auth) {
47
- onAuthStateChange(null);
48
- return;
49
- }
50
-
51
- unsubscribeRef.current = onAuthStateChanged(auth, onAuthStateChange);
52
-
53
- return () => {
54
- if (unsubscribeRef.current) {
55
- unsubscribeRef.current();
56
- unsubscribeRef.current = null;
57
- }
58
- };
59
- }, [auth, onAuthStateChange]);
60
- }