mirror of
https://github.com/stackblitz-labs/bolt.diy
synced 2025-06-26 18:26:38 +00:00
- Move stores/utils/types to their relative directories (i.e chat stores in chat directory) - Move utility files to shared/utils - Move component files to shared/components - Move type definitions to shared/types - Move stores to shared/stores - Update import paths across the project
148 lines
4.1 KiB
TypeScript
148 lines
4.1 KiB
TypeScript
import { useEffect, useState } from 'react';
|
|
import { toast } from 'react-toastify';
|
|
import { useStore } from '@nanostores/react';
|
|
import { logStore } from '~/shared/stores/logs';
|
|
import {
|
|
supabaseConnection,
|
|
isConnecting,
|
|
isFetchingStats,
|
|
isFetchingApiKeys,
|
|
updateSupabaseConnection,
|
|
fetchProjectApiKeys,
|
|
} from '~/shared/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'));
|
|
},
|
|
};
|
|
}
|