ezpm2gui 1.6.0 → 1.8.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.
Files changed (41) hide show
  1. package/README.md +330 -321
  2. package/bin/ezpm2gui.js +8 -8
  3. package/bin/ezpm2gui.ts +51 -51
  4. package/bin/generate-ecosystem.js +35 -35
  5. package/bin/generate-ecosystem.ts +56 -56
  6. package/dist/server/config/cron-jobs.json +1 -0
  7. package/dist/server/config/project-configs.json +235 -236
  8. package/dist/server/config/remote-connections.json +3 -0
  9. package/dist/server/index.js +42 -3
  10. package/dist/server/routes/deployApplication.js +47 -45
  11. package/dist/server/routes/logStreaming.js +31 -24
  12. package/dist/server/routes/modules.js +55 -0
  13. package/dist/server/routes/pageAuth.js +3 -3
  14. package/dist/server/routes/remoteConnections.js +13 -9
  15. package/dist/server/routes/remoteMetrics.d.ts +3 -0
  16. package/dist/server/routes/remoteMetrics.js +84 -0
  17. package/dist/server/services/ProjectSetupService.d.ts +1 -1
  18. package/dist/server/services/ProjectSetupService.js +25 -9
  19. package/dist/server/utils/metrics-history.d.ts +21 -0
  20. package/dist/server/utils/metrics-history.js +68 -0
  21. package/dist/server/utils/remote-metrics-db.d.ts +29 -0
  22. package/dist/server/utils/remote-metrics-db.js +134 -0
  23. package/dist/server/utils/remote-metrics-poller.d.ts +8 -0
  24. package/dist/server/utils/remote-metrics-poller.js +67 -0
  25. package/package.json +86 -73
  26. package/scripts/postinstall.js +36 -36
  27. package/src/client/build/asset-manifest.json +6 -6
  28. package/src/client/build/favicon.ico +2 -2
  29. package/src/client/build/index.html +1 -1
  30. package/src/client/build/logo192.svg +7 -7
  31. package/src/client/build/logo512.svg +7 -7
  32. package/src/client/build/manifest.json +24 -24
  33. package/src/client/build/static/css/main.9decb204.css +5 -0
  34. package/src/client/build/static/css/main.9decb204.css.map +1 -0
  35. package/src/client/build/static/js/main.28a4a583.js +3 -0
  36. package/src/client/build/static/js/main.28a4a583.js.map +1 -0
  37. package/src/client/build/static/css/main.775772ee.css +0 -5
  38. package/src/client/build/static/css/main.775772ee.css.map +0 -1
  39. package/src/client/build/static/js/main.cbcb09c9.js +0 -3
  40. package/src/client/build/static/js/main.cbcb09c9.js.map +0 -1
  41. /package/src/client/build/static/js/{main.cbcb09c9.js.LICENSE.txt → main.28a4a583.js.LICENSE.txt} +0 -0
