@umituz/react-native-firebase 1.13.149 → 1.13.150

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.
Files changed (35) hide show
  1. package/package.json +1 -1
  2. package/src/auth/infrastructure/services/apple-auth.service.ts +10 -2
  3. package/src/auth/infrastructure/services/google-auth.service.ts +10 -2
  4. package/src/auth/infrastructure/services/reauthentication.service.ts +5 -1
  5. package/src/auth/presentation/hooks/shared/auth-hooks.util.ts +60 -0
  6. package/src/auth/presentation/hooks/shared/hook-utils.util.ts +14 -216
  7. package/src/auth/presentation/hooks/shared/safe-state-hooks.util.ts +76 -0
  8. package/src/auth/presentation/hooks/shared/state-hooks.util.ts +97 -0
  9. package/src/domain/utils/async-executor.util.ts +16 -169
  10. package/src/domain/utils/error-handler.util.ts +18 -170
  11. package/src/domain/utils/error-handlers/error-checkers.ts +120 -0
  12. package/src/domain/utils/error-handlers/error-converters.ts +48 -0
  13. package/src/domain/utils/error-handlers/error-messages.ts +18 -0
  14. package/src/domain/utils/executors/advanced-executors.util.ts +59 -0
  15. package/src/domain/utils/executors/basic-executors.util.ts +56 -0
  16. package/src/domain/utils/executors/batch-executors.util.ts +42 -0
  17. package/src/domain/utils/executors/error-converters.util.ts +45 -0
  18. package/src/domain/utils/result/result-creators.ts +49 -0
  19. package/src/domain/utils/result/result-helpers.ts +60 -0
  20. package/src/domain/utils/result/result-types.ts +40 -0
  21. package/src/domain/utils/result.util.ts +28 -127
  22. package/src/domain/utils/validation.util.ts +38 -209
  23. package/src/domain/utils/validators/composite.validator.ts +24 -0
  24. package/src/domain/utils/validators/firebase.validator.ts +45 -0
  25. package/src/domain/utils/validators/generic.validator.ts +59 -0
  26. package/src/domain/utils/validators/string.validator.ts +25 -0
  27. package/src/domain/utils/validators/url.validator.ts +36 -0
  28. package/src/domain/utils/validators/user-input.validator.ts +54 -0
  29. package/src/firestore/infrastructure/middleware/QuotaTrackingMiddleware.ts +10 -3
  30. package/src/firestore/utils/deduplication/timer-manager.util.ts +2 -2
  31. package/src/firestore/utils/pagination.helper.ts +3 -1
  32. package/src/infrastructure/config/FirebaseClient.ts +28 -189
  33. package/src/infrastructure/config/clients/FirebaseClientSingleton.ts +82 -0
  34. package/src/infrastructure/config/services/FirebaseInitializationService.ts +115 -0
  35. package/src/init/createFirebaseInitModule.ts +9 -3
