@umituz/react-native-firebase 2.4.14 → 2.4.16

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 (32) hide show
  1. package/package.json +1 -1
  2. package/src/domains/account-deletion/infrastructure/services/account-deletion.service.ts +29 -21
  3. package/src/domains/account-deletion/infrastructure/services/reauthentication.service.ts +2 -2
  4. package/src/domains/auth/domain/utils/user-metadata.util.ts +72 -0
  5. package/src/domains/auth/domain/utils/user-validation.util.ts +77 -0
  6. package/src/domains/auth/infrastructure/services/apple-auth.service.ts +6 -27
  7. package/src/domains/auth/infrastructure/services/auth-guard.service.ts +39 -33
  8. package/src/domains/auth/infrastructure/services/base/base-auth.service.ts +2 -2
  9. package/src/domains/auth/infrastructure/services/email-auth.service.ts +18 -38
  10. package/src/domains/auth/infrastructure/services/google-auth.service.ts +6 -27
  11. package/src/domains/auth/infrastructure/services/utils/auth-result-converter.util.ts +71 -0
  12. package/src/domains/auth/infrastructure/utils/auth-guard.util.ts +98 -0
  13. package/src/domains/firestore/index.ts +1 -1
  14. package/src/domains/firestore/infrastructure/config/FirestoreClient.ts +3 -16
  15. package/src/domains/firestore/infrastructure/repositories/BaseRepository.ts +1 -4
  16. package/src/domains/firestore/utils/firestore-helper.ts +0 -3
  17. package/src/domains/firestore/utils/operation/operation-executor.util.ts +3 -3
  18. package/src/domains/firestore/utils/result/result.util.ts +7 -25
  19. package/src/index.ts +1 -1
  20. package/src/shared/domain/utils/async-executor.util.ts +1 -6
  21. package/src/shared/domain/utils/error-handler.util.ts +4 -2
  22. package/src/shared/domain/utils/error-handlers/error-checkers.ts +1 -1
  23. package/src/shared/domain/utils/error-handlers/error-converters.ts +6 -28
  24. package/src/shared/domain/utils/executors/basic-executors.util.ts +10 -6
  25. package/src/shared/domain/utils/index.ts +0 -4
  26. package/src/shared/domain/utils/result/result-creators.ts +3 -16
  27. package/src/shared/domain/utils/type-guards.util.ts +33 -8
  28. package/src/shared/domain/utils/validators/firebase.validator.ts +4 -5
  29. package/src/shared/domain/utils/validators/url.validator.ts +2 -2
  30. package/src/shared/domain/utils/validators/user-input.validator.ts +1 -1
  31. package/src/shared/domain/utils/validators/validation.util.ts +63 -0
  32. 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 { FirestoreResult, NoDbResult } from './utils/firestore-helper';
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 (!FirestoreClientSingleton.instance && !FirestoreClientSingleton.initInProgress) {
45
- FirestoreClientSingleton.initInProgress = true;
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) {
@@ -8,9 +8,6 @@ export type { Firestore } from "../infrastructure/config/FirestoreClient";
8
8
  export {
9
9
  createErrorResult,
10
10
  createSuccessResult,
11
- isSuccess,
12
- isError,
13
- type FirestoreResult,
14
11
  type NoDbResult,
15
12
  NO_DB_ERROR,
16
13
  } from "./result/result.util";
@@ -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 { FirestoreResult } from "../result/result.util";
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<FirestoreResult<T>>,
17
- ): Promise<FirestoreResult<T>> {
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
- export interface FirestoreResult<T> {
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 = FirestoreResult<never>;
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): FirestoreResult<T> {
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): FirestoreResult<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>(): FirestoreResult<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 { FirestoreResult, NoDbResult } from "./domains/firestore/utils/firestore-helper";
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 for backward compatibility
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 type { ErrorInfo } from './error-handlers/error-converters';
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 {
@@ -3,7 +3,7 @@
3
3
  * Check error types and categories
4
4
  */
5
5
 
6
- import type { ErrorInfo } from './error-converters';
6
+ import type { ErrorInfo } from '../result/result-types';
7
7
  import { hasCodeProperty, hasMessageProperty } from '../type-guards.util';
8
8
 
9
9
  /**
@@ -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) && error.code ? error.code : 'auth/failed',
18
+ code: hasCodeProperty(error) ? error.code : defaultCode,
41
19
  message: error.message,
42
20
  };
43
21
  }
44
22
  return {
45
- code: 'auth/failed',
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 type { ErrorConverter } from './error-converters.util';
9
- import { authErrorConverter, defaultErrorConverter } from './error-converters.util';
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 ?? defaultErrorConverter;
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) => defaultErrorConverter(error, defaultErrorCode));
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, authErrorConverter);
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
- 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
- };
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
- typeof error === 'object' &&
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
- typeof error === 'object' &&
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
- typeof error === 'object' &&
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
- typeof error === 'object' &&
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.trim());
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
- trimmed.includes('.firebaseapp.com') ||
31
- trimmed.includes('.web.app')
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.trim());
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.trim());
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.trim());
31
+ const urlObj = new URL(url);
32
32
  return urlObj.protocol === 'https:';
33
33
  } catch {
34
34
  return false;
@@ -13,7 +13,7 @@ export function isValidEmail(email: string): boolean {
13
13
  return false;
14
14
  }
15
15
  const emailPattern = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
16
- return emailPattern.test(email.trim());
16
+ return emailPattern.test(email);
17
17
  }
18
18
 
19
19
  /**