All checks were successful
Build Frontend / Build Frontend (push) Successful in 35s
315 lines
8.5 KiB
JavaScript
315 lines
8.5 KiB
JavaScript
#!/usr/bin/env node
|
||
|
||
/**
|
||
* Verification Script for Navbar Login Fix
|
||
*
|
||
* This script verifies that the WebSocket authentication state synchronization
|
||
* is working correctly after the navbar login fix deployment.
|
||
*
|
||
* Usage:
|
||
* node scripts/verify-login-fix.js
|
||
*/
|
||
|
||
const https = require('https');
|
||
const http = require('http');
|
||
|
||
const API_URL = process.env.VITE_API_URL || 'https://api.turbotrades.dev';
|
||
const WS_URL = process.env.VITE_WS_URL || 'wss://api.turbotrades.dev/ws';
|
||
|
||
const colors = {
|
||
reset: '\x1b[0m',
|
||
bright: '\x1b[1m',
|
||
green: '\x1b[32m',
|
||
red: '\x1b[31m',
|
||
yellow: '\x1b[33m',
|
||
blue: '\x1b[34m',
|
||
cyan: '\x1b[36m',
|
||
};
|
||
|
||
function log(message, color = colors.reset) {
|
||
console.log(`${color}${message}${colors.reset}`);
|
||
}
|
||
|
||
function success(message) {
|
||
log(`✅ ${message}`, colors.green);
|
||
}
|
||
|
||
function error(message) {
|
||
log(`❌ ${message}`, colors.red);
|
||
}
|
||
|
||
function warning(message) {
|
||
log(`⚠️ ${message}`, colors.yellow);
|
||
}
|
||
|
||
function info(message) {
|
||
log(`ℹ️ ${message}`, colors.cyan);
|
||
}
|
||
|
||
function section(message) {
|
||
log(`\n${colors.bright}${message}${colors.reset}`);
|
||
log('='.repeat(60));
|
||
}
|
||
|
||
// Check if endpoint is reachable
|
||
function checkEndpoint(url, description) {
|
||
return new Promise((resolve) => {
|
||
const urlObj = new URL(url);
|
||
const client = urlObj.protocol === 'https:' ? https : http;
|
||
|
||
const options = {
|
||
hostname: urlObj.hostname,
|
||
port: urlObj.port || (urlObj.protocol === 'https:' ? 443 : 80),
|
||
path: urlObj.pathname,
|
||
method: 'GET',
|
||
timeout: 5000,
|
||
};
|
||
|
||
const req = client.request(options, (res) => {
|
||
if (res.statusCode >= 200 && res.statusCode < 400) {
|
||
success(`${description}: Reachable (Status: ${res.statusCode})`);
|
||
resolve(true);
|
||
} else {
|
||
warning(`${description}: Returned status ${res.statusCode}`);
|
||
resolve(false);
|
||
}
|
||
});
|
||
|
||
req.on('error', (err) => {
|
||
error(`${description}: ${err.message}`);
|
||
resolve(false);
|
||
});
|
||
|
||
req.on('timeout', () => {
|
||
error(`${description}: Request timed out`);
|
||
req.destroy();
|
||
resolve(false);
|
||
});
|
||
|
||
req.end();
|
||
});
|
||
}
|
||
|
||
// Check WebSocket endpoint
|
||
function checkWebSocket(url) {
|
||
return new Promise((resolve) => {
|
||
try {
|
||
const WebSocket = require('ws');
|
||
const ws = new WebSocket(url);
|
||
|
||
const timeout = setTimeout(() => {
|
||
ws.close();
|
||
error('WebSocket: Connection timeout');
|
||
resolve(false);
|
||
}, 5000);
|
||
|
||
ws.on('open', () => {
|
||
clearTimeout(timeout);
|
||
success('WebSocket: Connection successful');
|
||
ws.close();
|
||
resolve(true);
|
||
});
|
||
|
||
ws.on('error', (err) => {
|
||
clearTimeout(timeout);
|
||
error(`WebSocket: ${err.message}`);
|
||
resolve(false);
|
||
});
|
||
|
||
} catch (err) {
|
||
error(`WebSocket: ws module not available (${err.message})`);
|
||
warning('Install with: npm install ws');
|
||
resolve(false);
|
||
}
|
||
});
|
||
}
|
||
|
||
// Read and verify frontend build files
|
||
function checkFrontendBuild() {
|
||
const fs = require('fs');
|
||
const path = require('path');
|
||
|
||
const distPath = path.join(__dirname, '..', 'frontend', 'dist');
|
||
const indexPath = path.join(distPath, 'index.html');
|
||
|
||
if (!fs.existsSync(distPath)) {
|
||
error('Frontend dist directory not found');
|
||
warning('Run: cd frontend && npm run build');
|
||
return false;
|
||
}
|
||
|
||
if (!fs.existsSync(indexPath)) {
|
||
error('Frontend index.html not found in dist/');
|
||
return false;
|
||
}
|
||
|
||
const indexContent = fs.readFileSync(indexPath, 'utf8');
|
||
|
||
// Check for recent build by looking for assets
|
||
const hasAssets = indexContent.includes('/assets/');
|
||
const hasModernJS = indexContent.includes('type="module"');
|
||
|
||
if (hasAssets && hasModernJS) {
|
||
success('Frontend build exists and looks valid');
|
||
|
||
// Get build timestamp from file modification time
|
||
const stats = fs.statSync(indexPath);
|
||
const buildTime = stats.mtime;
|
||
const now = new Date();
|
||
const ageMinutes = Math.floor((now - buildTime) / 1000 / 60);
|
||
|
||
if (ageMinutes < 60) {
|
||
success(`Build age: ${ageMinutes} minutes (recent)`);
|
||
} else if (ageMinutes < 1440) {
|
||
info(`Build age: ${Math.floor(ageMinutes / 60)} hours`);
|
||
} else {
|
||
warning(`Build age: ${Math.floor(ageMinutes / 1440)} days (consider rebuilding)`);
|
||
}
|
||
|
||
return true;
|
||
} else {
|
||
error('Frontend build appears invalid');
|
||
return false;
|
||
}
|
||
}
|
||
|
||
// Check source files for the fix
|
||
function checkSourceCode() {
|
||
const fs = require('fs');
|
||
const path = require('path');
|
||
|
||
const websocketStorePath = path.join(__dirname, '..', 'frontend', 'src', 'stores', 'websocket.js');
|
||
const authStorePath = path.join(__dirname, '..', 'frontend', 'src', 'stores', 'auth.js');
|
||
|
||
if (!fs.existsSync(websocketStorePath)) {
|
||
error('WebSocket store not found');
|
||
return false;
|
||
}
|
||
|
||
if (!fs.existsSync(authStorePath)) {
|
||
error('Auth store not found');
|
||
return false;
|
||
}
|
||
|
||
const websocketCode = fs.readFileSync(websocketStorePath, 'utf8');
|
||
const authCode = fs.readFileSync(authStorePath, 'utf8');
|
||
|
||
// Check for the fix in websocket store
|
||
const hasConnectedHandler = websocketCode.includes('case "connected":');
|
||
const callsFetchUser = websocketCode.includes('authStore.fetchUser()');
|
||
const declaresAuthStore = websocketCode.includes('const authStore = useAuthStore()');
|
||
|
||
if (hasConnectedHandler && callsFetchUser && declaresAuthStore) {
|
||
success('WebSocket store has the navbar login fix');
|
||
} else {
|
||
error('WebSocket store missing the fix');
|
||
if (!hasConnectedHandler) warning(' - Missing "connected" case handler');
|
||
if (!callsFetchUser) warning(' - Not calling authStore.fetchUser()');
|
||
if (!declaresAuthStore) warning(' - Not declaring authStore');
|
||
return false;
|
||
}
|
||
|
||
// Check for debug logging (optional)
|
||
const hasDebugLogs = websocketCode.includes('🟢 WebSocket received') ||
|
||
authCode.includes('🔵 fetchUser called');
|
||
|
||
if (hasDebugLogs) {
|
||
info('Debug logging is present (helpful for troubleshooting)');
|
||
} else {
|
||
info('Debug logging not present (clean for production)');
|
||
}
|
||
|
||
return true;
|
||
}
|
||
|
||
// Main verification flow
|
||
async function main() {
|
||
log('\n' + '='.repeat(60), colors.bright);
|
||
log(' NAVBAR LOGIN FIX - VERIFICATION SCRIPT', colors.bright);
|
||
log('='.repeat(60) + '\n', colors.bright);
|
||
|
||
let allChecks = true;
|
||
|
||
// 1. Check source code
|
||
section('1. Checking Source Code');
|
||
const sourceCheck = checkSourceCode();
|
||
allChecks = allChecks && sourceCheck;
|
||
|
||
// 2. Check frontend build
|
||
section('2. Checking Frontend Build');
|
||
const buildCheck = checkFrontendBuild();
|
||
allChecks = allChecks && buildCheck;
|
||
|
||
// 3. Check API endpoints
|
||
section('3. Checking API Endpoints');
|
||
|
||
const apiHealthCheck = await checkEndpoint(
|
||
`${API_URL}/api/health`,
|
||
'API Health Endpoint'
|
||
);
|
||
|
||
const apiAuthCheck = await checkEndpoint(
|
||
`${API_URL}/api/auth/me`,
|
||
'Auth Endpoint (/api/auth/me)'
|
||
);
|
||
|
||
const publicConfigCheck = await checkEndpoint(
|
||
`${API_URL}/api/config/public`,
|
||
'Public Config Endpoint'
|
||
);
|
||
|
||
allChecks = allChecks && apiHealthCheck && apiAuthCheck && publicConfigCheck;
|
||
|
||
// 4. Check WebSocket
|
||
section('4. Checking WebSocket Connection');
|
||
const wsCheck = await checkWebSocket(WS_URL);
|
||
allChecks = allChecks && wsCheck;
|
||
|
||
// Summary
|
||
section('Verification Summary');
|
||
|
||
if (allChecks) {
|
||
success('All checks passed! ✨');
|
||
log('\n📋 Next Steps:', colors.bright);
|
||
log(' 1. Deploy the frontend build to production');
|
||
log(' 2. Clear browser cache (Ctrl+Shift+R)');
|
||
log(' 3. Test Steam login in browser');
|
||
log(' 4. Verify navbar updates after login\n');
|
||
} else {
|
||
error('Some checks failed!');
|
||
log('\n📋 Recommended Actions:', colors.bright);
|
||
|
||
if (!sourceCheck) {
|
||
log(' • Verify the code changes are committed');
|
||
log(' • Pull latest changes: git pull origin main');
|
||
}
|
||
|
||
if (!buildCheck) {
|
||
log(' • Rebuild frontend: cd frontend && npm run build');
|
||
}
|
||
|
||
if (!apiHealthCheck || !apiAuthCheck || !publicConfigCheck) {
|
||
log(' • Check backend is running: pm2 status');
|
||
log(' • Check backend logs: pm2 logs turbotrades-backend');
|
||
log(' • Verify Nginx configuration');
|
||
}
|
||
|
||
if (!wsCheck) {
|
||
log(' • Check WebSocket endpoint in Nginx config');
|
||
log(' • Verify backend WebSocket service is running');
|
||
log(' • Check firewall rules for WebSocket connections');
|
||
}
|
||
|
||
log('');
|
||
}
|
||
|
||
process.exit(allChecks ? 0 : 1);
|
||
}
|
||
|
||
// Run the script
|
||
main().catch((err) => {
|
||
error(`Unexpected error: ${err.message}`);
|
||
console.error(err);
|
||
process.exit(1);
|
||
});
|