Files
tilbudgivern/debug-tool.js

208 lines
7.5 KiB
JavaScript

#!/usr/bin/env node
/**
* Tilbudgivern Debug Tool
* Et avanceret diagnosticering værktøj for at identificere problemer
*/
const http = require('http');
const { spawn } = require('child_process');
class DebugTool {
constructor() {
this.tests = [
{ name: 'Server Health Check', method: 'checkServer' },
{ name: 'Frontend Assets Check', method: 'checkAssets' },
{ name: 'API Endpoints Check', method: 'checkAPI' },
{ name: 'Database Connection', method: 'checkDatabase' },
{ name: 'PM2 Process Status', method: 'checkPM2' },
{ name: 'Recent Error Analysis', method: 'analyzeErrors' }
];
}
async run() {
console.log('\n🔧 Tilbudgivern Advanced Debug Tool\n');
console.log('═'.repeat(50));
for (const test of this.tests) {
try {
console.log(`\n📋 ${test.name}...`);
await this[test.method]();
console.log('✅ PASSED');
} catch (error) {
console.log(`❌ FAILED: ${error.message}`);
}
}
console.log('\n' + '═'.repeat(50));
console.log('🎯 Debug Complete! Tjek resultaterne ovenfor.\n');
}
checkServer() {
return new Promise((resolve, reject) => {
const req = http.get('http://localhost:4030', (res) => {
if (res.statusCode === 200) {
console.log(` Status: ${res.statusCode} OK`);
console.log(` Headers: ${JSON.stringify(res.headers, null, 2)}`);
resolve();
} else {
reject(new Error(`Server returned ${res.statusCode}`));
}
});
req.on('error', (err) => {
reject(new Error(`Connection failed: ${err.message}`));
});
req.setTimeout(5000, () => {
reject(new Error('Request timeout'));
});
});
}
checkAssets() {
return new Promise((resolve, reject) => {
// Check main JS file
const req = http.get('http://localhost:4030/static/js/main.a016d298.js', (res) => {
if (res.statusCode === 200) {
console.log(' React JS bundle: ✅ Loaded');
// Check CSS file
const cssReq = http.get('http://localhost:4030/static/css/main.a0ad9f95.css', (cssRes) => {
if (cssRes.statusCode === 200) {
console.log(' CSS bundle: ✅ Loaded');
resolve();
} else {
reject(new Error(`CSS bundle failed: ${cssRes.statusCode}`));
}
});
cssReq.on('error', (err) => reject(new Error(`CSS error: ${err.message}`)));
} else {
reject(new Error(`JS bundle failed: ${res.statusCode}`));
}
});
req.on('error', (err) => reject(new Error(`Asset check error: ${err.message}`)));
});
}
async checkAPI() {
const endpoints = [
'/api/materials',
'/api/material-packages',
'/api/quotes'
];
for (const endpoint of endpoints) {
try {
await this.testEndpoint(endpoint);
console.log(` ${endpoint}: ✅ Responding`);
} catch (error) {
console.log(` ${endpoint}: ❌ ${error.message}`);
}
}
}
testEndpoint(path) {
return new Promise((resolve, reject) => {
const req = http.get(`http://localhost:4030${path}`, (res) => {
if (res.statusCode < 500) {
resolve();
} else {
reject(new Error(`Server error ${res.statusCode}`));
}
});
req.on('error', (err) => reject(new Error(err.message)));
req.setTimeout(3000, () => reject(new Error('Timeout')));
});
}
async checkDatabase() {
return new Promise((resolve, reject) => {
// Test database connection via API
const req = http.get('http://localhost:4030/api/materials?limit=1', (res) => {
let data = '';
res.on('data', (chunk) => data += chunk);
res.on('end', () => {
try {
const result = JSON.parse(data);
if (Array.isArray(result)) {
console.log(' Database: ✅ Connected and responding');
console.log(` Sample data: ${result.length} materials available`);
resolve();
} else {
reject(new Error('Unexpected response format'));
}
} catch (error) {
reject(new Error(`Parse error: ${error.message}`));
}
});
});
req.on('error', (err) => reject(new Error(`DB test failed: ${err.message}`)));
});
}
async checkPM2() {
return new Promise((resolve, reject) => {
const pm2 = spawn('pm2', ['status'], { stdio: 'pipe' });
let output = '';
pm2.stdout.on('data', (data) => output += data);
pm2.stderr.on('data', (data) => output += data);
pm2.on('close', (code) => {
if (code === 0) {
console.log(' PM2 Status:');
const lines = output.split('\n');
lines.forEach(line => {
if (line.includes('tilbudgivern') || line.includes('online') || line.includes('stopped')) {
console.log(` ${line}`);
}
});
resolve();
} else {
reject(new Error(`PM2 command failed with code ${code}`));
}
});
});
}
async analyzeErrors() {
return new Promise((resolve, reject) => {
const pm2 = spawn('pm2', ['logs', 'tilbudgivern-unified', '--lines', '50', '--nostream'], { stdio: 'pipe' });
let output = '';
pm2.stdout.on('data', (data) => output += data);
pm2.stderr.on('data', (data) => output += data);
pm2.on('close', (code) => {
const errors = output.split('\n').filter(line =>
line.toLowerCase().includes('error') ||
line.toLowerCase().includes('failed') ||
line.toLowerCase().includes('exception')
);
if (errors.length > 0) {
console.log(` Recent Errors (${errors.length} found):`);
errors.slice(-5).forEach(error => {
console.log(` ${error.trim()}`);
});
} else {
console.log(' No recent errors found');
}
resolve();
});
});
}
}
// Kør debug tool
if (require.main === module) {
const debugTool = new DebugTool();
debugTool.run().catch(console.error);
}
module.exports = DebugTool;