diff --git a/modules/rflows/components/folk-flows-app.ts b/modules/rflows/components/folk-flows-app.ts index aafe7fb..144ceed 100644 --- a/modules/rflows/components/folk-flows-app.ts +++ b/modules/rflows/components/folk-flows-app.ts @@ -3873,7 +3873,9 @@ class FolkFlowsApp extends HTMLElement { if (!res.ok) { const err = await res.json().catch(() => ({ error: "Unknown error" })); - alert(`On-ramp failed: ${err.error || res.statusText}`); + const msg = typeof err.error === 'string' ? err.error : JSON.stringify(err.error) || res.statusText; + console.error("[UserOnRamp] Server error:", res.status, err); + alert(`On-ramp failed: ${msg}`); return; } @@ -3894,8 +3896,9 @@ class FolkFlowsApp extends HTMLElement { // Open on-ramp widget this.openWidgetModal(data.widgetUrl); } catch (err) { - console.error("[UserOnRamp] Error:", err); - alert("Failed to start on-ramp. Check console for details."); + const msg = err instanceof Error ? err.message : String(err); + console.error("[UserOnRamp] Error:", msg, err); + alert(`On-ramp failed: ${msg}`); } } @@ -3926,7 +3929,9 @@ class FolkFlowsApp extends HTMLElement { if (!res.ok) { const err = await res.json().catch(() => ({ error: "Unknown error" })); - alert(`On-ramp failed: ${err.error || res.statusText}`); + const msg = typeof err.error === 'string' ? err.error : JSON.stringify(err.error) || res.statusText; + console.error("[QuickFund] Server error:", res.status, err); + alert(`On-ramp failed: ${msg}`); return; } diff --git a/server/notification-routes.ts b/server/notification-routes.ts index a71c904..5664767 100644 --- a/server/notification-routes.ts +++ b/server/notification-routes.ts @@ -34,32 +34,42 @@ async function requireAuth(req: Request) { // ── GET / — Paginated notification list ── notificationRouter.get("/", async (c) => { - const claims = await requireAuth(c.req.raw); - if (!claims) return c.json({ error: "Authentication required" }, 401); + try { + const claims = await requireAuth(c.req.raw); + if (!claims) return c.json({ error: "Authentication required" }, 401); - const url = new URL(c.req.url); - const unreadOnly = url.searchParams.get("unread") === "true"; - const category = url.searchParams.get("category") || undefined; - const limit = Math.min(Number(url.searchParams.get("limit")) || 50, 100); - const offset = Number(url.searchParams.get("offset")) || 0; + const url = new URL(c.req.url); + const unreadOnly = url.searchParams.get("unread") === "true"; + const category = url.searchParams.get("category") || undefined; + const limit = Math.min(Number(url.searchParams.get("limit")) || 50, 100); + const offset = Number(url.searchParams.get("offset")) || 0; - const notifications = await getUserNotifications(claims.sub, { - unreadOnly, - category, - limit, - offset, - }); + const notifications = await getUserNotifications(claims.sub, { + unreadOnly, + category, + limit, + offset, + }); - return c.json({ notifications }); + return c.json({ notifications }); + } catch (err) { + console.error("[notifications] GET / failed:", err instanceof Error ? err.message : err); + return c.json({ notifications: [] }); + } }); // ── GET /count — Lightweight unread count (polling fallback) ── notificationRouter.get("/count", async (c) => { - const claims = await requireAuth(c.req.raw); - if (!claims) return c.json({ error: "Authentication required" }, 401); + try { + const claims = await requireAuth(c.req.raw); + if (!claims) return c.json({ error: "Authentication required" }, 401); - const count = await getUnreadCount(claims.sub); - return c.json({ unreadCount: count }); + const count = await getUnreadCount(claims.sub); + return c.json({ unreadCount: count }); + } catch (err) { + console.error("[notifications] GET /count failed:", err instanceof Error ? err.message : err); + return c.json({ unreadCount: 0 }); + } }); // ── PATCH /:id/read — Mark one notification as read ── diff --git a/src/encryptid/db.ts b/src/encryptid/db.ts index 725a6aa..15b3fa3 100644 --- a/src/encryptid/db.ts +++ b/src/encryptid/db.ts @@ -1156,11 +1156,16 @@ export async function getUserNotifications( } export async function getUnreadCount(userDid: string): Promise { - const [row] = await sql` - SELECT COUNT(*)::int as count FROM notifications - WHERE user_did = ${userDid} AND NOT read AND NOT dismissed - `; - return row.count; + try { + const [row] = await sql` + SELECT COUNT(*)::int as count FROM notifications + WHERE user_did = ${userDid} AND NOT read AND NOT dismissed + `; + return row?.count ?? 0; + } catch (err) { + console.error("[notifications] getUnreadCount failed:", err instanceof Error ? err.message : err); + return 0; + } } export async function markNotificationRead(id: string, userDid: string): Promise { diff --git a/website/sw.ts b/website/sw.ts index c5fdc1e..2416eed 100644 --- a/website/sw.ts +++ b/website/sw.ts @@ -133,7 +133,7 @@ self.addEventListener("fetch", (event) => { statusText: response.statusText, headers, }); - cache.put(event.request, timedResponse); + cache.put(event.request, timedResponse).catch(() => {}); } return response; }) @@ -171,7 +171,7 @@ self.addEventListener("fetch", (event) => { return fetch(event.request).then((response) => { if (response.ok) { const clone = response.clone(); - caches.open(STATIC_CACHE).then((cache) => cache.put(event.request, clone)); + caches.open(STATIC_CACHE).then((cache) => cache.put(event.request, clone).catch(() => {})); } return response; }); @@ -190,7 +190,7 @@ self.addEventListener("fetch", (event) => { .then((response) => { if (response.ok) { const clone = response.clone(); - caches.open(HTML_CACHE).then((cache) => cache.put(event.request, clone)); + caches.open(HTML_CACHE).then((cache) => cache.put(event.request, clone).catch(() => {})); } return response; }) @@ -210,7 +210,7 @@ self.addEventListener("fetch", (event) => { .then((response) => { if (response.ok) { const clone = response.clone(); - caches.open(STATIC_CACHE).then((cache) => cache.put(event.request, clone)); + caches.open(STATIC_CACHE).then((cache) => cache.put(event.request, clone).catch(() => {})); } return response; })