@umituz/react-native-firebase 2.6.2 → 2.6.4
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 +2 -34
- package/src/application/auth/use-cases/index.ts +1 -21
- package/src/domains/account-deletion/domain/index.ts +1 -8
- package/src/domains/account-deletion/index.ts +0 -42
- package/src/domains/account-deletion/infrastructure/services/AccountDeletionExecutor.ts +79 -0
- package/src/domains/account-deletion/infrastructure/services/AccountDeletionTypes.ts +0 -1
- package/src/domains/account-deletion/infrastructure/services/account-deletion.service.ts +2 -14
- package/src/domains/auth/index.ts +3 -12
- package/src/domains/auth/infrastructure.ts +11 -0
- package/src/domains/firestore/domain/entities/Collection.ts +0 -2
- package/src/domains/firestore/domain/index.ts +8 -12
- package/src/domains/firestore/domain/value-objects/{QueryOptions.ts.bak → QueryOptions.ts} +20 -68
- package/src/domains/firestore/domain/value-objects/QueryOptionsFactory.ts +95 -0
- package/src/domains/firestore/domain/value-objects/QueryOptionsHelpers.ts +110 -0
- package/src/domains/firestore/domain/value-objects/WhereClause.ts +115 -0
- package/src/domains/firestore/domain/value-objects/WhereClauseFactory.ts +101 -0
- package/src/domains/firestore/domain/value-objects/WhereClauseHelpers.ts +123 -0
- package/src/domains/firestore/domain/value-objects/WhereClauseValidation.ts +83 -0
- package/src/domains/firestore/presentation/hooks/useFirestoreMutation.ts +1 -1
- package/src/domains/firestore/presentation/hooks/useFirestoreQuery.ts +1 -1
- package/src/shared/infrastructure/config/base/ServiceClientSingleton.ts +29 -0
- package/src/application/auth/ports/AuthPort.ts.bak +0 -164
- package/src/application/auth/ports/AuthPort_part_aa +0 -150
- package/src/application/auth/ports/AuthPort_part_ab +0 -14
- package/src/application/auth/use-cases/SignInUseCase.ts.bak +0 -253
- 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 +0 -150
- package/src/application/auth/use-cases/SignInUseCase_part_ab +0 -103
- package/src/application/auth/use-cases/SignOutUseCase.ts.bak +0 -288
- 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 +0 -150
- package/src/application/auth/use-cases/SignOutUseCase_part_ab +0 -138
- package/src/domains/account-deletion/domain/services/UserValidationHelpers.ts.bak +0 -181
- package/src/domains/account-deletion/domain/services/UserValidationHelpers_part_aa +0 -150
- package/src/domains/account-deletion/domain/services/UserValidationHelpers_part_ab +0 -31
- package/src/domains/account-deletion/domain/services/UserValidationService.ts.bak +0 -286
- package/src/domains/account-deletion/domain/services/UserValidationService_part_aa +0 -150
- package/src/domains/account-deletion/domain/services/UserValidationService_part_ab +0 -136
- package/src/domains/account-deletion/infrastructure/services/AccountDeletionExecutor.ts.bak +0 -230
- package/src/domains/account-deletion/infrastructure/services/AccountDeletionExecutor_part_aa +0 -150
- package/src/domains/account-deletion/infrastructure/services/AccountDeletionExecutor_part_ab +0 -80
- package/src/domains/account-deletion/infrastructure/services/AccountDeletionReauthHandler.ts.bak +0 -174
- package/src/domains/account-deletion/infrastructure/services/AccountDeletionReauthHandler_part_aa +0 -150
- package/src/domains/account-deletion/infrastructure/services/AccountDeletionReauthHandler_part_ab +0 -24
- package/src/domains/account-deletion/infrastructure/services/AccountDeletionRepository.ts.bak +0 -266
- package/src/domains/account-deletion/infrastructure/services/AccountDeletionRepository_part_aa +0 -150
- package/src/domains/account-deletion/infrastructure/services/AccountDeletionRepository_part_ab +0 -116
- package/src/domains/account-deletion/infrastructure/services/reauthentication.service.ts.bak +0 -160
- package/src/domains/account-deletion/infrastructure/services/reauthentication.service_part_aa +0 -150
- package/src/domains/account-deletion/infrastructure/services/reauthentication.service_part_ab +0 -10
- package/src/domains/auth/infrastructure.ts.bak +0 -156
- package/src/domains/auth/infrastructure_part_aa +0 -150
- package/src/domains/auth/infrastructure_part_ab +0 -6
- package/src/domains/auth/presentation/hooks/GoogleOAuthHelpers.ts +0 -0
- package/src/domains/auth/presentation/hooks/GoogleOAuthHookService.ts.bak +0 -247
- package/src/domains/auth/presentation/hooks/GoogleOAuthHookService_part_aa +0 -150
- package/src/domains/auth/presentation/hooks/GoogleOAuthHookService_part_ab +0 -97
- package/src/domains/auth/presentation/hooks/GoogleOAuthService.ts +0 -0
- package/src/domains/firestore/domain/entities/Collection.ts.bak +0 -288
- package/src/domains/firestore/domain/entities/Collection_part_aa +0 -150
- package/src/domains/firestore/domain/entities/Collection_part_ab +0 -138
- package/src/domains/firestore/domain/entities/Document.ts.bak +0 -233
- 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 +0 -150
- package/src/domains/firestore/domain/entities/Document_part_ab +0 -83
- package/src/domains/firestore/domain/services/QueryService.ts.bak +0 -182
- package/src/domains/firestore/domain/services/QueryServiceAnalysis.ts.bak +0 -169
- package/src/domains/firestore/domain/services/QueryServiceAnalysis_part_aa +0 -150
- package/src/domains/firestore/domain/services/QueryServiceAnalysis_part_ab +0 -19
- package/src/domains/firestore/domain/services/QueryServiceHelpers.ts.bak +0 -151
- package/src/domains/firestore/domain/services/QueryServiceHelpers_part_aa +0 -150
- package/src/domains/firestore/domain/services/QueryServiceHelpers_part_ab +0 -1
- package/src/domains/firestore/domain/services/QueryService_part_aa +0 -150
- package/src/domains/firestore/domain/services/QueryService_part_ab +0 -32
- package/src/domains/firestore/domain/value-objects/QueryOptionsSerialization.ts.bak +0 -207
- package/src/domains/firestore/domain/value-objects/QueryOptionsSerialization_part_aa +0 -150
- package/src/domains/firestore/domain/value-objects/QueryOptionsSerialization_part_ab +0 -57
- package/src/domains/firestore/domain/value-objects/QueryOptionsValidation.ts.bak +0 -182
- package/src/domains/firestore/domain/value-objects/QueryOptionsValidation_part_aa +0 -150
- package/src/domains/firestore/domain/value-objects/QueryOptionsValidation_part_ab +0 -32
- package/src/domains/firestore/domain/value-objects/QueryOptions_part_aa +0 -150
- package/src/domains/firestore/domain/value-objects/QueryOptions_part_ab +0 -41
- package/src/domains/firestore/domain/value-objects/WhereClause.ts.bak +0 -299
- package/src/domains/firestore/domain/value-objects/WhereClauseFactory.ts.bak +0 -207
- package/src/domains/firestore/domain/value-objects/WhereClauseFactory_part_aa +0 -150
- package/src/domains/firestore/domain/value-objects/WhereClauseFactory_part_ab +0 -57
- package/src/domains/firestore/domain/value-objects/WhereClause_part_aa +0 -150
- package/src/domains/firestore/domain/value-objects/WhereClause_part_ab +0 -149
- package/src/shared/infrastructure/base/ErrorHandler.ts.bak +0 -189
- package/src/shared/infrastructure/base/ErrorHandler_part_aa +0 -150
- package/src/shared/infrastructure/base/ErrorHandler_part_ab +0 -39
- package/src/shared/infrastructure/base/ServiceBase.ts.bak +0 -220
- package/src/shared/infrastructure/base/ServiceBase_part_aa +0 -150
- package/src/shared/infrastructure/base/ServiceBase_part_ab +0 -70
- package/src/shared/infrastructure/config/base/ServiceClientSingleton.ts.bak +0 -155
- package/src/shared/infrastructure/config/base/ServiceClientSingleton_part_aa +0 -150
- package/src/shared/infrastructure/config/base/ServiceClientSingleton_part_ab +0 -5
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Query Options Helpers
|
|
3
|
+
* Single Responsibility: Provide helper functions for query options
|
|
4
|
+
*
|
|
5
|
+
* Max lines: 150 (enforced for maintainability)
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
import type { QueryOptions } from './QueryOptions';
|
|
9
|
+
import type { SortOptions, DateRangeOptions, PaginationOptions } from './QueryOptions';
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* Check if query options has where clauses
|
|
13
|
+
*/
|
|
14
|
+
export function hasWhereClauses(options: QueryOptions): boolean {
|
|
15
|
+
return options.whereClauses.length > 0;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* Check if query options has sort options
|
|
20
|
+
*/
|
|
21
|
+
export function hasSortOptions(options: QueryOptions): boolean {
|
|
22
|
+
return options.sortOptions.length > 0;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
/**
|
|
26
|
+
* Check if query options has date range
|
|
27
|
+
*/
|
|
28
|
+
export function hasDateRange(options: QueryOptions): boolean {
|
|
29
|
+
return options.dateRange !== null;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
/**
|
|
33
|
+
* Check if query options has pagination
|
|
34
|
+
*/
|
|
35
|
+
export function hasPagination(options: QueryOptions): boolean {
|
|
36
|
+
return options.pagination !== null;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
/**
|
|
40
|
+
* Check if query options is empty
|
|
41
|
+
*/
|
|
42
|
+
export function isEmpty(options: QueryOptions): boolean {
|
|
43
|
+
return (
|
|
44
|
+
options.whereClauses.length === 0 &&
|
|
45
|
+
options.sortOptions.length === 0 &&
|
|
46
|
+
options.dateRange === null &&
|
|
47
|
+
options.pagination === null
|
|
48
|
+
);
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
/**
|
|
52
|
+
* Get where clause count
|
|
53
|
+
*/
|
|
54
|
+
export function getWhereClauseCount(options: QueryOptions): number {
|
|
55
|
+
return options.whereClauses.length;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
/**
|
|
59
|
+
* Get sort option count
|
|
60
|
+
*/
|
|
61
|
+
export function getSortOptionCount(options: QueryOptions): number {
|
|
62
|
+
return options.sortOptions.length;
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
/**
|
|
66
|
+
* Get first sort option
|
|
67
|
+
*/
|
|
68
|
+
export function getFirstSortOption(options: QueryOptions): SortOptions | null {
|
|
69
|
+
return options.sortOptions.length > 0 ? options.sortOptions[0] || null : null;
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
/**
|
|
73
|
+
* Check if query has limit
|
|
74
|
+
*/
|
|
75
|
+
export function hasLimit(options: QueryOptions): boolean {
|
|
76
|
+
return options.pagination !== null && options.pagination.limit !== undefined;
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
/**
|
|
80
|
+
* Get limit value
|
|
81
|
+
*/
|
|
82
|
+
export function getLimit(options: QueryOptions): number | null {
|
|
83
|
+
return options.pagination?.limit || null;
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
/**
|
|
87
|
+
* Get cursor value
|
|
88
|
+
*/
|
|
89
|
+
export function getCursor(options: QueryOptions): number | null {
|
|
90
|
+
return options.pagination?.cursor || null;
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
/**
|
|
94
|
+
* Convert query options to summary object
|
|
95
|
+
*/
|
|
96
|
+
export function toSummary(options: QueryOptions): {
|
|
97
|
+
whereCount: number;
|
|
98
|
+
sortCount: number;
|
|
99
|
+
hasDateRange: boolean;
|
|
100
|
+
hasPagination: boolean;
|
|
101
|
+
limit: number | null;
|
|
102
|
+
} {
|
|
103
|
+
return {
|
|
104
|
+
whereCount: options.whereClauses.length,
|
|
105
|
+
sortCount: options.sortOptions.length,
|
|
106
|
+
hasDateRange: options.dateRange !== null,
|
|
107
|
+
hasPagination: options.pagination !== null,
|
|
108
|
+
limit: options.pagination?.limit || null,
|
|
109
|
+
};
|
|
110
|
+
}
|
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Where Clause Value Object (Main)
|
|
3
|
+
* Single Responsibility: Encapsulate where clause conditions
|
|
4
|
+
*
|
|
5
|
+
* Value object that represents a single where clause condition.
|
|
6
|
+
* Provides validation and business logic for query filtering.
|
|
7
|
+
*
|
|
8
|
+
* Max lines: 150 (enforced for maintainability)
|
|
9
|
+
*/
|
|
10
|
+
|
|
11
|
+
import type { WhereFilterOp } from 'firebase/firestore';
|
|
12
|
+
import * as Validation from './WhereClauseValidation';
|
|
13
|
+
import * as Helpers from './WhereClauseHelpers';
|
|
14
|
+
import * as Factory from './WhereClauseFactory';
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* Valid where operators for Firestore queries
|
|
18
|
+
*/
|
|
19
|
+
export type WhereOperator =
|
|
20
|
+
| '=='
|
|
21
|
+
| '!='
|
|
22
|
+
| '<'
|
|
23
|
+
| '<='
|
|
24
|
+
| '>'
|
|
25
|
+
| '>='
|
|
26
|
+
| 'array-contains'
|
|
27
|
+
| 'array-contains-any'
|
|
28
|
+
| 'in'
|
|
29
|
+
| 'not-in';
|
|
30
|
+
|
|
31
|
+
/**
|
|
32
|
+
* Where clause value object
|
|
33
|
+
* Immutable representation of a single query condition
|
|
34
|
+
*/
|
|
35
|
+
export class WhereClause {
|
|
36
|
+
readonly field: string;
|
|
37
|
+
readonly operator: WhereFilterOp;
|
|
38
|
+
readonly value: unknown;
|
|
39
|
+
|
|
40
|
+
constructor(field: string, operator: WhereFilterOp, value: unknown) {
|
|
41
|
+
this.field = field;
|
|
42
|
+
this.operator = operator;
|
|
43
|
+
this.value = Object.freeze(value);
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
// Instance methods using helpers
|
|
47
|
+
validate(): { valid: boolean; errors: string[] } {
|
|
48
|
+
return Validation.validateWhereClause(this);
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
equals(other: WhereClause): boolean {
|
|
52
|
+
return Helpers.whereClausesEqual(this, other);
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
isCompatibleWith(other: WhereClause): boolean {
|
|
56
|
+
return Helpers.areClausesCompatible(this, other);
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
getFieldPath(): string[] {
|
|
60
|
+
return Helpers.getFieldPath(this);
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
isNestedField(): boolean {
|
|
64
|
+
return Helpers.isNestedField(this);
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
getTopLevelField(): string {
|
|
68
|
+
return Helpers.getTopLevelField(this);
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
getDescription(): string {
|
|
72
|
+
return Helpers.getDescription(this);
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
toObject(): { field: string; operator: WhereFilterOp; value: unknown } {
|
|
76
|
+
return Helpers.toObject(this);
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
withValue(newValue: unknown): WhereClause {
|
|
80
|
+
return new WhereClause(this.field, this.operator, newValue);
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
withField(newField: string): WhereClause {
|
|
84
|
+
return new WhereClause(newField, this.operator, this.value);
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
withOperator(newOperator: WhereFilterOp): WhereClause {
|
|
88
|
+
return new WhereClause(this.field, newOperator, this.value);
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
isEquality(): boolean {
|
|
92
|
+
return Helpers.isEqualityClause(this);
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
isInequality(): boolean {
|
|
96
|
+
return Helpers.isInequalityClause(this);
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
isComparison(): boolean {
|
|
100
|
+
return Helpers.isComparisonClause(this);
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
isArrayOperator(): boolean {
|
|
104
|
+
return Helpers.isArrayClause(this);
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
isMembership(): boolean {
|
|
108
|
+
return Helpers.isMembershipClause(this);
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
requiresArrayValue(): boolean {
|
|
112
|
+
return Validation.requiresArrayValue(this.operator);
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Where Clause Factory
|
|
3
|
+
* Single Responsibility: Create where clauses
|
|
4
|
+
*
|
|
5
|
+
* Max lines: 150 (enforced for maintainability)
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
import type { WhereFilterOp } from 'firebase/firestore';
|
|
9
|
+
import { WhereClause } from './WhereClause';
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* Create equals where clause
|
|
13
|
+
*/
|
|
14
|
+
export function equals(field: string, value: unknown): WhereClause {
|
|
15
|
+
return new WhereClause(field, '==', value);
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* Create not-equals where clause
|
|
20
|
+
*/
|
|
21
|
+
export function notEquals(field: string, value: unknown): WhereClause {
|
|
22
|
+
return new WhereClause(field, '!=', value);
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
/**
|
|
26
|
+
* Create less-than where clause
|
|
27
|
+
*/
|
|
28
|
+
export function lessThan(field: string, value: unknown): WhereClause {
|
|
29
|
+
return new WhereClause(field, '<', value);
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
/**
|
|
33
|
+
* Create less-than-or-equal where clause
|
|
34
|
+
*/
|
|
35
|
+
export function lessThanOrEqual(field: string, value: unknown): WhereClause {
|
|
36
|
+
return new WhereClause(field, '<=', value);
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
/**
|
|
40
|
+
* Create greater-than where clause
|
|
41
|
+
*/
|
|
42
|
+
export function greaterThan(field: string, value: unknown): WhereClause {
|
|
43
|
+
return new WhereClause(field, '>', value);
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
/**
|
|
47
|
+
* Create greater-than-or-equal where clause
|
|
48
|
+
*/
|
|
49
|
+
export function greaterThanOrEqual(field: string, value: unknown): WhereClause {
|
|
50
|
+
return new WhereClause(field, '>=', value);
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
/**
|
|
54
|
+
* Create array-contains where clause
|
|
55
|
+
*/
|
|
56
|
+
export function arrayContains(field: string, value: unknown): WhereClause {
|
|
57
|
+
return new WhereClause(field, 'array-contains', value);
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
/**
|
|
61
|
+
* Create in where clause
|
|
62
|
+
*/
|
|
63
|
+
export function inOp(field: string, values: unknown[]): WhereClause {
|
|
64
|
+
return new WhereClause(field, 'in', values);
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
/**
|
|
68
|
+
* Create not-in where clause
|
|
69
|
+
*/
|
|
70
|
+
export function notIn(field: string, values: unknown[]): WhereClause {
|
|
71
|
+
return new WhereClause(field, 'not-in', values);
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
/**
|
|
75
|
+
* Create array-contains-any where clause
|
|
76
|
+
*/
|
|
77
|
+
export function arrayContainsAny(field: string, values: unknown[]): WhereClause {
|
|
78
|
+
return new WhereClause(field, 'array-contains-any', values);
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
/**
|
|
82
|
+
* Create where clause with custom operator
|
|
83
|
+
*/
|
|
84
|
+
export function where(
|
|
85
|
+
field: string,
|
|
86
|
+
operator: WhereFilterOp,
|
|
87
|
+
value: unknown
|
|
88
|
+
): WhereClause {
|
|
89
|
+
return new WhereClause(field, operator, value);
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
/**
|
|
93
|
+
* Create where clause from object
|
|
94
|
+
*/
|
|
95
|
+
export function fromObject(obj: {
|
|
96
|
+
field: string;
|
|
97
|
+
operator: WhereFilterOp;
|
|
98
|
+
value: unknown;
|
|
99
|
+
}): WhereClause {
|
|
100
|
+
return new WhereClause(obj.field, obj.operator, obj.value);
|
|
101
|
+
}
|
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Where Clause Helper Utilities
|
|
3
|
+
* Single Responsibility: Provide helper functions for where clauses
|
|
4
|
+
*
|
|
5
|
+
* Max lines: 150 (enforced for maintainability)
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
import type { WhereFilterOp } from 'firebase/firestore';
|
|
9
|
+
import type { WhereClause } from './WhereClause';
|
|
10
|
+
import {
|
|
11
|
+
isEqualityOperator,
|
|
12
|
+
isInequalityOperator,
|
|
13
|
+
isComparisonOperator,
|
|
14
|
+
isArrayOperator,
|
|
15
|
+
isMembershipOperator,
|
|
16
|
+
} from './WhereClauseValidation';
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* Get field path as array
|
|
20
|
+
*/
|
|
21
|
+
export function getFieldPath(clause: WhereClause): string[] {
|
|
22
|
+
return clause.field.split('.');
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
/**
|
|
26
|
+
* Check if field is nested
|
|
27
|
+
*/
|
|
28
|
+
export function isNestedField(clause: WhereClause): boolean {
|
|
29
|
+
return clause.field.includes('.');
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
/**
|
|
33
|
+
* Get top-level field name
|
|
34
|
+
*/
|
|
35
|
+
export function getTopLevelField(clause: WhereClause): string {
|
|
36
|
+
const parts = clause.field.split('.');
|
|
37
|
+
return parts[0] || '';
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
/**
|
|
41
|
+
* Get description of where clause
|
|
42
|
+
*/
|
|
43
|
+
export function getDescription(clause: WhereClause): string {
|
|
44
|
+
return `${clause.field} ${clause.operator} ${JSON.stringify(clause.value)}`;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
/**
|
|
48
|
+
* Convert where clause to object
|
|
49
|
+
*/
|
|
50
|
+
export function toObject(clause: WhereClause): {
|
|
51
|
+
field: string;
|
|
52
|
+
operator: WhereFilterOp;
|
|
53
|
+
value: unknown;
|
|
54
|
+
} {
|
|
55
|
+
return {
|
|
56
|
+
field: clause.field,
|
|
57
|
+
operator: clause.operator,
|
|
58
|
+
value: clause.value,
|
|
59
|
+
};
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
/**
|
|
63
|
+
* Check if two where clauses are equal
|
|
64
|
+
*/
|
|
65
|
+
export function whereClausesEqual(a: WhereClause, b: WhereClause): boolean {
|
|
66
|
+
return (
|
|
67
|
+
a.field === b.field &&
|
|
68
|
+
a.operator === b.operator &&
|
|
69
|
+
JSON.stringify(a.value) === JSON.stringify(b.value)
|
|
70
|
+
);
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
/**
|
|
74
|
+
* Check if where clauses are compatible (can be used together)
|
|
75
|
+
*/
|
|
76
|
+
export function areClausesCompatible(a: WhereClause, b: WhereClause): boolean {
|
|
77
|
+
// Same field with different operators is not allowed
|
|
78
|
+
if (a.field === b.field && a.operator !== b.operator) {
|
|
79
|
+
return false;
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
// Inequality operators cannot be combined with other inequality operators on same field
|
|
83
|
+
if (a.field === b.field && isInequalityOperator(a.operator) && isInequalityOperator(b.operator)) {
|
|
84
|
+
return false;
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
return true;
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
/**
|
|
91
|
+
* Check if clause is equality type
|
|
92
|
+
*/
|
|
93
|
+
export function isEqualityClause(clause: WhereClause): boolean {
|
|
94
|
+
return isEqualityOperator(clause.operator);
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
/**
|
|
98
|
+
* Check if clause is inequality type
|
|
99
|
+
*/
|
|
100
|
+
export function isInequalityClause(clause: WhereClause): boolean {
|
|
101
|
+
return isInequalityOperator(clause.operator);
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
/**
|
|
105
|
+
* Check if clause is comparison type
|
|
106
|
+
*/
|
|
107
|
+
export function isComparisonClause(clause: WhereClause): boolean {
|
|
108
|
+
return isComparisonOperator(clause.operator);
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
/**
|
|
112
|
+
* Check if clause is array type
|
|
113
|
+
*/
|
|
114
|
+
export function isArrayClause(clause: WhereClause): boolean {
|
|
115
|
+
return isArrayOperator(clause.operator);
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
/**
|
|
119
|
+
* Check if clause is membership type
|
|
120
|
+
*/
|
|
121
|
+
export function isMembershipClause(clause: WhereClause): boolean {
|
|
122
|
+
return isMembershipOperator(clause.operator);
|
|
123
|
+
}
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Where Clause Validation Utilities
|
|
3
|
+
* Single Responsibility: Validate where clauses
|
|
4
|
+
*
|
|
5
|
+
* Max lines: 150 (enforced for maintainability)
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
import type { WhereFilterOp } from 'firebase/firestore';
|
|
9
|
+
import type { WhereClause } from './WhereClause';
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* Validate where clause
|
|
13
|
+
*/
|
|
14
|
+
export function validateWhereClause(clause: WhereClause): {
|
|
15
|
+
valid: boolean;
|
|
16
|
+
errors: string[];
|
|
17
|
+
} {
|
|
18
|
+
const errors: string[] = [];
|
|
19
|
+
|
|
20
|
+
// Field validation
|
|
21
|
+
if (!clause.field || clause.field.trim() === '') {
|
|
22
|
+
errors.push('Field cannot be empty');
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
// Value validation
|
|
26
|
+
if (clause.value === undefined) {
|
|
27
|
+
errors.push('Value cannot be undefined');
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
// Operator-specific validation
|
|
31
|
+
if (requiresArrayValue(clause.operator)) {
|
|
32
|
+
if (!Array.isArray(clause.value)) {
|
|
33
|
+
errors.push(`Operator '${clause.operator}' requires an array value`);
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
return {
|
|
38
|
+
valid: errors.length === 0,
|
|
39
|
+
errors,
|
|
40
|
+
};
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
/**
|
|
44
|
+
* Check if operator requires array value
|
|
45
|
+
*/
|
|
46
|
+
export function requiresArrayValue(operator: WhereFilterOp): boolean {
|
|
47
|
+
return operator === 'in' || operator === 'not-in' || operator === 'array-contains-any';
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
/**
|
|
51
|
+
* Check if operator is equality type
|
|
52
|
+
*/
|
|
53
|
+
export function isEqualityOperator(operator: WhereFilterOp): boolean {
|
|
54
|
+
return operator === '==';
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
/**
|
|
58
|
+
* Check if operator is inequality type
|
|
59
|
+
*/
|
|
60
|
+
export function isInequalityOperator(operator: WhereFilterOp): boolean {
|
|
61
|
+
return operator === '!=';
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
/**
|
|
65
|
+
* Check if operator is comparison type
|
|
66
|
+
*/
|
|
67
|
+
export function isComparisonOperator(operator: WhereFilterOp): boolean {
|
|
68
|
+
return ['<', '<=', '>', '>='].includes(operator);
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
/**
|
|
72
|
+
* Check if operator is array type
|
|
73
|
+
*/
|
|
74
|
+
export function isArrayOperator(operator: WhereFilterOp): boolean {
|
|
75
|
+
return operator === 'array-contains' || operator === 'array-contains-any';
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
/**
|
|
79
|
+
* Check if operator is membership type
|
|
80
|
+
*/
|
|
81
|
+
export function isMembershipOperator(operator: WhereFilterOp): boolean {
|
|
82
|
+
return operator === 'in' || operator === 'not-in';
|
|
83
|
+
}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Service Client Singleton Base
|
|
3
|
+
* Base singleton pattern for service clients
|
|
4
|
+
*
|
|
5
|
+
* Max lines: 150 (enforced for maintainability)
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
export abstract class ServiceClientSingleton<TInstance> {
|
|
9
|
+
protected instance: TInstance | null = null;
|
|
10
|
+
|
|
11
|
+
protected constructor() {}
|
|
12
|
+
|
|
13
|
+
abstract initialize(): Promise<TInstance>;
|
|
14
|
+
|
|
15
|
+
getInstance(): TInstance {
|
|
16
|
+
if (!this.instance) {
|
|
17
|
+
throw new Error('Service not initialized. Call initialize() first.');
|
|
18
|
+
}
|
|
19
|
+
return this.instance;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
isInitialized(): boolean {
|
|
23
|
+
return this.instance !== null;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
reset(): void {
|
|
27
|
+
this.instance = null;
|
|
28
|
+
}
|
|
29
|
+
}
|