@umituz/react-native-firebase 1.7.0 → 1.7.3
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 +9 -4
- package/src/analytics/application/ports/IAnalyticsService.ts +92 -0
- package/src/analytics/index.ts +19 -0
- package/src/analytics/infrastructure/adapters/index.ts +10 -0
- package/src/analytics/infrastructure/adapters/native-analytics.adapter.ts +91 -0
- package/src/analytics/infrastructure/adapters/web-analytics.adapter.ts +63 -0
- package/src/analytics/infrastructure/services/FirebaseAnalyticsService.ts +187 -0
- package/src/analytics/infrastructure/services/PerformanceTracker.ts +49 -0
- package/src/analytics/infrastructure/services/analytics-event.service.ts +72 -0
- package/src/analytics/infrastructure/services/analytics-initializer.service.ts +162 -0
- package/src/analytics/infrastructure/services/analytics-user.service.ts +98 -0
- package/src/analytics/infrastructure/services/index.ts +12 -0
- package/src/analytics/presentation/decorators/PerformanceDecorator.ts +72 -0
- package/src/analytics/presentation/decorators/TrackingDecorator.ts +38 -0
- package/src/analytics/presentation/hooks/useNavigationTracking.ts +70 -0
- package/src/analytics/presentation/hooks/useScreenTime.ts +69 -0
- package/src/analytics/presentation/hooks/useScreenView.ts +70 -0
- package/src/analytics/presentation/utils/analyticsUtils.ts +78 -0
- package/src/crashlytics/index.ts +9 -0
- package/src/crashlytics/infrastructure/adapters/index.ts +8 -0
- package/src/crashlytics/infrastructure/adapters/native-crashlytics.adapter.ts +125 -0
- package/src/crashlytics/infrastructure/services/FirebaseCrashlyticsService.ts +99 -0
- package/src/crashlytics/infrastructure/services/crashlytics-error.service.ts +67 -0
- package/src/crashlytics/infrastructure/services/crashlytics-initializer.service.ts +31 -0
- package/src/crashlytics/infrastructure/services/crashlytics-user.service.ts +91 -0
- package/src/crashlytics/infrastructure/services/index.ts +11 -0
- package/src/domain/errors/FirebaseError.ts +20 -38
- package/src/domain/value-objects/FirebaseConfig.ts +10 -40
- package/src/index.ts +18 -22
- package/src/infrastructure/config/FirebaseClient.ts +11 -2
- package/README.md +0 -221
|
@@ -0,0 +1,125 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Native Crashlytics Adapter
|
|
3
|
+
* Single Responsibility: Handle Firebase Crashlytics native implementation
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
export interface CrashlyticsInstance {
|
|
7
|
+
setUserId(userId: string): Promise<void>;
|
|
8
|
+
setAttributes(attributes: Record<string, string>): Promise<void>;
|
|
9
|
+
recordError(error: Error): Promise<void>;
|
|
10
|
+
log(message: string): Promise<void>;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
export interface NativeCrashlyticsAdapter {
|
|
14
|
+
getCrashlytics(): CrashlyticsInstance;
|
|
15
|
+
setUserId(crashlytics: CrashlyticsInstance, userId: string): Promise<void>;
|
|
16
|
+
setAttributes(crashlytics: CrashlyticsInstance, attributes: Record<string, string>): Promise<void>;
|
|
17
|
+
recordError(crashlytics: CrashlyticsInstance, error: Error): Promise<void>;
|
|
18
|
+
log(crashlytics: CrashlyticsInstance, message: string): Promise<void>;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
interface NativeCrashlyticsModuleFunction {
|
|
22
|
+
(): CrashlyticsInstance;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
interface NativeCrashlyticsModuleObject {
|
|
26
|
+
default: () => CrashlyticsInstance;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
type NativeCrashlyticsModule = NativeCrashlyticsModuleFunction | NativeCrashlyticsModuleObject;
|
|
30
|
+
|
|
31
|
+
let nativeCrashlyticsModule: NativeCrashlyticsModule | null = null;
|
|
32
|
+
let isModuleLoaded = false;
|
|
33
|
+
|
|
34
|
+
function loadCrashlyticsModule(): void {
|
|
35
|
+
if (isModuleLoaded) return;
|
|
36
|
+
|
|
37
|
+
try {
|
|
38
|
+
// eslint-disable-next-line @typescript-eslint/no-require-imports
|
|
39
|
+
require('@react-native-firebase/app');
|
|
40
|
+
// eslint-disable-next-line @typescript-eslint/no-require-imports
|
|
41
|
+
const crashlytics = require('@react-native-firebase/crashlytics');
|
|
42
|
+
nativeCrashlyticsModule = crashlytics;
|
|
43
|
+
} catch {
|
|
44
|
+
// @react-native-firebase/crashlytics not available
|
|
45
|
+
} finally {
|
|
46
|
+
isModuleLoaded = true;
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
function getCrashlyticsInstance(): CrashlyticsInstance | null {
|
|
51
|
+
if (!isModuleLoaded) {
|
|
52
|
+
loadCrashlyticsModule();
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
if (!nativeCrashlyticsModule) return null;
|
|
56
|
+
|
|
57
|
+
try {
|
|
58
|
+
if (typeof nativeCrashlyticsModule === 'function') {
|
|
59
|
+
return nativeCrashlyticsModule();
|
|
60
|
+
}
|
|
61
|
+
if ('default' in nativeCrashlyticsModule && typeof nativeCrashlyticsModule.default === 'function') {
|
|
62
|
+
return nativeCrashlyticsModule.default();
|
|
63
|
+
}
|
|
64
|
+
} catch (error) {
|
|
65
|
+
/* eslint-disable-next-line no-console */
|
|
66
|
+
if (__DEV__) {
|
|
67
|
+
console.warn('[Crashlytics] Failed to get instance:', error);
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
return null;
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
export const nativeCrashlyticsAdapter: NativeCrashlyticsAdapter | null = {
|
|
75
|
+
getCrashlytics(): CrashlyticsInstance {
|
|
76
|
+
const instance = getCrashlyticsInstance();
|
|
77
|
+
if (!instance) {
|
|
78
|
+
throw new Error('Crashlytics not initialized');
|
|
79
|
+
}
|
|
80
|
+
return instance;
|
|
81
|
+
},
|
|
82
|
+
async setUserId(crashlytics: CrashlyticsInstance, userId: string): Promise<void> {
|
|
83
|
+
try {
|
|
84
|
+
await crashlytics.setUserId(userId);
|
|
85
|
+
} catch (error) {
|
|
86
|
+
/* eslint-disable-next-line no-console */
|
|
87
|
+
if (__DEV__) {
|
|
88
|
+
console.warn('[Crashlytics] Failed to set user ID:', error);
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
},
|
|
92
|
+
async setAttributes(
|
|
93
|
+
crashlytics: CrashlyticsInstance,
|
|
94
|
+
attributes: Record<string, string>,
|
|
95
|
+
): Promise<void> {
|
|
96
|
+
try {
|
|
97
|
+
await crashlytics.setAttributes(attributes);
|
|
98
|
+
} catch (error) {
|
|
99
|
+
/* eslint-disable-next-line no-console */
|
|
100
|
+
if (__DEV__) {
|
|
101
|
+
console.warn('[Crashlytics] Failed to set attributes:', error);
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
},
|
|
105
|
+
async recordError(crashlytics: CrashlyticsInstance, error: Error): Promise<void> {
|
|
106
|
+
try {
|
|
107
|
+
await crashlytics.recordError(error);
|
|
108
|
+
} catch (err) {
|
|
109
|
+
/* eslint-disable-next-line no-console */
|
|
110
|
+
if (__DEV__) {
|
|
111
|
+
console.warn('[Crashlytics] Failed to record error:', err);
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
},
|
|
115
|
+
async log(crashlytics: CrashlyticsInstance, message: string): Promise<void> {
|
|
116
|
+
try {
|
|
117
|
+
await crashlytics.log(message);
|
|
118
|
+
} catch (error) {
|
|
119
|
+
/* eslint-disable-next-line no-console */
|
|
120
|
+
if (__DEV__) {
|
|
121
|
+
console.warn('[Crashlytics] Failed to log message:', error);
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
},
|
|
125
|
+
};
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Firebase Crashlytics Service
|
|
3
|
+
* Single Responsibility: Orchestrate Crashlytics operations
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import { crashlyticsInitializerService } from './crashlytics-initializer.service';
|
|
7
|
+
import { crashlyticsErrorService } from './crashlytics-error.service';
|
|
8
|
+
import { crashlyticsUserService } from './crashlytics-user.service';
|
|
9
|
+
import type { CrashlyticsInstance } from '../adapters/native-crashlytics.adapter';
|
|
10
|
+
|
|
11
|
+
export interface ICrashlyticsService {
|
|
12
|
+
init(userId?: string, attributes?: Record<string, string>): Promise<void>;
|
|
13
|
+
logError(error: Error, context?: string): Promise<void>;
|
|
14
|
+
log(message: string): Promise<void>;
|
|
15
|
+
setAttribute(key: string, value: string): Promise<void>;
|
|
16
|
+
setAttributes(attributes: Record<string, string>): Promise<void>;
|
|
17
|
+
clearUserData(): Promise<void>;
|
|
18
|
+
destroy(): Promise<void>;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
class FirebaseCrashlyticsService implements ICrashlyticsService {
|
|
22
|
+
private isInitialized = false;
|
|
23
|
+
private userId: string | null = null;
|
|
24
|
+
private attributes: Record<string, string> = {};
|
|
25
|
+
private crashlytics: CrashlyticsInstance | null = null;
|
|
26
|
+
private isDestroyed = false;
|
|
27
|
+
|
|
28
|
+
async init(userId?: string, attributes?: Record<string, string>): Promise<void> {
|
|
29
|
+
if (this.isDestroyed) {
|
|
30
|
+
/* eslint-disable-next-line no-console */
|
|
31
|
+
if (__DEV__) {
|
|
32
|
+
console.warn('[Crashlytics] Cannot initialize destroyed service');
|
|
33
|
+
}
|
|
34
|
+
return;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
try {
|
|
38
|
+
this.crashlytics = crashlyticsInitializerService.initialize();
|
|
39
|
+
|
|
40
|
+
if (this.crashlytics) {
|
|
41
|
+
if (userId) {
|
|
42
|
+
this.userId = userId;
|
|
43
|
+
await crashlyticsUserService.setUserId(this.crashlytics, userId);
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
if (attributes) {
|
|
47
|
+
await this.setAttributes(attributes);
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
} catch (err) {
|
|
51
|
+
/* eslint-disable-next-line no-console */
|
|
52
|
+
if (__DEV__) {
|
|
53
|
+
console.warn('[Crashlytics] Init failed:', err);
|
|
54
|
+
}
|
|
55
|
+
} finally {
|
|
56
|
+
this.isInitialized = true;
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
async logError(error: Error, context?: string): Promise<void> {
|
|
61
|
+
if (this.isDestroyed) return;
|
|
62
|
+
await crashlyticsErrorService.logError(this.crashlytics, error, context);
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
async log(message: string): Promise<void> {
|
|
66
|
+
if (this.isDestroyed) return;
|
|
67
|
+
await crashlyticsErrorService.log(this.crashlytics, message);
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
async setAttribute(key: string, value: string): Promise<void> {
|
|
71
|
+
if (this.isDestroyed) return;
|
|
72
|
+
this.attributes[key] = value;
|
|
73
|
+
await crashlyticsUserService.setAttribute(this.crashlytics, key, value);
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
async setAttributes(attributes: Record<string, string>): Promise<void> {
|
|
77
|
+
if (this.isDestroyed) return;
|
|
78
|
+
await crashlyticsUserService.setAttributes(this.crashlytics, attributes);
|
|
79
|
+
Object.assign(this.attributes, attributes);
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
async clearUserData(): Promise<void> {
|
|
83
|
+
if (this.isDestroyed) return;
|
|
84
|
+
await crashlyticsUserService.clearUserData(this.crashlytics);
|
|
85
|
+
this.userId = null;
|
|
86
|
+
this.attributes = {};
|
|
87
|
+
this.isInitialized = false;
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
async destroy(): Promise<void> {
|
|
91
|
+
if (this.isDestroyed) return;
|
|
92
|
+
|
|
93
|
+
await this.clearUserData();
|
|
94
|
+
this.crashlytics = null;
|
|
95
|
+
this.isDestroyed = true;
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
export const firebaseCrashlyticsService = new FirebaseCrashlyticsService();
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Crashlytics Error Service
|
|
3
|
+
* Single Responsibility: Handle error logging operations
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import { nativeCrashlyticsAdapter } from '../adapters/native-crashlytics.adapter';
|
|
7
|
+
import type { CrashlyticsInstance } from '../adapters/native-crashlytics.adapter';
|
|
8
|
+
|
|
9
|
+
export class CrashlyticsErrorService {
|
|
10
|
+
/**
|
|
11
|
+
* Log error to Crashlytics
|
|
12
|
+
*/
|
|
13
|
+
async logError(
|
|
14
|
+
crashlytics: CrashlyticsInstance | null,
|
|
15
|
+
error: Error,
|
|
16
|
+
context?: string,
|
|
17
|
+
): Promise<void> {
|
|
18
|
+
try {
|
|
19
|
+
/* eslint-disable-next-line no-console */
|
|
20
|
+
if (__DEV__) {
|
|
21
|
+
console.error(`[Crashlytics] Error${context ? ` in ${context}` : ''}:`, error);
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
if (!crashlytics || !nativeCrashlyticsAdapter) {
|
|
25
|
+
return;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
if (context) {
|
|
29
|
+
await nativeCrashlyticsAdapter.log(crashlytics, `Context: ${context}`);
|
|
30
|
+
}
|
|
31
|
+
await nativeCrashlyticsAdapter.log(
|
|
32
|
+
crashlytics,
|
|
33
|
+
`Error: ${error.name} - ${error.message}`,
|
|
34
|
+
);
|
|
35
|
+
await nativeCrashlyticsAdapter.recordError(crashlytics, error);
|
|
36
|
+
} catch (err) {
|
|
37
|
+
/* eslint-disable-next-line no-console */
|
|
38
|
+
if (__DEV__) {
|
|
39
|
+
console.warn('[Crashlytics] Failed to log error:', err);
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
/**
|
|
45
|
+
* Log message to Crashlytics
|
|
46
|
+
*/
|
|
47
|
+
async log(crashlytics: CrashlyticsInstance | null, message: string): Promise<void> {
|
|
48
|
+
try {
|
|
49
|
+
if (!crashlytics || !nativeCrashlyticsAdapter) {
|
|
50
|
+
/* eslint-disable-next-line no-console */
|
|
51
|
+
if (__DEV__) {
|
|
52
|
+
console.log(`[Crashlytics] ${message}`);
|
|
53
|
+
}
|
|
54
|
+
return;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
await nativeCrashlyticsAdapter.log(crashlytics, message);
|
|
58
|
+
} catch (err) {
|
|
59
|
+
/* eslint-disable-next-line no-console */
|
|
60
|
+
if (__DEV__) {
|
|
61
|
+
console.warn('[Crashlytics] Failed to log message:', err);
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
export const crashlyticsErrorService = new CrashlyticsErrorService();
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Crashlytics Initializer Service
|
|
3
|
+
* Single Responsibility: Handle Crashlytics initialization logic
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import { nativeCrashlyticsAdapter } from '../adapters/native-crashlytics.adapter';
|
|
7
|
+
import type { CrashlyticsInstance } from '../adapters/native-crashlytics.adapter';
|
|
8
|
+
|
|
9
|
+
export class CrashlyticsInitializerService {
|
|
10
|
+
/**
|
|
11
|
+
* Initialize Crashlytics instance
|
|
12
|
+
* Returns null if Crashlytics is not available (e.g., on web)
|
|
13
|
+
*/
|
|
14
|
+
initialize(): CrashlyticsInstance | null {
|
|
15
|
+
if (!nativeCrashlyticsAdapter) {
|
|
16
|
+
return null;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
try {
|
|
20
|
+
return nativeCrashlyticsAdapter.getCrashlytics();
|
|
21
|
+
} catch (error) {
|
|
22
|
+
/* eslint-disable-next-line no-console */
|
|
23
|
+
if (__DEV__) {
|
|
24
|
+
console.warn('[Crashlytics] Initialization failed:', error);
|
|
25
|
+
}
|
|
26
|
+
return null;
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
export const crashlyticsInitializerService = new CrashlyticsInitializerService();
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Crashlytics User Service
|
|
3
|
+
* Single Responsibility: Handle user-related Crashlytics operations
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import { nativeCrashlyticsAdapter } from '../adapters/native-crashlytics.adapter';
|
|
7
|
+
import type { CrashlyticsInstance } from '../adapters/native-crashlytics.adapter';
|
|
8
|
+
|
|
9
|
+
export class CrashlyticsUserService {
|
|
10
|
+
/**
|
|
11
|
+
* Set user ID
|
|
12
|
+
*/
|
|
13
|
+
async setUserId(crashlytics: CrashlyticsInstance | null, userId: string): Promise<void> {
|
|
14
|
+
try {
|
|
15
|
+
if (!crashlytics || !nativeCrashlyticsAdapter) {
|
|
16
|
+
return;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
await nativeCrashlyticsAdapter.setUserId(crashlytics, userId);
|
|
20
|
+
} catch (err) {
|
|
21
|
+
/* eslint-disable-next-line no-console */
|
|
22
|
+
if (__DEV__) {
|
|
23
|
+
console.warn('[Crashlytics] Failed to set user ID:', err);
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
/**
|
|
29
|
+
* Set attribute
|
|
30
|
+
*/
|
|
31
|
+
async setAttribute(
|
|
32
|
+
crashlytics: CrashlyticsInstance | null,
|
|
33
|
+
key: string,
|
|
34
|
+
value: string,
|
|
35
|
+
): Promise<void> {
|
|
36
|
+
try {
|
|
37
|
+
if (!crashlytics || !nativeCrashlyticsAdapter) {
|
|
38
|
+
return;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
await nativeCrashlyticsAdapter.setAttributes(crashlytics, { [key]: value });
|
|
42
|
+
} catch (err) {
|
|
43
|
+
/* eslint-disable-next-line no-console */
|
|
44
|
+
if (__DEV__) {
|
|
45
|
+
console.warn('[Crashlytics] Failed to set attribute:', err);
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
/**
|
|
51
|
+
* Set multiple attributes
|
|
52
|
+
*/
|
|
53
|
+
async setAttributes(
|
|
54
|
+
crashlytics: CrashlyticsInstance | null,
|
|
55
|
+
attributes: Record<string, string>,
|
|
56
|
+
): Promise<void> {
|
|
57
|
+
try {
|
|
58
|
+
if (!crashlytics || !nativeCrashlyticsAdapter) {
|
|
59
|
+
return;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
await nativeCrashlyticsAdapter.setAttributes(crashlytics, attributes);
|
|
63
|
+
} catch (err) {
|
|
64
|
+
/* eslint-disable-next-line no-console */
|
|
65
|
+
if (__DEV__) {
|
|
66
|
+
console.warn('[Crashlytics] Failed to set attributes:', err);
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
/**
|
|
72
|
+
* Clear user data
|
|
73
|
+
*/
|
|
74
|
+
async clearUserData(crashlytics: CrashlyticsInstance | null): Promise<void> {
|
|
75
|
+
try {
|
|
76
|
+
if (!crashlytics || !nativeCrashlyticsAdapter) {
|
|
77
|
+
return;
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
await nativeCrashlyticsAdapter.setUserId(crashlytics, '');
|
|
81
|
+
await nativeCrashlyticsAdapter.setAttributes(crashlytics, {});
|
|
82
|
+
} catch (err) {
|
|
83
|
+
/* eslint-disable-next-line no-console */
|
|
84
|
+
if (__DEV__) {
|
|
85
|
+
console.warn('[Crashlytics] Failed to clear user data:', err);
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
export const crashlyticsUserService = new CrashlyticsUserService();
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Crashlytics Infrastructure Services
|
|
3
|
+
* Public API exports
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
export { firebaseCrashlyticsService } from './FirebaseCrashlyticsService';
|
|
7
|
+
export type { ICrashlyticsService } from './FirebaseCrashlyticsService';
|
|
8
|
+
export { crashlyticsInitializerService } from './crashlytics-initializer.service';
|
|
9
|
+
export { crashlyticsErrorService } from './crashlytics-error.service';
|
|
10
|
+
export { crashlyticsUserService } from './crashlytics-user.service';
|
|
11
|
+
|
|
@@ -1,56 +1,38 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Firebase Domain Errors
|
|
3
|
-
*
|
|
4
|
-
* Domain-Driven Design:
|
|
3
|
+
*
|
|
4
|
+
* Domain-Driven Design: Specialized error types for the Firebase domain
|
|
5
5
|
*/
|
|
6
6
|
|
|
7
7
|
/**
|
|
8
|
-
* Base Firebase
|
|
8
|
+
* Base Firebase error class
|
|
9
9
|
*/
|
|
10
10
|
export class FirebaseError extends Error {
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
super(message);
|
|
17
|
-
this.name = 'FirebaseError';
|
|
18
|
-
Object.setPrototypeOf(this, FirebaseError.prototype);
|
|
19
|
-
}
|
|
11
|
+
constructor(message: string, public code?: string, public cause?: any) {
|
|
12
|
+
super(message);
|
|
13
|
+
this.name = 'FirebaseError';
|
|
14
|
+
Object.setPrototypeOf(this, FirebaseError.prototype);
|
|
15
|
+
}
|
|
20
16
|
}
|
|
21
17
|
|
|
22
18
|
/**
|
|
23
|
-
* Initialization
|
|
24
|
-
* Thrown when Firebase client fails to initialize
|
|
19
|
+
* Initialization specific error
|
|
25
20
|
*/
|
|
26
21
|
export class FirebaseInitializationError extends FirebaseError {
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
22
|
+
constructor(message: string, cause?: any) {
|
|
23
|
+
super(message, 'INITIALIZATION_ERROR', cause);
|
|
24
|
+
this.name = 'FirebaseInitializationError';
|
|
25
|
+
Object.setPrototypeOf(this, FirebaseInitializationError.prototype);
|
|
26
|
+
}
|
|
32
27
|
}
|
|
33
28
|
|
|
34
29
|
/**
|
|
35
|
-
* Configuration
|
|
36
|
-
* Thrown when required configuration is missing or invalid
|
|
30
|
+
* Configuration specific error
|
|
37
31
|
*/
|
|
38
32
|
export class FirebaseConfigurationError extends FirebaseError {
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
33
|
+
constructor(message: string, cause?: any) {
|
|
34
|
+
super(message, 'CONFIGURATION_ERROR', cause);
|
|
35
|
+
this.name = 'FirebaseConfigurationError';
|
|
36
|
+
Object.setPrototypeOf(this, FirebaseConfigurationError.prototype);
|
|
37
|
+
}
|
|
44
38
|
}
|
|
45
|
-
|
|
46
|
-
// Note: FirebaseAnalyticsError, FirebaseCrashlyticsError, FirebaseAuthError, and FirebaseFirestoreError
|
|
47
|
-
// have been moved to their respective packages:
|
|
48
|
-
// - @umituz/react-native-firebase-analytics
|
|
49
|
-
// - @umituz/react-native-firebase-crashlytics
|
|
50
|
-
// - @umituz/react-native-firebase-auth
|
|
51
|
-
// - @umituz/react-native-firestore
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
@@ -1,44 +1,14 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Firebase
|
|
3
|
-
*
|
|
4
|
-
* Domain-Driven Design: Value
|
|
5
|
-
*/
|
|
6
|
-
|
|
7
|
-
/**
|
|
8
|
-
* Firebase Configuration
|
|
9
|
-
* Required configuration for initializing Firebase client
|
|
2
|
+
* Firebase Config - Domain Layer
|
|
3
|
+
*
|
|
4
|
+
* Domain-Driven Design: Value Object representing Firebase configuration parameters
|
|
10
5
|
*/
|
|
11
6
|
export interface FirebaseConfig {
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
*/
|
|
20
|
-
authDomain: string;
|
|
21
|
-
|
|
22
|
-
/**
|
|
23
|
-
* Firebase Project ID
|
|
24
|
-
*/
|
|
25
|
-
projectId: string;
|
|
26
|
-
|
|
27
|
-
/**
|
|
28
|
-
* Firebase Storage Bucket
|
|
29
|
-
*/
|
|
30
|
-
storageBucket?: string;
|
|
31
|
-
|
|
32
|
-
/**
|
|
33
|
-
* Firebase Messaging Sender ID
|
|
34
|
-
*/
|
|
35
|
-
messagingSenderId?: string;
|
|
36
|
-
|
|
37
|
-
/**
|
|
38
|
-
* Firebase App ID
|
|
39
|
-
*/
|
|
40
|
-
appId?: string;
|
|
7
|
+
apiKey: string;
|
|
8
|
+
authDomain: string;
|
|
9
|
+
projectId: string;
|
|
10
|
+
storageBucket?: string;
|
|
11
|
+
messagingSenderId?: string;
|
|
12
|
+
appId?: string;
|
|
13
|
+
measurementId?: string;
|
|
41
14
|
}
|
|
42
|
-
|
|
43
|
-
// Validation moved to FirebaseConfigValidator class (SOLID: Single Responsibility)
|
|
44
|
-
|
package/src/index.ts
CHANGED
|
@@ -1,26 +1,19 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* React Native Firebase -
|
|
2
|
+
* React Native Firebase - Unified Package
|
|
3
3
|
*
|
|
4
4
|
* Domain-Driven Design (DDD) Architecture
|
|
5
5
|
*
|
|
6
|
-
* This package provides
|
|
7
|
-
*
|
|
8
|
-
* -
|
|
9
|
-
* - @umituz/react-native-firebase-analytics - Firebase Analytics
|
|
10
|
-
* - @umituz/react-native-firebase-crashlytics - Firebase Crashlytics
|
|
11
|
-
* - @umituz/react-native-firestore - Firestore initialization and utilities
|
|
12
|
-
*
|
|
13
|
-
* Architecture:
|
|
14
|
-
* - domain: Entities, value objects, errors (business logic)
|
|
15
|
-
* - application: Ports (interfaces)
|
|
16
|
-
* - infrastructure: Firebase client implementation
|
|
6
|
+
* This package provides Firebase App initialization and core services:
|
|
7
|
+
* - Analytics
|
|
8
|
+
* - Crashlytics
|
|
17
9
|
*
|
|
18
10
|
* Usage:
|
|
19
11
|
* import { initializeFirebase, getFirebaseApp } from '@umituz/react-native-firebase';
|
|
12
|
+
* import { firebaseAnalyticsService } from '@umituz/react-native-firebase';
|
|
20
13
|
*/
|
|
21
14
|
|
|
22
15
|
// =============================================================================
|
|
23
|
-
//
|
|
16
|
+
// CORE - App Initialization & Type Definitions
|
|
24
17
|
// =============================================================================
|
|
25
18
|
|
|
26
19
|
export {
|
|
@@ -30,17 +23,8 @@ export {
|
|
|
30
23
|
} from './domain/errors/FirebaseError';
|
|
31
24
|
|
|
32
25
|
export type { FirebaseConfig } from './domain/value-objects/FirebaseConfig';
|
|
33
|
-
|
|
34
|
-
// =============================================================================
|
|
35
|
-
// APPLICATION LAYER - Ports
|
|
36
|
-
// =============================================================================
|
|
37
|
-
|
|
38
26
|
export type { IFirebaseClient } from './application/ports/IFirebaseClient';
|
|
39
27
|
|
|
40
|
-
// =============================================================================
|
|
41
|
-
// INFRASTRUCTURE LAYER - Implementation
|
|
42
|
-
// =============================================================================
|
|
43
|
-
|
|
44
28
|
export {
|
|
45
29
|
initializeFirebase,
|
|
46
30
|
getFirebaseApp,
|
|
@@ -56,3 +40,15 @@ export type {
|
|
|
56
40
|
FirebaseApp,
|
|
57
41
|
} from './infrastructure/config/FirebaseClient';
|
|
58
42
|
|
|
43
|
+
// =============================================================================
|
|
44
|
+
// ANALYTICS MODULE
|
|
45
|
+
// =============================================================================
|
|
46
|
+
|
|
47
|
+
export * from './analytics';
|
|
48
|
+
|
|
49
|
+
// =============================================================================
|
|
50
|
+
// CRASHLYTICS MODULE
|
|
51
|
+
// =============================================================================
|
|
52
|
+
|
|
53
|
+
export * from './crashlytics';
|
|
54
|
+
|
|
@@ -309,11 +309,11 @@ class ServiceInitializer {
|
|
|
309
309
|
try {
|
|
310
310
|
const serviceModule = require(packageName);
|
|
311
311
|
const service = serviceModule[initializerName];
|
|
312
|
-
|
|
312
|
+
|
|
313
313
|
if (isAsync && typeof service.init === 'function') {
|
|
314
314
|
return service;
|
|
315
315
|
}
|
|
316
|
-
|
|
316
|
+
|
|
317
317
|
return typeof service === 'function' ? service() : service;
|
|
318
318
|
} catch {
|
|
319
319
|
return null;
|
|
@@ -396,6 +396,15 @@ export async function initializeAllFirebaseServices(
|
|
|
396
396
|
|
|
397
397
|
const { auth, analytics, crashlytics } = await ServiceInitializer.initializeServices();
|
|
398
398
|
|
|
399
|
+
// Initialize services if they have an init method
|
|
400
|
+
if (analytics && typeof analytics.init === 'function') {
|
|
401
|
+
await analytics.init();
|
|
402
|
+
}
|
|
403
|
+
|
|
404
|
+
if (crashlytics && typeof crashlytics.init === 'function') {
|
|
405
|
+
await crashlytics.init();
|
|
406
|
+
}
|
|
407
|
+
|
|
399
408
|
return {
|
|
400
409
|
app,
|
|
401
410
|
auth,
|