@umituz/react-native-firebase 3.0.3 → 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 +7 -1
- package/src/domains/account-deletion/index.ts +15 -10
- package/src/domains/account-deletion/infrastructure/services/account-deletion.service.ts +235 -26
- package/src/domains/account-deletion/infrastructure/services/reauthentication.service.ts +160 -0
- package/src/domains/auth/domain/value-objects/FirebaseAuthConfig.ts +1 -1
- package/src/domains/auth/index.ts +156 -6
- package/src/domains/auth/infrastructure/config/FirebaseAuthClient.ts +60 -48
- package/src/domains/auth/infrastructure/config/initializers/FirebaseAuthInitializer.ts +41 -5
- 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/useGoogleOAuth.ts +115 -20
- package/src/domains/auth/presentation/hooks/utils/auth-state-change.handler.ts +5 -11
- package/src/domains/firestore/domain/constants/QuotaLimits.ts +101 -0
- package/src/domains/firestore/domain/entities/QuotaMetrics.ts +26 -0
- package/src/domains/firestore/domain/entities/RequestLog.ts +28 -0
- package/src/domains/firestore/domain/services/QuotaCalculator.ts +71 -0
- package/src/domains/firestore/index.ts +85 -31
- package/src/domains/firestore/infrastructure/config/FirestoreClient.ts +82 -45
- package/src/domains/firestore/infrastructure/config/initializers/FirebaseFirestoreInitializer.ts +249 -4
- package/src/domains/firestore/infrastructure/middleware/QueryDeduplicationMiddleware.ts +306 -0
- package/src/domains/firestore/infrastructure/middleware/QuotaTrackingMiddleware.ts +92 -0
- package/src/domains/firestore/infrastructure/repositories/BasePaginatedRepository.ts +9 -1
- package/src/domains/firestore/infrastructure/repositories/BaseQueryRepository.ts +34 -8
- package/src/domains/firestore/infrastructure/repositories/BaseRepository.ts +48 -9
- package/src/domains/firestore/infrastructure/services/RequestLoggerService.ts +168 -0
- package/src/domains/firestore/presentation/hooks/index.ts +10 -0
- package/src/domains/firestore/presentation/hooks/useFirestoreMutation.ts +1 -1
- package/src/domains/firestore/presentation/hooks/useFirestoreQuery.ts +1 -1
- package/src/domains/firestore/presentation/hooks/useFirestoreSnapshot.ts +2 -1
- package/src/domains/firestore/presentation/hooks/useSmartFirestoreSnapshot.ts +362 -0
- package/src/domains/firestore/presentation/query-keys/createFirestoreKeys.ts +32 -0
- package/src/domains/firestore/presentation/query-keys/index.ts +1 -0
- package/src/domains/firestore/utils/deduplication/pending-query-manager.util.ts +126 -0
- package/src/domains/firestore/utils/deduplication/query-key-generator.util.ts +41 -0
- package/src/domains/firestore/utils/deduplication/timer-manager.util.ts +83 -0
- 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 +324 -32
- package/src/shared/domain/utils/calculation.util.ts +305 -17
- package/src/shared/domain/utils/error-handlers/error-messages.ts +0 -15
- package/src/shared/domain/utils/index.ts +5 -0
- package/src/shared/infrastructure/config/base/ClientStateManager.ts +82 -0
- package/src/shared/infrastructure/config/base/ServiceClientSingleton.ts +136 -20
- package/src/shared/infrastructure/config/clients/FirebaseClientSingleton.ts +1 -1
- package/src/shared/infrastructure/config/initializers/FirebaseAppInitializer.ts +9 -0
- package/src/shared/infrastructure/config/services/FirebaseInitializationService.ts +1 -1
- package/src/shared/infrastructure/config/state/FirebaseClientState.ts +14 -36
- package/src/application/auth/index.ts +0 -10
- package/src/application/auth/use-cases/index.ts +0 -6
- package/src/domains/account-deletion/domain/index.ts +0 -8
- package/src/domains/account-deletion/infrastructure/services/AccountDeletionExecutor.ts +0 -79
- package/src/domains/account-deletion/infrastructure/services/AccountDeletionTypes.ts +0 -32
- package/src/domains/auth/domain.ts +0 -16
- package/src/domains/auth/infrastructure/config/index.ts +0 -2
- package/src/domains/auth/infrastructure/config/initializers/index.ts +0 -1
- package/src/domains/auth/infrastructure/services/index.ts +0 -16
- package/src/domains/auth/infrastructure/services/utils/index.ts +0 -1
- package/src/domains/auth/infrastructure/stores/index.ts +0 -1
- package/src/domains/auth/infrastructure/utils/index.ts +0 -1
- package/src/domains/auth/infrastructure.ts +0 -11
- package/src/domains/auth/presentation/hooks/useAppleAuth.ts +0 -82
- package/src/domains/auth/presentation.ts +0 -31
- package/src/domains/firestore/domain/entities/Collection.ts +0 -122
- package/src/domains/firestore/domain/entities/CollectionFactory.ts +0 -55
- package/src/domains/firestore/domain/entities/CollectionHelpers.ts +0 -143
- package/src/domains/firestore/domain/entities/CollectionUtils.ts +0 -72
- package/src/domains/firestore/domain/entities/CollectionValidation.ts +0 -138
- package/src/domains/firestore/domain/index.ts +0 -61
- package/src/domains/firestore/domain/value-objects/QueryOptions.ts +0 -143
- package/src/domains/firestore/domain/value-objects/QueryOptionsFactory.ts +0 -95
- package/src/domains/firestore/domain/value-objects/QueryOptionsHelpers.ts +0 -110
- package/src/domains/firestore/domain/value-objects/WhereClause.ts +0 -114
- package/src/domains/firestore/domain/value-objects/WhereClauseFactory.ts +0 -101
- package/src/domains/firestore/domain/value-objects/WhereClauseHelpers.ts +0 -123
- package/src/domains/firestore/domain/value-objects/WhereClauseValidation.ts +0 -83
- package/src/shared/infrastructure/base/ErrorHandler.ts +0 -81
- package/src/shared/infrastructure/base/ServiceBase.ts +0 -62
- package/src/shared/infrastructure/base/TypedGuard.ts +0 -131
- package/src/shared/infrastructure/base/index.ts +0 -34
- package/src/shared/types/firebase.types.ts +0 -274
|
@@ -1,143 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Collection Entity Helpers
|
|
3
|
-
* Single Responsibility: Provide utility methods for collections
|
|
4
|
-
*
|
|
5
|
-
* Helper methods separated from main Collection entity.
|
|
6
|
-
*
|
|
7
|
-
* Max lines: 150 (enforced for maintainability)
|
|
8
|
-
*/
|
|
9
|
-
|
|
10
|
-
import { Collection } from './Collection';
|
|
11
|
-
import { isValidCollectionPath, isValidCollectionName } from './CollectionValidation';
|
|
12
|
-
|
|
13
|
-
/**
|
|
14
|
-
* Check if collection is parent of another
|
|
15
|
-
*/
|
|
16
|
-
export function isParentOf(parent: Collection, child: Collection): boolean {
|
|
17
|
-
const childPath = child.getPath();
|
|
18
|
-
const parentPath = parent.getPath();
|
|
19
|
-
return childPath.startsWith(parentPath + '/');
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
/**
|
|
23
|
-
* Get collection ID (similar to name but more explicit)
|
|
24
|
-
*/
|
|
25
|
-
export function getCollectionId(collection: Collection): string {
|
|
26
|
-
return collection.getName();
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
/**
|
|
30
|
-
* Check if collections are equal
|
|
31
|
-
*/
|
|
32
|
-
export function collectionsEqual(col1: Collection, col2: Collection): boolean {
|
|
33
|
-
return col1.getPath() === col2.getPath();
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
/**
|
|
37
|
-
* Get collection size info (metadata)
|
|
38
|
-
*/
|
|
39
|
-
export function getCollectionInfo(collection: Collection): {
|
|
40
|
-
readonly name: string;
|
|
41
|
-
readonly path: string;
|
|
42
|
-
readonly depth: number;
|
|
43
|
-
readonly isNested: boolean;
|
|
44
|
-
readonly isRoot: boolean;
|
|
45
|
-
readonly isUserCollection: boolean;
|
|
46
|
-
} {
|
|
47
|
-
return {
|
|
48
|
-
name: collection.getName(),
|
|
49
|
-
path: collection.getPath(),
|
|
50
|
-
depth: collection.getDepth(),
|
|
51
|
-
isNested: collection.isNested(),
|
|
52
|
-
isRoot: collection.isRootLevel(),
|
|
53
|
-
isUserCollection: collection.isUserCollection(),
|
|
54
|
-
};
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
export function isValidCollection(collection: Collection): boolean {
|
|
58
|
-
return isValidCollectionName(collection.getName()) &&
|
|
59
|
-
isValidCollectionPath(collection.getPath());
|
|
60
|
-
}
|
|
61
|
-
|
|
62
|
-
export function collectionFromPath(db: any, path: string): Collection | null {
|
|
63
|
-
if (!isValidCollectionPath(path)) {
|
|
64
|
-
return null;
|
|
65
|
-
}
|
|
66
|
-
|
|
67
|
-
try {
|
|
68
|
-
const ref = db.collection(path);
|
|
69
|
-
return Collection.fromReference(ref as any);
|
|
70
|
-
} catch {
|
|
71
|
-
return null;
|
|
72
|
-
}
|
|
73
|
-
}
|
|
74
|
-
|
|
75
|
-
export function getSubCollectionNames(path: string): string[] {
|
|
76
|
-
if (!isValidCollectionPath(path)) {
|
|
77
|
-
return [];
|
|
78
|
-
}
|
|
79
|
-
|
|
80
|
-
const segments = path.split('/');
|
|
81
|
-
const collections: string[] = [];
|
|
82
|
-
|
|
83
|
-
// Extract collection names (even indices)
|
|
84
|
-
for (let i = 0; i < segments.length; i += 2) {
|
|
85
|
-
const segment = segments[i];
|
|
86
|
-
if (segment) {
|
|
87
|
-
collections.push(segment);
|
|
88
|
-
}
|
|
89
|
-
}
|
|
90
|
-
|
|
91
|
-
return collections;
|
|
92
|
-
}
|
|
93
|
-
|
|
94
|
-
export function buildCollectionPath(...parts: string[]): string {
|
|
95
|
-
if (parts.length === 0 || parts.length % 2 !== 0) {
|
|
96
|
-
throw new Error('Invalid collection path parts');
|
|
97
|
-
}
|
|
98
|
-
|
|
99
|
-
if (!parts.every(p => isValidCollectionName(p))) {
|
|
100
|
-
throw new Error('Invalid collection name in parts');
|
|
101
|
-
}
|
|
102
|
-
|
|
103
|
-
return parts.join('/');
|
|
104
|
-
}
|
|
105
|
-
|
|
106
|
-
export function parseCollectionPath(path: string): {
|
|
107
|
-
readonly collections: string[];
|
|
108
|
-
readonly documents: string[];
|
|
109
|
-
readonly segments: string[];
|
|
110
|
-
} | null {
|
|
111
|
-
if (!isValidCollectionPath(path)) {
|
|
112
|
-
return null;
|
|
113
|
-
}
|
|
114
|
-
|
|
115
|
-
const segments = path.split('/');
|
|
116
|
-
const collections: string[] = [];
|
|
117
|
-
const documents: string[] = [];
|
|
118
|
-
|
|
119
|
-
for (let i = 0; i < segments.length; i += 2) {
|
|
120
|
-
const collectionSegment = segments[i];
|
|
121
|
-
if (collectionSegment) {
|
|
122
|
-
collections.push(collectionSegment);
|
|
123
|
-
}
|
|
124
|
-
if (i + 1 < segments.length) {
|
|
125
|
-
const documentSegment = segments[i + 1];
|
|
126
|
-
if (documentSegment) {
|
|
127
|
-
documents.push(documentSegment);
|
|
128
|
-
}
|
|
129
|
-
}
|
|
130
|
-
}
|
|
131
|
-
|
|
132
|
-
return { collections, documents, segments };
|
|
133
|
-
}
|
|
134
|
-
|
|
135
|
-
export function isDocumentPath(path: string): boolean {
|
|
136
|
-
const segments = path.split('/');
|
|
137
|
-
return segments.length % 2 === 0 && segments.length >= 2;
|
|
138
|
-
}
|
|
139
|
-
|
|
140
|
-
export function isCollectionPath(path: string): boolean {
|
|
141
|
-
const segments = path.split('/');
|
|
142
|
-
return segments.length % 2 !== 0 && segments.length >= 1;
|
|
143
|
-
}
|
|
@@ -1,72 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Collection Utilities
|
|
3
|
-
* Single Responsibility: Provide utility functions for collection operations
|
|
4
|
-
*
|
|
5
|
-
* Max lines: 150 (enforced for maintainability)
|
|
6
|
-
*/
|
|
7
|
-
|
|
8
|
-
import type { CollectionReference, Query } from 'firebase/firestore';
|
|
9
|
-
import type { Collection, CollectionMetadata } from './Collection';
|
|
10
|
-
|
|
11
|
-
/**
|
|
12
|
-
* Get collection depth in hierarchy
|
|
13
|
-
* Root collections have depth 0
|
|
14
|
-
*/
|
|
15
|
-
export function getCollectionDepth(collection: Collection): number {
|
|
16
|
-
if (!collection.getParentPath()) return 0;
|
|
17
|
-
const path = collection.getPath();
|
|
18
|
-
return path.split('/').length / 2 - 1;
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
/**
|
|
22
|
-
* Convert collection to plain object (for serialization)
|
|
23
|
-
*/
|
|
24
|
-
export function collectionToObject(collection: Collection): CollectionMetadata {
|
|
25
|
-
return {
|
|
26
|
-
name: collection.getName(),
|
|
27
|
-
path: collection.getPath(),
|
|
28
|
-
parentPath: collection.getParentPath(),
|
|
29
|
-
};
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
/**
|
|
33
|
-
* Check if reference is a query (has filters/limits)
|
|
34
|
-
*/
|
|
35
|
-
export function isQueryReference<TDocument>(
|
|
36
|
-
reference: CollectionReference<TDocument> | Query<TDocument>
|
|
37
|
-
): boolean {
|
|
38
|
-
return 'type' in reference && reference.type === 'query';
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
/**
|
|
42
|
-
* Check if reference is a collection reference (no filters)
|
|
43
|
-
*/
|
|
44
|
-
export function isCollectionReference<TDocument>(
|
|
45
|
-
reference: CollectionReference<TDocument> | Query<TDocument>
|
|
46
|
-
): boolean {
|
|
47
|
-
return !isQueryReference(reference);
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
/**
|
|
51
|
-
* Get collection size info (metadata)
|
|
52
|
-
*/
|
|
53
|
-
export function getCollectionInfo(collection: Collection): {
|
|
54
|
-
readonly name: string;
|
|
55
|
-
readonly path: string;
|
|
56
|
-
readonly depth: number;
|
|
57
|
-
readonly isNested: boolean;
|
|
58
|
-
readonly isRoot: boolean;
|
|
59
|
-
readonly isUserCollection: boolean;
|
|
60
|
-
readonly isQuery: boolean;
|
|
61
|
-
} {
|
|
62
|
-
const reference = collection.getReference();
|
|
63
|
-
return {
|
|
64
|
-
name: collection.getName(),
|
|
65
|
-
path: collection.getPath(),
|
|
66
|
-
depth: getCollectionDepth(collection),
|
|
67
|
-
isNested: collection.isNested(),
|
|
68
|
-
isRoot: collection.isRootLevel(),
|
|
69
|
-
isUserCollection: collection.isUserCollection(),
|
|
70
|
-
isQuery: isQueryReference(reference),
|
|
71
|
-
};
|
|
72
|
-
}
|
|
@@ -1,138 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Collection Validation Utilities
|
|
3
|
-
* Single Responsibility: Validate collection names and paths
|
|
4
|
-
*
|
|
5
|
-
* Max lines: 150 (enforced for maintainability)
|
|
6
|
-
*/
|
|
7
|
-
|
|
8
|
-
import type { Collection } from './Collection';
|
|
9
|
-
|
|
10
|
-
/**
|
|
11
|
-
* Validate collection name format
|
|
12
|
-
*/
|
|
13
|
-
export function isValidCollectionName(name: string): boolean {
|
|
14
|
-
if (!name || typeof name !== 'string' || name.trim() === '') {
|
|
15
|
-
return false;
|
|
16
|
-
}
|
|
17
|
-
|
|
18
|
-
const invalidChars = /[\/\\.\s]/;
|
|
19
|
-
if (invalidChars.test(name)) {
|
|
20
|
-
return false;
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
if (name.startsWith('__') || name.endsWith('__')) {
|
|
24
|
-
return false;
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
if (name.length > 100) {
|
|
28
|
-
return false;
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
return true;
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
/**
|
|
35
|
-
* Check if collection is valid
|
|
36
|
-
*/
|
|
37
|
-
export function isValidCollection(collection: Collection): boolean {
|
|
38
|
-
return isValidCollectionName(collection.getName()) &&
|
|
39
|
-
isValidCollectionPath(collection.getPath());
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
/**
|
|
43
|
-
* Validate collection path format
|
|
44
|
-
*/
|
|
45
|
-
export function isValidCollectionPath(path: string): boolean {
|
|
46
|
-
if (!path || typeof path !== 'string' || path.trim() === '') {
|
|
47
|
-
return false;
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
const segments = path.split('/');
|
|
51
|
-
if (segments.length < 1 || segments.length % 2 === 0) {
|
|
52
|
-
return false;
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
return segments.every(segment => isValidCollectionName(segment));
|
|
56
|
-
}
|
|
57
|
-
|
|
58
|
-
/**
|
|
59
|
-
* Extract collection name from path
|
|
60
|
-
*/
|
|
61
|
-
export function extractCollectionNameFromPath(path: string): string | null {
|
|
62
|
-
if (!isValidCollectionPath(path)) {
|
|
63
|
-
return null;
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
const segments = path.split('/');
|
|
67
|
-
return segments[segments.length - 1] || null;
|
|
68
|
-
}
|
|
69
|
-
|
|
70
|
-
/**
|
|
71
|
-
* Extract parent path from collection path
|
|
72
|
-
*/
|
|
73
|
-
export function extractParentCollectionPath(path: string): string | null {
|
|
74
|
-
if (!isValidCollectionPath(path)) {
|
|
75
|
-
return null;
|
|
76
|
-
}
|
|
77
|
-
|
|
78
|
-
const segments = path.split('/');
|
|
79
|
-
if (segments.length <= 1) {
|
|
80
|
-
return null;
|
|
81
|
-
}
|
|
82
|
-
|
|
83
|
-
const result = segments.slice(0, -1).join('/');
|
|
84
|
-
return result || null;
|
|
85
|
-
}
|
|
86
|
-
|
|
87
|
-
/**
|
|
88
|
-
* Check if path points to document
|
|
89
|
-
*/
|
|
90
|
-
export function isDocumentPath(path: string): boolean {
|
|
91
|
-
const segments = path.split('/');
|
|
92
|
-
return segments.length % 2 === 0 && segments.length >= 2;
|
|
93
|
-
}
|
|
94
|
-
|
|
95
|
-
/**
|
|
96
|
-
* Check if path points to collection
|
|
97
|
-
*/
|
|
98
|
-
export function isCollectionPath(path: string): boolean {
|
|
99
|
-
const segments = path.split('/');
|
|
100
|
-
return segments.length % 2 !== 0 && segments.length >= 1;
|
|
101
|
-
}
|
|
102
|
-
|
|
103
|
-
/**
|
|
104
|
-
* Check if collection is a user collection (users/{userId}/{collection})
|
|
105
|
-
*/
|
|
106
|
-
export function isUserCollectionPath(path: string): boolean {
|
|
107
|
-
return path.startsWith('users/');
|
|
108
|
-
}
|
|
109
|
-
|
|
110
|
-
/**
|
|
111
|
-
* Extract user ID from user collection path
|
|
112
|
-
*/
|
|
113
|
-
export function extractUserIdFromPath(path: string): string | null {
|
|
114
|
-
if (!isUserCollectionPath(path)) return null;
|
|
115
|
-
|
|
116
|
-
const segments = path.split('/');
|
|
117
|
-
if (segments.length >= 3 && segments[0] === 'users') {
|
|
118
|
-
const userId = segments[1];
|
|
119
|
-
return userId || null;
|
|
120
|
-
}
|
|
121
|
-
|
|
122
|
-
return null;
|
|
123
|
-
}
|
|
124
|
-
|
|
125
|
-
/**
|
|
126
|
-
* Create a sub-collection path
|
|
127
|
-
*/
|
|
128
|
-
export function createSubCollectionPath(parentPath: string, subCollectionName: string): string | null {
|
|
129
|
-
if (!isValidCollectionPath(parentPath)) {
|
|
130
|
-
return null;
|
|
131
|
-
}
|
|
132
|
-
|
|
133
|
-
if (!isValidCollectionName(subCollectionName)) {
|
|
134
|
-
return null;
|
|
135
|
-
}
|
|
136
|
-
|
|
137
|
-
return `${parentPath}/${subCollectionName}`;
|
|
138
|
-
}
|
|
@@ -1,61 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Firestore Domain Layer
|
|
3
|
-
* Domain-Driven Design (DDD) - Domain Exports
|
|
4
|
-
*
|
|
5
|
-
* Pure domain logic without infrastructure concerns.
|
|
6
|
-
* Exports entities, value objects, and domain services.
|
|
7
|
-
*/
|
|
8
|
-
|
|
9
|
-
// Domain Errors
|
|
10
|
-
export {
|
|
11
|
-
FirebaseFirestoreError,
|
|
12
|
-
FirebaseFirestoreInitializationError,
|
|
13
|
-
FirebaseFirestoreQuotaError,
|
|
14
|
-
} from './errors/FirebaseFirestoreError';
|
|
15
|
-
|
|
16
|
-
// Domain Entities
|
|
17
|
-
export { Collection } from './entities/Collection';
|
|
18
|
-
export { fromReference, fromQuery, createCollection } from './entities/CollectionFactory';
|
|
19
|
-
export type { CollectionMetadata } from './entities/Collection';
|
|
20
|
-
|
|
21
|
-
// Collection Entity Helpers
|
|
22
|
-
export {
|
|
23
|
-
isParentOf,
|
|
24
|
-
getCollectionId,
|
|
25
|
-
collectionsEqual,
|
|
26
|
-
getCollectionInfo,
|
|
27
|
-
collectionFromPath,
|
|
28
|
-
getSubCollectionNames,
|
|
29
|
-
buildCollectionPath,
|
|
30
|
-
parseCollectionPath,
|
|
31
|
-
} from './entities/CollectionHelpers';
|
|
32
|
-
|
|
33
|
-
// Collection Utilities
|
|
34
|
-
export {
|
|
35
|
-
getCollectionDepth,
|
|
36
|
-
collectionToObject,
|
|
37
|
-
isQueryReference,
|
|
38
|
-
} from './entities/CollectionUtils';
|
|
39
|
-
|
|
40
|
-
// Collection Validation
|
|
41
|
-
export {
|
|
42
|
-
isValidCollectionName,
|
|
43
|
-
isValidCollectionPath,
|
|
44
|
-
isValidCollection,
|
|
45
|
-
extractCollectionNameFromPath,
|
|
46
|
-
extractParentCollectionPath,
|
|
47
|
-
isDocumentPath,
|
|
48
|
-
isCollectionPath,
|
|
49
|
-
isUserCollectionPath,
|
|
50
|
-
extractUserIdFromPath,
|
|
51
|
-
createSubCollectionPath,
|
|
52
|
-
} from './entities/CollectionValidation';
|
|
53
|
-
|
|
54
|
-
// Domain Value Objects
|
|
55
|
-
export { QueryOptions, createQueryOptions } from './value-objects/QueryOptions';
|
|
56
|
-
export type { SortOptions, DateRangeOptions, PaginationOptions } from './value-objects/QueryOptions';
|
|
57
|
-
|
|
58
|
-
// Where Clause
|
|
59
|
-
export { WhereClause } from './value-objects/WhereClause';
|
|
60
|
-
export { equals, where, fromObject as createWhereClause } from './value-objects/WhereClauseFactory';
|
|
61
|
-
export type { WhereOperator } from './value-objects/WhereClause';
|
|
@@ -1,143 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Query Options Value Object (Main)
|
|
3
|
-
* Single Responsibility: Encapsulate query configuration options
|
|
4
|
-
*
|
|
5
|
-
* Max lines: 150 (enforced for maintainability)
|
|
6
|
-
*/
|
|
7
|
-
|
|
8
|
-
import type { OrderByDirection } from 'firebase/firestore';
|
|
9
|
-
import { WhereClause } from './WhereClause';
|
|
10
|
-
import * as Factory from './QueryOptionsFactory';
|
|
11
|
-
|
|
12
|
-
export interface SortOptions {
|
|
13
|
-
readonly field: string;
|
|
14
|
-
readonly direction: OrderByDirection;
|
|
15
|
-
}
|
|
16
|
-
|
|
17
|
-
export interface DateRangeOptions {
|
|
18
|
-
readonly field: string;
|
|
19
|
-
readonly startDate?: Date;
|
|
20
|
-
readonly endDate?: Date;
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
export interface PaginationOptions {
|
|
24
|
-
readonly cursor?: number;
|
|
25
|
-
readonly limit?: number;
|
|
26
|
-
readonly startAfter?: number;
|
|
27
|
-
readonly startAt?: number;
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
export class QueryOptions {
|
|
31
|
-
readonly whereClauses: readonly WhereClause[];
|
|
32
|
-
readonly sortOptions: readonly SortOptions[];
|
|
33
|
-
readonly dateRange: DateRangeOptions | null;
|
|
34
|
-
readonly pagination: PaginationOptions | null;
|
|
35
|
-
|
|
36
|
-
private constructor(
|
|
37
|
-
whereClauses: WhereClause[],
|
|
38
|
-
sortOptions: SortOptions[],
|
|
39
|
-
dateRange: DateRangeOptions | null,
|
|
40
|
-
pagination: PaginationOptions | null
|
|
41
|
-
) {
|
|
42
|
-
this.whereClauses = Object.freeze(whereClauses);
|
|
43
|
-
this.sortOptions = Object.freeze(sortOptions);
|
|
44
|
-
this.dateRange = dateRange ? Object.freeze(dateRange) : null;
|
|
45
|
-
this.pagination = pagination ? Object.freeze(pagination) : null;
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
static empty(): QueryOptions {
|
|
49
|
-
return new QueryOptions([], [], null, null);
|
|
50
|
-
}
|
|
51
|
-
|
|
52
|
-
static create(options: {
|
|
53
|
-
where?: WhereClause[];
|
|
54
|
-
sort?: SortOptions[];
|
|
55
|
-
dateRange?: DateRangeOptions;
|
|
56
|
-
pagination?: PaginationOptions;
|
|
57
|
-
}): QueryOptions {
|
|
58
|
-
return new QueryOptions(
|
|
59
|
-
options.where || [],
|
|
60
|
-
options.sort || [],
|
|
61
|
-
options.dateRange || null,
|
|
62
|
-
options.pagination || null
|
|
63
|
-
);
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
withWhere(clause: WhereClause): QueryOptions {
|
|
67
|
-
return new QueryOptions(
|
|
68
|
-
[...this.whereClauses, clause] as WhereClause[],
|
|
69
|
-
[...this.sortOptions] as SortOptions[],
|
|
70
|
-
this.dateRange,
|
|
71
|
-
this.pagination
|
|
72
|
-
);
|
|
73
|
-
}
|
|
74
|
-
|
|
75
|
-
withSort(sort: SortOptions): QueryOptions {
|
|
76
|
-
return new QueryOptions(
|
|
77
|
-
[...this.whereClauses] as WhereClause[],
|
|
78
|
-
[...this.sortOptions, sort] as SortOptions[],
|
|
79
|
-
this.dateRange,
|
|
80
|
-
this.pagination
|
|
81
|
-
);
|
|
82
|
-
}
|
|
83
|
-
|
|
84
|
-
withDateRange(dateRange: DateRangeOptions): QueryOptions {
|
|
85
|
-
return new QueryOptions(
|
|
86
|
-
[...this.whereClauses] as WhereClause[],
|
|
87
|
-
[...this.sortOptions] as SortOptions[],
|
|
88
|
-
dateRange,
|
|
89
|
-
this.pagination
|
|
90
|
-
);
|
|
91
|
-
}
|
|
92
|
-
|
|
93
|
-
withPagination(pagination: PaginationOptions): QueryOptions {
|
|
94
|
-
return new QueryOptions(
|
|
95
|
-
[...this.whereClauses] as WhereClause[],
|
|
96
|
-
[...this.sortOptions] as SortOptions[],
|
|
97
|
-
this.dateRange,
|
|
98
|
-
pagination
|
|
99
|
-
);
|
|
100
|
-
}
|
|
101
|
-
|
|
102
|
-
withLimit(limit: number): QueryOptions {
|
|
103
|
-
return this.withPagination({
|
|
104
|
-
...this.pagination,
|
|
105
|
-
limit,
|
|
106
|
-
} as PaginationOptions);
|
|
107
|
-
}
|
|
108
|
-
|
|
109
|
-
clearWhere(): QueryOptions {
|
|
110
|
-
return new QueryOptions([], [...this.sortOptions] as SortOptions[], this.dateRange, this.pagination);
|
|
111
|
-
}
|
|
112
|
-
|
|
113
|
-
clearSort(): QueryOptions {
|
|
114
|
-
return new QueryOptions([...this.whereClauses] as WhereClause[], [], this.dateRange, this.pagination);
|
|
115
|
-
}
|
|
116
|
-
|
|
117
|
-
clearDateRange(): QueryOptions {
|
|
118
|
-
return new QueryOptions([...this.whereClauses] as WhereClause[], [...this.sortOptions] as SortOptions[], null, this.pagination);
|
|
119
|
-
}
|
|
120
|
-
|
|
121
|
-
clearPagination(): QueryOptions {
|
|
122
|
-
return new QueryOptions([...this.whereClauses] as WhereClause[], [...this.sortOptions] as SortOptions[], this.dateRange, null);
|
|
123
|
-
}
|
|
124
|
-
|
|
125
|
-
clone(modifications: {
|
|
126
|
-
where?: WhereClause[];
|
|
127
|
-
sort?: SortOptions[];
|
|
128
|
-
dateRange?: DateRangeOptions | null;
|
|
129
|
-
pagination?: PaginationOptions | null;
|
|
130
|
-
}): QueryOptions {
|
|
131
|
-
return Factory.clone(this, modifications);
|
|
132
|
-
}
|
|
133
|
-
}
|
|
134
|
-
|
|
135
|
-
// Factory function
|
|
136
|
-
export function createQueryOptions(options?: {
|
|
137
|
-
where?: WhereClause[];
|
|
138
|
-
sort?: SortOptions[];
|
|
139
|
-
dateRange?: DateRangeOptions;
|
|
140
|
-
pagination?: PaginationOptions;
|
|
141
|
-
}): QueryOptions {
|
|
142
|
-
return options ? QueryOptions.create(options) : QueryOptions.empty();
|
|
143
|
-
}
|
|
@@ -1,95 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Query Options Factory
|
|
3
|
-
* Single Responsibility: Create query options
|
|
4
|
-
*
|
|
5
|
-
* Max lines: 150 (enforced for maintainability)
|
|
6
|
-
*/
|
|
7
|
-
|
|
8
|
-
import type { WhereFilterOp, OrderByDirection } from 'firebase/firestore';
|
|
9
|
-
import type { SortOptions, DateRangeOptions, PaginationOptions } from './QueryOptions';
|
|
10
|
-
import { WhereClause } from './WhereClause';
|
|
11
|
-
import { QueryOptions } from './QueryOptions';
|
|
12
|
-
|
|
13
|
-
/**
|
|
14
|
-
* Create empty query options
|
|
15
|
-
*/
|
|
16
|
-
export function empty(): QueryOptions {
|
|
17
|
-
return QueryOptions.empty();
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
/**
|
|
21
|
-
* Create query options from partial configuration
|
|
22
|
-
*/
|
|
23
|
-
export function create(options: {
|
|
24
|
-
where?: WhereClause[];
|
|
25
|
-
sort?: SortOptions[];
|
|
26
|
-
dateRange?: DateRangeOptions;
|
|
27
|
-
pagination?: PaginationOptions;
|
|
28
|
-
}): QueryOptions {
|
|
29
|
-
return QueryOptions.create(options);
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
/**
|
|
33
|
-
* Create query options with where clause
|
|
34
|
-
*/
|
|
35
|
-
export function withWhere(
|
|
36
|
-
baseOptions: QueryOptions,
|
|
37
|
-
field: string,
|
|
38
|
-
operator: WhereFilterOp,
|
|
39
|
-
value: unknown
|
|
40
|
-
): QueryOptions {
|
|
41
|
-
const clause = new WhereClause(field, operator, value);
|
|
42
|
-
return baseOptions.withWhere(clause);
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
/**
|
|
46
|
-
* Create query options with sort
|
|
47
|
-
*/
|
|
48
|
-
export function withSort(
|
|
49
|
-
baseOptions: QueryOptions,
|
|
50
|
-
field: string,
|
|
51
|
-
direction: OrderByDirection
|
|
52
|
-
): QueryOptions {
|
|
53
|
-
return baseOptions.withSort({ field, direction });
|
|
54
|
-
}
|
|
55
|
-
|
|
56
|
-
/**
|
|
57
|
-
* Create query options with date range
|
|
58
|
-
*/
|
|
59
|
-
export function withDateRange(
|
|
60
|
-
baseOptions: QueryOptions,
|
|
61
|
-
field: string,
|
|
62
|
-
startDate?: Date,
|
|
63
|
-
endDate?: Date
|
|
64
|
-
): QueryOptions {
|
|
65
|
-
return baseOptions.withDateRange({ field, startDate, endDate });
|
|
66
|
-
}
|
|
67
|
-
|
|
68
|
-
/**
|
|
69
|
-
* Create query options with pagination
|
|
70
|
-
*/
|
|
71
|
-
export function withPagination(
|
|
72
|
-
baseOptions: QueryOptions,
|
|
73
|
-
pagination: PaginationOptions
|
|
74
|
-
): QueryOptions {
|
|
75
|
-
return baseOptions.withPagination(pagination);
|
|
76
|
-
}
|
|
77
|
-
|
|
78
|
-
/**
|
|
79
|
-
* Create query options with limit
|
|
80
|
-
*/
|
|
81
|
-
export function withLimit(baseOptions: QueryOptions, limit: number): QueryOptions {
|
|
82
|
-
return baseOptions.withLimit(limit);
|
|
83
|
-
}
|
|
84
|
-
|
|
85
|
-
/**
|
|
86
|
-
* Clone query options with modifications
|
|
87
|
-
*/
|
|
88
|
-
export function clone(baseOptions: QueryOptions, modifications: {
|
|
89
|
-
where?: WhereClause[];
|
|
90
|
-
sort?: SortOptions[];
|
|
91
|
-
dateRange?: DateRangeOptions | null;
|
|
92
|
-
pagination?: PaginationOptions | null;
|
|
93
|
-
}): QueryOptions {
|
|
94
|
-
return baseOptions.clone(modifications);
|
|
95
|
-
}
|