143 lines
5.0 KiB
TypeScript
143 lines
5.0 KiB
TypeScript
import { PrismaClient } from '@prisma/client';
|
|
|
|
const prisma = new PrismaClient();
|
|
|
|
async function cleanupOrphanedData() {
|
|
console.log('🔍 Checking for orphaned video references...');
|
|
|
|
try {
|
|
// Get all existing video IDs
|
|
const existingVideos = await prisma.video.findMany({
|
|
select: { id: true }
|
|
});
|
|
const existingVideoIds = new Set(existingVideos.map(v => v.id));
|
|
console.log(`📹 Found ${existingVideoIds.size} existing videos`);
|
|
|
|
let totalCleaned = 0;
|
|
|
|
// 1. Clean orphaned VideoProgress records
|
|
const allProgress = await prisma.videoProgress.findMany({
|
|
select: { id: true, videoId: true, userId: true }
|
|
});
|
|
const orphanedProgress = allProgress.filter(p => !existingVideoIds.has(p.videoId));
|
|
|
|
if (orphanedProgress.length > 0) {
|
|
console.log(`🧹 Found ${orphanedProgress.length} orphaned VideoProgress records`);
|
|
await prisma.videoProgress.deleteMany({
|
|
where: {
|
|
id: { in: orphanedProgress.map(p => p.id) }
|
|
}
|
|
});
|
|
console.log(`✅ Deleted ${orphanedProgress.length} orphaned VideoProgress records`);
|
|
totalCleaned += orphanedProgress.length;
|
|
}
|
|
|
|
// 2. Clean orphaned VideoWatchSegment records
|
|
const allSegments = await prisma.videoWatchSegment.findMany({
|
|
select: { id: true, videoId: true, userId: true }
|
|
});
|
|
const orphanedSegments = allSegments.filter(s => !existingVideoIds.has(s.videoId));
|
|
|
|
if (orphanedSegments.length > 0) {
|
|
console.log(`🧹 Found ${orphanedSegments.length} orphaned VideoWatchSegment records`);
|
|
await prisma.videoWatchSegment.deleteMany({
|
|
where: {
|
|
id: { in: orphanedSegments.map(s => s.id) }
|
|
}
|
|
});
|
|
console.log(`✅ Deleted ${orphanedSegments.length} orphaned VideoWatchSegment records`);
|
|
totalCleaned += orphanedSegments.length;
|
|
}
|
|
|
|
// 3. Clean orphaned VideoUnlock records
|
|
const allUnlocks = await prisma.videoUnlock.findMany({
|
|
select: { id: true, videoId: true, userId: true }
|
|
});
|
|
const orphanedUnlocks = allUnlocks.filter(u => !existingVideoIds.has(u.videoId));
|
|
|
|
if (orphanedUnlocks.length > 0) {
|
|
console.log(`🧹 Found ${orphanedUnlocks.length} orphaned VideoUnlock records`);
|
|
await prisma.videoUnlock.deleteMany({
|
|
where: {
|
|
id: { in: orphanedUnlocks.map(u => u.id) }
|
|
}
|
|
});
|
|
console.log(`✅ Deleted ${orphanedUnlocks.length} orphaned VideoUnlock records`);
|
|
totalCleaned += orphanedUnlocks.length;
|
|
}
|
|
|
|
// 4. Clean orphaned VideoLike records
|
|
const allLikes = await prisma.videoLike.findMany({
|
|
select: { id: true, videoId: true, userId: true }
|
|
});
|
|
const orphanedLikes = allLikes.filter(l => !existingVideoIds.has(l.videoId));
|
|
|
|
if (orphanedLikes.length > 0) {
|
|
console.log(`🧹 Found ${orphanedLikes.length} orphaned VideoLike records`);
|
|
await prisma.videoLike.deleteMany({
|
|
where: {
|
|
id: { in: orphanedLikes.map(l => l.id) }
|
|
}
|
|
});
|
|
console.log(`✅ Deleted ${orphanedLikes.length} orphaned VideoLike records`);
|
|
totalCleaned += orphanedLikes.length;
|
|
}
|
|
|
|
// 5. Clean orphaned Comment records
|
|
const allComments = await prisma.comment.findMany({
|
|
select: { id: true, videoId: true, userId: true }
|
|
});
|
|
const orphanedComments = allComments.filter(c => !existingVideoIds.has(c.videoId));
|
|
|
|
if (orphanedComments.length > 0) {
|
|
console.log(`🧹 Found ${orphanedComments.length} orphaned Comment records`);
|
|
await prisma.comment.deleteMany({
|
|
where: {
|
|
id: { in: orphanedComments.map(c => c.id) }
|
|
}
|
|
});
|
|
console.log(`✅ Deleted ${orphanedComments.length} orphaned Comment records`);
|
|
totalCleaned += orphanedComments.length;
|
|
}
|
|
|
|
// 6. Clean orphaned VideoCourse records
|
|
const allVideoCourses = await prisma.videoCourse.findMany({
|
|
select: { id: true, videoId: true, courseId: true }
|
|
});
|
|
const orphanedVideoCourses = allVideoCourses.filter(vc => !existingVideoIds.has(vc.videoId));
|
|
|
|
if (orphanedVideoCourses.length > 0) {
|
|
console.log(`🧹 Found ${orphanedVideoCourses.length} orphaned VideoCourse records`);
|
|
await prisma.videoCourse.deleteMany({
|
|
where: {
|
|
id: { in: orphanedVideoCourses.map(vc => vc.id) }
|
|
}
|
|
});
|
|
console.log(`✅ Deleted ${orphanedVideoCourses.length} orphaned VideoCourse records`);
|
|
totalCleaned += orphanedVideoCourses.length;
|
|
}
|
|
|
|
// 7. Report summary
|
|
if (totalCleaned === 0) {
|
|
console.log('✨ No orphaned video references found! Database is clean.');
|
|
} else {
|
|
console.log(`🎉 Cleanup complete! Removed ${totalCleaned} total orphaned records.`);
|
|
}
|
|
|
|
} catch (error) {
|
|
console.error('❌ Error during cleanup:', error);
|
|
} finally {
|
|
await prisma.$disconnect();
|
|
}
|
|
}
|
|
|
|
// Run the cleanup
|
|
cleanupOrphanedData()
|
|
.then(() => {
|
|
console.log('🔧 Cleanup script completed');
|
|
process.exit(0);
|
|
})
|
|
.catch((error) => {
|
|
console.error('💥 Script failed:', error);
|
|
process.exit(1);
|
|
}); |