Skip to content

Commit ab39f1a

Browse files
authored
Merge branch 'main' into feat/issue-1933-rbac
2 parents ce67fae + e4ff79b commit ab39f1a

12 files changed

Lines changed: 145 additions & 39 deletions

File tree

src/app/api/daily-note/route.ts

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,20 +22,36 @@ export async function GET(req: NextRequest) {
2222
yesterday.setDate(yesterday.getDate() - 1);
2323
const yesterdayDate = yesterday.toISOString().split("T")[0];
2424

25-
const { data: todayData } = await supabaseAdmin
25+
const { data: todayData, error: todayError } = await supabaseAdmin
2626
.from("daily_notes")
2727
.select("*")
2828
.eq("user_id", userId)
2929
.eq("date", todayDate)
3030
.single();
3131

32-
const { data: yesterdayData } = await supabaseAdmin
32+
if (todayError && todayError.code !== "PGRST116") {
33+
console.error("Failed to fetch today's daily note:", todayError);
34+
return NextResponse.json(
35+
{ error: "Failed to fetch daily notes" },
36+
{ status: 500 }
37+
);
38+
}
39+
40+
const { data: yesterdayData, error: yesterdayError } = await supabaseAdmin
3341
.from("daily_notes")
3442
.select("*")
3543
.eq("user_id", userId)
3644
.eq("date", yesterdayDate)
3745
.single();
3846

47+
if (yesterdayError && yesterdayError.code !== "PGRST116") {
48+
console.error("Failed to fetch yesterday's daily note:", yesterdayError);
49+
return NextResponse.json(
50+
{ error: "Failed to fetch daily notes" },
51+
{ status: 500 }
52+
);
53+
}
54+
3955
return NextResponse.json({
4056
todayNote: todayData?.note || "",
4157
yesterdayNote: yesterdayData?.note || "",

src/app/api/goals/route.ts

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -71,13 +71,18 @@ export async function GET() {
7171
if (!user) return Response.json({ error: "User not found" }, { status: 404 });
7272

7373
// Added .limit() to bound the database payload and the subsequent Promise.all loop
74-
const { data: goals } = await supabaseAdmin
74+
const { data: goals, error } = await supabaseAdmin
7575
.from("goals")
7676
.select("*")
7777
.eq("user_id", user.id)
7878
.order("created_at", { ascending: false })
7979
.limit(MAX_GOALS_PER_USER);
8080

81+
if (error) {
82+
console.error("Failed to fetch goals:", error);
83+
return Response.json({ error: "Failed to fetch goals" }, { status: 500 });
84+
}
85+
8186
// Reset progress if we're in a new period
8287
const processedGoals = await Promise.all(
8388
(goals ?? []).map(async (goal: Goal) => {

src/app/api/integrations/jira/credentials/route.ts

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -59,12 +59,20 @@ export async function GET(req: NextRequest) {
5959
const result = await requireUser();
6060
if ("error" in result) return result.error;
6161

62-
const { data: credentials } = await supabaseAdmin
62+
const { data: credentials, error } = await supabaseAdmin
6363
.from("jira_credentials")
6464
.select("id, jira_domain, email, project_key, is_active, created_at")
6565
.eq("user_id", result.user.id);
6666

67-
return Response.json({ credentials: credentials || [] });
67+
if (error) {
68+
console.error("Failed to fetch Jira credentials:", error);
69+
return Response.json(
70+
{ error: "Failed to fetch Jira credentials" },
71+
{ status: 500 }
72+
);
73+
}
74+
75+
return Response.json({ credentials: credentials ?? [] });
6876
}
6977

7078
export async function POST(req: NextRequest) {

src/app/api/local-coding/keys/route.ts

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,13 +22,21 @@ export async function GET() {
2222
const user = await resolveAppUser(session.githubId, session.githubLogin);
2323
if (!user) return Response.json({ error: "User not found" }, { status: 404 });
2424

25-
const { data: keys } = await supabaseAdmin
25+
const { data: keys, error } = await supabaseAdmin
2626
.from("local_coding_api_keys")
2727
.select("id, name, last_used_at, created_at")
2828
.eq("user_id", user.id)
2929
.order("created_at", { ascending: false });
3030

31-
return Response.json({ keys: keys || [] });
31+
if (error) {
32+
console.error("Failed to fetch local coding API keys:", error);
33+
return Response.json(
34+
{ error: "Failed to fetch API keys" },
35+
{ status: 500 }
36+
);
37+
}
38+
39+
return Response.json({ keys: keys ?? [] });
3240
}
3341

3442
export async function POST(req: NextRequest) {

src/app/api/local-coding/stats/route.ts

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -40,12 +40,11 @@ export async function GET(req: NextRequest) {
4040
.order("date", { ascending: false });
4141

4242
if (error) {
43-
// Table may not exist in all deployments — degrade gracefully
44-
return Response.json({
45-
dailyData: [],
46-
totals: { totalSeconds: 0, totalDays: 0, avgSecondsPerDay: 0 },
47-
hasData: false,
48-
});
43+
console.error("Failed to fetch local coding stats:", error);
44+
return Response.json(
45+
{ error: "Failed to fetch local coding stats" },
46+
{ status: 500 }
47+
);
4948
}
5049

5150
if (!sessions || sessions.length === 0) {

src/app/api/local-coding/sync/route.ts

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -239,12 +239,20 @@ export async function GET(req: NextRequest) {
239239
fromDate.setDate(fromDate.getDate() - days);
240240
const fromDateStr = fromDate.toISOString().slice(0, 10);
241241

242-
const { data: sessions } = await supabaseAdmin
242+
const { data: sessions, error } = await supabaseAdmin
243243
.from("local_coding_sessions")
244244
.select("*")
245245
.eq("user_id", userId)
246246
.gte("date", fromDateStr)
247247
.order("date", { ascending: false });
248248

249-
return Response.json({ sessions: sessions || [] });
249+
if (error) {
250+
console.error("Failed to fetch local coding sessions:", error);
251+
return Response.json(
252+
{ error: "Failed to fetch sessions" },
253+
{ status: 500 }
254+
);
255+
}
256+
257+
return Response.json({ sessions: sessions ?? [] });
250258
}

src/app/api/notifications/route.ts

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -54,8 +54,11 @@ export async function GET() {
5454
.limit(10);
5555

5656
if (error) {
57-
// Table may not exist in all deployments — degrade gracefully
58-
return NextResponse.json({ notifications: [], unreadCount: 0 });
57+
console.error("Failed to fetch notifications:", error);
58+
return NextResponse.json(
59+
{ error: "Failed to fetch notifications" },
60+
{ status: 500 }
61+
);
5962
}
6063

6164
const unreadCount = (data ?? []).filter((n) => !n.read).length;
@@ -92,8 +95,11 @@ export async function PATCH() {
9295
.eq("read", false);
9396

9497
if (error) {
95-
// Table may not exist — degrade gracefully
96-
return NextResponse.json({ success: true });
98+
console.error("Failed to mark notifications as read:", error);
99+
return NextResponse.json(
100+
{ error: "Failed to update notifications" },
101+
{ status: 500 }
102+
);
97103
}
98104

99105
return NextResponse.json({ success: true });

src/app/api/user/github-accounts/route.ts

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -38,8 +38,11 @@ export async function GET() {
3838
.order("added_at", { ascending: true });
3939

4040
if (error) {
41-
// Table may not exist in all deployments — return empty accounts
42-
return NextResponse.json({ accounts: [] });
41+
console.error("Failed to fetch linked GitHub accounts:", error);
42+
return NextResponse.json(
43+
{ error: "Failed to fetch accounts" },
44+
{ status: 500 }
45+
);
4346
}
4447

4548
return NextResponse.json({

src/app/api/user/pinned-repos/details/route.ts

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,18 @@ export async function GET() {
1919
.eq("github_id", session.githubId)
2020
.single();
2121

22-
if (error || !userRow) {
22+
if (error) {
23+
if (error.code === "PGRST116") {
24+
return Response.json({ pinnedRepos: [] });
25+
}
26+
console.error("Failed to fetch pinned repos from database:", error);
27+
return Response.json(
28+
{ error: "Failed to load pinned repositories" },
29+
{ status: 500 }
30+
);
31+
}
32+
33+
if (!userRow) {
2334
return Response.json({ pinnedRepos: [] });
2435
}
2536

src/app/api/wakatime/route.ts

Lines changed: 28 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -13,12 +13,23 @@ export async function GET() {
1313
}
1414

1515
try {
16-
const { data: user } = await supabaseAdmin
16+
const { data: user, error: userError } = await supabaseAdmin
1717
.from("users")
1818
.select("id, wakatime_api_key_encrypted")
1919
.eq("github_id", session.githubId)
2020
.single();
2121

22+
if (userError) {
23+
if (userError.code === "PGRST116") {
24+
return NextResponse.json({ hasData: false, not_configured: true });
25+
}
26+
console.error("Failed to fetch user for Wakatime stats:", userError);
27+
return NextResponse.json(
28+
{ error: "Failed to fetch Wakatime stats" },
29+
{ status: 500 }
30+
);
31+
}
32+
2233
if (!user) {
2334
return NextResponse.json({ hasData: false, not_configured: true });
2435
}
@@ -31,14 +42,22 @@ export async function GET() {
3142
date7DaysAgo.setDate(date7DaysAgo.getDate() - 7);
3243
const dateStr = date7DaysAgo.toISOString().split("T")[0];
3344

34-
const { data: stats, error } = await supabaseAdmin
45+
const { data: stats, error: statsError } = await supabaseAdmin
3546
.from("wakatime_stats")
3647
.select("*")
3748
.eq("user_id", user.id)
3849
.gte("date", dateStr)
3950
.order("date", { ascending: true });
4051

41-
if (error || !stats || stats.length === 0) {
52+
if (statsError) {
53+
console.error("Failed to fetch Wakatime stats:", statsError);
54+
return NextResponse.json(
55+
{ error: "Failed to fetch Wakatime stats" },
56+
{ status: 500 }
57+
);
58+
}
59+
60+
if (!stats || stats.length === 0) {
4261
return NextResponse.json({ hasData: false });
4362
}
4463

@@ -78,7 +97,11 @@ export async function GET() {
7897
topLanguage: getTop(languagesMap),
7998
topProject: getTop(projectsMap),
8099
});
81-
} catch {
82-
return NextResponse.json({ hasData: false });
100+
} catch (err) {
101+
console.error("Unexpected error in Wakatime GET:", err);
102+
return NextResponse.json(
103+
{ error: "Failed to fetch Wakatime stats" },
104+
{ status: 500 }
105+
);
83106
}
84107
}

0 commit comments

Comments
 (0)