@umituz/react-native-firebase 3.0.5 → 3.0.6
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/domains/account-deletion/infrastructure/services/account-deletion.service.ts +10 -1
- package/src/domains/auth/infrastructure/stores/auth.store.ts +4 -1
- package/src/domains/auth/presentation/hooks/useAnonymousAuth.ts +3 -1
- package/src/domains/auth/presentation/hooks/utils/auth-state-change.handler.ts +5 -11
- package/src/domains/firestore/index.ts +1 -2
- package/src/domains/firestore/infrastructure/middleware/QueryDeduplicationMiddleware.ts +0 -6
- package/src/domains/firestore/infrastructure/middleware/QuotaTrackingMiddleware.ts +3 -6
- package/src/domains/firestore/infrastructure/repositories/BasePaginatedRepository.ts +3 -1
- package/src/domains/firestore/infrastructure/repositories/BaseRepository.ts +6 -6
- package/src/domains/firestore/infrastructure/services/RequestLoggerService.ts +6 -3
- package/src/domains/firestore/presentation/hooks/useFirestoreSnapshot.ts +2 -1
- package/src/domains/firestore/presentation/hooks/useSmartFirestoreSnapshot.ts +2 -1
- package/src/domains/firestore/utils/deduplication/pending-query-manager.util.ts +13 -6
- package/src/domains/firestore/utils/deduplication/query-key-generator.util.ts +8 -1
- package/src/domains/firestore/utils/pagination.helper.ts +5 -2
- package/src/domains/firestore/utils/transaction/transaction.util.ts +8 -2
- package/src/index.ts +325 -5
- package/src/shared/domain/utils/error-handlers/error-messages.ts +0 -4
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@umituz/react-native-firebase",
|
|
3
|
-
"version": "3.0.
|
|
3
|
+
"version": "3.0.6",
|
|
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",
|
|
@@ -175,7 +175,16 @@ async function attemptReauth(user: User, options: AccountDeletionOptions, origin
|
|
|
175
175
|
if (res.success) {
|
|
176
176
|
try {
|
|
177
177
|
const postReauthAuth = getFirebaseAuth();
|
|
178
|
-
|
|
178
|
+
// FIX: Explicit null check - don't fallback to user if auth state changed
|
|
179
|
+
if (!postReauthAuth?.currentUser) {
|
|
180
|
+
return {
|
|
181
|
+
success: false,
|
|
182
|
+
error: { code: 'auth/user-changed', message: 'User changed during reauthentication' },
|
|
183
|
+
requiresReauth: false
|
|
184
|
+
};
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
const currentUser = postReauthAuth.currentUser;
|
|
179
188
|
|
|
180
189
|
if (originalUserId) {
|
|
181
190
|
const validationCheck = validateUserUnchanged(postReauthAuth, originalUserId);
|
|
@@ -82,7 +82,10 @@ export const useFirebaseAuthStore = createStore<AuthState, AuthActions>({
|
|
|
82
82
|
unsubscribe = null;
|
|
83
83
|
}
|
|
84
84
|
setupInProgress = false;
|
|
85
|
-
|
|
85
|
+
// Only decrement if we successfully incremented (wasn't already set up)
|
|
86
|
+
if (state.listenerSetup === false && !unsubscribe) {
|
|
87
|
+
activeComponentCount--;
|
|
88
|
+
}
|
|
86
89
|
set({ listenerSetup: false, loading: false });
|
|
87
90
|
throw error; // Re-throw to allow caller to handle
|
|
88
91
|
}
|
|
@@ -87,9 +87,11 @@ export function useAnonymousAuth(auth: Auth | null): UseAnonymousAuthResult {
|
|
|
87
87
|
|
|
88
88
|
try {
|
|
89
89
|
// Listen to auth state changes
|
|
90
|
-
|
|
90
|
+
// FIX: Capture return value for proper cleanup
|
|
91
|
+
const unsubscribe = onAuthStateChanged(auth, (user) => {
|
|
91
92
|
handleAuthStateChange(user);
|
|
92
93
|
});
|
|
94
|
+
unsubscribeRef.current = unsubscribe;
|
|
93
95
|
} catch (err) {
|
|
94
96
|
const authError = err instanceof Error ? err : new Error('Auth listener setup failed');
|
|
95
97
|
setError(authError);
|
|
@@ -30,17 +30,11 @@ export function createAuthStateChangeHandler(
|
|
|
30
30
|
const { setAuthState, setLoading, setError } = params;
|
|
31
31
|
|
|
32
32
|
return (user: User | null) => {
|
|
33
|
-
try
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
const authError =
|
|
39
|
-
err instanceof Error ? err : new Error('Auth state check failed');
|
|
40
|
-
setError(authError);
|
|
41
|
-
} finally {
|
|
42
|
-
setLoading(false);
|
|
43
|
-
}
|
|
33
|
+
// FIX: Removed unnecessary try-catch - createAuthCheckResult cannot throw
|
|
34
|
+
const authState = createAuthCheckResult(user);
|
|
35
|
+
setAuthState(authState);
|
|
36
|
+
setError(null);
|
|
37
|
+
setLoading(false);
|
|
44
38
|
};
|
|
45
39
|
}
|
|
46
40
|
|
|
@@ -89,7 +89,7 @@ export {
|
|
|
89
89
|
isRetryableError,
|
|
90
90
|
} from '../../shared/domain/utils/error-handlers/error-checkers';
|
|
91
91
|
export {
|
|
92
|
-
|
|
92
|
+
ERROR_MESSAGES,
|
|
93
93
|
} from '../../shared/domain/utils/error-handlers/error-messages';
|
|
94
94
|
|
|
95
95
|
// Middleware
|
|
@@ -97,7 +97,6 @@ export {
|
|
|
97
97
|
QueryDeduplicationMiddleware,
|
|
98
98
|
queryDeduplicationMiddleware,
|
|
99
99
|
syncDeduplicationWithQuota,
|
|
100
|
-
useDeduplicationWithQuota,
|
|
101
100
|
} from './infrastructure/middleware/QueryDeduplicationMiddleware';
|
|
102
101
|
export type {
|
|
103
102
|
QueryDeduplicationConfig,
|
|
@@ -304,9 +304,3 @@ export function syncDeduplicationWithQuota(
|
|
|
304
304
|
const quotaPercentage = counts.reads / quotaLimits.dailyReadLimit;
|
|
305
305
|
deduplication.adjustWindowForQuota(quotaPercentage);
|
|
306
306
|
}
|
|
307
|
-
|
|
308
|
-
/**
|
|
309
|
-
* @deprecated Use syncDeduplicationWithQuota instead (not a hook)
|
|
310
|
-
* This will be removed in a future version
|
|
311
|
-
*/
|
|
312
|
-
export const useDeduplicationWithQuota = syncDeduplicationWithQuota;
|
|
@@ -43,11 +43,10 @@ export class QuotaTrackingMiddleware {
|
|
|
43
43
|
|
|
44
44
|
/**
|
|
45
45
|
* Track read operation
|
|
46
|
-
* @param _collection - Collection name (reserved for future per-collection tracking)
|
|
47
46
|
* @param count - Number of documents read
|
|
48
47
|
* @param cached - Whether result was from cache
|
|
49
48
|
*/
|
|
50
|
-
trackRead(
|
|
49
|
+
trackRead(count: number = 1, cached: boolean = false): void {
|
|
51
50
|
if (!cached) {
|
|
52
51
|
this.readCount += count;
|
|
53
52
|
}
|
|
@@ -55,19 +54,17 @@ export class QuotaTrackingMiddleware {
|
|
|
55
54
|
|
|
56
55
|
/**
|
|
57
56
|
* Track write operation
|
|
58
|
-
* @param _collection - Collection name (reserved for future per-collection tracking)
|
|
59
57
|
* @param count - Number of documents written
|
|
60
58
|
*/
|
|
61
|
-
trackWrite(
|
|
59
|
+
trackWrite(count: number = 1): void {
|
|
62
60
|
this.writeCount += count;
|
|
63
61
|
}
|
|
64
62
|
|
|
65
63
|
/**
|
|
66
64
|
* Track delete operation
|
|
67
|
-
* @param _collection - Collection name (reserved for future per-collection tracking)
|
|
68
65
|
* @param count - Number of documents deleted
|
|
69
66
|
*/
|
|
70
|
-
trackDelete(
|
|
67
|
+
trackDelete(count: number = 1): void {
|
|
71
68
|
this.deleteCount += count;
|
|
72
69
|
}
|
|
73
70
|
|
|
@@ -78,7 +78,9 @@ export abstract class BasePaginatedRepository extends BaseQueryRepository {
|
|
|
78
78
|
}
|
|
79
79
|
|
|
80
80
|
// Generate a unique key for deduplication (after cursor is resolved)
|
|
81
|
-
|
|
81
|
+
// FIX: Escape cursor to prevent key collisions from special characters
|
|
82
|
+
const escapedCursor = cursorKey.replace(/[|]/g, '_');
|
|
83
|
+
const uniqueKey = `${collectionName}_list_${orderByField}_${orderDirection}_${fetchLimit}_${escapedCursor}`;
|
|
82
84
|
|
|
83
85
|
return this.executeQuery(
|
|
84
86
|
collectionName,
|
|
@@ -120,7 +120,7 @@ export abstract class BaseRepository implements IPathResolver {
|
|
|
120
120
|
/**
|
|
121
121
|
* Track read operation for quota monitoring
|
|
122
122
|
*
|
|
123
|
-
* @param collection - Collection name
|
|
123
|
+
* @param collection - Collection name (for documentation purposes)
|
|
124
124
|
* @param count - Number of documents read
|
|
125
125
|
* @param cached - Whether the result is from cache
|
|
126
126
|
*/
|
|
@@ -129,33 +129,33 @@ export abstract class BaseRepository implements IPathResolver {
|
|
|
129
129
|
count: number = 1,
|
|
130
130
|
cached: boolean = false,
|
|
131
131
|
): void {
|
|
132
|
-
quotaTrackingMiddleware.trackRead(
|
|
132
|
+
quotaTrackingMiddleware.trackRead(count, cached);
|
|
133
133
|
}
|
|
134
134
|
|
|
135
135
|
/**
|
|
136
136
|
* Track write operation for quota monitoring
|
|
137
137
|
*
|
|
138
|
-
* @param collection - Collection name
|
|
138
|
+
* @param collection - Collection name (for documentation purposes)
|
|
139
139
|
* @param count - Number of documents written
|
|
140
140
|
*/
|
|
141
141
|
protected trackWrite(
|
|
142
142
|
collection: string,
|
|
143
143
|
count: number = 1,
|
|
144
144
|
): void {
|
|
145
|
-
quotaTrackingMiddleware.trackWrite(
|
|
145
|
+
quotaTrackingMiddleware.trackWrite(count);
|
|
146
146
|
}
|
|
147
147
|
|
|
148
148
|
/**
|
|
149
149
|
* Track delete operation for quota monitoring
|
|
150
150
|
*
|
|
151
|
-
* @param collection - Collection name
|
|
151
|
+
* @param collection - Collection name (for documentation purposes)
|
|
152
152
|
* @param count - Number of documents deleted
|
|
153
153
|
*/
|
|
154
154
|
protected trackDelete(
|
|
155
155
|
collection: string,
|
|
156
156
|
count: number = 1,
|
|
157
157
|
): void {
|
|
158
|
-
quotaTrackingMiddleware.trackDelete(
|
|
158
|
+
quotaTrackingMiddleware.trackDelete(count);
|
|
159
159
|
}
|
|
160
160
|
|
|
161
161
|
/**
|
|
@@ -43,9 +43,11 @@ export class RequestLoggerService {
|
|
|
43
43
|
|
|
44
44
|
/**
|
|
45
45
|
* Get all logs
|
|
46
|
+
* PERF: Return array directly without copy - logs is private and immutable from outside
|
|
47
|
+
* Callers should not modify the returned array.
|
|
46
48
|
*/
|
|
47
49
|
getLogs(): RequestLog[] {
|
|
48
|
-
return
|
|
50
|
+
return this.logs;
|
|
49
51
|
}
|
|
50
52
|
|
|
51
53
|
/**
|
|
@@ -144,9 +146,10 @@ export class RequestLoggerService {
|
|
|
144
146
|
|
|
145
147
|
/**
|
|
146
148
|
* Notify all listeners
|
|
149
|
+
* PERF: Use for...of instead of forEach for better performance
|
|
147
150
|
*/
|
|
148
151
|
private notifyListeners(log: RequestLog): void {
|
|
149
|
-
this.listeners
|
|
152
|
+
for (const listener of this.listeners) {
|
|
150
153
|
try {
|
|
151
154
|
listener(log);
|
|
152
155
|
} catch (error) {
|
|
@@ -157,7 +160,7 @@ export class RequestLoggerService {
|
|
|
157
160
|
console.warn(`${RequestLoggerService.LISTENER_ERROR_PREFIX} ${errorMessage}`);
|
|
158
161
|
}
|
|
159
162
|
}
|
|
160
|
-
}
|
|
163
|
+
}
|
|
161
164
|
}
|
|
162
165
|
}
|
|
163
166
|
|
|
@@ -50,7 +50,8 @@ export function useFirestoreSnapshot<TData>(
|
|
|
50
50
|
const timeoutRef = useRef<ReturnType<typeof setTimeout> | null>(null);
|
|
51
51
|
|
|
52
52
|
// Stabilize queryKey to prevent unnecessary listener re-subscriptions
|
|
53
|
-
|
|
53
|
+
// PERF: Memoize stringified key to avoid expensive JSON.stringify on every render
|
|
54
|
+
const stableKeyString = useMemo(() => JSON.stringify(queryKey), [queryKey]);
|
|
54
55
|
const stableQueryKey = useMemo(() => queryKey, [stableKeyString]);
|
|
55
56
|
|
|
56
57
|
useEffect(() => {
|
|
@@ -119,7 +119,8 @@ export function useSmartFirestoreSnapshot<TData>(
|
|
|
119
119
|
});
|
|
120
120
|
|
|
121
121
|
// Stabilize queryKey to prevent unnecessary listener re-subscriptions
|
|
122
|
-
|
|
122
|
+
// PERF: Memoize stringified key to avoid expensive JSON.stringify on every render
|
|
123
|
+
const stableKeyString = useMemo(() => JSON.stringify(queryKey), [queryKey]);
|
|
123
124
|
const stableQueryKey = useMemo(() => queryKey, [stableKeyString]);
|
|
124
125
|
|
|
125
126
|
/**
|
|
@@ -38,7 +38,9 @@ export class PendingQueryManager {
|
|
|
38
38
|
const pending = this.pendingQueries.get(key);
|
|
39
39
|
if (!pending) return false;
|
|
40
40
|
|
|
41
|
-
|
|
41
|
+
// PERF: Cache Date.now() to avoid multiple calls in hot path
|
|
42
|
+
const now = Date.now();
|
|
43
|
+
const age = now - pending.timestamp;
|
|
42
44
|
if (age > this.deduplicationWindowMs) {
|
|
43
45
|
this.pendingQueries.delete(key);
|
|
44
46
|
return false;
|
|
@@ -61,17 +63,22 @@ export class PendingQueryManager {
|
|
|
61
63
|
* Also attaches cleanup handlers to prevent memory leaks.
|
|
62
64
|
*/
|
|
63
65
|
add(key: string, promise: Promise<unknown>): void {
|
|
66
|
+
// PERF: Cache timestamp to avoid multiple Date.now() calls
|
|
67
|
+
const now = Date.now();
|
|
68
|
+
|
|
69
|
+
// Set first, then attach cleanup handler to prevent race condition
|
|
70
|
+
// where immediately-resolved promise triggers cleanup before set()
|
|
71
|
+
this.pendingQueries.set(key, {
|
|
72
|
+
promise,
|
|
73
|
+
timestamp: now,
|
|
74
|
+
});
|
|
75
|
+
|
|
64
76
|
// Attach cleanup handler to ensure query is removed from map
|
|
65
77
|
// even if caller's finally block doesn't execute (e.g., unhandled rejection)
|
|
66
78
|
promise.finally(() => {
|
|
67
79
|
// Immediate cleanup - no delay needed for better performance
|
|
68
80
|
this.pendingQueries.delete(key);
|
|
69
81
|
});
|
|
70
|
-
|
|
71
|
-
this.pendingQueries.set(key, {
|
|
72
|
-
promise,
|
|
73
|
-
timestamp: Date.now(),
|
|
74
|
-
});
|
|
75
82
|
}
|
|
76
83
|
|
|
77
84
|
/**
|
|
@@ -13,9 +13,16 @@ export interface QueryKey {
|
|
|
13
13
|
/**
|
|
14
14
|
* Escape special characters in query key components
|
|
15
15
|
* Prevents key collisions when filter strings contain separator characters
|
|
16
|
+
* FIX: Escape ALL special characters that could cause issues, not just % and |
|
|
16
17
|
*/
|
|
17
18
|
function escapeKeyComponent(component: string): string {
|
|
18
|
-
return component
|
|
19
|
+
return component
|
|
20
|
+
.replace(/%/g, '%25')
|
|
21
|
+
.replace(/\|/g, '%7C')
|
|
22
|
+
.replace(/\n/g, '%0A')
|
|
23
|
+
.replace(/\r/g, '%0D')
|
|
24
|
+
.replace(/\0/g, '%00')
|
|
25
|
+
.replace(/\//g, '%2F');
|
|
19
26
|
}
|
|
20
27
|
|
|
21
28
|
/**
|
|
@@ -49,8 +49,11 @@ export class PaginationHelper<T> {
|
|
|
49
49
|
let nextCursor: string | null = null;
|
|
50
50
|
if (hasMoreValue && resultItems.length > 0) {
|
|
51
51
|
// Access is safe because we checked length > 0
|
|
52
|
-
const
|
|
53
|
-
|
|
52
|
+
const lastIndex = resultItems.length - 1;
|
|
53
|
+
const lastItem = resultItems[lastIndex];
|
|
54
|
+
if (lastItem) {
|
|
55
|
+
nextCursor = getCursor(lastItem);
|
|
56
|
+
}
|
|
54
57
|
}
|
|
55
58
|
|
|
56
59
|
return {
|
|
@@ -31,10 +31,16 @@ export async function runTransaction<T>(
|
|
|
31
31
|
const errorCode = hasCodeProperty(error) ? error.code : 'unknown';
|
|
32
32
|
|
|
33
33
|
if (isQuotaError(error)) {
|
|
34
|
-
|
|
34
|
+
// FIX: Preserve original error by adding it as a custom property
|
|
35
|
+
const quotaError = new Error(`[runTransaction] ${ERROR_MESSAGES.FIRESTORE.QUOTA_EXCEEDED}: ${errorMessage} (Code: ${errorCode})`);
|
|
36
|
+
(quotaError as any).originalError = error;
|
|
37
|
+
throw quotaError;
|
|
35
38
|
}
|
|
36
39
|
|
|
37
|
-
|
|
40
|
+
// FIX: Preserve original error for debugging
|
|
41
|
+
const transactionError = new Error(`[runTransaction] Transaction failed: ${errorMessage} (Code: ${errorCode})`);
|
|
42
|
+
(transactionError as any).originalError = error;
|
|
43
|
+
throw transactionError;
|
|
38
44
|
}
|
|
39
45
|
}
|
|
40
46
|
|
package/src/index.ts
CHANGED
|
@@ -46,12 +46,332 @@ export {
|
|
|
46
46
|
getSafeErrorCode,
|
|
47
47
|
} from "./shared/domain/guards/firebase-error.guard";
|
|
48
48
|
|
|
49
|
-
//
|
|
50
|
-
|
|
51
|
-
|
|
49
|
+
// =============================================================================
|
|
50
|
+
// AUTH DOMAIN EXPORTS
|
|
51
|
+
// =============================================================================
|
|
52
52
|
|
|
53
|
-
//
|
|
54
|
-
export
|
|
53
|
+
// Domain Layer
|
|
54
|
+
export type { FirebaseAuthConfig } from './domains/auth/domain/value-objects/FirebaseAuthConfig';
|
|
55
|
+
export {
|
|
56
|
+
isAnonymousUser,
|
|
57
|
+
} from './domains/auth/domain/entities/AnonymousUser';
|
|
58
|
+
export type { AnonymousUser } from './domains/auth/domain/entities/AnonymousUser';
|
|
59
|
+
|
|
60
|
+
// Infrastructure Layer - Config
|
|
61
|
+
export {
|
|
62
|
+
getFirebaseAuth,
|
|
63
|
+
isFirebaseAuthInitialized,
|
|
64
|
+
getFirebaseAuthInitializationError,
|
|
65
|
+
resetFirebaseAuthClient,
|
|
66
|
+
firebaseAuthClient,
|
|
67
|
+
initializeFirebaseAuth,
|
|
68
|
+
} from './domains/auth/infrastructure/config/FirebaseAuthClient';
|
|
69
|
+
export type { Auth } from './domains/auth/infrastructure/config/FirebaseAuthClient';
|
|
70
|
+
|
|
71
|
+
// Infrastructure Layer - Services
|
|
72
|
+
export {
|
|
73
|
+
checkAuthState,
|
|
74
|
+
isAuthenticated,
|
|
75
|
+
isAnonymous,
|
|
76
|
+
getCurrentUserId,
|
|
77
|
+
getCurrentUser,
|
|
78
|
+
getCurrentUserIdFromGlobal,
|
|
79
|
+
getCurrentUserFromGlobal,
|
|
80
|
+
isCurrentUserAuthenticated,
|
|
81
|
+
isCurrentUserAnonymous,
|
|
82
|
+
verifyUserId,
|
|
83
|
+
isValidUser,
|
|
84
|
+
} from './domains/auth/infrastructure/services/auth-utils.service';
|
|
85
|
+
export type { AuthCheckResult } from './domains/auth/infrastructure/services/auth-utils.service';
|
|
86
|
+
|
|
87
|
+
export {
|
|
88
|
+
AnonymousAuthService,
|
|
89
|
+
anonymousAuthService,
|
|
90
|
+
} from './domains/auth/infrastructure/services/anonymous-auth.service';
|
|
91
|
+
export type {
|
|
92
|
+
AnonymousAuthResult,
|
|
93
|
+
AnonymousAuthServiceInterface,
|
|
94
|
+
} from './domains/auth/infrastructure/services/anonymous-auth.service';
|
|
95
|
+
|
|
96
|
+
export {
|
|
97
|
+
shouldSkipFirestoreQuery,
|
|
98
|
+
createFirestoreQueryOptions,
|
|
99
|
+
} from './domains/auth/infrastructure/services/firestore-utils.service';
|
|
100
|
+
export type {
|
|
101
|
+
FirestoreQueryOptions,
|
|
102
|
+
FirestoreQueryResult,
|
|
103
|
+
FirestoreQuerySkipReason,
|
|
104
|
+
} from './domains/auth/infrastructure/services/firestore-utils.service';
|
|
105
|
+
|
|
106
|
+
// Social Auth Services
|
|
107
|
+
export {
|
|
108
|
+
GoogleAuthService,
|
|
109
|
+
googleAuthService,
|
|
110
|
+
} from './domains/auth/infrastructure/services/google-auth.service';
|
|
111
|
+
export type {
|
|
112
|
+
GoogleAuthConfig,
|
|
113
|
+
GoogleAuthResult,
|
|
114
|
+
} from './domains/auth/infrastructure/services/google-auth.types';
|
|
115
|
+
|
|
116
|
+
export {
|
|
117
|
+
GoogleOAuthService,
|
|
118
|
+
googleOAuthService,
|
|
119
|
+
} from './domains/auth/infrastructure/services/google-oauth.service';
|
|
120
|
+
export type { GoogleOAuthConfig } from './domains/auth/infrastructure/services/google-oauth.service';
|
|
121
|
+
|
|
122
|
+
export {
|
|
123
|
+
AppleAuthService,
|
|
124
|
+
appleAuthService,
|
|
125
|
+
} from './domains/auth/infrastructure/services/apple-auth.service';
|
|
126
|
+
export type { AppleAuthResult } from './domains/auth/infrastructure/services/apple-auth.types';
|
|
127
|
+
|
|
128
|
+
// Password & Email/Password Auth
|
|
129
|
+
export {
|
|
130
|
+
updateUserPassword,
|
|
131
|
+
} from './domains/auth/infrastructure/services/password.service';
|
|
132
|
+
|
|
133
|
+
export {
|
|
134
|
+
signInWithEmail,
|
|
135
|
+
signUpWithEmail,
|
|
136
|
+
signOut,
|
|
137
|
+
linkAnonymousWithEmail,
|
|
138
|
+
} from './domains/auth/infrastructure/services/email-auth.service';
|
|
139
|
+
export type {
|
|
140
|
+
EmailCredentials,
|
|
141
|
+
EmailAuthResult,
|
|
142
|
+
} from './domains/auth/infrastructure/services/email-auth.service';
|
|
143
|
+
|
|
144
|
+
// Auth Listener
|
|
145
|
+
export {
|
|
146
|
+
setupAuthListener,
|
|
147
|
+
} from './domains/auth/infrastructure/services/auth-listener.service';
|
|
148
|
+
export type {
|
|
149
|
+
AuthListenerConfig,
|
|
150
|
+
AuthListenerResult,
|
|
151
|
+
} from './domains/auth/infrastructure/services/auth-listener.service';
|
|
152
|
+
|
|
153
|
+
// User Document Service
|
|
154
|
+
export {
|
|
155
|
+
ensureUserDocument,
|
|
156
|
+
markUserDeleted,
|
|
157
|
+
configureUserDocumentService,
|
|
158
|
+
} from './domains/auth/infrastructure/services/user-document.service';
|
|
159
|
+
export type {
|
|
160
|
+
UserDocumentUser,
|
|
161
|
+
UserDocumentConfig,
|
|
162
|
+
UserDocumentExtras,
|
|
163
|
+
} from './domains/auth/infrastructure/services/user-document.types';
|
|
164
|
+
|
|
165
|
+
// Presentation Layer - Hooks
|
|
166
|
+
export { useFirebaseAuth } from './domains/auth/presentation/hooks/useFirebaseAuth';
|
|
167
|
+
export type { UseFirebaseAuthResult } from './domains/auth/presentation/hooks/useFirebaseAuth';
|
|
168
|
+
|
|
169
|
+
export { useAnonymousAuth } from './domains/auth/presentation/hooks/useAnonymousAuth';
|
|
170
|
+
export type { UseAnonymousAuthResult } from './domains/auth/presentation/hooks/useAnonymousAuth';
|
|
171
|
+
|
|
172
|
+
export { useSocialAuth } from './domains/auth/presentation/hooks/useSocialAuth';
|
|
173
|
+
export type {
|
|
174
|
+
SocialAuthConfig,
|
|
175
|
+
SocialAuthResult,
|
|
176
|
+
UseSocialAuthResult,
|
|
177
|
+
} from './domains/auth/presentation/hooks/useSocialAuth';
|
|
178
|
+
|
|
179
|
+
export { useGoogleOAuth } from './domains/auth/presentation/hooks/useGoogleOAuth';
|
|
180
|
+
export type { UseGoogleOAuthResult } from './domains/auth/presentation/hooks/useGoogleOAuth';
|
|
181
|
+
|
|
182
|
+
// =============================================================================
|
|
183
|
+
// ACCOUNT DELETION DOMAIN EXPORTS
|
|
184
|
+
// =============================================================================
|
|
185
|
+
|
|
186
|
+
export {
|
|
187
|
+
deleteCurrentUser,
|
|
188
|
+
deleteUserAccount,
|
|
189
|
+
} from './domains/account-deletion/infrastructure/services/account-deletion.service';
|
|
190
|
+
export type { AccountDeletionResult } from './domains/account-deletion/infrastructure/services/account-deletion.service';
|
|
191
|
+
|
|
192
|
+
export type {
|
|
193
|
+
AccountDeletionOptions,
|
|
194
|
+
ReauthenticationResult,
|
|
195
|
+
AuthProviderType,
|
|
196
|
+
ReauthCredentialResult,
|
|
197
|
+
} from './domains/account-deletion/application/ports/reauthentication.types';
|
|
198
|
+
|
|
199
|
+
export {
|
|
200
|
+
getUserAuthProvider,
|
|
201
|
+
reauthenticateWithPassword,
|
|
202
|
+
reauthenticateWithGoogle,
|
|
203
|
+
reauthenticateWithApple,
|
|
204
|
+
getAppleReauthCredential,
|
|
205
|
+
} from './domains/account-deletion/infrastructure/services/reauthentication.service';
|
|
206
|
+
|
|
207
|
+
// =============================================================================
|
|
208
|
+
// FIRESTORE DOMAIN EXPORTS
|
|
209
|
+
// =============================================================================
|
|
210
|
+
|
|
211
|
+
// Domain Errors
|
|
212
|
+
export {
|
|
213
|
+
FirebaseFirestoreError,
|
|
214
|
+
FirebaseFirestoreInitializationError,
|
|
215
|
+
FirebaseFirestoreQuotaError,
|
|
216
|
+
} from './domains/firestore/domain/errors/FirebaseFirestoreError';
|
|
217
|
+
|
|
218
|
+
// Firestore Client
|
|
219
|
+
export {
|
|
220
|
+
initializeFirestore,
|
|
221
|
+
getFirestore,
|
|
222
|
+
isFirestoreInitialized,
|
|
223
|
+
getFirestoreInitializationError,
|
|
224
|
+
resetFirestoreClient,
|
|
225
|
+
firestoreClient,
|
|
226
|
+
} from './domains/firestore/infrastructure/config/FirestoreClient';
|
|
227
|
+
export type { Firestore } from './domains/firestore/infrastructure/config/FirestoreClient';
|
|
228
|
+
|
|
229
|
+
// Repositories
|
|
230
|
+
export { BaseRepository } from './domains/firestore/infrastructure/repositories/BaseRepository';
|
|
231
|
+
export type { IPathResolver } from './domains/firestore/infrastructure/repositories/BaseRepository';
|
|
232
|
+
export { BaseQueryRepository } from './domains/firestore/infrastructure/repositories/BaseQueryRepository';
|
|
233
|
+
export { BasePaginatedRepository } from './domains/firestore/infrastructure/repositories/BasePaginatedRepository';
|
|
234
|
+
|
|
235
|
+
// Date Utilities
|
|
236
|
+
export {
|
|
237
|
+
isoToTimestamp,
|
|
238
|
+
timestampToISO,
|
|
239
|
+
timestampToDate,
|
|
240
|
+
getCurrentISOString,
|
|
241
|
+
formatRelativeTime,
|
|
242
|
+
} from './domains/firestore/utils/dateUtils';
|
|
243
|
+
export type { RelativeTimeLabels } from './domains/firestore/utils/dateUtils';
|
|
244
|
+
|
|
245
|
+
// Query Builder
|
|
246
|
+
export {
|
|
247
|
+
buildQuery,
|
|
248
|
+
createInFilter,
|
|
249
|
+
createEqualFilter,
|
|
250
|
+
} from './domains/firestore/utils/query-builder';
|
|
251
|
+
export type {
|
|
252
|
+
QueryBuilderOptions,
|
|
253
|
+
FieldFilter,
|
|
254
|
+
} from './domains/firestore/utils/query-builder';
|
|
255
|
+
|
|
256
|
+
// Pagination
|
|
257
|
+
export {
|
|
258
|
+
PaginationHelper,
|
|
259
|
+
createPaginationHelper,
|
|
260
|
+
} from './domains/firestore/utils/pagination.helper';
|
|
261
|
+
export type {
|
|
262
|
+
PaginatedResult,
|
|
263
|
+
PaginationParams,
|
|
264
|
+
} from './domains/firestore/types/pagination.types';
|
|
265
|
+
export { EMPTY_PAGINATED_RESULT } from './domains/firestore/types/pagination.types';
|
|
266
|
+
|
|
267
|
+
// Domain Constants
|
|
268
|
+
export {
|
|
269
|
+
FREE_TIER_LIMITS,
|
|
270
|
+
QUOTA_THRESHOLDS,
|
|
271
|
+
calculateQuotaUsage,
|
|
272
|
+
isQuotaThresholdReached,
|
|
273
|
+
getRemainingQuota,
|
|
274
|
+
} from './domains/firestore/domain/constants/QuotaLimits';
|
|
275
|
+
|
|
276
|
+
// Domain Entities
|
|
277
|
+
export type {
|
|
278
|
+
QuotaMetrics,
|
|
279
|
+
QuotaLimits,
|
|
280
|
+
QuotaStatus,
|
|
281
|
+
} from './domains/firestore/domain/entities/QuotaMetrics';
|
|
282
|
+
export type {
|
|
283
|
+
RequestLog,
|
|
284
|
+
RequestStats,
|
|
285
|
+
RequestType,
|
|
286
|
+
} from './domains/firestore/domain/entities/RequestLog';
|
|
287
|
+
|
|
288
|
+
// Domain Services
|
|
289
|
+
export { QuotaCalculator } from './domains/firestore/domain/services/QuotaCalculator';
|
|
290
|
+
|
|
291
|
+
// Quota Error Detection
|
|
292
|
+
export {
|
|
293
|
+
isQuotaError,
|
|
294
|
+
isRetryableError,
|
|
295
|
+
} from './shared/domain/utils/error-handlers/error-checkers';
|
|
296
|
+
export {
|
|
297
|
+
ERROR_MESSAGES,
|
|
298
|
+
} from './shared/domain/utils/error-handlers/error-messages';
|
|
299
|
+
|
|
300
|
+
// Middleware
|
|
301
|
+
export {
|
|
302
|
+
QueryDeduplicationMiddleware,
|
|
303
|
+
queryDeduplicationMiddleware,
|
|
304
|
+
syncDeduplicationWithQuota,
|
|
305
|
+
} from './domains/firestore/infrastructure/middleware/QueryDeduplicationMiddleware';
|
|
306
|
+
export type {
|
|
307
|
+
QueryDeduplicationConfig,
|
|
308
|
+
DeduplicationStatistics,
|
|
309
|
+
} from './domains/firestore/infrastructure/middleware/QueryDeduplicationMiddleware';
|
|
310
|
+
export {
|
|
311
|
+
QuotaTrackingMiddleware,
|
|
312
|
+
quotaTrackingMiddleware,
|
|
313
|
+
} from './domains/firestore/infrastructure/middleware/QuotaTrackingMiddleware';
|
|
314
|
+
|
|
315
|
+
// Services
|
|
316
|
+
export {
|
|
317
|
+
RequestLoggerService,
|
|
318
|
+
requestLoggerService,
|
|
319
|
+
} from './domains/firestore/infrastructure/services/RequestLoggerService';
|
|
320
|
+
|
|
321
|
+
// Firestore Helper Utilities
|
|
322
|
+
export {
|
|
323
|
+
withFirestore,
|
|
324
|
+
withFirestoreVoid,
|
|
325
|
+
withFirestoreBool,
|
|
326
|
+
} from './domains/firestore/utils/operation/operation-executor.util';
|
|
327
|
+
export {
|
|
328
|
+
runTransaction,
|
|
329
|
+
serverTimestamp,
|
|
330
|
+
} from './domains/firestore/utils/transaction/transaction.util';
|
|
331
|
+
export {
|
|
332
|
+
createErrorResult,
|
|
333
|
+
createSuccessResult,
|
|
334
|
+
} from './domains/firestore/utils/result/result.util';
|
|
335
|
+
export type { NoDbResult } from './domains/firestore/utils/result/result.util';
|
|
336
|
+
|
|
337
|
+
// Validation Utilities
|
|
338
|
+
export {
|
|
339
|
+
isValidCursor,
|
|
340
|
+
validateCursorOrThrow,
|
|
341
|
+
CursorValidationError,
|
|
342
|
+
} from './domains/firestore/utils/validation/cursor-validator.util';
|
|
343
|
+
export {
|
|
344
|
+
isValidFieldName,
|
|
345
|
+
} from './domains/firestore/utils/validation/field-validator.util';
|
|
346
|
+
export {
|
|
347
|
+
isValidDateRange,
|
|
348
|
+
validateDateRangeOrThrow,
|
|
349
|
+
} from './domains/firestore/utils/validation/date-validator.util';
|
|
350
|
+
|
|
351
|
+
// Presentation — TanStack Query integration
|
|
352
|
+
export { useFirestoreQuery } from './domains/firestore/presentation/hooks/useFirestoreQuery';
|
|
353
|
+
export { useFirestoreMutation } from './domains/firestore/presentation/hooks/useFirestoreMutation';
|
|
354
|
+
export { useFirestoreSnapshot } from './domains/firestore/presentation/hooks/useFirestoreSnapshot';
|
|
355
|
+
export { useSmartFirestoreSnapshot, useSmartListenerControl } from './domains/firestore/presentation/hooks/useSmartFirestoreSnapshot';
|
|
356
|
+
export { createFirestoreKeys } from './domains/firestore/presentation/query-keys/createFirestoreKeys';
|
|
357
|
+
|
|
358
|
+
export type { UseFirestoreQueryOptions } from './domains/firestore/presentation/hooks/useFirestoreQuery';
|
|
359
|
+
export type { UseFirestoreMutationOptions } from './domains/firestore/presentation/hooks/useFirestoreMutation';
|
|
360
|
+
export type { UseFirestoreSnapshotOptions } from './domains/firestore/presentation/hooks/useFirestoreSnapshot';
|
|
361
|
+
export type { UseSmartFirestoreSnapshotOptions, BackgroundStrategy } from './domains/firestore/presentation/hooks/useSmartFirestoreSnapshot';
|
|
362
|
+
|
|
363
|
+
// Firebase Types
|
|
364
|
+
export { Timestamp } from 'firebase/firestore';
|
|
365
|
+
export type {
|
|
366
|
+
CollectionReference,
|
|
367
|
+
QueryDocumentSnapshot,
|
|
368
|
+
DocumentData,
|
|
369
|
+
Transaction,
|
|
370
|
+
DocumentReference,
|
|
371
|
+
WriteBatch,
|
|
372
|
+
DocumentSnapshot,
|
|
373
|
+
QuerySnapshot,
|
|
374
|
+
} from 'firebase/firestore';
|
|
55
375
|
|
|
56
376
|
// Init Module Factory
|
|
57
377
|
export {
|