naim-firebase-auth-wrapper
Version:
React components and hooks for Firebase Authentication and Firestore with Mantine UI
164 lines • 6.29 kB
JavaScript
'use client';
import { jsx as _jsx } from "react/jsx-runtime";
import { createContext, useEffect, useState, useRef } from 'react';
import { signOut, } from 'firebase/auth';
import { MantineProvider } from '@mantine/core';
import { initializeFirebase } from '../firebase/config';
import { StylesProvider } from './StylesProvider';
import '@mantine/core/styles.css';
import { getUserOrganizations, setCurrentOrganization, createSession, clearSession, validateSession, updateSessionActivity, getUserProfile } from '../services/firestore';
export const AuthContext = createContext(null);
export const AuthProvider = ({ config, children }) => {
const [user, setUser] = useState(null);
const [loading, setLoading] = useState(true);
const [error, setError] = useState(null);
const [currentOrganization, setCurrentOrgState] = useState(null);
const [organizations, setOrganizations] = useState([]);
const authRef = useRef(null);
const appRef = useRef(null);
const dbRef = useRef(null);
// Initialize Firebase
useEffect(() => {
try {
// Initialize Firebase with provided config
const { app, auth, db } = initializeFirebase(config);
if (!app || !auth || !db) {
console.error('[AuthProvider] Failed to initialize Firebase');
setError(new Error('Failed to initialize Firebase'));
setLoading(false);
return () => { }; // Return empty cleanup function
}
// Store auth reference for later use
authRef.current = auth;
appRef.current = app;
dbRef.current = db;
// Set up auth listener
const unsubscribe = auth.onAuthStateChanged(async (user) => {
if (user) {
try {
await createSession(user.uid);
}
catch (error) {
console.error('[AuthProvider] Error creating session:', error);
}
}
else {
try {
await clearSession();
}
catch (error) {
console.error('[AuthProvider] Error clearing session:', error);
}
}
setUser(user);
setLoading(false);
});
return () => unsubscribe();
}
catch (err) {
console.error('[AuthProvider] Error in Firebase initialization effect:', err);
setError(err instanceof Error ? err : new Error('Unknown error during initialization'));
setLoading(false);
return () => { }; // Return empty cleanup function
}
}, [config]);
// Load user organizations when user changes
useEffect(() => {
if (!user || loading) {
return;
}
loadOrganizations();
}, [user, loading]);
// Load organizations for a user
const loadOrganizations = async () => {
if (user?.uid) {
try {
const orgs = await getUserOrganizations(user.uid);
setOrganizations(orgs);
// Set current organization if exists in user profile or default to first org
const userProfile = await getUserProfile(user.uid);
if (userProfile?.currentOrganization) {
setCurrentOrgState(userProfile.currentOrganization);
}
else if (orgs.length > 0) {
setCurrentOrgState(orgs[0].id);
await setCurrentOrganization(user.uid, orgs[0].id);
}
}
catch (error) {
console.error('Error loading organizations:', error);
}
}
};
// Set current organization handler
const setCurrentOrganizationHandler = async (orgId) => {
if (!user?.uid)
return;
try {
await setCurrentOrganization(user.uid, orgId);
setCurrentOrgState(orgId);
}
catch (error) {
console.error('Error setting current organization:', error);
}
};
// Session activity update interval
useEffect(() => {
if (!user)
return;
// Validate session on load
validateSession().catch(console.error);
// Update session activity every 5 minutes
const intervalId = setInterval(() => {
const sessionId = localStorage.getItem('sessionId');
if (sessionId) {
updateSessionActivity(sessionId).catch(console.error);
}
}, 5 * 60 * 1000);
return () => clearInterval(intervalId);
}, [user]);
// Sign out handler
const signOutHandler = async () => {
if (!authRef.current) {
console.error('Auth is not available');
return;
}
try {
// Clear session before signing out
await clearSession();
await signOut(authRef.current);
}
catch (error) {
console.error('Error signing out:', error);
throw error;
}
};
// Create a context value object to avoid recreating it on each render
const contextValue = {
user,
loading,
error,
auth: authRef, // Expose auth instance
app: appRef, // Expose app instance
db: dbRef, // Expose db instance
signInWithGoogle: async () => {
// Implementation in useAuth hook
},
signInWithEmail: async () => {
// Implementation in useAuth hook
},
signUp: async () => {
// Implementation in useAuth hook
},
signOut: signOutHandler,
forgotPassword: async () => {
// Implementation in useAuth hook
},
currentOrganization,
setCurrentOrganization: setCurrentOrganizationHandler,
organizations,
loadOrganizations
};
return (_jsx(StylesProvider, { children: _jsx(MantineProvider, { children: _jsx(AuthContext.Provider, { value: contextValue, children: children }) }) }));
};
//# sourceMappingURL=AuthProvider.js.map