@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.
Files changed (43) hide show
  1. package/LICENSE +0 -0
  2. package/README.md +0 -0
  3. package/lib/application/ports/IFirebaseClient.d.ts +37 -0
  4. package/lib/application/ports/IFirebaseClient.d.ts.map +1 -0
  5. package/lib/application/ports/IFirebaseClient.js +8 -0
  6. package/lib/application/ports/IFirebaseClient.js.map +1 -0
  7. package/lib/domain/errors/FirebaseError.d.ts +28 -0
  8. package/lib/domain/errors/FirebaseError.d.ts.map +1 -0
  9. package/lib/domain/errors/FirebaseError.js +46 -0
  10. package/lib/domain/errors/FirebaseError.js.map +1 -0
  11. package/lib/domain/value-objects/FirebaseConfig.d.ts +36 -0
  12. package/lib/domain/value-objects/FirebaseConfig.d.ts.map +1 -0
  13. package/lib/domain/value-objects/FirebaseConfig.js +8 -0
  14. package/lib/domain/value-objects/FirebaseConfig.js.map +1 -0
  15. package/lib/index.d.ts +26 -0
  16. package/lib/index.d.ts.map +1 -0
  17. package/lib/index.js +29 -0
  18. package/lib/index.js.map +1 -0
  19. package/lib/infrastructure/config/FirebaseClient.d.ts +145 -0
  20. package/lib/infrastructure/config/FirebaseClient.d.ts.map +1 -0
  21. package/lib/infrastructure/config/FirebaseClient.js +335 -0
  22. package/lib/infrastructure/config/FirebaseClient.js.map +1 -0
  23. package/lib/infrastructure/config/FirebaseConfigLoader.d.ts +16 -0
  24. package/lib/infrastructure/config/FirebaseConfigLoader.d.ts.map +1 -0
  25. package/lib/infrastructure/config/FirebaseConfigLoader.js +131 -0
  26. package/lib/infrastructure/config/FirebaseConfigLoader.js.map +1 -0
  27. package/lib/infrastructure/config/initializers/FirebaseAppInitializer.d.ts +17 -0
  28. package/lib/infrastructure/config/initializers/FirebaseAppInitializer.d.ts.map +1 -0
  29. package/lib/infrastructure/config/initializers/FirebaseAppInitializer.js +83 -0
  30. package/lib/infrastructure/config/initializers/FirebaseAppInitializer.js.map +1 -0
  31. package/lib/infrastructure/config/validators/FirebaseConfigValidator.d.ts +18 -0
  32. package/lib/infrastructure/config/validators/FirebaseConfigValidator.d.ts.map +1 -0
  33. package/lib/infrastructure/config/validators/FirebaseConfigValidator.js +62 -0
  34. package/lib/infrastructure/config/validators/FirebaseConfigValidator.js.map +1 -0
  35. package/package.json +19 -4
  36. package/src/application/ports/IFirebaseClient.ts +1 -1
  37. package/src/domain/errors/FirebaseError.ts +0 -0
  38. package/src/domain/value-objects/FirebaseConfig.ts +0 -0
  39. package/src/index.ts +0 -0
  40. package/src/infrastructure/config/FirebaseClient.ts +222 -92
  41. package/src/infrastructure/config/FirebaseConfigLoader.ts +140 -45
  42. package/src/infrastructure/config/initializers/FirebaseAppInitializer.ts +67 -27
  43. package/src/infrastructure/config/validators/FirebaseConfigValidator.ts +58 -25
@@ -10,56 +10,151 @@
10
10
 
11
11
  import type { FirebaseConfig } from '../../domain/value-objects/FirebaseConfig';
12
12
 
