@umituz/react-native-firebase 1.13.116 → 1.13.117
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 +1 -1
- package/src/auth/domain/errors/FirebaseAuthError.ts +0 -4
- package/src/auth/index.ts +0 -14
- package/src/auth/infrastructure/config/initializers/FirebaseAuthInitializer.ts +2 -23
- package/src/auth/infrastructure/services/apple-auth.types.ts +16 -4
- package/src/auth/infrastructure/services/auth-utils.service.ts +54 -46
- package/src/auth/infrastructure/services/google-auth.types.ts +18 -11
- package/src/auth/infrastructure/services/reauthentication.types.ts +16 -14
- package/src/auth/infrastructure/stores/auth.store.ts +1 -10
- package/src/auth/presentation/hooks/useAnonymousAuth.ts +1 -25
- package/src/domain/errors/FirebaseError.ts +0 -4
- package/src/firestore/domain/errors/FirebaseFirestoreError.ts +0 -8
- package/src/firestore/infrastructure/config/FirestoreClient.ts +0 -2
- package/src/firestore/infrastructure/middleware/QuotaTrackingMiddleware.ts +0 -13
- package/src/firestore/infrastructure/repositories/BaseRepository.ts +5 -5
- package/src/firestore/infrastructure/services/RequestLoggerService.ts +2 -24
- package/src/firestore/types/pagination.types.ts +0 -8
- package/src/firestore/utils/firestore-helper.ts +10 -14
- package/src/firestore/utils/quota-error-detector.util.ts +27 -16
- package/src/index.ts +0 -10
- package/src/infrastructure/config/FirebaseClient.ts +0 -9
- package/src/infrastructure/config/FirebaseConfigLoader.ts +33 -2
- package/src/infrastructure/config/orchestrators/FirebaseInitializationOrchestrator.ts +0 -21
- package/src/infrastructure/config/services/FirebaseServiceInitializer.ts +2 -18
- package/src/init/createFirebaseInitModule.ts +0 -1
- package/src/storage/deleter.ts +2 -35
- package/src/storage/uploader.ts +0 -34
- package/src/auth/README.md +0 -339
- package/src/auth/domain/README.md +0 -264
- package/src/auth/infrastructure/stores/README.md +0 -407
- package/src/auth/presentation/hooks/README.md +0 -442
- package/src/firestore/README.md +0 -566
- package/src/firestore/__tests__/BaseRepository.test.ts +0 -132
- package/src/firestore/__tests__/QueryDeduplicationMiddleware.test.ts +0 -147
- package/src/firestore/__tests__/mocks/react-native-firebase.ts +0 -23
- package/src/firestore/__tests__/setup.ts +0 -45
- package/src/firestore/utils/path-resolver/README.md +0 -277
- package/src/firestore/utils/quota-error-detector/README.md +0 -355
- package/src/storage/README.md +0 -493
- package/src/storage/uploader/README.md +0 -409
|
@@ -31,13 +31,10 @@ export function getDb(): Firestore | null {
|
|
|
31
31
|
*/
|
|
32
32
|
export async function withFirestore<T>(
|
|
33
33
|
operation: (db: Firestore) => Promise<FirestoreResult<T>>,
|
|
34
|
-
|
|
34
|
+
_logTag?: string
|
|
35
35
|
): Promise<FirestoreResult<T>> {
|
|
36
36
|
const db = getDb();
|
|
37
37
|
if (!db) {
|
|
38
|
-
if (__DEV__ && logTag) {
|
|
39
|
-
console.log(`[${logTag}] No Firestore instance`);
|
|
40
|
-
}
|
|
41
38
|
return NO_DB_ERROR as FirestoreResult<T>;
|
|
42
39
|
}
|
|
43
40
|
return operation(db);
|
|
@@ -48,13 +45,10 @@ export async function withFirestore<T>(
|
|
|
48
45
|
*/
|
|
49
46
|
export async function withFirestoreVoid(
|
|
50
47
|
operation: (db: Firestore) => Promise<void>,
|
|
51
|
-
|
|
48
|
+
_logTag?: string
|
|
52
49
|
): Promise<void> {
|
|
53
50
|
const db = getDb();
|
|
54
51
|
if (!db) {
|
|
55
|
-
if (__DEV__ && logTag) {
|
|
56
|
-
console.log(`[${logTag}] No Firestore instance`);
|
|
57
|
-
}
|
|
58
52
|
return;
|
|
59
53
|
}
|
|
60
54
|
return operation(db);
|
|
@@ -65,13 +59,10 @@ export async function withFirestoreVoid(
|
|
|
65
59
|
*/
|
|
66
60
|
export async function withFirestoreBool(
|
|
67
61
|
operation: (db: Firestore) => Promise<boolean>,
|
|
68
|
-
|
|
62
|
+
_logTag?: string
|
|
69
63
|
): Promise<boolean> {
|
|
70
64
|
const db = getDb();
|
|
71
65
|
if (!db) {
|
|
72
|
-
if (__DEV__ && logTag) {
|
|
73
|
-
console.log(`[${logTag}] No Firestore instance`);
|
|
74
|
-
}
|
|
75
66
|
return false;
|
|
76
67
|
}
|
|
77
68
|
return operation(db);
|
|
@@ -110,9 +101,14 @@ export async function runTransaction<T>(
|
|
|
110
101
|
): Promise<T> {
|
|
111
102
|
const db = getDb();
|
|
112
103
|
if (!db) {
|
|
113
|
-
throw new Error("[runTransaction] Firestore not initialized");
|
|
104
|
+
throw new Error("[runTransaction] Firestore database is not initialized. Please ensure Firebase is properly initialized before running transactions.");
|
|
105
|
+
}
|
|
106
|
+
try {
|
|
107
|
+
return await fbRunTransaction(db, updateFunction);
|
|
108
|
+
} catch (error) {
|
|
109
|
+
const errorMessage = error instanceof Error ? error.message : 'Unknown error';
|
|
110
|
+
throw new Error(`[runTransaction] Transaction failed: ${errorMessage}`);
|
|
114
111
|
}
|
|
115
|
-
return fbRunTransaction(db, updateFunction);
|
|
116
112
|
}
|
|
117
113
|
|
|
118
114
|
/**
|
|
@@ -16,24 +16,35 @@ const QUOTA_ERROR_MESSAGES = [
|
|
|
16
16
|
'too many requests',
|
|
17
17
|
];
|
|
18
18
|
|
|
19
|
+
/**
|
|
20
|
+
* Type guard for error with code property
|
|
21
|
+
*/
|
|
22
|
+
function hasCodeProperty(error: unknown): error is { code: string } {
|
|
23
|
+
return typeof error === 'object' && error !== null && 'code' in error && typeof (error as { code: unknown }).code === 'string';
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
/**
|
|
27
|
+
* Type guard for error with message property
|
|
28
|
+
*/
|
|
29
|
+
function hasMessageProperty(error: unknown): error is { message: string } {
|
|
30
|
+
return typeof error === 'object' && error !== null && 'message' in error && typeof (error as { message: unknown }).message === 'string';
|
|
31
|
+
}
|
|
32
|
+
|
|
19
33
|
/**
|
|
20
34
|
* Check if error is a Firestore quota error
|
|
21
35
|
*/
|
|
22
36
|
export function isQuotaError(error: unknown): boolean {
|
|
23
37
|
if (!error || typeof error !== 'object') return false;
|
|
24
38
|
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
: undefined;
|
|
31
|
-
|
|
32
|
-
if (code && QUOTA_ERROR_CODES.some((c) => code.includes(c))) {
|
|
33
|
-
return true;
|
|
39
|
+
if (hasCodeProperty(error)) {
|
|
40
|
+
const code = error.code;
|
|
41
|
+
if (QUOTA_ERROR_CODES.some((c) => code.includes(c))) {
|
|
42
|
+
return true;
|
|
43
|
+
}
|
|
34
44
|
}
|
|
35
45
|
|
|
36
|
-
if (
|
|
46
|
+
if (hasMessageProperty(error)) {
|
|
47
|
+
const message = error.message;
|
|
37
48
|
const lowerMessage = message.toLowerCase();
|
|
38
49
|
return QUOTA_ERROR_MESSAGES.some((m) => lowerMessage.includes(m));
|
|
39
50
|
}
|
|
@@ -47,13 +58,13 @@ export function isQuotaError(error: unknown): boolean {
|
|
|
47
58
|
export function isRetryableError(error: unknown): boolean {
|
|
48
59
|
if (!error || typeof error !== 'object') return false;
|
|
49
60
|
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
61
|
+
if (hasCodeProperty(error)) {
|
|
62
|
+
const code = error.code;
|
|
63
|
+
const retryableCodes = ['unavailable', 'deadline-exceeded', 'aborted'];
|
|
64
|
+
return retryableCodes.some((c) => code.includes(c));
|
|
65
|
+
}
|
|
55
66
|
|
|
56
|
-
return
|
|
67
|
+
return false;
|
|
57
68
|
}
|
|
58
69
|
|
|
59
70
|
/**
|
package/src/index.ts
CHANGED
|
@@ -11,10 +11,6 @@
|
|
|
11
11
|
* - @umituz/react-native-firebase/storage
|
|
12
12
|
*/
|
|
13
13
|
|
|
14
|
-
if (__DEV__) {
|
|
15
|
-
console.log("📍 [LIFECYCLE] @umituz/react-native-firebase/index.ts - START");
|
|
16
|
-
}
|
|
17
|
-
|
|
18
14
|
// Core Errors
|
|
19
15
|
export {
|
|
20
16
|
FirebaseError,
|
|
@@ -22,12 +18,6 @@ export {
|
|
|
22
18
|
FirebaseConfigurationError,
|
|
23
19
|
} from "./domain/errors/FirebaseError";
|
|
24
20
|
|
|
25
|
-
if (__DEV__) {
|
|
26
|
-
console.log(
|
|
27
|
-
"📍 [LIFECYCLE] @umituz/react-native-firebase/index.ts - Core errors exported",
|
|
28
|
-
);
|
|
29
|
-
}
|
|
30
|
-
|
|
31
21
|
// Core Types
|
|
32
22
|
export type { FirebaseConfig } from "./domain/value-objects/FirebaseConfig";
|
|
33
23
|
export type { IFirebaseClient } from "./application/ports/IFirebaseClient";
|
|
@@ -16,8 +16,6 @@
|
|
|
16
16
|
* - Dependency Inversion: Depends on abstractions (interfaces), not concrete implementations
|
|
17
17
|
*/
|
|
18
18
|
|
|
19
|
-
if (__DEV__) console.log("📍 [LIFECYCLE] FirebaseClient.ts - Module loading");
|
|
20
|
-
|
|
21
19
|
import type { FirebaseConfig } from '../../domain/value-objects/FirebaseConfig';
|
|
22
20
|
import type { IFirebaseClient } from '../../application/ports/IFirebaseClient';
|
|
23
21
|
import type { FirebaseApp } from './initializers/FirebaseAppInitializer';
|
|
@@ -144,13 +142,6 @@ export async function initializeAllFirebaseServices(
|
|
|
144
142
|
|
|
145
143
|
const { auth } = await FirebaseServiceInitializer.initializeServices(options);
|
|
146
144
|
|
|
147
|
-
if (__DEV__) {
|
|
148
|
-
console.log('[Firebase] All services initialized:', {
|
|
149
|
-
app: !!app,
|
|
150
|
-
auth: !!auth,
|
|
151
|
-
});
|
|
152
|
-
}
|
|
153
|
-
|
|
154
145
|
return {
|
|
155
146
|
app,
|
|
156
147
|
auth,
|
|
@@ -62,6 +62,15 @@ function getExpoValue(key: ConfigKey, expoConfig: Record<string, string>): strin
|
|
|
62
62
|
return expoConfig[mapping[key]] || '';
|
|
63
63
|
}
|
|
64
64
|
|
|
65
|
+
/**
|
|
66
|
+
* Validate Firebase API key format
|
|
67
|
+
*/
|
|
68
|
+
function validateApiKey(apiKey: string): boolean {
|
|
69
|
+
// Firebase API keys typically start with "AIza" followed by 35 characters
|
|
70
|
+
const apiKeyPattern = /^AIza[0-9A-Za-z_-]{35}$/;
|
|
71
|
+
return apiKeyPattern.test(apiKey);
|
|
72
|
+
}
|
|
73
|
+
|
|
65
74
|
/**
|
|
66
75
|
* Load Firebase configuration from Constants and environment variables
|
|
67
76
|
*/
|
|
@@ -76,11 +85,33 @@ export function loadFirebaseConfig(): FirebaseConfig | null {
|
|
|
76
85
|
config[key] = expoValue || getEnvValue(key);
|
|
77
86
|
}
|
|
78
87
|
|
|
79
|
-
// Validate required fields
|
|
80
|
-
|
|
88
|
+
// Validate required fields with proper checks
|
|
89
|
+
const apiKey = config.apiKey?.trim();
|
|
90
|
+
const authDomain = config.authDomain?.trim();
|
|
91
|
+
const projectId = config.projectId?.trim();
|
|
92
|
+
|
|
93
|
+
if (!apiKey || !authDomain || !projectId) {
|
|
94
|
+
if (__DEV__) {
|
|
95
|
+
console.error('[FirebaseConfigLoader] Missing required configuration fields');
|
|
96
|
+
}
|
|
97
|
+
return null;
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
// Validate API key format
|
|
101
|
+
if (!validateApiKey(apiKey)) {
|
|
102
|
+
if (__DEV__) {
|
|
103
|
+
console.error('[FirebaseConfigLoader] Invalid API key format');
|
|
104
|
+
}
|
|
81
105
|
return null;
|
|
82
106
|
}
|
|
83
107
|
|
|
108
|
+
// Validate authDomain format (should be like "projectId.firebaseapp.com")
|
|
109
|
+
if (!authDomain.includes('.firebaseapp.com') && !authDomain.includes('.web.app')) {
|
|
110
|
+
if (__DEV__) {
|
|
111
|
+
console.warn('[FirebaseConfigLoader] Unusual authDomain format, expected "projectId.firebaseapp.com" or similar');
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
|
|
84
115
|
return config as FirebaseConfig;
|
|
85
116
|
}
|
|
86
117
|
|
|
@@ -18,32 +18,18 @@ export class FirebaseInitializationOrchestrator {
|
|
|
18
18
|
state: FirebaseClientState
|
|
19
19
|
): FirebaseApp | null {
|
|
20
20
|
if (state.isInitialized()) {
|
|
21
|
-
if (__DEV__) {
|
|
22
|
-
console.log('[Firebase] Already initialized, returning existing instance');
|
|
23
|
-
}
|
|
24
21
|
return state.getApp();
|
|
25
22
|
}
|
|
26
23
|
|
|
27
24
|
if (state.getInitializationError()) {
|
|
28
|
-
if (__DEV__) {
|
|
29
|
-
console.log('[Firebase] Previous initialization failed, skipping retry');
|
|
30
|
-
}
|
|
31
25
|
return null;
|
|
32
26
|
}
|
|
33
27
|
|
|
34
28
|
try {
|
|
35
|
-
if (__DEV__) {
|
|
36
|
-
console.log('[Firebase] Initializing with projectId:', config.projectId);
|
|
37
|
-
}
|
|
38
|
-
|
|
39
29
|
FirebaseConfigValidator.validate(config);
|
|
40
30
|
const app = FirebaseAppInitializer.initialize(config);
|
|
41
31
|
state.setApp(app);
|
|
42
32
|
|
|
43
|
-
if (__DEV__) {
|
|
44
|
-
console.log('[Firebase] Successfully initialized');
|
|
45
|
-
}
|
|
46
|
-
|
|
47
33
|
return app;
|
|
48
34
|
} catch (error) {
|
|
49
35
|
const errorMessage =
|
|
@@ -67,16 +53,9 @@ export class FirebaseInitializationOrchestrator {
|
|
|
67
53
|
|
|
68
54
|
const autoConfig = loadFirebaseConfig();
|
|
69
55
|
if (autoConfig) {
|
|
70
|
-
if (__DEV__) {
|
|
71
|
-
console.log('[Firebase] Auto-initializing with environment config');
|
|
72
|
-
}
|
|
73
56
|
return this.initialize(autoConfig, state);
|
|
74
57
|
}
|
|
75
58
|
|
|
76
|
-
if (__DEV__) {
|
|
77
|
-
console.log('[Firebase] No configuration found for auto-initialization');
|
|
78
|
-
}
|
|
79
|
-
|
|
80
59
|
return null;
|
|
81
60
|
}
|
|
82
61
|
}
|
|
@@ -22,31 +22,15 @@ export class FirebaseServiceInitializer {
|
|
|
22
22
|
static async initializeServices(
|
|
23
23
|
options?: ServiceInitializationOptions
|
|
24
24
|
): Promise<ServiceInitializationResult> {
|
|
25
|
-
if (__DEV__) {
|
|
26
|
-
console.log('[Firebase] Initializing auth service...');
|
|
27
|
-
}
|
|
28
|
-
|
|
29
25
|
let auth: unknown = null;
|
|
30
26
|
if (options?.authInitializer) {
|
|
31
27
|
try {
|
|
32
28
|
auth = await options.authInitializer();
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
}
|
|
36
|
-
} catch (error) {
|
|
37
|
-
if (__DEV__) {
|
|
38
|
-
console.warn(
|
|
39
|
-
'[Firebase] Auth initialization failed:',
|
|
40
|
-
error instanceof Error ? error.message : 'Unknown error'
|
|
41
|
-
);
|
|
42
|
-
}
|
|
29
|
+
} catch {
|
|
30
|
+
// Silently fail, auth initialization is optional
|
|
43
31
|
}
|
|
44
32
|
}
|
|
45
33
|
|
|
46
|
-
if (__DEV__) {
|
|
47
|
-
console.log('[Firebase] Auth service initialized:', !!auth);
|
|
48
|
-
}
|
|
49
|
-
|
|
50
34
|
return { auth };
|
|
51
35
|
}
|
|
52
36
|
}
|
package/src/storage/deleter.ts
CHANGED
|
@@ -32,8 +32,7 @@ function extractStoragePath(downloadUrl: string): string | null {
|
|
|
32
32
|
}
|
|
33
33
|
|
|
34
34
|
return decodeURIComponent(pathMatch[1]);
|
|
35
|
-
} catch
|
|
36
|
-
if (__DEV__) console.warn('[StorageDeleter] Failed to parse URL:', error);
|
|
35
|
+
} catch {
|
|
37
36
|
return null;
|
|
38
37
|
}
|
|
39
38
|
}
|
|
@@ -45,18 +44,9 @@ function extractStoragePath(downloadUrl: string): string | null {
|
|
|
45
44
|
export async function deleteStorageFile(
|
|
46
45
|
downloadUrlOrPath: string
|
|
47
46
|
): Promise<DeleteResult> {
|
|
48
|
-
if (__DEV__) {
|
|
49
|
-
console.log("[StorageDeleter] Deleting", { url: downloadUrlOrPath });
|
|
50
|
-
}
|
|
51
|
-
|
|
52
47
|
const storagePath = extractStoragePath(downloadUrlOrPath);
|
|
53
48
|
|
|
54
49
|
if (!storagePath) {
|
|
55
|
-
if (__DEV__) {
|
|
56
|
-
console.error("[StorageDeleter] Invalid URL", {
|
|
57
|
-
url: downloadUrlOrPath,
|
|
58
|
-
});
|
|
59
|
-
}
|
|
60
50
|
return { success: false, storagePath: downloadUrlOrPath };
|
|
61
51
|
}
|
|
62
52
|
|
|
@@ -69,20 +59,8 @@ export async function deleteStorageFile(
|
|
|
69
59
|
const storageRef = ref(storage, storagePath);
|
|
70
60
|
await deleteObject(storageRef);
|
|
71
61
|
|
|
72
|
-
if (__DEV__) {
|
|
73
|
-
console.log("[StorageDeleter] Deleted successfully", {
|
|
74
|
-
storagePath,
|
|
75
|
-
});
|
|
76
|
-
}
|
|
77
|
-
|
|
78
62
|
return { success: true, storagePath };
|
|
79
|
-
} catch
|
|
80
|
-
if (__DEV__) {
|
|
81
|
-
console.error("[StorageDeleter] Delete failed", {
|
|
82
|
-
storagePath,
|
|
83
|
-
error,
|
|
84
|
-
});
|
|
85
|
-
}
|
|
63
|
+
} catch {
|
|
86
64
|
return { success: false, storagePath };
|
|
87
65
|
}
|
|
88
66
|
}
|
|
@@ -97,10 +75,6 @@ export async function deleteStorageFile(
|
|
|
97
75
|
export async function deleteStorageFiles(
|
|
98
76
|
urlsOrPaths: string[]
|
|
99
77
|
): Promise<BatchDeleteResult> {
|
|
100
|
-
if (__DEV__) {
|
|
101
|
-
console.log("[StorageDeleter] Batch delete", { count: urlsOrPaths.length });
|
|
102
|
-
}
|
|
103
|
-
|
|
104
78
|
const storage = getStorageInstance();
|
|
105
79
|
if (!storage) {
|
|
106
80
|
return {
|
|
@@ -131,12 +105,5 @@ export async function deleteStorageFiles(
|
|
|
131
105
|
}
|
|
132
106
|
});
|
|
133
107
|
|
|
134
|
-
if (__DEV__) {
|
|
135
|
-
console.log("[StorageDeleter] Batch delete complete", {
|
|
136
|
-
successful: successful.length,
|
|
137
|
-
failed: failed.length,
|
|
138
|
-
});
|
|
139
|
-
}
|
|
140
|
-
|
|
141
108
|
return { successful, failed };
|
|
142
109
|
}
|
package/src/storage/uploader.ts
CHANGED
|
@@ -20,9 +20,6 @@ export function getMimeType(base64: string): string {
|
|
|
20
20
|
if (base64.startsWith("data:image/png")) return "image/png";
|
|
21
21
|
if (base64.startsWith("data:image/webp")) return "image/webp";
|
|
22
22
|
if (base64.startsWith("data:image/gif")) return "image/gif";
|
|
23
|
-
if (__DEV__) {
|
|
24
|
-
console.warn("[StorageUploader] Could not detect MIME type from base64 prefix, falling back to image/jpeg");
|
|
25
|
-
}
|
|
26
23
|
return "image/jpeg";
|
|
27
24
|
}
|
|
28
25
|
|
|
@@ -47,13 +44,6 @@ export async function uploadBase64Image(
|
|
|
47
44
|
const mimeType = options?.mimeType ?? getMimeType(base64);
|
|
48
45
|
const dataUrl = ensureDataUrl(base64, mimeType);
|
|
49
46
|
|
|
50
|
-
if (__DEV__) {
|
|
51
|
-
console.log("[StorageUploader] Starting base64 upload", {
|
|
52
|
-
storagePath,
|
|
53
|
-
mimeType,
|
|
54
|
-
});
|
|
55
|
-
}
|
|
56
|
-
|
|
57
47
|
const storage = getStorageInstance();
|
|
58
48
|
if (!storage) {
|
|
59
49
|
throw new Error("Firebase Storage not initialized");
|
|
@@ -71,13 +61,6 @@ export async function uploadBase64Image(
|
|
|
71
61
|
await uploadBytes(storageRef, blob, metadata);
|
|
72
62
|
const downloadUrl = await getDownloadURL(storageRef);
|
|
73
63
|
|
|
74
|
-
if (__DEV__) {
|
|
75
|
-
console.log("[StorageUploader] Upload complete", {
|
|
76
|
-
storagePath,
|
|
77
|
-
downloadUrl,
|
|
78
|
-
});
|
|
79
|
-
}
|
|
80
|
-
|
|
81
64
|
return {
|
|
82
65
|
downloadUrl,
|
|
83
66
|
storagePath,
|
|
@@ -92,13 +75,6 @@ export async function uploadFile(
|
|
|
92
75
|
storagePath: string,
|
|
93
76
|
options?: UploadOptions
|
|
94
77
|
): Promise<UploadResult> {
|
|
95
|
-
if (__DEV__) {
|
|
96
|
-
console.log("[StorageUploader] Starting file upload", {
|
|
97
|
-
uri,
|
|
98
|
-
storagePath,
|
|
99
|
-
});
|
|
100
|
-
}
|
|
101
|
-
|
|
102
78
|
const storage = getStorageInstance();
|
|
103
79
|
if (!storage) {
|
|
104
80
|
throw new Error("Firebase Storage not initialized");
|
|
@@ -109,9 +85,6 @@ export async function uploadFile(
|
|
|
109
85
|
const blob = await response.blob();
|
|
110
86
|
|
|
111
87
|
const contentType = options?.mimeType ?? "image/jpeg";
|
|
112
|
-
if (!options?.mimeType && __DEV__) {
|
|
113
|
-
console.warn("[StorageUploader] No MIME type provided for file upload, falling back to image/jpeg");
|
|
114
|
-
}
|
|
115
88
|
const metadata: UploadMetadata = {
|
|
116
89
|
contentType,
|
|
117
90
|
customMetadata: options?.customMetadata,
|
|
@@ -120,13 +93,6 @@ export async function uploadFile(
|
|
|
120
93
|
await uploadBytes(storageRef, blob, metadata);
|
|
121
94
|
const downloadUrl = await getDownloadURL(storageRef);
|
|
122
95
|
|
|
123
|
-
if (__DEV__) {
|
|
124
|
-
console.log("[StorageUploader] Upload complete", {
|
|
125
|
-
storagePath,
|
|
126
|
-
downloadUrl,
|
|
127
|
-
});
|
|
128
|
-
}
|
|
129
|
-
|
|
130
96
|
return {
|
|
131
97
|
downloadUrl,
|
|
132
98
|
storagePath,
|