diff --git a/src/app/api/daily-note/route.ts b/src/app/api/daily-note/route.ts index 398b4e6b5..86919d1d1 100644 --- a/src/app/api/daily-note/route.ts +++ b/src/app/api/daily-note/route.ts @@ -22,20 +22,36 @@ export async function GET(req: NextRequest) { yesterday.setDate(yesterday.getDate() - 1); const yesterdayDate = yesterday.toISOString().split("T")[0]; - const { data: todayData } = await supabaseAdmin + const { data: todayData, error: todayError } = await supabaseAdmin .from("daily_notes") .select("*") .eq("user_id", userId) .eq("date", todayDate) .single(); - const { data: yesterdayData } = await supabaseAdmin + if (todayError && todayError.code !== "PGRST116") { + console.error("Failed to fetch today's daily note:", todayError); + return NextResponse.json( + { error: "Failed to fetch daily notes" }, + { status: 500 } + ); + } + + const { data: yesterdayData, error: yesterdayError } = await supabaseAdmin .from("daily_notes") .select("*") .eq("user_id", userId) .eq("date", yesterdayDate) .single(); + if (yesterdayError && yesterdayError.code !== "PGRST116") { + console.error("Failed to fetch yesterday's daily note:", yesterdayError); + return NextResponse.json( + { error: "Failed to fetch daily notes" }, + { status: 500 } + ); + } + return NextResponse.json({ todayNote: todayData?.note || "", yesterdayNote: yesterdayData?.note || "", diff --git a/src/app/api/goals/route.ts b/src/app/api/goals/route.ts index fe37c2a5c..a885507e8 100644 --- a/src/app/api/goals/route.ts +++ b/src/app/api/goals/route.ts @@ -71,13 +71,18 @@ export async function GET() { if (!user) return Response.json({ error: "User not found" }, { status: 404 }); // Added .limit() to bound the database payload and the subsequent Promise.all loop - const { data: goals } = await supabaseAdmin + const { data: goals, error } = await supabaseAdmin .from("goals") .select("*") .eq("user_id", user.id) .order("created_at", { ascending: false }) .limit(MAX_GOALS_PER_USER); + if (error) { + console.error("Failed to fetch goals:", error); + return Response.json({ error: "Failed to fetch goals" }, { status: 500 }); + } + // Reset progress if we're in a new period const processedGoals = await Promise.all( (goals ?? []).map(async (goal: Goal) => { diff --git a/src/app/api/integrations/jira/credentials/route.ts b/src/app/api/integrations/jira/credentials/route.ts index 821dbba3c..84c945561 100644 --- a/src/app/api/integrations/jira/credentials/route.ts +++ b/src/app/api/integrations/jira/credentials/route.ts @@ -59,12 +59,20 @@ export async function GET(req: NextRequest) { const result = await requireUser(); if ("error" in result) return result.error; - const { data: credentials } = await supabaseAdmin + const { data: credentials, error } = await supabaseAdmin .from("jira_credentials") .select("id, jira_domain, email, project_key, is_active, created_at") .eq("user_id", result.user.id); - return Response.json({ credentials: credentials || [] }); + if (error) { + console.error("Failed to fetch Jira credentials:", error); + return Response.json( + { error: "Failed to fetch Jira credentials" }, + { status: 500 } + ); + } + + return Response.json({ credentials: credentials ?? [] }); } export async function POST(req: NextRequest) { diff --git a/src/app/api/local-coding/keys/route.ts b/src/app/api/local-coding/keys/route.ts index 23f4a0be5..7a8b9c7d6 100644 --- a/src/app/api/local-coding/keys/route.ts +++ b/src/app/api/local-coding/keys/route.ts @@ -22,13 +22,21 @@ export async function GET() { const user = await resolveAppUser(session.githubId, session.githubLogin); if (!user) return Response.json({ error: "User not found" }, { status: 404 }); - const { data: keys } = await supabaseAdmin + const { data: keys, error } = await supabaseAdmin .from("local_coding_api_keys") .select("id, name, last_used_at, created_at") .eq("user_id", user.id) .order("created_at", { ascending: false }); - return Response.json({ keys: keys || [] }); + if (error) { + console.error("Failed to fetch local coding API keys:", error); + return Response.json( + { error: "Failed to fetch API keys" }, + { status: 500 } + ); + } + + return Response.json({ keys: keys ?? [] }); } export async function POST(req: NextRequest) { diff --git a/src/app/api/local-coding/stats/route.ts b/src/app/api/local-coding/stats/route.ts index c1e5cd4ec..be722998f 100644 --- a/src/app/api/local-coding/stats/route.ts +++ b/src/app/api/local-coding/stats/route.ts @@ -40,12 +40,11 @@ export async function GET(req: NextRequest) { .order("date", { ascending: false }); if (error) { - // Table may not exist in all deployments — degrade gracefully - return Response.json({ - dailyData: [], - totals: { totalSeconds: 0, totalDays: 0, avgSecondsPerDay: 0 }, - hasData: false, - }); + console.error("Failed to fetch local coding stats:", error); + return Response.json( + { error: "Failed to fetch local coding stats" }, + { status: 500 } + ); } if (!sessions || sessions.length === 0) { diff --git a/src/app/api/local-coding/sync/route.ts b/src/app/api/local-coding/sync/route.ts index af0184470..f8db005ce 100644 --- a/src/app/api/local-coding/sync/route.ts +++ b/src/app/api/local-coding/sync/route.ts @@ -239,12 +239,20 @@ export async function GET(req: NextRequest) { fromDate.setDate(fromDate.getDate() - days); const fromDateStr = fromDate.toISOString().slice(0, 10); - const { data: sessions } = await supabaseAdmin + const { data: sessions, error } = await supabaseAdmin .from("local_coding_sessions") .select("*") .eq("user_id", userId) .gte("date", fromDateStr) .order("date", { ascending: false }); - return Response.json({ sessions: sessions || [] }); + if (error) { + console.error("Failed to fetch local coding sessions:", error); + return Response.json( + { error: "Failed to fetch sessions" }, + { status: 500 } + ); + } + + return Response.json({ sessions: sessions ?? [] }); } diff --git a/src/app/api/notifications/route.ts b/src/app/api/notifications/route.ts index 025fb422a..a19c5240c 100644 --- a/src/app/api/notifications/route.ts +++ b/src/app/api/notifications/route.ts @@ -54,8 +54,11 @@ export async function GET() { .limit(10); if (error) { - // Table may not exist in all deployments — degrade gracefully - return NextResponse.json({ notifications: [], unreadCount: 0 }); + console.error("Failed to fetch notifications:", error); + return NextResponse.json( + { error: "Failed to fetch notifications" }, + { status: 500 } + ); } const unreadCount = (data ?? []).filter((n) => !n.read).length; @@ -92,8 +95,11 @@ export async function PATCH() { .eq("read", false); if (error) { - // Table may not exist — degrade gracefully - return NextResponse.json({ success: true }); + console.error("Failed to mark notifications as read:", error); + return NextResponse.json( + { error: "Failed to update notifications" }, + { status: 500 } + ); } return NextResponse.json({ success: true }); diff --git a/src/app/api/user/github-accounts/route.ts b/src/app/api/user/github-accounts/route.ts index 87d2d1af9..74846346c 100644 --- a/src/app/api/user/github-accounts/route.ts +++ b/src/app/api/user/github-accounts/route.ts @@ -38,8 +38,11 @@ export async function GET() { .order("added_at", { ascending: true }); if (error) { - // Table may not exist in all deployments — return empty accounts - return NextResponse.json({ accounts: [] }); + console.error("Failed to fetch linked GitHub accounts:", error); + return NextResponse.json( + { error: "Failed to fetch accounts" }, + { status: 500 } + ); } return NextResponse.json({ diff --git a/src/app/api/user/pinned-repos/details/route.ts b/src/app/api/user/pinned-repos/details/route.ts index af76a4a54..68fba5baa 100644 --- a/src/app/api/user/pinned-repos/details/route.ts +++ b/src/app/api/user/pinned-repos/details/route.ts @@ -19,7 +19,18 @@ export async function GET() { .eq("github_id", session.githubId) .single(); - if (error || !userRow) { + if (error) { + if (error.code === "PGRST116") { + return Response.json({ pinnedRepos: [] }); + } + console.error("Failed to fetch pinned repos from database:", error); + return Response.json( + { error: "Failed to load pinned repositories" }, + { status: 500 } + ); + } + + if (!userRow) { return Response.json({ pinnedRepos: [] }); } diff --git a/src/app/api/wakatime/route.ts b/src/app/api/wakatime/route.ts index 32bb8f9b3..8f6cf310b 100644 --- a/src/app/api/wakatime/route.ts +++ b/src/app/api/wakatime/route.ts @@ -13,12 +13,23 @@ export async function GET() { } try { - const { data: user } = await supabaseAdmin + const { data: user, error: userError } = await supabaseAdmin .from("users") .select("id, wakatime_api_key_encrypted") .eq("github_id", session.githubId) .single(); + if (userError) { + if (userError.code === "PGRST116") { + return NextResponse.json({ hasData: false, not_configured: true }); + } + console.error("Failed to fetch user for Wakatime stats:", userError); + return NextResponse.json( + { error: "Failed to fetch Wakatime stats" }, + { status: 500 } + ); + } + if (!user) { return NextResponse.json({ hasData: false, not_configured: true }); } @@ -31,14 +42,22 @@ export async function GET() { date7DaysAgo.setDate(date7DaysAgo.getDate() - 7); const dateStr = date7DaysAgo.toISOString().split("T")[0]; - const { data: stats, error } = await supabaseAdmin + const { data: stats, error: statsError } = await supabaseAdmin .from("wakatime_stats") .select("*") .eq("user_id", user.id) .gte("date", dateStr) .order("date", { ascending: true }); - if (error || !stats || stats.length === 0) { + if (statsError) { + console.error("Failed to fetch Wakatime stats:", statsError); + return NextResponse.json( + { error: "Failed to fetch Wakatime stats" }, + { status: 500 } + ); + } + + if (!stats || stats.length === 0) { return NextResponse.json({ hasData: false }); } @@ -78,7 +97,11 @@ export async function GET() { topLanguage: getTop(languagesMap), topProject: getTop(projectsMap), }); - } catch { - return NextResponse.json({ hasData: false }); + } catch (err) { + console.error("Unexpected error in Wakatime GET:", err); + return NextResponse.json( + { error: "Failed to fetch Wakatime stats" }, + { status: 500 } + ); } } diff --git a/src/app/api/webhooks/custom/route.ts b/src/app/api/webhooks/custom/route.ts index a7cc1dcc4..6acb2bb61 100644 --- a/src/app/api/webhooks/custom/route.ts +++ b/src/app/api/webhooks/custom/route.ts @@ -36,13 +36,21 @@ export async function GET(req: NextRequest) { const result = await requireUser(); if ("error" in result) return result.error; - const { data: webhooks } = await supabaseAdmin + const { data: webhooks, error } = await supabaseAdmin .from("webhook_configs") .select("id, name, url, events, is_enabled, created_at, updated_at") .eq("user_id", result.user.id) .order("created_at", { ascending: false }); - return Response.json({ webhooks: webhooks || [] }); + if (error) { + console.error("Failed to fetch webhooks:", error); + return Response.json( + { error: "Failed to fetch webhooks" }, + { status: 500 } + ); + } + + return Response.json({ webhooks: webhooks ?? [] }); } export async function POST(req: NextRequest) {