#!/usr/bin/env tsx import dotenv from 'dotenv'; import path from 'path'; dotenv.config({ path: path.resolve(process.cwd(), '.env.local') }); import { Pool } from 'pg'; import { PrismaPg } from '@prisma/adapter-pg'; import { PrismaClient } from '@prisma/client'; const pool = new Pool({ connectionString: process.env.DATABASE_URL }); const adapter = new PrismaPg(pool); const prisma = new PrismaClient({ adapter }); async function main() { const dryRun = !process.argv.includes('--execute'); if (dryRun) { console.log('DRY RUN - pass --execute to actually delete duplicates\n'); } const churches = await prisma.church.findMany({ where: { massSchedules: { some: { isActive: true } } }, include: { massSchedules: { where: { isActive: true }, orderBy: { createdAt: 'asc' } } }, }); let churchesFixed = 0; let rowsDeleted = 0; for (const church of churches) { const seen = new Map(); const toDelete: string[] = []; for (const m of church.massSchedules) { const key = `${m.dayOfWeek}:${m.time}:${m.language}`; if (seen.has(key)) { toDelete.push(m.id); } else { seen.set(key, m.id); } } if (toDelete.length > 0) { churchesFixed++; rowsDeleted += toDelete.length; if (!dryRun) { await prisma.massSchedule.deleteMany({ where: { id: { in: toDelete } }, }); } } } console.log(`Churches with duplicates: ${churchesFixed}`); console.log(`Duplicate rows ${dryRun ? 'found' : 'deleted'}: ${rowsDeleted}`); await prisma.$disconnect(); await pool.end(); } main().catch((err) => { console.error('Fatal error:', err); process.exit(1); });