Spaces:
Sleeping
Sleeping
| import { useEffect, useState } from 'react'; | |
| import { toast } from 'react-toastify'; | |
| import { useStore } from '@nanostores/react'; | |
| import { logStore } from '~/lib/stores/logs'; | |
| import { | |
| supabaseConnection, | |
| isConnecting, | |
| isFetchingStats, | |
| isFetchingApiKeys, | |
| updateSupabaseConnection, | |
| fetchProjectApiKeys, | |
| } from '~/lib/stores/supabase'; | |
| export function useSupabaseConnection() { | |
| const connection = useStore(supabaseConnection); | |
| const connecting = useStore(isConnecting); | |
| const fetchingStats = useStore(isFetchingStats); | |
| const fetchingApiKeys = useStore(isFetchingApiKeys); | |
| const [isProjectsExpanded, setIsProjectsExpanded] = useState(false); | |
| const [isDropdownOpen, setIsDropdownOpen] = useState(false); | |
| useEffect(() => { | |
| const savedConnection = localStorage.getItem('supabase_connection'); | |
| const savedCredentials = localStorage.getItem('supabaseCredentials'); | |
| if (savedConnection) { | |
| const parsed = JSON.parse(savedConnection); | |
| if (savedCredentials && !parsed.credentials) { | |
| parsed.credentials = JSON.parse(savedCredentials); | |
| } | |
| updateSupabaseConnection(parsed); | |
| if (parsed.token && parsed.selectedProjectId && !parsed.credentials) { | |
| fetchProjectApiKeys(parsed.selectedProjectId, parsed.token).catch(console.error); | |
| } | |
| } | |
| }, []); | |
| const handleConnect = async () => { | |
| isConnecting.set(true); | |
| try { | |
| const cleanToken = connection.token.trim(); | |
| const response = await fetch('/api/supabase', { | |
| method: 'POST', | |
| headers: { | |
| 'Content-Type': 'application/json', | |
| }, | |
| body: JSON.stringify({ | |
| token: cleanToken, | |
| }), | |
| }); | |
| const data = (await response.json()) as any; | |
| if (!response.ok) { | |
| throw new Error(data.error || 'Failed to connect'); | |
| } | |
| updateSupabaseConnection({ | |
| user: data.user, | |
| token: connection.token, | |
| stats: data.stats, | |
| }); | |
| toast.success('Successfully connected to Supabase'); | |
| setIsProjectsExpanded(true); | |
| return true; | |
| } catch (error) { | |
| console.error('Connection error:', error); | |
| logStore.logError('Failed to authenticate with Supabase', { error }); | |
| toast.error(error instanceof Error ? error.message : 'Failed to connect to Supabase'); | |
| updateSupabaseConnection({ user: null, token: '' }); | |
| return false; | |
| } finally { | |
| isConnecting.set(false); | |
| } | |
| }; | |
| const handleDisconnect = () => { | |
| updateSupabaseConnection({ user: null, token: '' }); | |
| toast.success('Disconnected from Supabase'); | |
| setIsDropdownOpen(false); | |
| }; | |
| const selectProject = async (projectId: string) => { | |
| const currentState = supabaseConnection.get(); | |
| let projectData = undefined; | |
| if (projectId && currentState.stats?.projects) { | |
| projectData = currentState.stats.projects.find((project) => project.id === projectId); | |
| } | |
| updateSupabaseConnection({ | |
| selectedProjectId: projectId, | |
| project: projectData, | |
| }); | |
| if (projectId && currentState.token) { | |
| try { | |
| await fetchProjectApiKeys(projectId, currentState.token); | |
| toast.success('Project selected successfully'); | |
| } catch (error) { | |
| console.error('Failed to fetch API keys:', error); | |
| toast.error('Selected project but failed to fetch API keys'); | |
| } | |
| } else { | |
| toast.success('Project selected successfully'); | |
| } | |
| setIsDropdownOpen(false); | |
| }; | |
| const handleCreateProject = async () => { | |
| window.open('https://app.supabase.com/new/new-project', '_blank'); | |
| }; | |
| return { | |
| connection, | |
| connecting, | |
| fetchingStats, | |
| fetchingApiKeys, | |
| isProjectsExpanded, | |
| setIsProjectsExpanded, | |
| isDropdownOpen, | |
| setIsDropdownOpen, | |
| handleConnect, | |
| handleDisconnect, | |
| selectProject, | |
| handleCreateProject, | |
| updateToken: (token: string) => updateSupabaseConnection({ ...connection, token }), | |
| isConnected: !!(connection.user && connection.token), | |
| fetchProjectApiKeys: (projectId: string) => { | |
| if (connection.token) { | |
| return fetchProjectApiKeys(projectId, connection.token); | |
| } | |
| return Promise.reject(new Error('No token available')); | |
| }, | |
| }; | |
| } | |