@umituz/react-native-firebase 1.13.149 → 1.13.150

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 (35) hide show
  1. package/package.json +1 -1
  2. package/src/auth/infrastructure/services/apple-auth.service.ts +10 -2
  3. package/src/auth/infrastructure/services/google-auth.service.ts +10 -2
  4. package/src/auth/infrastructure/services/reauthentication.service.ts +5 -1
  5. package/src/auth/presentation/hooks/shared/auth-hooks.util.ts +60 -0
  6. package/src/auth/presentation/hooks/shared/hook-utils.util.ts +14 -216
  7. package/src/auth/presentation/hooks/shared/safe-state-hooks.util.ts +76 -0
  8. package/src/auth/presentation/hooks/shared/state-hooks.util.ts +97 -0
  9. package/src/domain/utils/async-executor.util.ts +16 -169
  10. package/src/domain/utils/error-handler.util.ts +18 -170
  11. package/src/domain/utils/error-handlers/error-checkers.ts +120 -0
  12. package/src/domain/utils/error-handlers/error-converters.ts +48 -0
  13. package/src/domain/utils/error-handlers/error-messages.ts +18 -0
  14. package/src/domain/utils/executors/advanced-executors.util.ts +59 -0
  15. package/src/domain/utils/executors/basic-executors.util.ts +56 -0
  16. package/src/domain/utils/executors/batch-executors.util.ts +42 -0
  17. package/src/domain/utils/executors/error-converters.util.ts +45 -0
  18. package/src/domain/utils/result/result-creators.ts +49 -0
  19. package/src/domain/utils/result/result-helpers.ts +60 -0
  20. package/src/domain/utils/result/result-types.ts +40 -0
  21. package/src/domain/utils/result.util.ts +28 -127
  22. package/src/domain/utils/validation.util.ts +38 -209
  23. package/src/domain/utils/validators/composite.validator.ts +24 -0
  24. package/src/domain/utils/validators/firebase.validator.ts +45 -0
  25. package/src/domain/utils/validators/generic.validator.ts +59 -0
  26. package/src/domain/utils/validators/string.validator.ts +25 -0
  27. package/src/domain/utils/validators/url.validator.ts +36 -0
  28. package/src/domain/utils/validators/user-input.validator.ts +54 -0
  29. package/src/firestore/infrastructure/middleware/QuotaTrackingMiddleware.ts +10 -3
  30. package/src/firestore/utils/deduplication/timer-manager.util.ts +2 -2
  31. package/src/firestore/utils/pagination.helper.ts +3 -1
  32. package/src/infrastructure/config/FirebaseClient.ts +28 -189
  33. package/src/infrastructure/config/clients/FirebaseClientSingleton.ts +82 -0
  34. package/src/infrastructure/config/services/FirebaseInitializationService.ts +115 -0
  35. package/src/init/createFirebaseInitModule.ts +9 -3
