@umituz/react-native-firebase 2.4.14 → 2.4.15
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/domains/account-deletion/infrastructure/services/account-deletion.service.ts +29 -21
- package/src/domains/account-deletion/infrastructure/services/reauthentication.service.ts +2 -2
- package/src/domains/auth/domain/utils/user-metadata.util.ts +72 -0
- package/src/domains/auth/domain/utils/user-validation.util.ts +77 -0
- package/src/domains/auth/infrastructure/services/apple-auth.service.ts +6 -27
- package/src/domains/auth/infrastructure/services/auth-guard.service.ts +39 -33
- package/src/domains/auth/infrastructure/services/base/base-auth.service.ts +2 -2
- package/src/domains/auth/infrastructure/services/email-auth.service.ts +18 -38
- package/src/domains/auth/infrastructure/services/google-auth.service.ts +6 -27
- package/src/domains/auth/infrastructure/services/utils/auth-result-converter.util.ts +71 -0
- package/src/domains/auth/infrastructure/utils/auth-guard.util.ts +98 -0
- package/src/domains/firestore/index.ts +1 -1
- package/src/domains/firestore/infrastructure/config/FirestoreClient.ts +3 -16
- package/src/domains/firestore/infrastructure/repositories/BaseRepository.ts +1 -4
- package/src/domains/firestore/utils/firestore-helper.ts +0 -3
- package/src/domains/firestore/utils/operation/operation-executor.util.ts +3 -3
- package/src/domains/firestore/utils/result/result.util.ts +7 -25
- package/src/index.ts +1 -1
- package/src/shared/domain/utils/async-executor.util.ts +1 -6
- package/src/shared/domain/utils/error-handler.util.ts +4 -2
- package/src/shared/domain/utils/error-handlers/error-checkers.ts +1 -1
- package/src/shared/domain/utils/error-handlers/error-converters.ts +6 -28
- package/src/shared/domain/utils/executors/basic-executors.util.ts +10 -6
- package/src/shared/domain/utils/index.ts +0 -4
- package/src/shared/domain/utils/result/result-creators.ts +3 -16
- package/src/shared/domain/utils/type-guards.util.ts +33 -8
- package/src/shared/domain/utils/validators/firebase.validator.ts +4 -5
- package/src/shared/domain/utils/validators/url.validator.ts +2 -2
- package/src/shared/domain/utils/validators/user-input.validator.ts +1 -1
- package/src/shared/domain/utils/validators/validation.util.ts +63 -0
- package/src/shared/domain/utils/executors/error-converters.util.ts +0 -45
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Auth Result Converter Utilities
|
|
3
|
+
* Shared utilities for converting Result types to service-specific result types
|
|
4
|
+
* Eliminates duplicate result conversion logic in OAuth providers (Apple, Google)
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
import { isSuccess } from '../../../../../shared/domain/utils/result/result-helpers';
|
|
8
|
+
import type { Result } from '../../../../../shared/domain/utils/result/result-types';
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* Generic OAuth authentication success result
|
|
12
|
+
* Used by Apple, Google, and other OAuth providers
|
|
13
|
+
*/
|
|
14
|
+
export interface OAuthAuthSuccessResult {
|
|
15
|
+
success: true;
|
|
16
|
+
userCredential: any;
|
|
17
|
+
isNewUser: boolean;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* Generic OAuth authentication error result
|
|
22
|
+
*/
|
|
23
|
+
export interface OAuthAuthErrorResult {
|
|
24
|
+
success: false;
|
|
25
|
+
error: string;
|
|
26
|
+
code?: string;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* Generic OAuth authentication result (discriminated union)
|
|
31
|
+
*/
|
|
32
|
+
export type OAuthAuthResult = OAuthAuthSuccessResult | OAuthAuthErrorResult;
|
|
33
|
+
|
|
34
|
+
/**
|
|
35
|
+
* Convert standard Result to OAuth-specific result format
|
|
36
|
+
* Eliminates duplicate conversion logic in Apple and Google auth services
|
|
37
|
+
*
|
|
38
|
+
* @param result - Standard Result from executeAuthOperation
|
|
39
|
+
* @param defaultErrorMessage - Default error message for the specific OAuth provider
|
|
40
|
+
* @returns OAuth-specific result with userCredential and isNewUser
|
|
41
|
+
*
|
|
42
|
+
* @example
|
|
43
|
+
* ```typescript
|
|
44
|
+
* // In AppleAuthService
|
|
45
|
+
* private convertToAppleAuthResult(result: Result<{ userCredential: any; isNewUser: boolean }>): AppleAuthResult {
|
|
46
|
+
* return convertToOAuthResult(result, "Apple sign-in failed");
|
|
47
|
+
* }
|
|
48
|
+
*
|
|
49
|
+
* // In GoogleAuthService
|
|
50
|
+
* private convertToGoogleAuthResult(result: Result<{ userCredential: any; isNewUser: boolean }>): GoogleAuthResult {
|
|
51
|
+
* return convertToOAuthResult(result, "Google sign-in failed");
|
|
52
|
+
* }
|
|
53
|
+
* ```
|
|
54
|
+
*/
|
|
55
|
+
export function convertToOAuthResult(
|
|
56
|
+
result: Result<{ userCredential: any; isNewUser: boolean }>,
|
|
57
|
+
defaultErrorMessage: string = 'Authentication failed'
|
|
58
|
+
): OAuthAuthResult {
|
|
59
|
+
if (isSuccess(result) && result.data) {
|
|
60
|
+
return {
|
|
61
|
+
success: true,
|
|
62
|
+
userCredential: result.data.userCredential,
|
|
63
|
+
isNewUser: result.data.isNewUser,
|
|
64
|
+
} as OAuthAuthSuccessResult;
|
|
65
|
+
}
|
|
66
|
+
return {
|
|
67
|
+
success: false,
|
|
68
|
+
error: result.error?.message ?? defaultErrorMessage,
|
|
69
|
+
code: result.error?.code,
|
|
70
|
+
} as OAuthAuthErrorResult;
|
|
71
|
+
}
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Auth Guard Utilities
|
|
3
|
+
* Reusable helpers for auth initialization checks and error handling
|
|
4
|
+
* Eliminates duplicate auth guard patterns across services and hooks
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
import type { Auth } from 'firebase/auth';
|
|
8
|
+
import { getFirebaseAuth } from '../config/FirebaseAuthClient';
|
|
9
|
+
import {
|
|
10
|
+
failureResultFrom,
|
|
11
|
+
successResult,
|
|
12
|
+
failureResultFromError,
|
|
13
|
+
} from '../../../../shared/domain/utils/result/result-creators';
|
|
14
|
+
import type { Result, FailureResult } from '../../../../shared/domain/utils/result/result-types';
|
|
15
|
+
import { ERROR_MESSAGES } from '../../../../shared/domain/utils/error-handlers/error-messages';
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* Result of auth guard check
|
|
19
|
+
*/
|
|
20
|
+
export type AuthGuardResult =
|
|
21
|
+
| { success: true; auth: Auth }
|
|
22
|
+
| FailureResult;
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
* Guard that ensures auth is initialized before proceeding
|
|
26
|
+
* Returns auth instance or failure result
|
|
27
|
+
*
|
|
28
|
+
* @example
|
|
29
|
+
* ```typescript
|
|
30
|
+
* const guardResult = requireAuth();
|
|
31
|
+
* if (!guardResult.success) {
|
|
32
|
+
* return guardResult;
|
|
33
|
+
* }
|
|
34
|
+
* const auth = guardResult.auth;
|
|
35
|
+
* ```
|
|
36
|
+
*/
|
|
37
|
+
export function requireAuth(): AuthGuardResult {
|
|
38
|
+
const auth = getFirebaseAuth();
|
|
39
|
+
if (!auth) {
|
|
40
|
+
return failureResultFrom('auth/not-ready', ERROR_MESSAGES.AUTH.NOT_INITIALIZED);
|
|
41
|
+
}
|
|
42
|
+
return { success: true, auth };
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
/**
|
|
46
|
+
* Execute auth operation with automatic auth initialization check and error handling
|
|
47
|
+
* Eliminates need for manual auth guards and try-catch blocks
|
|
48
|
+
*
|
|
49
|
+
* @param operation - Operation that requires auth instance
|
|
50
|
+
* @returns Result with operation data or error
|
|
51
|
+
*
|
|
52
|
+
* @example
|
|
53
|
+
* ```typescript
|
|
54
|
+
* export async function signInWithEmail(email: string, password: string): Promise<Result<User>> {
|
|
55
|
+
* return withAuth(async (auth) => {
|
|
56
|
+
* const userCredential = await signInWithEmailAndPassword(auth, email, password);
|
|
57
|
+
* return userCredential.user;
|
|
58
|
+
* });
|
|
59
|
+
* }
|
|
60
|
+
* ```
|
|
61
|
+
*/
|
|
62
|
+
export async function withAuth<T>(
|
|
63
|
+
operation: (auth: Auth) => Promise<T>
|
|
64
|
+
): Promise<Result<T>> {
|
|
65
|
+
const guardResult = requireAuth();
|
|
66
|
+
if (!guardResult.success) {
|
|
67
|
+
return guardResult;
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
try {
|
|
71
|
+
const data = await operation(guardResult.auth);
|
|
72
|
+
return successResult(data);
|
|
73
|
+
} catch (error) {
|
|
74
|
+
return failureResultFromError(error, 'auth/operation-failed');
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
/**
|
|
79
|
+
* Synchronous version of withAuth for non-async operations
|
|
80
|
+
*
|
|
81
|
+
* @param operation - Synchronous operation that requires auth instance
|
|
82
|
+
* @returns Result with operation data or error
|
|
83
|
+
*/
|
|
84
|
+
export function withAuthSync<T>(
|
|
85
|
+
operation: (auth: Auth) => T
|
|
86
|
+
): Result<T> {
|
|
87
|
+
const guardResult = requireAuth();
|
|
88
|
+
if (!guardResult.success) {
|
|
89
|
+
return guardResult;
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
try {
|
|
93
|
+
const data = operation(guardResult.auth);
|
|
94
|
+
return successResult(data);
|
|
95
|
+
} catch (error) {
|
|
96
|
+
return failureResultFromError(error, 'auth/operation-failed');
|
|
97
|
+
}
|
|
98
|
+
}
|
|
@@ -120,7 +120,7 @@ export {
|
|
|
120
120
|
runTransaction,
|
|
121
121
|
serverTimestamp,
|
|
122
122
|
} from './utils/firestore-helper';
|
|
123
|
-
export type {
|
|
123
|
+
export type { NoDbResult } from './utils/firestore-helper';
|
|
124
124
|
|
|
125
125
|
// Validation Utilities
|
|
126
126
|
export {
|
|
@@ -38,25 +38,12 @@ class FirestoreClientSingleton extends ServiceClientSingleton<Firestore> {
|
|
|
38
38
|
}
|
|
39
39
|
|
|
40
40
|
private static instance: FirestoreClientSingleton | null = null;
|
|
41
|
-
private static initInProgress = false;
|
|
42
41
|
|
|
43
42
|
static getInstance(): FirestoreClientSingleton {
|
|
44
|
-
if (!
|
|
45
|
-
|
|
46
|
-
try {
|
|
47
|
-
FirestoreClientSingleton.instance = new FirestoreClientSingleton();
|
|
48
|
-
} finally {
|
|
49
|
-
FirestoreClientSingleton.initInProgress = false;
|
|
50
|
-
}
|
|
43
|
+
if (!this.instance) {
|
|
44
|
+
this.instance = new FirestoreClientSingleton();
|
|
51
45
|
}
|
|
52
|
-
|
|
53
|
-
// Wait for initialization to complete if in progress
|
|
54
|
-
while (FirestoreClientSingleton.initInProgress && !FirestoreClientSingleton.instance) {
|
|
55
|
-
// Busy wait - in practice this should be very brief
|
|
56
|
-
// Consider using a Promise-based approach for better async handling
|
|
57
|
-
}
|
|
58
|
-
|
|
59
|
-
return FirestoreClientSingleton.instance!;
|
|
46
|
+
return this.instance;
|
|
60
47
|
}
|
|
61
48
|
|
|
62
49
|
/**
|
|
@@ -71,14 +71,11 @@ export abstract class BaseRepository implements IPathResolver {
|
|
|
71
71
|
* @param operation - Operation to execute
|
|
72
72
|
* @returns Operation result
|
|
73
73
|
* @throws Error if operation fails
|
|
74
|
+
* @note State check is handled by getDb() - all Firestore operations must go through getDb()
|
|
74
75
|
*/
|
|
75
76
|
protected async executeOperation<T>(
|
|
76
77
|
operation: () => Promise<T>
|
|
77
78
|
): Promise<T> {
|
|
78
|
-
if (this.state === RepositoryState.DESTROYED) {
|
|
79
|
-
throw new Error(ERROR_MESSAGES.REPOSITORY.DESTROYED);
|
|
80
|
-
}
|
|
81
|
-
|
|
82
79
|
try {
|
|
83
80
|
return await operation();
|
|
84
81
|
} catch (error) {
|
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
|
|
6
6
|
import type { Firestore } from "../../infrastructure/config/FirestoreClient";
|
|
7
7
|
import { getFirestore } from "../../infrastructure/config/FirestoreClient";
|
|
8
|
-
import type {
|
|
8
|
+
import type { Result } from "../../../../shared/domain/utils/result/result-types";
|
|
9
9
|
import { createNoDbErrorResult } from "../result/result.util";
|
|
10
10
|
|
|
11
11
|
/**
|
|
@@ -13,8 +13,8 @@ import { createNoDbErrorResult } from "../result/result.util";
|
|
|
13
13
|
* Returns error result if db is not available
|
|
14
14
|
*/
|
|
15
15
|
export async function withFirestore<T>(
|
|
16
|
-
operation: (db: Firestore) => Promise<
|
|
17
|
-
): Promise<
|
|
16
|
+
operation: (db: Firestore) => Promise<Result<T>>,
|
|
17
|
+
): Promise<Result<T>> {
|
|
18
18
|
const db = getFirestore();
|
|
19
19
|
if (!db) {
|
|
20
20
|
return createNoDbErrorResult<T>();
|
|
@@ -3,13 +3,9 @@
|
|
|
3
3
|
* Utilities for creating Firestore result objects
|
|
4
4
|
*/
|
|
5
5
|
|
|
6
|
-
|
|
7
|
-
success: boolean;
|
|
8
|
-
data?: T;
|
|
9
|
-
error?: { message: string; code: string };
|
|
10
|
-
}
|
|
6
|
+
import type { Result, FailureResult } from '../../../../shared/domain/utils/result/result-types';
|
|
11
7
|
|
|
12
|
-
export type NoDbResult =
|
|
8
|
+
export type NoDbResult = FailureResult;
|
|
13
9
|
|
|
14
10
|
export const NO_DB_ERROR: NoDbResult = {
|
|
15
11
|
success: false,
|
|
@@ -19,37 +15,23 @@ export const NO_DB_ERROR: NoDbResult = {
|
|
|
19
15
|
/**
|
|
20
16
|
* Create a standard error result
|
|
21
17
|
*/
|
|
22
|
-
export function createErrorResult<T>(message: string, code: string):
|
|
18
|
+
export function createErrorResult<T>(message: string, code: string): Result<T> {
|
|
23
19
|
return { success: false, error: { message, code } };
|
|
24
20
|
}
|
|
25
21
|
|
|
26
22
|
/**
|
|
27
23
|
* Create a standard success result
|
|
28
24
|
*/
|
|
29
|
-
export function createFirestoreSuccessResult<T>(data?: T):
|
|
30
|
-
return { success: true, data };
|
|
25
|
+
export function createFirestoreSuccessResult<T>(data?: T): Result<T> {
|
|
26
|
+
return { success: true, data: data as T };
|
|
31
27
|
}
|
|
32
28
|
|
|
33
29
|
/**
|
|
34
30
|
* Create no-db error result with proper typing
|
|
35
31
|
*/
|
|
36
|
-
export function createNoDbErrorResult<T>():
|
|
32
|
+
export function createNoDbErrorResult<T>(): Result<T> {
|
|
37
33
|
return { success: false, error: NO_DB_ERROR.error };
|
|
38
34
|
}
|
|
39
35
|
|
|
40
|
-
|
|
41
|
-
* Check if result is successful
|
|
42
|
-
*/
|
|
43
|
-
export function isSuccess<T>(result: FirestoreResult<T>): result is FirestoreResult<T> & { success: true } {
|
|
44
|
-
return result.success;
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
/**
|
|
48
|
-
* Check if result is an error
|
|
49
|
-
*/
|
|
50
|
-
export function isError<T>(result: FirestoreResult<T>): result is FirestoreResult<T> & { success: false } {
|
|
51
|
-
return !result.success;
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
// Keep old function name for backwards compatibility
|
|
36
|
+
// Alias for backward compatibility
|
|
55
37
|
export const createSuccessResult = createFirestoreSuccessResult;
|
package/src/index.ts
CHANGED
|
@@ -88,7 +88,7 @@ export {
|
|
|
88
88
|
runTransaction,
|
|
89
89
|
serverTimestamp,
|
|
90
90
|
} from "./domains/firestore/utils/firestore-helper";
|
|
91
|
-
export type {
|
|
91
|
+
export type { NoDbResult } from "./domains/firestore/utils/firestore-helper";
|
|
92
92
|
|
|
93
93
|
// Init Module Factory
|
|
94
94
|
export {
|
|
@@ -1,13 +1,8 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Async Operation Executor Utility
|
|
3
|
-
* Re-exports all async executors
|
|
4
|
-
* @deprecated Import from specific executor files instead
|
|
3
|
+
* Re-exports all async executors
|
|
5
4
|
*/
|
|
6
5
|
|
|
7
|
-
// Error Converters
|
|
8
|
-
export type { ErrorConverter } from './executors/error-converters.util';
|
|
9
|
-
export { authErrorConverter, defaultErrorConverter } from './executors/error-converters.util';
|
|
10
|
-
|
|
11
6
|
// Basic Executors
|
|
12
7
|
export {
|
|
13
8
|
executeOperation,
|
|
@@ -4,9 +4,11 @@
|
|
|
4
4
|
* @deprecated Import from specific error-handler files instead
|
|
5
5
|
*/
|
|
6
6
|
|
|
7
|
+
// Error Types
|
|
8
|
+
export type { ErrorInfo } from './result/result-types';
|
|
9
|
+
|
|
7
10
|
// Error Converters
|
|
8
|
-
export
|
|
9
|
-
export { toErrorInfo, toAuthErrorInfo } from './error-handlers/error-converters';
|
|
11
|
+
export { toErrorInfo } from './error-handlers/error-converters';
|
|
10
12
|
|
|
11
13
|
// Error Checkers
|
|
12
14
|
export {
|
|
@@ -4,45 +4,23 @@
|
|
|
4
4
|
*/
|
|
5
5
|
|
|
6
6
|
import { hasCodeProperty } from '../type-guards.util';
|
|
7
|
-
|
|
8
|
-
/**
|
|
9
|
-
* Standard error structure with code and message
|
|
10
|
-
*/
|
|
11
|
-
export interface ErrorInfo {
|
|
12
|
-
code: string;
|
|
13
|
-
message: string;
|
|
14
|
-
}
|
|
7
|
+
import type { ErrorInfo } from '../result/result-types';
|
|
15
8
|
|
|
16
9
|
/**
|
|
17
10
|
* Convert unknown error to standard error info
|
|
18
11
|
* Handles Error objects, strings, and unknown types
|
|
12
|
+
* @param error - Unknown error object
|
|
13
|
+
* @param defaultCode - Default error code if none found (e.g., 'auth/failed', 'firestore/error')
|
|
19
14
|
*/
|
|
20
|
-
export function toErrorInfo(error: unknown): ErrorInfo {
|
|
21
|
-
if (error instanceof Error) {
|
|
22
|
-
return {
|
|
23
|
-
code: hasCodeProperty(error) ? error.code : 'unknown',
|
|
24
|
-
message: error.message,
|
|
25
|
-
};
|
|
26
|
-
}
|
|
27
|
-
return {
|
|
28
|
-
code: 'unknown',
|
|
29
|
-
message: typeof error === 'string' ? error : 'Unknown error',
|
|
30
|
-
};
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
/**
|
|
34
|
-
* Convert unknown error to auth error info
|
|
35
|
-
* Auth-specific error codes are prefixed with 'auth/'
|
|
36
|
-
*/
|
|
37
|
-
export function toAuthErrorInfo(error: unknown): ErrorInfo {
|
|
15
|
+
export function toErrorInfo(error: unknown, defaultCode: string = 'unknown'): ErrorInfo {
|
|
38
16
|
if (error instanceof Error) {
|
|
39
17
|
return {
|
|
40
|
-
code: hasCodeProperty(error)
|
|
18
|
+
code: hasCodeProperty(error) ? error.code : defaultCode,
|
|
41
19
|
message: error.message,
|
|
42
20
|
};
|
|
43
21
|
}
|
|
44
22
|
return {
|
|
45
|
-
code:
|
|
23
|
+
code: defaultCode,
|
|
46
24
|
message: typeof error === 'string' ? error : 'Unknown error',
|
|
47
25
|
};
|
|
48
26
|
}
|
|
@@ -4,9 +4,13 @@
|
|
|
4
4
|
*/
|
|
5
5
|
|
|
6
6
|
import type { Result } from '../result.util';
|
|
7
|
-
import { successResult } from '../result.util';
|
|
8
|
-
import
|
|
9
|
-
|
|
7
|
+
import { successResult, failureResultFromError } from '../result.util';
|
|
8
|
+
import { toErrorInfo } from '../error-handlers/error-converters';
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* Error converter function type
|
|
12
|
+
*/
|
|
13
|
+
export type ErrorConverter = (error: unknown) => { code: string; message: string };
|
|
10
14
|
|
|
11
15
|
/**
|
|
12
16
|
* Execute async operation with error handling
|
|
@@ -20,7 +24,7 @@ export async function executeOperation<T>(
|
|
|
20
24
|
const data = await operation();
|
|
21
25
|
return successResult(data);
|
|
22
26
|
} catch (error) {
|
|
23
|
-
const converter = errorConverter ??
|
|
27
|
+
const converter = errorConverter ?? ((err: unknown) => toErrorInfo(err, 'operation/failed'));
|
|
24
28
|
return { success: false, error: converter(error) };
|
|
25
29
|
}
|
|
26
30
|
}
|
|
@@ -32,7 +36,7 @@ export async function executeOperationWithCode<T>(
|
|
|
32
36
|
operation: () => Promise<T>,
|
|
33
37
|
defaultErrorCode = 'operation/failed'
|
|
34
38
|
): Promise<Result<T>> {
|
|
35
|
-
return executeOperation(operation, (error) =>
|
|
39
|
+
return executeOperation(operation, (error: unknown) => toErrorInfo(error, defaultErrorCode));
|
|
36
40
|
}
|
|
37
41
|
|
|
38
42
|
/**
|
|
@@ -52,5 +56,5 @@ export async function executeVoidOperation(
|
|
|
52
56
|
export async function executeAuthOperation<T>(
|
|
53
57
|
operation: () => Promise<T>
|
|
54
58
|
): Promise<Result<T>> {
|
|
55
|
-
return executeOperation(operation,
|
|
59
|
+
return executeOperation(operation, (error: unknown) => toErrorInfo(error, 'auth/failed'));
|
|
56
60
|
}
|
|
@@ -30,9 +30,6 @@ export {
|
|
|
30
30
|
executeSequence,
|
|
31
31
|
executeWithRetry,
|
|
32
32
|
executeWithTimeout,
|
|
33
|
-
authErrorConverter,
|
|
34
|
-
defaultErrorConverter,
|
|
35
|
-
type ErrorConverter,
|
|
36
33
|
} from './async-executor.util';
|
|
37
34
|
|
|
38
35
|
// Service configuration
|
|
@@ -57,7 +54,6 @@ export {
|
|
|
57
54
|
// Error handling
|
|
58
55
|
export {
|
|
59
56
|
toErrorInfo,
|
|
60
|
-
toAuthErrorInfo,
|
|
61
57
|
hasErrorCode,
|
|
62
58
|
isCancelledError,
|
|
63
59
|
isQuotaErrorInfo,
|
|
@@ -4,6 +4,7 @@
|
|
|
4
4
|
*/
|
|
5
5
|
|
|
6
6
|
import type { SuccessResult, FailureResult, ErrorInfo } from './result-types';
|
|
7
|
+
import { toErrorInfo } from '../error-handlers/error-converters';
|
|
7
8
|
|
|
8
9
|
/**
|
|
9
10
|
* Create a success result with optional data
|
|
@@ -28,22 +29,8 @@ export function failureResultFrom(code: string, message: string): FailureResult
|
|
|
28
29
|
|
|
29
30
|
/**
|
|
30
31
|
* Create a failure result from an unknown error
|
|
32
|
+
* Uses consolidated error converter for consistency
|
|
31
33
|
*/
|
|
32
34
|
export function failureResultFromError(error: unknown, defaultCode = 'operation/failed'): FailureResult {
|
|
33
|
-
|
|
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
|
-
};
|
|
35
|
+
return failureResult(toErrorInfo(error, defaultCode));
|
|
49
36
|
}
|
|
@@ -5,14 +5,42 @@
|
|
|
5
5
|
* Provides type-safe checking without using 'as' assertions.
|
|
6
6
|
*/
|
|
7
7
|
|
|
8
|
+
/**
|
|
9
|
+
* Type guard for non-null objects
|
|
10
|
+
* Eliminates duplicate object checking pattern throughout the codebase
|
|
11
|
+
*
|
|
12
|
+
* @example
|
|
13
|
+
* ```typescript
|
|
14
|
+
* if (isObject(value)) {
|
|
15
|
+
* // value is Record<string, unknown>
|
|
16
|
+
* }
|
|
17
|
+
* ```
|
|
18
|
+
*/
|
|
19
|
+
export function isObject(value: unknown): value is Record<string, unknown> {
|
|
20
|
+
return typeof value === 'object' && value !== null;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* Type guard for objects with a specific property
|
|
25
|
+
*
|
|
26
|
+
* @param value - Value to check
|
|
27
|
+
* @param key - Property key to check for
|
|
28
|
+
* @returns True if value is an object with the specified property
|
|
29
|
+
*/
|
|
30
|
+
export function hasProperty<K extends string>(
|
|
31
|
+
value: unknown,
|
|
32
|
+
key: K
|
|
33
|
+
): value is Record<K, unknown> {
|
|
34
|
+
return isObject(value) && key in value;
|
|
35
|
+
}
|
|
36
|
+
|
|
8
37
|
/**
|
|
9
38
|
* Type guard for objects with a 'code' property of type string
|
|
10
39
|
* Commonly used for Firebase errors and other error objects
|
|
11
40
|
*/
|
|
12
41
|
export function hasCodeProperty(error: unknown): error is { code: string } {
|
|
13
42
|
return (
|
|
14
|
-
|
|
15
|
-
error !== null &&
|
|
43
|
+
isObject(error) &&
|
|
16
44
|
'code' in error &&
|
|
17
45
|
typeof (error as { code: unknown }).code === 'string'
|
|
18
46
|
);
|
|
@@ -24,8 +52,7 @@ export function hasCodeProperty(error: unknown): error is { code: string } {
|
|
|
24
52
|
*/
|
|
25
53
|
export function hasMessageProperty(error: unknown): error is { message: string } {
|
|
26
54
|
return (
|
|
27
|
-
|
|
28
|
-
error !== null &&
|
|
55
|
+
isObject(error) &&
|
|
29
56
|
'message' in error &&
|
|
30
57
|
typeof (error as { message: unknown }).message === 'string'
|
|
31
58
|
);
|
|
@@ -45,8 +72,7 @@ export function hasCodeAndMessageProperties(error: unknown): error is { code: st
|
|
|
45
72
|
*/
|
|
46
73
|
export function hasNameProperty(error: unknown): error is { name: string } {
|
|
47
74
|
return (
|
|
48
|
-
|
|
49
|
-
error !== null &&
|
|
75
|
+
isObject(error) &&
|
|
50
76
|
'name' in error &&
|
|
51
77
|
typeof (error as { name: unknown }).name === 'string'
|
|
52
78
|
);
|
|
@@ -58,8 +84,7 @@ export function hasNameProperty(error: unknown): error is { name: string } {
|
|
|
58
84
|
*/
|
|
59
85
|
export function hasStackProperty(error: unknown): error is { stack: string } {
|
|
60
86
|
return (
|
|
61
|
-
|
|
62
|
-
error !== null &&
|
|
87
|
+
isObject(error) &&
|
|
63
88
|
'stack' in error &&
|
|
64
89
|
typeof (error as { stack: unknown }).stack === 'string'
|
|
65
90
|
);
|
|
@@ -14,7 +14,7 @@ export function isValidFirebaseApiKey(apiKey: string): boolean {
|
|
|
14
14
|
return false;
|
|
15
15
|
}
|
|
16
16
|
const apiKeyPattern = /^AIza[0-9A-Za-z_-]{35}$/;
|
|
17
|
-
return apiKeyPattern.test(apiKey
|
|
17
|
+
return apiKeyPattern.test(apiKey);
|
|
18
18
|
}
|
|
19
19
|
|
|
20
20
|
/**
|
|
@@ -25,10 +25,9 @@ export function isValidFirebaseAuthDomain(authDomain: string): boolean {
|
|
|
25
25
|
if (!isValidString(authDomain)) {
|
|
26
26
|
return false;
|
|
27
27
|
}
|
|
28
|
-
const trimmed = authDomain.trim();
|
|
29
28
|
return (
|
|
30
|
-
|
|
31
|
-
|
|
29
|
+
authDomain.includes('.firebaseapp.com') ||
|
|
30
|
+
authDomain.includes('.web.app')
|
|
32
31
|
);
|
|
33
32
|
}
|
|
34
33
|
|
|
@@ -41,5 +40,5 @@ export function isValidFirebaseProjectId(projectId: string): boolean {
|
|
|
41
40
|
return false;
|
|
42
41
|
}
|
|
43
42
|
const pattern = /^[a-z0-9][a-z0-9-]{4,28}[a-z0-9]$/;
|
|
44
|
-
return pattern.test(projectId
|
|
43
|
+
return pattern.test(projectId);
|
|
45
44
|
}
|
|
@@ -13,7 +13,7 @@ export function isValidUrl(url: string): boolean {
|
|
|
13
13
|
return false;
|
|
14
14
|
}
|
|
15
15
|
try {
|
|
16
|
-
new URL(url
|
|
16
|
+
new URL(url);
|
|
17
17
|
return true;
|
|
18
18
|
} catch {
|
|
19
19
|
return false;
|
|
@@ -28,7 +28,7 @@ export function isValidHttpsUrl(url: string): boolean {
|
|
|
28
28
|
return false;
|
|
29
29
|
}
|
|
30
30
|
try {
|
|
31
|
-
const urlObj = new URL(url
|
|
31
|
+
const urlObj = new URL(url);
|
|
32
32
|
return urlObj.protocol === 'https:';
|
|
33
33
|
} catch {
|
|
34
34
|
return false;
|