@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
|
@@ -1,150 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Where Clause Value Object
|
|
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
|
-
|
|
13
|
-
/**
|
|
14
|
-
* Valid where operators for Firestore queries
|
|
15
|
-
*/
|
|
16
|
-
export type WhereOperator =
|
|
17
|
-
| '=='
|
|
18
|
-
| '!='
|
|
19
|
-
| '<'
|
|
20
|
-
| '<='
|
|
21
|
-
| '>'
|
|
22
|
-
| '>='
|
|
23
|
-
| 'array-contains'
|
|
24
|
-
| 'array-contains-any'
|
|
25
|
-
| 'in'
|
|
26
|
-
| 'not-in';
|
|
27
|
-
|
|
28
|
-
/**
|
|
29
|
-
* Where clause value object
|
|
30
|
-
* Immutable representation of a single query condition
|
|
31
|
-
*/
|
|
32
|
-
export class WhereClause {
|
|
33
|
-
readonly field: string;
|
|
34
|
-
readonly operator: WhereFilterOp;
|
|
35
|
-
readonly value: unknown;
|
|
36
|
-
|
|
37
|
-
private constructor(field: string, operator: WhereFilterOp, value: unknown) {
|
|
38
|
-
this.field = field;
|
|
39
|
-
this.operator = operator;
|
|
40
|
-
this.value = Object.freeze(value);
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
/**
|
|
44
|
-
* Create a where clause
|
|
45
|
-
*/
|
|
46
|
-
static create(field: string, operator: WhereFilterOp, value: unknown): WhereClause {
|
|
47
|
-
return new WhereClause(field, operator, value);
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
/**
|
|
51
|
-
* Create equality clause (==)
|
|
52
|
-
*/
|
|
53
|
-
static equals(field: string, value: unknown): WhereClause {
|
|
54
|
-
return new WhereClause(field, '==', value);
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
/**
|
|
58
|
-
* Create inequality clause (!=)
|
|
59
|
-
*/
|
|
60
|
-
static notEquals(field: string, value: unknown): WhereClause {
|
|
61
|
-
return new WhereClause(field, '!=', value);
|
|
62
|
-
}
|
|
63
|
-
|
|
64
|
-
/**
|
|
65
|
-
* Create less than clause (<)
|
|
66
|
-
*/
|
|
67
|
-
static lessThan(field: string, value: unknown): WhereClause {
|
|
68
|
-
return new WhereClause(field, '<', value);
|
|
69
|
-
}
|
|
70
|
-
|
|
71
|
-
/**
|
|
72
|
-
* Create less than or equal clause (<=)
|
|
73
|
-
*/
|
|
74
|
-
static lessThanOrEqual(field: string, value: unknown): WhereClause {
|
|
75
|
-
return new WhereClause(field, '<=', value);
|
|
76
|
-
}
|
|
77
|
-
|
|
78
|
-
/**
|
|
79
|
-
* Create greater than clause (>)
|
|
80
|
-
*/
|
|
81
|
-
static greaterThan(field: string, value: unknown): WhereClause {
|
|
82
|
-
return new WhereClause(field, '>', value);
|
|
83
|
-
}
|
|
84
|
-
|
|
85
|
-
/**
|
|
86
|
-
* Create greater than or equal clause (>=)
|
|
87
|
-
*/
|
|
88
|
-
static greaterThanOrEqual(field: string, value: unknown): WhereClause {
|
|
89
|
-
return new WhereClause(field, '>=', value);
|
|
90
|
-
}
|
|
91
|
-
|
|
92
|
-
/**
|
|
93
|
-
* Create array contains clause
|
|
94
|
-
*/
|
|
95
|
-
static arrayContains(field: string, value: unknown): WhereClause {
|
|
96
|
-
return new WhereClause(field, 'array-contains', value);
|
|
97
|
-
}
|
|
98
|
-
|
|
99
|
-
/**
|
|
100
|
-
* Create array contains any clause
|
|
101
|
-
*/
|
|
102
|
-
static arrayContainsAny(field: string, values: unknown[]): WhereClause {
|
|
103
|
-
return new WhereClause(field, 'array-contains-any', values);
|
|
104
|
-
}
|
|
105
|
-
|
|
106
|
-
/**
|
|
107
|
-
* Create in clause
|
|
108
|
-
*/
|
|
109
|
-
static in(field: string, values: unknown[]): WhereClause {
|
|
110
|
-
return new WhereClause(field, 'in', values);
|
|
111
|
-
}
|
|
112
|
-
|
|
113
|
-
/**
|
|
114
|
-
* Create not-in clause
|
|
115
|
-
*/
|
|
116
|
-
static notIn(field: string, values: unknown[]): WhereClause {
|
|
117
|
-
return new WhereClause(field, 'not-in', values);
|
|
118
|
-
}
|
|
119
|
-
|
|
120
|
-
/**
|
|
121
|
-
* Validate where clause
|
|
122
|
-
*/
|
|
123
|
-
validate(): { valid: boolean; errors: string[] } {
|
|
124
|
-
const errors: string[] = [];
|
|
125
|
-
|
|
126
|
-
// Validate field name
|
|
127
|
-
if (!this.field || typeof this.field !== 'string' || this.field.trim() === '') {
|
|
128
|
-
errors.push('Field name must be a non-empty string');
|
|
129
|
-
}
|
|
130
|
-
|
|
131
|
-
// Validate operator
|
|
132
|
-
const validOperators: WhereFilterOp[] = [
|
|
133
|
-
'==', '!=', '<', '<=', '>', '>=',
|
|
134
|
-
'array-contains', 'array-contains-any', 'in', 'not-in'
|
|
135
|
-
];
|
|
136
|
-
if (!validOperators.includes(this.operator)) {
|
|
137
|
-
errors.push(`Invalid operator: ${this.operator}`);
|
|
138
|
-
}
|
|
139
|
-
|
|
140
|
-
// Validate value based on operator
|
|
141
|
-
if (this.operator === 'array-contains-any' || this.operator === 'in' || this.operator === 'not-in') {
|
|
142
|
-
if (!Array.isArray(this.value)) {
|
|
143
|
-
errors.push(`Operator ${this.operator} requires an array value`);
|
|
144
|
-
} else if (this.value.length === 0) {
|
|
145
|
-
errors.push(`Operator ${this.operator} requires a non-empty array`);
|
|
146
|
-
} else if (this.value.length > 10) {
|
|
147
|
-
errors.push(`Operator ${this.operator} supports maximum 10 elements`);
|
|
148
|
-
}
|
|
149
|
-
}
|
|
150
|
-
|
|
@@ -1,149 +0,0 @@
|
|
|
1
|
-
return {
|
|
2
|
-
valid: errors.length === 0,
|
|
3
|
-
errors,
|
|
4
|
-
};
|
|
5
|
-
}
|
|
6
|
-
|
|
7
|
-
/**
|
|
8
|
-
* Check if equals another where clause
|
|
9
|
-
*/
|
|
10
|
-
equals(other: WhereClause): boolean {
|
|
11
|
-
return (
|
|
12
|
-
this.field === other.field &&
|
|
13
|
-
this.operator === other.operator &&
|
|
14
|
-
JSON.stringify(this.value) === JSON.stringify(other.value)
|
|
15
|
-
);
|
|
16
|
-
}
|
|
17
|
-
|
|
18
|
-
/**
|
|
19
|
-
* Check if compatible for compound queries
|
|
20
|
-
* Some operator combinations are not allowed in Firestore
|
|
21
|
-
*/
|
|
22
|
-
isCompatibleWith(other: WhereClause): boolean {
|
|
23
|
-
// Equality and inequality operators can be combined
|
|
24
|
-
// Array operators and membership operators have restrictions
|
|
25
|
-
if (
|
|
26
|
-
(this.isArrayOperator() || this.isMembership()) &&
|
|
27
|
-
(other.isArrayOperator() || other.isMembership())
|
|
28
|
-
) {
|
|
29
|
-
// Only one array/membership clause per query
|
|
30
|
-
return false;
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
return true;
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
/**
|
|
37
|
-
* Get field path components
|
|
38
|
-
* Returns array of field path segments (for nested fields)
|
|
39
|
-
*/
|
|
40
|
-
getFieldPath(): string[] {
|
|
41
|
-
return this.field.split('.');
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
/**
|
|
45
|
-
* Check if field is nested (contains dots)
|
|
46
|
-
*/
|
|
47
|
-
isNestedField(): boolean {
|
|
48
|
-
return this.field.includes('.');
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
/**
|
|
52
|
-
* Get top-level field name
|
|
53
|
-
*/
|
|
54
|
-
getTopLevelField(): string {
|
|
55
|
-
return this.getFieldPath()[0];
|
|
56
|
-
}
|
|
57
|
-
|
|
58
|
-
/**
|
|
59
|
-
* Get human-readable description
|
|
60
|
-
*/
|
|
61
|
-
getDescription(): string {
|
|
62
|
-
const valueStr = Array.isArray(this.value)
|
|
63
|
-
? `[${this.value.map(v => JSON.stringify(v)).join(', ')}]`
|
|
64
|
-
: JSON.stringify(this.value);
|
|
65
|
-
|
|
66
|
-
return `${this.field} ${this.operator} ${valueStr}`;
|
|
67
|
-
}
|
|
68
|
-
|
|
69
|
-
/**
|
|
70
|
-
* Convert to plain object (for serialization)
|
|
71
|
-
*/
|
|
72
|
-
toObject(): { field: string; operator: WhereFilterOp; value: unknown } {
|
|
73
|
-
return {
|
|
74
|
-
field: this.field,
|
|
75
|
-
operator: this.operator,
|
|
76
|
-
value: this.value,
|
|
77
|
-
};
|
|
78
|
-
}
|
|
79
|
-
|
|
80
|
-
/**
|
|
81
|
-
* Create from plain object
|
|
82
|
-
*/
|
|
83
|
-
static fromObject(obj: { field: string; operator: WhereFilterOp; value: unknown }): WhereClause {
|
|
84
|
-
return WhereClause.create(obj.field, obj.operator, obj.value);
|
|
85
|
-
}
|
|
86
|
-
|
|
87
|
-
/**
|
|
88
|
-
* Clone with new value
|
|
89
|
-
*/
|
|
90
|
-
withValue(newValue: unknown): WhereClause {
|
|
91
|
-
return new WhereClause(this.field, this.operator, newValue);
|
|
92
|
-
}
|
|
93
|
-
|
|
94
|
-
/**
|
|
95
|
-
* Clone with new field
|
|
96
|
-
*/
|
|
97
|
-
withField(newField: string): WhereClause {
|
|
98
|
-
return new WhereClause(newField, this.operator, this.value);
|
|
99
|
-
}
|
|
100
|
-
|
|
101
|
-
/**
|
|
102
|
-
* Clone with new operator
|
|
103
|
-
*/
|
|
104
|
-
withOperator(newOperator: WhereFilterOp): WhereClause {
|
|
105
|
-
return new WhereClause(this.field, newOperator, this.value);
|
|
106
|
-
}
|
|
107
|
-
|
|
108
|
-
/**
|
|
109
|
-
* Check if is equality operator
|
|
110
|
-
*/
|
|
111
|
-
isEquality(): boolean {
|
|
112
|
-
return this.operator === '==';
|
|
113
|
-
}
|
|
114
|
-
|
|
115
|
-
/**
|
|
116
|
-
* Check if is inequality operator
|
|
117
|
-
*/
|
|
118
|
-
isInequality(): boolean {
|
|
119
|
-
return this.operator === '!=';
|
|
120
|
-
}
|
|
121
|
-
|
|
122
|
-
/**
|
|
123
|
-
* Check if is comparison operator (<, <=, >, >=)
|
|
124
|
-
*/
|
|
125
|
-
isComparison(): boolean {
|
|
126
|
-
return ['<', '<=', '>', '>='].includes(this.operator);
|
|
127
|
-
}
|
|
128
|
-
|
|
129
|
-
/**
|
|
130
|
-
* Check if is array operator
|
|
131
|
-
*/
|
|
132
|
-
isArrayOperator(): boolean {
|
|
133
|
-
return ['array-contains', 'array-contains-any'].includes(this.operator);
|
|
134
|
-
}
|
|
135
|
-
|
|
136
|
-
/**
|
|
137
|
-
* Check if is membership operator (in, not-in)
|
|
138
|
-
*/
|
|
139
|
-
isMembership(): boolean {
|
|
140
|
-
return ['in', 'not-in'].includes(this.operator);
|
|
141
|
-
}
|
|
142
|
-
|
|
143
|
-
/**
|
|
144
|
-
* Check if operator requires array value
|
|
145
|
-
*/
|
|
146
|
-
requiresArrayValue(): boolean {
|
|
147
|
-
return ['array-contains-any', 'in', 'not-in'].includes(this.operator);
|
|
148
|
-
}
|
|
149
|
-
}
|
|
@@ -1,189 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Error Handler Base Class
|
|
3
|
-
* Single Responsibility: Centralized error handling and conversion
|
|
4
|
-
*
|
|
5
|
-
* Eliminates try-catch duplication across 9+ files.
|
|
6
|
-
* Provides standardized error-to-ErrorInfo conversion.
|
|
7
|
-
* Integrates with existing Result pattern.
|
|
8
|
-
*
|
|
9
|
-
* Max lines: 150 (enforced for maintainability)
|
|
10
|
-
*/
|
|
11
|
-
|
|
12
|
-
import type { ErrorInfo } from '../../domain/utils';
|
|
13
|
-
import { toErrorInfo, successResult, type Result } from '../../domain/utils';
|
|
14
|
-
import { isCancelledError, isQuotaError, isRetryableError } from '../../domain/utils/error-handlers/error-checkers';
|
|
15
|
-
import { ERROR_MESSAGES } from '../../domain/utils/error-handlers/error-messages';
|
|
16
|
-
|
|
17
|
-
/**
|
|
18
|
-
* Error handler options
|
|
19
|
-
*/
|
|
20
|
-
export interface ErrorHandlerOptions {
|
|
21
|
-
/** Default error code if none can be extracted */
|
|
22
|
-
defaultErrorCode?: string;
|
|
23
|
-
/** Custom error message mapper */
|
|
24
|
-
errorMapper?: (error: unknown) => string | null;
|
|
25
|
-
/** Enable detailed logging in development */
|
|
26
|
-
enableDevLogging?: boolean;
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
/**
|
|
30
|
-
* Base class for error handling
|
|
31
|
-
* Provides centralized error conversion and handling
|
|
32
|
-
*/
|
|
33
|
-
export class ErrorHandler {
|
|
34
|
-
private readonly options: ErrorHandlerOptions;
|
|
35
|
-
|
|
36
|
-
constructor(options: ErrorHandlerOptions = {}) {
|
|
37
|
-
this.options = {
|
|
38
|
-
defaultErrorCode: 'unknown/error',
|
|
39
|
-
enableDevLogging: __DEV__,
|
|
40
|
-
...options,
|
|
41
|
-
};
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
/**
|
|
45
|
-
* Wrap an async operation with standardized error handling
|
|
46
|
-
* Eliminates try-catch duplication across services
|
|
47
|
-
*/
|
|
48
|
-
async handleAsync<T>(
|
|
49
|
-
operation: () => Promise<T>,
|
|
50
|
-
errorCode: string = this.options.defaultErrorCode || 'unknown/error'
|
|
51
|
-
): Promise<Result<T>> {
|
|
52
|
-
try {
|
|
53
|
-
const result = await operation();
|
|
54
|
-
return successResult(result);
|
|
55
|
-
} catch (error) {
|
|
56
|
-
if (this.options.enableDevLogging) {
|
|
57
|
-
console.error(`[ErrorHandler] Operation failed: ${errorCode}`, error);
|
|
58
|
-
}
|
|
59
|
-
return { success: false, error: toErrorInfo(error, errorCode) };
|
|
60
|
-
}
|
|
61
|
-
}
|
|
62
|
-
|
|
63
|
-
/**
|
|
64
|
-
* Wrap a synchronous operation with standardized error handling
|
|
65
|
-
*/
|
|
66
|
-
handle<T>(
|
|
67
|
-
operation: () => T,
|
|
68
|
-
errorCode: string = this.options.defaultErrorCode || 'unknown/error'
|
|
69
|
-
): Result<T> {
|
|
70
|
-
try {
|
|
71
|
-
const result = operation();
|
|
72
|
-
return successResult(result);
|
|
73
|
-
} catch (error) {
|
|
74
|
-
if (this.options.enableDevLogging) {
|
|
75
|
-
console.error(`[ErrorHandler] Operation failed: ${errorCode}`, error);
|
|
76
|
-
}
|
|
77
|
-
return { success: false, error: toErrorInfo(error, errorCode) };
|
|
78
|
-
}
|
|
79
|
-
}
|
|
80
|
-
|
|
81
|
-
/**
|
|
82
|
-
* Convert error to ErrorInfo with optional custom code
|
|
83
|
-
*/
|
|
84
|
-
toErrorInfo(error: unknown, code?: string): ErrorInfo {
|
|
85
|
-
// Try custom error mapper first
|
|
86
|
-
if (this.options.errorMapper) {
|
|
87
|
-
const customMessage = this.options.errorMapper(error);
|
|
88
|
-
if (customMessage) {
|
|
89
|
-
return {
|
|
90
|
-
code: code || this.options.defaultErrorCode || 'unknown/error',
|
|
91
|
-
message: customMessage,
|
|
92
|
-
};
|
|
93
|
-
}
|
|
94
|
-
}
|
|
95
|
-
|
|
96
|
-
// Use standard conversion
|
|
97
|
-
return toErrorInfo(error, code || this.options.defaultErrorCode);
|
|
98
|
-
}
|
|
99
|
-
|
|
100
|
-
/**
|
|
101
|
-
* Check if error is a cancelled operation
|
|
102
|
-
*/
|
|
103
|
-
isCancelledError(error: unknown): boolean {
|
|
104
|
-
return isCancelledError(error);
|
|
105
|
-
}
|
|
106
|
-
|
|
107
|
-
/**
|
|
108
|
-
* Check if error is a quota error
|
|
109
|
-
*/
|
|
110
|
-
isQuotaError(error: unknown): boolean {
|
|
111
|
-
return isQuotaError(error);
|
|
112
|
-
}
|
|
113
|
-
|
|
114
|
-
/**
|
|
115
|
-
* Check if error is retryable
|
|
116
|
-
*/
|
|
117
|
-
isRetryableError(error: unknown): boolean {
|
|
118
|
-
return isRetryableError(error);
|
|
119
|
-
}
|
|
120
|
-
|
|
121
|
-
/**
|
|
122
|
-
* Get user-friendly error message
|
|
123
|
-
* Maps error codes to user-friendly messages
|
|
124
|
-
*/
|
|
125
|
-
getUserMessage(error: ErrorInfo): string {
|
|
126
|
-
// Check if it's a known error category
|
|
127
|
-
if (error.code.startsWith('auth/')) {
|
|
128
|
-
return this.getAuthUserMessage(error.code);
|
|
129
|
-
}
|
|
130
|
-
if (error.code.startsWith('firestore/')) {
|
|
131
|
-
return this.getFirestoreUserMessage(error.code);
|
|
132
|
-
}
|
|
133
|
-
if (error.code.startsWith('storage/')) {
|
|
134
|
-
return ERROR_MESSAGES.STORAGE.GENERIC_ERROR;
|
|
135
|
-
}
|
|
136
|
-
|
|
137
|
-
return error.message || ERROR_MESSAGES.GENERAL.UNKNOWN;
|
|
138
|
-
}
|
|
139
|
-
|
|
140
|
-
/**
|
|
141
|
-
* Get user-friendly auth error message
|
|
142
|
-
*/
|
|
143
|
-
private getAuthUserMessage(code: string): string {
|
|
144
|
-
// Map common auth error codes to user-friendly messages
|
|
145
|
-
const authMessages: Record<string, string> = {
|
|
146
|
-
'auth/user-not-found': ERROR_MESSAGES.AUTH.USER_NOT_FOUND,
|
|
147
|
-
'auth/wrong-password': ERROR_MESSAGES.AUTH.INVALID_CREDENTIALS,
|
|
148
|
-
'auth/email-already-in-use': ERROR_MESSAGES.AUTH.EMAIL_ALREADY_IN_USE,
|
|
149
|
-
'auth/invalid-email': ERROR_MESSAGES.AUTH.INVALID_EMAIL,
|
|
150
|
-
'auth/weak-password': ERROR_MESSAGES.AUTH.WEAK_PASSWORD,
|
|
151
|
-
'auth/too-many-requests': ERROR_MESSAGES.AUTH.TOO_MANY_REQUESTS,
|
|
152
|
-
'auth/user-disabled': ERROR_MESSAGES.AUTH.USER_DISABLED,
|
|
153
|
-
};
|
|
154
|
-
|
|
155
|
-
return authMessages[code] || ERROR_MESSAGES.AUTH.GENERIC_ERROR;
|
|
156
|
-
}
|
|
157
|
-
|
|
158
|
-
/**
|
|
159
|
-
* Get user-friendly firestore error message
|
|
160
|
-
*/
|
|
161
|
-
private getFirestoreUserMessage(code: string): string {
|
|
162
|
-
const firestoreMessages: Record<string, string> = {
|
|
163
|
-
'firestore/permission-denied': ERROR_MESSAGES.FIRESTORE.PERMISSION_DENIED,
|
|
164
|
-
'firestore/not-found': ERROR_MESSAGES.FIRESTORE.NOT_FOUND,
|
|
165
|
-
'firestore/unavailable': ERROR_MESSAGES.FIRESTORE.UNAVAILABLE,
|
|
166
|
-
};
|
|
167
|
-
|
|
168
|
-
return firestoreMessages[code] || ERROR_MESSAGES.FIRESTORE.GENERIC_ERROR;
|
|
169
|
-
}
|
|
170
|
-
|
|
171
|
-
/**
|
|
172
|
-
* Create a failure result from error code
|
|
173
|
-
*/
|
|
174
|
-
failureFrom(code: string, message?: string): Result {
|
|
175
|
-
return {
|
|
176
|
-
success: false,
|
|
177
|
-
error: {
|
|
178
|
-
code,
|
|
179
|
-
message: message || ERROR_MESSAGES.GENERAL.UNKNOWN,
|
|
180
|
-
},
|
|
181
|
-
};
|
|
182
|
-
}
|
|
183
|
-
}
|
|
184
|
-
|
|
185
|
-
/**
|
|
186
|
-
* Default error handler instance
|
|
187
|
-
* Can be used across the application
|
|
188
|
-
*/
|
|
189
|
-
export const defaultErrorHandler = new ErrorHandler();
|
|
@@ -1,150 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Error Handler Base Class
|
|
3
|
-
* Single Responsibility: Centralized error handling and conversion
|
|
4
|
-
*
|
|
5
|
-
* Eliminates try-catch duplication across 9+ files.
|
|
6
|
-
* Provides standardized error-to-ErrorInfo conversion.
|
|
7
|
-
* Integrates with existing Result pattern.
|
|
8
|
-
*
|
|
9
|
-
* Max lines: 150 (enforced for maintainability)
|
|
10
|
-
*/
|
|
11
|
-
|
|
12
|
-
import type { ErrorInfo } from '../../domain/utils';
|
|
13
|
-
import { toErrorInfo, successResult, type Result } from '../../domain/utils';
|
|
14
|
-
import { isCancelledError, isQuotaError, isRetryableError } from '../../domain/utils/error-handlers/error-checkers';
|
|
15
|
-
import { ERROR_MESSAGES } from '../../domain/utils/error-handlers/error-messages';
|
|
16
|
-
|
|
17
|
-
/**
|
|
18
|
-
* Error handler options
|
|
19
|
-
*/
|
|
20
|
-
export interface ErrorHandlerOptions {
|
|
21
|
-
/** Default error code if none can be extracted */
|
|
22
|
-
defaultErrorCode?: string;
|
|
23
|
-
/** Custom error message mapper */
|
|
24
|
-
errorMapper?: (error: unknown) => string | null;
|
|
25
|
-
/** Enable detailed logging in development */
|
|
26
|
-
enableDevLogging?: boolean;
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
/**
|
|
30
|
-
* Base class for error handling
|
|
31
|
-
* Provides centralized error conversion and handling
|
|
32
|
-
*/
|
|
33
|
-
export class ErrorHandler {
|
|
34
|
-
private readonly options: ErrorHandlerOptions;
|
|
35
|
-
|
|
36
|
-
constructor(options: ErrorHandlerOptions = {}) {
|
|
37
|
-
this.options = {
|
|
38
|
-
defaultErrorCode: 'unknown/error',
|
|
39
|
-
enableDevLogging: __DEV__,
|
|
40
|
-
...options,
|
|
41
|
-
};
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
/**
|
|
45
|
-
* Wrap an async operation with standardized error handling
|
|
46
|
-
* Eliminates try-catch duplication across services
|
|
47
|
-
*/
|
|
48
|
-
async handleAsync<T>(
|
|
49
|
-
operation: () => Promise<T>,
|
|
50
|
-
errorCode: string = this.options.defaultErrorCode || 'unknown/error'
|
|
51
|
-
): Promise<Result<T>> {
|
|
52
|
-
try {
|
|
53
|
-
const result = await operation();
|
|
54
|
-
return successResult(result);
|
|
55
|
-
} catch (error) {
|
|
56
|
-
if (this.options.enableDevLogging) {
|
|
57
|
-
console.error(`[ErrorHandler] Operation failed: ${errorCode}`, error);
|
|
58
|
-
}
|
|
59
|
-
return { success: false, error: toErrorInfo(error, errorCode) };
|
|
60
|
-
}
|
|
61
|
-
}
|
|
62
|
-
|
|
63
|
-
/**
|
|
64
|
-
* Wrap a synchronous operation with standardized error handling
|
|
65
|
-
*/
|
|
66
|
-
handle<T>(
|
|
67
|
-
operation: () => T,
|
|
68
|
-
errorCode: string = this.options.defaultErrorCode || 'unknown/error'
|
|
69
|
-
): Result<T> {
|
|
70
|
-
try {
|
|
71
|
-
const result = operation();
|
|
72
|
-
return successResult(result);
|
|
73
|
-
} catch (error) {
|
|
74
|
-
if (this.options.enableDevLogging) {
|
|
75
|
-
console.error(`[ErrorHandler] Operation failed: ${errorCode}`, error);
|
|
76
|
-
}
|
|
77
|
-
return { success: false, error: toErrorInfo(error, errorCode) };
|
|
78
|
-
}
|
|
79
|
-
}
|
|
80
|
-
|
|
81
|
-
/**
|
|
82
|
-
* Convert error to ErrorInfo with optional custom code
|
|
83
|
-
*/
|
|
84
|
-
toErrorInfo(error: unknown, code?: string): ErrorInfo {
|
|
85
|
-
// Try custom error mapper first
|
|
86
|
-
if (this.options.errorMapper) {
|
|
87
|
-
const customMessage = this.options.errorMapper(error);
|
|
88
|
-
if (customMessage) {
|
|
89
|
-
return {
|
|
90
|
-
code: code || this.options.defaultErrorCode || 'unknown/error',
|
|
91
|
-
message: customMessage,
|
|
92
|
-
};
|
|
93
|
-
}
|
|
94
|
-
}
|
|
95
|
-
|
|
96
|
-
// Use standard conversion
|
|
97
|
-
return toErrorInfo(error, code || this.options.defaultErrorCode);
|
|
98
|
-
}
|
|
99
|
-
|
|
100
|
-
/**
|
|
101
|
-
* Check if error is a cancelled operation
|
|
102
|
-
*/
|
|
103
|
-
isCancelledError(error: unknown): boolean {
|
|
104
|
-
return isCancelledError(error);
|
|
105
|
-
}
|
|
106
|
-
|
|
107
|
-
/**
|
|
108
|
-
* Check if error is a quota error
|
|
109
|
-
*/
|
|
110
|
-
isQuotaError(error: unknown): boolean {
|
|
111
|
-
return isQuotaError(error);
|
|
112
|
-
}
|
|
113
|
-
|
|
114
|
-
/**
|
|
115
|
-
* Check if error is retryable
|
|
116
|
-
*/
|
|
117
|
-
isRetryableError(error: unknown): boolean {
|
|
118
|
-
return isRetryableError(error);
|
|
119
|
-
}
|
|
120
|
-
|
|
121
|
-
/**
|
|
122
|
-
* Get user-friendly error message
|
|
123
|
-
* Maps error codes to user-friendly messages
|
|
124
|
-
*/
|
|
125
|
-
getUserMessage(error: ErrorInfo): string {
|
|
126
|
-
// Check if it's a known error category
|
|
127
|
-
if (error.code.startsWith('auth/')) {
|
|
128
|
-
return this.getAuthUserMessage(error.code);
|
|
129
|
-
}
|
|
130
|
-
if (error.code.startsWith('firestore/')) {
|
|
131
|
-
return this.getFirestoreUserMessage(error.code);
|
|
132
|
-
}
|
|
133
|
-
if (error.code.startsWith('storage/')) {
|
|
134
|
-
return ERROR_MESSAGES.STORAGE.GENERIC_ERROR;
|
|
135
|
-
}
|
|
136
|
-
|
|
137
|
-
return error.message || ERROR_MESSAGES.GENERAL.UNKNOWN;
|
|
138
|
-
}
|
|
139
|
-
|
|
140
|
-
/**
|
|
141
|
-
* Get user-friendly auth error message
|
|
142
|
-
*/
|
|
143
|
-
private getAuthUserMessage(code: string): string {
|
|
144
|
-
// Map common auth error codes to user-friendly messages
|
|
145
|
-
const authMessages: Record<string, string> = {
|
|
146
|
-
'auth/user-not-found': ERROR_MESSAGES.AUTH.USER_NOT_FOUND,
|
|
147
|
-
'auth/wrong-password': ERROR_MESSAGES.AUTH.INVALID_CREDENTIALS,
|
|
148
|
-
'auth/email-already-in-use': ERROR_MESSAGES.AUTH.EMAIL_ALREADY_IN_USE,
|
|
149
|
-
'auth/invalid-email': ERROR_MESSAGES.AUTH.INVALID_EMAIL,
|
|
150
|
-
'auth/weak-password': ERROR_MESSAGES.AUTH.WEAK_PASSWORD,
|
|
@@ -1,39 +0,0 @@
|
|
|
1
|
-
'auth/too-many-requests': ERROR_MESSAGES.AUTH.TOO_MANY_REQUESTS,
|
|
2
|
-
'auth/user-disabled': ERROR_MESSAGES.AUTH.USER_DISABLED,
|
|
3
|
-
};
|
|
4
|
-
|
|
5
|
-
return authMessages[code] || ERROR_MESSAGES.AUTH.GENERIC_ERROR;
|
|
6
|
-
}
|
|
7
|
-
|
|
8
|
-
/**
|
|
9
|
-
* Get user-friendly firestore error message
|
|
10
|
-
*/
|
|
11
|
-
private getFirestoreUserMessage(code: string): string {
|
|
12
|
-
const firestoreMessages: Record<string, string> = {
|
|
13
|
-
'firestore/permission-denied': ERROR_MESSAGES.FIRESTORE.PERMISSION_DENIED,
|
|
14
|
-
'firestore/not-found': ERROR_MESSAGES.FIRESTORE.NOT_FOUND,
|
|
15
|
-
'firestore/unavailable': ERROR_MESSAGES.FIRESTORE.UNAVAILABLE,
|
|
16
|
-
};
|
|
17
|
-
|
|
18
|
-
return firestoreMessages[code] || ERROR_MESSAGES.FIRESTORE.GENERIC_ERROR;
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
/**
|
|
22
|
-
* Create a failure result from error code
|
|
23
|
-
*/
|
|
24
|
-
failureFrom(code: string, message?: string): Result {
|
|
25
|
-
return {
|
|
26
|
-
success: false,
|
|
27
|
-
error: {
|
|
28
|
-
code,
|
|
29
|
-
message: message || ERROR_MESSAGES.GENERAL.UNKNOWN,
|
|
30
|
-
},
|
|
31
|
-
};
|
|
32
|
-
}
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
/**
|
|
36
|
-
* Default error handler instance
|
|
37
|
-
* Can be used across the application
|
|
38
|
-
*/
|
|
39
|
-
export const defaultErrorHandler = new ErrorHandler();
|