@umituz/react-native-auth 2.7.3 → 2.7.6
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 +40 -16
- package/src/application/ports/IAuthRepository.ts +11 -0
- package/src/infrastructure/adapters/StorageProviderAdapter.ts +26 -10
- package/src/infrastructure/adapters/UIProviderAdapter.ts +20 -9
- package/src/infrastructure/providers/FirebaseAuthProvider.ts +3 -2
- package/src/infrastructure/repositories/AuthRepository.ts +91 -0
- package/src/infrastructure/services/AuthPackage.ts +14 -6
- package/src/infrastructure/services/AuthService.ts +67 -119
- package/src/infrastructure/services/GuestModeService.ts +1 -6
- package/src/infrastructure/utils/AuthValidation.ts +15 -14
- package/src/infrastructure/utils/auth-tracker.util.ts +28 -0
- package/src/presentation/components/AccountActions.tsx +38 -50
- package/src/presentation/components/AuthBottomSheet.tsx +4 -4
- package/src/presentation/components/AuthDivider.tsx +0 -1
- package/src/presentation/components/AuthGradientBackground.tsx +1 -1
- package/src/presentation/components/AuthLegalLinks.tsx +7 -8
- package/src/presentation/components/EditProfileActions.tsx +53 -0
- package/src/presentation/components/EditProfileAvatar.tsx +33 -0
- package/src/presentation/components/EditProfileForm.tsx +55 -0
- package/src/presentation/components/LoginForm.tsx +1 -1
- package/src/presentation/components/PasswordMatchIndicator.tsx +6 -14
- package/src/presentation/components/PasswordStrengthIndicator.tsx +11 -17
- package/src/presentation/components/ProfileBenefitsList.tsx +47 -0
- package/src/presentation/components/ProfileSection.tsx +20 -85
- package/src/presentation/components/RegisterForm.tsx +6 -6
- package/src/presentation/components/SocialLoginButtons.tsx +11 -15
- package/src/presentation/hooks/mutations/useAuthMutations.ts +50 -0
- package/src/presentation/hooks/useAccountManagement.ts +1 -0
- package/src/presentation/hooks/useAuthActions.ts +19 -35
- package/src/presentation/hooks/useAuthState.ts +3 -1
- package/src/presentation/hooks/useLoginForm.ts +6 -8
- package/src/presentation/hooks/useProfileUpdate.ts +7 -7
- package/src/presentation/hooks/useRegisterForm.ts +16 -17
- package/src/presentation/hooks/useUserProfile.ts +3 -3
- package/src/presentation/navigation/AuthNavigator.tsx +10 -6
- package/src/presentation/screens/AccountScreen.tsx +9 -1
- package/src/presentation/screens/EditProfileScreen.tsx +40 -185
- package/src/presentation/screens/LoginScreen.tsx +4 -6
- package/src/presentation/screens/RegisterScreen.tsx +4 -6
- package/src/presentation/stores/authModalStore.ts +2 -1
- package/src/types/external.d.ts +31 -45
- package/src/infrastructure/services/AuthCoreService.ts +0 -138
package/package.json
CHANGED
|
@@ -1,12 +1,13 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@umituz/react-native-auth",
|
|
3
|
-
"version": "2.7.
|
|
3
|
+
"version": "2.7.6",
|
|
4
4
|
"description": "Authentication service for React Native apps - Secure, type-safe, and production-ready. Provider-agnostic design with dependency injection, configurable validation, and comprehensive error handling.",
|
|
5
5
|
"main": "./src/index.ts",
|
|
6
6
|
"types": "./src/index.ts",
|
|
7
7
|
"scripts": {
|
|
8
|
-
"typecheck": "
|
|
9
|
-
"lint": "
|
|
8
|
+
"typecheck": "tsc --noEmit",
|
|
9
|
+
"lint": "eslint src --ext .ts,.tsx --max-warnings 0",
|
|
10
|
+
"lint:fix": "eslint src --ext .ts,.tsx --fix",
|
|
10
11
|
"version:patch": "npm version patch -m 'chore: release v%s'",
|
|
11
12
|
"version:minor": "npm version minor -m 'chore: release v%s'",
|
|
12
13
|
"version:major": "npm version major -m 'chore: release v%s'"
|
|
@@ -34,12 +35,14 @@
|
|
|
34
35
|
"@gorhom/bottom-sheet": ">=4.0.0",
|
|
35
36
|
"@react-navigation/native": ">=6.0.0",
|
|
36
37
|
"@react-navigation/stack": ">=6.0.0",
|
|
37
|
-
"@
|
|
38
|
-
"@umituz/react-native-
|
|
39
|
-
"@umituz/react-native-
|
|
40
|
-
"@umituz/react-native-
|
|
41
|
-
"@umituz/react-native-
|
|
42
|
-
"@umituz/react-native-
|
|
38
|
+
"@tanstack/react-query": ">=5.0.0",
|
|
39
|
+
"@umituz/react-native-design-system": "*",
|
|
40
|
+
"@umituz/react-native-firebase": "*",
|
|
41
|
+
"@umituz/react-native-localization": "*",
|
|
42
|
+
"@umituz/react-native-sentry": "*",
|
|
43
|
+
"@umituz/react-native-storage": "*",
|
|
44
|
+
"@umituz/react-native-tanstack": "*",
|
|
45
|
+
"@umituz/react-native-validation": "*",
|
|
43
46
|
"expo-linear-gradient": ">=13.0.0",
|
|
44
47
|
"firebase": ">=11.0.0",
|
|
45
48
|
"react": ">=18.2.0",
|
|
@@ -51,20 +54,40 @@
|
|
|
51
54
|
"zustand": ">=4.0.0"
|
|
52
55
|
},
|
|
53
56
|
"devDependencies": {
|
|
57
|
+
"@expo/vector-icons": "^15.0.3",
|
|
54
58
|
"@gorhom/bottom-sheet": "^5.0.0",
|
|
55
59
|
"@react-native-async-storage/async-storage": "^1.24.0",
|
|
60
|
+
"@react-native-community/datetimepicker": "^8.5.1",
|
|
61
|
+
"@react-navigation/bottom-tabs": "^7.9.0",
|
|
56
62
|
"@react-navigation/native": "^6.0.0",
|
|
57
63
|
"@react-navigation/stack": "^6.0.0",
|
|
64
|
+
"@sentry/react-native": "^7.8.0",
|
|
65
|
+
"@sentry/types": "^10.32.1",
|
|
66
|
+
"@tanstack/react-query": "^5.0.0",
|
|
58
67
|
"@types/node": "^20.0.0",
|
|
59
68
|
"@types/react": "~19.1.0",
|
|
60
|
-
"@
|
|
61
|
-
"@
|
|
62
|
-
"@umituz/react-native-
|
|
63
|
-
"@umituz/react-native-
|
|
64
|
-
"@umituz/react-native-
|
|
69
|
+
"@typescript-eslint/eslint-plugin": "^7.0.0",
|
|
70
|
+
"@typescript-eslint/parser": "^7.0.0",
|
|
71
|
+
"@umituz/react-native-design-system": "^2.3.31",
|
|
72
|
+
"@umituz/react-native-design-system-theme": "^1.12.3",
|
|
73
|
+
"@umituz/react-native-firebase": "*",
|
|
74
|
+
"@umituz/react-native-haptics": "^1.0.2",
|
|
75
|
+
"@umituz/react-native-localization": "*",
|
|
76
|
+
"@umituz/react-native-sentry": "*",
|
|
77
|
+
"@umituz/react-native-storage": "*",
|
|
78
|
+
"@umituz/react-native-tanstack": "*",
|
|
79
|
+
"@umituz/react-native-uuid": "^1.2.1",
|
|
80
|
+
"@umituz/react-native-validation": "*",
|
|
81
|
+
"eslint": "^8.57.0",
|
|
65
82
|
"expo-apple-authentication": "^6.0.0",
|
|
83
|
+
"expo-application": "^7.0.8",
|
|
84
|
+
"expo-clipboard": "^8.0.8",
|
|
66
85
|
"expo-crypto": "^12.0.0",
|
|
86
|
+
"expo-device": "^8.0.10",
|
|
87
|
+
"expo-file-system": "^19.0.21",
|
|
88
|
+
"expo-haptics": "^15.0.8",
|
|
67
89
|
"expo-linear-gradient": "^13.0.0",
|
|
90
|
+
"expo-sharing": "^14.0.8",
|
|
68
91
|
"firebase": "^11.0.0",
|
|
69
92
|
"react": "~19.1.0",
|
|
70
93
|
"react-native": "~0.81.5",
|
|
@@ -72,7 +95,8 @@
|
|
|
72
95
|
"react-native-reanimated": "^3.0.0",
|
|
73
96
|
"react-native-safe-area-context": "^4.0.0",
|
|
74
97
|
"react-native-svg": "^15.15.1",
|
|
75
|
-
"
|
|
98
|
+
"rn-emoji-keyboard": "^1.7.0",
|
|
99
|
+
"typescript": "^5.3.0",
|
|
76
100
|
"zustand": "^4.0.0"
|
|
77
101
|
},
|
|
78
102
|
"publishConfig": {
|
|
@@ -83,4 +107,4 @@
|
|
|
83
107
|
"README.md",
|
|
84
108
|
"LICENSE"
|
|
85
109
|
]
|
|
86
|
-
}
|
|
110
|
+
}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
|
|
2
|
+
import type { AuthUser } from "../../domain/entities/AuthUser";
|
|
3
|
+
import type { SignUpParams, SignInParams } from "../ports/IAuthService";
|
|
4
|
+
|
|
5
|
+
export interface IAuthRepository {
|
|
6
|
+
signUp(params: SignUpParams): Promise<AuthUser>;
|
|
7
|
+
signIn(params: SignInParams): Promise<AuthUser>;
|
|
8
|
+
signOut(): Promise<void>;
|
|
9
|
+
getCurrentUser(): AuthUser | null;
|
|
10
|
+
onAuthStateChange(callback: (user: AuthUser | null) => void): () => void;
|
|
11
|
+
}
|
|
@@ -3,21 +3,37 @@
|
|
|
3
3
|
* Adapts external storage implementations to our IStorageProvider interface
|
|
4
4
|
*/
|
|
5
5
|
|
|
6
|
-
import type { IStorageProvider } from "../services/
|
|
6
|
+
import type { IStorageProvider } from "../services/AuthPackage";
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* Interface that describes the shape of common storage implementations
|
|
10
|
+
* to avoid using 'any' and resolve lint errors.
|
|
11
|
+
*/
|
|
12
|
+
interface StorageLike {
|
|
13
|
+
getString?: (
|
|
14
|
+
key: string,
|
|
15
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
16
|
+
defaultValue?: any
|
|
17
|
+
) => Promise<{ value: string | null } | null>;
|
|
18
|
+
getItem?: (key: string) => Promise<string | null>;
|
|
19
|
+
setString?: (key: string, value: string) => Promise<void>;
|
|
20
|
+
setItem?: (key: string, value: string) => Promise<void>;
|
|
21
|
+
removeItem?: (key: string) => Promise<void>;
|
|
22
|
+
}
|
|
7
23
|
|
|
8
24
|
export class StorageProviderAdapter implements IStorageProvider {
|
|
9
|
-
private storage:
|
|
25
|
+
private storage: StorageLike;
|
|
10
26
|
|
|
11
|
-
constructor(storage:
|
|
12
|
-
this.storage = storage;
|
|
27
|
+
constructor(storage: unknown) {
|
|
28
|
+
this.storage = storage as StorageLike;
|
|
13
29
|
}
|
|
14
30
|
|
|
15
31
|
async get(key: string): Promise<string | null> {
|
|
16
32
|
try {
|
|
17
|
-
if (this.storage.getString) {
|
|
33
|
+
if (typeof this.storage.getString === "function") {
|
|
18
34
|
const result = await this.storage.getString(key, null);
|
|
19
35
|
return result?.value ?? null;
|
|
20
|
-
} else if (this.storage.getItem) {
|
|
36
|
+
} else if (typeof this.storage.getItem === "function") {
|
|
21
37
|
return await this.storage.getItem(key);
|
|
22
38
|
} else {
|
|
23
39
|
throw new Error("Unsupported storage implementation");
|
|
@@ -28,9 +44,9 @@ export class StorageProviderAdapter implements IStorageProvider {
|
|
|
28
44
|
}
|
|
29
45
|
|
|
30
46
|
async set(key: string, value: string): Promise<void> {
|
|
31
|
-
if (this.storage.setString) {
|
|
47
|
+
if (typeof this.storage.setString === "function") {
|
|
32
48
|
await this.storage.setString(key, value);
|
|
33
|
-
} else if (this.storage.setItem) {
|
|
49
|
+
} else if (typeof this.storage.setItem === "function") {
|
|
34
50
|
await this.storage.setItem(key, value);
|
|
35
51
|
} else {
|
|
36
52
|
throw new Error("Unsupported storage implementation");
|
|
@@ -38,7 +54,7 @@ export class StorageProviderAdapter implements IStorageProvider {
|
|
|
38
54
|
}
|
|
39
55
|
|
|
40
56
|
async remove(key: string): Promise<void> {
|
|
41
|
-
if (this.storage.removeItem) {
|
|
57
|
+
if (typeof this.storage.removeItem === "function") {
|
|
42
58
|
await this.storage.removeItem(key);
|
|
43
59
|
} else {
|
|
44
60
|
throw new Error("Unsupported storage implementation");
|
|
@@ -46,6 +62,6 @@ export class StorageProviderAdapter implements IStorageProvider {
|
|
|
46
62
|
}
|
|
47
63
|
}
|
|
48
64
|
|
|
49
|
-
export function createStorageProvider(storage:
|
|
65
|
+
export function createStorageProvider(storage: unknown): IStorageProvider {
|
|
50
66
|
return new StorageProviderAdapter(storage);
|
|
51
67
|
}
|
|
@@ -3,30 +3,37 @@
|
|
|
3
3
|
* Adapts external UI implementations to our IUIProvider interface
|
|
4
4
|
*/
|
|
5
5
|
|
|
6
|
+
import type { DesignTokens } from "@umituz/react-native-design-system";
|
|
6
7
|
import type { IUIProvider } from "../services/AuthPackage";
|
|
7
8
|
|
|
8
9
|
export class UIProviderAdapter implements IUIProvider {
|
|
9
|
-
private theme:
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
10
|
+
private theme: DesignTokens | null = null;
|
|
11
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
12
|
+
private localization: any = null;
|
|
13
|
+
|
|
14
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
15
|
+
constructor(theme?: DesignTokens, localization?: any) {
|
|
16
|
+
this.theme = theme || null;
|
|
17
|
+
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
|
|
18
|
+
this.localization = localization || null;
|
|
15
19
|
}
|
|
16
20
|
|
|
17
|
-
getTheme():
|
|
21
|
+
getTheme(): DesignTokens | null {
|
|
18
22
|
return this.theme;
|
|
19
23
|
}
|
|
20
24
|
|
|
25
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
21
26
|
getLocalization(): any {
|
|
22
27
|
return this.localization;
|
|
23
28
|
}
|
|
24
29
|
|
|
25
|
-
updateTheme(theme:
|
|
30
|
+
updateTheme(theme: DesignTokens): void {
|
|
26
31
|
this.theme = theme;
|
|
27
32
|
}
|
|
28
33
|
|
|
34
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
29
35
|
updateLocalization(localization: any): void {
|
|
36
|
+
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
|
|
30
37
|
this.localization = localization;
|
|
31
38
|
}
|
|
32
39
|
}
|
|
@@ -34,6 +41,10 @@ export class UIProviderAdapter implements IUIProvider {
|
|
|
34
41
|
/**
|
|
35
42
|
* Create UI provider from theme and localization implementations
|
|
36
43
|
*/
|
|
37
|
-
export function createUIProvider(
|
|
44
|
+
export function createUIProvider(
|
|
45
|
+
theme?: DesignTokens,
|
|
46
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
47
|
+
localization?: any
|
|
48
|
+
): IUIProvider {
|
|
38
49
|
return new UIProviderAdapter(theme, localization);
|
|
39
50
|
}
|
|
@@ -9,7 +9,6 @@ import {
|
|
|
9
9
|
signOut as firebaseSignOut,
|
|
10
10
|
onAuthStateChanged,
|
|
11
11
|
updateProfile,
|
|
12
|
-
type User,
|
|
13
12
|
type Auth,
|
|
14
13
|
} from "firebase/auth";
|
|
15
14
|
import type {
|
|
@@ -34,6 +33,8 @@ export class FirebaseAuthProvider implements IAuthProvider {
|
|
|
34
33
|
if (!this.auth) {
|
|
35
34
|
throw new Error("Firebase Auth instance must be provided");
|
|
36
35
|
}
|
|
36
|
+
// Satisfy require-await
|
|
37
|
+
await Promise.resolve();
|
|
37
38
|
}
|
|
38
39
|
|
|
39
40
|
setAuth(auth: Auth): void {
|
|
@@ -119,7 +120,7 @@ export class FirebaseAuthProvider implements IAuthProvider {
|
|
|
119
120
|
onAuthStateChange(callback: (user: AuthUser | null) => void): () => void {
|
|
120
121
|
if (!this.auth) {
|
|
121
122
|
callback(null);
|
|
122
|
-
return () => {};
|
|
123
|
+
return () => { };
|
|
123
124
|
}
|
|
124
125
|
|
|
125
126
|
return onAuthStateChanged(this.auth, (user) => {
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Auth Repository
|
|
3
|
+
* Implementation of the Auth Repository Port
|
|
4
|
+
* Handles data access for authentication
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
import type { IAuthRepository } from "../../application/ports/IAuthRepository";
|
|
8
|
+
import type { IAuthProvider } from "../../application/ports/IAuthProvider";
|
|
9
|
+
import type { AuthUser } from "../../domain/entities/AuthUser";
|
|
10
|
+
import type { SignUpParams, SignInParams } from "../../application/ports/IAuthService";
|
|
11
|
+
import {
|
|
12
|
+
AuthValidationError,
|
|
13
|
+
AuthWeakPasswordError,
|
|
14
|
+
AuthInvalidEmailError,
|
|
15
|
+
} from "../../domain/errors/AuthError";
|
|
16
|
+
import {
|
|
17
|
+
validateEmail,
|
|
18
|
+
validatePasswordForLogin,
|
|
19
|
+
validatePasswordForRegister,
|
|
20
|
+
validateDisplayName,
|
|
21
|
+
} from "../utils/AuthValidation";
|
|
22
|
+
import type { AuthConfig } from "../../domain/value-objects/AuthConfig";
|
|
23
|
+
|
|
24
|
+
export class AuthRepository implements IAuthRepository {
|
|
25
|
+
private provider: IAuthProvider;
|
|
26
|
+
private config: AuthConfig;
|
|
27
|
+
|
|
28
|
+
constructor(provider: IAuthProvider, config: AuthConfig) {
|
|
29
|
+
this.provider = provider;
|
|
30
|
+
this.config = config;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
async signUp(params: SignUpParams): Promise<AuthUser> {
|
|
34
|
+
// Validate email
|
|
35
|
+
const emailResult = validateEmail(params.email);
|
|
36
|
+
if (!emailResult.isValid) {
|
|
37
|
+
throw new AuthInvalidEmailError(emailResult.error);
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
// Validate display name if provided
|
|
41
|
+
if (params.displayName) {
|
|
42
|
+
const nameResult = validateDisplayName(params.displayName);
|
|
43
|
+
if (!nameResult.isValid) {
|
|
44
|
+
throw new AuthValidationError(nameResult.error || "Invalid name", "displayName");
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
// Validate password strength for registration
|
|
49
|
+
const passwordResult = validatePasswordForRegister(params.password, this.config.password);
|
|
50
|
+
if (!passwordResult.isValid) {
|
|
51
|
+
throw new AuthWeakPasswordError(passwordResult.error);
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
return this.provider.signUp({
|
|
55
|
+
email: params.email,
|
|
56
|
+
password: params.password,
|
|
57
|
+
displayName: params.displayName,
|
|
58
|
+
});
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
async signIn(params: SignInParams): Promise<AuthUser> {
|
|
62
|
+
// Validate email format
|
|
63
|
+
const emailResult = validateEmail(params.email);
|
|
64
|
+
if (!emailResult.isValid) {
|
|
65
|
+
throw new AuthInvalidEmailError(emailResult.error);
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
// For login, only check if password is provided (no strength requirements)
|
|
69
|
+
const passwordResult = validatePasswordForLogin(params.password);
|
|
70
|
+
if (!passwordResult.isValid) {
|
|
71
|
+
throw new AuthValidationError(passwordResult.error || "Password is required", "password");
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
return this.provider.signIn({
|
|
75
|
+
email: params.email,
|
|
76
|
+
password: params.password,
|
|
77
|
+
});
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
async signOut(): Promise<void> {
|
|
81
|
+
await this.provider.signOut();
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
getCurrentUser(): AuthUser | null {
|
|
85
|
+
return this.provider.getCurrentUser();
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
onAuthStateChange(callback: (user: AuthUser | null) => void): () => void {
|
|
89
|
+
return this.provider.onAuthStateChange(callback);
|
|
90
|
+
}
|
|
91
|
+
}
|
|
@@ -3,7 +3,8 @@
|
|
|
3
3
|
* Centralized configuration for the auth package
|
|
4
4
|
*/
|
|
5
5
|
|
|
6
|
-
import type {
|
|
6
|
+
import type { DesignTokens } from "@umituz/react-native-design-system";
|
|
7
|
+
import type { PasswordConfig } from "../../domain/value-objects/AuthConfig";
|
|
7
8
|
|
|
8
9
|
export interface AuthPackageConfig {
|
|
9
10
|
storageKeys: {
|
|
@@ -15,7 +16,8 @@ export interface AuthPackageConfig {
|
|
|
15
16
|
passwordConfig: PasswordConfig;
|
|
16
17
|
};
|
|
17
18
|
ui: {
|
|
18
|
-
theme?:
|
|
19
|
+
theme?: DesignTokens;
|
|
20
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
19
21
|
localization?: any;
|
|
20
22
|
};
|
|
21
23
|
features: {
|
|
@@ -58,13 +60,17 @@ export interface IStorageProvider {
|
|
|
58
60
|
}
|
|
59
61
|
|
|
60
62
|
export interface IUIProvider {
|
|
61
|
-
getTheme():
|
|
63
|
+
getTheme(): DesignTokens | null;
|
|
64
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
62
65
|
getLocalization(): any;
|
|
63
66
|
}
|
|
64
67
|
|
|
65
68
|
export interface IValidationProvider {
|
|
66
69
|
validateEmail(email: string): { isValid: boolean; error?: string };
|
|
67
|
-
validatePassword(
|
|
70
|
+
validatePassword(
|
|
71
|
+
password: string,
|
|
72
|
+
config: PasswordConfig
|
|
73
|
+
): { isValid: boolean; error?: string };
|
|
68
74
|
}
|
|
69
75
|
|
|
70
76
|
export class AuthPackage {
|
|
@@ -124,7 +130,7 @@ export class AuthPackage {
|
|
|
124
130
|
return this.validationProvider;
|
|
125
131
|
}
|
|
126
132
|
|
|
127
|
-
isFeatureEnabled(feature: keyof AuthPackageConfig[
|
|
133
|
+
isFeatureEnabled(feature: keyof AuthPackageConfig["features"]): boolean {
|
|
128
134
|
return this.config.features[feature];
|
|
129
135
|
}
|
|
130
136
|
}
|
|
@@ -132,7 +138,9 @@ export class AuthPackage {
|
|
|
132
138
|
// Global package instance
|
|
133
139
|
let packageInstance: AuthPackage | null = null;
|
|
134
140
|
|
|
135
|
-
export function initializeAuthPackage(
|
|
141
|
+
export function initializeAuthPackage(
|
|
142
|
+
config: Partial<AuthPackageConfig> = {}
|
|
143
|
+
): AuthPackage {
|
|
136
144
|
if (!packageInstance) {
|
|
137
145
|
packageInstance = new AuthPackage(config);
|
|
138
146
|
}
|