@umituz/react-native-firebase 1.13.111 → 1.13.114
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 +2 -1
- package/src/firestore/index.ts +2 -0
- package/src/firestore/infrastructure/config/initializers/FirebaseFirestoreInitializer.ts +1 -1
- package/src/firestore/infrastructure/repositories/BasePaginatedRepository.ts +15 -3
- package/src/firestore/infrastructure/repositories/BaseQueryRepository.ts +19 -12
- package/src/firestore/utils/firestore-helper.ts +32 -0
- package/src/index.ts +12 -1
- package/src/infrastructure/config/FirebaseConfigLoader.ts +1 -0
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@umituz/react-native-firebase",
|
|
3
|
-
"version": "1.13.
|
|
3
|
+
"version": "1.13.114",
|
|
4
4
|
"description": "Unified Firebase package for React Native apps - Auth and Firestore services using Firebase JS SDK (no native modules).",
|
|
5
5
|
"main": "./src/index.ts",
|
|
6
6
|
"types": "./src/index.ts",
|
|
@@ -62,6 +62,7 @@
|
|
|
62
62
|
"expo-apple-authentication": "^8.0.8",
|
|
63
63
|
"expo-application": "^7.0.8",
|
|
64
64
|
"expo-clipboard": "^8.0.8",
|
|
65
|
+
"expo-constants": "^18.0.13",
|
|
65
66
|
"expo-crypto": "^15.0.8",
|
|
66
67
|
"expo-device": "^8.0.10",
|
|
67
68
|
"expo-file-system": "^19.0.21",
|
package/src/firestore/index.ts
CHANGED
|
@@ -42,7 +42,9 @@ export abstract class BasePaginatedRepository extends BaseQueryRepository {
|
|
|
42
42
|
limit(fetchLimit),
|
|
43
43
|
);
|
|
44
44
|
|
|
45
|
+
let cursorKey = 'start';
|
|
45
46
|
if (helper.hasCursor(params) && params?.cursor) {
|
|
47
|
+
cursorKey = params.cursor;
|
|
46
48
|
const cursorDoc = await getDoc(doc(db, collectionName, params.cursor));
|
|
47
49
|
if (cursorDoc.exists()) {
|
|
48
50
|
q = query(
|
|
@@ -54,9 +56,19 @@ export abstract class BasePaginatedRepository extends BaseQueryRepository {
|
|
|
54
56
|
}
|
|
55
57
|
}
|
|
56
58
|
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
59
|
+
// Generate a unique key for deduplication
|
|
60
|
+
const uniqueKey = `${collectionName}_list_${orderByField}_${orderDirection}_${fetchLimit}_${cursorKey}`;
|
|
61
|
+
|
|
62
|
+
return this.executeQuery(
|
|
63
|
+
collectionName,
|
|
64
|
+
q,
|
|
65
|
+
async () => {
|
|
66
|
+
const snapshot = await getDocs(q);
|
|
67
|
+
return snapshot.docs;
|
|
68
|
+
},
|
|
69
|
+
false, // Default to false as we don't know yet
|
|
70
|
+
uniqueKey
|
|
71
|
+
);
|
|
60
72
|
}
|
|
61
73
|
|
|
62
74
|
/**
|
|
@@ -16,34 +16,41 @@ export abstract class BaseQueryRepository extends BaseRepository {
|
|
|
16
16
|
* Prevents duplicate queries and tracks quota usage
|
|
17
17
|
*
|
|
18
18
|
* @param collection - Collection name
|
|
19
|
-
* @param query - Firestore query
|
|
19
|
+
* @param query - Firestore query (kept for interface compatibility)
|
|
20
20
|
* @param queryFn - Function to execute the query
|
|
21
21
|
* @param cached - Whether the result is from cache
|
|
22
|
+
* @param uniqueKey - Unique key for deduplication (critical for correct caching)
|
|
22
23
|
* @returns Query result
|
|
23
24
|
*/
|
|
24
25
|
protected async executeQuery<T>(
|
|
25
26
|
collection: string,
|
|
26
|
-
|
|
27
|
+
_query: Query,
|
|
27
28
|
queryFn: () => Promise<T>,
|
|
28
29
|
cached: boolean = false,
|
|
30
|
+
uniqueKey?: string
|
|
29
31
|
): Promise<T> {
|
|
32
|
+
// FIX: query.toString() returns "[object Object]" which breaks deduplication
|
|
33
|
+
// We must rely on the caller providing a uniqueKey or fallback to a collection-based key (less efficient but safe)
|
|
34
|
+
const safeKey = uniqueKey || `${collection}_generic_query_${Date.now()}`;
|
|
35
|
+
|
|
30
36
|
const queryKey = {
|
|
31
37
|
collection,
|
|
32
|
-
filters:
|
|
38
|
+
filters: safeKey, // Use the unique key as the filter identifier
|
|
33
39
|
limit: undefined,
|
|
34
40
|
orderBy: undefined,
|
|
35
41
|
};
|
|
36
42
|
|
|
37
43
|
return queryDeduplicationMiddleware.deduplicate(queryKey, async () => {
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
44
|
+
// Execute the query function
|
|
45
|
+
const result = await queryFn();
|
|
46
|
+
|
|
47
|
+
// Track the operation after successful execution
|
|
48
|
+
// We calculate count based on result if possible, otherwise default to 1 (for list/count queries)
|
|
49
|
+
const count = Array.isArray(result) ? result.length : 1;
|
|
50
|
+
|
|
51
|
+
this.trackRead(collection, count, cached);
|
|
52
|
+
|
|
53
|
+
return result;
|
|
47
54
|
});
|
|
48
55
|
}
|
|
49
56
|
|
|
@@ -90,3 +90,35 @@ export function createErrorResult<T>(message: string, code: string): FirestoreRe
|
|
|
90
90
|
export function createSuccessResult<T>(data?: T): FirestoreResult<T> {
|
|
91
91
|
return { success: true, data };
|
|
92
92
|
}
|
|
93
|
+
|
|
94
|
+
// ---------------------------------------------------------------------------
|
|
95
|
+
// Transaction & Timestamp Wrappers (Facade Pattern)
|
|
96
|
+
// ---------------------------------------------------------------------------
|
|
97
|
+
|
|
98
|
+
import {
|
|
99
|
+
runTransaction as fbRunTransaction,
|
|
100
|
+
serverTimestamp as fbServerTimestamp,
|
|
101
|
+
type Transaction
|
|
102
|
+
} from "firebase/firestore";
|
|
103
|
+
|
|
104
|
+
/**
|
|
105
|
+
* Execute a transaction with automatic DB instance check.
|
|
106
|
+
* Wraps the Firebase runTransaction to ensure the DB is initialized.
|
|
107
|
+
*/
|
|
108
|
+
export async function runTransaction<T>(
|
|
109
|
+
updateFunction: (transaction: Transaction) => Promise<T>
|
|
110
|
+
): Promise<T> {
|
|
111
|
+
const db = getDb();
|
|
112
|
+
if (!db) {
|
|
113
|
+
throw new Error("[runTransaction] Firestore not initialized");
|
|
114
|
+
}
|
|
115
|
+
return fbRunTransaction(db, updateFunction);
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
/**
|
|
119
|
+
* Get the server timestamp (Sentinel value).
|
|
120
|
+
* Wraps Firebase serverTimestamp to avoid direct dependency.
|
|
121
|
+
*/
|
|
122
|
+
export function serverTimestamp() {
|
|
123
|
+
return fbServerTimestamp();
|
|
124
|
+
}
|
package/src/index.ts
CHANGED
|
@@ -86,7 +86,16 @@ export {
|
|
|
86
86
|
export { BaseRepository } from "./firestore/infrastructure/repositories/BaseRepository";
|
|
87
87
|
export { FirestorePathResolver } from "./firestore/utils/path-resolver";
|
|
88
88
|
export { PaginationHelper } from "./firestore/utils/pagination.helper";
|
|
89
|
-
|
|
89
|
+
|
|
90
|
+
export { Timestamp } from "firebase/firestore";
|
|
91
|
+
export type {
|
|
92
|
+
Transaction,
|
|
93
|
+
DocumentReference,
|
|
94
|
+
WriteBatch,
|
|
95
|
+
DocumentSnapshot,
|
|
96
|
+
QuerySnapshot,
|
|
97
|
+
Firestore,
|
|
98
|
+
} from "firebase/firestore";
|
|
90
99
|
|
|
91
100
|
// Firestore Helper Utilities
|
|
92
101
|
export {
|
|
@@ -96,6 +105,8 @@ export {
|
|
|
96
105
|
withFirestoreBool,
|
|
97
106
|
createErrorResult,
|
|
98
107
|
createSuccessResult,
|
|
108
|
+
runTransaction,
|
|
109
|
+
serverTimestamp,
|
|
99
110
|
} from "./firestore/utils/firestore-helper";
|
|
100
111
|
export type { FirestoreResult, NoDbResult } from "./firestore/utils/firestore-helper";
|
|
101
112
|
|
|
@@ -37,6 +37,7 @@ function getEnvValue(key: ConfigKey): string {
|
|
|
37
37
|
*/
|
|
38
38
|
function loadExpoConfig(): Record<string, string> {
|
|
39
39
|
try {
|
|
40
|
+
// eslint-disable-next-line @typescript-eslint/no-require-imports
|
|
40
41
|
const Constants = require('expo-constants');
|
|
41
42
|
const expoConfig = Constants?.expoConfig || Constants?.default?.expoConfig;
|
|
42
43
|
return expoConfig?.extra || {};
|