From 38367daebea197f2949042b4067250f30af88e84 Mon Sep 17 00:00:00 2001 From: "Builder.io" Date: Sat, 27 Sep 2025 21:57:41 +0000 Subject: [PATCH] Make project service resilient with timeout and localStorage fallback cgen-0a88274abfc64dc5b2fc449daf876ffe --- client/lib/aethex-database-adapter.ts | 134 +++++++++++++++++++------- 1 file changed, 97 insertions(+), 37 deletions(-) diff --git a/client/lib/aethex-database-adapter.ts b/client/lib/aethex-database-adapter.ts index e482632e..188c8cdd 100644 --- a/client/lib/aethex-database-adapter.ts +++ b/client/lib/aethex-database-adapter.ts @@ -243,68 +243,128 @@ export const aethexUserService = { // Project Services export const aethexProjectService = { async getUserProjects(userId: string): Promise { - const { data, error } = await supabase - .from("projects") - .select("*") - .eq("user_id", userId) - .order("created_at", { ascending: false }); + try { + const { data, error } = await supabase + .from("projects") + .select("*") + .eq("user_id", userId) + .order("created_at", { ascending: false }); - if (error) { - console.warn("Error fetching projects:", error); - return []; + if (!error && Array.isArray(data)) { + return data as AethexProject[]; + } + + if (error) console.warn("Error fetching projects:", error); + } catch (err) { + console.warn("Exception fetching projects, using local fallback:", err); } - return data as AethexProject[]; + try { + const raw = localStorage.getItem("mock_projects"); + const all = raw ? (JSON.parse(raw) as AethexProject[]) : []; + return all.filter((p) => p.user_id === userId).sort((a, b) => (b.created_at || "").localeCompare(a.created_at || "")); + } catch { + return []; + } }, async createProject( project: Omit, ): Promise { - const { data, error } = await supabase - .from("projects") - .insert(project) - .select() - .single(); + try { + const supabasePromise = supabase + .from("projects") + .insert(project) + .select() + .single(); - if (error) { - console.warn("Error creating project:", error); - throw error; + const timeout = new Promise((resolve) => + setTimeout(() => resolve({ data: null, error: new Error("timeout") }), 6000) + ); + + const { data, error } = await (Promise.race([supabasePromise as any, timeout]) as Promise); + + if (!error && data) { + return data as AethexProject; + } + + if (error) console.warn("Create project failed or timed out, using local fallback:", error?.message || error); + } catch (err: any) { + console.warn("Create project exception, using local fallback:", err?.message || err); } - return data as AethexProject; + const now = new Date().toISOString(); + const localProject: AethexProject = { + ...(project as any), + id: `local_${Date.now()}_${Math.random().toString(36).slice(2)}`, + created_at: now, + updated_at: now, + } as AethexProject; + + try { + const raw = localStorage.getItem("mock_projects"); + const list: AethexProject[] = raw ? JSON.parse(raw) : []; + list.unshift(localProject); + localStorage.setItem("mock_projects", JSON.stringify(list)); + } catch {} + + return localProject; }, async updateProject( projectId: string, updates: Partial, ): Promise { - const { data, error } = await supabase - .from("projects") - .update(updates) - .eq("id", projectId) - .select() - .single(); + try { + const { data, error } = await supabase + .from("projects") + .update(updates) + .eq("id", projectId) + .select() + .single(); - if (error) { - console.warn("Error updating project:", error); - throw error; + if (!error && data) return data as AethexProject; + if (error) console.warn("Error updating project:", error); + } catch (err) { + console.warn("Exception updating project, using local fallback:", err); } - return data as AethexProject; + try { + const raw = localStorage.getItem("mock_projects"); + const list: AethexProject[] = raw ? JSON.parse(raw) : []; + const idx = list.findIndex((p) => (p as any).id === projectId); + if (idx >= 0) { + const updated = { ...list[idx], ...updates, updated_at: new Date().toISOString() } as AethexProject; + list[idx] = updated; + localStorage.setItem("mock_projects", JSON.stringify(list)); + return updated; + } + } catch {} + + return null; }, async deleteProject(projectId: string): Promise { - const { error } = await supabase - .from("projects") - .delete() - .eq("id", projectId); - - if (error) { - console.warn("Error deleting project:", error); - return false; + try { + const { error } = await supabase + .from("projects") + .delete() + .eq("id", projectId); + if (!error) return true; + if (error) console.warn("Error deleting project:", error); + } catch (err) { + console.warn("Exception deleting project, using local fallback:", err); } - return true; + try { + const raw = localStorage.getItem("mock_projects"); + const list: AethexProject[] = raw ? JSON.parse(raw) : []; + const next = list.filter((p) => (p as any).id !== projectId); + localStorage.setItem("mock_projects", JSON.stringify(next)); + return true; + } catch {} + + return false; }, async getAllProjects(limit = 10): Promise {