From 90497e9e7cff189c84e2444c8d179778687e2cde Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebastian=20Kr=C3=BCger?= Date: Sat, 7 Mar 2026 19:33:16 +0100 Subject: [PATCH] fix: resolve TypeScript build errors from leftJoin nullable types Non-null assert photo/achievement ids that are structurally non-null due to FK constraints but nullable in Drizzle's leftJoin return type. Add missing description field to enrichVideo model select and map. Co-Authored-By: Claude Sonnet 4.6 --- .../backend/src/graphql/resolvers/gamification.ts | 9 ++++++++- packages/backend/src/graphql/resolvers/models.ts | 4 ++-- packages/backend/src/graphql/resolvers/users.ts | 4 ++-- packages/backend/src/graphql/resolvers/videos.ts | 13 ++++++++++++- 4 files changed, 24 insertions(+), 6 deletions(-) diff --git a/packages/backend/src/graphql/resolvers/gamification.ts b/packages/backend/src/graphql/resolvers/gamification.ts index 9dad1a4..3b494d2 100644 --- a/packages/backend/src/graphql/resolvers/gamification.ts +++ b/packages/backend/src/graphql/resolvers/gamification.ts @@ -102,7 +102,14 @@ builder.queryField("userGamification", (t) => return { stats: stats[0] ? { ...stats[0], rank } : null, achievements: userAchievements.map((a) => ({ - ...a, + id: a.id!, + code: a.code!, + name: a.name!, + description: a.description!, + icon: a.icon!, + category: a.category!, + required_count: a.required_count!, + progress: a.progress!, date_unlocked: a.date_unlocked!, })), recent_points: recentPoints, diff --git a/packages/backend/src/graphql/resolvers/models.ts b/packages/backend/src/graphql/resolvers/models.ts index 56ac49f..5920fab 100644 --- a/packages/backend/src/graphql/resolvers/models.ts +++ b/packages/backend/src/graphql/resolvers/models.ts @@ -15,8 +15,8 @@ async function enrichModel(db: DB, user: typeof users.$inferSelect) { const seen = new Set(); const photos = photoRows - .filter((p) => p.id && !seen.has(p.id) && seen.add(p.id)) - .map((p) => ({ id: p.id, filename: p.filename })); + .filter((p) => p.id !== null && !seen.has(p.id!) && seen.add(p.id!)) + .map((p) => ({ id: p.id!, filename: p.filename! })); return { ...user, photos }; } diff --git a/packages/backend/src/graphql/resolvers/users.ts b/packages/backend/src/graphql/resolvers/users.ts index a72baf1..90318f8 100644 --- a/packages/backend/src/graphql/resolvers/users.ts +++ b/packages/backend/src/graphql/resolvers/users.ts @@ -195,8 +195,8 @@ builder.queryField("adminGetUser", (t) => .orderBy(user_photos.sort); const seen = new Set(); const photos = photoRows - .filter((p) => p.id && !seen.has(p.id) && seen.add(p.id)) - .map((p) => ({ id: p.id, filename: p.filename })); + .filter((p) => p.id !== null && !seen.has(p.id!) && seen.add(p.id!)) + .map((p) => ({ id: p.id!, filename: p.filename! })); return { ...user[0], photos }; }, }), diff --git a/packages/backend/src/graphql/resolvers/videos.ts b/packages/backend/src/graphql/resolvers/videos.ts index 453857d..3309a5e 100644 --- a/packages/backend/src/graphql/resolvers/videos.ts +++ b/packages/backend/src/graphql/resolvers/videos.ts @@ -41,6 +41,7 @@ async function enrichVideo(db: DB, video: typeof videos.$inferSelect) { artist_name: users.artist_name, slug: users.slug, avatar: users.avatar, + description: users.description, }) .from(video_models) .leftJoin(users, eq(video_models.user_id, users.id)) @@ -63,9 +64,19 @@ async function enrichVideo(db: DB, video: typeof videos.$inferSelect) { .from(video_plays) .where(eq(video_plays.video_id, video.id)); + const models = modelRows + .filter((m) => m.id !== null) + .map((m) => ({ + id: m.id!, + artist_name: m.artist_name, + slug: m.slug, + avatar: m.avatar, + description: m.description, + })); + return { ...video, - models: modelRows, + models, movie_file: movieFile, likes_count: likesCount[0]?.count || 0, plays_count: playsCount[0]?.count || 0,