@@ -1,236 +1,235 @@
1
- {
2
- "projectTypes": {
3
- "node": {
4
- "name": "Node.js",
5
- "detection": {
6
- "files": ["package.json"],
7
- "extensions": [".js", ".ts", ".jsx", ".tsx"]
8
- },
9
- "setup": {
10
- "steps": [
11
- {
12
- "name": "Check Node.js version",
13
- "command": "node --version",
14
- "description": "Verifying Node.js installation",
15
- "required": true
16
- },
17
- {
18
- "name": "Install dependencies",
19
- "command": "npm install",
20
- "description": "Installing project dependencies",
21
- "required": true,
22
- "workingDirectory": "project"
23
- },
24
- {
25
- "name": "Build project (if build script exists)",
26
- "command": "npm run build",
27
- "description": "Building the project",
28
- "required": false,
29
- "conditional": "build_script_exists",
30
- "workingDirectory": "project"
31
- },
32
- {
33
- "name": "Run tests (if test script exists)",
34
- "command": "npm test",
35
- "description": "Running tests",
36
- "required": false,
37
- "conditional": "test_script_exists",
38
- "workingDirectory": "project"
39
- }
40
- ],
41
- "environment": {
42
- "NODE_ENV": "production"
43
- }
44
- },
45
- "validation": {
46
- "checks": [
47
- {
48
- "name": "package.json exists",
49
- "file": "package.json"
50
- },
51
- {
52
- "name": "node_modules exists after install",
53
- "directory": "node_modules"
54
- }
55
- ]
56
- },
57
- "defaultConfig": {
58
- "interpreter": "node",
59
- "execMode": "fork",
60
- "supportsCluster": true,
61
- "startScript": "npm start"
62
- }
63
- },
64
- "python": {
65
- "name": "Python",
66
- "detection": {
67
- "files": ["requirements.txt", "pyproject.toml", "setup.py", "Pipfile"],
68
- "extensions": [".py"]
69
- },
70
- "setup": {
71
- "steps": [
72
- {
73
- "name": "Check Python version",
74
- "command": "python --version",
75
- "description": "Verifying Python installation",
76
- "required": true
77
- },
78
- {
79
- "name": "Create virtual environment",
80
- "command": "python -m venv venv",
81
- "description": "Creating Python virtual environment",
82
- "required": true,
83
- "workingDirectory": "project"
84
- },
85
- {
86
- "name": "Activate virtual environment (Windows)",
87
- "command": ".\\venv\\Scripts\\Activate.ps1",
88
- "description": "Activating virtual environment",
89
- "required": true,
90
- "platform": "win32",
91
- "workingDirectory": "project"
92
- },
93
- {
94
- "name": "Activate virtual environment (Unix)",
95
- "command": "source venv/bin/activate",
96
- "description": "Activating virtual environment",
97
- "required": true,
98
- "platform": "unix",
99
- "workingDirectory": "project"
100
- },
101
- {
102
- "name": "Upgrade pip",
103
- "command": "python -m pip install --upgrade pip",
104
- "description": "Upgrading pip",
105
- "required": true,
106
- "workingDirectory": "project",
107
- "useVenv": true
108
- },
109
- {
110
- "name": "Install requirements",
111
- "command": "pip install -r requirements.txt",
112
- "description": "Installing Python dependencies",
113
- "required": true,
114
- "conditional": "requirements_exists",
115
- "workingDirectory": "project",
116
- "useVenv": true
117
- },
118
- {
119
- "name": "Install from pyproject.toml",
120
- "command": "pip install -e .",
121
- "description": "Installing from pyproject.toml",
122
- "required": true,
123
- "conditional": "pyproject_exists",
124
- "workingDirectory": "project",
125
- "useVenv": true
126
- }
127
- ],
128
- "environment": {
129
- "PYTHONPATH": ".",
130
- "PYTHON_UNBUFFERED": "1"
131
- }
132
- },
133
- "validation": {
134
- "checks": [
135
- {
136
- "name": "Virtual environment created",
137
- "directory": "venv"
138
- },
139
- {
140
- "name": "Requirements file exists",
141
- "file": "requirements.txt",
142
- "optional": true
143
- }
144
- ]
145
- },
146
- "defaultConfig": {
147
- "interpreter": "python",
148
- "execMode": "fork",
149
- "supportsCluster": false,
150
- "interpreterPath": "venv/Scripts/python.exe"
151
- }
152
- },
153
- "dotnet": {
154
- "name": ".NET",
155
- "detection": {
156
- "files": ["*.csproj", "*.fsproj", "*.vbproj", "*.sln"],
157
- "extensions": [".cs", ".fs", ".vb"]
158
- },
159
- "setup": {
160
- "steps": [
161
- {
162
- "name": "Check .NET version",
163
- "command": "dotnet --version",
164
- "description": "Verifying .NET installation",
165
- "required": true
166
- },
167
- {
168
- "name": "Restore packages",
169
- "command": "dotnet restore",
170
- "description": "Restoring NuGet packages",
171
- "required": true,
172
- "workingDirectory": "project"
173
- },
174
- {
175
- "name": "Build project",
176
- "command": "dotnet build --configuration Release",
177
- "description": "Building .NET project",
178
- "required": true,
179
- "workingDirectory": "project"
180
- },
181
- {
182
- "name": "Publish project",
183
- "command": "dotnet publish --configuration Release --output ./publish",
184
- "description": "Publishing .NET project",
185
- "required": true,
186
- "workingDirectory": "project"
187
- },
188
- {
189
- "name": "Run tests",
190
- "command": "dotnet test",
191
- "description": "Running .NET tests",
192
- "required": false,
193
- "conditional": "test_project_exists",
194
- "workingDirectory": "project"
195
- }
196
- ],
197
- "environment": {
198
- "DOTNET_ENVIRONMENT": "Production",
199
- "ASPNETCORE_ENVIRONMENT": "Production"
200
- }
201
- },
202
- "validation": {
203
- "checks": [
204
- {
205
- "name": "Project file exists",
206
- "pattern": "*.csproj"
207
- },
208
- {
209
- "name": "Publish directory exists",
210
- "directory": "publish"
211
- }
212
- ]
213
- },
214
- "defaultConfig": {
215
- "interpreter": "dotnet",
216
- "execMode": "fork",
217
- "supportsCluster": false,
218
- "startCommand": "dotnet run"
219
- }
220
- }
221
- },
222
- "global": {
223
- "timeouts": {
224
- "setup": 300000,
225
- "validation": 30000
226
- },
227
- "retries": {
228
- "setup": 2,
229
- "validation": 1
230
- },
231
- "logging": {
232
- "level": "info",
233
- "file": "deployment.log"
234
- }
235
- }
236
- }
1
+ {
2
+ "projectTypes": {
3
+ "node": {
4
+ "name": "Node.js",
5
+ "detection": {
6
+ "files": ["package.json"],
7
+ "extensions": [".js", ".ts", ".jsx", ".tsx"]
8
+ },
9
+ "setup": {
10
+ "steps": [
11
+ {
12
+ "name": "Check Node.js version",
13
+ "command": "node --version",
14
+ "description": "Verifying Node.js installation",
15
+ "required": true
16
+ },
17
+ {
18
+ "name": "Install dependencies",
19
+ "command": "npm install",
20
+ "description": "Installing project dependencies",
21
+ "required": true,
22
+ "workingDirectory": "project"
23
+ },
24
+ {
25
+ "name": "Build project (if build script exists)",
26
+ "command": "npm run build",
27
+ "description": "Building the project",
28
+ "required": false,
29
+ "conditional": "build_script_exists",
30
+ "workingDirectory": "project"
31
+ },
32
+ {
33
+ "name": "Run tests (if test script exists)",
34
+ "command": "npm test",
35
+ "description": "Running tests",
36
+ "required": false,
37
+ "conditional": "test_script_exists",
38
+ "workingDirectory": "project"
39
+ }
40
+ ],
41
+ "environment": {}
42
+ },
43
+ "validation": {
44
+ "checks": [
45
+ {
46
+ "name": "package.json exists",
47
+ "file": "package.json"
48
+ },
49
+ {
50
+ "name": "node_modules exists after install",
51
+ "directory": "node_modules",
52
+ "optional": true
53
+ }
54
+ ]
55
+ },
56
+ "defaultConfig": {
57
+ "interpreter": "node",
58
+ "execMode": "fork",
59
+ "supportsCluster": true,
60
+ "startScript": "npm start"
61
+ }
62
+ },
63
+ "python": {
64
+ "name": "Python",
65
+ "detection": {
66
+ "files": ["requirements.txt", "pyproject.toml", "setup.py", "Pipfile"],
67
+ "extensions": [".py"]
68
+ },
69
+ "setup": {
70
+ "steps": [
71
+ {
72
+ "name": "Check Python version",
73
+ "command": "python --version",
74
+ "description": "Verifying Python installation",
75
+ "required": true
76
+ },
77
+ {
78
+ "name": "Create virtual environment",
79
+ "command": "python -m venv venv",
80
+ "description": "Creating Python virtual environment",
81
+ "required": true,
82
+ "workingDirectory": "project"
83
+ },
84
+ {
85
+ "name": "Activate virtual environment (Windows)",
86
+ "command": ".\\venv\\Scripts\\Activate.ps1",
87
+ "description": "Activating virtual environment",
88
+ "required": true,
89
+ "platform": "win32",
90
+ "workingDirectory": "project"
91
+ },
92
+ {
93
+ "name": "Activate virtual environment (Unix)",
94
+ "command": "source venv/bin/activate",
95
+ "description": "Activating virtual environment",
96
+ "required": true,
97
+ "platform": "unix",
98
+ "workingDirectory": "project"
99
+ },
100
+ {
101
+ "name": "Upgrade pip",
102
+ "command": "python -m pip install --upgrade pip",
103
+ "description": "Upgrading pip",
104
+ "required": true,
105
+ "workingDirectory": "project",
106
+ "useVenv": true
107
+ },
108
+ {
109
+ "name": "Install requirements",
110
+ "command": "pip install -r requirements.txt",
111
+ "description": "Installing Python dependencies",
112
+ "required": true,
113
+ "conditional": "requirements_exists",
114
+ "workingDirectory": "project",
115
+ "useVenv": true
116
+ },
117
+ {
118
+ "name": "Install from pyproject.toml",
119
+ "command": "pip install -e .",
120
+ "description": "Installing from pyproject.toml",
121
+ "required": true,
122
+ "conditional": "pyproject_exists",
123
+ "workingDirectory": "project",
124
+ "useVenv": true
125
+ }
126
+ ],
127
+ "environment": {
128
+ "PYTHONPATH": ".",
129
+ "PYTHON_UNBUFFERED": "1"
130
+ }
131
+ },
132
+ "validation": {
133
+ "checks": [
134
+ {
135
+ "name": "Virtual environment created",
136
+ "directory": "venv"
137
+ },
138
+ {
139
+ "name": "Requirements file exists",
140
+ "file": "requirements.txt",
141
+ "optional": true
142
+ }
143
+ ]
144
+ },
145
+ "defaultConfig": {
146
+ "interpreter": "python",
147
+ "execMode": "fork",
148
+ "supportsCluster": false,
149
+ "interpreterPath": "venv/Scripts/python.exe"
150
+ }
151
+ },
152
+ "dotnet": {
153
+ "name": ".NET",
154
+ "detection": {
155
+ "files": ["*.csproj", "*.fsproj", "*.vbproj", "*.sln"],
156
+ "extensions": [".cs", ".fs", ".vb"]
157
+ },
158
+ "setup": {
159
+ "steps": [
160
+ {
161
+ "name": "Check .NET version",
162
+ "command": "dotnet --version",
163
+ "description": "Verifying .NET installation",
164
+ "required": true
165
+ },
166
+ {
167
+ "name": "Restore packages",
168
+ "command": "dotnet restore",
169
+ "description": "Restoring NuGet packages",
170
+ "required": true,
171
+ "workingDirectory": "project"
172
+ },
173
+ {
174
+ "name": "Build project",
175
+ "command": "dotnet build --configuration Release",
176
+ "description": "Building .NET project",
177
+ "required": true,
178
+ "workingDirectory": "project"
179
+ },
180
+ {
181
+ "name": "Publish project",
182
+ "command": "dotnet publish --configuration Release --output ./publish",
183
+ "description": "Publishing .NET project",
184
+ "required": true,
185
+ "workingDirectory": "project"
186
+ },
187
+ {
188
+ "name": "Run tests",
189
+ "command": "dotnet test",
190
+ "description": "Running .NET tests",
191
+ "required": false,
192
+ "conditional": "test_project_exists",
193
+ "workingDirectory": "project"
194
+ }
195
+ ],
196
+ "environment": {
197
+ "DOTNET_ENVIRONMENT": "Production",
198
+ "ASPNETCORE_ENVIRONMENT": "Production"
199
+ }
200
+ },
201
+ "validation": {
202
+ "checks": [
203
+ {
204
+ "name": "Project file exists",
205
+ "pattern": "*.csproj"
206
+ },
207
+ {
208
+ "name": "Publish directory exists",
209
+ "directory": "publish"
210
+ }
211
+ ]
212
+ },
213
+ "defaultConfig": {
214
+ "interpreter": "dotnet",
215
+ "execMode": "fork",
216
+ "supportsCluster": false,
217
+ "startCommand": "dotnet run"
218
+ }
219
+ }
220
+ },
221
+ "global": {
222
+ "timeouts": {
223
+ "setup": 300000,
224
+ "validation": 30000
225
+ },
226
+ "retries": {
227
+ "setup": 2,
228
+ "validation": 1
229
+ },
230
+ "logging": {
231
+ "level": "info",
232
+ "file": "deployment.log"
233
+ }
234
+ }
235
+ }
@@ -0,0 +1,3 @@
1
+ {
2
+ "connections": []
3
+ }
@@ -26,6 +26,9 @@ const pageAuth_1 = __importDefault(require("./routes/pageAuth"));
26
26
  const logStreaming_1 = require("./routes/logStreaming");