@@ -0,0 +1,45 @@
1
+ /**
2
+ * Firebase-Specific Validators
3
+ * Validation utilities for Firebase configuration
4
+ */
5
+
6
+ import { isValidString } from './string.validator';
7
+
8
+ /**
9
+ * Validate Firebase API key format
10
+ * Firebase API keys typically start with "AIza" followed by 35 characters
11
+ */
12
+ export function isValidFirebaseApiKey(apiKey: string): boolean {
13
+ if (!isValidString(apiKey)) {
14
+ return false;
15
+ }
16
+ const apiKeyPattern = /^AIza[0-9A-Za-z_-]{35}$/;
17
+ return apiKeyPattern.test(apiKey.trim());
18
+ }
19
+
20
+ /**
21
+ * Validate Firebase authDomain format
22
+ * Expected format: "projectId.firebaseapp.com" or "projectId.web.app"
23
+ */
24
+ export function isValidFirebaseAuthDomain(authDomain: string): boolean {
25
+ if (!isValidString(authDomain)) {
26
+ return false;
27
+ }
28
+ const trimmed = authDomain.trim();
29
+ return (
30
+ trimmed.includes('.firebaseapp.com') ||
31
+ trimmed.includes('.web.app')
32
+ );
33
+ }
34
+
35
+ /**
36
+ * Validate Firebase projectId format
37
+ * Project IDs must be 6-30 characters, lowercase, alphanumeric, and may contain hyphens
38
+ */
39
+ export function isValidFirebaseProjectId(projectId: string): boolean {
40
+ if (!isValidString(projectId)) {
41
+ return false;
42
+ }
43
+ const pattern = /^[a-z0-9][a-z0-9-]{4,28}[a-z0-9]$/;
44
+ return pattern.test(projectId.trim());
45
+ }
@@ -0,0 +1,59 @@
1
+ /**
2
+ * Generic Validators
3
+ * Generic validation utilities for arrays, numbers, and objects
4
+ */
5
+
6
+ /**
7
+ * Check if array is not empty
8
+ */
9
+ export function isNonEmptyArray<T>(value: unknown): value is [T, ...T[]] {
10
+ return Array.isArray(value) && value.length > 0;
11
+ }
12
+
13
+ /**
14
+ * Check if number is in range
15
+ */
16
+ export function isInRange(value: number, min: number, max: number): boolean {
17
+ return typeof value === 'number' && value >= min && value <= max;
18
+ }
19
+
20
+ /**
21
+ * Check if number is positive
22
+ */
23
+ export function isPositive(value: number): boolean {
24
+ return typeof value === 'number' && value > 0;
25
+ }
26
+
27
+ /**
28
+ * Check if number is non-negative
29
+ */
30
+ export function isNonNegative(value: number): boolean {
31
+ return typeof value === 'number' && value >= 0;
32
+ }
33
+
34
+ /**
35
+ * Validate object has required properties
36
+ */
37
+ export function hasRequiredProperties<T extends Record<string, unknown>>(
38
+ obj: unknown,
39
+ requiredProps: (keyof T)[]
40
+ ): obj is T {
41
+ if (typeof obj !== 'object' || obj === null) {
42
+ return false;
43
+ }
44
+ return requiredProps.every((prop) => prop in obj);
45
+ }
46
+
47
+ /**
48
+ * Validate all items in array match predicate
49
+ */
50
+ export function allMatch<T>(items: unknown[], predicate: (item: unknown) => item is T): boolean {
51
+ return Array.isArray(items) && items.every(predicate);
52
+ }
53
+
54
+ /**
55
+ * Validate at least one item in array matches predicate
56
+ */
57
+ export function anyMatch<T>(items: unknown[], predicate: (item: unknown) => item is T): boolean {
58
+ return Array.isArray(items) && items.some(predicate);
59
+ }
@@ -0,0 +1,25 @@
1
+ /**
2
+ * String Validators
3
+ * Basic string validation utilities
4
+ */
5
+
6
+ /**
7
+ * Check if a string is a valid non-empty value
8
+ */
9
+ export function isValidString(value: unknown): value is string {
10
+ return typeof value === 'string' && value.trim().length > 0;
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
+ }
@@ -0,0 +1,36 @@
1
+ /**
2
+ * URL Validators
3
+ * Validation utilities for URLs
4
+ */
5
+
6
+ import { isValidString } from './string.validator';
7
+
8
+ /**
9
+ * Validate URL format
10
+ */
11
+ export function isValidUrl(url: string): boolean {
12
+ if (!isValidString(url)) {
13
+ return false;
14
+ }
15
+ try {
16
+ new URL(url.trim());
17
+ return true;
18
+ } catch {
19
+ return false;
20
+ }
21
+ }
22
+
23
+ /**
24
+ * Validate HTTPS URL
25
+ */
26
+ export function isValidHttpsUrl(url: string): boolean {
27
+ if (!isValidString(url)) {
28
+ return false;
29
+ }
30
+ try {
31
+ const urlObj = new URL(url.trim());
32
+ return urlObj.protocol === 'https:';
33
+ } catch {
34
+ return false;
35
+ }
36
+ }
@@ -0,0 +1,54 @@
1
+ /**
2
+ * User Input Validators
3
+ * Validation utilities for user input (email, password, username, phone)
4
+ */
5
+
6
+ import { isValidString } from './string.validator';
7
+
8
+ /**
9
+ * Validate email format
10
+ */
11
+ export function isValidEmail(email: string): boolean {
12
+ if (!isValidString(email)) {
13
+ return false;
14
+ }
15
+ const emailPattern = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
16
+ return emailPattern.test(email.trim());
17
+ }
18
+
19
+ /**
20
+ * Validate password strength
21
+ * At least 8 characters, containing uppercase, lowercase, and number
22
+ */
23
+ export function isStrongPassword(password: string): boolean {
24
+ if (!isValidString(password) || password.length < 8) {
25
+ return false;
26
+ }
27
+ const hasUpperCase = /[A-Z]/.test(password);
28
+ const hasLowerCase = /[a-z]/.test(password);
29
+ const hasNumber = /[0-9]/.test(password);
30
+ return hasUpperCase && hasLowerCase && hasNumber;
31
+ }
32
+
33
+ /**
34
+ * Validate username format
35
+ * Alphanumeric, underscores, and hyphens, 3-20 characters
36
+ */
37
+ export function isValidUsername(username: string): boolean {
38
+ if (!isValidString(username)) {
39
+ return false;
40
+ }
41
+ const pattern = /^[a-zA-Z0-9_-]{3,20}$/;
42
+ return pattern.test(username);
43
+ }
44
+
45
+ /**
46
+ * Validate phone number format (basic check)
47
+ */
48
+ export function isValidPhoneNumber(phone: string): boolean {
49
+ if (!isValidString(phone)) {
50
+ return false;
51
+ }
52
+ const cleaned = phone.replace(/\s+/g, '').replace(/[-+()]/g, '');
53
+ return /^[0-9]{10,15}$/.test(cleaned);
54
+ }
@@ -43,8 +43,11 @@ export class QuotaTrackingMiddleware {
43
43
 
44
44
  /**
45
45
  * Track read operation
46
+ * @param _collection - Collection name (reserved for future per-collection tracking)
47
+ * @param count - Number of documents read
48
+ * @param cached - Whether result was from cache
46
49
  */
47
- trackRead(collection: string, count: number = 1, cached: boolean = false): void {
50
+ trackRead(_collection: string, count: number = 1, cached: boolean = false): void {
48
51
  if (!cached) {
49
52
  this.readCount += count;
50
53
  }
@@ -52,15 +55,19 @@ export class QuotaTrackingMiddleware {
52
55
 
53
56
  /**
54
57
  * Track write operation
58
+ * @param _collection - Collection name (reserved for future per-collection tracking)
59
+ * @param count - Number of documents written
55
60
  */
56
- trackWrite(collection: string, count: number = 1): void {
61
+ trackWrite(_collection: string, count: number = 1): void {
57
62
  this.writeCount += count;
58
63
  }
59
64
 
60
65
  /**
61
66
  * Track delete operation
67
+ * @param _collection - Collection name (reserved for future per-collection tracking)
68
+ * @param count - Number of documents deleted
62
69
  */
63
- trackDelete(collection: string, count: number = 1): void {
70
+ trackDelete(_collection: string, count: number = 1): void {
64
71
  this.deleteCount += count;
65
72
  }
66
73
 
@@ -31,8 +31,8 @@ export class TimerManager {
31
31
  this.options.onCleanup();
32
32
  } catch (error) {
33
33
  // Silently handle cleanup errors to prevent timer from causing issues
34
- // Log error in development for debugging
35
- if (process.env.NODE_ENV === 'development') {
34
+ // Log error in development for debugging (use __DEV__ for React Native)
35
+ if (__DEV__) {
36
36
  console.error('TimerManager cleanup error:', error);
37
37
  }
38
38
  }
@@ -33,7 +33,9 @@ export class PaginationHelper<T> {
33
33
  ): PaginatedResult<T> {
34
34
  const hasMore = items.length > pageLimit;
35
35
  const resultItems = hasMore ? items.slice(0, pageLimit) : items;
36
- const lastItem = resultItems[resultItems.length - 1];
36
+
37
+ // Safe access: check array is not empty before accessing last item
38
+ const lastItem = resultItems.length > 0 ? resultItems[resultItems.length - 1] : undefined;
37
39
  const nextCursor = hasMore && lastItem
38
40
  ? getCursor(lastItem)
39
41
  : null;
@@ -6,192 +6,31 @@
6
6
  *
7
7
  * IMPORTANT: This package does NOT read from .env files.
8
8
  * Configuration must be provided by the application.
9
- */
10
-
11
- import type { FirebaseConfig } from '../../domain/value-objects/FirebaseConfig';
12
- import type { IFirebaseClient } from '../../application/ports/IFirebaseClient';
13
- import type { FirebaseApp } from './initializers/FirebaseAppInitializer';
14
- import { FirebaseClientState } from './state/FirebaseClientState';
15
- import { FirebaseInitializationOrchestrator } from './orchestrators/FirebaseInitializationOrchestrator';
16
- import { loadFirebaseConfig } from './FirebaseConfigLoader';
17
-
18
- export type { FirebaseApp };
19
-
20
- /**
21
- * Auth initializer callback type
22
- */
23
- export type AuthInitializer = () => Promise<void> | ((() => (any | null) | null));
24
-
25
- /**
26
- * Service initialization options
27
- */
28
- export interface ServiceInitializationOptions {
29
- authInitializer?: AuthInitializer;
30
- }
31
-
32
- /**
33
- * Service initialization result interface
34
- */
35
- export interface ServiceInitializationResult {
36
- app: FirebaseApp | null;
37
- auth: boolean | null;
38
- authError?: string;
39
- }
40
-
41
- /**
42
- * Firebase Client Singleton
43
- * Orchestrates Firebase initialization using specialized initializers
44
- */
45
- class FirebaseClientSingleton implements IFirebaseClient {
46
- private static instance: FirebaseClientSingleton | null = null;
47
- private state: FirebaseClientState;
48
- private lastError: string | null = null;
49
-
50
- private constructor() {
51
- this.state = new FirebaseClientState();
52
- }
53
-
54
- static getInstance(): FirebaseClientSingleton {
55
- if (!FirebaseClientSingleton.instance) {
56
- FirebaseClientSingleton.instance = new FirebaseClientSingleton();
57
- }
58
- return FirebaseClientSingleton.instance;
59
- }
60
-
61
- initialize(config: FirebaseConfig): FirebaseApp | null {
62
- try {
63
- const result = FirebaseInitializationOrchestrator.initialize(config);
64
- // Sync state with orchestrator result
65
- this.state.setInstance(result);
66
- this.lastError = null;
67
- return result;
68
- } catch (error) {
69
- const errorMessage = error instanceof Error ? error.message : 'Unknown error';
70
- this.lastError = errorMessage;
71
- this.state.setInitializationError(errorMessage);
72
- return null;
73
- }
74
- }
75
-
76
- getApp(): FirebaseApp | null {
77
- // Check local state first
78
- const localApp = this.state.getApp();
79
- if (localApp) return localApp;
80
-
81
- // Try to get from orchestrator
82
- const result = FirebaseInitializationOrchestrator.autoInitialize();
83
- if (result) {
84
- this.state.setInstance(result);
85
- }
86
- return result;
87
- }
88
-
89
- isInitialized(): boolean {
90
- // Check both local state and orchestrator for consistency
91
- if (this.state.isInitialized()) return true;
92
-
93
- // Check if Firebase has any apps initialized
94
- return FirebaseInitializationOrchestrator.autoInitialize() !== null;
95
- }
96
-
97
- getInitializationError(): string | null {
98
- // Check local state first
99
- const localError = this.state.getInitializationError();
100
- if (localError) return localError;
101
- // Return last error
102
- return this.lastError;
103
- }
104
-
105
- reset(): void {
106
- // Reset local state
107
- this.state.reset();
108
- this.lastError = null;
109
- // Note: We don't reset Firebase apps as they might be in use
110
- }
111
- }
112
-
113
- export const firebaseClient = FirebaseClientSingleton.getInstance();
114
-
115
- /**
116
- * Initialize Firebase client with configuration
117
- */
118
- export function initializeFirebase(config: FirebaseConfig): FirebaseApp | null {
119
- return firebaseClient.initialize(config);
120
- }
121
-
122
- /**
123
- * Get Firebase app instance
124
- * Auto-initializes from Constants/environment if not already initialized
125
- */
126
- export function getFirebaseApp(): FirebaseApp | null {
127
- return firebaseClient.getApp();
128
- }
129
-
130
- /**
131
- * Auto-initialize Firebase from Constants/environment
132
- */
133
- export function autoInitializeFirebase(): FirebaseApp | null {
134
- const config = loadFirebaseConfig();
135
- if (config) {
136
- return initializeFirebase(config);
137
- }
138
- return null;
139
- }
140
-
141
- /**
142
- * Initialize all Firebase services (App and Auth)
143
- * This is the main entry point for applications
144
- */
145
- export async function initializeAllFirebaseServices(
146
- config?: FirebaseConfig,
147
- options?: ServiceInitializationOptions
148
- ): Promise<ServiceInitializationResult> {
149
- const app = config ? initializeFirebase(config) : autoInitializeFirebase();
150
-
151
- if (!app) {
152
- return {
153
- app: null,
154
- auth: null,
155
- };
156
- }
157
-
158
- // Initialize Auth if provided
159
- let authSuccess = null;
160
- let authError: string | undefined;
161
-
162
- if (options?.authInitializer) {
163
- try {
164
- await options.authInitializer();
165
- authSuccess = true;
166
- } catch (error) {
167
- authError = error instanceof Error ? error.message : 'Auth initialization failed';
168
- }
169
- }
170
-
171
- return {
172
- app,
173
- auth: authSuccess,
174
- authError,
175
- };
176
- }
177
-
178
- /**
179
- * Check if Firebase client is initialized
180
- */
181
- export function isFirebaseInitialized(): boolean {
182
- return firebaseClient.isInitialized();
183
- }
184
-
185
- /**
186
- * Get initialization error if any
187
- */
188
- export function getFirebaseInitializationError(): string | null {
189
- return firebaseClient.getInitializationError();
190
- }
191
-
192
- /**
193
- * Reset Firebase client instance
194
- */
195
- export function resetFirebaseClient(): void {
196
- firebaseClient.reset();
197
- }
9
+ *
10
+ * @deprecated Import from specific files instead:
11
+ * - FirebaseClientSingleton from './clients/FirebaseClientSingleton'
12
+ * - Initialization functions from './services/FirebaseInitializationService'
13
+ */
14
+
15
+ export type { FirebaseApp } from './initializers/FirebaseAppInitializer';
16
+
17
+ // Export singleton for backward compatibility
18
+ export { FirebaseClientSingleton } from './clients/FirebaseClientSingleton';
19
+ export const firebaseClient = require('./clients/FirebaseClientSingleton').FirebaseClientSingleton.getInstance();
20
+
21
+ // Re-export types and functions
22
+ export type {
23
+ AuthInitializer,
24
+ ServiceInitializationOptions,
25
+ ServiceInitializationResult,
26
+ } from './services/FirebaseInitializationService';
27
+
28
+ export {
29
+ initializeFirebase,
30
+ getFirebaseApp,
31
+ autoInitializeFirebase,
32
+ initializeAllFirebaseServices,
33
+ isFirebaseInitialized,
34
+ getFirebaseInitializationError,
35
+ resetFirebaseClient,
36
+ } from './services/FirebaseInitializationService';
@@ -0,0 +1,82 @@
1
+ /**
2
+ * Firebase Client Singleton
3
+ * Core singleton implementation for Firebase client
4
+ */
5
+
6
+ import type { FirebaseConfig } from '../../../domain/value-objects/FirebaseConfig';
7
+ import type { IFirebaseClient } from '../../../application/ports/IFirebaseClient';
8
+ import type { FirebaseApp } from '../initializers/FirebaseAppInitializer';
9
+ import { FirebaseClientState } from '../state/FirebaseClientState';
10
+ import { FirebaseInitializationOrchestrator } from '../orchestrators/FirebaseInitializationOrchestrator';
11
+
12
+ /**
13
+ * Firebase Client Singleton
14
+ * Orchestrates Firebase initialization using specialized initializers
15
+ */
16
+ export class FirebaseClientSingleton implements IFirebaseClient {
17
+ private static instance: FirebaseClientSingleton | null = null;
18
+ private state: FirebaseClientState;
19
+ private lastError: string | null = null;
20
+
21
+ private constructor() {
22
+ this.state = new FirebaseClientState();
23
+ }
24
+
25
+ static getInstance(): FirebaseClientSingleton {
26
+ if (!FirebaseClientSingleton.instance) {
27
+ FirebaseClientSingleton.instance = new FirebaseClientSingleton();
28
+ }
29
+ return FirebaseClientSingleton.instance;
30
+ }
31
+
32
+ initialize(config: FirebaseConfig): FirebaseApp | null {
33
+ try {
34
+ const result = FirebaseInitializationOrchestrator.initialize(config);
35
+ // Sync state with orchestrator result
36
+ this.state.setInstance(result);
37
+ this.lastError = null;
38
+ return result;
39
+ } catch (error) {
40
+ const errorMessage = error instanceof Error ? error.message : 'Unknown error';
41
+ this.lastError = errorMessage;
42
+ this.state.setInitializationError(errorMessage);
43
+ return null;
44
+ }
45
+ }
46
+
47
+ getApp(): FirebaseApp | null {
48
+ // Check local state first
49
+ const localApp = this.state.getApp();
50
+ if (localApp) return localApp;
51
+
52
+ // Try to get from orchestrator
53
+ const result = FirebaseInitializationOrchestrator.autoInitialize();
54
+ if (result) {
55
+ this.state.setInstance(result);
56
+ }
57
+ return result;
58
+ }
59
+
60
+ isInitialized(): boolean {
61
+ // Check both local state and orchestrator for consistency
62
+ if (this.state.isInitialized()) return true;
63
+
64
+ // Check if Firebase has any apps initialized
65
+ return FirebaseInitializationOrchestrator.autoInitialize() !== null;
66
+ }
67
+
68
+ getInitializationError(): string | null {
69
+ // Check local state first
70
+ const localError = this.state.getInitializationError();
71
+ if (localError) return localError;
72
+ // Return last error
73
+ return this.lastError;
74
+ }
75
+
76
+ reset(): void {
77
+ // Reset local state
78
+ this.state.reset();
79
+ this.lastError = null;
80
+ // Note: We don't reset Firebase apps as they might be in use
81
+ }
82
+ }
@@ -0,0 +1,115 @@
1
+ /**
2
+ * Firebase Initialization Service
3
+ * Service layer for Firebase initialization with auth support
4
+ */
5
+
6
+ import type { FirebaseConfig } from '../../../domain/value-objects/FirebaseConfig';
7
+ import type { FirebaseApp } from '../initializers/FirebaseAppInitializer';
8
+ import { FirebaseClientSingleton } from '../clients/FirebaseClientSingleton';
9
+ import { loadFirebaseConfig } from '../FirebaseConfigLoader';
10
+
11
+ /**
12
+ * Auth initializer callback type
13
+ * Returns a Promise that resolves when auth initialization is complete
14
+ */
15
+ export type AuthInitializer = () => Promise<void>;
16
+
17
+ /**
18
+ * Service initialization options
19
+ */
20
+ export interface ServiceInitializationOptions {
21
+ authInitializer?: AuthInitializer;
22
+ }
23
+
24
+ /**
25
+ * Service initialization result interface
26
+ */
27
+ export interface ServiceInitializationResult {
28
+ app: FirebaseApp | null;
29
+ auth: boolean | null;
30
+ authError?: string;
31
+ }
32
+
33
+ /**
34
+ * Initialize Firebase client with configuration
35
+ */
36
+ export function initializeFirebase(config: FirebaseConfig): FirebaseApp | null {
37
+ return FirebaseClientSingleton.getInstance().initialize(config);
38
+ }
39
+
40
+ /**
41
+ * Get Firebase app instance
42
+ * Auto-initializes from Constants/environment if not already initialized
43
+ */
44
+ export function getFirebaseApp(): FirebaseApp | null {
45
+ return FirebaseClientSingleton.getInstance().getApp();
46
+ }
47
+
48
+ /**
49
+ * Auto-initialize Firebase from Constants/environment
50
+ */
51
+ export function autoInitializeFirebase(): FirebaseApp | null {
52
+ const config = loadFirebaseConfig();
53
+ if (config) {
54
+ return initializeFirebase(config);
55
+ }
56
+ return null;
57
+ }
58
+
59
+ /**
60
+ * Initialize all Firebase services (App and Auth)
61
+ * This is the main entry point for applications
62
+ */
63
+ export async function initializeAllFirebaseServices(
64
+ config?: FirebaseConfig,
65
+ options?: ServiceInitializationOptions
66
+ ): Promise<ServiceInitializationResult> {
67
+ const app = config ? initializeFirebase(config) : autoInitializeFirebase();
68
+
69
+ if (!app) {
70
+ return {
71
+ app: null,
72
+ auth: null,
73
+ };
74
+ }
75
+
76
+ // Initialize Auth if provided
77
+ let authSuccess = null;
78
+ let authError: string | undefined;
79
+
80
+ if (options?.authInitializer) {
81
+ try {
82
+ await options.authInitializer();
83
+ authSuccess = true;
84
+ } catch (error) {
85
+ authError = error instanceof Error ? error.message : 'Auth initialization failed';
86
+ }
87
+ }
88
+
89
+ return {
90
+ app,
91
+ auth: authSuccess,
92
+ authError,
93
+ };
94
+ }
95
+
96
+ /**
97
+ * Check if Firebase client is initialized
98
+ */
99
+ export function isFirebaseInitialized(): boolean {
100
+ return FirebaseClientSingleton.getInstance().isInitialized();
101
+ }
102
+
103
+ /**
104
+ * Get initialization error if any
105
+ */
106
+ export function getFirebaseInitializationError(): string | null {
107
+ return FirebaseClientSingleton.getInstance().getInitializationError();
108
+ }
109
+
110
+ /**
111
+ * Reset Firebase client instance
112
+ */
113
+ export function resetFirebaseClient(): void {
114
+ FirebaseClientSingleton.getInstance().reset();
115
+ }