import React, { createContext, useContext, useState, useEffect, ReactNode } from 'react'; import type FileSystem from '@oddjs/odd/fs/index'; import { Session, SessionError } from '../lib/auth/types'; import { AuthService } from '../lib/auth/authService'; import { saveSession, clearStoredSession } from '../lib/auth/sessionPersistence'; interface AuthContextType { session: Session; setSession: (updatedSession: Partial) => void; updateSession: (updatedSession: Partial) => void; clearSession: () => void; fileSystem: FileSystem | null; setFileSystem: (fs: FileSystem | null) => void; initialize: () => Promise; login: (username: string) => Promise; register: (username: string) => Promise; logout: () => Promise; } const initialSession: Session = { username: '', authed: false, loading: true, backupCreated: null }; const AuthContext = createContext(undefined); export const AuthProvider: React.FC<{ children: ReactNode }> = ({ children }) => { const [session, setSessionState] = useState(initialSession); const [fileSystem, setFileSystemState] = useState(null); // Update session with partial data const setSession = (updatedSession: Partial) => { setSessionState(prev => { const newSession = { ...prev, ...updatedSession }; // Save session to localStorage if authenticated if (newSession.authed && newSession.username) { saveSession(newSession); } return newSession; }); }; // Set file system const setFileSystem = (fs: FileSystem | null) => { setFileSystemState(fs); }; /** * Initialize the authentication state */ const initialize = async (): Promise => { setSession({ loading: true }); try { const { session: newSession, fileSystem: newFs } = await AuthService.initialize(); setSession(newSession); setFileSystem(newFs); } catch (error) { setSession({ loading: false, authed: false, error: error as SessionError }); } }; /** * Login with a username */ const login = async (username: string): Promise => { setSession({ loading: true }); const result = await AuthService.login(username); if (result.success && result.session && result.fileSystem) { setSession(result.session); setFileSystem(result.fileSystem); return true; } else { setSession({ loading: false, error: result.error as SessionError }); return false; } }; /** * Register a new user */ const register = async (username: string): Promise => { setSession({ loading: true }); const result = await AuthService.register(username); if (result.success && result.session && result.fileSystem) { setSession(result.session); setFileSystem(result.fileSystem); return true; } else { setSession({ loading: false, error: result.error as SessionError }); return false; } }; /** * Clear the current session */ const clearSession = (): void => { clearStoredSession(); setSession({ username: '', authed: false, loading: false, backupCreated: null }); setFileSystem(null); }; /** * Logout the current user */ const logout = async (): Promise => { try { await AuthService.logout(); clearSession(); } catch (error) { console.error('Logout error:', error); throw error; } }; // Initialize on mount useEffect(() => { initialize(); }, []); const contextValue: AuthContextType = { session, setSession, updateSession: setSession, clearSession, fileSystem, setFileSystem, initialize, login, register, logout }; return ( {children} ); }; export const useAuth = (): AuthContextType => { const context = useContext(AuthContext); if (context === undefined) { throw new Error('useAuth must be used within an AuthProvider'); } return context; };