27
27
  const pm2_connection_1 = require("./utils/pm2-connection");
28
28
  const remote_connection_1 = require("./utils/remote-connection");
29
+ const metrics_history_1 = require("./utils/metrics-history");
30
+ const remoteMetrics_1 = __importDefault(require("./routes/remoteMetrics"));
31
+ const remote_metrics_poller_1 = require("./utils/remote-metrics-poller");
29
32
  /**
30
33
  * Create and configure the express server
31
34
  */
@@ -68,6 +71,9 @@ function createServer() {
68
71
  app.use('/api/cron-jobs', cronJobs_1.default);
69
72
  app.use('/api/update', updates_1.default);
70
73
  app.use('/api/auth', pageAuth_1.default);
74
+ app.use('/api/remote-metrics', remoteMetrics_1.default);
75
+ // Start remote metrics poller (30-second interval, polls all connected servers)
76
+ remote_metrics_poller_1.remoteMetricsPoller.start();
71
77
  // Setup log streaming with Socket.IO
72
78
  (0, logStreaming_1.setupLogStreaming)(io); // PM2 API endpoints
73
79
  app.get('/api/processes', async (req, res) => {
@@ -137,6 +143,24 @@ function createServer() {
137
143
  };
138
144
  res.json(metrics);
139
145
  });
146
+ // @group MetricsHistory : Return full history for all processes
147
+ app.get('/api/metrics/history', (_req, res) => {
148
+ res.json(metrics_history_1.metricsHistory.getAll());
149
+ });
150
+ // @group MetricsHistory : Return history for a single process by pm_id
151
+ app.get('/api/metrics/history/:processId', (req, res) => {
152
+ const pm_id = parseInt(req.params.processId, 10);
153
+ if (isNaN(pm_id)) {
154
+ res.status(400).json({ error: 'Invalid processId' });
155
+ return;
156
+ }
157
+ const entry = metrics_history_1.metricsHistory.getOne(pm_id);
158
+ if (!entry) {
159
+ res.status(404).json({ error: 'No history found for this process' });
160
+ return;
161
+ }
162
+ res.json(entry);
163
+ });
140
164
  // @group LogHistory : Resolve log path from PM2 process descriptor
141
165
  const resolveLocalLogPath = async (id, logType) => {
142
166
  var _a, _b, _c;
@@ -355,6 +379,19 @@ function createServer() {
355
379
  res.status(500).json({ error: 'Failed to download file' });
356
380
  }
357
381
  });
