@umituz/react-native-firebase 2.4.29 → 2.4.32
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/application/ports/reauthentication.types.ts +0 -14
- package/src/domains/account-deletion/infrastructure/services/account-deletion.service.ts +0 -2
- package/src/domains/account-deletion/infrastructure/services/reauthentication.service.ts +0 -6
- package/src/domains/auth/domain/entities/AnonymousUser.ts +0 -13
- package/src/domains/auth/domain/utils/user-validation.util.ts +0 -19
- package/src/domains/auth/infrastructure/config/FirebaseAuthClient.ts +0 -1
- package/src/domains/auth/infrastructure/services/apple-auth.types.ts +0 -19
- package/src/domains/auth/infrastructure/services/base/base-auth.service.ts +0 -49
- package/src/domains/auth/infrastructure/services/google-auth.types.ts +0 -12
- package/src/domains/auth/infrastructure/services/user-document.service.ts +0 -6
- package/src/domains/auth/infrastructure/services/utils/auth-result-converter.util.ts +3 -3
- package/src/domains/auth/infrastructure/utils/auth-guard.util.ts +2 -48
- package/src/domains/auth/presentation/hooks/useGoogleOAuth.ts +1 -1
- package/src/domains/auth/presentation/hooks/utils/auth-state-change.handler.ts +2 -2
- package/src/domains/firestore/infrastructure/middleware/QueryDeduplicationMiddleware.ts +0 -1
- package/src/domains/firestore/infrastructure/repositories/BaseRepository.ts +1 -1
- package/src/domains/firestore/utils/deduplication/pending-query-manager.util.ts +1 -1
- package/src/domains/firestore/utils/deduplication/query-key-generator.util.ts +0 -16
- package/src/domains/firestore/utils/deduplication/timer-manager.util.ts +1 -1
- package/src/domains/firestore/utils/firestore-helper.ts +0 -3
- package/src/domains/firestore/utils/query/filters.util.ts +0 -10
- package/src/domains/firestore/utils/query-builder.ts +3 -3
- package/src/domains/firestore/utils/result/result.util.ts +2 -5
- package/src/index.ts +1 -1
- package/src/init/index.ts +0 -2
- package/src/shared/domain/guards/firebase-error.guard.ts +3 -3
- package/src/shared/domain/utils/async-executor.util.ts +1 -10
- package/src/shared/domain/utils/error-handlers/error-checkers.ts +1 -37
- package/src/shared/domain/utils/error-handlers/error-messages.ts +0 -3
- package/src/shared/domain/utils/executors/basic-executors.util.ts +1 -22
- package/src/shared/domain/utils/id-generator.util.ts +0 -37
- package/src/shared/domain/utils/index.ts +0 -90
- package/src/shared/domain/utils/result/result-creators.ts +1 -1
- package/src/shared/domain/utils/result/result-helpers.ts +1 -48
- package/src/shared/domain/utils/service-config.util.ts +2 -21
- package/src/shared/domain/utils/type-guards.util.ts +1 -55
- package/src/shared/domain/utils/validators/firebase.validator.ts +0 -11
- package/src/shared/domain/utils/validators/string.validator.ts +0 -14
- package/src/shared/infrastructure/config/base/ClientStateManager.ts +1 -1
- package/src/shared/infrastructure/config/base/ServiceClientSingleton.ts +2 -2
- package/src/shared/infrastructure/config/initializers/FirebaseAppInitializer.ts +2 -92
- package/src/domains/auth/domain/errors/FirebaseAuthError.ts +0 -18
- package/src/domains/auth/infrastructure/services/auth-guard.service.ts +0 -101
- package/src/domains/auth/presentation/hooks/shared/auth-hooks.util.ts +0 -60
- package/src/domains/auth/presentation/hooks/shared/safe-state-hooks.util.ts +0 -76
- package/src/domains/auth/presentation/hooks/shared/state-hooks.util.ts +0 -97
- package/src/shared/domain/utils/credential.util.ts +0 -102
- package/src/shared/domain/utils/executors/advanced-executors.util.ts +0 -59
- package/src/shared/domain/utils/executors/batch-executors.util.ts +0 -42
- package/src/shared/domain/utils/validators/composite.validator.ts +0 -24
- package/src/shared/domain/utils/validators/generic.validator.ts +0 -59
- package/src/shared/domain/utils/validators/url.validator.ts +0 -36
- package/src/shared/domain/utils/validators/user-input.validator.ts +0 -54
- package/src/shared/domain/utils/validators/validation.util.ts +0 -63
- package/src/shared/infrastructure/config/validators/FirebaseConfigValidator.ts +0 -89
|
@@ -11,40 +11,3 @@
|
|
|
11
11
|
export function generateUniqueId(): string {
|
|
12
12
|
return `${Date.now()}-${Math.random().toString(36).substring(2, 11)}`;
|
|
13
13
|
}
|
|
14
|
-
|
|
15
|
-
/**
|
|
16
|
-
* Generate a short random ID
|
|
17
|
-
* Useful for temporary identifiers where uniqueness within scope is sufficient
|
|
18
|
-
* @returns Random identifier string
|
|
19
|
-
*/
|
|
20
|
-
export function generateShortId(length: number = 8): string {
|
|
21
|
-
return Math.random().toString(36).substring(2, 2 + length);
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
/**
|
|
25
|
-
* Generate a UUID-like ID
|
|
26
|
-
* Format: xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx
|
|
27
|
-
* @returns UUID-like identifier string
|
|
28
|
-
*/
|
|
29
|
-
export function generateUUID(): string {
|
|
30
|
-
return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, (c) => {
|
|
31
|
-
const r = (Math.random() * 16) | 0;
|
|
32
|
-
const v = c === 'x' ? r : (r & 0x3) | 0x8;
|
|
33
|
-
return v.toString(16);
|
|
34
|
-
});
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
/**
|
|
38
|
-
* Generate a nanoid-like ID
|
|
39
|
-
* Uses URL-safe characters for better compatibility
|
|
40
|
-
* @param length - Length of the ID (default: 21)
|
|
41
|
-
* @returns URL-safe unique identifier string
|
|
42
|
-
*/
|
|
43
|
-
export function generateNanoId(length: number = 21): string {
|
|
44
|
-
const chars = 'ModuleSymbhasOwnPr-0123456789ABCDEFGHNRVfgctiUvz_KqYTJkLxpZXIjQW';
|
|
45
|
-
let result = '';
|
|
46
|
-
for (let i = 0; i < length; i++) {
|
|
47
|
-
result += chars.charAt(Math.floor(Math.random() * chars.length));
|
|
48
|
-
}
|
|
49
|
-
return result;
|
|
50
|
-
}
|
|
@@ -6,112 +6,22 @@
|
|
|
6
6
|
// Result types and helpers
|
|
7
7
|
export type {
|
|
8
8
|
Result,
|
|
9
|
-
SuccessResult,
|
|
10
|
-
FailureResult,
|
|
11
|
-
ErrorInfo,
|
|
12
9
|
} from './result/result-types';
|
|
13
10
|
|
|
14
11
|
export {
|
|
15
12
|
successResult,
|
|
16
|
-
failureResult,
|
|
17
13
|
failureResultFrom,
|
|
18
|
-
failureResultFromError,
|
|
19
14
|
} from './result/result-creators';
|
|
20
15
|
|
|
21
|
-
export {
|
|
22
|
-
isSuccess,
|
|
23
|
-
isFailure,
|
|
24
|
-
getDataOrDefault,
|
|
25
|
-
mapResult,
|
|
26
|
-
chainResults,
|
|
27
|
-
} from './result/result-helpers';
|
|
28
|
-
|
|
29
16
|
// Async operation execution
|
|
30
17
|
export {
|
|
31
18
|
executeOperation,
|
|
32
|
-
executeOperationWithCode,
|
|
33
|
-
executeVoidOperation,
|
|
34
19
|
executeAuthOperation,
|
|
35
|
-
executeAll,
|
|
36
|
-
executeSequence,
|
|
37
|
-
executeWithRetry,
|
|
38
|
-
executeWithTimeout,
|
|
39
20
|
} from './async-executor.util';
|
|
40
21
|
|
|
41
|
-
// Service configuration
|
|
42
|
-
export {
|
|
43
|
-
ConfigurableService,
|
|
44
|
-
createConfigurableService,
|
|
45
|
-
type ConfigState,
|
|
46
|
-
type IConfigurableService,
|
|
47
|
-
} from './service-config.util';
|
|
48
|
-
|
|
49
|
-
// Credential utilities
|
|
50
|
-
export {
|
|
51
|
-
generateGoogleCredential,
|
|
52
|
-
generateAppleCredential,
|
|
53
|
-
isAppleSignInAvailable,
|
|
54
|
-
performAppleSignIn,
|
|
55
|
-
isValidEmailPassword,
|
|
56
|
-
type EmailPasswordCredential,
|
|
57
|
-
type CredentialGenerator,
|
|
58
|
-
} from './credential.util';
|
|
59
|
-
|
|
60
22
|
// Error handling
|
|
61
23
|
export { toErrorInfo } from './error-handlers/error-converters';
|
|
62
24
|
|
|
63
|
-
export {
|
|
64
|
-
hasErrorCode,
|
|
65
|
-
isCancelledError,
|
|
66
|
-
isQuotaErrorInfo,
|
|
67
|
-
isNetworkError,
|
|
68
|
-
isAuthError,
|
|
69
|
-
isQuotaError,
|
|
70
|
-
isRetryableError,
|
|
71
|
-
} from './error-handlers/error-checkers';
|
|
72
|
-
|
|
73
25
|
export {
|
|
74
26
|
ERROR_MESSAGES,
|
|
75
|
-
getQuotaErrorMessage,
|
|
76
|
-
getRetryableErrorMessage,
|
|
77
27
|
} from './error-handlers/error-messages';
|
|
78
|
-
|
|
79
|
-
// Type guards
|
|
80
|
-
export {
|
|
81
|
-
hasCodeProperty,
|
|
82
|
-
hasMessageProperty,
|
|
83
|
-
hasCodeAndMessageProperties,
|
|
84
|
-
} from './type-guards.util';
|
|
85
|
-
|
|
86
|
-
// Validation
|
|
87
|
-
export {
|
|
88
|
-
isValidString,
|
|
89
|
-
isEmptyString,
|
|
90
|
-
isDefined,
|
|
91
|
-
} from './validators/string.validator';
|
|
92
|
-
|
|
93
|
-
export {
|
|
94
|
-
isValidFirebaseApiKey,
|
|
95
|
-
isValidFirebaseAuthDomain,
|
|
96
|
-
isValidFirebaseProjectId,
|
|
97
|
-
} from './validators/firebase.validator';
|
|
98
|
-
|
|
99
|
-
export {
|
|
100
|
-
isValidUrl,
|
|
101
|
-
isValidHttpsUrl,
|
|
102
|
-
} from './validators/url.validator';
|
|
103
|
-
|
|
104
|
-
export { isValidEmail } from './validators/user-input.validator';
|
|
105
|
-
|
|
106
|
-
export {
|
|
107
|
-
isNonEmptyArray,
|
|
108
|
-
isInRange,
|
|
109
|
-
isPositive,
|
|
110
|
-
isNonNegative,
|
|
111
|
-
} from './validators/generic.validator';
|
|
112
|
-
|
|
113
|
-
// ID generation
|
|
114
|
-
export {
|
|
115
|
-
generateUniqueId,
|
|
116
|
-
generateShortId,
|
|
117
|
-
} from './id-generator.util';
|
|
@@ -16,7 +16,7 @@ export function successResult<T = void>(data?: T): SuccessResult<T> {
|
|
|
16
16
|
/**
|
|
17
17
|
* Create a failure result with error information
|
|
18
18
|
*/
|
|
19
|
-
|
|
19
|
+
function failureResult(error: ErrorInfo): FailureResult {
|
|
20
20
|
return { success: false, error };
|
|
21
21
|
}
|
|
22
22
|
|
|
@@ -3,8 +3,7 @@
|
|
|
3
3
|
* Utility functions for working with Result type
|
|
4
4
|
*/
|
|
5
5
|
|
|
6
|
-
import type { Result, SuccessResult
|
|
7
|
-
import { successResult } from './result-creators';
|
|
6
|
+
import type { Result, SuccessResult } from './result-types';
|
|
8
7
|
|
|
9
8
|
/**
|
|
10
9
|
* Check if result is successful
|
|
@@ -12,49 +11,3 @@ import { successResult } from './result-creators';
|
|
|
12
11
|
export function isSuccess<T>(result: Result<T>): result is SuccessResult<T> {
|
|
13
12
|
return result.success === true && result.error === undefined;
|
|
14
13
|
}
|
|
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 && result.error !== undefined;
|
|
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
|
-
}
|
|
@@ -3,26 +3,16 @@ import { ERROR_MESSAGES } from './error-handlers/error-messages';
|
|
|
3
3
|
/**
|
|
4
4
|
* Configuration state management
|
|
5
5
|
*/
|
|
6
|
-
|
|
6
|
+
interface ConfigState<TConfig> {
|
|
7
7
|
config: TConfig | null;
|
|
8
8
|
initialized: boolean;
|
|
9
9
|
}
|
|
10
10
|
|
|
11
|
-
/**
|
|
12
|
-
* Configurable service interface
|
|
13
|
-
*/
|
|
14
|
-
export interface IConfigurableService<TConfig> {
|
|
15
|
-
configure(config: TConfig): void;
|
|
16
|
-
isConfigured(): boolean;
|
|
17
|
-
getConfig(): TConfig | null;
|
|
18
|
-
reset(): void;
|
|
19
|
-
}
|
|
20
|
-
|
|
21
11
|
/**
|
|
22
12
|
* Base class for configurable services
|
|
23
13
|
* Provides configuration management pattern
|
|
24
14
|
*/
|
|
25
|
-
export class ConfigurableService<TConfig = unknown>
|
|
15
|
+
export class ConfigurableService<TConfig = unknown> {
|
|
26
16
|
protected configState: ConfigState<TConfig>;
|
|
27
17
|
private customValidator?: (config: TConfig) => boolean;
|
|
28
18
|
|
|
@@ -81,12 +71,3 @@ export class ConfigurableService<TConfig = unknown> implements IConfigurableServ
|
|
|
81
71
|
return this.configState.config;
|
|
82
72
|
}
|
|
83
73
|
}
|
|
84
|
-
|
|
85
|
-
/**
|
|
86
|
-
* Create a configurable service instance
|
|
87
|
-
*/
|
|
88
|
-
export function createConfigurableService<TConfig>(
|
|
89
|
-
validator?: (config: TConfig) => boolean
|
|
90
|
-
): ConfigurableService<TConfig> {
|
|
91
|
-
return new ConfigurableService<TConfig>(validator);
|
|
92
|
-
}
|
|
@@ -7,33 +7,11 @@
|
|
|
7
7
|
|
|
8
8
|
/**
|
|
9
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
10
|
*/
|
|
19
|
-
|
|
11
|
+
function isObject(value: unknown): value is Record<string, unknown> {
|
|
20
12
|
return typeof value === 'object' && value !== null;
|
|
21
13
|
}
|
|
22
14
|
|
|
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
|
-
|
|
37
15
|
/**
|
|
38
16
|
* Type guard for objects with a 'code' property of type string
|
|
39
17
|
* Commonly used for Firebase errors and other error objects
|
|
@@ -57,35 +35,3 @@ export function hasMessageProperty(error: unknown): error is { message: string }
|
|
|
57
35
|
typeof (error as { message: unknown }).message === 'string'
|
|
58
36
|
);
|
|
59
37
|
}
|
|
60
|
-
|
|
61
|
-
/**
|
|
62
|
-
* Type guard for objects with both 'code' and 'message' properties
|
|
63
|
-
* Commonly used for Firebase error objects
|
|
64
|
-
*/
|
|
65
|
-
export function hasCodeAndMessageProperties(error: unknown): error is { code: string; message: string } {
|
|
66
|
-
return hasCodeProperty(error) && hasMessageProperty(error);
|
|
67
|
-
}
|
|
68
|
-
|
|
69
|
-
/**
|
|
70
|
-
* Type guard for objects with a 'name' property of type string
|
|
71
|
-
* Commonly used for Error objects
|
|
72
|
-
*/
|
|
73
|
-
export function hasNameProperty(error: unknown): error is { name: string } {
|
|
74
|
-
return (
|
|
75
|
-
isObject(error) &&
|
|
76
|
-
'name' in error &&
|
|
77
|
-
typeof (error as { name: unknown }).name === 'string'
|
|
78
|
-
);
|
|
79
|
-
}
|
|
80
|
-
|
|
81
|
-
/**
|
|
82
|
-
* Type guard for objects with a 'stack' property of type string
|
|
83
|
-
* Commonly used for Error objects
|
|
84
|
-
*/
|
|
85
|
-
export function hasStackProperty(error: unknown): error is { stack: string } {
|
|
86
|
-
return (
|
|
87
|
-
isObject(error) &&
|
|
88
|
-
'stack' in error &&
|
|
89
|
-
typeof (error as { stack: unknown }).stack === 'string'
|
|
90
|
-
);
|
|
91
|
-
}
|
|
@@ -31,14 +31,3 @@ export function isValidFirebaseAuthDomain(authDomain: string): boolean {
|
|
|
31
31
|
);
|
|
32
32
|
}
|
|
33
33
|
|
|
34
|
-
/**
|
|
35
|
-
* Validate Firebase projectId format
|
|
36
|
-
* Project IDs must be 6-30 characters, lowercase, alphanumeric, and may contain hyphens
|
|
37
|
-
*/
|
|
38
|
-
export function isValidFirebaseProjectId(projectId: string): boolean {
|
|
39
|
-
if (!isValidString(projectId)) {
|
|
40
|
-
return false;
|
|
41
|
-
}
|
|
42
|
-
const pattern = /^[a-z0-9][a-z0-9-]{4,28}[a-z0-9]$/;
|
|
43
|
-
return pattern.test(projectId);
|
|
44
|
-
}
|
|
@@ -9,17 +9,3 @@
|
|
|
9
9
|
export function isValidString(value: unknown): value is string {
|
|
10
10
|
return typeof value === 'string' && value.trim().length > 0;
|
|
11
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
|
-
* Check if value is defined (not null or undefined)
|
|
22
|
-
*/
|
|
23
|
-
export function isDefined<T>(value: T | null | undefined): value is T {
|
|
24
|
-
return value !== null && value !== undefined;
|
|
25
|
-
}
|
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
* @template TInstance - The service instance type (e.g., FirebaseApp, Firestore, Auth)
|
|
8
8
|
*/
|
|
9
9
|
|
|
10
|
-
|
|
10
|
+
interface ClientState<TInstance> {
|
|
11
11
|
instance: TInstance | null;
|
|
12
12
|
initializationError: string | null;
|
|
13
13
|
isInitialized: boolean;
|
|
@@ -14,13 +14,13 @@
|
|
|
14
14
|
* @template TConfig - The configuration type (optional)
|
|
15
15
|
*/
|
|
16
16
|
|
|
17
|
-
|
|
17
|
+
interface ServiceClientState<TInstance> {
|
|
18
18
|
instance: TInstance | null;
|
|
19
19
|
initializationError: string | null;
|
|
20
20
|
isInitialized: boolean;
|
|
21
21
|
}
|
|
22
22
|
|
|
23
|
-
|
|
23
|
+
interface ServiceClientOptions<TInstance, TConfig = unknown> {
|
|
24
24
|
serviceName: string;
|
|
25
25
|
initializer?: (config?: TConfig) => TInstance | null;
|
|
26
26
|
autoInitializer?: () => TInstance | null;
|
|
@@ -1,99 +1,9 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Firebase App Initializer
|
|
3
3
|
*
|
|
4
|
-
* Single Responsibility:
|
|
4
|
+
* Single Responsibility: Expose Firebase App type
|
|
5
5
|
*/
|
|
6
6
|
|
|
7
|
-
import {
|
|
8
|
-
initializeApp,
|
|
9
|
-
getApps,
|
|
10
|
-
type FirebaseApp as FirebaseAppType,
|
|
11
|
-
} from 'firebase/app';
|
|
12
|
-
import type { FirebaseConfig } from '../../../domain/value-objects/FirebaseConfig';
|
|
13
|
-
import { FirebaseInitializationError } from '../../../domain/errors/FirebaseError';
|
|
7
|
+
import type { FirebaseApp as FirebaseAppType } from 'firebase/app';
|
|
14
8
|
|
|
15
9
|
export type FirebaseApp = FirebaseAppType;
|
|
16
|
-
|
|
17
|
-
/**
|
|
18
|
-
* Firebase configuration mapper
|
|
19
|
-
*/
|
|
20
|
-
class FirebaseConfigMapper {
|
|
21
|
-
/**
|
|
22
|
-
* Map domain config to Firebase SDK config
|
|
23
|
-
*/
|
|
24
|
-
static toFirebaseConfig(config: FirebaseConfig): Record<string, string | undefined> {
|
|
25
|
-
return {
|
|
26
|
-
apiKey: config.apiKey,
|
|
27
|
-
authDomain: config.authDomain,
|
|
28
|
-
projectId: config.projectId,
|
|
29
|
-
storageBucket: config.storageBucket,
|
|
30
|
-
messagingSenderId: config.messagingSenderId,
|
|
31
|
-
appId: config.appId,
|
|
32
|
-
};
|
|
33
|
-
}
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
/**
|
|
37
|
-
* Firebase App manager
|
|
38
|
-
*/
|
|
39
|
-
class FirebaseAppManager {
|
|
40
|
-
/**
|
|
41
|
-
* Check if Firebase App is already initialized
|
|
42
|
-
*/
|
|
43
|
-
static isInitialized(): boolean {
|
|
44
|
-
try {
|
|
45
|
-
const existingApps = getApps();
|
|
46
|
-
return existingApps.length > 0;
|
|
47
|
-
} catch {
|
|
48
|
-
return false;
|
|
49
|
-
}
|
|
50
|
-
}
|
|
51
|
-
|
|
52
|
-
/**
|
|
53
|
-
* Get existing Firebase App instance
|
|
54
|
-
*/
|
|
55
|
-
static getExistingApp(): FirebaseApp | null {
|
|
56
|
-
try {
|
|
57
|
-
const existingApps = getApps();
|
|
58
|
-
return existingApps.length > 0 ? existingApps[0] ?? null : null;
|
|
59
|
-
} catch {
|
|
60
|
-
return null;
|
|
61
|
-
}
|
|
62
|
-
}
|
|
63
|
-
|
|
64
|
-
/**
|
|
65
|
-
* Create new Firebase App instance
|
|
66
|
-
*/
|
|
67
|
-
static createApp(config: FirebaseConfig): FirebaseApp {
|
|
68
|
-
try {
|
|
69
|
-
const firebaseConfig = FirebaseConfigMapper.toFirebaseConfig(config);
|
|
70
|
-
return initializeApp(firebaseConfig);
|
|
71
|
-
} catch (error) {
|
|
72
|
-
throw new FirebaseInitializationError(
|
|
73
|
-
`Failed to initialize Firebase App: ${
|
|
74
|
-
error instanceof Error ? error.message : 'Unknown error'
|
|
75
|
-
}`,
|
|
76
|
-
error
|
|
77
|
-
);
|
|
78
|
-
}
|
|
79
|
-
}
|
|
80
|
-
}
|
|
81
|
-
|
|
82
|
-
/**
|
|
83
|
-
* Initializes Firebase App
|
|
84
|
-
*/
|
|
85
|
-
export class FirebaseAppInitializer {
|
|
86
|
-
/**
|
|
87
|
-
* Initialize or get existing Firebase App
|
|
88
|
-
*/
|
|
89
|
-
static initialize(config: FirebaseConfig): FirebaseApp {
|
|
90
|
-
// Return existing app if already initialized
|
|
91
|
-
const existingApp = FirebaseAppManager.getExistingApp();
|
|
92
|
-
if (existingApp) {
|
|
93
|
-
return existingApp;
|
|
94
|
-
}
|
|
95
|
-
|
|
96
|
-
// Create new app
|
|
97
|
-
return FirebaseAppManager.createApp(config);
|
|
98
|
-
}
|
|
99
|
-
}
|
|
@@ -1,18 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Firebase Auth Error Classes
|
|
3
|
-
* Custom error types for Firebase Auth operations
|
|
4
|
-
*/
|
|
5
|
-
|
|
6
|
-
export class FirebaseAuthError extends Error {
|
|
7
|
-
constructor(message: string) {
|
|
8
|
-
super(message);
|
|
9
|
-
this.name = 'FirebaseAuthError';
|
|
10
|
-
}
|
|
11
|
-
}
|
|
12
|
-
|
|
13
|
-
export class FirebaseAuthInitializationError extends FirebaseAuthError {
|
|
14
|
-
constructor(message: string) {
|
|
15
|
-
super(message);
|
|
16
|
-
this.name = 'FirebaseAuthInitializationError';
|
|
17
|
-
}
|
|
18
|
-
}
|
|
@@ -1,101 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Auth Guard Service
|
|
3
|
-
* Single Responsibility: Validate authenticated user access
|
|
4
|
-
*
|
|
5
|
-
* SOLID: Single Responsibility - Only handles auth validation
|
|
6
|
-
* Generic implementation for all React Native apps
|
|
7
|
-
*/
|
|
8
|
-
|
|
9
|
-
import {
|
|
10
|
-
getCurrentUserId,
|
|
11
|
-
getCurrentUser,
|
|
12
|
-
} from './auth-utils.service';
|
|
13
|
-
import { ERROR_MESSAGES } from '../../../../shared/domain/utils/error-handlers/error-messages';
|
|
14
|
-
import { withAuth, withAuthSync } from '../utils/auth-guard.util';
|
|
15
|
-
|
|
16
|
-
/**
|
|
17
|
-
* Auth Guard Service
|
|
18
|
-
* Provides authentication validation for protected operations
|
|
19
|
-
*/
|
|
20
|
-
export class AuthGuardService {
|
|
21
|
-
/**
|
|
22
|
-
* Check if user is authenticated (not guest)
|
|
23
|
-
* @throws Error if user is not authenticated
|
|
24
|
-
*/
|
|
25
|
-
async requireAuthenticatedUser(): Promise<string> {
|
|
26
|
-
const result = await withAuth(async (auth) => {
|
|
27
|
-
const userId = getCurrentUserId(auth);
|
|
28
|
-
if (!userId) {
|
|
29
|
-
throw new Error(ERROR_MESSAGES.AUTH.NOT_AUTHENTICATED);
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
const currentUser = getCurrentUser(auth);
|
|
33
|
-
if (!currentUser) {
|
|
34
|
-
throw new Error(ERROR_MESSAGES.AUTH.NOT_AUTHENTICATED);
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
if (currentUser.isAnonymous) {
|
|
38
|
-
throw new Error(ERROR_MESSAGES.AUTH.NON_ANONYMOUS_ONLY);
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
return userId;
|
|
42
|
-
});
|
|
43
|
-
|
|
44
|
-
if (!result.success) {
|
|
45
|
-
throw new Error(result.error?.message || 'Authentication failed');
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
if (!result.data) {
|
|
49
|
-
throw new Error('No user ID returned');
|
|
50
|
-
}
|
|
51
|
-
|
|
52
|
-
return result.data;
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
/**
|
|
56
|
-
* Check if user is authenticated (not guest)
|
|
57
|
-
* Returns null if not authenticated instead of throwing
|
|
58
|
-
*/
|
|
59
|
-
async getAuthenticatedUserId(): Promise<string | null> {
|
|
60
|
-
try {
|
|
61
|
-
return await this.requireAuthenticatedUser();
|
|
62
|
-
} catch {
|
|
63
|
-
return null;
|
|
64
|
-
}
|
|
65
|
-
}
|
|
66
|
-
|
|
67
|
-
/**
|
|
68
|
-
* Check if current user is authenticated (not guest)
|
|
69
|
-
*/
|
|
70
|
-
isAuthenticated(): boolean {
|
|
71
|
-
const result = withAuthSync((auth) => {
|
|
72
|
-
const currentUser = getCurrentUser(auth);
|
|
73
|
-
if (!currentUser) {
|
|
74
|
-
return false;
|
|
75
|
-
}
|
|
76
|
-
|
|
77
|
-
// User must not be anonymous
|
|
78
|
-
return !currentUser.isAnonymous;
|
|
79
|
-
});
|
|
80
|
-
|
|
81
|
-
return result.success && result.data ? result.data : false;
|
|
82
|
-
}
|
|
83
|
-
|
|
84
|
-
/**
|
|
85
|
-
* Check if current user is guest (anonymous)
|
|
86
|
-
*/
|
|
87
|
-
isGuest(): boolean {
|
|
88
|
-
const result = withAuthSync((auth) => {
|
|
89
|
-
const currentUser = getCurrentUser(auth);
|
|
90
|
-
if (!currentUser) {
|
|
91
|
-
return false;
|
|
92
|
-
}
|
|
93
|
-
|
|
94
|
-
return currentUser.isAnonymous;
|
|
95
|
-
});
|
|
96
|
-
|
|
97
|
-
return result.success && result.data ? result.data : false;
|
|
98
|
-
}
|
|
99
|
-
}
|
|
100
|
-
|
|
101
|
-
export const authGuardService = new AuthGuardService();
|
|
@@ -1,60 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Auth-Specific Hooks
|
|
3
|
-
* React hooks for Firebase Auth state management
|
|
4
|
-
*/
|
|
5
|
-
|
|
6
|
-
import { useRef, useEffect } from 'react';
|
|
7
|
-
import { onAuthStateChanged, type Auth, type User } from 'firebase/auth';
|
|
8
|
-
|
|
9
|
-
/**
|
|
10
|
-
* Create an auth state handler
|
|
11
|
-
*/
|
|
12
|
-
export function createAuthStateHandler(
|
|
13
|
-
setState: (user: User | null) => void,
|
|
14
|
-
setLoading: (loading: boolean) => void,
|
|
15
|
-
setError: (error: Error | null) => void
|
|
16
|
-
): (user: User | null) => void {
|
|
17
|
-
return (user: User | null) => {
|
|
18
|
-
try {
|
|
19
|
-
setState(user);
|
|
20
|
-
setError(null);
|
|
21
|
-
} catch (err) {
|
|
22
|
-
const error = err instanceof Error ? err : new Error('Auth state update failed');
|
|
23
|
-
setError(error);
|
|
24
|
-
} finally {
|
|
25
|
-
setLoading(false);
|
|
26
|
-
}
|
|
27
|
-
};
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
/**
|
|
31
|
-
* Hook for managing auth listener lifecycle
|
|
32
|
-
*/
|
|
33
|
-
export function useAuthListener(
|
|
34
|
-
auth: Auth | null,
|
|
35
|
-
onAuthStateChange: (user: User | null) => void
|
|
36
|
-
): void {
|
|
37
|
-
const unsubscribeRef = useRef<(() => void) | null>(null);
|
|
38
|
-
|
|
39
|
-
useEffect(() => {
|
|
40
|
-
// Cleanup previous listener
|
|
41
|
-
if (unsubscribeRef.current) {
|
|
42
|
-
unsubscribeRef.current();
|
|
43
|
-
unsubscribeRef.current = null;
|
|
44
|
-
}
|
|
45
|
-
|
|
46
|
-
if (!auth) {
|
|
47
|
-
onAuthStateChange(null);
|
|
48
|
-
return;
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
unsubscribeRef.current = onAuthStateChanged(auth, onAuthStateChange);
|
|
52
|
-
|
|
53
|
-
return () => {
|
|
54
|
-
if (unsubscribeRef.current) {
|
|
55
|
-
unsubscribeRef.current();
|
|
56
|
-
unsubscribeRef.current = null;
|
|
57
|
-
}
|
|
58
|
-
};
|
|
59
|
-
}, [auth, onAuthStateChange]);
|
|
60
|
-
}
|