import { useCallback } from 'react';
import { usePersSDK } from '../providers/PersSDKProvider';
import type { RawUserData } from '@explorins/pers-sdk/core';
import { AccountOwnerType } from '@explorins/pers-sdk/core';
import type { UserDTO, SessionAuthContextResponseDTO } from '@explorins/pers-sdk';
// Re-export RawUserData for convenience
export type { RawUserData };
/**
* React hook for authentication operations in the PERS SDK
*
* Provides methods for user login, logout, token management, and authentication state.
* Automatically manages authentication state and user data synchronization.
*
* @returns Authentication hook with methods and state
*
* @example
* ```typescript
* function LoginComponent() {
* const { login, logout, isAuthenticated, user } = useAuth();
*
* const handleLogin = async (token: string) => {
* try {
* await login(token, 'user');
* console.log('Login successful');
* } catch (error) {
* console.error('Login failed:', error);
* }
* };
*
* return (
*
* {isAuthenticated ? (
*
*
Welcome, {user?.name}
*
*
* ) : (
*
* )}
*
* );
* }
* ```
*/
export const useAuth = () => {
const {
sdk,
authProvider,
isInitialized,
isAuthenticated,
user,
refreshUserData
} = usePersSDK();
/**
* Authenticates a user with a JWT token
*
* @param jwtToken - The JWT token to authenticate with
* @param userType - The type of user (AccountOwnerType), defaults to USER
* @returns Promise resolving to session auth context with user data
* @throws Error if SDK is not initialized or authentication fails
*
* @example
* ```typescript
* const { login } = useAuth();
* const result = await login(jwtToken, AccountOwnerType.USER);
* console.log('Logged in user:', result.user);
* ```
*/
const login = useCallback(async (jwtToken: string, userType: AccountOwnerType = AccountOwnerType.USER): Promise => {
if (!sdk || !authProvider) {
throw new Error('SDK not initialized. Call initialize() first.');
}
try {
// Set token in auth provider
await authProvider.setAccessToken(jwtToken);
// Perform login - emits login_success event which Provider handles
const result = await sdk.auth.loginWithToken(jwtToken, userType);
return result;
} catch (error) {
console.error('Login failed:', error);
throw error;
}
}, [sdk, authProvider]);
/**
* Logs in a user using raw user data (direct authentication bypass)
*
* @param rawUserData - Raw user data for direct authentication
* @throws Error if SDK is not initialized or authentication fails
*
* @example
* ```typescript
* const { loginWithRawData } = useAuth();
* await loginWithRawData({ userId: '123', email: 'user@example.com' });
* ```
*/
const loginWithRawData = useCallback(async (rawUserData: RawUserData): Promise => {
if (!sdk || !authProvider) {
throw new Error('SDK not initialized. Call initialize() first.');
}
try {
// Use the raw data login - emits login_success event which Provider handles
const result = await sdk.auth.loginWithRawData(rawUserData);
// Set token from result
if (result.accessToken) {
await authProvider.setAccessToken(result.accessToken);
}
} catch (error) {
console.error('Raw data login failed:', error);
throw error;
}
}, [sdk, authProvider]);
/**
* Logs out the current user and clears authentication state
*
* @throws Error if logout process fails
*
* @example
* ```typescript
* const { logout } = useAuth();
* await logout();
* console.log('User logged out');
* ```
*/
const logout = useCallback(async (): Promise => {
if (!sdk) {
throw new Error('SDK not initialized. Call initialize() first.');
}
try {
// clearAuth emits logout_success event which Provider handles
await sdk.auth.clearAuth();
} catch (error) {
console.error('Logout failed:', error);
throw error;
}
}, [sdk]);
/**
* Retrieves the current authenticated user data
*
* @returns Promise resolving to current user data
* @throws Error if SDK is not initialized
*
* @example
* ```typescript
* const { getCurrentUser } = useAuth();
* const user = await getCurrentUser();
* console.log('Current user:', user.email);
* ```
*/
const getCurrentUser = useCallback(async (): Promise => {
if (!sdk) {
throw new Error('SDK not initialized. Call initialize() first.');
}
return sdk.auth.getCurrentUser();
}, [sdk]);
/**
* Checks if the current session is authenticated
*
* @returns Promise resolving to authentication status
*
* @example
* ```typescript
* const { checkIsAuthenticated } = useAuth();
* const isAuth = await checkIsAuthenticated();
* console.log('Is authenticated:', isAuth);
* ```
*/
const checkIsAuthenticated = useCallback(async (): Promise => {
if (!sdk) {
return false;
}
return sdk.auth.isAuthenticated();
}, [sdk]);
/**
* Refreshes authentication tokens
*
* @param refreshToken - Optional refresh token to use
* @returns Promise resolving to new session auth response
* @throws Error if SDK is not initialized
*
* @example
* ```typescript
* const { refreshTokens } = useAuth();
* const tokens = await refreshTokens();
* console.log('Tokens refreshed:', tokens);
* ```
*/
const refreshTokens = useCallback(async (refreshToken?: string) => {
if (!sdk) {
throw new Error('SDK not initialized. Call initialize() first.');
}
return sdk.auth.refreshTokens(refreshToken);
}, [sdk]);
/**
* Clears all authentication data and resets auth state
*
* @throws Error if SDK is not initialized
*
* @example
* ```typescript
* const { clearAuth } = useAuth();
* await clearAuth();
* console.log('Auth data cleared');
* ```
*/
const clearAuth = useCallback(async (): Promise => {
if (!sdk) {
throw new Error('SDK not initialized. Call initialize() first.');
}
// clearAuth emits logout_success event which Provider handles
await sdk.auth.clearAuth();
}, [sdk]);
/**
* Checks if the current authentication is valid (non-expired)
*
* @returns Boolean indicating if auth is valid
*
* @example
* ```typescript
* const { hasValidAuth } = useAuth();
* const isValid = hasValidAuth();
* console.log('Auth is valid:', isValid);
* ```
*/
const hasValidAuth = useCallback(async (): Promise => {
if (!sdk) {
return false;
}
return await sdk.auth.hasValidAuth();
}, [sdk]);
return {
// State
isInitialized,
isAuthenticated,
user,
// Methods
login,
loginWithRawData,
logout,
refreshUserData,
getCurrentUser,
checkIsAuthenticated,
refreshTokens,
clearAuth,
hasValidAuth,
};
};
export type AuthHook = ReturnType;