#!/usr/bin/env node /** * Chat Database Migration Verification Script * * This script verifies that the chat database migration was successful * by comparing record counts and testing basic functionality. */ require('dotenv').config({ path: '../.env' }); const { Pool } = require('pg'); // Database configuration const pool = new Pool({ host: process.env.CHAT_DB_HOST || 'localhost', user: process.env.CHAT_DB_USER || 'rocketchat_user', password: process.env.CHAT_DB_PASSWORD, database: process.env.CHAT_DB_NAME || 'rocketchat_converted', port: process.env.CHAT_DB_PORT || 5432, }); const originalStats = process.argv[2] ? JSON.parse(process.argv[2]) : null; async function verifyMigration() { console.log('๐Ÿ” Starting migration verification...\n'); try { // Test basic connection console.log('๐Ÿ”— Testing database connection...'); const versionResult = await pool.query('SELECT version()'); console.log('โœ… Database connection successful'); console.log(` PostgreSQL version: ${versionResult.rows[0].version.split(' ')[1]}\n`); // Get table statistics console.log('๐Ÿ“Š Checking table statistics...'); const statsResult = await pool.query(` SELECT tablename, n_live_tup as row_count, n_dead_tup as dead_rows, schemaname FROM pg_stat_user_tables WHERE schemaname = 'public' ORDER BY n_live_tup DESC `); if (statsResult.rows.length === 0) { console.log('โŒ No tables found! Migration may have failed.'); return false; } console.log('๐Ÿ“‹ Table Statistics:'); console.log(' Table Name | Row Count | Dead Rows'); console.log(' -------------------|-----------|----------'); let totalRows = 0; const tableStats = {}; for (const row of statsResult.rows) { const rowCount = parseInt(row.row_count) || 0; const deadRows = parseInt(row.dead_rows) || 0; totalRows += rowCount; tableStats[row.tablename] = rowCount; console.log(` ${row.tablename.padEnd(18)} | ${rowCount.toString().padStart(9)} | ${deadRows.toString().padStart(8)}`); } console.log(`\n Total rows across all tables: ${totalRows}\n`); // Verify critical tables exist and have data const criticalTables = ['users', 'message', 'room']; console.log('๐Ÿ”‘ Checking critical tables...'); for (const table of criticalTables) { if (tableStats[table] > 0) { console.log(`โœ… ${table}: ${tableStats[table]} rows`); } else if (tableStats[table] === 0) { console.log(`โš ๏ธ ${table}: table exists but is empty`); } else { console.log(`โŒ ${table}: table not found`); return false; } } // Test specific functionality console.log('\n๐Ÿงช Testing specific functionality...'); // Test users table const userTest = await pool.query(` SELECT COUNT(*) as total_users, COUNT(*) FILTER (WHERE active = true) as active_users, COUNT(*) FILTER (WHERE type = 'user') as regular_users FROM users `); if (userTest.rows[0]) { const { total_users, active_users, regular_users } = userTest.rows[0]; console.log(`โœ… Users: ${total_users} total, ${active_users} active, ${regular_users} regular users`); } // Test messages table const messageTest = await pool.query(` SELECT COUNT(*) as total_messages, COUNT(DISTINCT rid) as unique_rooms, MIN(ts) as oldest_message, MAX(ts) as newest_message FROM message `); if (messageTest.rows[0]) { const { total_messages, unique_rooms, oldest_message, newest_message } = messageTest.rows[0]; console.log(`โœ… Messages: ${total_messages} total across ${unique_rooms} rooms`); if (oldest_message && newest_message) { console.log(` Date range: ${oldest_message.toISOString().split('T')[0]} to ${newest_message.toISOString().split('T')[0]}`); } } // Test rooms table const roomTest = await pool.query(` SELECT COUNT(*) as total_rooms, COUNT(*) FILTER (WHERE t = 'c') as channels, COUNT(*) FILTER (WHERE t = 'p') as private_groups, COUNT(*) FILTER (WHERE t = 'd') as direct_messages FROM room `); if (roomTest.rows[0]) { const { total_rooms, channels, private_groups, direct_messages } = roomTest.rows[0]; console.log(`โœ… Rooms: ${total_rooms} total (${channels} channels, ${private_groups} private, ${direct_messages} DMs)`); } // Test file uploads if table exists if (tableStats.uploads > 0) { const uploadTest = await pool.query(` SELECT COUNT(*) as total_uploads, COUNT(DISTINCT typegroup) as file_types, pg_size_pretty(SUM(size)) as total_size FROM uploads WHERE size IS NOT NULL `); if (uploadTest.rows[0]) { const { total_uploads, file_types, total_size } = uploadTest.rows[0]; console.log(`โœ… Uploads: ${total_uploads} files, ${file_types} types, ${total_size || 'unknown size'}`); } } // Test server health endpoint simulation console.log('\n๐Ÿฅ Testing application endpoints simulation...'); try { const healthTest = await pool.query(` SELECT (SELECT COUNT(*) FROM users WHERE active = true) as active_users, (SELECT COUNT(*) FROM message) as total_messages, (SELECT COUNT(*) FROM room) as total_rooms `); if (healthTest.rows[0]) { const stats = healthTest.rows[0]; console.log('โœ… Health check simulation passed'); console.log(` Active users: ${stats.active_users}`); console.log(` Total messages: ${stats.total_messages}`); console.log(` Total rooms: ${stats.total_rooms}`); } } catch (error) { console.log(`โš ๏ธ Health check simulation failed: ${error.message}`); } // Check indexes console.log('\n๐Ÿ“‡ Checking database indexes...'); const indexResult = await pool.query(` SELECT schemaname, tablename, indexname, indexdef FROM pg_indexes WHERE schemaname = 'public' ORDER BY tablename, indexname `); const indexesByTable = {}; for (const idx of indexResult.rows) { if (!indexesByTable[idx.tablename]) { indexesByTable[idx.tablename] = []; } indexesByTable[idx.tablename].push(idx.indexname); } for (const [table, indexes] of Object.entries(indexesByTable)) { console.log(` ${table}: ${indexes.length} indexes`); } console.log('\n๐ŸŽ‰ Migration verification completed successfully!'); console.log('\nโœ… Summary:'); console.log(` - Database connection: Working`); console.log(` - Tables created: ${statsResult.rows.length}`); console.log(` - Total data rows: ${totalRows}`); console.log(` - Critical tables: All present`); console.log(` - Indexes: ${indexResult.rows.length} total`); console.log('\n๐Ÿš€ Next steps:'); console.log(' 1. Update your application configuration'); console.log(' 2. Start your chat server'); console.log(' 3. Test chat functionality in the browser'); console.log(' 4. Monitor logs for any issues'); return true; } catch (error) { console.error('โŒ Migration verification failed:', error.message); console.error('\n๐Ÿ”ง Troubleshooting steps:'); console.error(' 1. Check database connection settings'); console.error(' 2. Verify database and user exist'); console.error(' 3. Check PostgreSQL logs'); console.error(' 4. Ensure import completed without errors'); return false; } finally { await pool.end(); } } // Run verification if (require.main === module) { verifyMigration().then(success => { process.exit(success ? 0 : 1); }); } module.exports = { verifyMigration };