mirror of
https://github.com/rcourtman/Pulse.git
synced 2026-09-10 10:35:51 +00:00
Reorganize and enhance scripts with improved startup and configuration tools
This commit is contained in:
+70
-5
@@ -6,14 +6,79 @@ This directory contains various scripts used for development, testing, and maint
|
||||
|
||||
These scripts are for development and testing purposes only. They are not part of the main Pulse application and should not be used in production environments.
|
||||
|
||||
For more information about the development tools, see [README-dev-tools.md](README-dev-tools.md).
|
||||
|
||||
## Available Scripts
|
||||
|
||||
- **generate-mock-data.js** - Generates simulated data for development and testing
|
||||
### Core Scripts
|
||||
|
||||
- **start.js** - Main launcher script that provides a menu to select which environment to start
|
||||
- **install.sh** - Interactive installation and setup script
|
||||
- **check-config.js** - Validates the configuration and checks for common issues
|
||||
- **monitor-logs.js** - Real-time log monitoring with filtering capabilities
|
||||
- **run-with-logs.js** - Runs the application and monitors logs in the same terminal
|
||||
|
||||
### Development Scripts
|
||||
|
||||
- **start-dev.sh/bat** - Start the application in development mode with mock data
|
||||
- **start-mock-dev.sh/bat** - Start the application in development mode with mock data (alias for start-dev.sh)
|
||||
- **start-mock-server.js** - Starts only the mock data server
|
||||
- **debug-socket.js** - Debug proxy for troubleshooting socket communication
|
||||
- **debug-proxy.sh** - Runs the application with the debug proxy
|
||||
|
||||
## Production Scripts
|
||||
### Production Scripts
|
||||
|
||||
There are currently no production scripts in this directory.
|
||||
- **start-prod.sh/bat** - Start the application in production mode
|
||||
- **docker-prod.sh** - Start the application in production mode with Docker
|
||||
|
||||
### Utility Scripts
|
||||
|
||||
- **check-connections.js** - Tests various connection methods to help diagnose issues
|
||||
- **clear-data.js** - Clears cached data and resets the application state
|
||||
- **configure-env.js** - Interactive script to configure the .env file
|
||||
- **verify-cluster-config.js** - Verifies the cluster configuration
|
||||
|
||||
## Which Script Should I Use?
|
||||
|
||||
Instead of calling these scripts directly, you can use the npm scripts in the root directory:
|
||||
|
||||
```bash
|
||||
# Development mode with mock data (local)
|
||||
npm run dev
|
||||
|
||||
# Development mode with mock data (Docker)
|
||||
npm run dev:docker
|
||||
|
||||
# Production mode with real Proxmox data (local)
|
||||
npm run prod
|
||||
|
||||
# Production mode with real Proxmox data (Docker)
|
||||
npm run prod:docker
|
||||
|
||||
# Monitor logs
|
||||
npm run logs
|
||||
|
||||
# Check container status
|
||||
npm run status
|
||||
|
||||
# Restart the application
|
||||
npm run restart
|
||||
|
||||
# Stop the application
|
||||
npm run stop
|
||||
|
||||
# Clean up (remove containers, images, volumes)
|
||||
npm run cleanup
|
||||
```
|
||||
|
||||
## Using the Launcher
|
||||
|
||||
You can also use the launcher in the root directory:
|
||||
|
||||
```bash
|
||||
# On Unix/Linux/macOS
|
||||
./start.sh
|
||||
|
||||
# On Windows
|
||||
start.bat
|
||||
```
|
||||
|
||||
The launcher provides a menu to select which environment to start, making it easier for users to choose the right option.
|
||||
Executable
+336
@@ -0,0 +1,336 @@
|
||||
#!/usr/bin/env node
|
||||
|
||||
/**
|
||||
* AI Helper Script
|
||||
*
|
||||
* This script is designed to help AI assistants run commands and immediately see their output
|
||||
* without getting stuck waiting for long-running processes to complete.
|
||||
*
|
||||
* It runs a command in the background, captures the initial output, and returns control to the terminal.
|
||||
*
|
||||
* Usage:
|
||||
* node scripts/ai-helper.js [command] [options]
|
||||
*
|
||||
* Commands:
|
||||
* start-server Start the server in the background
|
||||
* check-logs Check the most recent logs
|
||||
* check-cluster Check cluster-related logs
|
||||
* check-status Check if the server is running
|
||||
* stop-server Stop the server
|
||||
* verify-config Verify the current environment configuration
|
||||
*
|
||||
* Options:
|
||||
* --env=<env> Environment (prod, dev, or dev:no-cluster, default: prod)
|
||||
* --lines=<number> Number of log lines to show (default: 20)
|
||||
* --help Show this help message
|
||||
*
|
||||
* Examples:
|
||||
* node scripts/ai-helper.js start-server --env=prod
|
||||
* node scripts/ai-helper.js check-logs --lines=50
|
||||
* node scripts/ai-helper.js check-cluster
|
||||
* node scripts/ai-helper.js verify-config
|
||||
*/
|
||||
|
||||
const { execSync, spawn } = require('child_process');
|
||||
const fs = require('fs');
|
||||
const path = require('path');
|
||||
|
||||
// Parse command line arguments
|
||||
const args = process.argv.slice(2);
|
||||
const command = args[0];
|
||||
const options = {
|
||||
env: getArgValue(args, '--env') || 'prod',
|
||||
lines: parseInt(getArgValue(args, '--lines') || '20', 10),
|
||||
help: args.includes('--help') || args.includes('-h')
|
||||
};
|
||||
|
||||
// Show help if requested or no command provided
|
||||
if (options.help || !command) {
|
||||
console.log(fs.readFileSync(__filename, 'utf8')
|
||||
.split('\n')
|
||||
.filter(line => line.startsWith(' *'))
|
||||
.map(line => line.substring(3))
|
||||
.join('\n'));
|
||||
process.exit(0);
|
||||
}
|
||||
|
||||
// Validate environment
|
||||
if (!['prod', 'prod:no-cluster', 'dev', 'dev:no-cluster'].includes(options.env)) {
|
||||
console.error(`Error: Unknown environment "${options.env}". Use "prod", "prod:no-cluster", "dev", or "dev:no-cluster".`);
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
// Ensure logs directory exists
|
||||
if (!fs.existsSync('logs')) {
|
||||
fs.mkdirSync('logs');
|
||||
}
|
||||
|
||||
// Create a unique log file for this run
|
||||
const timestamp = new Date().toISOString().replace(/[:.]/g, '-');
|
||||
const logFile = `logs/ai-helper-${timestamp}.log`;
|
||||
|
||||
// Execute the requested command
|
||||
switch (command) {
|
||||
case 'start-server':
|
||||
startServer(options.env);
|
||||
break;
|
||||
case 'check-logs':
|
||||
checkLogs(options.lines);
|
||||
break;
|
||||
case 'check-cluster':
|
||||
checkClusterLogs(options.lines);
|
||||
break;
|
||||
case 'check-status':
|
||||
checkStatus();
|
||||
break;
|
||||
case 'stop-server':
|
||||
stopServer();
|
||||
break;
|
||||
case 'verify-config':
|
||||
verifyConfig();
|
||||
break;
|
||||
default:
|
||||
console.error(`Unknown command: ${command}`);
|
||||
console.log('Run with --help to see available commands');
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
// Helper function to get argument value
|
||||
function getArgValue(args, name) {
|
||||
const arg = args.find(a => a.startsWith(`${name}=`));
|
||||
return arg ? arg.split('=')[1] : null;
|
||||
}
|
||||
|
||||
// Start the server in the background
|
||||
function startServer(env) {
|
||||
console.log(`Starting server in ${env} mode...`);
|
||||
|
||||
try {
|
||||
// First, configure the environment
|
||||
execSync(`node scripts/configure-env.js ${env}`, { stdio: 'inherit' });
|
||||
|
||||
// Build the application if needed
|
||||
if (env === 'prod') {
|
||||
console.log('Building the application...');
|
||||
execSync('npm run build', { stdio: 'inherit' });
|
||||
}
|
||||
|
||||
// Start the server in the background
|
||||
const serverProcess = spawn('node', [
|
||||
env === 'prod' ? 'dist/server.js' : 'scripts/start.js',
|
||||
env === 'prod' ? '' : 'dev:mock'
|
||||
].filter(Boolean), {
|
||||
detached: true,
|
||||
stdio: ['ignore', fs.openSync(logFile, 'w'), fs.openSync(logFile, 'w')]
|
||||
});
|
||||
|
||||
// Don't wait for the server to exit
|
||||
serverProcess.unref();
|
||||
|
||||
console.log(`Server started with PID ${serverProcess.pid}`);
|
||||
console.log(`Logs are being written to ${logFile}`);
|
||||
|
||||
// Wait a moment for the server to start
|
||||
setTimeout(() => {
|
||||
// Show the initial logs
|
||||
console.log('\nInitial server logs:');
|
||||
try {
|
||||
const initialLogs = execSync(`tail -n 20 ${logFile}`).toString();
|
||||
console.log(initialLogs || 'No logs yet');
|
||||
} catch (error) {
|
||||
console.log('No logs available yet');
|
||||
}
|
||||
|
||||
console.log('\nTo check logs later, run:');
|
||||
console.log(` node scripts/ai-helper.js check-logs`);
|
||||
console.log('To stop the server, run:');
|
||||
console.log(` node scripts/ai-helper.js stop-server`);
|
||||
|
||||
// For development mode, remind the user to access the application on port 7654
|
||||
if (env !== 'prod') {
|
||||
console.log('\nAccess the application at:');
|
||||
console.log(' http://localhost:7654');
|
||||
}
|
||||
}, 2000);
|
||||
} catch (error) {
|
||||
console.error('Error starting server:', error.message);
|
||||
process.exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
// Check the most recent logs
|
||||
function checkLogs(lines) {
|
||||
console.log(`Checking the most recent logs (${lines} lines)...`);
|
||||
|
||||
try {
|
||||
// Find the most recent log file
|
||||
const logDir = path.resolve(process.cwd(), 'logs');
|
||||
const logFiles = fs.readdirSync(logDir)
|
||||
.filter(file => file.endsWith('.log'))
|
||||
.map(file => ({
|
||||
name: file,
|
||||
time: fs.statSync(path.join(logDir, file)).mtime.getTime()
|
||||
}))
|
||||
.sort((a, b) => b.time - a.time);
|
||||
|
||||
if (logFiles.length === 0) {
|
||||
console.log('No log files found');
|
||||
return;
|
||||
}
|
||||
|
||||
const recentLogFile = path.join(logDir, logFiles[0].name);
|
||||
console.log(`Most recent log file: ${recentLogFile}`);
|
||||
|
||||
// Show the logs
|
||||
const logs = execSync(`tail -n ${lines} ${recentLogFile}`).toString();
|
||||
console.log('\nRecent logs:');
|
||||
console.log(logs || 'No logs found');
|
||||
} catch (error) {
|
||||
console.error('Error checking logs:', error.message);
|
||||
}
|
||||
}
|
||||
|
||||
// Check cluster-related logs
|
||||
function checkClusterLogs(lines) {
|
||||
console.log('Checking cluster-related logs...');
|
||||
|
||||
try {
|
||||
// Find the most recent log file
|
||||
const logDir = path.resolve(process.cwd(), 'logs');
|
||||
const logFiles = fs.readdirSync(logDir)
|
||||
.filter(file => file.endsWith('.log'))
|
||||
.map(file => ({
|
||||
name: file,
|
||||
time: fs.statSync(path.join(logDir, file)).mtime.getTime()
|
||||
}))
|
||||
.sort((a, b) => b.time - a.time);
|
||||
|
||||
if (logFiles.length === 0) {
|
||||
console.log('No log files found');
|
||||
return;
|
||||
}
|
||||
|
||||
const recentLogFile = path.join(logDir, logFiles[0].name);
|
||||
console.log(`Searching in: ${recentLogFile}`);
|
||||
|
||||
// Search for cluster-related logs
|
||||
const grepCommand = `grep -i "cluster\\|clusterMode\\|autoDetectCluster" ${recentLogFile} | tail -n ${lines}`;
|
||||
try {
|
||||
const clusterLogs = execSync(grepCommand).toString();
|
||||
console.log('\nCluster-related logs:');
|
||||
console.log(clusterLogs || 'No cluster-related logs found');
|
||||
} catch (error) {
|
||||
// grep returns exit code 1 if no matches found
|
||||
console.log('No cluster-related logs found');
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('Error checking cluster logs:', error.message);
|
||||
}
|
||||
}
|
||||
|
||||
// Check if the server is running
|
||||
function checkStatus() {
|
||||
console.log('Checking server status...');
|
||||
|
||||
try {
|
||||
const psOutput = execSync('ps aux | grep "[n]ode.*server.js\\|[n]ode.*start.js"').toString();
|
||||
console.log('\nRunning server processes:');
|
||||
console.log(psOutput || 'No server processes found');
|
||||
|
||||
// Check if the frontend is responding
|
||||
try {
|
||||
console.log('\nChecking frontend on port 7654:');
|
||||
// Just check if we get a 200 response, don't try to parse the HTML
|
||||
const frontendResponse = execSync('curl -s -o /dev/null -w "%{http_code}" http://localhost:7654/').toString();
|
||||
if (frontendResponse.trim() === '200') {
|
||||
console.log('✅ Frontend is responding (HTTP 200)');
|
||||
} else {
|
||||
console.log(`❌ Frontend returned HTTP ${frontendResponse}`);
|
||||
}
|
||||
} catch (error) {
|
||||
console.log('❌ Frontend is not responding');
|
||||
}
|
||||
|
||||
// Check if the mock server is responding (in dev mode)
|
||||
try {
|
||||
console.log('\nChecking mock server on port 7656:');
|
||||
const mockResponse = execSync('curl -s -o /dev/null -w "%{http_code}" http://localhost:7656/').toString();
|
||||
if (mockResponse.trim() === '200') {
|
||||
console.log('✅ Mock server is responding (HTTP 200)');
|
||||
} else {
|
||||
console.log(`❌ Mock server returned HTTP ${mockResponse}`);
|
||||
}
|
||||
} catch (error) {
|
||||
console.log('❌ Mock server is not responding (this is normal in production mode)');
|
||||
}
|
||||
|
||||
// Check if the API is responding
|
||||
try {
|
||||
console.log('\nChecking API on port 7654 (via frontend proxy):');
|
||||
const apiResponse = execSync('curl -s http://localhost:7654/api/nodes | head -n 5').toString();
|
||||
if (apiResponse && apiResponse.includes('nodes')) {
|
||||
console.log('✅ API is responding via frontend proxy');
|
||||
console.log('First few lines of API response:');
|
||||
console.log(apiResponse);
|
||||
} else {
|
||||
console.log('❌ API response via frontend proxy is invalid');
|
||||
console.log(apiResponse);
|
||||
}
|
||||
} catch (error) {
|
||||
console.log('❌ API is not responding via frontend proxy');
|
||||
|
||||
// Try direct API access on port 7656 (for development mode)
|
||||
try {
|
||||
console.log('\nTrying direct API access on port 7656:');
|
||||
const directApiResponse = execSync('curl -s http://localhost:7656/api/nodes | head -n 5').toString();
|
||||
console.log(directApiResponse);
|
||||
console.log('✅ API is responding directly on port 7656');
|
||||
} catch (error) {
|
||||
console.log('❌ API is not responding on port 7656 either');
|
||||
}
|
||||
}
|
||||
|
||||
console.log('\nServer information:');
|
||||
console.log('- The frontend is running on port 7654 (accessible in browser)');
|
||||
console.log('- The backend API is running on port 7656 (internal only)');
|
||||
console.log('- The mock data server is running on port 7656 (in development mode)');
|
||||
|
||||
} catch (error) {
|
||||
console.log('No server processes found');
|
||||
}
|
||||
}
|
||||
|
||||
// Stop the server
|
||||
function stopServer() {
|
||||
console.log('Stopping server processes...');
|
||||
|
||||
try {
|
||||
// Kill processes by pattern
|
||||
execSync('pkill -f "node.*server.js\\|node.*start.js\\|vite"');
|
||||
console.log('Server processes stopped by pattern');
|
||||
} catch (error) {
|
||||
console.log('No matching processes found to stop by pattern');
|
||||
}
|
||||
|
||||
try {
|
||||
// Kill processes by port
|
||||
execSync('npx kill-port 7654 7656 3000');
|
||||
console.log('Processes on ports 7654, 7656, and 3000 stopped');
|
||||
} catch (error) {
|
||||
console.log('No processes found on ports 7654, 7656, or 3000');
|
||||
}
|
||||
|
||||
console.log('All server processes have been stopped');
|
||||
}
|
||||
|
||||
// Verify the current environment configuration
|
||||
function verifyConfig() {
|
||||
console.log('Verifying environment configuration...');
|
||||
|
||||
try {
|
||||
execSync('node scripts/verify-cluster-config.js', { stdio: 'inherit' });
|
||||
} catch (error) {
|
||||
console.error('Error verifying configuration:', error.message);
|
||||
process.exit(1);
|
||||
}
|
||||
}
|
||||
Executable
+111
@@ -0,0 +1,111 @@
|
||||
#!/usr/bin/env node
|
||||
|
||||
/**
|
||||
* Check Configuration Script
|
||||
*
|
||||
* This script checks if the Proxmox configuration is valid before running in production mode.
|
||||
* If the configuration is missing or invalid, it provides guidance to the user.
|
||||
*/
|
||||
|
||||
const fs = require('fs');
|
||||
const path = require('path');
|
||||
const readline = require('readline');
|
||||
const dotenv = require('dotenv');
|
||||
|
||||
// Load environment variables
|
||||
dotenv.config();
|
||||
|
||||
// Path to the .env file
|
||||
const envFilePath = path.join(process.cwd(), '.env');
|
||||
|
||||
// Check if .env file exists
|
||||
if (!fs.existsSync(envFilePath)) {
|
||||
console.error('\x1b[31mError: .env file not found.\x1b[0m');
|
||||
console.log('Please create a .env file with your Proxmox configuration.');
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
// Check if Proxmox configuration is valid
|
||||
// We'll check for the default configuration or additional nodes
|
||||
const defaultVars = [
|
||||
'PROXMOX_HOST',
|
||||
'PROXMOX_NODE',
|
||||
'PROXMOX_TOKEN_ID',
|
||||
'PROXMOX_TOKEN_SECRET'
|
||||
];
|
||||
|
||||
// Check if we have the default configuration
|
||||
const hasDefaultConfig = defaultVars.every(varName =>
|
||||
process.env[varName] && process.env[varName] !== 'your-token-secret-here' && process.env[varName] !== 'your-token-secret'
|
||||
);
|
||||
|
||||
// Check for additional nodes (with numeric suffix)
|
||||
let hasAdditionalNodes = false;
|
||||
for (let i = 2; i <= 10; i++) {
|
||||
const hostKey = `PROXMOX_HOST_${i}`;
|
||||
const nodeNameKey = `PROXMOX_NODE_${i}`;
|
||||
const tokenIdKey = `PROXMOX_TOKEN_ID_${i}`;
|
||||
const tokenSecretKey = `PROXMOX_TOKEN_SECRET_${i}`;
|
||||
|
||||
const hasNodeConfig = [hostKey, nodeNameKey, tokenIdKey, tokenSecretKey].every(key =>
|
||||
process.env[key] && process.env[key] !== 'your-token-secret-here' && process.env[key] !== 'your-token-secret'
|
||||
);
|
||||
|
||||
if (hasNodeConfig) {
|
||||
hasAdditionalNodes = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// If mock data is enabled, we don't need Proxmox configuration
|
||||
const mockDataEnabled = process.env.USE_MOCK_DATA === 'true' || process.env.MOCK_DATA_ENABLED === 'true';
|
||||
|
||||
if (!hasDefaultConfig && !hasAdditionalNodes && !mockDataEnabled) {
|
||||
console.error('\x1b[31mError: Missing or invalid Proxmox configuration.\x1b[0m');
|
||||
console.log('You need to configure at least one Proxmox node:');
|
||||
console.log('\nDefault node configuration:');
|
||||
defaultVars.forEach(varName => {
|
||||
console.log(` - ${varName}`);
|
||||
});
|
||||
|
||||
console.log('\nYou have two options:');
|
||||
console.log('1. Update your .env file with valid Proxmox details');
|
||||
console.log('2. Use development mode with mock data instead');
|
||||
|
||||
const rl = readline.createInterface({
|
||||
input: process.stdin,
|
||||
output: process.stdout
|
||||
});
|
||||
|
||||
rl.question('\nWould you like to continue with mock data instead? (y/n): ', (answer) => {
|
||||
rl.close();
|
||||
|
||||
if (answer.toLowerCase() === 'y' || answer.toLowerCase() === 'yes') {
|
||||
console.log('\n\x1b[33mSwitching to development mode with mock data...\x1b[0m');
|
||||
|
||||
// Update the current .env file with development settings
|
||||
let envContent = fs.readFileSync(envFilePath, 'utf8');
|
||||
envContent = envContent.replace(/NODE_ENV=.*/g, 'NODE_ENV=development');
|
||||
envContent = envContent.replace(/USE_MOCK_DATA=.*/g, 'USE_MOCK_DATA=true');
|
||||
envContent = envContent.replace(/MOCK_DATA_ENABLED=.*/g, 'MOCK_DATA_ENABLED=true');
|
||||
fs.writeFileSync(envFilePath, envContent);
|
||||
console.log('\x1b[32mUpdated .env file with development settings and mock data enabled.\x1b[0m');
|
||||
|
||||
console.log('\x1b[33mPlease run "npm run dev" to start in development mode.\x1b[0m');
|
||||
process.exit(0);
|
||||
} else {
|
||||
console.log('\nPlease update your .env file with valid Proxmox configuration and try again.');
|
||||
process.exit(1);
|
||||
}
|
||||
});
|
||||
} else {
|
||||
// Configuration is valid
|
||||
if (hasDefaultConfig) {
|
||||
console.log('\x1b[32mDefault Proxmox configuration is valid. Continuing with production mode.\x1b[0m');
|
||||
} else if (hasAdditionalNodes) {
|
||||
console.log('\x1b[32mAdditional Proxmox node configuration is valid. Continuing with production mode.\x1b[0m');
|
||||
} else if (mockDataEnabled) {
|
||||
console.log('\x1b[32mMock data is enabled. No Proxmox configuration needed. Continuing with production mode.\x1b[0m');
|
||||
}
|
||||
process.exit(0);
|
||||
}
|
||||
@@ -0,0 +1,236 @@
|
||||
#!/usr/bin/env node
|
||||
|
||||
/**
|
||||
* Script to check connections between frontend, backend, and mock server
|
||||
* Usage: node scripts/check-connections.js
|
||||
*/
|
||||
|
||||
const http = require('http');
|
||||
const net = require('net');
|
||||
const fs = require('fs');
|
||||
const path = require('path');
|
||||
const dotenv = require('dotenv');
|
||||
|
||||
// Load environment variables
|
||||
dotenv.config();
|
||||
|
||||
console.log('Pulse Connection Checker');
|
||||
console.log('=======================');
|
||||
console.log(`Environment: ${process.env.NODE_ENV || 'Not set'}`);
|
||||
console.log(`USE_MOCK_DATA: ${process.env.USE_MOCK_DATA || 'Not set'}`);
|
||||
console.log(`MOCK_DATA_ENABLED: ${process.env.MOCK_DATA_ENABLED || 'Not set'}`);
|
||||
|
||||
// Check if a port is in use
|
||||
function checkPort(port) {
|
||||
return new Promise((resolve) => {
|
||||
const server = net.createServer();
|
||||
|
||||
server.once('error', (err) => {
|
||||
if (err.code === 'EADDRINUSE') {
|
||||
resolve(true); // Port is in use
|
||||
} else {
|
||||
resolve(false);
|
||||
}
|
||||
});
|
||||
|
||||
server.once('listening', () => {
|
||||
server.close();
|
||||
resolve(false); // Port is not in use
|
||||
});
|
||||
|
||||
server.listen(port);
|
||||
});
|
||||
}
|
||||
|
||||
// Check if a server is responding on a given port
|
||||
function checkServer(host, port, path = '/') {
|
||||
return new Promise((resolve) => {
|
||||
const req = http.request({
|
||||
host,
|
||||
port,
|
||||
path,
|
||||
method: 'GET',
|
||||
timeout: 3000
|
||||
}, (res) => {
|
||||
let data = '';
|
||||
res.on('data', (chunk) => {
|
||||
data += chunk;
|
||||
});
|
||||
res.on('end', () => {
|
||||
resolve({
|
||||
status: res.statusCode,
|
||||
data: data.substring(0, 100) // Just get the first 100 chars
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
req.on('error', (err) => {
|
||||
resolve({
|
||||
status: 'error',
|
||||
error: err.message
|
||||
});
|
||||
});
|
||||
|
||||
req.on('timeout', () => {
|
||||
req.destroy();
|
||||
resolve({
|
||||
status: 'timeout',
|
||||
error: 'Request timed out'
|
||||
});
|
||||
});
|
||||
|
||||
req.end();
|
||||
});
|
||||
}
|
||||
|
||||
// Check frontend socket.js file
|
||||
function checkFrontendSocketConfig() {
|
||||
const socketJsPath = path.join(process.cwd(), 'frontend', 'src', 'hooks', 'useSocket.js');
|
||||
|
||||
if (!fs.existsSync(socketJsPath)) {
|
||||
return {
|
||||
exists: false,
|
||||
error: 'useSocket.js file not found'
|
||||
};
|
||||
}
|
||||
|
||||
const content = fs.readFileSync(socketJsPath, 'utf8');
|
||||
|
||||
// Check if we're using the dynamic port selection
|
||||
if (content.includes('useMockData ?')) {
|
||||
// We're using dynamic port selection
|
||||
const isDevelopment = process.env.NODE_ENV === 'development';
|
||||
const useMockData = process.env.USE_MOCK_DATA === 'true' || process.env.MOCK_DATA_ENABLED === 'true';
|
||||
|
||||
if (isDevelopment) {
|
||||
const port = useMockData ? '7656' : '7654';
|
||||
return {
|
||||
exists: true,
|
||||
port,
|
||||
isDynamic: true,
|
||||
useMockData
|
||||
};
|
||||
} else {
|
||||
// In production, we use window.location.origin
|
||||
return {
|
||||
exists: true,
|
||||
port: '7654', // Production always uses 7654
|
||||
isDynamic: true,
|
||||
useMockData: false
|
||||
};
|
||||
}
|
||||
} else {
|
||||
// Extract the port from the socketUrl (old method)
|
||||
const portMatch = content.match(/socketUrl\s*=\s*`http:\/\/\${currentHost}:(\d+)`/);
|
||||
const port = portMatch ? portMatch[1] : null;
|
||||
|
||||
return {
|
||||
exists: true,
|
||||
port,
|
||||
isDynamic: false
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
async function main() {
|
||||
// Check if backend server is running (port 7654)
|
||||
const backendRunning = await checkPort(7654);
|
||||
console.log(`\nBackend server (port 7654): ${backendRunning ? 'RUNNING' : 'NOT RUNNING'}`);
|
||||
|
||||
if (backendRunning) {
|
||||
const backendResponse = await checkServer('localhost', 7654);
|
||||
console.log(` Response: ${typeof backendResponse.status === 'number' ? backendResponse.status : backendResponse.status}`);
|
||||
if (backendResponse.error) {
|
||||
console.log(` Error: ${backendResponse.error}`);
|
||||
}
|
||||
}
|
||||
|
||||
// Check if mock server is running (port 7656)
|
||||
const mockRunning = await checkPort(7656);
|
||||
console.log(`\nMock server (port 7656): ${mockRunning ? 'RUNNING' : 'NOT RUNNING'}`);
|
||||
|
||||
if (mockRunning) {
|
||||
const mockResponse = await checkServer('localhost', 7656);
|
||||
console.log(` Response: ${typeof mockResponse.status === 'number' ? mockResponse.status : mockResponse.status}`);
|
||||
if (mockResponse.error) {
|
||||
console.log(` Error: ${mockResponse.error}`);
|
||||
}
|
||||
}
|
||||
|
||||
// Check frontend socket configuration
|
||||
const socketConfig = checkFrontendSocketConfig();
|
||||
console.log('\nFrontend Socket Configuration:');
|
||||
if (socketConfig.exists) {
|
||||
if (socketConfig.isDynamic) {
|
||||
console.log(' Dynamic port selection: ENABLED');
|
||||
console.log(` Current environment: ${process.env.NODE_ENV || 'Not set'}`);
|
||||
console.log(` Mock data enabled: ${socketConfig.useMockData ? 'Yes' : 'No'}`);
|
||||
console.log(` Will connect to port: ${socketConfig.port}`);
|
||||
|
||||
if (socketConfig.port === '7654') {
|
||||
console.log(' Frontend is configured to connect to the BACKEND server');
|
||||
} else if (socketConfig.port === '7656') {
|
||||
console.log(' Frontend is configured to connect to the MOCK server');
|
||||
}
|
||||
} else {
|
||||
console.log(` Socket port: ${socketConfig.port || 'Not found'}`);
|
||||
if (socketConfig.port === '7654') {
|
||||
console.log(' Frontend is configured to connect to the BACKEND server');
|
||||
} else if (socketConfig.port === '7656') {
|
||||
console.log(' Frontend is configured to connect to the MOCK server');
|
||||
} else {
|
||||
console.log(` Frontend is configured to connect to an UNKNOWN port: ${socketConfig.port}`);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
console.log(` Error: ${socketConfig.error}`);
|
||||
}
|
||||
|
||||
// Check if frontend dev server is running
|
||||
const frontendRunning = await checkPort(5173);
|
||||
console.log(`\nFrontend dev server (port 5173): ${!frontendRunning ? 'RUNNING' : 'NOT RUNNING'}`);
|
||||
|
||||
// Summary and recommendations
|
||||
console.log('\nSummary:');
|
||||
|
||||
if (process.env.NODE_ENV === 'production') {
|
||||
console.log('- Running in PRODUCTION mode');
|
||||
|
||||
if (process.env.USE_MOCK_DATA === 'true' || process.env.MOCK_DATA_ENABLED === 'true') {
|
||||
console.log(' WARNING: Mock data is enabled in production mode!');
|
||||
}
|
||||
|
||||
if (socketConfig.port === '7656') {
|
||||
console.log(' WARNING: Frontend is configured to connect to the mock server (port 7656) but you are in production mode!');
|
||||
console.log(' SOLUTION: Edit frontend/src/hooks/useSocket.js to use port 7654 instead of 7656');
|
||||
}
|
||||
} else {
|
||||
console.log('- Running in DEVELOPMENT mode');
|
||||
|
||||
if (process.env.USE_MOCK_DATA !== 'true' && process.env.MOCK_DATA_ENABLED !== 'true') {
|
||||
console.log(' NOTE: Mock data is disabled in development mode');
|
||||
}
|
||||
|
||||
if (socketConfig.port === '7654' && (process.env.USE_MOCK_DATA === 'true' || process.env.MOCK_DATA_ENABLED === 'true')) {
|
||||
console.log(' WARNING: Frontend is configured to connect to the backend server (port 7654) but mock data is enabled!');
|
||||
console.log(' SOLUTION: Edit frontend/src/hooks/useSocket.js to use port 7656 instead of 7654');
|
||||
}
|
||||
}
|
||||
|
||||
if (backendRunning && mockRunning && socketConfig.port === '7656' && process.env.NODE_ENV === 'production') {
|
||||
console.log('\nPROBLEM DETECTED: You are running in production mode but the frontend is connecting to the mock server!');
|
||||
console.log('SOLUTION: Kill all servers, edit frontend/src/hooks/useSocket.js to use port 7654, and restart with npm run prod');
|
||||
}
|
||||
|
||||
if (!backendRunning && process.env.NODE_ENV === 'production') {
|
||||
console.log('\nPROBLEM DETECTED: Production backend server is not running!');
|
||||
console.log('SOLUTION: Start the production server with npm run prod');
|
||||
}
|
||||
|
||||
if (!mockRunning && (process.env.USE_MOCK_DATA === 'true' || process.env.MOCK_DATA_ENABLED === 'true')) {
|
||||
console.log('\nPROBLEM DETECTED: Mock data is enabled but the mock server is not running!');
|
||||
console.log('SOLUTION: Start the mock server with npm run mock');
|
||||
}
|
||||
}
|
||||
|
||||
main().catch(console.error);
|
||||
@@ -0,0 +1,71 @@
|
||||
/**
|
||||
* Script to clear persisted data files when switching between environments
|
||||
* This script is called by the start-dev.sh and start-prod.sh scripts
|
||||
*/
|
||||
|
||||
const fs = require('fs');
|
||||
const path = require('path');
|
||||
|
||||
// Directories to clear
|
||||
const dataDirs = [
|
||||
'data',
|
||||
'logs',
|
||||
'tmp'
|
||||
];
|
||||
|
||||
// Function to clear a directory
|
||||
function clearDirectory(dirPath) {
|
||||
if (!fs.existsSync(dirPath)) {
|
||||
console.log(`Directory ${dirPath} does not exist, creating it...`);
|
||||
fs.mkdirSync(dirPath, { recursive: true });
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
const files = fs.readdirSync(dirPath);
|
||||
|
||||
for (const file of files) {
|
||||
const filePath = path.join(dirPath, file);
|
||||
const stat = fs.statSync(filePath);
|
||||
|
||||
if (stat.isDirectory()) {
|
||||
// Skip .git and node_modules directories
|
||||
if (file !== '.git' && file !== 'node_modules') {
|
||||
clearDirectory(filePath);
|
||||
}
|
||||
} else {
|
||||
// Delete the file
|
||||
fs.unlinkSync(filePath);
|
||||
console.log(`Deleted file: ${filePath}`);
|
||||
}
|
||||
}
|
||||
|
||||
console.log(`Cleared directory: ${dirPath}`);
|
||||
} catch (error) {
|
||||
console.error(`Error clearing directory ${dirPath}:`, error.message);
|
||||
}
|
||||
}
|
||||
|
||||
// Main function
|
||||
function clearData() {
|
||||
console.log('Clearing persisted data files...');
|
||||
|
||||
// Get the project root directory
|
||||
const rootDir = path.resolve(__dirname, '..');
|
||||
|
||||
// Clear each directory
|
||||
for (const dir of dataDirs) {
|
||||
const dirPath = path.join(rootDir, dir);
|
||||
clearDirectory(dirPath);
|
||||
}
|
||||
|
||||
console.log('Data clearing complete.');
|
||||
}
|
||||
|
||||
// Run the script if called directly
|
||||
if (require.main === module) {
|
||||
clearData();
|
||||
}
|
||||
|
||||
// Export for use in other scripts
|
||||
module.exports = clearData;
|
||||
Executable
+100
@@ -0,0 +1,100 @@
|
||||
#!/usr/bin/env node
|
||||
|
||||
/**
|
||||
* Script to configure environment variables in .env file
|
||||
* Usage: node scripts/configure-env.js [prod|dev]
|
||||
*/
|
||||
|
||||
const fs = require('fs');
|
||||
const path = require('path');
|
||||
const dotenv = require('dotenv');
|
||||
|
||||
// Get the environment from command line arguments
|
||||
const args = process.argv.slice(2);
|
||||
const env = args[0] || 'dev'; // Default to dev if no argument provided
|
||||
|
||||
// Path to the .env file
|
||||
const envFilePath = path.resolve(process.cwd(), '.env');
|
||||
|
||||
// Check if .env file exists
|
||||
if (!fs.existsSync(envFilePath)) {
|
||||
console.error('Error: .env file not found. Please create one by copying .env.example');
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
// Load current .env file
|
||||
const currentEnv = dotenv.parse(fs.readFileSync(envFilePath));
|
||||
|
||||
// Define environment-specific values
|
||||
const envConfigs = {
|
||||
prod: {
|
||||
NODE_ENV: 'production',
|
||||
LOG_LEVEL: 'info',
|
||||
USE_MOCK_DATA: 'false',
|
||||
MOCK_DATA_ENABLED: 'false',
|
||||
PROXMOX_AUTO_DETECT_CLUSTER: 'true',
|
||||
PROXMOX_CLUSTER_MODE: 'true',
|
||||
MOCK_CLUSTER_ENABLED: 'false',
|
||||
DOCKERFILE: 'docker/Dockerfile'
|
||||
},
|
||||
'prod:no-cluster': {
|
||||
NODE_ENV: 'production',
|
||||
LOG_LEVEL: 'info',
|
||||
USE_MOCK_DATA: 'false',
|
||||
MOCK_DATA_ENABLED: 'false',
|
||||
PROXMOX_AUTO_DETECT_CLUSTER: 'false',
|
||||
PROXMOX_CLUSTER_MODE: 'false',
|
||||
MOCK_CLUSTER_ENABLED: 'false',
|
||||
DOCKERFILE: 'docker/Dockerfile'
|
||||
},
|
||||
dev: {
|
||||
NODE_ENV: 'development',
|
||||
LOG_LEVEL: 'info',
|
||||
USE_MOCK_DATA: 'true',
|
||||
MOCK_DATA_ENABLED: 'true',
|
||||
PROXMOX_AUTO_DETECT_CLUSTER: 'true',
|
||||
PROXMOX_CLUSTER_MODE: 'true',
|
||||
MOCK_CLUSTER_ENABLED: 'true',
|
||||
DOCKERFILE: 'docker/Dockerfile.dev'
|
||||
},
|
||||
'dev:no-cluster': {
|
||||
NODE_ENV: 'development',
|
||||
LOG_LEVEL: 'info',
|
||||
USE_MOCK_DATA: 'true',
|
||||
MOCK_DATA_ENABLED: 'true',
|
||||
PROXMOX_AUTO_DETECT_CLUSTER: 'false',
|
||||
PROXMOX_CLUSTER_MODE: 'false',
|
||||
MOCK_CLUSTER_ENABLED: 'false',
|
||||
DOCKERFILE: 'docker/Dockerfile.dev'
|
||||
}
|
||||
};
|
||||
|
||||
// Get the config for the specified environment
|
||||
const config = envConfigs[env];
|
||||
if (!config) {
|
||||
console.error(`Error: Unknown environment "${env}". Use "prod", "prod:no-cluster", "dev", or "dev:no-cluster".`);
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
// Update the .env file
|
||||
let envContent = fs.readFileSync(envFilePath, 'utf8');
|
||||
|
||||
// Update each environment variable
|
||||
Object.entries(config).forEach(([key, value]) => {
|
||||
// Check if the key exists in the .env file
|
||||
const regex = new RegExp(`^${key}=.*$`, 'm');
|
||||
if (regex.test(envContent)) {
|
||||
// Replace the existing value
|
||||
envContent = envContent.replace(regex, `${key}=${value}`);
|
||||
console.log(`Updated ${key}=${value}`);
|
||||
} else {
|
||||
// Add the key if it doesn't exist
|
||||
envContent += `\n${key}=${value}`;
|
||||
console.log(`Added ${key}=${value}`);
|
||||
}
|
||||
});
|
||||
|
||||
// Write the updated content back to the .env file
|
||||
fs.writeFileSync(envFilePath, envContent);
|
||||
|
||||
console.log(`\nEnvironment configured for ${env === 'prod' ? 'production' : env === 'prod:no-cluster' ? 'production (no cluster)' : env === 'dev' ? 'development' : 'development (no cluster)'}`);
|
||||
@@ -12,9 +12,9 @@ RED='\033[0;31m'
|
||||
NC='\033[0m' # No Color
|
||||
|
||||
# Port configuration
|
||||
MOCK_PORT=7655
|
||||
PROXY_PORT=7656
|
||||
FRONTEND_PORT=3000
|
||||
MOCK_PORT=7656
|
||||
PROXY_PORT=7657
|
||||
FRONTEND_PORT=7654
|
||||
|
||||
echo -e "${BLUE}"
|
||||
echo "╔════════════════════════════════════════════════════════════╗"
|
||||
|
||||
@@ -22,8 +22,8 @@ const io = new SocketServer(server, {
|
||||
});
|
||||
|
||||
// Configuration
|
||||
const PROXY_PORT = 7656;
|
||||
const BACKEND_PORT = 7655;
|
||||
const PROXY_PORT = 7657;
|
||||
const BACKEND_PORT = 7656;
|
||||
const BACKEND_URL = `http://localhost:${BACKEND_PORT}`;
|
||||
const LOG_FILE = './socket-debug.log';
|
||||
|
||||
|
||||
@@ -29,14 +29,14 @@ try {
|
||||
|
||||
// Backend ports
|
||||
try {
|
||||
execSync('npx kill-port 7654 7655', { stdio: 'inherit' });
|
||||
execSync('npx kill-port 7654 7656', { stdio: 'inherit' });
|
||||
} catch (error) {
|
||||
console.log('No processes using backend ports.');
|
||||
}
|
||||
|
||||
// Frontend ports
|
||||
try {
|
||||
execSync('npx kill-port 3000 9513', { stdio: 'inherit' });
|
||||
execSync('npx kill-port 7654 9513', { stdio: 'inherit' });
|
||||
} catch (error) {
|
||||
console.log('No processes using frontend ports.');
|
||||
}
|
||||
|
||||
Executable
+107
@@ -0,0 +1,107 @@
|
||||
#!/bin/bash
|
||||
|
||||
# Make script executable if it isn't already
|
||||
chmod +x "$0"
|
||||
|
||||
# Default values
|
||||
BUILD=false
|
||||
RUN=false
|
||||
DETACHED=false
|
||||
CLEANUP=false
|
||||
HELP=false
|
||||
|
||||
# Parse command line arguments
|
||||
while [[ $# -gt 0 ]]; do
|
||||
case "$1" in
|
||||
--build)
|
||||
BUILD=true
|
||||
shift
|
||||
;;
|
||||
--run)
|
||||
RUN=true
|
||||
shift
|
||||
;;
|
||||
--detached)
|
||||
DETACHED=true
|
||||
shift
|
||||
;;
|
||||
--cleanup)
|
||||
CLEANUP=true
|
||||
shift
|
||||
;;
|
||||
--help)
|
||||
HELP=true
|
||||
shift
|
||||
;;
|
||||
*)
|
||||
echo "Unknown option: $1"
|
||||
HELP=true
|
||||
shift
|
||||
;;
|
||||
esac
|
||||
done
|
||||
|
||||
# Display help
|
||||
if [ "$HELP" = true ]; then
|
||||
echo "Usage: $0 [options]"
|
||||
echo "Options:"
|
||||
echo " --build Build the Docker image"
|
||||
echo " --run Run the Docker container"
|
||||
echo " --detached Run in detached mode (background)"
|
||||
echo " --cleanup Remove existing containers and images"
|
||||
echo " --help Display this help message"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
# Ensure we're in the project root directory
|
||||
if [ ! -f "docker-compose.yml" ]; then
|
||||
echo "Error: docker-compose.yml not found. Please run this script from the project root directory."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Ensure .env file exists
|
||||
if [ ! -f ".env" ]; then
|
||||
if [ -f ".env.example" ]; then
|
||||
echo "Creating .env file from .env.example..."
|
||||
cp .env.example .env
|
||||
else
|
||||
echo "Error: .env file not found and .env.example is missing."
|
||||
exit 1
|
||||
fi
|
||||
fi
|
||||
|
||||
# Cleanup if requested
|
||||
if [ "$CLEANUP" = true ]; then
|
||||
echo "Cleaning up Docker resources..."
|
||||
docker compose down --rmi all --volumes --remove-orphans
|
||||
exit 0
|
||||
fi
|
||||
|
||||
# Build if requested
|
||||
if [ "$BUILD" = true ]; then
|
||||
echo "Building Docker image..."
|
||||
docker compose build
|
||||
fi
|
||||
|
||||
# Run if requested
|
||||
if [ "$RUN" = true ]; then
|
||||
# Stop any existing containers
|
||||
echo "Stopping any existing containers..."
|
||||
docker compose down
|
||||
|
||||
# Run the container
|
||||
if [ "$DETACHED" = true ]; then
|
||||
echo "Starting container in detached mode..."
|
||||
docker compose up -d
|
||||
else
|
||||
echo "Starting container..."
|
||||
docker compose up
|
||||
fi
|
||||
fi
|
||||
|
||||
# If no action specified, show help
|
||||
if [ "$BUILD" = false ] && [ "$RUN" = false ] && [ "$CLEANUP" = false ]; then
|
||||
echo "No action specified. Use --build, --run, or --cleanup."
|
||||
echo "Run with --help for more information."
|
||||
exit 1
|
||||
fi
|
||||
Executable
+177
@@ -0,0 +1,177 @@
|
||||
#!/bin/bash
|
||||
|
||||
# Colors for output
|
||||
GREEN='\033[0;32m'
|
||||
YELLOW='\033[1;33m'
|
||||
RED='\033[0;31m'
|
||||
BLUE='\033[0;34m'
|
||||
NC='\033[0m' # No Color
|
||||
|
||||
# Function to check if a command exists
|
||||
command_exists() {
|
||||
command -v "$1" >/dev/null 2>&1
|
||||
}
|
||||
|
||||
# Function to print a section header
|
||||
print_header() {
|
||||
echo -e "\n${BLUE}==== $1 ====${NC}\n"
|
||||
}
|
||||
|
||||
# Function to print a success message
|
||||
print_success() {
|
||||
echo -e "${GREEN}✓ $1${NC}"
|
||||
}
|
||||
|
||||
# Function to print a warning message
|
||||
print_warning() {
|
||||
echo -e "${YELLOW}⚠ $1${NC}"
|
||||
}
|
||||
|
||||
# Function to print an error message
|
||||
print_error() {
|
||||
echo -e "${RED}✗ $1${NC}"
|
||||
}
|
||||
|
||||
# Function to print a step
|
||||
print_step() {
|
||||
echo -e "${BLUE}$1${NC}"
|
||||
}
|
||||
|
||||
# Welcome message
|
||||
clear
|
||||
echo -e "${BLUE}"
|
||||
echo " _____ _ _____ _ _ _ "
|
||||
echo " | __ \ | | |_ _| | | | | | "
|
||||
echo " | |__) | | |___ ___ | | _ __ ___| |_ __ _| | | ___ _ __ "
|
||||
echo " | ___/ | | / __|/ _ \ | | | '_ \/ __| __/ _\` | | |/ _ \ '__|"
|
||||
echo " | | | |_| \__ \ __/ _| |_| | | \__ \ || (_| | | | __/ | "
|
||||
echo " |_| \__,_|___/\___| |_____|_| |_|___/\__\__,_|_|_|\___|_| "
|
||||
echo -e "${NC}"
|
||||
echo -e "Welcome to the Pulse installation script!\n"
|
||||
|
||||
# Ask for installation type
|
||||
print_header "Installation Type"
|
||||
echo "Please select the type of installation:"
|
||||
echo "1) Production - connect to a real Proxmox server"
|
||||
echo "2) Development - use with mock data (no Proxmox server needed)"
|
||||
read -p "Enter your choice (1/2) [1]: " install_type
|
||||
install_type=${install_type:-1}
|
||||
|
||||
# Set environment variables based on installation type
|
||||
if [ "$install_type" = "1" ]; then
|
||||
# Production with real Proxmox
|
||||
NODE_ENV="production"
|
||||
USE_MOCK_DATA="false"
|
||||
MOCK_DATA_ENABLED="false"
|
||||
echo "Set up for production with real Proxmox server"
|
||||
elif [ "$install_type" = "2" ]; then
|
||||
# Development with mock data
|
||||
NODE_ENV="development"
|
||||
USE_MOCK_DATA="true"
|
||||
MOCK_DATA_ENABLED="true"
|
||||
echo "Set up for development with mock data"
|
||||
else
|
||||
print_error "Invalid choice. Exiting."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Check for Docker
|
||||
print_header "Checking System Requirements"
|
||||
if command_exists docker; then
|
||||
print_success "Docker is installed ($(docker --version))"
|
||||
else
|
||||
print_error "Docker is not installed. Please install Docker before continuing."
|
||||
echo "Visit https://docs.docker.com/get-docker/ for installation instructions."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Check for Docker Compose
|
||||
if command_exists docker-compose; then
|
||||
print_success "Docker Compose is installed ($(docker-compose --version))"
|
||||
elif docker compose version >/dev/null 2>&1; then
|
||||
print_success "Docker Compose plugin is installed ($(docker compose version))"
|
||||
else
|
||||
print_warning "Docker Compose is not installed. It's recommended for easier management."
|
||||
echo "Visit https://docs.docker.com/compose/install/ for installation instructions."
|
||||
fi
|
||||
|
||||
# Create .env file if it doesn't exist
|
||||
print_header "Environment Configuration"
|
||||
if [ -f ".env" ]; then
|
||||
print_warning "An existing .env file was found."
|
||||
read -p "Do you want to create a new one? This will overwrite the existing file. (y/n) [n]: " create_new_env
|
||||
create_new_env=${create_new_env:-n}
|
||||
else
|
||||
create_new_env="y"
|
||||
fi
|
||||
|
||||
if [ "$create_new_env" = "y" ] || [ "$create_new_env" = "Y" ]; then
|
||||
echo "Creating new .env file..."
|
||||
|
||||
# Copy the example file
|
||||
cp .env.example .env
|
||||
|
||||
# Update the .env file with the installation type
|
||||
sed -i.bak "s/NODE_ENV=.*/NODE_ENV=$NODE_ENV/" .env
|
||||
sed -i.bak "s/USE_MOCK_DATA=.*/USE_MOCK_DATA=$USE_MOCK_DATA/" .env
|
||||
sed -i.bak "s/MOCK_DATA_ENABLED=.*/MOCK_DATA_ENABLED=$MOCK_DATA_ENABLED/" .env
|
||||
rm -f .env.bak
|
||||
|
||||
print_success "Created new .env file with $NODE_ENV configuration"
|
||||
|
||||
# If using real Proxmox, ask for server details
|
||||
if [ "$install_type" = "1" ]; then
|
||||
print_step "Please enter your Proxmox server details:"
|
||||
|
||||
read -p "Proxmox Host URL (e.g., https://proxmox.local:8006): " proxmox_host
|
||||
read -p "Proxmox Node Name (e.g., pve): " proxmox_node
|
||||
read -p "Proxmox API Token ID (e.g., root@pam!pulse): " proxmox_token_id
|
||||
read -p "Proxmox API Token Secret: " proxmox_token_secret
|
||||
|
||||
# Update the .env file with Proxmox details if provided
|
||||
if [ -n "$proxmox_host" ]; then
|
||||
sed -i.bak "s|PROXMOX_HOST=.*|PROXMOX_HOST=$proxmox_host|" .env
|
||||
fi
|
||||
|
||||
if [ -n "$proxmox_node" ]; then
|
||||
sed -i.bak "s/PROXMOX_NODE=.*/PROXMOX_NODE=$proxmox_node/" .env
|
||||
fi
|
||||
|
||||
if [ -n "$proxmox_token_id" ]; then
|
||||
sed -i.bak "s/PROXMOX_TOKEN_ID=.*/PROXMOX_TOKEN_ID=$proxmox_token_id/" .env
|
||||
fi
|
||||
|
||||
if [ -n "$proxmox_token_secret" ]; then
|
||||
sed -i.bak "s/PROXMOX_TOKEN_SECRET=.*/PROXMOX_TOKEN_SECRET=$proxmox_token_secret/" .env
|
||||
fi
|
||||
|
||||
rm -f .env.bak
|
||||
print_success "Updated .env file with Proxmox configuration"
|
||||
fi
|
||||
else
|
||||
print_success "Using existing .env file"
|
||||
fi
|
||||
|
||||
# Ask if the user wants to run the setup script
|
||||
print_header "Setup"
|
||||
read -p "Do you want to run the application now? (y/n) [y]: " run_setup
|
||||
run_setup=${run_setup:-y}
|
||||
|
||||
if [ "$run_setup" = "y" ] || [ "$run_setup" = "Y" ]; then
|
||||
if [ "$install_type" = "1" ]; then
|
||||
echo "Starting Pulse with Proxmox connection..."
|
||||
npm run prod:docker
|
||||
else
|
||||
echo "Starting Pulse with mock data..."
|
||||
npm run dev:docker
|
||||
fi
|
||||
else
|
||||
echo -e "\nTo start Pulse later, run one of the following commands:"
|
||||
echo -e " - For production: ${GREEN}npm run prod:docker${NC}"
|
||||
echo -e " - For development with mock data: ${GREEN}npm run dev:docker${NC}"
|
||||
fi
|
||||
|
||||
print_header "Installation Complete"
|
||||
echo "Thank you for installing Pulse!"
|
||||
echo "Access the dashboard at http://localhost:7654"
|
||||
echo -e "For more information, see the ${BLUE}README.md${NC} file or visit ${BLUE}https://github.com/rcourtman/pulse${NC}"
|
||||
Executable
+238
@@ -0,0 +1,238 @@
|
||||
#!/usr/bin/env node
|
||||
|
||||
/**
|
||||
* Log Monitor Script
|
||||
*
|
||||
* This script provides real-time monitoring of application logs with filtering capabilities.
|
||||
* It makes troubleshooting easier by allowing you to focus on specific log types or components.
|
||||
*
|
||||
* Usage:
|
||||
* node scripts/monitor-logs.js [options]
|
||||
*
|
||||
* Options:
|
||||
* --level=<level> Filter by log level (error, warn, info, debug)
|
||||
* --component=<name> Filter by component name (e.g., ProxmoxClient, NodeManager)
|
||||
* --search=<text> Search for specific text in logs
|
||||
* --follow Follow log file in real-time (default: true)
|
||||
* --lines=<number> Number of lines to show initially (default: 50)
|
||||
* --file=<filename> Log file to monitor (default: latest combined log)
|
||||
* --color Use colored output (default: true)
|
||||
* --help Show this help message
|
||||
*
|
||||
* Examples:
|
||||
* node scripts/monitor-logs.js --level=error
|
||||
* node scripts/monitor-logs.js --component=ProxmoxClient
|
||||
* node scripts/monitor-logs.js --search=cluster
|
||||
* node scripts/monitor-logs.js --level=info --component=NodeManager
|
||||
*/
|
||||
|
||||
const fs = require('fs');
|
||||
const path = require('path');
|
||||
const { spawn } = require('child_process');
|
||||
const readline = require('readline');
|
||||
|
||||
// Parse command line arguments
|
||||
const args = process.argv.slice(2);
|
||||
const options = {
|
||||
level: getArgValue(args, '--level'),
|
||||
component: getArgValue(args, '--component'),
|
||||
search: getArgValue(args, '--search'),
|
||||
follow: getArgValue(args, '--follow') !== 'false',
|
||||
lines: parseInt(getArgValue(args, '--lines') || '50', 10),
|
||||
file: getArgValue(args, '--file'),
|
||||
color: getArgValue(args, '--color') !== 'false',
|
||||
help: args.includes('--help') || args.includes('-h')
|
||||
};
|
||||
|
||||
// Show help if requested
|
||||
if (options.help) {
|
||||
console.log(fs.readFileSync(__filename, 'utf8')
|
||||
.split('\n')
|
||||
.filter(line => line.startsWith(' *'))
|
||||
.map(line => line.substring(3))
|
||||
.join('\n'));
|
||||
process.exit(0);
|
||||
}
|
||||
|
||||
// Find the log directory
|
||||
const logDir = path.resolve(process.cwd(), 'logs');
|
||||
|
||||
// Find the most recent log file if not specified
|
||||
if (!options.file) {
|
||||
try {
|
||||
const logFiles = fs.readdirSync(logDir)
|
||||
.filter(file => file.startsWith('combined') && file.endsWith('.log'))
|
||||
.map(file => ({
|
||||
name: file,
|
||||
time: fs.statSync(path.join(logDir, file)).mtime.getTime()
|
||||
}))
|
||||
.sort((a, b) => b.time - a.time);
|
||||
|
||||
if (logFiles.length > 0) {
|
||||
options.file = logFiles[0].name;
|
||||
} else {
|
||||
options.file = 'combined.log';
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('Error finding log files:', error.message);
|
||||
options.file = 'combined.log';
|
||||
}
|
||||
}
|
||||
|
||||
const logFile = path.join(logDir, options.file);
|
||||
|
||||
// ANSI color codes
|
||||
const colors = {
|
||||
reset: '\x1b[0m',
|
||||
bright: '\x1b[1m',
|
||||
dim: '\x1b[2m',
|
||||
red: '\x1b[31m',
|
||||
green: '\x1b[32m',
|
||||
yellow: '\x1b[33m',
|
||||
blue: '\x1b[34m',
|
||||
magenta: '\x1b[35m',
|
||||
cyan: '\x1b[36m',
|
||||
white: '\x1b[37m',
|
||||
bgRed: '\x1b[41m',
|
||||
bgGreen: '\x1b[42m',
|
||||
bgYellow: '\x1b[43m',
|
||||
bgBlue: '\x1b[44m'
|
||||
};
|
||||
|
||||
// Color mapping for log levels
|
||||
const levelColors = {
|
||||
error: colors.red,
|
||||
warn: colors.yellow,
|
||||
info: colors.green,
|
||||
debug: colors.blue,
|
||||
silly: colors.magenta
|
||||
};
|
||||
|
||||
// Check if the log file exists
|
||||
if (!fs.existsSync(logFile)) {
|
||||
console.error(`Log file not found: ${logFile}`);
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
console.log(`Monitoring log file: ${logFile}`);
|
||||
console.log(`Filters: ${Object.entries(options)
|
||||
.filter(([key, value]) => ['level', 'component', 'search'].includes(key) && value)
|
||||
.map(([key, value]) => `${key}=${value}`)
|
||||
.join(', ') || 'none'}`);
|
||||
console.log('Press Ctrl+C to exit\n');
|
||||
|
||||
// Build the tail command
|
||||
const tailArgs = ['-n', options.lines.toString()];
|
||||
if (options.follow) {
|
||||
tailArgs.push('-f');
|
||||
}
|
||||
tailArgs.push(logFile);
|
||||
|
||||
// Start the tail process
|
||||
const tail = spawn('tail', tailArgs);
|
||||
|
||||
// Process each line of output
|
||||
tail.stdout.setEncoding('utf8');
|
||||
const rl = readline.createInterface({
|
||||
input: tail.stdout,
|
||||
terminal: false
|
||||
});
|
||||
|
||||
rl.on('line', (line) => {
|
||||
try {
|
||||
// Try to parse the line as JSON
|
||||
const logEntry = JSON.parse(line);
|
||||
|
||||
// Apply filters
|
||||
if (options.level && logEntry.level !== options.level) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (options.component &&
|
||||
(!logEntry.component || !logEntry.component.includes(options.component))) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (options.search &&
|
||||
!line.toLowerCase().includes(options.search.toLowerCase())) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Format the output
|
||||
let formattedLine = '';
|
||||
|
||||
if (options.color) {
|
||||
const levelColor = levelColors[logEntry.level] || colors.white;
|
||||
|
||||
// Timestamp
|
||||
formattedLine += `${colors.dim}${new Date(logEntry.timestamp).toISOString()}${colors.reset} `;
|
||||
|
||||
// Level
|
||||
formattedLine += `${levelColor}${logEntry.level.toUpperCase().padEnd(5)}${colors.reset} `;
|
||||
|
||||
// Component
|
||||
if (logEntry.component) {
|
||||
formattedLine += `${colors.cyan}[${logEntry.component}]${colors.reset} `;
|
||||
}
|
||||
|
||||
// Message
|
||||
formattedLine += logEntry.message;
|
||||
|
||||
// Highlight search term if specified
|
||||
if (options.search) {
|
||||
const regex = new RegExp(options.search, 'gi');
|
||||
formattedLine = formattedLine.replace(regex, match =>
|
||||
`${colors.bgYellow}${colors.bright}${match}${colors.reset}`);
|
||||
}
|
||||
|
||||
// Add metadata if present
|
||||
if (logEntry.meta && Object.keys(logEntry.meta).length > 0) {
|
||||
formattedLine += `\n${colors.dim}${JSON.stringify(logEntry.meta, null, 2)}${colors.reset}`;
|
||||
}
|
||||
} else {
|
||||
// Simple formatting without colors
|
||||
formattedLine = `${new Date(logEntry.timestamp).toISOString()} ${logEntry.level.toUpperCase().padEnd(5)} `;
|
||||
|
||||
if (logEntry.component) {
|
||||
formattedLine += `[${logEntry.component}] `;
|
||||
}
|
||||
|
||||
formattedLine += logEntry.message;
|
||||
|
||||
// Add metadata if present
|
||||
if (logEntry.meta && Object.keys(logEntry.meta).length > 0) {
|
||||
formattedLine += `\n${JSON.stringify(logEntry.meta, null, 2)}`;
|
||||
}
|
||||
}
|
||||
|
||||
console.log(formattedLine);
|
||||
} catch (error) {
|
||||
// If not JSON, just print the line as is
|
||||
if (options.search && !line.toLowerCase().includes(options.search.toLowerCase())) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (options.color && options.search) {
|
||||
const regex = new RegExp(options.search, 'gi');
|
||||
console.log(line.replace(regex, match =>
|
||||
`${colors.bgYellow}${colors.bright}${match}${colors.reset}`));
|
||||
} else {
|
||||
console.log(line);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
// Handle errors
|
||||
tail.stderr.on('data', (data) => {
|
||||
console.error(`Error: ${data}`);
|
||||
});
|
||||
|
||||
tail.on('close', (code) => {
|
||||
console.log(`Monitoring ended with code ${code}`);
|
||||
});
|
||||
|
||||
// Helper function to get argument value
|
||||
function getArgValue(args, name) {
|
||||
const arg = args.find(a => a.startsWith(`${name}=`));
|
||||
return arg ? arg.split('=')[1] : null;
|
||||
}
|
||||
Executable
+98
@@ -0,0 +1,98 @@
|
||||
#!/usr/bin/env node
|
||||
|
||||
/**
|
||||
* Run With Logs Script
|
||||
*
|
||||
* This script runs the application and monitors logs in a split terminal.
|
||||
* It makes it easier to see what's happening in the application in real-time.
|
||||
*
|
||||
* Usage:
|
||||
* node scripts/run-with-logs.js [dev|prod] [options]
|
||||
*
|
||||
* Options:
|
||||
* --search=<text> Search for specific text in logs
|
||||
* --level=<level> Filter by log level (error, warn, info, debug)
|
||||
* --component=<name> Filter by component name
|
||||
* --no-cluster Disable cluster mode
|
||||
* --help Show this help message
|
||||
*
|
||||
* Examples:
|
||||
* node scripts/run-with-logs.js dev
|
||||
* node scripts/run-with-logs.js prod --search=cluster
|
||||
* node scripts/run-with-logs.js dev --no-cluster
|
||||
*/
|
||||
|
||||
const { spawn } = require('child_process');
|
||||
const fs = require('fs');
|
||||
|
||||
// Parse command line arguments
|
||||
const args = process.argv.slice(2);
|
||||
const env = args[0] === 'prod' ? 'prod' : 'dev';
|
||||
const noCluster = args.includes('--no-cluster');
|
||||
const help = args.includes('--help') || args.includes('-h');
|
||||
|
||||
// Show help if requested
|
||||
if (help) {
|
||||
console.log(fs.readFileSync(__filename, 'utf8')
|
||||
.split('\n')
|
||||
.filter(line => line.startsWith(' *'))
|
||||
.map(line => line.substring(3))
|
||||
.join('\n'));
|
||||
process.exit(0);
|
||||
}
|
||||
|
||||
// Extract log options
|
||||
const logOptions = args
|
||||
.filter(arg => arg.startsWith('--') && !arg.startsWith('--no-'))
|
||||
.join(' ');
|
||||
|
||||
// Determine which npm script to run
|
||||
const npmScript = noCluster ? `${env}:no-cluster` : env;
|
||||
|
||||
console.log(`Starting application in ${env} mode${noCluster ? ' with cluster mode disabled' : ''}...`);
|
||||
|
||||
// Create a unique log file for this run
|
||||
const timestamp = new Date().toISOString().replace(/[:.]/g, '-');
|
||||
const logFile = `logs/app-${env}-${timestamp}.log`;
|
||||
|
||||
// Ensure logs directory exists
|
||||
if (!fs.existsSync('logs')) {
|
||||
fs.mkdirSync('logs');
|
||||
}
|
||||
|
||||
// Start the application and redirect output to the log file
|
||||
const app = spawn('npm', ['run', npmScript], {
|
||||
stdio: ['ignore', fs.openSync(logFile, 'w'), fs.openSync(logFile, 'w')],
|
||||
detached: true
|
||||
});
|
||||
|
||||
// Don't wait for the app to exit
|
||||
app.unref();
|
||||
|
||||
console.log(`Application started with PID ${app.pid}`);
|
||||
console.log(`Logs are being written to ${logFile}`);
|
||||
console.log('Starting log monitor...\n');
|
||||
|
||||
// Wait a moment for the app to start writing logs
|
||||
setTimeout(() => {
|
||||
// Start the log monitor
|
||||
const logMonitor = spawn('node', ['scripts/monitor-logs.js', `--file=${logFile.split('/')[1]}`, '--follow=true', ...logOptions.split(' ').filter(Boolean)], {
|
||||
stdio: 'inherit'
|
||||
});
|
||||
|
||||
// Handle log monitor exit
|
||||
logMonitor.on('exit', (code) => {
|
||||
console.log(`\nLog monitor exited with code ${code}`);
|
||||
console.log(`The application is still running with PID ${app.pid}`);
|
||||
console.log('To stop the application, run:');
|
||||
console.log(` kill ${app.pid}`);
|
||||
process.exit(0);
|
||||
});
|
||||
|
||||
// Handle SIGINT (Ctrl+C)
|
||||
process.on('SIGINT', () => {
|
||||
console.log('\nStopping application and log monitor...');
|
||||
process.kill(-app.pid, 'SIGINT');
|
||||
process.exit(0);
|
||||
});
|
||||
}, 1000);
|
||||
@@ -0,0 +1,98 @@
|
||||
@echo off
|
||||
setlocal
|
||||
|
||||
REM Stop any running Pulse Docker containers first
|
||||
echo Stopping any running Pulse Docker containers...
|
||||
where docker >nul 2>&1
|
||||
if %ERRORLEVEL% EQU 0 (
|
||||
for /f "tokens=*" %%i in ('docker ps -q --filter "name=pulse"') do (
|
||||
docker stop %%i
|
||||
)
|
||||
) else (
|
||||
echo Docker not found, skipping container cleanup...
|
||||
)
|
||||
|
||||
REM Kill any existing servers
|
||||
echo Killing any existing servers...
|
||||
taskkill /f /im "node.exe" /fi "WINDOWTITLE eq node dist/server.js" 2>nul
|
||||
call npx kill-port 7654 7656 3000
|
||||
|
||||
REM Clear any existing data files that might persist between sessions
|
||||
echo Clearing any persisted data from previous sessions...
|
||||
node scripts/clear-data.js
|
||||
|
||||
REM Set environment to development
|
||||
set NODE_ENV=development
|
||||
|
||||
REM Load environment variables from .env if it exists
|
||||
if exist .env (
|
||||
echo Loading environment from .env
|
||||
for /f "tokens=*" %%a in (.env) do (
|
||||
set "%%a"
|
||||
)
|
||||
)
|
||||
|
||||
REM Override with development settings
|
||||
set USE_MOCK_DATA=true
|
||||
set MOCK_DATA_ENABLED=true
|
||||
set MOCK_SERVER_PORT=7656
|
||||
|
||||
REM Start the mock data server on port 7656
|
||||
echo Starting mock data server on port 7656...
|
||||
start /b cmd /c "npx ts-node src/mock/run-server.ts"
|
||||
|
||||
REM Wait a moment for the mock server to start
|
||||
timeout /t 3 /nobreak > nul
|
||||
|
||||
REM Verify mock server is running
|
||||
call :check_server_running 7656 "Mock server"
|
||||
if %ERRORLEVEL% NEQ 0 (
|
||||
echo ERROR: Mock server failed to start on port 7656
|
||||
exit /b 1
|
||||
)
|
||||
|
||||
REM Start the backend server on port 7654
|
||||
echo Starting backend server on port 7654...
|
||||
start /b cmd /c "set PORT=7654 && npm run dev:server"
|
||||
|
||||
REM Wait a moment for the server to start
|
||||
timeout /t 3 /nobreak > nul
|
||||
|
||||
REM Verify backend server is running
|
||||
call :check_server_running 7654 "Backend server"
|
||||
if %ERRORLEVEL% NEQ 0 (
|
||||
echo ERROR: Backend server failed to start on port 7654
|
||||
exit /b 1
|
||||
)
|
||||
|
||||
REM Set host IP to bind to all interfaces
|
||||
set HOST_IP=0.0.0.0
|
||||
|
||||
echo.
|
||||
echo Pulse is now running in development mode with mock data!
|
||||
echo - Mock Data Server: http://localhost:7656 (internal only)
|
||||
echo - Backend API: http://localhost:7654 (internal only)
|
||||
echo - Frontend UI: http://localhost:3000 (use this for development)
|
||||
echo.
|
||||
echo Access the application at: http://localhost:3000
|
||||
echo.
|
||||
|
||||
REM Start the frontend Vite dev server
|
||||
echo Starting frontend development server on port 3000...
|
||||
cd frontend && npm run dev -- --host %HOST_IP% --port 3000 --strict-port
|
||||
|
||||
REM When the frontend exits, also kill the backend and mock servers
|
||||
taskkill /f /im "node.exe" /fi "WINDOWTITLE eq npm run dev:server" 2>nul
|
||||
taskkill /f /im "node.exe" /fi "WINDOWTITLE eq npx ts-node src/mock/run-server.ts" 2>nul
|
||||
exit /b 0
|
||||
|
||||
:check_server_running
|
||||
set PORT=%~1
|
||||
set SERVER_NAME=%~2
|
||||
netstat -ano | findstr ":%PORT% " | findstr "LISTENING" > nul
|
||||
if %ERRORLEVEL% NEQ 0 (
|
||||
echo %SERVER_NAME% is not running on port %PORT%
|
||||
exit /b 1
|
||||
)
|
||||
echo %SERVER_NAME% is running on port %PORT%
|
||||
exit /b 0
|
||||
@@ -1,84 +0,0 @@
|
||||
/**
|
||||
* Cross-platform script to start the development environment
|
||||
* Detects the platform and runs the appropriate script
|
||||
*/
|
||||
|
||||
const { spawn } = require('child_process');
|
||||
const os = require('os');
|
||||
const path = require('path');
|
||||
const fs = require('fs');
|
||||
|
||||
// Ensure logo files are properly copied to frontend/public/logos
|
||||
function ensureLogoFiles() {
|
||||
console.log('Ensuring logo files are properly available in frontend...');
|
||||
|
||||
const sourceDir = path.join(process.cwd(), 'public', 'logos');
|
||||
const targetDir = path.join(process.cwd(), 'frontend', 'public', 'logos');
|
||||
|
||||
// Create target directory if it doesn't exist
|
||||
if (!fs.existsSync(targetDir)) {
|
||||
console.log('Creating frontend/public/logos directory...');
|
||||
fs.mkdirSync(targetDir, { recursive: true });
|
||||
}
|
||||
|
||||
// Copy all PNG files from source to target
|
||||
if (fs.existsSync(sourceDir)) {
|
||||
const files = fs.readdirSync(sourceDir);
|
||||
let copyCount = 0;
|
||||
|
||||
for (const file of files) {
|
||||
if (file.endsWith('.png')) {
|
||||
const sourcePath = path.join(sourceDir, file);
|
||||
const targetPath = path.join(targetDir, file);
|
||||
|
||||
fs.copyFileSync(sourcePath, targetPath);
|
||||
copyCount++;
|
||||
}
|
||||
}
|
||||
|
||||
console.log(`Copied ${copyCount} logo files to frontend/public/logos`);
|
||||
} else {
|
||||
console.warn('Warning: public/logos directory not found. Logo files may not be available.');
|
||||
}
|
||||
}
|
||||
|
||||
// Ensure logo files are available before starting the development environment
|
||||
ensureLogoFiles();
|
||||
|
||||
// Detect the platform
|
||||
const isWindows = os.platform() === 'win32';
|
||||
|
||||
console.log(`Detected platform: ${os.platform()}`);
|
||||
console.log(`Starting development environment on ${isWindows ? 'Windows' : 'Unix-like'} system...`);
|
||||
|
||||
// Define the command to run based on the platform
|
||||
let command, args;
|
||||
|
||||
if (isWindows) {
|
||||
console.log('Running Windows start script...');
|
||||
command = path.join(process.cwd(), 'start-dev.bat');
|
||||
args = [];
|
||||
} else {
|
||||
console.log('Running Unix start script...');
|
||||
command = './start-dev.sh';
|
||||
args = [];
|
||||
}
|
||||
|
||||
// Spawn the process
|
||||
const child = spawn(command, args, {
|
||||
stdio: 'inherit',
|
||||
shell: true,
|
||||
cwd: process.cwd()
|
||||
});
|
||||
|
||||
// Handle process exit
|
||||
child.on('exit', (code) => {
|
||||
console.log(`Development environment exited with code ${code}`);
|
||||
process.exit(code);
|
||||
});
|
||||
|
||||
// Handle errors
|
||||
child.on('error', (err) => {
|
||||
console.error('Failed to start development environment:', err);
|
||||
process.exit(1);
|
||||
});
|
||||
Executable
+143
@@ -0,0 +1,143 @@
|
||||
#!/bin/bash
|
||||
|
||||
# Make script executable if it isn't already
|
||||
chmod +x "$0"
|
||||
|
||||
# Check for dry run flag from command line or environment variable
|
||||
DRY_RUN=false
|
||||
if [ "$DRY_RUN" = "true" ]; then
|
||||
echo "Dry run mode enabled via environment variable - will not actually start the server"
|
||||
else
|
||||
for arg in "$@"; do
|
||||
if [ "$arg" == "--dry-run" ]; then
|
||||
DRY_RUN=true
|
||||
echo "Dry run mode enabled via command line flag - will not actually start the server"
|
||||
fi
|
||||
done
|
||||
fi
|
||||
|
||||
# Check if running in Docker
|
||||
if [ -n "$DOCKER_CONTAINER" ]; then
|
||||
echo "Running in Docker container"
|
||||
else
|
||||
# Stop any running Pulse Docker containers first if not in Docker
|
||||
echo "Stopping any running Pulse Docker containers..."
|
||||
if command -v docker &> /dev/null; then
|
||||
docker ps -q --filter "name=pulse" | xargs -r docker stop
|
||||
else
|
||||
echo "Docker not found, skipping container cleanup..."
|
||||
fi
|
||||
fi
|
||||
|
||||
# Kill any existing servers
|
||||
echo "Killing any existing servers..."
|
||||
pkill -f "node dist/server.js" || true
|
||||
pkill -f "ts-node src/mock/run-server.ts" || true
|
||||
npx kill-port 7654 7656 3000
|
||||
|
||||
# Clear any existing data files that might persist between sessions
|
||||
echo "Clearing any persisted data from previous sessions..."
|
||||
node scripts/clear-data.js
|
||||
|
||||
# Set environment to development
|
||||
export NODE_ENV=development
|
||||
|
||||
# Load environment variables from .env if it exists
|
||||
if [ -f .env ]; then
|
||||
echo "Loading environment from .env"
|
||||
set -a
|
||||
source .env
|
||||
set +a
|
||||
fi
|
||||
|
||||
# Override with development settings
|
||||
export USE_MOCK_DATA=true
|
||||
export MOCK_DATA_ENABLED=true
|
||||
export MOCK_SERVER_PORT=7656
|
||||
|
||||
# Check if we should use mock data
|
||||
if [ "$USE_MOCK_DATA" = "true" ] || [ "$MOCK_DATA_ENABLED" = "true" ]; then
|
||||
echo "Starting development environment with mock data..."
|
||||
|
||||
# Start the mock data server
|
||||
echo "Starting mock data server on port 7656..."
|
||||
|
||||
if [ "$DRY_RUN" = false ]; then
|
||||
# If running in Docker, we need to bind to 0.0.0.0 instead of localhost
|
||||
if [ -n "$DOCKER_CONTAINER" ]; then
|
||||
# Create a modified version of the run-server.ts file that binds to 0.0.0.0
|
||||
echo "global.HOST = '0.0.0.0';" > /tmp/mock-server-config.js
|
||||
# Start the mock server with the modified config
|
||||
NODE_OPTIONS="--require /tmp/mock-server-config.js" MOCK_SERVER_PORT=7656 ts-node src/mock/run-server.ts > /tmp/pulse-mock-server.log 2>&1 &
|
||||
else
|
||||
# Start the mock server normally
|
||||
MOCK_SERVER_PORT=7656 ts-node src/mock/run-server.ts > /tmp/pulse-mock-server.log 2>&1 &
|
||||
fi
|
||||
|
||||
MOCK_SERVER_PID=$!
|
||||
|
||||
# Wait a moment for the mock server to start
|
||||
sleep 2
|
||||
|
||||
# Verify mock server is running
|
||||
if curl -s http://localhost:7656 > /dev/null; then
|
||||
echo "✅ Mock server is running on port 7656"
|
||||
else
|
||||
echo "❌ Mock server failed to start"
|
||||
cat /tmp/pulse-mock-server.log
|
||||
fi
|
||||
else
|
||||
echo "[DRY RUN] Would start mock data server"
|
||||
fi
|
||||
else
|
||||
echo "Starting development environment with real data..."
|
||||
fi
|
||||
|
||||
# Start the backend server with hot reloading on port 7654
|
||||
echo "Starting backend server on port 7654..."
|
||||
if [ "$DRY_RUN" = false ]; then
|
||||
PORT=7654 ts-node-dev --respawn --transpile-only src/server.ts &
|
||||
BACKEND_PID=$!
|
||||
|
||||
# Wait a moment for the server to start
|
||||
sleep 3
|
||||
|
||||
# Verify backend server is running
|
||||
if curl -s http://localhost:7654/api/status > /dev/null; then
|
||||
echo "✅ Backend server is running on port 7654"
|
||||
else
|
||||
echo "❌ Backend server failed to start"
|
||||
fi
|
||||
else
|
||||
echo "[DRY RUN] Would start backend server with: PORT=7654 ts-node-dev --respawn --transpile-only src/server.ts"
|
||||
fi
|
||||
|
||||
# Get the host IP (use 0.0.0.0 in Docker, otherwise use localhost)
|
||||
HOST_IP="0.0.0.0"
|
||||
if [ -z "$DOCKER_CONTAINER" ]; then
|
||||
# Not in Docker, use 0.0.0.0 to bind to all interfaces
|
||||
HOST_IP="0.0.0.0"
|
||||
fi
|
||||
|
||||
echo ""
|
||||
echo "Pulse is now running in development mode!"
|
||||
echo "- Backend API: http://localhost:7654"
|
||||
echo "- Mock Server: http://localhost:7656"
|
||||
echo "- Frontend UI: http://localhost:3000 (use this for development)"
|
||||
echo ""
|
||||
echo "Access the application at: http://localhost:3000"
|
||||
echo ""
|
||||
|
||||
# Start the frontend Vite dev server with hot reloading on port 3000
|
||||
echo "Starting frontend development server on port 3000..."
|
||||
if [ "$DRY_RUN" = false ]; then
|
||||
cd frontend && npm run dev -- --host "$HOST_IP" --port 3000 --strict-port
|
||||
|
||||
# When the frontend exits, also kill the backend and mock server
|
||||
kill $BACKEND_PID
|
||||
if [ -n "$MOCK_SERVER_PID" ]; then
|
||||
kill $MOCK_SERVER_PID
|
||||
fi
|
||||
else
|
||||
echo "[DRY RUN] Would start frontend with: cd frontend && npm run dev -- --host \"$HOST_IP\" --port 3000 --strict-port"
|
||||
fi
|
||||
@@ -0,0 +1,77 @@
|
||||
@echo off
|
||||
setlocal
|
||||
|
||||
REM Stop any running Pulse Docker containers first
|
||||
echo Stopping any running Pulse Docker containers...
|
||||
where docker >nul 2>&1
|
||||
if %ERRORLEVEL% EQU 0 (
|
||||
for /f "tokens=*" %%i in ('docker ps -q --filter "name=pulse"') do (
|
||||
docker stop %%i
|
||||
)
|
||||
) else (
|
||||
echo Docker not found, skipping container cleanup...
|
||||
)
|
||||
|
||||
REM Kill any existing servers
|
||||
echo Killing any existing servers...
|
||||
taskkill /f /im "node.exe" /fi "WINDOWTITLE eq node dist/server.js" 2>nul
|
||||
call npx kill-port 7654 7655 3000
|
||||
|
||||
REM Set environment to development with mock data
|
||||
set NODE_ENV=development
|
||||
set USE_MOCK_DATA=true
|
||||
set MOCK_DATA_ENABLED=true
|
||||
|
||||
REM Load environment variables from .env if it exists
|
||||
if exist .env (
|
||||
echo Loading environment from .env
|
||||
for /f "tokens=*" %%a in (.env) do (
|
||||
set "%%a"
|
||||
)
|
||||
)
|
||||
|
||||
REM Override with mock data settings
|
||||
set USE_MOCK_DATA=true
|
||||
set MOCK_DATA_ENABLED=true
|
||||
|
||||
REM Start the mock data server
|
||||
echo Starting mock data server...
|
||||
start /b cmd /c "ts-node src/mock/run-server.ts > %TEMP%\pulse-mock-server.log 2>&1"
|
||||
|
||||
REM Wait a moment for the mock server to start
|
||||
timeout /t 2 /nobreak > nul
|
||||
|
||||
REM Start the backend server with mock data
|
||||
echo Starting backend server with mock data on port 7655...
|
||||
start /b cmd /c "set USE_MOCK_DATA=true && set MOCK_DATA_ENABLED=true && set PORT=7655 && npm run dev:server"
|
||||
|
||||
REM Wait a moment for the server to start
|
||||
timeout /t 3 /nobreak > nul
|
||||
|
||||
REM Set host IP to bind to all interfaces
|
||||
set HOST_IP=0.0.0.0
|
||||
|
||||
REM Verify mock data is enabled
|
||||
echo Verifying mock data is enabled...
|
||||
curl -s "http://localhost:7655/api/status" | findstr "mockDataEnabled" > nul
|
||||
if %ERRORLEVEL% EQU 0 (
|
||||
echo ✅ Mock data is enabled
|
||||
) else (
|
||||
echo ❌ Mock data is NOT enabled
|
||||
)
|
||||
|
||||
echo.
|
||||
echo Pulse is now running with mock data!
|
||||
echo - Backend API: http://localhost:7655 (internal only)
|
||||
echo - Frontend UI: http://localhost:7654 (use this for development)
|
||||
echo.
|
||||
echo Access the application at: http://localhost:7654
|
||||
echo.
|
||||
|
||||
REM Start the frontend Vite dev server
|
||||
echo Starting Pulse interface with mock data on port 7654...
|
||||
cd frontend && set USE_MOCK_DATA=true && set MOCK_DATA_ENABLED=true && npm run dev -- --host %HOST_IP% --port 7654
|
||||
|
||||
REM When the frontend exits, also kill the backend and mock server
|
||||
taskkill /f /im "node.exe" /fi "WINDOWTITLE eq npm run dev:server" 2>nul
|
||||
taskkill /f /im "node.exe" /fi "WINDOWTITLE eq ts-node src/mock/run-server.ts" 2>nul
|
||||
@@ -1,84 +0,0 @@
|
||||
/**
|
||||
* Cross-platform script to start the mock development environment
|
||||
* Detects the platform and runs the appropriate script
|
||||
*/
|
||||
|
||||
const { spawn } = require('child_process');
|
||||
const os = require('os');
|
||||
const path = require('path');
|
||||
const fs = require('fs');
|
||||
|
||||
// Ensure logo files are properly copied to frontend/public/logos
|
||||
function ensureLogoFiles() {
|
||||
console.log('Ensuring logo files are properly available in frontend...');
|
||||
|
||||
const sourceDir = path.join(process.cwd(), 'public', 'logos');
|
||||
const targetDir = path.join(process.cwd(), 'frontend', 'public', 'logos');
|
||||
|
||||
// Create target directory if it doesn't exist
|
||||
if (!fs.existsSync(targetDir)) {
|
||||
console.log('Creating frontend/public/logos directory...');
|
||||
fs.mkdirSync(targetDir, { recursive: true });
|
||||
}
|
||||
|
||||
// Copy all PNG files from source to target
|
||||
if (fs.existsSync(sourceDir)) {
|
||||
const files = fs.readdirSync(sourceDir);
|
||||
let copyCount = 0;
|
||||
|
||||
for (const file of files) {
|
||||
if (file.endsWith('.png')) {
|
||||
const sourcePath = path.join(sourceDir, file);
|
||||
const targetPath = path.join(targetDir, file);
|
||||
|
||||
fs.copyFileSync(sourcePath, targetPath);
|
||||
copyCount++;
|
||||
}
|
||||
}
|
||||
|
||||
console.log(`Copied ${copyCount} logo files to frontend/public/logos`);
|
||||
} else {
|
||||
console.warn('Warning: public/logos directory not found. Logo files may not be available.');
|
||||
}
|
||||
}
|
||||
|
||||
// Ensure logo files are available before starting the development environment
|
||||
ensureLogoFiles();
|
||||
|
||||
// Detect the platform
|
||||
const isWindows = os.platform() === 'win32';
|
||||
|
||||
console.log(`Detected platform: ${os.platform()}`);
|
||||
console.log(`Starting mock development environment on ${isWindows ? 'Windows' : 'Unix-like'} system...`);
|
||||
|
||||
// Define the command to run based on the platform
|
||||
let command, args;
|
||||
|
||||
if (isWindows) {
|
||||
console.log('Running Windows mock start script...');
|
||||
command = path.join(process.cwd(), 'start-mock-dev.bat');
|
||||
args = [];
|
||||
} else {
|
||||
console.log('Running Unix mock start script...');
|
||||
command = './start-mock-dev.sh';
|
||||
args = [];
|
||||
}
|
||||
|
||||
// Spawn the process
|
||||
const child = spawn(command, args, {
|
||||
stdio: 'inherit',
|
||||
shell: true,
|
||||
cwd: process.cwd()
|
||||
});
|
||||
|
||||
// Handle process exit
|
||||
child.on('exit', (code) => {
|
||||
console.log(`Mock development environment exited with code ${code}`);
|
||||
process.exit(code);
|
||||
});
|
||||
|
||||
// Handle errors
|
||||
child.on('error', (err) => {
|
||||
console.error('Failed to start mock development environment:', err);
|
||||
process.exit(1);
|
||||
});
|
||||
Executable
+119
@@ -0,0 +1,119 @@
|
||||
#!/bin/bash
|
||||
|
||||
# Make script executable if it isn't already
|
||||
chmod +x "$0"
|
||||
|
||||
# Check for dry run flag from command line or environment variable
|
||||
DRY_RUN=false
|
||||
if [ "$DRY_RUN" = "true" ]; then
|
||||
echo "Dry run mode enabled via environment variable - will not actually start the server"
|
||||
else
|
||||
for arg in "$@"; do
|
||||
if [ "$arg" == "--dry-run" ]; then
|
||||
DRY_RUN=true
|
||||
echo "Dry run mode enabled via command line flag - will not actually start the server"
|
||||
fi
|
||||
done
|
||||
fi
|
||||
|
||||
# Stop any running Pulse Docker containers first
|
||||
echo "Stopping any running Pulse Docker containers..."
|
||||
if command -v docker &> /dev/null; then
|
||||
docker ps -q --filter "name=pulse" | xargs -r docker stop
|
||||
else
|
||||
echo "Docker not found, skipping container cleanup..."
|
||||
fi
|
||||
|
||||
# Kill any existing servers
|
||||
echo "Killing any existing servers..."
|
||||
pkill -f "node dist/server.js" || true
|
||||
pkill -f "ts-node src/mock/run-server.ts" || true
|
||||
npx kill-port 7654 7655 7656 5173
|
||||
|
||||
# Set environment to development with mock data
|
||||
export NODE_ENV=development
|
||||
export USE_MOCK_DATA=true
|
||||
export MOCK_DATA_ENABLED=true
|
||||
export MOCK_SERVER_PORT=7656
|
||||
|
||||
# Load environment variables from .env if it exists
|
||||
if [ -f .env ]; then
|
||||
echo "Loading environment from .env"
|
||||
set -a
|
||||
source .env
|
||||
set +a
|
||||
# Override mock data settings
|
||||
export USE_MOCK_DATA=true
|
||||
export MOCK_DATA_ENABLED=true
|
||||
export MOCK_SERVER_PORT=7656
|
||||
fi
|
||||
|
||||
# Start the mock data server
|
||||
echo "Starting mock data server on port 7656..."
|
||||
if [ "$DRY_RUN" = false ]; then
|
||||
MOCK_SERVER_PORT=7656 ts-node src/mock/run-server.ts > /tmp/pulse-mock-server.log 2>&1 &
|
||||
MOCK_SERVER_PID=$!
|
||||
|
||||
# Wait a moment for the mock server to start
|
||||
sleep 2
|
||||
|
||||
# Check if the mock data server is running
|
||||
if ! ps -p $MOCK_SERVER_PID > /dev/null; then
|
||||
echo "Error: Mock data server failed to start."
|
||||
echo "Check the logs at /tmp/pulse-mock-server.log for details."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Verify mock server is running
|
||||
if curl -s http://localhost:7656 > /dev/null; then
|
||||
echo "✅ Mock server is running on port 7656"
|
||||
else
|
||||
echo "❌ Mock server failed to start"
|
||||
cat /tmp/pulse-mock-server.log
|
||||
fi
|
||||
else
|
||||
echo "[DRY RUN] Would start mock data server with: MOCK_SERVER_PORT=7656 ts-node src/mock/run-server.ts"
|
||||
fi
|
||||
|
||||
# Start the backend server with mock data on port 7654
|
||||
echo "Starting backend server with mock data on port 7654..."
|
||||
if [ "$DRY_RUN" = false ]; then
|
||||
USE_MOCK_DATA=true MOCK_DATA_ENABLED=true PORT=7654 npm run dev:server &
|
||||
BACKEND_PID=$!
|
||||
|
||||
# Wait a moment for the server to start
|
||||
sleep 3
|
||||
|
||||
# Verify mock data is enabled - check port 7654 where the backend is running
|
||||
echo "Verifying mock data is enabled..."
|
||||
curl -s "http://localhost:7654/api/status" | grep -q "mockDataEnabled" && echo "✅ Mock data is enabled" || echo "❌ Mock data is NOT enabled"
|
||||
else
|
||||
echo "[DRY RUN] Would start backend server with: USE_MOCK_DATA=true MOCK_DATA_ENABLED=true PORT=7654 npm run dev:server"
|
||||
fi
|
||||
|
||||
# Get the host IP (use 0.0.0.0 in Docker, otherwise use localhost or your local IP)
|
||||
HOST_IP="0.0.0.0"
|
||||
if [[ -z "${DOCKER_CONTAINER}" ]]; then
|
||||
# Not in Docker, still use 0.0.0.0 to bind to all interfaces
|
||||
HOST_IP="0.0.0.0"
|
||||
fi
|
||||
|
||||
echo ""
|
||||
echo "Pulse is now running with mock data!"
|
||||
echo "- Backend API: http://localhost:7654"
|
||||
echo "- Mock Server: http://localhost:7656"
|
||||
echo "- Frontend UI: http://localhost:5173 (use this for development)"
|
||||
echo ""
|
||||
echo "Access the application at: http://localhost:5173"
|
||||
echo ""
|
||||
|
||||
# Start the frontend Vite dev server on port 5173
|
||||
echo "Starting Pulse interface with mock data on port 5173..."
|
||||
if [ "$DRY_RUN" = false ]; then
|
||||
cd frontend && USE_MOCK_DATA=true MOCK_DATA_ENABLED=true npm run dev -- --host "${HOST_IP}" --port 5173
|
||||
|
||||
# When the frontend exits, also kill the backend and mock server
|
||||
kill $BACKEND_PID $MOCK_SERVER_PID
|
||||
else
|
||||
echo "[DRY RUN] Would start frontend with: cd frontend && USE_MOCK_DATA=true MOCK_DATA_ENABLED=true npm run dev -- --host \"${HOST_IP}\" --port 5173"
|
||||
fi
|
||||
Executable
+58
@@ -0,0 +1,58 @@
|
||||
#!/usr/bin/env node
|
||||
|
||||
/**
|
||||
* Script to start just the mock server
|
||||
* Usage: node scripts/start-mock-server.js
|
||||
*/
|
||||
|
||||
const { spawn } = require('child_process');
|
||||
const path = require('path');
|
||||
const fs = require('fs');
|
||||
const dotenv = require('dotenv');
|
||||
|
||||
// Load environment variables
|
||||
dotenv.config();
|
||||
|
||||
// Use port 7656 to avoid conflicts with the backend server
|
||||
const MOCK_PORT = 7656;
|
||||
|
||||
console.log(`Starting mock server on port ${MOCK_PORT}...`);
|
||||
|
||||
// Set environment variables
|
||||
process.env.NODE_ENV = 'development';
|
||||
process.env.USE_MOCK_DATA = 'true';
|
||||
process.env.MOCK_DATA_ENABLED = 'true';
|
||||
process.env.MOCK_SERVER_PORT = MOCK_PORT.toString();
|
||||
|
||||
// Start the mock server
|
||||
const mockServer = spawn('npx', ['ts-node', 'src/mock/run-server.ts'], {
|
||||
stdio: 'inherit',
|
||||
env: {
|
||||
...process.env,
|
||||
NODE_ENV: 'development',
|
||||
USE_MOCK_DATA: 'true',
|
||||
MOCK_DATA_ENABLED: 'true',
|
||||
PORT: MOCK_PORT.toString(),
|
||||
MOCK_SERVER_PORT: MOCK_PORT.toString()
|
||||
}
|
||||
});
|
||||
|
||||
// Handle mock server exit
|
||||
mockServer.on('exit', (code) => {
|
||||
console.log(`Mock server exited with code ${code}`);
|
||||
process.exit(code);
|
||||
});
|
||||
|
||||
// Handle process termination
|
||||
process.on('SIGINT', () => {
|
||||
console.log('Stopping mock server...');
|
||||
mockServer.kill();
|
||||
});
|
||||
|
||||
process.on('SIGTERM', () => {
|
||||
console.log('Stopping mock server...');
|
||||
mockServer.kill();
|
||||
});
|
||||
|
||||
console.log(`Mock server started on port ${MOCK_PORT}`);
|
||||
console.log('Press Ctrl+C to stop');
|
||||
@@ -0,0 +1,71 @@
|
||||
@echo off
|
||||
setlocal enabledelayedexpansion
|
||||
|
||||
REM Check for dry run flag
|
||||
set DRY_RUN=false
|
||||
for %%a in (%*) do (
|
||||
if "%%a"=="--dry-run" (
|
||||
set DRY_RUN=true
|
||||
echo Dry run mode enabled - will not actually start the server
|
||||
)
|
||||
)
|
||||
|
||||
REM Kill any existing server processes
|
||||
taskkill /f /im "node.exe" /fi "WINDOWTITLE eq node dist/server.js" 2>nul
|
||||
taskkill /f /im "node.exe" /fi "WINDOWTITLE eq ts-node src/mock/run-server.ts" 2>nul
|
||||
call npx kill-port 7654 7655 7656 5173
|
||||
|
||||
REM Clear any existing data files that might persist between sessions
|
||||
echo Clearing any persisted data from previous sessions...
|
||||
node scripts/clear-data.js
|
||||
|
||||
REM Set environment to production
|
||||
set NODE_ENV=production
|
||||
|
||||
REM Load environment variables from .env if it exists
|
||||
if exist .env (
|
||||
echo Loading environment from .env
|
||||
for /f "tokens=*" %%a in (.env) do (
|
||||
set "line=%%a"
|
||||
if not "!line:~0,1!"=="#" (
|
||||
if not "!line!"=="" (
|
||||
set "%%a"
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
|
||||
REM Force mock data to be disabled for production
|
||||
set USE_MOCK_DATA=false
|
||||
set MOCK_DATA_ENABLED=false
|
||||
|
||||
REM Build the backend
|
||||
echo Building the backend...
|
||||
if "%DRY_RUN%"=="false" (
|
||||
call npm run build
|
||||
) else (
|
||||
echo [DRY RUN] Would run: npm run build
|
||||
)
|
||||
|
||||
REM Build the frontend
|
||||
echo Building the frontend...
|
||||
if "%DRY_RUN%"=="false" (
|
||||
cd frontend
|
||||
call npm run build
|
||||
cd ..
|
||||
) else (
|
||||
echo [DRY RUN] Would run: cd frontend ^&^& npm run build ^&^& cd ..
|
||||
)
|
||||
|
||||
REM Start the production server
|
||||
echo Starting production server...
|
||||
if "%DRY_RUN%"=="false" (
|
||||
node dist/server.js
|
||||
) else (
|
||||
echo [DRY RUN] Would run: node dist/server.js
|
||||
)
|
||||
|
||||
REM When the server exits, also kill the mock server if it's running
|
||||
if "%USE_MOCK_DATA%"=="true" (
|
||||
taskkill /f /im "node.exe" /fi "WINDOWTITLE eq ts-node src/mock/run-server.ts" 2>nul
|
||||
)
|
||||
Executable
+71
@@ -0,0 +1,71 @@
|
||||
#!/bin/bash
|
||||
|
||||
# Make script executable if it isn't already
|
||||
chmod +x "$0"
|
||||
|
||||
# Check for dry run flag from command line or environment variable
|
||||
DRY_RUN=false
|
||||
if [ "$DRY_RUN" = "true" ]; then
|
||||
echo "Dry run mode enabled via environment variable - will not actually start the server"
|
||||
else
|
||||
for arg in "$@"; do
|
||||
if [ "$arg" == "--dry-run" ]; then
|
||||
DRY_RUN=true
|
||||
echo "Dry run mode enabled via command line flag - will not actually start the server"
|
||||
fi
|
||||
done
|
||||
fi
|
||||
|
||||
# Kill any existing servers
|
||||
echo "Killing any existing servers..."
|
||||
pkill -f "node dist/server.js" || true
|
||||
pkill -f "ts-node src/mock/run-server.ts" || true
|
||||
npx kill-port 7654 7655 7656 5173
|
||||
|
||||
# Clear any existing data files that might persist between sessions
|
||||
echo "Clearing any persisted data from previous sessions..."
|
||||
node scripts/clear-data.js
|
||||
|
||||
# Set environment to production and load the environment file
|
||||
export NODE_ENV=production
|
||||
|
||||
# Load environment variables from .env if it exists
|
||||
if [ -f .env ]; then
|
||||
echo "Loading environment from .env"
|
||||
set -a
|
||||
source .env
|
||||
set +a
|
||||
fi
|
||||
|
||||
# Force mock data to be disabled for production
|
||||
export USE_MOCK_DATA=false
|
||||
export MOCK_DATA_ENABLED=false
|
||||
|
||||
# Build the backend
|
||||
echo "Building backend..."
|
||||
if [ "$DRY_RUN" = false ]; then
|
||||
npm run build
|
||||
else
|
||||
echo "[DRY RUN] Would run: npm run build"
|
||||
fi
|
||||
|
||||
# Build the frontend
|
||||
echo "Building frontend..."
|
||||
if [ "$DRY_RUN" = false ]; then
|
||||
cd frontend && npm run build && cd ..
|
||||
else
|
||||
echo "[DRY RUN] Would run: cd frontend && npm run build && cd .."
|
||||
fi
|
||||
|
||||
# Start the production server
|
||||
echo "Starting production server..."
|
||||
if [ "$DRY_RUN" = false ]; then
|
||||
node dist/server.js
|
||||
else
|
||||
echo "[DRY RUN] Would run: node dist/server.js"
|
||||
fi
|
||||
|
||||
# When the server exits, also kill the mock server if it's running
|
||||
if [ -n "$MOCK_SERVER_PID" ]; then
|
||||
kill $MOCK_SERVER_PID
|
||||
fi
|
||||
@@ -0,0 +1,137 @@
|
||||
/**
|
||||
* Unified cross-platform script to start Pulse in different environments
|
||||
* Usage: node start.js [dev|prod] [--dry-run]
|
||||
*/
|
||||
|
||||
const { spawn } = require('child_process');
|
||||
const os = require('os');
|
||||
const path = require('path');
|
||||
const fs = require('fs');
|
||||
const dotenv = require('dotenv');
|
||||
|
||||
// Parse command line arguments
|
||||
const args = process.argv.slice(2);
|
||||
const mode = args[0] || 'dev'; // Default to dev mode if not specified
|
||||
const isDryRun = args.includes('--dry-run');
|
||||
|
||||
// Detect the platform
|
||||
const isWindows = os.platform() === 'win32';
|
||||
|
||||
console.log(`Detected platform: ${os.platform()}`);
|
||||
console.log(`Starting Pulse in ${mode} mode on ${isWindows ? 'Windows' : 'Unix-like'} system...`);
|
||||
if (isDryRun) {
|
||||
console.log('Dry run mode enabled - commands will be shown but not executed');
|
||||
}
|
||||
|
||||
// Load environment variables
|
||||
function loadEnvironment() {
|
||||
// Load from .env file
|
||||
dotenv.config();
|
||||
|
||||
// For development mode, override with development settings if not already set
|
||||
if (mode === 'dev' && process.env.NODE_ENV !== 'development') {
|
||||
process.env.NODE_ENV = 'development';
|
||||
process.env.USE_MOCK_DATA = 'true';
|
||||
process.env.MOCK_DATA_ENABLED = 'true';
|
||||
process.env.MOCK_SERVER_PORT = '7656';
|
||||
console.log('Using development settings with mock data');
|
||||
} else if (mode === 'prod' && process.env.NODE_ENV !== 'production') {
|
||||
process.env.NODE_ENV = 'production';
|
||||
process.env.USE_MOCK_DATA = 'false';
|
||||
process.env.MOCK_DATA_ENABLED = 'false';
|
||||
console.log('Using production settings with real data');
|
||||
}
|
||||
}
|
||||
|
||||
// Ensure logo files are properly copied to frontend/public/logos
|
||||
function ensureLogoFiles() {
|
||||
console.log('Ensuring logo files are properly available in frontend...');
|
||||
|
||||
const sourceDir = path.join(process.cwd(), 'public', 'logos');
|
||||
const targetDir = path.join(process.cwd(), 'frontend', 'public', 'logos');
|
||||
|
||||
// Create target directory if it doesn't exist
|
||||
if (!fs.existsSync(targetDir)) {
|
||||
console.log('Creating frontend/public/logos directory...');
|
||||
fs.mkdirSync(targetDir, { recursive: true });
|
||||
}
|
||||
|
||||
// Copy all logo files
|
||||
try {
|
||||
const files = fs.readdirSync(sourceDir);
|
||||
for (const file of files) {
|
||||
if (file.endsWith('.png') || file.endsWith('.svg')) {
|
||||
const sourcePath = path.join(sourceDir, file);
|
||||
const targetPath = path.join(targetDir, file);
|
||||
|
||||
// Only copy if the file doesn't exist or is older
|
||||
if (!fs.existsSync(targetPath) ||
|
||||
fs.statSync(sourcePath).mtime > fs.statSync(targetPath).mtime) {
|
||||
console.log(`Copying ${file} to frontend/public/logos...`);
|
||||
fs.copyFileSync(sourcePath, targetPath);
|
||||
}
|
||||
}
|
||||
}
|
||||
console.log('Logo files are up to date.');
|
||||
} catch (error) {
|
||||
console.warn(`Warning: Could not copy logo files: ${error.message}`);
|
||||
console.warn('This is not critical, continuing with startup...');
|
||||
}
|
||||
}
|
||||
|
||||
// Start the appropriate script based on the platform and mode
|
||||
function startScript() {
|
||||
let scriptPath;
|
||||
|
||||
if (isWindows) {
|
||||
// Windows scripts
|
||||
if (mode === 'prod') {
|
||||
scriptPath = path.join(process.cwd(), 'scripts', 'start-prod.bat');
|
||||
} else {
|
||||
scriptPath = path.join(process.cwd(), 'scripts', 'start-dev.bat');
|
||||
}
|
||||
} else {
|
||||
// Unix-like scripts
|
||||
if (mode === 'prod') {
|
||||
scriptPath = path.join(process.cwd(), 'scripts', 'start-prod.sh');
|
||||
} else {
|
||||
scriptPath = path.join(process.cwd(), 'scripts', 'start-dev.sh');
|
||||
}
|
||||
|
||||
// Make the script executable
|
||||
try {
|
||||
fs.chmodSync(scriptPath, '755');
|
||||
} catch (error) {
|
||||
console.error(`Error making script executable: ${error.message}`);
|
||||
process.exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
console.log(`Starting script: ${scriptPath}`);
|
||||
|
||||
if (isDryRun) {
|
||||
console.log('Dry run mode - not actually executing the script');
|
||||
return;
|
||||
}
|
||||
|
||||
// Execute the script
|
||||
const scriptArgs = args.filter(arg => arg !== mode && arg !== '--dry-run');
|
||||
const child = isWindows
|
||||
? spawn('cmd.exe', ['/c', scriptPath, ...scriptArgs], { stdio: 'inherit' })
|
||||
: spawn(scriptPath, scriptArgs, { stdio: 'inherit' });
|
||||
|
||||
child.on('error', (error) => {
|
||||
console.error(`Error starting script: ${error.message}`);
|
||||
process.exit(1);
|
||||
});
|
||||
|
||||
child.on('close', (code) => {
|
||||
console.log(`Script exited with code ${code}`);
|
||||
process.exit(code);
|
||||
});
|
||||
}
|
||||
|
||||
// Main execution
|
||||
loadEnvironment();
|
||||
ensureLogoFiles();
|
||||
startScript();
|
||||
@@ -0,0 +1,96 @@
|
||||
/**
|
||||
* Test script to check the Proxmox cluster API response
|
||||
* This will help diagnose why standalone nodes are being detected as part of a cluster
|
||||
*/
|
||||
|
||||
const axios = require('axios');
|
||||
const https = require('https');
|
||||
require('dotenv').config();
|
||||
|
||||
// Create an axios instance with SSL verification disabled
|
||||
const createClient = (host, tokenId, tokenSecret) => {
|
||||
return axios.create({
|
||||
baseURL: `${host}/api2/json`,
|
||||
headers: {
|
||||
'Authorization': `PVEAPIToken=${tokenId}=${tokenSecret}`
|
||||
},
|
||||
httpsAgent: new https.Agent({
|
||||
rejectUnauthorized: false
|
||||
})
|
||||
});
|
||||
};
|
||||
|
||||
// Test function to check cluster status
|
||||
const testClusterStatus = async (host, tokenId, tokenSecret, nodeName) => {
|
||||
try {
|
||||
console.log(`Testing cluster status for node: ${nodeName} (${host})`);
|
||||
const client = createClient(host, tokenId, tokenSecret);
|
||||
|
||||
// Try to access the cluster status endpoint
|
||||
const response = await client.get('/cluster/status');
|
||||
|
||||
console.log(`Response status: ${response.status}`);
|
||||
console.log(`Response data: ${JSON.stringify(response.data, null, 2)}`);
|
||||
|
||||
// Check if there's a cluster type in the response
|
||||
if (response.data && response.data.data && Array.isArray(response.data.data)) {
|
||||
const clusterInfo = response.data.data.find(item => item.type === 'cluster');
|
||||
if (clusterInfo) {
|
||||
console.log(`Found cluster info: ${JSON.stringify(clusterInfo, null, 2)}`);
|
||||
console.log(`This node IS part of a cluster named: ${clusterInfo.name}`);
|
||||
} else {
|
||||
console.log('No cluster type found in the response');
|
||||
console.log('This node is NOT part of a cluster, but the cluster API is available');
|
||||
}
|
||||
} else {
|
||||
console.log('No data array in response');
|
||||
console.log('This node is NOT part of a cluster');
|
||||
}
|
||||
|
||||
console.log('-----------------------------------');
|
||||
} catch (error) {
|
||||
console.error(`Error testing cluster status for ${nodeName}:`, error.message);
|
||||
if (error.response) {
|
||||
console.log(`Response status: ${error.response.status}`);
|
||||
console.log(`Response data: ${JSON.stringify(error.response.data, null, 2)}`);
|
||||
}
|
||||
console.log('This node is NOT part of a cluster (error response)');
|
||||
console.log('-----------------------------------');
|
||||
}
|
||||
};
|
||||
|
||||
// Main function to test all nodes
|
||||
const testAllNodes = async () => {
|
||||
// Node 1
|
||||
await testClusterStatus(
|
||||
process.env.PROXMOX_HOST,
|
||||
process.env.PROXMOX_TOKEN_ID,
|
||||
process.env.PROXMOX_TOKEN_SECRET,
|
||||
process.env.PROXMOX_NODE
|
||||
);
|
||||
|
||||
// Node 2
|
||||
if (process.env.PROXMOX_HOST_2) {
|
||||
await testClusterStatus(
|
||||
process.env.PROXMOX_HOST_2,
|
||||
process.env.PROXMOX_TOKEN_ID_2,
|
||||
process.env.PROXMOX_TOKEN_SECRET_2,
|
||||
process.env.PROXMOX_NODE_2
|
||||
);
|
||||
}
|
||||
|
||||
// Node 3
|
||||
if (process.env.PROXMOX_HOST_3) {
|
||||
await testClusterStatus(
|
||||
process.env.PROXMOX_HOST_3,
|
||||
process.env.PROXMOX_TOKEN_ID_3,
|
||||
process.env.PROXMOX_TOKEN_SECRET_3,
|
||||
process.env.PROXMOX_NODE_3
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
// Run the tests
|
||||
testAllNodes().catch(error => {
|
||||
console.error('Error running tests:', error);
|
||||
});
|
||||
@@ -0,0 +1,119 @@
|
||||
/**
|
||||
* Test script to verify our fix for cluster detection
|
||||
* This script directly tests the fixed isNodeInCluster function
|
||||
*/
|
||||
|
||||
const axios = require('axios');
|
||||
const https = require('https');
|
||||
require('dotenv').config();
|
||||
|
||||
// Create an axios instance with SSL verification disabled
|
||||
const createClient = (host, tokenId, tokenSecret) => {
|
||||
return axios.create({
|
||||
baseURL: `${host}/api2/json`,
|
||||
headers: {
|
||||
'Authorization': `PVEAPIToken=${tokenId}=${tokenSecret}`
|
||||
},
|
||||
httpsAgent: new https.Agent({
|
||||
rejectUnauthorized: false
|
||||
})
|
||||
});
|
||||
};
|
||||
|
||||
// Our fixed isNodeInCluster function
|
||||
async function isNodeInCluster(client, nodeName) {
|
||||
try {
|
||||
console.log(`Testing cluster detection for node: ${nodeName}`);
|
||||
|
||||
// Try to access the cluster status endpoint
|
||||
const response = await client.get('/cluster/status');
|
||||
|
||||
console.log(`Response status: ${response.status}`);
|
||||
console.log(`Response data: ${JSON.stringify(response.data, null, 2)}`);
|
||||
|
||||
if (response.data && response.data.data && Array.isArray(response.data.data)) {
|
||||
// Only consider it a cluster if we find an item with type: "cluster"
|
||||
const clusterInfo = response.data.data.find(item => item.type === 'cluster');
|
||||
|
||||
console.log(`Cluster info: ${JSON.stringify(clusterInfo, null, 2)}`);
|
||||
|
||||
if (clusterInfo && clusterInfo.type === 'cluster') {
|
||||
const clusterName = clusterInfo.name || 'proxmox-cluster';
|
||||
console.log(`Node IS part of cluster: ${clusterName}`);
|
||||
return { isCluster: true, clusterName };
|
||||
} else {
|
||||
console.log('Node has cluster API but no cluster type found - NOT part of a cluster');
|
||||
return { isCluster: false, clusterName: '' };
|
||||
}
|
||||
} else {
|
||||
console.log('Node is not part of a cluster (empty response data)');
|
||||
return { isCluster: false, clusterName: '' };
|
||||
}
|
||||
} catch (error) {
|
||||
// If we get a 404 error, it means the cluster endpoint doesn't exist, so the node is not part of a cluster
|
||||
if (error.response && error.response.status === 404) {
|
||||
console.log('Node is not part of a cluster (404 response from cluster endpoint)');
|
||||
return { isCluster: false, clusterName: '' };
|
||||
}
|
||||
|
||||
// For other errors, log them but assume the node is not in a cluster
|
||||
console.error('Error checking if node is in cluster:', error.message);
|
||||
if (error.response) {
|
||||
console.log(`Response status: ${error.response.status}`);
|
||||
console.log(`Response data: ${JSON.stringify(error.response.data, null, 2)}`);
|
||||
}
|
||||
return { isCluster: false, clusterName: '' };
|
||||
}
|
||||
}
|
||||
|
||||
// Test function for a single node
|
||||
async function testNode(host, tokenId, tokenSecret, nodeName) {
|
||||
console.log(`\n=== Testing node: ${nodeName} (${host}) ===\n`);
|
||||
try {
|
||||
const client = createClient(host, tokenId, tokenSecret);
|
||||
const result = await isNodeInCluster(client, nodeName);
|
||||
console.log(`\nFinal result: Node ${nodeName} ${result.isCluster ? 'IS' : 'is NOT'} part of a cluster`);
|
||||
if (result.isCluster) {
|
||||
console.log(`Cluster name: ${result.clusterName}`);
|
||||
}
|
||||
} catch (error) {
|
||||
console.error(`Error testing node ${nodeName}:`, error.message);
|
||||
}
|
||||
console.log('\n=== Test complete ===\n');
|
||||
}
|
||||
|
||||
// Main function to test all nodes
|
||||
async function testAllNodes() {
|
||||
// Node 1
|
||||
await testNode(
|
||||
process.env.PROXMOX_HOST,
|
||||
process.env.PROXMOX_TOKEN_ID,
|
||||
process.env.PROXMOX_TOKEN_SECRET,
|
||||
process.env.PROXMOX_NODE
|
||||
);
|
||||
|
||||
// Node 2
|
||||
if (process.env.PROXMOX_HOST_2) {
|
||||
await testNode(
|
||||
process.env.PROXMOX_HOST_2,
|
||||
process.env.PROXMOX_TOKEN_ID_2,
|
||||
process.env.PROXMOX_TOKEN_SECRET_2,
|
||||
process.env.PROXMOX_NODE_2
|
||||
);
|
||||
}
|
||||
|
||||
// Node 3
|
||||
if (process.env.PROXMOX_HOST_3) {
|
||||
await testNode(
|
||||
process.env.PROXMOX_HOST_3,
|
||||
process.env.PROXMOX_TOKEN_ID_3,
|
||||
process.env.PROXMOX_TOKEN_SECRET_3,
|
||||
process.env.PROXMOX_NODE_3
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
// Run the tests
|
||||
testAllNodes().catch(error => {
|
||||
console.error('Error running tests:', error);
|
||||
});
|
||||
@@ -0,0 +1,123 @@
|
||||
/**
|
||||
* Test script to demonstrate mock cluster mode
|
||||
*
|
||||
* This script creates mock clients for multiple nodes and shows how
|
||||
* the VM and container IDs are generated with and without cluster mode.
|
||||
*
|
||||
* Run with:
|
||||
* npx ts-node scripts/test-mock-cluster.ts
|
||||
*/
|
||||
|
||||
import { MockClient } from '../src/api/mock-client';
|
||||
import { NodeConfig } from '../src/types';
|
||||
|
||||
// Create mock node configs
|
||||
const nodeConfigs: NodeConfig[] = [
|
||||
{
|
||||
id: 'node-1',
|
||||
name: 'pve-1',
|
||||
host: 'http://localhost:7656',
|
||||
tokenId: 'mock-token',
|
||||
tokenSecret: 'mock-secret'
|
||||
},
|
||||
{
|
||||
id: 'node-2',
|
||||
name: 'pve-2',
|
||||
host: 'http://localhost:7656',
|
||||
tokenId: 'mock-token',
|
||||
tokenSecret: 'mock-secret'
|
||||
},
|
||||
{
|
||||
id: 'node-3',
|
||||
name: 'pve-3',
|
||||
host: 'http://localhost:7656',
|
||||
tokenId: 'mock-token',
|
||||
tokenSecret: 'mock-secret'
|
||||
}
|
||||
];
|
||||
|
||||
// Test with cluster mode enabled
|
||||
async function testWithClusterMode() {
|
||||
console.log('\n=== Testing with Cluster Mode Enabled ===');
|
||||
|
||||
// Set environment variables for cluster mode
|
||||
process.env.MOCK_CLUSTER_ENABLED = 'true';
|
||||
process.env.MOCK_CLUSTER_NAME = 'test-cluster';
|
||||
|
||||
const clients = nodeConfigs.map(config => new MockClient(config));
|
||||
|
||||
// Get VMs and containers from each client
|
||||
for (let i = 0; i < clients.length; i++) {
|
||||
const client = clients[i];
|
||||
const vms = await client.getVMs();
|
||||
const containers = await client.getContainers();
|
||||
|
||||
console.log(`\nNode: ${nodeConfigs[i].name} (${nodeConfigs[i].id})`);
|
||||
console.log('VMs:');
|
||||
vms.forEach(vm => {
|
||||
console.log(` ${vm.id} (VMID: ${vm.vmid}, Name: ${vm.name}, Node: ${vm.node})`);
|
||||
});
|
||||
|
||||
console.log('Containers:');
|
||||
containers.forEach(container => {
|
||||
console.log(` ${container.id} (VMID: ${container.vmid}, Name: ${container.name}, Node: ${container.node})`);
|
||||
});
|
||||
}
|
||||
|
||||
// Clean up
|
||||
clients.forEach(client => client.disconnect());
|
||||
}
|
||||
|
||||
// Test with cluster mode disabled
|
||||
async function testWithoutClusterMode() {
|
||||
console.log('\n=== Testing with Cluster Mode Disabled ===');
|
||||
|
||||
// Set environment variables to disable cluster mode
|
||||
process.env.MOCK_CLUSTER_ENABLED = 'false';
|
||||
|
||||
const clients = nodeConfigs.map(config => new MockClient(config));
|
||||
|
||||
// Get VMs and containers from each client
|
||||
for (let i = 0; i < clients.length; i++) {
|
||||
const client = clients[i];
|
||||
const vms = await client.getVMs();
|
||||
const containers = await client.getContainers();
|
||||
|
||||
console.log(`\nNode: ${nodeConfigs[i].name} (${nodeConfigs[i].id})`);
|
||||
console.log('VMs:');
|
||||
vms.forEach(vm => {
|
||||
console.log(` ${vm.id} (VMID: ${vm.vmid}, Name: ${vm.name}, Node: ${vm.node})`);
|
||||
});
|
||||
|
||||
console.log('Containers:');
|
||||
containers.forEach(container => {
|
||||
console.log(` ${container.id} (VMID: ${container.vmid}, Name: ${container.name}, Node: ${container.node})`);
|
||||
});
|
||||
}
|
||||
|
||||
// Clean up
|
||||
clients.forEach(client => client.disconnect());
|
||||
}
|
||||
|
||||
// Run the tests
|
||||
async function runTests() {
|
||||
try {
|
||||
await testWithClusterMode();
|
||||
await testWithoutClusterMode();
|
||||
|
||||
console.log('\n=== Summary ===');
|
||||
console.log('With cluster mode enabled:');
|
||||
console.log('- VMs and containers have IDs like: test-cluster-vm-100, test-cluster-ct-200');
|
||||
console.log('- The same VMID across different nodes will have the same ID');
|
||||
console.log('- This results in deduplication in the UI');
|
||||
|
||||
console.log('\nWith cluster mode disabled:');
|
||||
console.log('- VMs and containers have IDs like: node-1-vm-100, node-2-vm-100');
|
||||
console.log('- The same VMID across different nodes will have different IDs');
|
||||
console.log('- This results in showing all VMs/containers from all nodes in the UI');
|
||||
} catch (error) {
|
||||
console.error('Error running tests:', error);
|
||||
}
|
||||
}
|
||||
|
||||
runTests();
|
||||
@@ -47,6 +47,19 @@ echo "🚀 Starting mock data server..."
|
||||
export NODE_ENV=development
|
||||
export USE_MOCK_DATA=true
|
||||
export MOCK_DATA_ENABLED=true
|
||||
|
||||
# Load environment variables from .env if it exists
|
||||
if [ -f "$PROJECT_ROOT/.env" ]; then
|
||||
echo "Loading environment from .env"
|
||||
set -a
|
||||
source "$PROJECT_ROOT/.env"
|
||||
set +a
|
||||
# Override with mock data settings
|
||||
export NODE_ENV=development
|
||||
export USE_MOCK_DATA=true
|
||||
export MOCK_DATA_ENABLED=true
|
||||
fi
|
||||
|
||||
cd "$PROJECT_ROOT" && ts-node src/mock/run-server.ts > /tmp/pulse-mock-server.log 2>&1 &
|
||||
MOCK_SERVER_PID=$!
|
||||
echo "Mock server started with PID: $MOCK_SERVER_PID"
|
||||
@@ -73,7 +86,7 @@ if ! ps -p $BACKEND_PID > /dev/null; then
|
||||
fi
|
||||
|
||||
echo "🚀 Starting frontend server..."
|
||||
cd "$PROJECT_ROOT/frontend" && USE_MOCK_DATA=true MOCK_DATA_ENABLED=true npm run dev -- --host "0.0.0.0" --port 3000 > /tmp/pulse-frontend.log 2>&1 &
|
||||
cd "$PROJECT_ROOT/frontend" && USE_MOCK_DATA=true MOCK_DATA_ENABLED=true npm run dev -- --host "0.0.0.0" --port 7654 > /tmp/pulse-frontend.log 2>&1 &
|
||||
FRONTEND_PID=$!
|
||||
echo "Frontend server started with PID: $FRONTEND_PID"
|
||||
|
||||
@@ -82,15 +95,15 @@ echo "⏳ Waiting for servers to start..."
|
||||
sleep 15
|
||||
|
||||
# Verify services are running correctly
|
||||
if ! curl -s http://localhost:3000 > /dev/null; then
|
||||
echo "❌ Error: Frontend server is not running on port 3000"
|
||||
if ! curl -s http://localhost:7654 > /dev/null; then
|
||||
echo "❌ Error: Frontend server is not running on port 7654"
|
||||
cat /tmp/pulse-frontend.log
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Check if mock data server is responding
|
||||
if ! curl -s http://localhost:7655/status > /dev/null; then
|
||||
echo "❌ Error: Mock data server is not responding on port 7655"
|
||||
if ! curl -s http://localhost:7656/status > /dev/null; then
|
||||
echo "❌ Error: Mock data server is not responding on port 7656"
|
||||
cat /tmp/pulse-mock-server.log
|
||||
exit 1
|
||||
fi
|
||||
|
||||
Executable
+120
@@ -0,0 +1,120 @@
|
||||
#!/usr/bin/env node
|
||||
|
||||
/**
|
||||
* Verify Cluster Configuration Script
|
||||
*
|
||||
* This script checks the current environment configuration for cluster detection settings
|
||||
* and verifies that they are correctly applied.
|
||||
*
|
||||
* Usage: node scripts/verify-cluster-config.js
|
||||
*/
|
||||
|
||||
const fs = require('fs');
|
||||
const path = require('path');
|
||||
const dotenv = require('dotenv');
|
||||
|
||||
// Load environment variables from .env file
|
||||
const envFilePath = path.resolve(process.cwd(), '.env');
|
||||
if (!fs.existsSync(envFilePath)) {
|
||||
console.error('Error: .env file not found');
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
const envConfig = dotenv.parse(fs.readFileSync(envFilePath));
|
||||
|
||||
// Check cluster configuration
|
||||
console.log('=== Cluster Configuration ===');
|
||||
console.log(`PROXMOX_AUTO_DETECT_CLUSTER: ${envConfig.PROXMOX_AUTO_DETECT_CLUSTER || 'not set'}`);
|
||||
console.log(`PROXMOX_CLUSTER_MODE: ${envConfig.PROXMOX_CLUSTER_MODE || 'not set'}`);
|
||||
console.log(`MOCK_CLUSTER_ENABLED: ${envConfig.MOCK_CLUSTER_ENABLED || 'not set'}`);
|
||||
|
||||
// Check environment mode
|
||||
console.log('\n=== Environment Mode ===');
|
||||
console.log(`NODE_ENV: ${envConfig.NODE_ENV || 'not set'}`);
|
||||
console.log(`LOG_LEVEL: ${envConfig.LOG_LEVEL || 'not set'}`);
|
||||
console.log(`USE_MOCK_DATA: ${envConfig.USE_MOCK_DATA || 'not set'}`);
|
||||
console.log(`MOCK_DATA_ENABLED: ${envConfig.MOCK_DATA_ENABLED || 'not set'}`);
|
||||
|
||||
// Check if the configuration is consistent
|
||||
console.log('\n=== Configuration Analysis ===');
|
||||
|
||||
// Check if cluster detection is enabled
|
||||
const isClusterDetectionEnabled =
|
||||
envConfig.PROXMOX_AUTO_DETECT_CLUSTER === 'true' &&
|
||||
envConfig.PROXMOX_CLUSTER_MODE === 'true';
|
||||
|
||||
// Check if we're in development mode
|
||||
const isDevMode = envConfig.NODE_ENV === 'development';
|
||||
|
||||
// Check if we're using mock data
|
||||
const isMockDataEnabled =
|
||||
envConfig.USE_MOCK_DATA === 'true' &&
|
||||
envConfig.MOCK_DATA_ENABLED === 'true';
|
||||
|
||||
// Check if mock cluster is enabled
|
||||
const isMockClusterEnabled = envConfig.MOCK_CLUSTER_ENABLED === 'true';
|
||||
|
||||
// Check if log level is set to info
|
||||
const isLogLevelInfo = envConfig.LOG_LEVEL === 'info';
|
||||
|
||||
console.log(`Cluster Detection: ${isClusterDetectionEnabled ? 'Enabled' : 'Disabled'}`);
|
||||
console.log(`Development Mode: ${isDevMode ? 'Yes' : 'No'}`);
|
||||
console.log(`Log Level: ${envConfig.LOG_LEVEL || 'not set'}`);
|
||||
console.log(`Mock Data: ${isMockDataEnabled ? 'Enabled' : 'Disabled'}`);
|
||||
console.log(`Mock Cluster: ${isMockClusterEnabled ? 'Enabled' : 'Disabled'}`);
|
||||
|
||||
// Verify configuration consistency
|
||||
console.log('\n=== Configuration Consistency ===');
|
||||
|
||||
if (isDevMode) {
|
||||
if (isMockDataEnabled) {
|
||||
console.log('✓ Development mode is correctly using mock data');
|
||||
|
||||
if (isLogLevelInfo) {
|
||||
console.log('✓ Log level is correctly set to info for development mode');
|
||||
} else {
|
||||
console.log('✗ Log level should be set to info for development mode');
|
||||
}
|
||||
|
||||
if (isClusterDetectionEnabled) {
|
||||
console.log('✓ Cluster detection is correctly enabled for development mode');
|
||||
|
||||
if (isMockClusterEnabled) {
|
||||
console.log('✓ Mock cluster is correctly enabled for development mode with cluster detection');
|
||||
} else {
|
||||
console.log('✗ Mock cluster should be enabled for development mode with cluster detection');
|
||||
}
|
||||
} else {
|
||||
console.log('✗ Cluster detection should be enabled for development mode');
|
||||
|
||||
if (!isMockClusterEnabled) {
|
||||
console.log('✓ Mock cluster is correctly disabled for no-cluster mode');
|
||||
} else {
|
||||
console.log('✗ Mock cluster should be disabled for no-cluster mode');
|
||||
}
|
||||
}
|
||||
} else {
|
||||
console.log('✗ Development mode should use mock data');
|
||||
}
|
||||
} else {
|
||||
// Production mode
|
||||
if (!isMockDataEnabled) {
|
||||
console.log('✓ Production mode is correctly not using mock data');
|
||||
|
||||
if (isLogLevelInfo) {
|
||||
console.log('✓ Log level is correctly set to info for production mode');
|
||||
} else {
|
||||
console.log('✗ Log level should be set to info for production mode');
|
||||
}
|
||||
|
||||
if (isClusterDetectionEnabled) {
|
||||
console.log('✓ Cluster detection is correctly enabled for production mode');
|
||||
} else {
|
||||
console.log('✗ Cluster detection should be enabled for production mode');
|
||||
}
|
||||
} else {
|
||||
console.log('✗ Production mode should not use mock data');
|
||||
}
|
||||
}
|
||||
|
||||
console.log('\nVerification complete.');
|
||||
Reference in New Issue
Block a user