@@ -0,0 +1,42 @@
1
+ /**
2
+ * Batch Async Executors
3
+ * Execute multiple operations in parallel or sequence
4
+ */
5
+
6
+ import type { Result, FailureResult } from '../result.util';
7
+ import { failureResultFromError, successResult } from '../result.util';
8
+
9
+ /**
10
+ * Execute multiple operations in parallel
11
+ * Returns success only if all operations succeed
12
+ */
13
+ export async function executeAll<T>(
14
+ ...operations: (() => Promise<Result<T>>)[]
15
+ ): Promise<Result<T[]>> {
16
+ try {
17
+ const results = await Promise.all(operations.map((op) => op()));
18
+ const failures = results.filter((r) => !r.success);
19
+ if (failures.length > 0) {
20
+ return failures[0] as FailureResult;
21
+ }
22
+ const data = results.map((r) => (r as { success: true; data: T }).data);
23
+ return successResult(data);
24
+ } catch (error) {
25
+ return failureResultFromError(error);
26
+ }
27
+ }
28
+
29
+ /**
30
+ * Execute operations in sequence, stopping at first failure
31
+ */
32
+ export async function executeSequence<T>(
33
+ ...operations: (() => Promise<Result<T>>)[]
34
+ ): Promise<Result<void>> {
35
+ for (const operation of operations) {
36
+ const result = await operation();
37
+ if (!result.success) {
38
+ return result as Result<void>;
39
+ }
40
+ }
41
+ return successResult();
42
+ }
@@ -0,0 +1,45 @@
1
+ /**
2
+ * Error Converters
3
+ * Convert unknown errors to structured ErrorInfo
4
+ */
5
+
6
+ /**
7
+ * Error converter function type
8
+ * Converts unknown errors to ErrorInfo
9
+ */
10
+ export type ErrorConverter = (error: unknown) => { code: string; message: string };
11
+
12
+ /**
13
+ * Default error converter for auth operations
14
+ */
15
+ export function authErrorConverter(error: unknown): { code: string; message: string } {
16
+ if (error instanceof Error) {
17
+ return {
18
+ code: (error as { code?: string }).code ?? 'auth/failed',
19
+ message: error.message,
20
+ };
21
+ }
22
+ return {
23
+ code: 'auth/failed',
24
+ message: typeof error === 'string' ? error : 'Authentication failed',
25
+ };
26
+ }
27
+
28
+ /**
29
+ * Default error converter for operations
30
+ */
31
+ export function defaultErrorConverter(
32
+ error: unknown,
33
+ defaultCode = 'operation/failed'
34
+ ): { code: string; message: string } {
35
+ if (error instanceof Error) {
36
+ return {
37
+ code: (error as { code?: string }).code ?? defaultCode,
38
+ message: error.message,
39
+ };
40
+ }
41
+ return {
42
+ code: defaultCode,
43
+ message: typeof error === 'string' ? error : 'Operation failed',
44
+ };
45
+ }
@@ -0,0 +1,49 @@
1
+ /**
2
+ * Result Creators
3
+ * Factory functions for creating Result instances
4
+ */
5
+
6
+ import type { SuccessResult, FailureResult, ErrorInfo } from './result-types';
7
+
8
+ /**
9
+ * Create a success result with optional data
10
+ */
11
+ export function successResult<T = void>(data?: T): SuccessResult<T> {
12
+ return { success: true, data: data as T };
13
+ }
14
+
15
+ /**
16
+ * Create a failure result with error information
17
+ */
18
+ export function failureResult(error: ErrorInfo): FailureResult {
19
+ return { success: false, error };
20
+ }
21
+
22
+ /**
23
+ * Create a failure result from error code and message
24
+ */
25
+ export function failureResultFrom(code: string, message: string): FailureResult {
26
+ return { success: false, error: { code, message } };
27
+ }
28
+
29
+ /**
30
+ * Create a failure result from an unknown error
31
+ */
32
+ export function failureResultFromError(error: unknown, defaultCode = 'operation/failed'): FailureResult {
33
+ if (error instanceof Error) {
34
+ return {
35
+ success: false,
36
+ error: {
37
+ code: (error as { code?: string }).code ?? defaultCode,
38
+ message: error.message,
39
+ },
40
+ };
41
+ }
42
+ return {
43
+ success: false,
44
+ error: {
45
+ code: defaultCode,
46
+ message: typeof error === 'string' ? error : 'Unknown error occurred',
47
+ },
48
+ };
49
+ }
@@ -0,0 +1,60 @@
1
+ /**
2
+ * Result Helpers
3
+ * Utility functions for working with Result type
4
+ */
5
+
6
+ import type { Result, SuccessResult, FailureResult } from './result-types';
7
+ import { successResult } from './result-creators';
8
+
9
+ /**
10
+ * Check if result is successful
11
+ */
12
+ export function isSuccess<T>(result: Result<T>): result is SuccessResult<T> {
13
+ return result.success === true && result.error === undefined;
14
+ }
15
+
16
+ /**
17
+ * Check if result is a failure
18
+ */
19
+ export function isFailure<T>(result: Result<T>): result is FailureResult {
20
+ return result.success === false;
21
+ }
22
+
23
+ /**
24
+ * Get data from result or return default
25
+ */
26
+ export function getDataOrDefault<T>(result: Result<T>, defaultValue: T): T {
27
+ return isSuccess(result) ? (result.data ?? defaultValue) : defaultValue;
28
+ }
29
+
30
+ /**
31
+ * Map success result data to another type
32
+ */
33
+ export function mapResult<T, U>(
34
+ result: Result<T>,
35
+ mapper: (data: T) => U
36
+ ): Result<U> {
37
+ if (isSuccess(result) && result.data !== undefined) {
38
+ return successResult(mapper(result.data));
39
+ }
40
+ // Return a new failure result to avoid type conflicts
41
+ if (isFailure(result)) {
42
+ return { success: false, error: result.error };
43
+ }
44
+ return successResult();
45
+ }
46
+
47
+ /**
48
+ * Chain multiple results, stopping at first failure
49
+ */
50
+ export async function chainResults<T>(
51
+ ...operations: (() => Promise<Result<T>>)[]
52
+ ): Promise<Result<T>> {
53
+ for (const operation of operations) {
54
+ const result = await operation();
55
+ if (isFailure(result)) {
56
+ return result;
57
+ }
58
+ }
59
+ return successResult();
60
+ }
@@ -0,0 +1,40 @@
1
+ /**
2
+ * Result Types
3
+ * Type definitions for Result pattern
4
+ */
5
+
6
+ /**
7
+ * Standard error information structure
8
+ */
9
+ export interface ErrorInfo {
10
+ code: string;
11
+ message: string;
12
+ }
13
+
14
+ /**
15
+ * Standard result type for operations
16
+ * Success contains data, failure contains error info
17
+ */
18
+ export interface Result<T = void> {
19
+ readonly success: boolean;
20
+ readonly data?: T;
21
+ readonly error?: ErrorInfo;
22
+ }
23
+
24
+ /**
25
+ * Success result type guard
26
+ */
27
+ export type SuccessResult<T = void> = Result<T> & {
28
+ readonly success: true;
29
+ readonly data: T;
30
+ readonly error?: never;
31
+ };
32
+
33
+ /**
34
+ * Failure result type guard
35
+ */
36
+ export type FailureResult = Result & {
37
+ readonly success: false;
38
+ readonly data?: never;
39
+ readonly error: ErrorInfo;
40
+ };
@@ -1,129 +1,30 @@
1
1
  /**
2
2
  * Result Utility
3
- * Unified result type for all operations across auth and firestore modules
4
- * Provides type-safe success/failure handling
5
- */
6
-
7
- /**
8
- * Standard error information structure
9
- */
10
- export interface ErrorInfo {
11
- code: string;
12
- message: string;
13
- }
14
-
15
- /**
16
- * Standard result type for operations
17
- * Success contains data, failure contains error info
18
- */
19
- export interface Result<T = void> {
20
- readonly success: boolean;
21
- readonly data?: T;
22
- readonly error?: ErrorInfo;
23
- }
24
-
25
- /**
26
- * Success result type guard
27
- */
28
- export type SuccessResult<T = void> = Result<T> & { readonly success: true; readonly data: T; readonly error?: never };
29
-
30
- /**
31
- * Failure result type guard
32
- */
33
- export type FailureResult = Result & { readonly success: false; readonly data?: never; readonly error: ErrorInfo };
34
-
35
- /**
36
- * Create a success result with optional data
37
- */
38
- export function successResult<T = void>(data?: T): SuccessResult<T> {
39
- return { success: true, data: data as T };
40
- }
41
-
42
- /**
43
- * Create a failure result with error information
44
- */
45
- export function failureResult(error: ErrorInfo): FailureResult {
46
- return { success: false, error };
47
- }
48
-
49
- /**
50
- * Create a failure result from error code and message
51
- */
52
- export function failureResultFrom(code: string, message: string): FailureResult {
53
- return { success: false, error: { code, message } };
54
- }
55
-
56
- /**
57
- * Create a failure result from an unknown error
58
- */
59
- export function failureResultFromError(error: unknown, defaultCode = 'operation/failed'): FailureResult {
60
- if (error instanceof Error) {
61
- return {
62
- success: false,
63
- error: {
64
- code: (error as { code?: string }).code ?? defaultCode,
65
- message: error.message,
66
- },
67
- };
68
- }
69
- return {
70
- success: false,
71
- error: {
72
- code: defaultCode,
73
- message: typeof error === 'string' ? error : 'Unknown error occurred',
74
- },
75
- };
76
- }
77
-
78
- /**
79
- * Check if result is successful
80
- */
81
- export function isSuccess<T>(result: Result<T>): result is SuccessResult<T> {
82
- return result.success === true && result.error === undefined;
83
- }
84
-
85
- /**
86
- * Check if result is a failure
87
- */
88
- export function isFailure<T>(result: Result<T>): result is FailureResult {
89
- return result.success === false;
90
- }
91
-
92
- /**
93
- * Get data from result or return default
94
- */
95
- export function getDataOrDefault<T>(result: Result<T>, defaultValue: T): T {
96
- return isSuccess(result) ? (result.data ?? defaultValue) : defaultValue;
97
- }
98
-
99
- /**
100
- * Map success result data to another type
101
- */
102
- export function mapResult<T, U>(
103
- result: Result<T>,
104
- mapper: (data: T) => U
105
- ): Result<U> {
106
- if (isSuccess(result) && result.data !== undefined) {
107
- return successResult(mapper(result.data));
108
- }
109
- // Return a new failure result to avoid type conflicts
110
- if (isFailure(result)) {
111
- return { success: false, error: result.error };
112
- }
113
- return successResult();
114
- }
115
-
116
- /**
117
- * Chain multiple results, stopping at first failure
118
- */
119
- export async function chainResults<T>(
120
- ...operations: (() => Promise<Result<T>>)[]
121
- ): Promise<Result<T>> {
122
- for (const operation of operations) {
123
- const result = await operation();
124
- if (isFailure(result)) {
125
- return result;
126
- }
127
- }
128
- return successResult();
129
- }
3
+ * Re-exports all result utilities for backward compatibility
4
+ * @deprecated Import from specific result files instead
5
+ */
6
+
7
+ // Types
8
+ export type {
9
+ ErrorInfo,
10
+ Result,
11
+ SuccessResult,
12
+ FailureResult,
13
+ } from './result/result-types';
14
+
15
+ // Creators
16
+ export {
17
+ successResult,
18
+ failureResult,
19
+ failureResultFrom,
20
+ failureResultFromError,
21
+ } from './result/result-creators';
22
+
23
+ // Helpers
24
+ export {
25
+ isSuccess,
26
+ isFailure,
27
+ getDataOrDefault,
28
+ mapResult,
29
+ chainResults,
30
+ } from './result/result-helpers';
@@ -1,211 +1,40 @@
1
1
  /**
2
2
  * Validation Utility
3
- * Centralized validation utilities for common patterns
4
- */
5
-
6
- /**
7
- * Check if a string is a valid non-empty value
8
- */
9
- export function isValidString(value: unknown): value is string {
10
- return typeof value === 'string' && value.trim().length > 0;
11
- }
12
-
13
- /**
14
- * Check if a string is empty or whitespace only
15
- */
16
- export function isEmptyString(value: unknown): boolean {
17
- return typeof value === 'string' && value.trim().length === 0;
18
- }
19
-
20
- /**
21
- * Validate Firebase API key format
22
- * Firebase API keys typically start with "AIza" followed by 35 characters
23
- */
24
- export function isValidFirebaseApiKey(apiKey: string): boolean {
25
- if (!isValidString(apiKey)) {
26
- return false;
27
- }
28
- const apiKeyPattern = /^AIza[0-9A-Za-z_-]{35}$/;
29
- return apiKeyPattern.test(apiKey.trim());
30
- }
31
-
32
- /**
33
- * Validate Firebase authDomain format
34
- * Expected format: "projectId.firebaseapp.com" or "projectId.web.app"
35
- */
36
- export function isValidFirebaseAuthDomain(authDomain: string): boolean {
37
- if (!isValidString(authDomain)) {
38
- return false;
39
- }
40
- const trimmed = authDomain.trim();
41
- return (
42
- trimmed.includes('.firebaseapp.com') ||
43
- trimmed.includes('.web.app')
44
- );
45
- }
46
-
47
- /**
48
- * Validate Firebase projectId format
49
- * Project IDs must be 6-30 characters, lowercase, alphanumeric, and may contain hyphens
50
- */
51
- export function isValidFirebaseProjectId(projectId: string): boolean {
52
- if (!isValidString(projectId)) {
53
- return false;
54
- }
55
- const pattern = /^[a-z0-9][a-z0-9-]{4,28}[a-z0-9]$/;
56
- return pattern.test(projectId.trim());
57
- }
58
-
59
- /**
60
- * Validate URL format
61
- */
62
- export function isValidUrl(url: string): boolean {
63
- if (!isValidString(url)) {
64
- return false;
65
- }
66
- try {
67
- new URL(url.trim());
68
- return true;
69
- } catch {
70
- return false;
71
- }
72
- }
73
-
74
- /**
75
- * Validate HTTPS URL
76
- */
77
- export function isValidHttpsUrl(url: string): boolean {
78
- if (!isValidString(url)) {
79
- return false;
80
- }
81
- try {
82
- const urlObj = new URL(url.trim());
83
- return urlObj.protocol === 'https:';
84
- } catch {
85
- return false;
86
- }
87
- }
88
-
89
- /**
90
- * Validate email format
91
- */
92
- export function isValidEmail(email: string): boolean {
93
- if (!isValidString(email)) {
94
- return false;
95
- }
96
- const emailPattern = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
97
- return emailPattern.test(email.trim());
98
- }
99
-
100
- /**
101
- * Check if value is defined (not null or undefined)
102
- */
103
- export function isDefined<T>(value: T | null | undefined): value is T {
104
- return value !== null && value !== undefined;
105
- }
106
-
107
- /**
108
- * Check if array is not empty
109
- */
110
- export function isNonEmptyArray<T>(value: unknown): value is [T, ...T[]] {
111
- return Array.isArray(value) && value.length > 0;
112
- }
113
-
114
- /**
115
- * Check if number is in range
116
- */
117
- export function isInRange(value: number, min: number, max: number): boolean {
118
- return typeof value === 'number' && value >= min && value <= max;
119
- }
120
-
121
- /**
122
- * Check if number is positive
123
- */
124
- export function isPositive(value: number): boolean {
125
- return typeof value === 'number' && value > 0;
126
- }
127
-
128
- /**
129
- * Check if number is non-negative
130
- */
131
- export function isNonNegative(value: number): boolean {
132
- return typeof value === 'number' && value >= 0;
133
- }
134
-
135
- /**
136
- * Validate password strength
137
- * At least 8 characters, containing uppercase, lowercase, and number
138
- */
139
- export function isStrongPassword(password: string): boolean {
140
- if (!isValidString(password) || password.length < 8) {
141
- return false;
142
- }
143
- const hasUpperCase = /[A-Z]/.test(password);
144
- const hasLowerCase = /[a-z]/.test(password);
145
- const hasNumber = /[0-9]/.test(password);
146
- return hasUpperCase && hasLowerCase && hasNumber;
147
- }
148
-
149
- /**
150
- * Validate username format
151
- * Alphanumeric, underscores, and hyphens, 3-20 characters
152
- */
153
- export function isValidUsername(username: string): boolean {
154
- if (!isValidString(username)) {
155
- return false;
156
- }
157
- const pattern = /^[a-zA-Z0-9_-]{3,20}$/;
158
- return pattern.test(username);
159
- }
160
-
161
- /**
162
- * Validate phone number format (basic check)
163
- */
164
- export function isValidPhoneNumber(phone: string): boolean {
165
- if (!isValidString(phone)) {
166
- return false;
167
- }
168
- const cleaned = phone.replace(/\s+/g, '').replace(/[-+()]/g, '');
169
- return /^[0-9]{10,15}$/.test(cleaned);
170
- }
171
-
172
- /**
173
- * Validate object has required properties
174
- */
175
- export function hasRequiredProperties<T extends Record<string, unknown>>(
176
- obj: unknown,
177
- requiredProps: (keyof T)[]
178
- ): obj is T {
179
- if (typeof obj !== 'object' || obj === null) {
180
- return false;
181
- }
182
- return requiredProps.every((prop) => prop in obj);
183
- }
184
-
185
- /**
186
- * Validate all items in array match predicate
187
- */
188
- export function allMatch<T>(items: unknown[], predicate: (item: unknown) => item is T): boolean {
189
- return Array.isArray(items) && items.every(predicate);
190
- }
191
-
192
- /**
193
- * Validate at least one item in array matches predicate
194
- */
195
- export function anyMatch<T>(items: unknown[], predicate: (item: unknown) => item is T): boolean {
196
- return Array.isArray(items) && items.some(predicate);
197
- }
198
-
199
- /**
200
- * Create a validator that combines multiple validators
201
- */
202
- export function combineValidators(...validators: ((value: string) => boolean)[]): (value: string) => boolean {
203
- return (value: string) => validators.every((validator) => validator(value));
204
- }
205
-
206
- /**
207
- * Create a validator that checks if value matches one of validators
208
- */
209
- export function anyValidator(...validators: ((value: string) => boolean)[]): (value: string) => boolean {
210
- return (value: string) => validators.some((validator) => validator(value));
211
- }
3
+ * Re-exports all validators for backward compatibility
4
+ * @deprecated Import from specific validator files instead
5
+ */
6
+
7
+ // String Validators
8
+ export { isValidString, isEmptyString, isDefined } from './validators/string.validator';
9
+
10
+ // Firebase Validators
11
+ export {
12
+ isValidFirebaseApiKey,
13
+ isValidFirebaseAuthDomain,
14
+ isValidFirebaseProjectId,
15
+ } from './validators/firebase.validator';
16
+
17
+ // URL Validators
18
+ export { isValidUrl, isValidHttpsUrl } from './validators/url.validator';
19
+
20
+ // User Input Validators
21
+ export {
22
+ isValidEmail,
23
+ isStrongPassword,
24
+ isValidUsername,
25
+ isValidPhoneNumber,
26
+ } from './validators/user-input.validator';
27
+
28
+ // Generic Validators
29
+ export {
30
+ isNonEmptyArray,
31
+ isInRange,
32
+ isPositive,
33
+ isNonNegative,
34
+ hasRequiredProperties,
35
+ allMatch,
36
+ anyMatch,
37
+ } from './validators/generic.validator';
38
+
39
+ // Composite Validators
40
+ export { combineValidators, anyValidator } from './validators/composite.validator';
@@ -0,0 +1,24 @@
1
+ /**
2
+ * Composite Validators
3
+ * Higher-order validators for combining multiple validation rules
4
+ */
5
+
6
+ /**
7
+ * Create a validator that combines multiple validators (AND logic)
8
+ * All validators must pass
9
+ */
10
+ export function combineValidators(
11
+ ...validators: ((value: string) => boolean)[]
12
+ ): (value: string) => boolean {
13
+ return (value: string) => validators.every((validator) => validator(value));
14
+ }
15
+
16
+ /**
17
+ * Create a validator that checks if value matches one of validators (OR logic)
18
+ * At least one validator must pass
19
+ */
20
+ export function anyValidator(
21
+ ...validators: ((value: string) => boolean)[]
22
+ ): (value: string) => boolean {
23
+ return (value: string) => validators.some((validator) => validator(value));
24
+ }