diff --git a/src/lib/session.ts b/src/lib/session.ts index 0cbb6ab..bebf3ab 100644 --- a/src/lib/session.ts +++ b/src/lib/session.ts @@ -2,6 +2,8 @@ import { eq } from "drizzle-orm"; import { auth } from "@/lib/auth"; import { db } from "@/lib/db"; import { householdMembers, households, users } from "@/modules/_core/schema"; +import { ensureDefaultCalendarsForMembership } from "@/modules/calendar/server/defaults"; +import { ensureDefaultListsForHousehold } from "@/modules/lists/server/defaults"; export interface CurrentSession { user: typeof users.$inferSelect; @@ -25,7 +27,36 @@ export async function getCurrentSession(): Promise { .where(eq(householdMembers.userId, session.user.id)) .limit(1); - if (!row) throw new Error("No household membership"); + if (row) return row; - return row; + // No membership yet — happens when the household was seeded after the user's + // first sign-in (e.g. first deploy). Auto-enroll into the single household. + const [household] = await db.select().from(households).limit(1); + if (!household) throw new Error("No household membership"); + + const [anyMember] = await db + .select() + .from(householdMembers) + .where(eq(householdMembers.householdId, household.id)) + .limit(1); + const role = anyMember ? "member" : "owner"; + + await db + .insert(householdMembers) + .values({ householdId: household.id, userId: session.user.id, role }) + .onConflictDoNothing(); + + await ensureDefaultCalendarsForMembership({ householdId: household.id, userId: session.user.id }); + await ensureDefaultListsForHousehold(household.id); + + const [fixed] = await db + .select({ user: users, household: households, role: householdMembers.role }) + .from(householdMembers) + .innerJoin(users, eq(householdMembers.userId, users.id)) + .innerJoin(households, eq(householdMembers.householdId, households.id)) + .where(eq(householdMembers.userId, session.user.id)) + .limit(1); + + if (!fixed) throw new Error("No household membership"); + return fixed; }