13
+ /**
14
+ * Configuration source interface
15
+ */
16
+ interface ConfigSource {
17
+ getApiKey(): string;
18
+ getAuthDomain(): string;
19
+ getProjectId(): string;
20
+ getStorageBucket(): string;
21
+ getMessagingSenderId(): string;
22
+ getAppId(): string;
23
+ }
24
+
25
+ /**
26
+ * Expo Constants configuration source
27
+ */
28
+ class ExpoConfigSource implements ConfigSource {
29
+ private extra: any;
30
+
31
+ constructor() {
32
+ let Constants: any;
33
+
34
+ try {
35
+ Constants = require('expo-constants');
36
+ } catch {
37
+ // expo-constants not available
38
+ }
39
+
40
+ const expoConfig = Constants?.expoConfig || Constants?.default?.expoConfig;
41
+ this.extra = expoConfig?.extra || {};
42
+ }
43
+
44
+ getApiKey(): string {
45
+ return this.extra?.firebaseApiKey || '';
46
+ }
47
+
48
+ getAuthDomain(): string {
49
+ return this.extra?.firebaseAuthDomain || '';
50
+ }
51
+
52
+ getProjectId(): string {
53
+ return this.extra?.firebaseProjectId || '';
54
+ }
55
+
56
+ getStorageBucket(): string {
57
+ return this.extra?.firebaseStorageBucket || '';
58
+ }
59
+
60
+ getMessagingSenderId(): string {
61
+ return this.extra?.firebaseMessagingSenderId || '';
62
+ }
63
+
64
+ getAppId(): string {
65
+ return this.extra?.firebaseAppId || '';
66
+ }
67
+ }
68
+
69
+ /**
70
+ * Environment variables configuration source
71
+ */
72
+ class EnvironmentConfigSource implements ConfigSource {
73
+ getApiKey(): string {
74
+ return process.env.EXPO_PUBLIC_FIREBASE_API_KEY ||
75
+ process.env.FIREBASE_API_KEY ||
76
+ '';
77
+ }
78
+
79
+ getAuthDomain(): string {
80
+ return process.env.EXPO_PUBLIC_FIREBASE_AUTH_DOMAIN ||
81
+ process.env.FIREBASE_AUTH_DOMAIN ||
82
+ '';
83
+ }
84
+
85
+ getProjectId(): string {
86
+ return process.env.EXPO_PUBLIC_FIREBASE_PROJECT_ID ||
87
+ process.env.FIREBASE_PROJECT_ID ||
88
+ '';
89
+ }
90
+
91
+ getStorageBucket(): string {
92
+ return process.env.EXPO_PUBLIC_FIREBASE_STORAGE_BUCKET ||
93
+ process.env.FIREBASE_STORAGE_BUCKET ||
94
+ '';
95
+ }
96
+
97
+ getMessagingSenderId(): string {
98
+ return process.env.EXPO_PUBLIC_FIREBASE_MESSAGING_SENDER_ID ||
99
+ process.env.FIREBASE_MESSAGING_SENDER_ID ||
100
+ '';
101
+ }
102
+
103
+ getAppId(): string {
104
+ return process.env.EXPO_PUBLIC_FIREBASE_APP_ID ||
105
+ process.env.FIREBASE_APP_ID ||
106
+ '';
107
+ }
108
+ }
109
+
110
+ /**
111
+ * Configuration aggregator
112
+ */
113
+ class ConfigAggregator {
114
+ private sources: ConfigSource[];
115
+
116
+ constructor() {
117
+ this.sources = [
118
+ new ExpoConfigSource(),
119
+ new EnvironmentConfigSource(),
120
+ ];
121
+ }
122
+
123
+ /**
124
+ * Get configuration value from first available source
125
+ */
126
+ private getValue(getter: (source: ConfigSource) => string): string {
127
+ for (const source of this.sources) {
128
+ const value = getter(source);
129
+ if (value && value.trim() !== '') {
130
+ return value;
131
+ }
132
+ }
133
+ return '';
134
+ }
135
+
136
+ /**
137
+ * Build Firebase configuration from all sources
138
+ */
139
+ buildConfig(): Partial<FirebaseConfig> {
140
+ return {
141
+ apiKey: this.getValue(source => source.getApiKey()),
142
+ authDomain: this.getValue(source => source.getAuthDomain()),
143
+ projectId: this.getValue(source => source.getProjectId()),
144
+ storageBucket: this.getValue(source => source.getStorageBucket()),
145
+ messagingSenderId: this.getValue(source => source.getMessagingSenderId()),
146
+ appId: this.getValue(source => source.getAppId()),
147
+ };
148
+ }
149
+ }
150
+
13
151
  /**
14
152
  * Load Firebase configuration from Constants and environment variables
15
153
  * Returns null if no valid configuration is found
16
154
  */
