ezpm2gui 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/ .npmignore +39 -0
- package/README.md +102 -0
- package/bin/ezpm2gui.js +52 -0
- package/bin/generate-ecosystem.js +57 -0
- package/dist/index.d.ts +14 -0
- package/dist/index.js +18 -0
- package/dist/server/index.d.ts +5 -0
- package/dist/server/index.js +219 -0
- package/install.bat +22 -0
- package/install.sh +23 -0
- package/package.json +49 -0
- package/scripts/postinstall.js +36 -0
- package/src/client/build/asset-manifest.json +13 -0
- package/src/client/build/index.html +1 -0
- package/src/client/build/manifest.json +25 -0
- package/src/client/build/static/css/main.c1cbda3a.css +2 -0
- package/src/client/build/static/css/main.c1cbda3a.css.map +1 -0
- package/src/client/build/static/js/main.dde30e92.js +3 -0
- package/src/client/build/static/js/main.dde30e92.js.LICENSE.txt +53 -0
- package/src/client/build/static/js/main.dde30e92.js.map +1 -0
- package/src/client/package-lock.json +16192 -0
- package/src/client/package.json +39 -0
- package/src/client/public/index.html +20 -0
- package/src/client/public/manifest.json +25 -0
- package/src/index.ts +24 -0
- package/src/server/index.ts +240 -0
- package/tsconfig.json +18 -0
package/ .npmignore
ADDED
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
# Development files
|
|
2
|
+
src/
|
|
3
|
+
.git/
|
|
4
|
+
.github/
|
|
5
|
+
.gitignore
|
|
6
|
+
.editorconfig
|
|
7
|
+
.eslintrc
|
|
8
|
+
.prettierrc
|
|
9
|
+
tsconfig.json
|
|
10
|
+
nodemon.json
|
|
11
|
+
|
|
12
|
+
# Tests
|
|
13
|
+
__tests__/
|
|
14
|
+
coverage/
|
|
15
|
+
.nyc_output/
|
|
16
|
+
|
|
17
|
+
# Logs
|
|
18
|
+
logs/
|
|
19
|
+
*.log
|
|
20
|
+
npm-debug.log*
|
|
21
|
+
yarn-debug.log*
|
|
22
|
+
yarn-error.log*
|
|
23
|
+
|
|
24
|
+
# Cache and temp files
|
|
25
|
+
.cache/
|
|
26
|
+
.temp/
|
|
27
|
+
.tmp/
|
|
28
|
+
*.tmp
|
|
29
|
+
*.temp
|
|
30
|
+
|
|
31
|
+
# IDE specific files
|
|
32
|
+
.idea/
|
|
33
|
+
.vscode/
|
|
34
|
+
*.swp
|
|
35
|
+
*.swo
|
|
36
|
+
.DS_Store
|
|
37
|
+
|
|
38
|
+
# Include dist directory when publishing
|
|
39
|
+
!dist/
|
package/README.md
ADDED
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
# ezPM2GUI
|
|
2
|
+
|
|
3
|
+
A modern web-based graphical user interface for the PM2 process manager.
|
|
4
|
+
|
|
5
|
+

