@umituz/react-native-firebase 2.6.0 → 2.6.2
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/application/auth/index.ts +42 -0
- package/src/application/auth/ports/AuthPort.ts.bak +164 -0
- package/src/application/auth/ports/AuthPort_part_aa +150 -0
- package/src/application/auth/ports/AuthPort_part_ab +14 -0
- package/src/application/auth/use-cases/SignInUseCase.ts.bak +253 -0
- package/src/application/auth/use-cases/SignInUseCaseHelpers.ts +0 -0
- package/src/application/auth/use-cases/SignInUseCaseMain.ts +0 -0
- package/src/application/auth/use-cases/SignInUseCase_part_aa +150 -0
- package/src/application/auth/use-cases/SignInUseCase_part_ab +103 -0
- package/src/application/auth/use-cases/SignOutUseCase.ts.bak +288 -0
- package/src/application/auth/use-cases/SignOutUseCaseCleanup.ts +0 -0
- package/src/application/auth/use-cases/SignOutUseCaseMain.ts +0 -0
- package/src/application/auth/use-cases/SignOutUseCase_part_aa +150 -0
- package/src/application/auth/use-cases/SignOutUseCase_part_ab +138 -0
- package/src/application/auth/use-cases/index.ts +26 -0
- package/src/domains/account-deletion/domain/index.ts +15 -0
- package/src/domains/account-deletion/domain/services/UserValidationHelpers.ts.bak +181 -0
- package/src/domains/account-deletion/domain/services/UserValidationHelpers_part_aa +150 -0
- package/src/domains/account-deletion/domain/services/UserValidationHelpers_part_ab +31 -0
- package/src/domains/account-deletion/domain/services/UserValidationService.ts.bak +286 -0
- package/src/domains/account-deletion/domain/services/UserValidationService_part_aa +150 -0
- package/src/domains/account-deletion/domain/services/UserValidationService_part_ab +136 -0
- package/src/domains/account-deletion/index.ts +43 -6
- package/src/domains/account-deletion/infrastructure/services/AccountDeletionExecutor.ts.bak +230 -0
- package/src/domains/account-deletion/infrastructure/services/AccountDeletionExecutor_part_aa +150 -0
- package/src/domains/account-deletion/infrastructure/services/AccountDeletionExecutor_part_ab +80 -0
- package/src/domains/account-deletion/infrastructure/services/AccountDeletionReauthHandler.ts.bak +174 -0
- package/src/domains/account-deletion/infrastructure/services/AccountDeletionReauthHandler_part_aa +150 -0
- package/src/domains/account-deletion/infrastructure/services/AccountDeletionReauthHandler_part_ab +24 -0
- package/src/domains/account-deletion/infrastructure/services/AccountDeletionRepository.ts.bak +266 -0
- package/src/domains/account-deletion/infrastructure/services/AccountDeletionRepository_part_aa +150 -0
- package/src/domains/account-deletion/infrastructure/services/AccountDeletionRepository_part_ab +116 -0
- package/src/domains/account-deletion/infrastructure/services/AccountDeletionTypes.ts +33 -0
- package/src/domains/account-deletion/infrastructure/services/account-deletion.service.ts +39 -227
- package/src/domains/account-deletion/infrastructure/services/reauthentication.service_part_aa +150 -0
- package/src/domains/account-deletion/infrastructure/services/reauthentication.service_part_ab +10 -0
- package/src/domains/auth/domain.ts +16 -0
- package/src/domains/auth/index.ts +7 -148
- package/src/domains/auth/infrastructure.ts.bak +156 -0
- package/src/domains/auth/infrastructure_part_aa +150 -0
- package/src/domains/auth/infrastructure_part_ab +6 -0
- package/src/domains/auth/presentation/hooks/GoogleOAuthHelpers.ts +0 -0
- package/src/domains/auth/presentation/hooks/GoogleOAuthHookService.ts.bak +247 -0
- package/src/domains/auth/presentation/hooks/GoogleOAuthHookService_part_aa +150 -0
- package/src/domains/auth/presentation/hooks/GoogleOAuthHookService_part_ab +97 -0
- package/src/domains/auth/presentation/hooks/GoogleOAuthService.ts +0 -0
- package/src/domains/auth/presentation/hooks/useGoogleOAuth.ts +49 -103
- package/src/domains/auth/presentation.ts +25 -0
- package/src/domains/firestore/domain/entities/Collection.ts +128 -0
- package/src/domains/firestore/domain/entities/Collection.ts.bak +288 -0
- package/src/domains/firestore/domain/entities/CollectionFactory.ts +55 -0
- package/src/domains/firestore/domain/entities/CollectionHelpers.ts +143 -0
- package/src/domains/firestore/domain/entities/CollectionUtils.ts +72 -0
- package/src/domains/firestore/domain/entities/CollectionValidation.ts +138 -0
- package/src/domains/firestore/domain/entities/Collection_part_aa +150 -0
- package/src/domains/firestore/domain/entities/Collection_part_ab +138 -0
- package/src/domains/firestore/domain/entities/Document.ts.bak +233 -0
- package/src/domains/firestore/domain/entities/DocumentHelpers.ts +0 -0
- package/src/domains/firestore/domain/entities/DocumentMain.ts +0 -0
- package/src/domains/firestore/domain/entities/Document_part_aa +150 -0
- package/src/domains/firestore/domain/entities/Document_part_ab +83 -0
- package/src/domains/firestore/domain/index.ts +65 -0
- package/src/domains/firestore/domain/services/QueryService.ts.bak +182 -0
- package/src/domains/firestore/domain/services/QueryServiceAnalysis.ts.bak +169 -0
- package/src/domains/firestore/domain/services/QueryServiceAnalysis_part_aa +150 -0
- package/src/domains/firestore/domain/services/QueryServiceAnalysis_part_ab +19 -0
- package/src/domains/firestore/domain/services/QueryServiceHelpers.ts.bak +151 -0
- package/src/domains/firestore/domain/services/QueryServiceHelpers_part_aa +150 -0
- package/src/domains/firestore/domain/services/QueryServiceHelpers_part_ab +1 -0
- package/src/domains/firestore/domain/services/QueryService_part_aa +150 -0
- package/src/domains/firestore/domain/services/QueryService_part_ab +32 -0
- package/src/domains/firestore/domain/value-objects/QueryOptions.ts.bak +191 -0
- package/src/domains/firestore/domain/value-objects/QueryOptionsSerialization.ts.bak +207 -0
- package/src/domains/firestore/domain/value-objects/QueryOptionsSerialization_part_aa +150 -0
- package/src/domains/firestore/domain/value-objects/QueryOptionsSerialization_part_ab +57 -0
- package/src/domains/firestore/domain/value-objects/QueryOptionsValidation.ts.bak +182 -0
- package/src/domains/firestore/domain/value-objects/QueryOptionsValidation_part_aa +150 -0
- package/src/domains/firestore/domain/value-objects/QueryOptionsValidation_part_ab +32 -0
- package/src/domains/firestore/domain/value-objects/QueryOptions_part_aa +150 -0
- package/src/domains/firestore/domain/value-objects/QueryOptions_part_ab +41 -0
- package/src/domains/firestore/domain/value-objects/WhereClause.ts.bak +299 -0
- package/src/domains/firestore/domain/value-objects/WhereClauseFactory.ts.bak +207 -0
- package/src/domains/firestore/domain/value-objects/WhereClauseFactory_part_aa +150 -0
- package/src/domains/firestore/domain/value-objects/WhereClauseFactory_part_ab +57 -0
- package/src/domains/firestore/domain/value-objects/WhereClause_part_aa +150 -0
- package/src/domains/firestore/domain/value-objects/WhereClause_part_ab +149 -0
- package/src/domains/firestore/index.ts +9 -6
- package/src/index.ts +25 -0
- package/src/shared/domain/utils/error-handlers/error-messages.ts +11 -0
- package/src/shared/infrastructure/base/ErrorHandler.ts.bak +189 -0
- package/src/shared/infrastructure/base/ErrorHandler_part_aa +150 -0
- package/src/shared/infrastructure/base/ErrorHandler_part_ab +39 -0
- package/src/shared/infrastructure/base/ServiceBase.ts.bak +220 -0
- package/src/shared/infrastructure/base/ServiceBase_part_aa +150 -0
- package/src/shared/infrastructure/base/ServiceBase_part_ab +70 -0
- package/src/shared/infrastructure/base/TypedGuard.ts +131 -0
- package/src/shared/infrastructure/base/index.ts +34 -0
- package/src/shared/infrastructure/config/base/ServiceClientSingleton_part_aa +150 -0
- package/src/shared/infrastructure/config/base/ServiceClientSingleton_part_ab +5 -0
- /package/src/domains/account-deletion/infrastructure/services/{reauthentication.service.ts → reauthentication.service.ts.bak} +0 -0
- /package/src/shared/infrastructure/config/base/{ServiceClientSingleton.ts → ServiceClientSingleton.ts.bak} +0 -0
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
if (!this.isAvailable()) {
|
|
2
|
+
return {
|
|
3
|
+
valid: false,
|
|
4
|
+
error: 'expo-auth-session is not available. Please install expo-auth-session and expo-web-browser.',
|
|
5
|
+
};
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
if (!this.isConfigured()) {
|
|
9
|
+
return {
|
|
10
|
+
valid: false,
|
|
11
|
+
error: 'Google Sign-In is not configured. Please provide valid client IDs.',
|
|
12
|
+
};
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
return { valid: true };
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* Get error message from error
|
|
20
|
+
*/
|
|
21
|
+
getErrorMessage(error: unknown): string {
|
|
22
|
+
if (error instanceof Error) {
|
|
23
|
+
return error.message;
|
|
24
|
+
}
|
|
25
|
+
return 'Google sign-in failed';
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
/**
|
|
29
|
+
* Check if response is successful
|
|
30
|
+
*/
|
|
31
|
+
isSuccessfulResponse(response: AuthSessionResponse | null): boolean {
|
|
32
|
+
return response?.type === 'success' && !!response.authentication?.idToken;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
/**
|
|
36
|
+
* Check if response is error
|
|
37
|
+
*/
|
|
38
|
+
isErrorResponse(response: AuthSessionResponse | null): boolean {
|
|
39
|
+
return response?.type === 'error';
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
/**
|
|
43
|
+
* Extract ID token from response
|
|
44
|
+
*/
|
|
45
|
+
extractIdToken(response: AuthSessionResponse | null): string | null {
|
|
46
|
+
return response?.authentication?.idToken || null;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
/**
|
|
50
|
+
* Create error result
|
|
51
|
+
*/
|
|
52
|
+
createErrorResult(error: string): { success: false; error: string } {
|
|
53
|
+
return { success: false, error };
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
/**
|
|
57
|
+
* Check if auth request is ready
|
|
58
|
+
*/
|
|
59
|
+
isReady(): boolean {
|
|
60
|
+
const [request, , promptAsync] = this.authRequest;
|
|
61
|
+
return request !== null && promptAsync !== null;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
/**
|
|
65
|
+
* Get configuration
|
|
66
|
+
*/
|
|
67
|
+
getConfig(): GoogleOAuthConfig | undefined {
|
|
68
|
+
return this.config;
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
/**
|
|
72
|
+
* Reset service state
|
|
73
|
+
*/
|
|
74
|
+
reset(): void {
|
|
75
|
+
this.config = undefined;
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
/**
|
|
80
|
+
* Factory function to create Google OAuth hook service
|
|
81
|
+
*/
|
|
82
|
+
export function createGoogleOAuthHookService(config?: GoogleOAuthConfig): GoogleOAuthHookService {
|
|
83
|
+
return new GoogleOAuthHookService(config);
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
/**
|
|
87
|
+
* Check if expo-auth-session is available
|
|
88
|
+
* Useful for conditional rendering
|
|
89
|
+
*/
|
|
90
|
+
export function isExpoAuthSessionAvailable(): boolean {
|
|
91
|
+
return isExpoAuthAvailable;
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
/**
|
|
95
|
+
* Re-export types for convenience
|
|
96
|
+
*/
|
|
97
|
+
export type { AuthSessionResponse, ExpoAuthSessionModule };
|
|
File without changes
|
|
@@ -1,37 +1,21 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* useGoogleOAuth Hook
|
|
3
3
|
* Handles Google OAuth flow using expo-auth-session and Firebase auth
|
|
4
|
-
*
|
|
4
|
+
*
|
|
5
|
+
* This hook delegates business logic to GoogleOAuthHookService.
|
|
6
|
+
* Focuses only on React state management and side effects.
|
|
7
|
+
*
|
|
8
|
+
* Max lines: 150 (enforced for maintainability)
|
|
5
9
|
*/
|
|
6
10
|
|
|
7
|
-
import { useState, useCallback, useEffect,
|
|
8
|
-
import {
|
|
9
|
-
import {
|
|
10
|
-
import
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
}
|
|
16
|
-
|
|
17
|
-
interface ExpoAuthSessionModule {
|
|
18
|
-
useAuthRequest: (config: {
|
|
19
|
-
iosClientId: string;
|
|
20
|
-
webClientId: string;
|
|
21
|
-
androidClientId: string;
|
|
22
|
-
}) => [unknown, AuthSessionResponse | null, (() => Promise<AuthSessionResponse>) | null];
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
let ExpoAuthSession: ExpoAuthSessionModule | null = null;
|
|
26
|
-
let isExpoAuthAvailable = false;
|
|
27
|
-
|
|
28
|
-
try {
|
|
29
|
-
// eslint-disable-next-line @typescript-eslint/no-require-imports
|
|
30
|
-
ExpoAuthSession = require("expo-auth-session/providers/google") as ExpoAuthSessionModule;
|
|
31
|
-
isExpoAuthAvailable = true;
|
|
32
|
-
} catch {
|
|
33
|
-
// expo-auth-session not available - hook will return unavailable state
|
|
34
|
-
}
|
|
11
|
+
import { useState, useCallback, useEffect, useMemo } from 'react';
|
|
12
|
+
import { getFirebaseAuth } from '../../infrastructure/config/FirebaseAuthClient';
|
|
13
|
+
import type { GoogleOAuthConfig } from '../../infrastructure/services/google-oauth.service';
|
|
14
|
+
import {
|
|
15
|
+
GoogleOAuthHookService,
|
|
16
|
+
createGoogleOAuthHookService,
|
|
17
|
+
isExpoAuthSessionAvailable,
|
|
18
|
+
} from './GoogleOAuthHookService';
|
|
35
19
|
|
|
36
20
|
export interface UseGoogleOAuthResult {
|
|
37
21
|
signInWithGoogle: () => Promise<SocialAuthResult>;
|
|
@@ -55,107 +39,62 @@ export function useGoogleOAuth(config?: GoogleOAuthConfig): UseGoogleOAuthResult
|
|
|
55
39
|
const [isLoading, setIsLoading] = useState(false);
|
|
56
40
|
const [googleError, setGoogleError] = useState<string | null>(null);
|
|
57
41
|
|
|
58
|
-
//
|
|
59
|
-
const
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
//
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
webClientId: config?.webClientId ?? "",
|
|
73
|
-
androidClientId: config?.androidClientId ?? "",
|
|
74
|
-
})
|
|
75
|
-
: [null, null, null];
|
|
42
|
+
// Initialize service with config
|
|
43
|
+
const service = useMemo(() => createGoogleOAuthHookService(config), [config]);
|
|
44
|
+
|
|
45
|
+
// Update service when config changes
|
|
46
|
+
useEffect(() => {
|
|
47
|
+
service.updateConfig(config);
|
|
48
|
+
}, [service, config]);
|
|
49
|
+
|
|
50
|
+
// Memoize service checks
|
|
51
|
+
const googleAvailable = useMemo(() => service.isAvailable(), [service]);
|
|
52
|
+
const googleConfigured = useMemo(() => service.isConfigured(), [service]);
|
|
53
|
+
|
|
54
|
+
// Get auth request tuple from service
|
|
55
|
+
const [, response] = service.getAuthRequest();
|
|
76
56
|
|
|
77
57
|
// Handle OAuth response
|
|
78
58
|
useEffect(() => {
|
|
79
59
|
if (!googleAvailable || !response) return;
|
|
80
60
|
|
|
81
61
|
const handleResponse = async () => {
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
}
|
|
93
|
-
|
|
94
|
-
await googleOAuthService.signInWithOAuth(
|
|
95
|
-
auth,
|
|
96
|
-
configRef.current,
|
|
97
|
-
async () => response
|
|
98
|
-
);
|
|
99
|
-
} catch (error) {
|
|
100
|
-
setGoogleError(
|
|
101
|
-
error instanceof Error ? error.message : "Firebase sign-in failed"
|
|
102
|
-
);
|
|
103
|
-
} finally {
|
|
104
|
-
setIsLoading(false);
|
|
105
|
-
}
|
|
106
|
-
} else if (response.type === "error") {
|
|
107
|
-
setGoogleError("Google authentication failed");
|
|
62
|
+
setIsLoading(true);
|
|
63
|
+
setGoogleError(null);
|
|
64
|
+
|
|
65
|
+
try {
|
|
66
|
+
const auth = getFirebaseAuth();
|
|
67
|
+
await service.handleResponse(response, auth);
|
|
68
|
+
} catch (error) {
|
|
69
|
+
setGoogleError(service.getErrorMessage(error));
|
|
70
|
+
} finally {
|
|
71
|
+
setIsLoading(false);
|
|
108
72
|
}
|
|
109
73
|
};
|
|
110
74
|
|
|
111
|
-
// Call async function and catch errors separately
|
|
112
75
|
handleResponse().catch((err) => {
|
|
113
|
-
// Errors are already handled in handleResponse
|
|
114
76
|
if (__DEV__) {
|
|
115
77
|
console.error('[useGoogleOAuth] Unexpected error in handleResponse:', err);
|
|
116
78
|
}
|
|
117
79
|
});
|
|
118
|
-
}, [response, googleAvailable]);
|
|
80
|
+
}, [response, googleAvailable, service]);
|
|
119
81
|
|
|
82
|
+
// Sign in with Google
|
|
120
83
|
const signInWithGoogle = useCallback(async (): Promise<SocialAuthResult> => {
|
|
121
|
-
if (!googleAvailable) {
|
|
122
|
-
const error = "expo-auth-session is not available. Please install expo-auth-session and expo-web-browser.";
|
|
123
|
-
setGoogleError(error);
|
|
124
|
-
return { success: false, error };
|
|
125
|
-
}
|
|
126
|
-
|
|
127
|
-
if (!googleConfigured) {
|
|
128
|
-
const error = "Google Sign-In is not configured. Please provide valid client IDs.";
|
|
129
|
-
setGoogleError(error);
|
|
130
|
-
return { success: false, error };
|
|
131
|
-
}
|
|
132
|
-
|
|
133
|
-
if (!request || !promptAsync) {
|
|
134
|
-
const error = "Google Sign-In not ready";
|
|
135
|
-
setGoogleError(error);
|
|
136
|
-
return { success: false, error };
|
|
137
|
-
}
|
|
138
|
-
|
|
139
84
|
setIsLoading(true);
|
|
140
85
|
setGoogleError(null);
|
|
141
86
|
|
|
142
87
|
try {
|
|
143
88
|
const auth = getFirebaseAuth();
|
|
144
|
-
|
|
145
|
-
const error = "Firebase Auth not initialized";
|
|
146
|
-
setGoogleError(error);
|
|
147
|
-
return { success: false, error };
|
|
148
|
-
}
|
|
149
|
-
|
|
150
|
-
return await googleOAuthService.signInWithOAuth(auth, config, promptAsync);
|
|
89
|
+
return await service.signIn(auth);
|
|
151
90
|
} catch (error) {
|
|
152
|
-
const errorMessage = error
|
|
91
|
+
const errorMessage = service.getErrorMessage(error);
|
|
153
92
|
setGoogleError(errorMessage);
|
|
154
93
|
return { success: false, error: errorMessage };
|
|
155
94
|
} finally {
|
|
156
95
|
setIsLoading(false);
|
|
157
96
|
}
|
|
158
|
-
}, [
|
|
97
|
+
}, [service]);
|
|
159
98
|
|
|
160
99
|
return {
|
|
161
100
|
signInWithGoogle,
|
|
@@ -165,3 +104,10 @@ export function useGoogleOAuth(config?: GoogleOAuthConfig): UseGoogleOAuthResult
|
|
|
165
104
|
googleError,
|
|
166
105
|
};
|
|
167
106
|
}
|
|
107
|
+
|
|
108
|
+
/**
|
|
109
|
+
* Check if expo-auth-session is available
|
|
110
|
+
* Useful for conditional rendering
|
|
111
|
+
*/
|
|
112
|
+
export { isExpoAuthSessionAvailable };
|
|
113
|
+
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Firebase Auth Presentation Layer
|
|
3
|
+
* Domain-Driven Design (DDD) - Presentation Exports
|
|
4
|
+
*
|
|
5
|
+
* React hooks for Firebase authentication.
|
|
6
|
+
* Provides clean interface for UI components.
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
export { useFirebaseAuth } from './presentation/hooks/useFirebaseAuth';
|
|
10
|
+
export type { UseFirebaseAuthResult } from './presentation/hooks/useFirebaseAuth';
|
|
11
|
+
|
|
12
|
+
export { useAnonymousAuth } from './presentation/hooks/useAnonymousAuth';
|
|
13
|
+
export type { UseAnonymousAuthResult } from './presentation/hooks/useAnonymousAuth';
|
|
14
|
+
|
|
15
|
+
export { useSocialAuth } from './presentation/hooks/useSocialAuth';
|
|
16
|
+
export type {
|
|
17
|
+
SocialAuthConfig,
|
|
18
|
+
SocialAuthResult,
|
|
19
|
+
UseSocialAuthResult,
|
|
20
|
+
} from './presentation/hooks/useSocialAuth';
|
|
21
|
+
|
|
22
|
+
export { useGoogleOAuth } from './presentation/hooks/useGoogleOAuth';
|
|
23
|
+
export type {
|
|
24
|
+
UseGoogleOAuthResult,
|
|
25
|
+
} from './presentation/hooks/useGoogleOAuth';
|
|
@@ -0,0 +1,128 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Collection Entity (Main)
|
|
3
|
+
* Single Responsibility: Represent a Firestore collection with metadata
|
|
4
|
+
*
|
|
5
|
+
* Domain entity that encapsulates collection information and metadata.
|
|
6
|
+
* Provides business logic for collection operations.
|
|
7
|
+
*
|
|
8
|
+
* Max lines: 150 (enforced for maintainability)
|
|
9
|
+
*/
|
|
10
|
+
|
|
11
|
+
import type { CollectionReference, Query } from 'firebase/firestore';
|
|
12
|
+
import {
|
|
13
|
+
isValidCollectionName,
|
|
14
|
+
isValidCollectionPath,
|
|
15
|
+
extractCollectionNameFromPath,
|
|
16
|
+
extractParentCollectionPath,
|
|
17
|
+
isUserCollectionPath,
|
|
18
|
+
extractUserIdFromPath,
|
|
19
|
+
createSubCollectionPath as createSubCollectionPathUtil,
|
|
20
|
+
} from './CollectionValidation';
|
|
21
|
+
import {
|
|
22
|
+
getCollectionDepth,
|
|
23
|
+
collectionToObject,
|
|
24
|
+
isQueryReference,
|
|
25
|
+
isCollectionReference as isCollectionReferenceUtil,
|
|
26
|
+
} from './CollectionUtils';
|
|
27
|
+
import { fromReference, fromQuery } from './CollectionFactory';
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* Collection metadata
|
|
31
|
+
*/
|
|
32
|
+
export interface CollectionMetadata {
|
|
33
|
+
readonly name: string;
|
|
34
|
+
readonly path: string;
|
|
35
|
+
readonly parentPath?: string;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
/**
|
|
39
|
+
* Collection entity
|
|
40
|
+
* Represents a Firestore collection with metadata
|
|
41
|
+
*/
|
|
42
|
+
export class Collection<TDocument = unknown> {
|
|
43
|
+
readonly name: string;
|
|
44
|
+
readonly path: string;
|
|
45
|
+
readonly parentPath: string | undefined;
|
|
46
|
+
private readonly reference: CollectionReference<TDocument> | Query<TDocument>;
|
|
47
|
+
|
|
48
|
+
constructor(
|
|
49
|
+
reference: CollectionReference<TDocument> | Query<TDocument>,
|
|
50
|
+
metadata: CollectionMetadata
|
|
51
|
+
) {
|
|
52
|
+
this.reference = reference;
|
|
53
|
+
this.name = metadata.name;
|
|
54
|
+
this.path = metadata.path;
|
|
55
|
+
this.parentPath = metadata.parentPath || undefined;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
/**
|
|
59
|
+
* Create collection from collection reference
|
|
60
|
+
*/
|
|
61
|
+
static fromReference<TDocument = unknown>(
|
|
62
|
+
reference: CollectionReference<TDocument>
|
|
63
|
+
): Collection<TDocument> {
|
|
64
|
+
return fromReference(reference);
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
/**
|
|
68
|
+
* Create collection from query
|
|
69
|
+
*/
|
|
70
|
+
static fromQuery<TDocument = unknown>(query: Query<TDocument>, name: string, path: string): Collection<TDocument> {
|
|
71
|
+
return fromQuery(query, name, path);
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
getName(): string {
|
|
75
|
+
return this.name;
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
getPath(): string {
|
|
79
|
+
return this.path;
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
getParentPath(): string | undefined {
|
|
83
|
+
return this.parentPath;
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
isNested(): boolean {
|
|
87
|
+
return this.parentPath !== undefined;
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
isRootLevel(): boolean {
|
|
91
|
+
return this.parentPath === undefined;
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
getDepth(): number {
|
|
95
|
+
return getCollectionDepth(this);
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
getReference(): CollectionReference<TDocument> | Query<TDocument> {
|
|
99
|
+
return this.reference;
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
isQuery(): boolean {
|
|
103
|
+
return isQueryReference(this.reference);
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
isCollectionReference(): boolean {
|
|
107
|
+
return isCollectionReferenceUtil(this.reference);
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
toObject(): CollectionMetadata {
|
|
111
|
+
return collectionToObject(this);
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
createSubCollectionPath(subCollectionName: string): string | null {
|
|
115
|
+
return createSubCollectionPathUtil(this.path, subCollectionName);
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
isUserCollection(): boolean {
|
|
119
|
+
return isUserCollectionPath(this.path);
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
extractUserId(): string | null {
|
|
123
|
+
return extractUserIdFromPath(this.path);
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
// Re-export factory function for backward compatibility
|
|
128
|
+
export { createCollection, fromReference, fromQuery } from './CollectionFactory';
|