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
95 lines
2.9 KiB
TypeScript
95 lines
2.9 KiB
TypeScript
import { atom } from 'nanostores';
|
|
import type { VercelConnection } from '~/shared/types/vercel';
|
|
import { logStore } from './logs';
|
|
import { toast } from 'react-toastify';
|
|
|
|
// Initialize with stored connection or defaults
|
|
const storedConnection = typeof window !== 'undefined' ? localStorage.getItem('vercel_connection') : null;
|
|
const initialConnection: VercelConnection = storedConnection
|
|
? JSON.parse(storedConnection)
|
|
: {
|
|
user: null,
|
|
token: '',
|
|
stats: undefined,
|
|
};
|
|
|
|
export const vercelConnection = atom<VercelConnection>(initialConnection);
|
|
export const isConnecting = atom<boolean>(false);
|
|
export const isFetchingStats = atom<boolean>(false);
|
|
|
|
export const updateVercelConnection = (updates: Partial<VercelConnection>) => {
|
|
const currentState = vercelConnection.get();
|
|
const newState = { ...currentState, ...updates };
|
|
vercelConnection.set(newState);
|
|
|
|
// Persist to localStorage
|
|
if (typeof window !== 'undefined') {
|
|
localStorage.setItem('vercel_connection', JSON.stringify(newState));
|
|
}
|
|
};
|
|
|
|
export async function fetchVercelStats(token: string) {
|
|
try {
|
|
isFetchingStats.set(true);
|
|
|
|
const projectsResponse = await fetch('https://api.vercel.com/v9/projects', {
|
|
headers: {
|
|
Authorization: `Bearer ${token}`,
|
|
'Content-Type': 'application/json',
|
|
},
|
|
});
|
|
|
|
if (!projectsResponse.ok) {
|
|
throw new Error(`Failed to fetch projects: ${projectsResponse.status}`);
|
|
}
|
|
|
|
const projectsData = (await projectsResponse.json()) as any;
|
|
const projects = projectsData.projects || [];
|
|
|
|
// Fetch latest deployment for each project
|
|
const projectsWithDeployments = await Promise.all(
|
|
projects.map(async (project: any) => {
|
|
try {
|
|
const deploymentsResponse = await fetch(
|
|
`https://api.vercel.com/v6/deployments?projectId=${project.id}&limit=1`,
|
|
{
|
|
headers: {
|
|
Authorization: `Bearer ${token}`,
|
|
'Content-Type': 'application/json',
|
|
},
|
|
},
|
|
);
|
|
|
|
if (deploymentsResponse.ok) {
|
|
const deploymentsData = (await deploymentsResponse.json()) as any;
|
|
return {
|
|
...project,
|
|
latestDeployments: deploymentsData.deployments || [],
|
|
};
|
|
}
|
|
|
|
return project;
|
|
} catch (error) {
|
|
console.error(`Error fetching deployments for project ${project.id}:`, error);
|
|
return project;
|
|
}
|
|
}),
|
|
);
|
|
|
|
const currentState = vercelConnection.get();
|
|
updateVercelConnection({
|
|
...currentState,
|
|
stats: {
|
|
projects: projectsWithDeployments,
|
|
totalProjects: projectsWithDeployments.length,
|
|
},
|
|
});
|
|
} catch (error) {
|
|
console.error('Vercel API Error:', error);
|
|
logStore.logError('Failed to fetch Vercel stats', { error });
|
|
toast.error('Failed to fetch Vercel statistics');
|
|
} finally {
|
|
isFetchingStats.set(false);
|
|
}
|
|
}
|