#!/usr/bin/env node import { db } from './src/lib/server/db/index.js'; import { audioFile } from './src/lib/server/db/schema.js'; import { uploadToS3, generateAudioS3Key } from './src/lib/server/s3.js'; import { eq, isNull } from 'drizzle-orm'; async function migrateExistingFilesToS3() { console.log('Starting migration of existing audio files to S3...'); try { // Find all files that have blob data but no S3 key const filesToMigrate = await db.select().from(audioFile).where(isNull(audioFile.s3Key)); console.log(`Found ${filesToMigrate.length} files to migrate`); if (filesToMigrate.length === 0) { console.log('No files need migration. All files are already using S3.'); return; } for (const file of filesToMigrate) { console.log(`Migrating ${file.filename}...`); try { // Generate S3 key const s3Key = generateAudioS3Key(file.id, file.filename); // Upload blob data to S3 await uploadToS3(s3Key, file.data, file.contentType); // Update database record with S3 key await db.update(audioFile) .set({ s3Key }) .where(eq(audioFile.id, file.id)); console.log(`āœ“ Migrated ${file.filename} to S3: ${s3Key}`); } catch (error) { console.error(`āœ— Failed to migrate ${file.filename}:`, error); throw error; // Stop migration on first error } } console.log(`\nāœ… Successfully migrated ${filesToMigrate.length} files to S3`); console.log('You can now safely run the database schema migration to remove the blob column.'); } catch (error) { console.error('Migration failed:', error); process.exit(1); } } // Run migration migrateExistingFilesToS3();