bolt.diy/app/lib/persistence/apps.ts
2025-04-27 12:03:25 -07:00

109 lines
2.8 KiB
TypeScript

// Functions for accessing the apps table in the database
import { getSupabase } from '~/lib/supabase/client';
import type { Message } from './message';
export interface BuildAppOutcome {
testsPassed?: boolean;
hasDatabase?: boolean;
}
export interface BuildAppResult {
id: string;
title: string | undefined;
elapsedMinutes: number;
totalPeanuts: number;
imageDataURL: string | undefined;
messages: Message[];
protocolChatId: string;
outcome: BuildAppOutcome;
appId: string;
createdAt: string;
}
function parseBuildAppOutcome(outcome: string): BuildAppOutcome {
try {
const json = JSON.parse(outcome);
return {
testsPassed: !!json.testsPassed,
hasDatabase: !!json.hasDatabase,
};
} catch (error) {
// 2025/04/26: Watch for old formats for outcomes.
if (outcome === 'success') {
return {
testsPassed: true,
};
}
if (outcome === 'error') {
return {
testsPassed: false,
};
}
console.error('Failed to parse outcome:', error);
return {};
}
}
function databaseRowToBuildAppResult(row: any): BuildAppResult {
// Determine the outcome based on the result field
const outcome = parseBuildAppOutcome(row.outcome);
return {
id: row.id,
title: row.title,
elapsedMinutes: row.elapsed_minutes || 0,
totalPeanuts: row.total_peanuts || 0,
imageDataURL: row.image_url,
messages: row.messages || [],
protocolChatId: row.protocol_chat_id,
outcome,
appId: row.app_id,
createdAt: row.created_at,
};
}
/**
* Get all apps created within the last X hours
* @param hours Number of hours to look back
* @returns Array of BuildAppResult objects
*/
async function getAppsCreatedInLastXHours(hours: number): Promise<BuildAppResult[]> {
try {
// Calculate the timestamp for X hours ago
const hoursAgo = new Date();
hoursAgo.setHours(hoursAgo.getHours() - hours);
const { data, error } = await getSupabase()
.from('apps')
.select('*')
.eq('deleted', false)
.gte('created_at', hoursAgo.toISOString())
.order('created_at', { ascending: false });
if (error) {
console.error('Error fetching recent apps:', error);
throw error;
}
// Ignore apps that don't have a title or image.
return data.map(databaseRowToBuildAppResult).filter((app) => app.title && app.imageDataURL);
} catch (error) {
console.error('Failed to get recent apps:', error);
throw error;
}
}
const HOUR_RANGES = [1, 2, 3, 6, 12, 24];
export async function getRecentApps(numApps: number): Promise<BuildAppResult[]> {
let apps: BuildAppResult[] = [];
for (const range of HOUR_RANGES) {
apps = await getAppsCreatedInLastXHours(range);
if (apps.length >= numApps) {
return apps.slice(0, numApps);
}
}
return apps;
}