17
155
  export function loadFirebaseConfig(): FirebaseConfig | null {
18
- let Constants: any;
19
-
20
- // Try to load expo-constants (optional dependency)
21
- try {
22
- Constants = require('expo-constants');
23
- } catch {
24
- // expo-constants not available, skip
25
- }
26
-
27
- // Try both Constants.expoConfig and Constants.default.expoConfig
28
- const expoConfig = Constants?.expoConfig || Constants?.default?.expoConfig;
29
- const extra = expoConfig?.extra;
30
-
31
- const config: Partial<FirebaseConfig> = {
32
- apiKey:
33
- extra?.firebaseApiKey ||
34
- process.env.EXPO_PUBLIC_FIREBASE_API_KEY ||
35
- process.env.FIREBASE_API_KEY ||
36
- '',
37
- authDomain:
38
- extra?.firebaseAuthDomain ||
39
- process.env.EXPO_PUBLIC_FIREBASE_AUTH_DOMAIN ||
40
- process.env.FIREBASE_AUTH_DOMAIN ||
41
- '',
42
- projectId:
43
- extra?.firebaseProjectId ||
44
- process.env.EXPO_PUBLIC_FIREBASE_PROJECT_ID ||
45
- process.env.FIREBASE_PROJECT_ID ||
46
- '',
47
- storageBucket:
48
- extra?.firebaseStorageBucket ||
49
- process.env.EXPO_PUBLIC_FIREBASE_STORAGE_BUCKET ||
50
- process.env.FIREBASE_STORAGE_BUCKET ||
51
- '',
52
- messagingSenderId:
53
- extra?.firebaseMessagingSenderId ||
54
- process.env.EXPO_PUBLIC_FIREBASE_MESSAGING_SENDER_ID ||
55
- process.env.FIREBASE_MESSAGING_SENDER_ID ||
56
- '',
57
- appId:
58
- extra?.firebaseAppId ||
59
- process.env.EXPO_PUBLIC_FIREBASE_APP_ID ||
60
- process.env.FIREBASE_APP_ID ||
61
- '',
62
- };
156
+ const aggregator = new ConfigAggregator();
157
+ const config = aggregator.buildConfig();
63
158
 
64
159
  // Only return config if required fields are present and not empty
65
160
  if (
@@ -4,34 +4,67 @@
4
4
  * Single Responsibility: Initialize Firebase App instance
5
5
  */
6
6
 
7
- import { initializeApp, getApps, FirebaseApp } from 'firebase/app';
8
7
  import type { FirebaseConfig } from '../../../domain/value-objects/FirebaseConfig';
9
8
  import { FirebaseInitializationError } from '../../../domain/errors/FirebaseError';
10
9
 
10
+ export type FirebaseApp = any;
11
+
12
+ declare const initializeApp: any;
13
+ declare const getApps: any;
14
+
11
15
  /**
12
- * Initializes Firebase App
16
+ * Firebase configuration mapper
13
17
  */
14
- export class FirebaseAppInitializer {
18
+ class FirebaseConfigMapper {
15
19
  /**
16
- * Initialize or get existing Firebase App
20
+ * Map domain config to Firebase SDK config
17
21
  */
18
- static initialize(config: FirebaseConfig): FirebaseApp {
19
- // Return existing app if already initialized
20
- const existingApps = getApps();
21
- if (existingApps.length > 0) {
22
- return existingApps[0];
22
+ static toFirebaseConfig(config: FirebaseConfig): Record<string, any> {
23
+ return {
24
+ apiKey: config.apiKey,
25
+ authDomain: config.authDomain,
26
+ projectId: config.projectId,
27
+ storageBucket: config.storageBucket,
28
+ messagingSenderId: config.messagingSenderId,
29
+ appId: config.appId,
30
+ };
31
+ }
32
+ }
33
+
34
+ /**
35
+ * Firebase App manager
36
+ */
37
+ class FirebaseAppManager {
38
+ /**
39
+ * Check if Firebase App is already initialized
40
+ */
41
+ static isInitialized(): boolean {
42
+ try {
43
+ const existingApps = getApps();
44
+ return existingApps.length > 0;
45
+ } catch {
46
+ return false;
23
47
  }
48
+ }
24
49
 
50
+ /**
51
+ * Get existing Firebase App instance
52
+ */
53
+ static getExistingApp(): FirebaseApp | null {
25
54
  try {
26
- const firebaseConfig = {
27
- apiKey: config.apiKey,
28
- authDomain: config.authDomain,
29
- projectId: config.projectId,
30
- storageBucket: config.storageBucket,
31
- messagingSenderId: config.messagingSenderId,
32
- appId: config.appId,
33
- };
55
+ const existingApps = getApps();
56
+ return existingApps.length > 0 ? existingApps[0] : null;
57
+ } catch {
58
+ return null;
59
+ }
60
+ }
34
61
 
62
+ /**
63
+ * Create new Firebase App instance
64
+ */
65
+ static createApp(config: FirebaseConfig): FirebaseApp {
66
+ try {
67
+ const firebaseConfig = FirebaseConfigMapper.toFirebaseConfig(config);
35
68
  return initializeApp(firebaseConfig);
36
69
  } catch (error) {
37
70
  throw new FirebaseInitializationError(
@@ -44,14 +77,21 @@ export class FirebaseAppInitializer {
44
77
  }
45
78
  }
46
79
 
80
+ /**
81
+ * Initializes Firebase App
82
+ */
83
+ export class FirebaseAppInitializer {
84
+ /**
85
+ * Initialize or get existing Firebase App
86
+ */
87
+ static initialize(config: FirebaseConfig): FirebaseApp {
88
+ // Return existing app if already initialized
89
+ const existingApp = FirebaseAppManager.getExistingApp();
90
+ if (existingApp) {
91
+ return existingApp;
92
+ }
47
93
 
48
-
49
-
50
-
51
-
52
-
53
-
54
-
55
-
56
-
57
-
94
+ // Create new app
95
+ return FirebaseAppManager.createApp(config);
96
+ }
97
+ }
@@ -8,43 +8,76 @@ import type { FirebaseConfig } from '../../../domain/value-objects/FirebaseConfi
8
8
  import { FirebaseConfigurationError } from '../../../domain/errors/FirebaseError';
9
9
 
10
10
  /**
11
- * Validates Firebase configuration
11
+ * Validation rule interface
12
12
  */
13
- export class FirebaseConfigValidator {
14
- /**
15
- * Validate Firebase configuration
16
- * @throws {FirebaseConfigurationError} If configuration is invalid
17
- */
18
- static validate(config: FirebaseConfig): void {
19
- if (!config.apiKey || typeof config.apiKey !== 'string') {
13
+ interface ValidationRule {
14
+ validate(config: FirebaseConfig): void;
15
+ }
16
+
17
+ /**
18
+ * Required field validation rule
19
+ */
20
+ class RequiredFieldRule implements ValidationRule {
21
+ constructor(
22
+ private fieldName: string,
23
+ private getter: (config: FirebaseConfig) => string | undefined
24
+ ) {}
25
+
26
+ validate(config: FirebaseConfig): void {
27
+ const value = this.getter(config);
28
+
29
+ if (!value || typeof value !== 'string') {
20
30
  throw new FirebaseConfigurationError(
21
- 'Firebase API Key is required and must be a string'
31
+ `Firebase ${this.fieldName} is required and must be a string`
22
32
  );
23
33
  }
24
34
 
25
- if (!config.authDomain || typeof config.authDomain !== 'string') {
26
- throw new FirebaseConfigurationError(
27
- 'Firebase Auth Domain is required and must be a string'
28
- );
35
+ if (value.trim().length === 0) {
36
+ throw new FirebaseConfigurationError(`Firebase ${this.fieldName} cannot be empty`);
29
37
  }
38
+ }
39
+ }
30
40
 
31
- if (!config.projectId || typeof config.projectId !== 'string') {
41
+ /**
42
+ * Placeholder validation rule
43
+ */
44
+ class PlaceholderRule implements ValidationRule {
45
+ constructor(
46
+ private fieldName: string,
47
+ private getter: (config: FirebaseConfig) => string | undefined,
48
+ private placeholder: string
49
+ ) {}
50
+
51
+ validate(config: FirebaseConfig): void {
52
+ const value = this.getter(config);
53
+
54
+ if (value && value.includes(this.placeholder)) {
32
55
  throw new FirebaseConfigurationError(
33
- 'Firebase Project ID is required and must be a string'
56
+ `Please replace placeholder values with actual Firebase credentials for ${this.fieldName}`
34
57
  );
35
58
  }
59
+ }
60
+ }
36
61
 
37
- if (config.apiKey.trim().length === 0) {
38
- throw new FirebaseConfigurationError('Firebase API Key cannot be empty');
39
- }
62
+ /**
63
+ * Firebase Configuration Validator
64
+ */
65
+ export class FirebaseConfigValidator {
66
+ private static rules: ValidationRule[] = [
67
+ new RequiredFieldRule('API Key', config => config.apiKey),
68
+ new RequiredFieldRule('Auth Domain', config => config.authDomain),
69
+ new RequiredFieldRule('Project ID', config => config.projectId),
70
+ new PlaceholderRule('API Key', config => config.apiKey, 'your_firebase_api_key'),
71
+ new PlaceholderRule('Project ID', config => config.projectId, 'your-project-id'),
72
+ ];
40
73
 
41
- if (
42
- config.apiKey.includes('your_firebase_api_key') ||
43
- config.projectId.includes('your-project-id')
44
- ) {
45
- throw new FirebaseConfigurationError(
46
- 'Please replace placeholder values with actual Firebase credentials'
47
- );
74
+ /**
75
+ * Validate Firebase configuration
76
+ * @throws {FirebaseConfigurationError} If configuration is invalid
77
+ */
78
+ static validate(config: FirebaseConfig): void {
79
+ for (const rule of this.rules) {
80
+ rule.validate(config);
48
81
  }
49
82
  }
50
83
  }