382
+ // @group MetricsHistory : Server-level polling — records PM2 process metrics into the history store
383
+ // This runs once regardless of how many clients are connected so the ring buffer fills consistently.
384
+ const historyPollInterval = setInterval(async () => {
385
+ try {
386
+ const processList = await (0, pm2_connection_1.executePM2Command)((callback) => {
387
+ pm2_1.default.list(callback);
388
+ });
389
+ metrics_history_1.metricsHistory.record(processList);
390
+ }
391
+ catch {
392
+ // silent — best-effort recording; don't crash the server
393
+ }
394
+ }, 3000);
358
395
  // WebSocket for real-time updates
359
396
  io.on('connection', (socket) => {
360
397
  console.log('Client connected');
@@ -403,15 +440,17 @@ function createServer() {
403
440
  res.status(404).send('File not found. Please check server configuration.');
404
441
  }
405
442
  });
443
+ // Clean up history poll on server close
444
+ server.on('close', () => clearInterval(historyPollInterval));
406
445
  // Return the server instance
407
446
  return server;
408
447
  }
409
448
  // Only start the server if this file is run directly
410
449
  if (require.main === module) {
411
- const PORT = process.env.PORT || 3101;
412
- const HOST = process.env.HOST || 'localhost';
450
+ const PORT = parseInt(process.env.PORT || '3101', 10);
451
+ const HOST = process.env.HOST || '::';
413
452
  const server = createServer();
414
- server.listen(PORT, () => {
453
+ server.listen(PORT, HOST, () => {
415
454
  console.log(`Server running on http://${HOST}:${PORT}`);
416
455
  });
417
456
  // Handle shutdown gracefully