|
|
6
|
+
|
|
7
|
+
## Features
|
|
8
|
+
|
|
9
|
+
- Real-time process monitoring
|
|
10
|
+
- Process management (start, stop, restart, delete)
|
|
11
|
+
- Detailed process information and logs
|
|
12
|
+
- System metrics dashboard
|
|
13
|
+
- WebSocket for live updates
|
|
14
|
+
- Process CPU and memory charts
|
|
15
|
+
- Filter processes by status or name
|
|
16
|
+
- Responsive design for desktop and mobile
|
|
17
|
+
|
|
18
|
+
## Installation
|
|
19
|
+
|
|
20
|
+
### Global Installation
|
|
21
|
+
|
|
22
|
+
```bash
|
|
23
|
+
npm install -g ezpm2gui
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
### Local Installation
|
|
27
|
+
|
|
28
|
+
```bash
|
|
29
|
+
npm install ezpm2gui
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
## Usage
|
|
33
|
+
|
|
34
|
+
### As a Command Line Tool (Global Installation)
|
|
35
|
+
|
|
36
|
+
```bash
|
|
37
|
+
# Start the ezPM2GUI web interface
|
|
38
|
+
ezpm2gui
|
|
39
|
+
|
|
40
|
+
# Generate a sample PM2 ecosystem config
|
|
41
|
+
ezpm2gui-generate-ecosystem
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
### As a Module (Local Installation)
|
|
45
|
+
|
|
46
|
+
```javascript
|
|
47
|
+
const ezpm2gui = require('ezpm2gui');
|
|
48
|
+
|
|
49
|
+
// Start the server with default options
|
|
50
|
+
ezpm2gui.start();
|
|
51
|
+
|
|
52
|
+
// Or with custom options
|
|
53
|
+
ezpm2gui.start({
|
|
54
|
+
port: 3030,
|
|
55
|
+
host: '0.0.0.0'
|
|
56
|
+
});
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
### Access the UI
|
|
60
|
+
|
|
61
|
+
Once started, open your browser and navigate to:
|
|
62
|
+
|
|
63
|
+
```
|
|
64
|
+
http://localhost:3001
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
## Requirements
|
|
68
|
+
|
|
69
|
+
- Node.js 14.x or later
|
|
70
|
+
- PM2 installed globally (`npm install -g pm2`)
|
|
71
|
+
|
|
72
|
+
## Configuration
|
|
73
|
+
|
|
74
|
+
ezPM2GUI uses environment variables for configuration:
|
|
75
|
+
|
|
76
|
+
- `PORT`: The port to run the server on (default: 3001)
|
|
77
|
+
- `HOST`: The host to bind to (default: localhost)
|
|
78
|
+
|
|
79
|
+
## Development
|
|
80
|
+
|
|
81
|
+
See [DEVELOPMENT.md](DEVELOPMENT.md) for detailed development instructions.
|
|
82
|
+
|
|
83
|
+
```bash
|
|
84
|
+
# Clone the repository
|
|
85
|
+
git clone https://github.com/yourusername/ezpm2gui.git
|
|
86
|
+
cd ezpm2gui
|
|
87
|
+
|
|
88
|
+
# Install dependencies and build
|
|
89
|
+
./install.sh # On Linux/macOS
|
|
90
|
+
install.bat # On Windows
|
|
91
|
+
|
|
92
|
+
# Start the application
|
|
93
|
+
npm start
|
|
94
|
+
```
|
|
95
|
+
|
|
96
|
+
## License
|
|
97
|
+
|
|
98
|
+
ISC
|
|
99
|
+
|
|
100
|
+
## Credits
|
|
101
|
+
|
|
102
|
+
Built with ❤️ as a modern alternative to pm2-gui
|
package/bin/ezpm2gui.js
ADDED
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
const { spawn } = require('child_process');
|
|
4
|
+
const path = require('path');
|
|
5
|
+
const fs = require('fs');
|
|
6
|
+
|
|
7
|
+
// Determine the path to the server executable
|
|
8
|
+
const serverPath = path.join(__dirname, '../dist/server/index.js');
|
|
9
|
+
|
|
10
|
+
// Check if the server file exists
|
|
11
|
+
if (!fs.existsSync(serverPath)) {
|
|
12
|
+
console.error('Error: Server executable not found. Please make sure the package is built correctly.');
|
|
13
|
+
process.exit(1);
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
// Start the server
|
|
17
|
+
const server = spawn('node', [serverPath], { stdio: 'inherit' });
|
|
18
|
+
|
|
19
|
+
// Log startup message
|
|
20
|
+
console.log('\x1b[36m%s\x1b[0m', `
|
|
21
|
+
╔════════════════════════════════════╗
|
|
22
|
+
║ ezPM2GUI Started ║
|
|
23
|
+
╚════════════════════════════════════╝
|
|
24
|
+
|
|
25
|
+
Web interface available at: \x1b[1mhttp://localhost:3001\x1b[0m
|
|
26
|
+
|
|
27
|
+
Press Ctrl+C to stop the server.
|
|
28
|
+
`);
|
|
29
|
+
|
|
30
|
+
// Handle server process events
|
|
31
|
+
server.on('error', (err) => {
|
|
32
|
+
console.error('Failed to start server:', err);
|
|
33
|
+
process.exit(1);
|
|
34
|
+
});
|
|
35
|
+
|
|
36
|
+
server.on('exit', (code) => {
|
|
37
|
+
if (code !== 0) {
|
|
38
|
+
console.error(`Server exited with code ${code}`);
|
|
39
|
+
}
|
|
40
|
+
process.exit(code);
|
|
41
|
+
});
|
|
42
|
+
|
|
43
|
+
// Handle process signals for graceful shutdown
|
|
44
|
+
process.on('SIGINT', () => {
|
|
45
|
+
console.log('Shutting down ezPM2GUI...');
|
|
46
|
+
server.kill('SIGINT');
|
|
47
|
+
});
|
|
48
|
+
|
|
49
|
+
process.on('SIGTERM', () => {
|
|
50
|
+
console.log('Shutting down ezPM2GUI...');
|
|
51
|
+
server.kill('SIGTERM');
|
|
52
|
+
});
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
const fs = require('fs');
|
|
4
|
+
const path = require('path');
|
|
5
|
+
|
|
6
|
+
const ecosystemConfig = `
|
|
7
|
+
module.exports = {
|
|
8
|
+
apps : [
|
|
9
|
+
{
|
|
10
|
+
name: "my-api",
|
|
11
|
+
script: "./api/index.js",
|
|
12
|
+
instances: 2,
|
|
13
|
+
exec_mode: "cluster",
|
|
14
|
+
watch: false,
|
|
15
|
+
env: {
|
|
16
|
+
NODE_ENV: "production",
|
|
17
|
+
PORT: 3000
|
|
18
|
+
}
|
|
19
|
+
},
|
|
20
|
+
{
|
|
21
|
+
name: "worker",
|
|
22
|
+
script: "./workers/queue-processor.js",
|
|
23
|
+
instances: 1,
|
|
24
|
+
watch: false,
|
|
25
|
+
env: {
|
|
26
|
+
NODE_ENV: "production"
|
|
27
|
+
}
|
|
28
|
+
},
|
|
29
|
+
{
|
|
30
|
+
name: "cron-job",
|
|
31
|
+
script: "./cron/scheduler.js",
|
|
32
|
+
instances: 1,
|
|
33
|
+
watch: false,
|
|
34
|
+
cron_restart: "0 0 * * *",
|
|
35
|
+
env: {
|
|
36
|
+
NODE_ENV: "production"
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
]
|
|
40
|
+
}
|
|
41
|
+
`;
|
|
42
|
+
|
|
43
|
+
// Get the output path
|
|
44
|
+
const outputPath = process.argv[2] || 'ecosystem.config.js';
|
|
45
|
+
const fullPath = path.resolve(process.cwd(), outputPath);
|
|
46
|
+
|
|
47
|
+
try {
|
|
48
|
+
// Write file
|
|
49
|
+
fs.writeFileSync(fullPath, ecosystemConfig);
|
|
50
|
+
console.log(`PM2 ecosystem file generated at: ${fullPath}`);
|
|
51
|
+
console.log('\nTo start your PM2 processes with this configuration:');
|
|
52
|
+
console.log(' pm2 start ecosystem.config.js');
|
|
53
|
+
console.log('\nTo monitor your processes with ezPM2GUI:');
|
|
54
|
+
console.log(' ezpm2gui');
|
|
55
|
+
} catch (error) {
|
|
56
|
+
console.error('Error generating ecosystem file:', error);
|
|
57
|
+
}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
interface StartOptions {
|
|
2
|
+
port?: number;
|
|
3
|
+
host?: string;
|
|
4
|
+
}
|
|
5
|
+
/**
|
|
6
|
+
* Start the ezPM2GUI server
|
|
7
|
+
* @param options Configuration options
|
|
8
|
+
* @returns The HTTP server instance
|
|
9
|
+
*/
|
|
10
|
+
export declare function start(options?: StartOptions): import("http").Server<typeof import("http").IncomingMessage, typeof import("http").ServerResponse>;
|
|
11
|
+
declare const _default: {
|
|
12
|
+
start: typeof start;
|
|
13
|
+
};
|
|
14
|
+
export default _default;
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.start = start;
|
|
4
|
+
// src/index.ts - Main entry point for programmatic usage
|
|
5
|
+
const index_1 = require("./server/index");
|
|
6
|
+
/**
|
|
7
|
+
* Start the ezPM2GUI server
|
|
8
|
+
* @param options Configuration options
|
|
9
|
+
* @returns The HTTP server instance
|
|
10
|
+
*/
|
|
11
|
+
function start(options = {}) {
|
|
12
|
+
const port = options.port || process.env.PORT || 3001;
|
|
13
|
+
const host = options.host || process.env.HOST || 'localhost';
|
|
14
|
+
process.env.PORT = port.toString();
|
|
15
|
+
process.env.HOST = host;
|
|
16
|
+
return (0, index_1.createServer)();
|
|
17
|
+
}
|
|
18
|
+
exports.default = { start };
|
|
@@ -0,0 +1,219 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.createServer = createServer;
|
|
7
|
+
const express_1 = __importDefault(require("express"));
|
|
8
|
+
const http_1 = __importDefault(require("http"));
|
|
9
|
+
const socket_io_1 = require("socket.io");
|
|
10
|
+
const pm2_1 = __importDefault(require("pm2"));
|
|
11
|
+
const os_1 = __importDefault(require("os"));
|
|
12
|
+
/**
|
|
13
|
+
* Create and configure the express server
|
|
14
|
+
*/
|
|
15
|
+
function createServer() {
|
|
16
|
+
// Initialize Express app
|
|
17
|
+
const app = (0, express_1.default)();
|
|
18
|
+
const server = http_1.default.createServer(app);
|
|
19
|
+
const io = new socket_io_1.Server(server, {
|
|
20
|
+
cors: {
|
|
21
|
+
origin: '*',
|
|
22
|
+
methods: ['GET', 'POST']
|
|
23
|
+
}
|
|
24
|
+
}); // Serve static files from the React app build directory
|
|
25
|
+
const staticPath = 'D:/Personal/ezpm2gui/src/client/build';
|
|
26
|
+
console.log('Serving static files from:', staticPath);
|
|
27
|
+
const fs = require('fs');
|
|
28
|
+
if (fs.existsSync(staticPath)) {
|
|
29
|
+
app.use(express_1.default.static(staticPath));
|
|
30
|
+
}
|
|
31
|
+
else {
|
|
32
|
+
console.error('Static files directory not found at:', staticPath);
|
|
33
|
+
}
|
|
34
|
+
// PM2 API endpoints
|
|
35
|
+
app.get('/api/processes', (req, res) => {
|
|
36
|
+
pm2_1.default.connect((err) => {
|
|
37
|
+
if (err) {
|
|
38
|
+
console.error(err);
|
|
39
|
+
res.status(500).json({ error: 'Failed to connect to PM2' });
|
|
40
|
+
return;
|
|
41
|
+
}
|
|
42
|
+
pm2_1.default.list((err, processList) => {
|
|
43
|
+
pm2_1.default.disconnect();
|
|
44
|
+
if (err) {
|
|
45
|
+
console.error(err);
|
|
46
|
+
res.status(500).json({ error: 'Failed to get PM2 processes' });
|
|
47
|
+
return;
|
|
48
|
+
}
|
|
49
|
+
res.json(processList);
|
|
50
|
+
});
|
|
51
|
+
});
|
|
52
|
+
});
|
|
53
|
+
// Action endpoints (start, stop, restart, delete)
|
|
54
|
+
app.post('/api/process/:id/:action', (req, res) => {
|
|
55
|
+
const { id, action } = req.params;
|
|
56
|
+
pm2_1.default.connect((err) => {
|
|
57
|
+
if (err) {
|
|
58
|
+
console.error(err);
|
|
59
|
+
res.status(500).json({ error: 'Failed to connect to PM2' });
|
|
60
|
+
return;
|
|
61
|
+
}
|
|
62
|
+
const processAction = (actionName, cb) => {
|
|
63
|
+
switch (actionName) {
|
|
64
|
+
case 'start':
|
|
65
|
+
pm2_1.default.start(id, cb);
|
|
66
|
+
break;
|
|
67
|
+
case 'stop':
|
|
68
|
+
pm2_1.default.stop(id, cb);
|
|
69
|
+
break;
|
|
70
|
+
case 'restart':
|
|
71
|
+
pm2_1.default.restart(id, cb);
|
|
72
|
+
break;
|
|
73
|
+
case 'delete':
|
|
74
|
+
pm2_1.default.delete(id, cb);
|
|
75
|
+
break;
|
|
76
|
+
default:
|
|
77
|
+
cb(new Error('Invalid action'));
|
|
78
|
+
}
|
|
79
|
+
};
|
|
80
|
+
processAction(action, (err) => {
|
|
81
|
+
pm2_1.default.disconnect();
|
|
82
|
+
if (err) {
|
|
83
|
+
console.error(err);
|
|
84
|
+
res.status(500).json({ error: `Failed to ${action} process` });
|
|
85
|
+
return;
|
|
86
|
+
}
|
|
87
|
+
res.json({ success: true, message: `Process ${id} ${action} request received` });
|
|
88
|
+
});
|
|
89
|
+
});
|
|
90
|
+
});
|
|
91
|
+
// Get system metrics
|
|
92
|
+
app.get('/api/metrics', (req, res) => {
|
|
93
|
+
const metrics = {
|
|
94
|
+
loadAvg: os_1.default.loadavg(),
|
|
95
|
+
memory: {
|
|
96
|
+
total: os_1.default.totalmem(),
|
|
97
|
+
free: os_1.default.freemem(),
|
|
98
|
+
used: os_1.default.totalmem() - os_1.default.freemem()
|
|
99
|
+
},
|
|
100
|
+
uptime: os_1.default.uptime(),
|
|
101
|
+
cpus: os_1.default.cpus().length
|
|
102
|
+
};
|
|
103
|
+
res.json(metrics);
|
|
104
|
+
});
|
|
105
|
+
// Get process logs
|
|
106
|
+
app.get('/api/logs/:id/:type', (req, res) => {
|
|
107
|
+
const { id, type } = req.params;
|
|
108
|
+
const logType = type === 'err' ? 'err' : 'out';
|
|
109
|
+
pm2_1.default.connect((err) => {
|
|
110
|
+
if (err) {
|
|
111
|
+
console.error(err);
|
|
112
|
+
res.status(500).json({ error: 'Failed to connect to PM2' });
|
|
113
|
+
return;
|
|
114
|
+
}
|
|
115
|
+
pm2_1.default.describe(id, (err, processDesc) => {
|
|
116
|
+
var _a, _b;
|
|
117
|
+
if (err || !processDesc || processDesc.length === 0) {
|
|
118
|
+
pm2_1.default.disconnect();
|
|
119
|
+
res.status(404).json({ error: 'Process not found' });
|
|
120
|
+
return;
|
|
121
|
+
}
|
|
122
|
+
const logPath = (_b = (_a = processDesc[0]) === null || _a === void 0 ? void 0 : _a.pm2_env) === null || _b === void 0 ? void 0 : _b[`pm_${logType}_log_path`];
|
|
123
|
+
if (!logPath) {
|
|
124
|
+
pm2_1.default.disconnect();
|
|
125
|
+
res.status(404).json({ error: `Log file for ${logType} not found` });
|
|
126
|
+
return;
|
|
127
|
+
}
|
|
128
|
+
try {
|
|
129
|
+
// Read the log file using Node.js fs instead of exec
|
|
130
|
+
const fs = require('fs');
|
|
131
|
+
let logContent = '';
|
|
132
|
+
if (fs.existsSync(logPath)) {
|
|
133
|
+
// Read the last part of the file (up to 10KB to avoid huge responses)
|
|
134
|
+
const stats = fs.statSync(logPath);
|
|
135
|
+
const fileSize = stats.size;
|
|
136
|
+
const readSize = Math.min(fileSize, 10 * 1024); // 10KB max
|
|
137
|
+
const position = Math.max(0, fileSize - readSize);
|
|
138
|
+
const buffer = Buffer.alloc(readSize);
|
|
139
|
+
const fd = fs.openSync(logPath, 'r');
|
|
140
|
+
fs.readSync(fd, buffer, 0, readSize, position);
|
|
141
|
+
fs.closeSync(fd);
|
|
142
|
+
logContent = buffer.toString('utf8');
|
|
143
|
+
}
|
|
144
|
+
const logs = logContent.split('\n').filter((line) => line.trim() !== '');
|
|
145
|
+
pm2_1.default.disconnect();
|
|
146
|
+
res.json({ logs });
|
|
147
|
+
}
|
|
148
|
+
catch (error) {
|
|
149
|
+
console.error(`Error reading log file: ${error}`);
|
|
150
|
+
pm2_1.default.disconnect();
|
|
151
|
+
res.status(500).json({ error: 'Failed to read log file' });
|
|
152
|
+
}
|
|
153
|
+
});
|
|
154
|
+
});
|
|
155
|
+
});
|
|
156
|
+
// WebSocket for real-time updates
|
|
157
|
+
io.on('connection', (socket) => {
|
|
158
|
+
console.log('Client connected');
|
|
159
|
+
// Send process updates every 3 seconds
|
|
160
|
+
const processInterval = setInterval(() => {
|
|
161
|
+
pm2_1.default.connect((err) => {
|
|
162
|
+
if (err) {
|
|
163
|
+
console.error(err);
|
|
164
|
+
return;
|
|
165
|
+
}
|
|
166
|
+
pm2_1.default.list((err, processList) => {
|
|
167
|
+
pm2_1.default.disconnect();
|
|
168
|
+
if (err) {
|
|
169
|
+
console.error(err);
|
|
170
|
+
return;
|
|
171
|
+
}
|
|
172
|
+
socket.emit('processes', processList);
|
|
173
|
+
});
|
|
174
|
+
});
|
|
175
|
+
}, 3000);
|
|
176
|
+
// Send system metrics every 2 seconds
|
|
177
|
+
const metricsInterval = setInterval(() => {
|
|
178
|
+
const metrics = {
|
|
179
|
+
loadAvg: os_1.default.loadavg(),
|
|
180
|
+
memory: {
|
|
181
|
+
total: os_1.default.totalmem(),
|
|
182
|
+
free: os_1.default.freemem(),
|
|
183
|
+
used: os_1.default.totalmem() - os_1.default.freemem()
|
|
184
|
+
},
|
|
185
|
+
uptime: os_1.default.uptime(),
|
|
186
|
+
cpus: os_1.default.cpus().length
|
|
187
|
+
};
|
|
188
|
+
socket.emit('metrics', metrics);
|
|
189
|
+
}, 2000);
|
|
190
|
+
socket.on('disconnect', () => {
|
|
191
|
+
console.log('Client disconnected');
|
|
192
|
+
clearInterval(processInterval);
|
|
193
|
+
clearInterval(metricsInterval);
|
|
194
|
+
});
|
|
195
|
+
}); // Catch-all route to return the React app
|
|
196
|
+
app.get('*', (req, res) => {
|
|
197
|
+
const indexPath = 'D:/Personal/ezpm2gui/src/client/build/index.html';
|
|
198
|
+
console.log('Trying to serve index.html from:', indexPath);
|
|
199
|
+
const fs = require('fs');
|
|
200
|
+
if (fs.existsSync(indexPath)) {
|
|
201
|
+
res.sendFile(indexPath);
|
|
202
|
+
}
|
|
203
|
+
else {
|
|
204
|
+
console.error('Index.html file not found at:', indexPath);
|
|
205
|
+
res.status(404).send('File not found. Please check server configuration.');
|
|
206
|
+
}
|
|
207
|
+
});
|
|
208
|
+
// Return the server instance
|
|
209
|
+
return server;
|
|
210
|
+
}
|
|
211
|
+
// Only start the server if this file is run directly
|
|
212
|
+
if (require.main === module) {
|
|
213
|
+
const PORT = process.env.PORT || 3001;
|
|
214
|
+
const HOST = process.env.HOST || 'localhost';
|
|
215
|
+
const server = createServer();
|
|
216
|
+
server.listen(PORT, () => {
|
|
217
|
+
console.log(`Server running on http://${HOST}:${PORT}`);
|
|
218
|
+
});
|
|
219
|
+
}
|
package/install.bat
ADDED
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
@echo off
|
|
2
|
+
echo Installing client dependencies...
|
|
3
|
+
cd src\client
|
|
4
|
+
call npm install
|
|
5
|
+
|
|
6
|
+
echo Building client...
|
|
7
|
+
call npm run build
|
|
8
|
+
|
|
9
|
+
echo Installing server dependencies...
|
|
10
|
+
cd ..\..
|
|
11
|
+
call npm install
|
|
12
|
+
|
|
13
|
+
echo Building server...
|
|
14
|
+
call npm run build
|
|
15
|
+
|
|
16
|
+
echo.
|
|
17
|
+
echo ======================================
|
|
18
|
+
echo Installation complete!
|
|
19
|
+
echo.
|
|
20
|
+
echo To start the application, run:
|
|
21
|
+
echo npm start
|
|
22
|
+
echo ======================================
|
package/install.sh
ADDED
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
|
|
3
|
+
echo "Installing client dependencies..."
|
|
4
|
+
cd src/client
|
|
5
|
+
npm install
|
|
6
|
+
|
|
7
|
+
echo "Building client..."
|
|
8
|
+
npm run build
|
|
9
|
+
|
|
10
|
+
echo "Installing server dependencies..."
|
|
11
|
+
cd ../..
|
|
12
|
+
npm install
|
|
13
|
+
|
|
14
|
+
echo "Building server..."
|
|
15
|
+
npm run build
|
|
16
|
+
|
|
17
|
+
echo ""
|
|
18
|
+
echo "======================================"
|
|
19
|
+
echo "Installation complete!"
|
|
20
|
+
echo ""
|
|
21
|
+
echo "To start the application, run:"
|
|
22
|
+
echo "npm start"
|
|
23
|
+
echo "======================================="
|
package/package.json
ADDED
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "ezpm2gui",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"main": "dist/server/index.js",
|
|
5
|
+
"bin": {
|
|
6
|
+
"ezpm2gui": "./bin/ezpm2gui.js",
|
|
7
|
+
"ezpm2gui-generate-ecosystem": "./bin/generate-ecosystem.js"
|
|
8
|
+
},
|
|
9
|
+
"scripts": {
|
|
10
|
+
"start": "node dist/server/index.js",
|
|
11
|
+
"dev": "concurrently \"npm run dev:server\" \"npm run dev:client\"",
|
|
12
|
+
"dev:server": "nodemon --exec ts-node src/server/index.ts",
|
|
13
|
+
"dev:client": "cd src/client && npm start",
|
|
14
|
+
"build": "npm run build:server && npm run build:client",
|
|
15
|
+
"build:server": "tsc",
|
|
16
|
+
"build:client": "cd src/client && npm run build",
|
|
17
|
+
"prepare": "npm run build",
|
|
18
|
+
"test": "echo \"Error: no test specified\" && exit 1",
|
|
19
|
+
"postinstall": "node scripts/postinstall.js"
|
|
20
|
+
},
|
|
21
|
+
"keywords": ["pm2", "gui", "monitor", "process-manager", "dashboard"],
|
|
22
|
+
"author": "Chandan Bhagat",
|
|
23
|
+
"license": "ISC",
|
|
24
|
+
"repository": {
|
|
25
|
+
"type": "git",
|
|
26
|
+
"url": "git+https://github.com/thechandanbhagat/ezpm2gui.git"
|
|
27
|
+
},
|
|
28
|
+
"description": "A modern web-based GUI for PM2 process manager",
|
|
29
|
+
"dependencies": {
|
|
30
|
+
"axios": "^1.9.0",
|
|
31
|
+
"chart.js": "^4.4.9",
|
|
32
|
+
"express": "^4.18.3",
|
|
33
|
+
"pm2": "^6.0.5",
|
|
34
|
+
"react": "^19.1.0",
|
|
35
|
+
"react-dom": "^19.1.0",
|
|
36
|
+
"react-scripts": "^5.0.1",
|
|
37
|
+
"socket.io": "^4.8.1"
|
|
38
|
+
},
|
|
39
|
+
"devDependencies": {
|
|
40
|
+
"@types/express": "^4.17.21",
|
|
41
|
+
"@types/node": "^22.15.17",
|
|
42
|
+
"@types/react": "^19.1.3",
|
|
43
|
+
"@types/react-dom": "^19.1.4",
|
|
44
|
+
"@types/socket.io": "^3.0.2",
|
|
45
|
+
"concurrently": "^9.1.2",
|
|
46
|
+
"nodemon": "^3.1.10",
|
|
47
|
+
"typescript": "^5.8.3"
|
|
48
|
+
}
|
|
49
|
+
}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
const { execSync } = require('child_process');
|
|
2
|
+
const fs = require('fs');
|
|
3
|
+
const path = require('path');
|
|
4
|
+
|
|
5
|
+
console.log('Running postinstall script...');
|
|
6
|
+
|
|
7
|
+
const isGlobalInstall = process.env.npm_config_global === 'true';
|
|
8
|
+
if (isGlobalInstall) {
|
|
9
|
+
console.log('Global installation detected, skipping client dependencies.');
|
|
10
|
+
process.exit(0);
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
// Check if we're in a development environment
|
|
14
|
+
const clientDir = path.join(__dirname, '..', 'src', 'client');
|
|
15
|
+
const clientNodeModules = path.join(clientDir, 'node_modules');
|
|
16
|
+
const packageJsonPath = path.join(clientDir, 'package.json');
|
|
17
|
+
|
|
18
|
+
if (fs.existsSync(packageJsonPath) && !fs.existsSync(clientNodeModules)) {
|
|
19
|
+
console.log('Installing client dependencies...');
|
|
20
|
+
try {
|
|
21
|
+
// Change to client directory
|
|
22
|
+
process.chdir(clientDir);
|
|
23
|
+
|
|
24
|
+
// Install dependencies
|
|
25
|
+
execSync('npm install', { stdio: 'inherit' });
|
|
26
|
+
|
|
27
|
+
console.log('Client dependencies installed successfully.');
|
|
28
|
+
} catch (error) {
|
|
29
|
+
console.error('Error installing client dependencies:', error.message);
|
|
30
|
+
console.error('Please run "cd src/client && npm install" manually.');
|
|
31
|
+
}
|
|
32
|
+
} else {
|
|
33
|
+
console.log('Client dependencies already installed or client package.json not found.');
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
console.log('Postinstall completed.');
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
{
|
|
2
|
+
"files": {
|
|
3
|
+
"main.css": "/static/css/main.c1cbda3a.css",
|
|
4
|
+
"main.js": "/static/js/main.dde30e92.js",
|
|
5
|
+
"index.html": "/index.html",
|
|
6
|
+
"main.c1cbda3a.css.map": "/static/css/main.c1cbda3a.css.map",
|
|
7
|
+
"main.dde30e92.js.map": "/static/js/main.dde30e92.js.map"
|
|
8
|
+
},
|
|
9
|
+
"entrypoints": [
|
|
10
|
+
"static/css/main.c1cbda3a.css",
|
|
11
|
+
"static/js/main.dde30e92.js"
|
|
12
|
+
]
|
|
13
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
<!doctype html><html lang="en"><head><meta charset="utf-8"/><link rel="icon" href="/favicon.ico"/><meta name="viewport" content="width=device-width,initial-scale=1"/><meta name="theme-color" content="#4a90e2"/><meta name="description" content="ezPM2GUI - A modern interface for PM2 process manager"/><link rel="apple-touch-icon" href="/logo192.png"/><link rel="manifest" href="/manifest.json"/><title>ezPM2GUI - PM2 Process Manager</title><script defer="defer" src="/static/js/main.dde30e92.js"></script><link href="/static/css/main.c1cbda3a.css" rel="stylesheet"></head><body><noscript>You need to enable JavaScript to run this app.</noscript><div id="root"></div></body></html>
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
{
|
|
2
|
+
"short_name": "ezPM2GUI",
|
|
3
|
+
"name": "ezPM2GUI - Modern PM2 Interface",
|
|
4
|
+
"icons": [
|
|
5
|
+
{
|
|
6
|
+
"src": "favicon.ico",
|
|
7
|
+
"sizes": "64x64 32x32 24x24 16x16",
|
|
8
|
+
"type": "image/x-icon"
|
|
9
|
+
},
|
|
10
|
+
{
|
|
11
|
+
"src": "logo192.png",
|
|
12
|
+
"type": "image/png",
|
|
13
|
+
"sizes": "192x192"
|
|
14
|
+
},
|
|
15
|
+
{
|
|
16
|
+
"src": "logo512.png",
|
|
17
|
+
"type": "image/png",
|
|
18
|
+
"sizes": "512x512"
|
|
19
|
+
}
|
|
20
|
+
],
|
|
21
|
+
"start_url": ".",
|
|
22
|
+
"display": "standalone",
|
|
23
|
+
"theme_color": "#4a90e2",
|
|
24
|
+
"background_color": "#f8f9fa"
|
|
25
|
+
}
|