208 lines
7.5 KiB
JavaScript
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; |