@umituz/react-native-firebase 2.4.30 → 2.4.33

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 (55) hide show
  1. package/package.json +1 -1
  2. package/src/domains/account-deletion/application/ports/reauthentication.types.ts +0 -14
  3. package/src/domains/account-deletion/infrastructure/services/account-deletion.service.ts +0 -2
  4. package/src/domains/account-deletion/infrastructure/services/reauthentication.service.ts +0 -6
  5. package/src/domains/auth/domain/entities/AnonymousUser.ts +0 -13
  6. package/src/domains/auth/domain/utils/user-validation.util.ts +0 -19
  7. package/src/domains/auth/infrastructure/config/FirebaseAuthClient.ts +0 -1
  8. package/src/domains/auth/infrastructure/services/apple-auth.types.ts +0 -19
  9. package/src/domains/auth/infrastructure/services/base/base-auth.service.ts +0 -49
  10. package/src/domains/auth/infrastructure/services/google-auth.types.ts +0 -12
  11. package/src/domains/auth/infrastructure/services/user-document.service.ts +0 -6
  12. package/src/domains/auth/infrastructure/services/utils/auth-result-converter.util.ts +3 -3
  13. package/src/domains/auth/infrastructure/utils/auth-guard.util.ts +2 -48
  14. package/src/domains/auth/presentation/hooks/useGoogleOAuth.ts +1 -1
  15. package/src/domains/auth/presentation/hooks/utils/auth-state-change.handler.ts +2 -2
  16. package/src/domains/firestore/infrastructure/middleware/QueryDeduplicationMiddleware.ts +0 -1
  17. package/src/domains/firestore/infrastructure/repositories/BaseRepository.ts +1 -1
  18. package/src/domains/firestore/utils/deduplication/pending-query-manager.util.ts +1 -1
  19. package/src/domains/firestore/utils/deduplication/query-key-generator.util.ts +0 -16
  20. package/src/domains/firestore/utils/deduplication/timer-manager.util.ts +1 -1
  21. package/src/domains/firestore/utils/firestore-helper.ts +0 -3
  22. package/src/domains/firestore/utils/query/filters.util.ts +0 -10
  23. package/src/domains/firestore/utils/query-builder.ts +3 -3
  24. package/src/domains/firestore/utils/result/result.util.ts +2 -5
  25. package/src/init/index.ts +0 -2
  26. package/src/shared/domain/guards/firebase-error.guard.ts +3 -3
  27. package/src/shared/domain/utils/async-executor.util.ts +1 -10
  28. package/src/shared/domain/utils/error-handlers/error-checkers.ts +1 -37
  29. package/src/shared/domain/utils/error-handlers/error-messages.ts +0 -3
  30. package/src/shared/domain/utils/executors/basic-executors.util.ts +1 -22
  31. package/src/shared/domain/utils/id-generator.util.ts +0 -37
  32. package/src/shared/domain/utils/index.ts +0 -90
  33. package/src/shared/domain/utils/result/result-creators.ts +1 -1
  34. package/src/shared/domain/utils/result/result-helpers.ts +1 -48
  35. package/src/shared/domain/utils/service-config.util.ts +2 -21
  36. package/src/shared/domain/utils/type-guards.util.ts +1 -55
  37. package/src/shared/domain/utils/validators/firebase.validator.ts +0 -11
  38. package/src/shared/domain/utils/validators/string.validator.ts +0 -14
  39. package/src/shared/infrastructure/config/base/ClientStateManager.ts +1 -1
  40. package/src/shared/infrastructure/config/base/ServiceClientSingleton.ts +2 -2
  41. package/src/shared/infrastructure/config/initializers/FirebaseAppInitializer.ts +2 -92
  42. package/src/domains/auth/domain/errors/FirebaseAuthError.ts +0 -18
  43. package/src/domains/auth/infrastructure/services/auth-guard.service.ts +0 -101
  44. package/src/domains/auth/presentation/hooks/shared/auth-hooks.util.ts +0 -60
  45. package/src/domains/auth/presentation/hooks/shared/safe-state-hooks.util.ts +0 -76
  46. package/src/domains/auth/presentation/hooks/shared/state-hooks.util.ts +0 -97
  47. package/src/shared/domain/utils/credential.util.ts +0 -102
  48. package/src/shared/domain/utils/executors/advanced-executors.util.ts +0 -59
  49. package/src/shared/domain/utils/executors/batch-executors.util.ts +0 -42
  50. package/src/shared/domain/utils/validators/composite.validator.ts +0 -24
  51. package/src/shared/domain/utils/validators/generic.validator.ts +0 -59
  52. package/src/shared/domain/utils/validators/url.validator.ts +0 -36
  53. package/src/shared/domain/utils/validators/user-input.validator.ts +0 -54
  54. package/src/shared/domain/utils/validators/validation.util.ts +0 -63
  55. package/src/shared/infrastructure/config/validators/FirebaseConfigValidator.ts +0 -89
