'use server' import { prisma } from './db' import { getServerSession } from 'next-auth' import { authOptions } from '@/pages/api/auth/[...nextauth]' /** * Migration utilities for transitioning existing anonymous lists to user-owned lists * Requirements: 10.2, 10.3, 10.4, 10.5 */ export type MigrationResult = | { success: true; migratedCount: number } | { success: false; error: string } export type ClaimableList = { id: string title: string color: string itemCount: number createdAt: Date updatedAt: Date } /** * Get lists that can be claimed by a new user * This checks for lists in localStorage that exist in the database * Requirement: 10.2 - Provide migration path for existing anonymous lists */ export async function getClaimableLists(listIds: string[]): Promise { try { if (!listIds || listIds.length === 0) { return [] } // Find lists that exist in the database // Note: In a real migration scenario, we'd need a way to identify orphaned lists // For now, we'll check if the provided list IDs exist const lists = await prisma.list.findMany({ where: { id: { in: listIds, }, }, include: { _count: { select: { items: true, }, }, }, }) return lists.map(list => ({ id: list.id, title: list.title, color: list.color, itemCount: list._count.items, createdAt: list.createdAt, updatedAt: list.updatedAt, })) } catch (error) { console.error('Error fetching claimable lists:', error) return [] } } /** * Claim existing lists and associate them with the current user * Requirements: 10.2, 10.3, 10.4, 10.5 */ export async function claimLists(listIds: string[]): Promise { try { // Get current user session const session = await getServerSession(authOptions) if (!session?.user?.id) { return { success: false, error: 'Unauthorized: Please log in to claim lists' } } const userId = session.user.id if (!listIds || listIds.length === 0) { return { success: true, migratedCount: 0 } } // Update all specified lists to be owned by the current user // Requirement 10.3 - Preserve all list data including items, metadata, and timestamps // Requirement 10.4 - Ensure all lists have an associated owner // Use transaction to update each list individually to ensure proper type checking let migratedCount = 0 for (const listId of listIds) { try { await prisma.list.update({ where: { id: listId }, data: { ownerId: userId }, }) migratedCount++ } catch (err) { console.error(`Failed to claim list ${listId}:`, err) // Continue with other lists } } // Requirement 10.5 - Display migrated lists in user's account // Lists will now appear in getLists() since they have the user's ownerId return { success: true, migratedCount } } catch (error) { console.error('Error claiming lists:', error) return { success: false, error: 'Failed to claim lists. Please try again.' } } } /** * Check if a user has any lists (to determine if they're a new user) */ export async function hasExistingLists(): Promise { try { const session = await getServerSession(authOptions) if (!session?.user?.id) { return false } const count = await prisma.list.count({ where: { ownerId: session.user.id, }, }) return count > 0 } catch (error) { console.error('Error checking existing lists:', error) return false } } /** * Migrate all orphaned lists to a system user * This is a one-time migration script for deployment * Requirement: 10.1, 10.4 - Migration path and ensure all lists have owner */ export async function migrateOrphanedListsToSystemUser(): Promise { try { // First, check if system user exists const systemUser = await prisma.user.findUnique({ where: { email: 'system@ultimatelists.app' }, }) if (!systemUser) { return { success: false, error: 'System user does not exist. Run migration script first.' } } // This would migrate lists if ownerId was nullable // Since our current schema requires ownerId, this is a placeholder // In a real migration, you'd run this before making ownerId required return { success: true, migratedCount: 0 } } catch (error) { console.error('Error migrating orphaned lists:', error) return { success: false, error: 'Migration failed. Please contact support.' } } }