@umituz/react-native-firebase 1.4.0 → 1.5.1
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/LICENSE +0 -0
- package/README.md +0 -0
- package/lib/application/ports/IFirebaseClient.d.ts +37 -0
- package/lib/application/ports/IFirebaseClient.d.ts.map +1 -0
- package/lib/application/ports/IFirebaseClient.js +8 -0
- package/lib/application/ports/IFirebaseClient.js.map +1 -0
- package/lib/domain/errors/FirebaseError.d.ts +28 -0
- package/lib/domain/errors/FirebaseError.d.ts.map +1 -0
- package/lib/domain/errors/FirebaseError.js +46 -0
- package/lib/domain/errors/FirebaseError.js.map +1 -0
- package/lib/domain/value-objects/FirebaseConfig.d.ts +36 -0
- package/lib/domain/value-objects/FirebaseConfig.d.ts.map +1 -0
- package/lib/domain/value-objects/FirebaseConfig.js +8 -0
- package/lib/domain/value-objects/FirebaseConfig.js.map +1 -0
- package/lib/index.d.ts +26 -0
- package/lib/index.d.ts.map +1 -0
- package/lib/index.js +29 -0
- package/lib/index.js.map +1 -0
- package/lib/infrastructure/config/FirebaseClient.d.ts +145 -0
- package/lib/infrastructure/config/FirebaseClient.d.ts.map +1 -0
- package/lib/infrastructure/config/FirebaseClient.js +335 -0
- package/lib/infrastructure/config/FirebaseClient.js.map +1 -0
- package/lib/infrastructure/config/FirebaseConfigLoader.d.ts +16 -0
- package/lib/infrastructure/config/FirebaseConfigLoader.d.ts.map +1 -0
- package/lib/infrastructure/config/FirebaseConfigLoader.js +131 -0
- package/lib/infrastructure/config/FirebaseConfigLoader.js.map +1 -0
- package/lib/infrastructure/config/initializers/FirebaseAppInitializer.d.ts +17 -0
- package/lib/infrastructure/config/initializers/FirebaseAppInitializer.d.ts.map +1 -0
- package/lib/infrastructure/config/initializers/FirebaseAppInitializer.js +83 -0
- package/lib/infrastructure/config/initializers/FirebaseAppInitializer.js.map +1 -0
- package/lib/infrastructure/config/validators/FirebaseConfigValidator.d.ts +18 -0
- package/lib/infrastructure/config/validators/FirebaseConfigValidator.d.ts.map +1 -0
- package/lib/infrastructure/config/validators/FirebaseConfigValidator.js +62 -0
- package/lib/infrastructure/config/validators/FirebaseConfigValidator.js.map +1 -0
- package/package.json +19 -4
- package/src/application/ports/IFirebaseClient.ts +1 -1
- package/src/domain/errors/FirebaseError.ts +0 -0
- package/src/domain/value-objects/FirebaseConfig.ts +0 -0
- package/src/index.ts +0 -0
- package/src/infrastructure/config/FirebaseClient.ts +222 -92
- package/src/infrastructure/config/FirebaseConfigLoader.ts +140 -45
- package/src/infrastructure/config/initializers/FirebaseAppInitializer.ts +67 -27
- package/src/infrastructure/config/validators/FirebaseConfigValidator.ts +58 -25
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Firebase Configuration Validator
|
|
3
|
+
*
|
|
4
|
+
* Single Responsibility: Validates Firebase configuration
|
|
5
|
+
*/
|
|
6
|
+
import { FirebaseConfigurationError } from '../../../domain/errors/FirebaseError';
|
|
7
|
+
/**
|
|
8
|
+
* Required field validation rule
|
|
9
|
+
*/
|
|
10
|
+
class RequiredFieldRule {
|
|
11
|
+
constructor(fieldName, getter) {
|
|
12
|
+
this.fieldName = fieldName;
|
|
13
|
+
this.getter = getter;
|
|
14
|
+
}
|
|
15
|
+
validate(config) {
|
|
16
|
+
const value = this.getter(config);
|
|
17
|
+
if (!value || typeof value !== 'string') {
|
|
18
|
+
throw new FirebaseConfigurationError(`Firebase ${this.fieldName} is required and must be a string`);
|
|
19
|
+
}
|
|
20
|
+
if (value.trim().length === 0) {
|
|
21
|
+
throw new FirebaseConfigurationError(`Firebase ${this.fieldName} cannot be empty`);
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* Placeholder validation rule
|
|
27
|
+
*/
|
|
28
|
+
class PlaceholderRule {
|
|
29
|
+
constructor(fieldName, getter, placeholder) {
|
|
30
|
+
this.fieldName = fieldName;
|
|
31
|
+
this.getter = getter;
|
|
32
|
+
this.placeholder = placeholder;
|
|
33
|
+
}
|
|
34
|
+
validate(config) {
|
|
35
|
+
const value = this.getter(config);
|
|
36
|
+
if (value && value.includes(this.placeholder)) {
|
|
37
|
+
throw new FirebaseConfigurationError(`Please replace placeholder values with actual Firebase credentials for ${this.fieldName}`);
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
/**
|
|
42
|
+
* Firebase Configuration Validator
|
|
43
|
+
*/
|
|
44
|
+
export class FirebaseConfigValidator {
|
|
45
|
+
/**
|
|
46
|
+
* Validate Firebase configuration
|
|
47
|
+
* @throws {FirebaseConfigurationError} If configuration is invalid
|
|
48
|
+
*/
|
|
49
|
+
static validate(config) {
|
|
50
|
+
for (const rule of this.rules) {
|
|
51
|
+
rule.validate(config);
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
FirebaseConfigValidator.rules = [
|
|
56
|
+
new RequiredFieldRule('API Key', config => config.apiKey),
|
|
57
|
+
new RequiredFieldRule('Auth Domain', config => config.authDomain),
|
|
58
|
+
new RequiredFieldRule('Project ID', config => config.projectId),
|
|
59
|
+
new PlaceholderRule('API Key', config => config.apiKey, 'your_firebase_api_key'),
|
|
60
|
+
new PlaceholderRule('Project ID', config => config.projectId, 'your-project-id'),
|
|
61
|
+
];
|
|
62
|
+
//# sourceMappingURL=FirebaseConfigValidator.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"FirebaseConfigValidator.js","sourceRoot":"","sources":["../../../../src/infrastructure/config/validators/FirebaseConfigValidator.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAGH,OAAO,EAAE,0BAA0B,EAAE,MAAM,sCAAsC,CAAC;AASlF;;GAEG;AACH,MAAM,iBAAiB;IACrB,YACU,SAAiB,EACjB,MAAsD;QADtD,cAAS,GAAT,SAAS,CAAQ;QACjB,WAAM,GAAN,MAAM,CAAgD;IAC7D,CAAC;IAEJ,QAAQ,CAAC,MAAsB;QAC7B,MAAM,KAAK,GAAG,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC;QAElC,IAAI,CAAC,KAAK,IAAI,OAAO,KAAK,KAAK,QAAQ,EAAE,CAAC;YACxC,MAAM,IAAI,0BAA0B,CAClC,YAAY,IAAI,CAAC,SAAS,mCAAmC,CAC9D,CAAC;QACJ,CAAC;QAED,IAAI,KAAK,CAAC,IAAI,EAAE,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YAC9B,MAAM,IAAI,0BAA0B,CAAC,YAAY,IAAI,CAAC,SAAS,kBAAkB,CAAC,CAAC;QACrF,CAAC;IACH,CAAC;CACF;AAED;;GAEG;AACH,MAAM,eAAe;IACnB,YACU,SAAiB,EACjB,MAAsD,EACtD,WAAmB;QAFnB,cAAS,GAAT,SAAS,CAAQ;QACjB,WAAM,GAAN,MAAM,CAAgD;QACtD,gBAAW,GAAX,WAAW,CAAQ;IAC1B,CAAC;IAEJ,QAAQ,CAAC,MAAsB;QAC7B,MAAM,KAAK,GAAG,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC;QAElC,IAAI,KAAK,IAAI,KAAK,CAAC,QAAQ,CAAC,IAAI,CAAC,WAAW,CAAC,EAAE,CAAC;YAC9C,MAAM,IAAI,0BAA0B,CAClC,0EAA0E,IAAI,CAAC,SAAS,EAAE,CAC3F,CAAC;QACJ,CAAC;IACH,CAAC;CACF;AAED;;GAEG;AACH,MAAM,OAAO,uBAAuB;IASlC;;;OAGG;IACH,MAAM,CAAC,QAAQ,CAAC,MAAsB;QACpC,KAAK,MAAM,IAAI,IAAI,IAAI,CAAC,KAAK,EAAE,CAAC;YAC9B,IAAI,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC;QACxB,CAAC;IACH,CAAC;;AAhBc,6BAAK,GAAqB;IACvC,IAAI,iBAAiB,CAAC,SAAS,EAAE,MAAM,CAAC,EAAE,CAAC,MAAM,CAAC,MAAM,CAAC;IACzD,IAAI,iBAAiB,CAAC,aAAa,EAAE,MAAM,CAAC,EAAE,CAAC,MAAM,CAAC,UAAU,CAAC;IACjE,IAAI,iBAAiB,CAAC,YAAY,EAAE,MAAM,CAAC,EAAE,CAAC,MAAM,CAAC,SAAS,CAAC;IAC/D,IAAI,eAAe,CAAC,SAAS,EAAE,MAAM,CAAC,EAAE,CAAC,MAAM,CAAC,MAAM,EAAE,uBAAuB,CAAC;IAChF,IAAI,eAAe,CAAC,YAAY,EAAE,MAAM,CAAC,EAAE,CAAC,MAAM,CAAC,SAAS,EAAE,iBAAiB,CAAC;CACjF,CAAC"}
|
package/package.json
CHANGED
|
@@ -1,12 +1,17 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@umituz/react-native-firebase",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.5.1",
|
|
4
4
|
"description": "Firebase core package for React Native apps - Centralized initialization for all Firebase services (App, Auth, Analytics, Crashlytics). Use dedicated packages for service-specific operations.",
|
|
5
|
-
"main": "./
|
|
6
|
-
"types": "./
|
|
5
|
+
"main": "./lib/index.js",
|
|
6
|
+
"types": "./lib/index.d.ts",
|
|
7
7
|
"scripts": {
|
|
8
|
+
"build": "tsc",
|
|
8
9
|
"typecheck": "tsc --noEmit",
|
|
9
10
|
"lint": "tsc --noEmit",
|
|
11
|
+
"test": "jest",
|
|
12
|
+
"test:watch": "jest --watch",
|
|
13
|
+
"test:coverage": "jest --coverage",
|
|
14
|
+
"prepublishOnly": "npm run build",
|
|
10
15
|
"version:patch": "npm version patch -m 'chore: release v%s'",
|
|
11
16
|
"version:minor": "npm version minor -m 'chore: release v%s'",
|
|
12
17
|
"version:major": "npm version major -m 'chore: release v%s'"
|
|
@@ -31,17 +36,27 @@
|
|
|
31
36
|
"react-native": ">=0.74.0"
|
|
32
37
|
},
|
|
33
38
|
"devDependencies": {
|
|
39
|
+
"@types/jest": "^30.0.0",
|
|
40
|
+
"@types/node": "^25.0.1",
|
|
34
41
|
"@types/react": "^18.2.45",
|
|
35
42
|
"@types/react-native": "^0.73.0",
|
|
43
|
+
"chalk": "^4.1.2",
|
|
44
|
+
"find-up": "^8.0.0",
|
|
36
45
|
"firebase": "^11.0.0",
|
|
46
|
+
"jest": "^30.2.0",
|
|
47
|
+
"p-limit": "^7.2.0",
|
|
48
|
+
"p-try": "^3.0.0",
|
|
49
|
+
"path-exists": "^5.0.0",
|
|
37
50
|
"react": "^18.2.0",
|
|
38
51
|
"react-native": "^0.74.0",
|
|
39
|
-
"
|
|
52
|
+
"ts-jest": "^29.4.6",
|
|
53
|
+
"typescript": "^5.9.3"
|
|
40
54
|
},
|
|
41
55
|
"publishConfig": {
|
|
42
56
|
"access": "public"
|
|
43
57
|
},
|
|
44
58
|
"files": [
|
|
59
|
+
"lib",
|
|
45
60
|
"src",
|
|
46
61
|
"README.md",
|
|
47
62
|
"LICENSE"
|
|
File without changes
|
|
File without changes
|
package/src/index.ts
CHANGED
|
File without changes
|
|
@@ -13,104 +13,208 @@
|
|
|
13
13
|
* - Dependency Inversion: Depends on abstractions (interfaces), not concrete implementations
|
|
14
14
|
*/
|
|
15
15
|
|
|
16
|
-
import type { FirebaseApp } from 'firebase/app';
|
|
17
16
|
import type { FirebaseConfig } from '../../domain/value-objects/FirebaseConfig';
|
|
18
|
-
import { FirebaseInitializationError } from '../../domain/errors/FirebaseError';
|
|
19
17
|
import type { IFirebaseClient } from '../../application/ports/IFirebaseClient';
|
|
20
18
|
import { FirebaseConfigValidator } from './validators/FirebaseConfigValidator';
|
|
21
19
|
import { FirebaseAppInitializer } from './initializers/FirebaseAppInitializer';
|
|
22
20
|
import { loadFirebaseConfig } from './FirebaseConfigLoader';
|
|
23
21
|
|
|
22
|
+
export type FirebaseApp = any;
|
|
23
|
+
|
|
24
|
+
// Development environment check
|
|
25
|
+
declare const __DEV__: boolean;
|
|
26
|
+
|
|
24
27
|
/**
|
|
25
|
-
* Firebase Client
|
|
26
|
-
*
|
|
28
|
+
* Firebase Client State Manager
|
|
29
|
+
* Manages the state of Firebase initialization
|
|
27
30
|
*/
|
|
28
|
-
class
|
|
29
|
-
private static instance: FirebaseClientSingleton | null = null;
|
|
31
|
+
class FirebaseClientState {
|
|
30
32
|
private app: FirebaseApp | null = null;
|
|
31
33
|
private initializationError: string | null = null;
|
|
32
34
|
|
|
33
|
-
|
|
34
|
-
|
|
35
|
+
/**
|
|
36
|
+
* Get the current Firebase app instance
|
|
37
|
+
*/
|
|
38
|
+
getApp(): FirebaseApp | null {
|
|
39
|
+
return this.app;
|
|
35
40
|
}
|
|
36
41
|
|
|
37
42
|
/**
|
|
38
|
-
*
|
|
43
|
+
* Set the Firebase app instance
|
|
39
44
|
*/
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
FirebaseClientSingleton.instance = new FirebaseClientSingleton();
|
|
43
|
-
}
|
|
44
|
-
return FirebaseClientSingleton.instance;
|
|
45
|
+
setApp(app: FirebaseApp | null): void {
|
|
46
|
+
this.app = app;
|
|
45
47
|
}
|
|
46
48
|
|
|
47
49
|
/**
|
|
48
|
-
*
|
|
49
|
-
* Configuration must be provided by the application (not from .env)
|
|
50
|
-
*
|
|
51
|
-
* @param config - Firebase configuration
|
|
52
|
-
* @returns Firebase app instance or null if initialization fails
|
|
50
|
+
* Check if client is initialized
|
|
53
51
|
*/
|
|
54
|
-
|
|
52
|
+
isInitialized(): boolean {
|
|
53
|
+
return this.app !== null;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
/**
|
|
57
|
+
* Get initialization error if any
|
|
58
|
+
*/
|
|
59
|
+
getInitializationError(): string | null {
|
|
60
|
+
return this.initializationError;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
/**
|
|
64
|
+
* Set initialization error
|
|
65
|
+
*/
|
|
66
|
+
setInitializationError(error: string | null): void {
|
|
67
|
+
this.initializationError = error;
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
/**
|
|
71
|
+
* Reset the client state
|
|
72
|
+
*/
|
|
73
|
+
reset(): void {
|
|
74
|
+
this.app = null;
|
|
75
|
+
this.initializationError = null;
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
/**
|
|
80
|
+
* Firebase Initialization Orchestrator
|
|
81
|
+
* Handles the initialization logic
|
|
82
|
+
*/
|
|
83
|
+
class FirebaseInitializationOrchestrator {
|
|
84
|
+
/**
|
|
85
|
+
* Initialize Firebase with configuration
|
|
86
|
+
*/
|
|
87
|
+
static initialize(
|
|
88
|
+
config: FirebaseConfig,
|
|
89
|
+
state: FirebaseClientState
|
|
90
|
+
): FirebaseApp | null {
|
|
55
91
|
// Return existing instance if already initialized
|
|
56
|
-
if (
|
|
57
|
-
|
|
92
|
+
if (state.isInitialized()) {
|
|
93
|
+
if (__DEV__) {
|
|
94
|
+
console.log('[Firebase] Already initialized, returning existing instance');
|
|
95
|
+
}
|
|
96
|
+
return state.getApp();
|
|
58
97
|
}
|
|
59
98
|
|
|
60
99
|
// Don't retry if initialization already failed
|
|
61
|
-
if (
|
|
100
|
+
if (state.getInitializationError()) {
|
|
101
|
+
if (__DEV__) {
|
|
102
|
+
console.log('[Firebase] Previous initialization failed, skipping retry');
|
|
103
|
+
}
|
|
62
104
|
return null;
|
|
63
105
|
}
|
|
64
106
|
|
|
65
107
|
try {
|
|
108
|
+
if (__DEV__) {
|
|
109
|
+
console.log('[Firebase] Initializing with projectId:', config.projectId);
|
|
110
|
+
}
|
|
111
|
+
|
|
66
112
|
// Validate configuration
|
|
67
113
|
FirebaseConfigValidator.validate(config);
|
|
68
114
|
|
|
69
115
|
// Initialize Firebase App
|
|
70
|
-
|
|
116
|
+
const app = FirebaseAppInitializer.initialize(config);
|
|
117
|
+
state.setApp(app);
|
|
118
|
+
|
|
119
|
+
if (__DEV__) {
|
|
120
|
+
console.log('[Firebase] Successfully initialized');
|
|
121
|
+
}
|
|
71
122
|
|
|
72
|
-
return
|
|
123
|
+
return app;
|
|
73
124
|
} catch (error) {
|
|
74
|
-
|
|
125
|
+
const errorMessage =
|
|
75
126
|
error instanceof Error
|
|
76
127
|
? error.message
|
|
77
128
|
: 'Failed to initialize Firebase client';
|
|
129
|
+
state.setInitializationError(errorMessage);
|
|
130
|
+
|
|
131
|
+
if (__DEV__) {
|
|
132
|
+
console.error('[Firebase] Initialization failed:', errorMessage);
|
|
133
|
+
}
|
|
134
|
+
|
|
78
135
|
return null;
|
|
79
136
|
}
|
|
80
137
|
}
|
|
81
138
|
|
|
82
139
|
/**
|
|
83
|
-
*
|
|
84
|
-
* Auto-initializes from Constants/environment if not already initialized
|
|
85
|
-
* Returns null if config is not available (offline mode)
|
|
86
|
-
* @returns Firebase app instance or null if not initialized
|
|
140
|
+
* Auto-initialize Firebase from environment
|
|
87
141
|
*/
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
142
|
+
static autoInitialize(state: FirebaseClientState): FirebaseApp | null {
|
|
143
|
+
if (state.isInitialized() || state.getInitializationError()) {
|
|
144
|
+
return state.getApp();
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
const autoConfig = loadFirebaseConfig();
|
|
148
|
+
if (autoConfig) {
|
|
149
|
+
if (__DEV__) {
|
|
150
|
+
console.log('[Firebase] Auto-initializing with environment config');
|
|
94
151
|
}
|
|
152
|
+
return this.initialize(autoConfig, state);
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
if (__DEV__) {
|
|
156
|
+
console.log('[Firebase] No configuration found for auto-initialization');
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
return null;
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
/**
|
|
164
|
+
* Firebase Client Singleton
|
|
165
|
+
* Orchestrates Firebase initialization using specialized initializers
|
|
166
|
+
*/
|
|
167
|
+
class FirebaseClientSingleton implements IFirebaseClient {
|
|
168
|
+
private static instance: FirebaseClientSingleton | null = null;
|
|
169
|
+
private state: FirebaseClientState;
|
|
170
|
+
|
|
171
|
+
private constructor() {
|
|
172
|
+
this.state = new FirebaseClientState();
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
/**
|
|
176
|
+
* Get singleton instance
|
|
177
|
+
*/
|
|
178
|
+
static getInstance(): FirebaseClientSingleton {
|
|
179
|
+
if (!FirebaseClientSingleton.instance) {
|
|
180
|
+
FirebaseClientSingleton.instance = new FirebaseClientSingleton();
|
|
95
181
|
}
|
|
182
|
+
return FirebaseClientSingleton.instance;
|
|
183
|
+
}
|
|
96
184
|
|
|
97
|
-
|
|
98
|
-
|
|
185
|
+
/**
|
|
186
|
+
* Initialize Firebase client with configuration
|
|
187
|
+
* Configuration must be provided by the application (not from .env)
|
|
188
|
+
*
|
|
189
|
+
* @param config - Firebase configuration
|
|
190
|
+
* @returns Firebase app instance or null if initialization fails
|
|
191
|
+
*/
|
|
192
|
+
initialize(config: FirebaseConfig): FirebaseApp | null {
|
|
193
|
+
return FirebaseInitializationOrchestrator.initialize(config, this.state);
|
|
99
194
|
}
|
|
100
195
|
|
|
196
|
+
/**
|
|
197
|
+
* Get the Firebase app instance
|
|
198
|
+
* Auto-initializes from Constants/environment if not already initialized
|
|
199
|
+
* Returns null if config is not available (offline mode - no error)
|
|
200
|
+
* @returns Firebase app instance or null if not initialized
|
|
201
|
+
*/
|
|
202
|
+
getApp(): FirebaseApp | null {
|
|
203
|
+
return FirebaseInitializationOrchestrator.autoInitialize(this.state);
|
|
204
|
+
}
|
|
101
205
|
|
|
102
206
|
/**
|
|
103
207
|
* Check if client is initialized
|
|
104
208
|
*/
|
|
105
209
|
isInitialized(): boolean {
|
|
106
|
-
return this.
|
|
210
|
+
return this.state.isInitialized();
|
|
107
211
|
}
|
|
108
212
|
|
|
109
213
|
/**
|
|
110
214
|
* Get initialization error if any
|
|
111
215
|
*/
|
|
112
216
|
getInitializationError(): string | null {
|
|
113
|
-
return this.
|
|
217
|
+
return this.state.getInitializationError();
|
|
114
218
|
}
|
|
115
219
|
|
|
116
220
|
/**
|
|
@@ -118,8 +222,7 @@ class FirebaseClientSingleton implements IFirebaseClient {
|
|
|
118
222
|
* Useful for testing
|
|
119
223
|
*/
|
|
120
224
|
reset(): void {
|
|
121
|
-
this.
|
|
122
|
-
this.initializationError = null;
|
|
225
|
+
this.state.reset();
|
|
123
226
|
}
|
|
124
227
|
}
|
|
125
228
|
|
|
@@ -178,6 +281,79 @@ export function autoInitializeFirebase(): FirebaseApp | null {
|
|
|
178
281
|
return null;
|
|
179
282
|
}
|
|
180
283
|
|
|
284
|
+
/**
|
|
285
|
+
* Service initialization result interface
|
|
286
|
+
*/
|
|
287
|
+
interface ServiceInitializationResult {
|
|
288
|
+
app: FirebaseApp | null;
|
|
289
|
+
auth: any | null;
|
|
290
|
+
analytics: any | null;
|
|
291
|
+
crashlytics: any | null;
|
|
292
|
+
}
|
|
293
|
+
|
|
294
|
+
/**
|
|
295
|
+
* Service initializer class for better separation of concerns
|
|
296
|
+
*/
|
|
297
|
+
class ServiceInitializer {
|
|
298
|
+
/**
|
|
299
|
+
* Initialize optional Firebase service with error handling
|
|
300
|
+
*/
|
|
301
|
+
private static initializeService(
|
|
302
|
+
packageName: string,
|
|
303
|
+
initializerName: string,
|
|
304
|
+
isAsync = false
|
|
305
|
+
): any | null {
|
|
306
|
+
try {
|
|
307
|
+
const serviceModule = require(packageName);
|
|
308
|
+
const service = serviceModule[initializerName];
|
|
309
|
+
|
|
310
|
+
if (isAsync && typeof service.init === 'function') {
|
|
311
|
+
return service;
|
|
312
|
+
}
|
|
313
|
+
|
|
314
|
+
return typeof service === 'function' ? service() : service;
|
|
315
|
+
} catch {
|
|
316
|
+
return null;
|
|
317
|
+
}
|
|
318
|
+
}
|
|
319
|
+
|
|
320
|
+
/**
|
|
321
|
+
* Initialize all optional Firebase services
|
|
322
|
+
*/
|
|
323
|
+
static async initializeServices(): Promise<{
|
|
324
|
+
auth: any | null;
|
|
325
|
+
analytics: any | null;
|
|
326
|
+
crashlytics: any | null;
|
|
327
|
+
}> {
|
|
328
|
+
if (__DEV__) {
|
|
329
|
+
console.log('[Firebase] Initializing optional services...');
|
|
330
|
+
}
|
|
331
|
+
|
|
332
|
+
const auth = this.initializeService(
|
|
333
|
+
'@umituz/react-native-firebase-auth',
|
|
334
|
+
'initializeFirebaseAuth'
|
|
335
|
+
);
|
|
336
|
+
|
|
337
|
+
const analytics = this.initializeService(
|
|
338
|
+
'@umituz/react-native-firebase-analytics',
|
|
339
|
+
'firebaseAnalyticsService',
|
|
340
|
+
true
|
|
341
|
+
);
|
|
342
|
+
|
|
343
|
+
const crashlytics = this.initializeService(
|
|
344
|
+
'@umituz/react-native-firebase-crashlytics',
|
|
345
|
+
'firebaseCrashlyticsService',
|
|
346
|
+
true
|
|
347
|
+
);
|
|
348
|
+
|
|
349
|
+
if (__DEV__) {
|
|
350
|
+
console.log('[Firebase] Services initialized - Auth:', !!auth, 'Analytics:', !!analytics, 'Crashlytics:', !!crashlytics);
|
|
351
|
+
}
|
|
352
|
+
|
|
353
|
+
return { auth, analytics, crashlytics };
|
|
354
|
+
}
|
|
355
|
+
}
|
|
356
|
+
|
|
181
357
|
/**
|
|
182
358
|
* Initialize all Firebase services (App, Auth, Analytics, Crashlytics)
|
|
183
359
|
* This is the main entry point for applications - call this once at app startup
|
|
@@ -203,22 +379,10 @@ export function autoInitializeFirebase(): FirebaseApp | null {
|
|
|
203
379
|
*/
|
|
204
380
|
export async function initializeAllFirebaseServices(
|
|
205
381
|
config?: FirebaseConfig
|
|
206
|
-
): Promise<{
|
|
207
|
-
app
|
|
208
|
-
auth: any | null;
|
|
209
|
-
analytics: any | null;
|
|
210
|
-
crashlytics: any | null;
|
|
211
|
-
}> {
|
|
212
|
-
// 1. Initialize Firebase App
|
|
213
|
-
let app: FirebaseApp | null = null;
|
|
214
|
-
if (config) {
|
|
215
|
-
app = initializeFirebase(config);
|
|
216
|
-
} else {
|
|
217
|
-
app = autoInitializeFirebase();
|
|
218
|
-
}
|
|
382
|
+
): Promise<ServiceInitializationResult> {
|
|
383
|
+
const app = config ? initializeFirebase(config) : autoInitializeFirebase();
|
|
219
384
|
|
|
220
385
|
if (!app) {
|
|
221
|
-
// Firebase App not available - return null for all services
|
|
222
386
|
return {
|
|
223
387
|
app: null,
|
|
224
388
|
auth: null,
|
|
@@ -227,37 +391,7 @@ export async function initializeAllFirebaseServices(
|
|
|
227
391
|
};
|
|
228
392
|
}
|
|
229
393
|
|
|
230
|
-
|
|
231
|
-
let auth: any | null = null;
|
|
232
|
-
try {
|
|
233
|
-
// eslint-disable-next-line @typescript-eslint/no-require-imports
|
|
234
|
-
const { initializeFirebaseAuth } = require('@umituz/react-native-firebase-auth');
|
|
235
|
-
auth = initializeFirebaseAuth();
|
|
236
|
-
} catch {
|
|
237
|
-
// @umituz/react-native-firebase-auth not available
|
|
238
|
-
}
|
|
239
|
-
|
|
240
|
-
// 3. Initialize Firebase Analytics (if package is available)
|
|
241
|
-
let analytics: any | null = null;
|
|
242
|
-
try {
|
|
243
|
-
// eslint-disable-next-line @typescript-eslint/no-require-imports
|
|
244
|
-
const { firebaseAnalyticsService } = require('@umituz/react-native-firebase-analytics');
|
|
245
|
-
await firebaseAnalyticsService.init();
|
|
246
|
-
analytics = firebaseAnalyticsService;
|
|
247
|
-
} catch {
|
|
248
|
-
// @umituz/react-native-firebase-analytics not available
|
|
249
|
-
}
|
|
250
|
-
|
|
251
|
-
// 4. Initialize Firebase Crashlytics (if package is available)
|
|
252
|
-
let crashlytics: any | null = null;
|
|
253
|
-
try {
|
|
254
|
-
// eslint-disable-next-line @typescript-eslint/no-require-imports
|
|
255
|
-
const { firebaseCrashlyticsService } = require('@umituz/react-native-firebase-crashlytics');
|
|
256
|
-
await firebaseCrashlyticsService.init();
|
|
257
|
-
crashlytics = firebaseCrashlyticsService;
|
|
258
|
-
} catch {
|
|
259
|
-
// @umituz/react-native-firebase-crashlytics not available
|
|
260
|
-
}
|
|
394
|
+
const { auth, analytics, crashlytics } = await ServiceInitializer.initializeServices();
|
|
261
395
|
|
|
262
396
|
return {
|
|
263
397
|
app,
|
|
@@ -287,8 +421,4 @@ export function getFirebaseInitializationError(): string | null {
|
|
|
287
421
|
*/
|
|
288
422
|
export function resetFirebaseClient(): void {
|
|
289
423
|
firebaseClient.reset();
|
|
290
|
-
}
|
|
291
|
-
|
|
292
|
-
// Export types
|
|
293
|
-
export type { FirebaseApp } from 'firebase/app';
|
|
294
|
-
export type { FirebaseConfig } from '../../domain/value-objects/FirebaseConfig';
|
|
424
|
+
}
|