@@ -1,76 +0,0 @@
1
- /**
2
- * Safe State Hooks
3
- * React hooks for safe state management and mounted state tracking
4
- */
5
-
6
- import { useState, useCallback, useRef, useEffect } from 'react';
7
-
8
- /**
9
- * Hook for tracking mounted state
10
- */
11
- export function useIsMounted(): () => boolean {
12
- const isMountedRef = useRef<boolean>(true);
13
-
14
- useEffect(() => {
15
- isMountedRef.current = true;
16
- return () => {
17
- isMountedRef.current = false;
18
- };
19
- }, []);
20
-
21
- return useCallback(() => isMountedRef.current, []);
22
- }
23
-
24
- /**
25
- * Hook for safe state updates (only if mounted)
26
- */
27
- export function useSafeState<T>(
28
- initialValue: T
29
- ): [T, (value: T | ((prev: T) => T)) => void] {
30
- const isMounted = useIsMounted();
31
- const [state, setState] = useState<T>(initialValue);
32
-
33
- const setSafeState = useCallback(
34
- (value: T | ((prev: T) => T)) => {
35
- if (isMounted()) {
36
- setState(value);
37
- }
38
- },
39
- [isMounted]
40
- );
41
-
42
- return [state, setSafeState];
43
- }
44
-
45
- /**
46
- * Hook for debounced value updates
47
- */
48
- export function useDebouncedValue<T>(value: T, delayMs: number): T {
49
- const [debouncedValue, setDebouncedValue] = useState<T>(value);
50
-
51
- useEffect(() => {
52
- const handler = setTimeout(() => {
53
- setDebouncedValue(value);
54
- }, delayMs);
55
-
56
- return () => {
57
- clearTimeout(handler);
58
- };
59
- }, [value, delayMs]);
60
-
61
- return debouncedValue;
62
- }
63
-
64
- /**
65
- * Hook for managing cleanup callbacks
66
- */
67
- export function useCleanup(
68
- cleanupFn: () => void,
69
- deps: React.DependencyList = []
70
- ): void {
71
- useEffect(() => {
72
- return () => {
73
- cleanupFn();
74
- };
75
- }, deps);
76
- }
@@ -1,97 +0,0 @@
1
- /**
2
- * State Management Hooks
3
- * React hooks for managing component state with loading and error handling
4
- */
5
-
6
- import { useState, useCallback, useRef } from 'react';
7
-
8
- /**
9
- * Hook state management result
10
- */
11
- export interface HookState<T> {
12
- value: T;
13
- loading: boolean;
14
- error: Error | null;
15
- }
16
-
17
- /**
18
- * Hook state actions
19
- */
20
- export interface HookStateActions<T> {
21
- setValue: (value: T) => void;
22
- setLoading: (loading: boolean) => void;
23
- setError: (error: Error | null) => void;
24
- clearError: () => void;
25
- reset: () => void;
26
- }
27
-
28
- /**
29
- * Create a stateful hook with loading and error handling
30
- */
31
- export function useHookState<T>(
32
- initialValue: T
33
- ): [HookState<T>, HookStateActions<T>] {
34
- const [value, setValue] = useState<T>(initialValue);
35
- const [loading, setLoading] = useState<boolean>(false);
36
- const [error, setError] = useState<Error | null>(null);
37
-
38
- const clearError = useCallback(() => {
39
- setError(null);
40
- }, []);
41
-
42
- const reset = useCallback(() => {
43
- setValue(initialValue);
44
- setLoading(false);
45
- setError(null);
46
- }, [initialValue]);
47
-
48
- const state: HookState<T> = { value, loading, error };
49
- const actions: HookStateActions<T> = {
50
- setValue,
51
- setLoading,
52
- setError,
53
- clearError,
54
- reset,
55
- };
56
-
57
- return [state, actions];
58
- }
59
-
60
- /**
61
- * Hook for managing async operation state
62
- */
63
- export function useAsyncOperation<T = void>() {
64
- const [loading, setLoading] = useState<boolean>(false);
65
- const [error, setError] = useState<Error | null>(null);
66
- const operationRef = useRef<Promise<T> | null>(null);
67
-
68
- const execute = useCallback(async (operation: () => Promise<T>): Promise<T> => {
69
- setLoading(true);
70
- setError(null);
71
-
72
- try {
73
- const promise = operation();
74
- operationRef.current = promise;
75
- const result = await promise;
76
- return result;
77
- } catch (err) {
78
- const error = err instanceof Error ? err : new Error(String(err));
79
- setError(error);
80
- throw error;
81
- } finally {
82
- setLoading(false);
83
- operationRef.current = null;
84
- }
85
- }, []);
86
-
87
- const clearError = useCallback(() => {
88
- setError(null);
89
- }, []);
90
-
91
- return {
92
- loading,
93
- error,
94
- execute,
95
- clearError,
96
- };
97
- }
@@ -1,102 +0,0 @@
1
- /**
2
- * Credential Utility
3
- * Centralized credential generation for authentication providers
4
- * Eliminates code duplication across auth services
5
- */
6
-
7
- import {
8
- GoogleAuthProvider,
9
- OAuthProvider,
10
- type AuthCredential,
11
- } from 'firebase/auth';
12
- import * as AppleAuthentication from 'expo-apple-authentication';
13
- import { Platform } from 'react-native';
14
- import { generateNonce, hashNonce } from '../../../domains/auth/infrastructure/services/crypto.util';
15
-
16
- /**
17
- * Generate Google credential from ID token
18
- */
19
- export function generateGoogleCredential(idToken: string): AuthCredential {
20
- return GoogleAuthProvider.credential(idToken);
21
- }
22
-
23
- /**
24
- * Generate Apple credential from identity token and nonce
25
- */
26
- export function generateAppleCredential(
27
- identityToken: string,
28
- rawNonce: string
29
- ): AuthCredential {
30
- const provider = new OAuthProvider('apple.com');
31
- return provider.credential({
32
- idToken: identityToken,
33
- rawNonce,
34
- });
35
- }
36
-
37
- /**
38
- * Check if Apple Sign-In is available
39
- */
40
- export async function isAppleSignInAvailable(): Promise<boolean> {
41
- if (Platform.OS !== 'ios') {
42
- return false;
43
- }
44
- try {
45
- return await AppleAuthentication.isAvailableAsync();
46
- } catch {
47
- return false;
48
- }
49
- }
50
-
51
- /**
52
- * Perform Apple Sign-In with default scopes
53
- */
54
- export async function performAppleSignIn(): Promise<{
55
- identityToken: string | null;
56
- nonce: string;
57
- rawNonce: string;
58
- }> {
59
- const rawNonce = await generateNonce();
60
- const hashedNonce = await hashNonce(rawNonce);
61
-
62
- const result = await AppleAuthentication.signInAsync({
63
- requestedScopes: [
64
- AppleAuthentication.AppleAuthenticationScope.FULL_NAME,
65
- AppleAuthentication.AppleAuthenticationScope.EMAIL,
66
- ],
67
- nonce: hashedNonce,
68
- });
69
-
70
- return {
71
- identityToken: result.identityToken,
72
- nonce: hashedNonce,
73
- rawNonce,
74
- };
75
- }
76
-
77
- /**
78
- * Email/Password credential interface
79
- */
80
- export interface EmailPasswordCredential {
81
- email: string;
82
- password: string;
83
- }
84
-
85
- /**
86
- * Validate email/password credential
87
- */
88
- export function isValidEmailPassword(credential: EmailPasswordCredential): boolean {
89
- return (
90
- typeof credential.email === 'string' &&
91
- credential.email.length > 0 &&
92
- typeof credential.password === 'string' &&
93
- credential.password.length > 0
94
- );
95
- }
96
-
97
- /**
98
- * Custom credential generator interface
99
- */
100
- export interface CredentialGenerator {
101
- generate(): AuthCredential | Promise<AuthCredential>;
102
- }
@@ -1,59 +0,0 @@
1
- /**
2
- * Advanced Async Executors
3
- * Retry and timeout support for async operations
4
- */
5
-
6
- import type { Result } from '../result/result-types';
7
- import { failureResultFromError, successResult } from '../result/result-creators';
8
- import { executeOperation } from './basic-executors.util';
9
-
10
- /**
11
- * Execute operation with retry
12
- * @param operation - Operation to execute
13
- * @param maxRetries - Maximum number of retries (default: 3)
14
- * @param delayMs - Base delay between retries in milliseconds (default: 1000)
15
- */
16
- export async function executeWithRetry<T>(
17
- operation: () => Promise<T>,
18
- maxRetries = 3,
19
- delayMs = 1000
20
- ): Promise<Result<T>> {
21
- let lastError: unknown;
22
- for (let i = 0; i <= maxRetries; i++) {
23
- try {
24
- const data = await operation();
25
- return successResult(data);
26
- } catch (error) {
27
- lastError = error;
28
- if (i < maxRetries) {
29
- // Exponential backoff: delay * (attempt + 1)
30
- await new Promise((resolve) => setTimeout(() => resolve(undefined), delayMs * (i + 1)));
31
- }
32
- }
33
- }
34
- return failureResultFromError(lastError);
35
- }
36
-
37
- /**
38
- * Execute operation with timeout
39
- * @param operation - Operation to execute
40
- * @param timeoutMs - Timeout in milliseconds
41
- */
42
- export async function executeWithTimeout<T>(
43
- operation: () => Promise<T>,
44
- timeoutMs: number
45
- ): Promise<Result<T>> {
46
- return Promise.race([
47
- executeOperation(operation),
48
- new Promise<Result<T>>((resolve) =>
49
- setTimeout(
50
- () =>
51
- resolve({
52
- success: false,
53
- error: { code: 'timeout', message: `Operation timed out after ${timeoutMs}ms` },
54
- }),
55
- timeoutMs
56
- )
57
- ),
58
- ]);
59
- }
@@ -1,42 +0,0 @@
1
- import type { Result } from '../result/result-types';
2
- import { failureResultFromError, successResult } from '../result/result-creators';
3
- import { isSuccess, isFailure } from '../result/result-helpers';
4
-
5
- export async function executeAll<T>(
6
- ...operations: (() => Promise<Result<T>>)[]
7
- ): Promise<Result<T[]>> {
8
- try {
9
- const results = await Promise.all(operations.map((op) => op()));
10
-
11
- // FIX: Use isFailure() type guard instead of manual check
12
- for (const result of results) {
13
- if (isFailure(result)) {
14
- return result;
15
- }
16
- }
17
-
18
- const data: T[] = [];
19
- for (const result of results) {
20
- if (isSuccess(result) && result.data !== undefined) {
21
- data.push(result.data);
22
- }
23
- }
24
-
25
- return successResult(data);
26
- } catch (error) {
27
- return failureResultFromError(error);
28
- }
29
- }
30
-
31
- export async function executeSequence<T>(
32
- ...operations: (() => Promise<Result<T>>)[]
33
- ): Promise<Result<void>> {
34
- for (const operation of operations) {
35
- const result = await operation();
36
- // FIX: Use isFailure() type guard instead of manual check
37
- if (isFailure(result)) {
38
- return { success: false, error: result.error };
39
- }
40
- }
41
- return successResult();
42
- }
@@ -1,24 +0,0 @@
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
- }
@@ -1,59 +0,0 @@
1
- /**
2
- * Generic Validators
3
- * Generic validation utilities for arrays, numbers, and objects
4
- */
5
-
6
- /**
7
- * Check if array is not empty
8
- */
9
- export function isNonEmptyArray<T>(value: unknown): value is [T, ...T[]] {
10
- return Array.isArray(value) && value.length > 0;
11
- }
12
-
13
- /**
14
- * Check if number is in range
15
- */
16
- export function isInRange(value: number, min: number, max: number): boolean {
17
- return typeof value === 'number' && value >= min && value <= max;
18
- }
19
-
20
- /**
21
- * Check if number is positive
22
- */
23
- export function isPositive(value: number): boolean {
24
- return typeof value === 'number' && value > 0;
25
- }
26
-
27
- /**
28
- * Check if number is non-negative
29
- */
30
- export function isNonNegative(value: number): boolean {
31
- return typeof value === 'number' && value >= 0;
32
- }
33
-
34
- /**
35
- * Validate object has required properties
36
- */
37
- export function hasRequiredProperties<T extends Record<string, unknown>>(
38
- obj: unknown,
39
- requiredProps: (keyof T)[]
40
- ): obj is T {
41
- if (typeof obj !== 'object' || obj === null) {
42
- return false;
43
- }
44
- return requiredProps.every((prop) => prop in obj);
45
- }
46
-
47
- /**
48
- * Validate all items in array match predicate
49
- */
50
- export function allMatch<T>(items: unknown[], predicate: (item: unknown) => item is T): boolean {
51
- return Array.isArray(items) && items.every(predicate);
52
- }
53
-
54
- /**
55
- * Validate at least one item in array matches predicate
56
- */
57
- export function anyMatch<T>(items: unknown[], predicate: (item: unknown) => item is T): boolean {
58
- return Array.isArray(items) && items.some(predicate);
59
- }
@@ -1,36 +0,0 @@
1
- /**
2
- * URL Validators
3
- * Validation utilities for URLs
4
- */
5
-
6
- import { isValidString } from './string.validator';
7
-
8
- /**
9
- * Validate URL format
10
- */
11
- export function isValidUrl(url: string): boolean {
12
- if (!isValidString(url)) {
13
- return false;
14
- }
15
- try {
16
- new URL(url);
17
- return true;
18
- } catch {
19
- return false;
20
- }
21
- }
22
-
23
- /**
24
- * Validate HTTPS URL
25
- */
26
- export function isValidHttpsUrl(url: string): boolean {
27
- if (!isValidString(url)) {
28
- return false;
29
- }
30
- try {
31
- const urlObj = new URL(url);
32
- return (urlObj as any).protocol === 'https:';
33
- } catch {
34
- return false;
35
- }
36
- }
@@ -1,54 +0,0 @@
1
- /**
2
- * User Input Validators
3
- * Validation utilities for user input (email, password, username, phone)
4
- */
5
-
6
- import { isValidString } from './string.validator';
7
-
8
- /**
9
- * Validate email format
10
- */
11
- export function isValidEmail(email: string): boolean {
12
- if (!isValidString(email)) {
13
- return false;
14
- }
15
- const emailPattern = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
16
- return emailPattern.test(email);
17
- }
18
-
19
- /**
20
- * Validate password strength
21
- * At least 8 characters, containing uppercase, lowercase, and number
22
- */
23
- export function isStrongPassword(password: string): boolean {
24
- if (!isValidString(password) || password.length < 8) {
25
- return false;
26
- }
27
- const hasUpperCase = /[A-Z]/.test(password);
28
- const hasLowerCase = /[a-z]/.test(password);
29
- const hasNumber = /[0-9]/.test(password);
30
- return hasUpperCase && hasLowerCase && hasNumber;
31
- }
32
-
33
- /**
34
- * Validate username format
35
- * Alphanumeric, underscores, and hyphens, 3-20 characters
36
- */
37
- export function isValidUsername(username: string): boolean {
38
- if (!isValidString(username)) {
39
- return false;
40
- }
41
- const pattern = /^[a-zA-Z0-9_-]{3,20}$/;
42
- return pattern.test(username);
43
- }
44
-
45
- /**
46
- * Validate phone number format (basic check)
47
- */
48
- export function isValidPhoneNumber(phone: string): boolean {
49
- if (!isValidString(phone)) {
50
- return false;
51
- }
52
- const cleaned = phone.replace(/\s+/g, '').replace(/[-+()]/g, '');
53
- return /^[0-9]{10,15}$/.test(cleaned);
54
- }
@@ -1,63 +0,0 @@
1
- /**
2
- * Generic Validation Utilities
3
- * Provides reusable validation patterns to eliminate duplication
4
- */
5
-
6
- /**
7
- * Generic validation utility that throws error if validation fails
8
- * Eliminates duplicate validate-or-throw patterns across the codebase
9
- *
10
- * @param value - Value to validate
11
- * @param validator - Validation function that returns true if valid
12
- * @param errorMessage - Error message to throw if validation fails
13
- * @param ErrorClass - Error class to instantiate (defaults to Error)
14
- * @throws {ErrorClass} When validation fails
15
- *
16
- * @example
17
- * ```typescript
18
- * validateOrThrow(
19
- * cursor,
20
- * isValidCursor,
21
- * ERROR_MESSAGES.FIRESTORE.INVALID_CURSOR,
22
- * CursorValidationError
23
- * );
24
- * ```
25
- */
26
- export function validateOrThrow<T>(
27
- value: T,
28
- validator: (value: T) => boolean,
29
- errorMessage: string,
30
- ErrorClass: new (message: string) => Error = Error
31
- ): void {
32
- if (!validator(value)) {
33
- throw new ErrorClass(errorMessage);
34
- }
35
- }
36
-
37
- /**
38
- * Validate multiple values, throw on first failure
39
- * Useful for validating multiple preconditions before an operation
40
- *
41
- * @param validations - Array of validation configurations
42
- * @throws {Error} When any validation fails
43
- *
44
- * @example
45
- * ```typescript
46
- * validateAllOrThrow([
47
- * { value: email, validator: isValidEmail, errorMessage: 'Invalid email' },
48
- * { value: password, validator: isValidPassword, errorMessage: 'Invalid password' },
49
- * ]);
50
- * ```
51
- */
52
- export function validateAllOrThrow<T = unknown>(
53
- validations: Array<{
54
- value: T;
55
- validator: (value: T) => boolean;
56
- errorMessage: string;
57
- ErrorClass?: new (message: string) => Error;
58
- }>
59
- ): void {
60
- for (const { value, validator, errorMessage, ErrorClass = Error } of validations) {
61
- validateOrThrow(value, validator, errorMessage, ErrorClass);
62
- }
63
- }
@@ -1,89 +0,0 @@
1
- /**
2
- * Firebase Configuration Validator
3
- *
4
- * Single Responsibility: Validates Firebase configuration
5
- * Uses centralized validation utilities from validation.util.ts
6
- */
7
-
8
- import type { FirebaseConfig } from '../../../domain/value-objects/FirebaseConfig';
9
- import { FirebaseConfigurationError } from '../../../domain/errors/FirebaseError';
10
- import { isValidString } from '../../../domain/utils/validators/string.validator';
11
- import { isValidFirebaseApiKey, isValidFirebaseProjectId, isValidFirebaseAuthDomain } from '../../../domain/utils/validators/firebase.validator';
12
-
13
- /**
14
- * Validation rule interface
15
- */
16
- interface ValidationRule {
17
- validate(config: FirebaseConfig): void;
18
- }
19
-
20
- /**
21
- * Required field validation rule using centralized validation
22
- */
23
- class RequiredFieldRule implements ValidationRule {
24
- constructor(
25
- private fieldName: string,
26
- private getter: (config: FirebaseConfig) => string | undefined,
27
- private customValidator?: (value: string) => boolean
28
- ) {}
29
-
30
- validate(config: FirebaseConfig): void {
31
- const value = this.getter(config);
32
-
33
- if (!isValidString(value)) {
34
- throw new FirebaseConfigurationError(
35
- `Firebase ${this.fieldName} is required and must be a non-empty string`
36
- );
37
- }
38
-
39
- if (this.customValidator && !this.customValidator(value)) {
40
- throw new FirebaseConfigurationError(
41
- `Firebase ${this.fieldName} format is invalid`
42
- );
43
- }
44
- }
45
- }
46
-
47
- /**
48
- * Placeholder validation rule
49
- */
50
- class PlaceholderRule implements ValidationRule {
51
- constructor(
52
- private fieldName: string,
53
- private getter: (config: FirebaseConfig) => string | undefined,
54
- private placeholder: string
55
- ) {}
56
-
57
- validate(config: FirebaseConfig): void {
58
- const value = this.getter(config);
59
-
60
- if (value && value.includes(this.placeholder)) {
61
- throw new FirebaseConfigurationError(
62
- `Please replace placeholder values with actual Firebase credentials for ${this.fieldName}`
63
- );
64
- }
65
- }
66
- }
67
-
68
- /**
69
- * Firebase Configuration Validator
70
- */
71
- export class FirebaseConfigValidator {
72
- private static rules: ValidationRule[] = [
73
- new RequiredFieldRule('API Key', config => config.apiKey, isValidFirebaseApiKey),
74
- new RequiredFieldRule('Auth Domain', config => config.authDomain, isValidFirebaseAuthDomain),
75
- new RequiredFieldRule('Project ID', config => config.projectId, isValidFirebaseProjectId),
76
- new PlaceholderRule('API Key', config => config.apiKey, 'your_firebase_api_key'),
77
- new PlaceholderRule('Project ID', config => config.projectId, 'your-project-id'),
78
- ];
79
-
80
- /**
81
- * Validate Firebase configuration
82
- * @throws {FirebaseConfigurationError} If configuration is invalid
83
- */
84
- static validate(config: FirebaseConfig): void {
85
- for (const rule of this.rules) {
86
- rule.validate(config);
87
- }
88
- }
89
- }