import { db, shoppingLists, shoppingListMembers, eq, and } from "@epicure/db"; export type ShoppingListRole = "owner" | "editor" | "viewer"; export type ShoppingListAccess = { list: typeof shoppingLists.$inferSelect; role: ShoppingListRole; }; /** * Resolves access to a shopping list — owner, member with their assigned role, * or (when `userId` is null, i.e. no session) an anonymous visitor via the * public link: "editor" if the owner enabled public editing, "viewer" if the * list is merely public, else no access. The link's id is the only credential * an anonymous visitor has, so this must never fall through to a real role * for a non-public list. */ export async function getShoppingListAccess( listId: string, userId: string | null ): Promise { const list = await db.query.shoppingLists.findFirst({ where: eq(shoppingLists.id, listId) }); if (!list) return null; if (userId) { if (list.userId === userId) return { list, role: "owner" }; const member = await db.query.shoppingListMembers.findFirst({ where: and(eq(shoppingListMembers.listId, listId), eq(shoppingListMembers.userId, userId)), }); if (member) return { list, role: member.role }; } if (!list.isPublic) return null; return { list, role: list.publicEditable ? "editor" : "viewer" }; } export function canWriteShoppingList(role: ShoppingListRole): boolean { return role === "owner" || role === "editor"; }