ezpm2gui 1.0.0 → 1.1.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/README.md +202 -14
- package/bin/ezpm2gui.js +40 -44
- package/bin/ezpm2gui.ts +51 -0
- package/bin/generate-ecosystem.js +24 -22
- package/bin/generate-ecosystem.ts +56 -0
- package/dist/server/index.js +40 -20
- package/dist/server/routes/clusterManagement.d.ts +3 -0
- package/dist/server/routes/clusterManagement.js +152 -0
- package/dist/server/routes/deployApplication.d.ts +3 -0
- package/dist/server/routes/deployApplication.js +163 -0
- package/dist/server/routes/logStreaming.d.ts +5 -0
- package/dist/server/routes/logStreaming.js +102 -0
- package/dist/server/routes/modules.d.ts +3 -0
- package/dist/server/routes/modules.js +106 -0
- package/dist/server/routes/processConfig.d.ts +3 -0
- package/dist/server/routes/processConfig.js +118 -0
- package/dist/server/utils/pm2-connection.d.ts +16 -0
- package/dist/server/utils/pm2-connection.js +141 -0
- package/package.json +19 -5
- package/src/client/build/asset-manifest.json +6 -6
- package/src/client/build/index.html +1 -1
- package/src/client/build/static/css/main.672b8f26.css +2 -0
- package/src/client/build/static/css/main.672b8f26.css.map +1 -0
- package/src/client/build/static/js/main.1d7f99ff.js +156 -0
- package/src/client/build/static/js/{main.dde30e92.js.LICENSE.txt → main.1d7f99ff.js.LICENSE.txt} +19 -0
- package/src/client/build/static/js/main.1d7f99ff.js.map +1 -0
- package/ .npmignore +0 -39
- package/install.bat +0 -22
- package/install.sh +0 -23
- package/src/client/build/static/css/main.c1cbda3a.css +0 -2
- package/src/client/build/static/css/main.c1cbda3a.css.map +0 -1
- package/src/client/build/static/js/main.dde30e92.js +0 -3
- package/src/client/build/static/js/main.dde30e92.js.map +0 -1
- package/src/client/package-lock.json +0 -16192
- package/src/client/package.json +0 -39
- package/src/client/public/index.html +0 -20
- package/src/client/public/manifest.json +0 -25
- package/src/index.ts +0 -24
- package/src/server/index.ts +0 -240
- package/tsconfig.json +0 -18
|
@@ -0,0 +1,141 @@
|
|
|
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.executePM2Command = exports.disconnectFromPM2 = exports.connectToPM2 = void 0;
|
|
7
|
+
const pm2_1 = __importDefault(require("pm2"));
|
|
8
|
+
/**
|
|
9
|
+
* Utility to manage PM2 connections
|
|
10
|
+
* This implements connection pooling to avoid the overhead of
|
|
11
|
+
* repeatedly connecting and disconnecting to PM2
|
|
12
|
+
*/
|
|
13
|
+
let isConnected = false;
|
|
14
|
+
let connectionPromise = null;
|
|
15
|
+
let connectionRetries = 0;
|
|
16
|
+
const MAX_RETRIES = 3;
|
|
17
|
+
const RETRY_DELAY = 1000;
|
|
18
|
+
/**
|
|
19
|
+
* Check if PM2 is installed and available
|
|
20
|
+
*/
|
|
21
|
+
const checkPM2Installation = () => {
|
|
22
|
+
return new Promise((resolve) => {
|
|
23
|
+
const { exec } = require('child_process');
|
|
24
|
+
exec('pm2 --version', (error) => {
|
|
25
|
+
if (error) {
|
|
26
|
+
console.error('PM2 is not installed or not available in PATH');
|
|
27
|
+
resolve(false);
|
|
28
|
+
}
|
|
29
|
+
else {
|
|
30
|
+
resolve(true);
|
|
31
|
+
}
|
|
32
|
+
});
|
|
33
|
+
});
|
|
34
|
+
};
|
|
35
|
+
/**
|
|
36
|
+
* Connect to PM2 if not already connected
|
|
37
|
+
* Returns a promise that resolves when the connection is established
|
|
38
|
+
*/
|
|
39
|
+
const connectToPM2 = async () => {
|
|
40
|
+
// If already connected, return resolved promise
|
|
41
|
+
if (isConnected) {
|
|
42
|
+
return Promise.resolve();
|
|
43
|
+
}
|
|
44
|
+
// If a connection attempt is in progress, return that promise
|
|
45
|
+
if (connectionPromise) {
|
|
46
|
+
return connectionPromise;
|
|
47
|
+
}
|
|
48
|
+
// First check if PM2 is installed
|
|
49
|
+
const isPM2Installed = await checkPM2Installation();
|
|
50
|
+
if (!isPM2Installed) {
|
|
51
|
+
return Promise.reject(new Error('PM2 is not installed or not in your PATH. Please install PM2 globally using: npm install -g pm2'));
|
|
52
|
+
}
|
|
53
|
+
// Start a new connection attempt
|
|
54
|
+
connectionPromise = new Promise((resolve, reject) => {
|
|
55
|
+
pm2_1.default.connect((err) => {
|
|
56
|
+
if (err) {
|
|
57
|
+
console.error('Failed to connect to PM2:', err);
|
|
58
|
+
// Retry logic
|
|
59
|
+
if (connectionRetries < MAX_RETRIES) {
|
|
60
|
+
connectionRetries++;
|
|
61
|
+
connectionPromise = null;
|
|
62
|
+
// Wait and try again
|
|
63
|
+
setTimeout(() => {
|
|
64
|
+
(0, exports.connectToPM2)()
|
|
65
|
+
.then(resolve)
|
|
66
|
+
.catch(reject);
|
|
67
|
+
}, RETRY_DELAY);
|
|
68
|
+
}
|
|
69
|
+
else {
|
|
70
|
+
// Max retries reached
|
|
71
|
+
connectionRetries = 0;
|
|
72
|
+
connectionPromise = null;
|
|
73
|
+
reject(err);
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
else {
|
|
77
|
+
isConnected = true;
|
|
78
|
+
connectionRetries = 0;
|
|
79
|
+
resolve();
|
|
80
|
+
}
|
|
81
|
+
});
|
|
82
|
+
});
|
|
83
|
+
return connectionPromise;
|
|
84
|
+
};
|
|
85
|
+
exports.connectToPM2 = connectToPM2;
|
|
86
|
+
/**
|
|
87
|
+
* Safely disconnect from PM2
|
|
88
|
+
* Use this when shutting down the server
|
|
89
|
+
*/
|
|
90
|
+
const disconnectFromPM2 = () => {
|
|
91
|
+
return new Promise((resolve) => {
|
|
92
|
+
if (isConnected) {
|
|
93
|
+
pm2_1.default.disconnect();
|
|
94
|
+
isConnected = false;
|
|
95
|
+
connectionPromise = null;
|
|
96
|
+
}
|
|
97
|
+
resolve();
|
|
98
|
+
});
|
|
99
|
+
};
|
|
100
|
+
exports.disconnectFromPM2 = disconnectFromPM2;
|
|
101
|
+
/**
|
|
102
|
+
* Execute a PM2 command with automatic connection handling
|
|
103
|
+
* This will connect to PM2 if needed, run the command,
|
|
104
|
+
* and properly handle the result
|
|
105
|
+
*/
|
|
106
|
+
const executePM2Command = async (command) => {
|
|
107
|
+
try {
|
|
108
|
+
await (0, exports.connectToPM2)();
|
|
109
|
+
return new Promise((resolve, reject) => {
|
|
110
|
+
command((err, result) => {
|
|
111
|
+
if (err) {
|
|
112
|
+
reject(err);
|
|
113
|
+
}
|
|
114
|
+
else if (result === undefined) {
|
|
115
|
+
reject(new Error('PM2 command returned undefined result'));
|
|
116
|
+
}
|
|
117
|
+
else {
|
|
118
|
+
resolve(result);
|
|
119
|
+
}
|
|
120
|
+
});
|
|
121
|
+
});
|
|
122
|
+
}
|
|
123
|
+
catch (err) {
|
|
124
|
+
// If connection fails, ensure we reset the connection state
|
|
125
|
+
isConnected = false;
|
|
126
|
+
connectionPromise = null;
|
|
127
|
+
throw err;
|
|
128
|
+
}
|
|
129
|
+
};
|
|
130
|
+
exports.executePM2Command = executePM2Command;
|
|
131
|
+
// Handle process termination to clean up PM2 connection
|
|
132
|
+
process.on('SIGINT', () => {
|
|
133
|
+
(0, exports.disconnectFromPM2)().then(() => {
|
|
134
|
+
process.exit(0);
|
|
135
|
+
});
|
|
136
|
+
});
|
|
137
|
+
process.on('SIGTERM', () => {
|
|
138
|
+
(0, exports.disconnectFromPM2)().then(() => {
|
|
139
|
+
process.exit(0);
|
|
140
|
+
});
|
|
141
|
+
});
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "ezpm2gui",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.1.0",
|
|
4
4
|
"main": "dist/server/index.js",
|
|
5
5
|
"bin": {
|
|
6
6
|
"ezpm2gui": "./bin/ezpm2gui.js",
|
|
@@ -11,14 +11,21 @@
|
|
|
11
11
|
"dev": "concurrently \"npm run dev:server\" \"npm run dev:client\"",
|
|
12
12
|
"dev:server": "nodemon --exec ts-node src/server/index.ts",
|
|
13
13
|
"dev:client": "cd src/client && npm start",
|
|
14
|
-
"build": "
|
|
14
|
+
"build": "node scripts/build.js",
|
|
15
15
|
"build:server": "tsc",
|
|
16
16
|
"build:client": "cd src/client && npm run build",
|
|
17
|
+
"build:bin": "tsc --project tsconfig.bin.json",
|
|
17
18
|
"prepare": "npm run build",
|
|
18
19
|
"test": "echo \"Error: no test specified\" && exit 1",
|
|
19
20
|
"postinstall": "node scripts/postinstall.js"
|
|
20
21
|
},
|
|
21
|
-
"keywords": [
|
|
22
|
+
"keywords": [
|
|
23
|
+
"pm2",
|
|
24
|
+
"gui",
|
|
25
|
+
"monitor",
|
|
26
|
+
"process-manager",
|
|
27
|
+
"dashboard"
|
|
28
|
+
],
|
|
22
29
|
"author": "Chandan Bhagat",
|
|
23
30
|
"license": "ISC",
|
|
24
31
|
"repository": {
|
|
@@ -26,6 +33,12 @@
|
|
|
26
33
|
"url": "git+https://github.com/thechandanbhagat/ezpm2gui.git"
|
|
27
34
|
},
|
|
28
35
|
"description": "A modern web-based GUI for PM2 process manager",
|
|
36
|
+
"files": [
|
|
37
|
+
"dist/",
|
|
38
|
+
"bin/",
|
|
39
|
+
"src/client/build/",
|
|
40
|
+
"scripts/postinstall.js"
|
|
41
|
+
],
|
|
29
42
|
"dependencies": {
|
|
30
43
|
"axios": "^1.9.0",
|
|
31
44
|
"chart.js": "^4.4.9",
|
|
@@ -39,11 +52,12 @@
|
|
|
39
52
|
"devDependencies": {
|
|
40
53
|
"@types/express": "^4.17.21",
|
|
41
54
|
"@types/node": "^22.15.17",
|
|
42
|
-
"@types/react": "^19.1.
|
|
43
|
-
"@types/react-dom": "^19.1.
|
|
55
|
+
"@types/react": "^19.1.4",
|
|
56
|
+
"@types/react-dom": "^19.1.5",
|
|
44
57
|
"@types/socket.io": "^3.0.2",
|
|
45
58
|
"concurrently": "^9.1.2",
|
|
46
59
|
"nodemon": "^3.1.10",
|
|
60
|
+
"ts-node": "^10.9.2",
|
|
47
61
|
"typescript": "^5.8.3"
|
|
48
62
|
}
|
|
49
63
|
}
|
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
{
|
|
2
2
|
"files": {
|
|
3
|
-
"main.css": "/static/css/main.
|
|
4
|
-
"main.js": "/static/js/main.
|
|
3
|
+
"main.css": "/static/css/main.672b8f26.css",
|
|
4
|
+
"main.js": "/static/js/main.1d7f99ff.js",
|
|
5
5
|
"index.html": "/index.html",
|
|
6
|
-
"main.
|
|
7
|
-
"main.
|
|
6
|
+
"main.672b8f26.css.map": "/static/css/main.672b8f26.css.map",
|
|
7
|
+
"main.1d7f99ff.js.map": "/static/js/main.1d7f99ff.js.map"
|
|
8
8
|
},
|
|
9
9
|
"entrypoints": [
|
|
10
|
-
"static/css/main.
|
|
11
|
-
"static/js/main.
|
|
10
|
+
"static/css/main.672b8f26.css",
|
|
11
|
+
"static/js/main.1d7f99ff.js"
|
|
12
12
|
]
|
|
13
13
|
}
|
|
@@ -1 +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.
|
|
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.1d7f99ff.js"></script><link href="/static/css/main.672b8f26.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,2 @@
|
|
|
1
|
+
body{-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;font-family:-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Oxygen,Ubuntu,Cantarell,Fira Sans,Droid Sans,Helvetica Neue,sans-serif;margin:0;transition:background-color .3s ease,color .3s ease}code{font-family:source-code-pro,Menlo,Monaco,Consolas,Courier New,monospace}::-webkit-scrollbar{height:8px;width:8px}::-webkit-scrollbar-track{background:#0000000d;border-radius:4px}::-webkit-scrollbar-thumb{background:#0003;border-radius:4px}::-webkit-scrollbar-thumb:hover{background:#0000004d}[data-theme=dark] ::-webkit-scrollbar-track{background:#ffffff0d}[data-theme=dark] ::-webkit-scrollbar-thumb{background:#fff3}[data-theme=dark] ::-webkit-scrollbar-thumb:hover{background:#ffffff4d}:focus{outline:2px solid var(--primary-color);outline-offset:2px}*{transition:background-color .3s ease,color .3s ease,border-color .3s ease,box-shadow .3s ease}
|
|
2
|
+
/*# sourceMappingURL=main.672b8f26.css.map*/
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"static/css/main.672b8f26.css","mappings":"AAAA,KAKE,kCAAmC,CACnC,iCAAkC,CAJlC,mIAEY,CAHZ,QAAS,CAMT,mDACF,CAEA,KACE,uEAEF,CAGA,oBAEE,UAAW,CADX,SAEF,CAEA,0BACE,oBAA+B,CAC/B,iBACF,CAEA,0BACE,gBAA8B,CAC9B,iBACF,CAEA,gCACE,oBACF,CAGA,4CACE,oBACF,CAEA,4CACE,gBACF,CAEA,kDACE,oBACF,CAGA,OACE,sCAAuC,CACvC,kBACF,CAGA,EACE,6FACF","sources":["index.css"],"sourcesContent":["body {\r\n margin: 0;\r\n font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen',\r\n 'Ubuntu', 'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue',\r\n sans-serif;\r\n -webkit-font-smoothing: antialiased;\r\n -moz-osx-font-smoothing: grayscale;\r\n transition: background-color 0.3s ease, color 0.3s ease;\r\n}\r\n\r\ncode {\r\n font-family: source-code-pro, Menlo, Monaco, Consolas, 'Courier New',\r\n monospace;\r\n}\r\n\r\n/* Global scrollbar styling */\r\n::-webkit-scrollbar {\r\n width: 8px;\r\n height: 8px;\r\n}\r\n\r\n::-webkit-scrollbar-track {\r\n background: rgba(0, 0, 0, 0.05);\r\n border-radius: 4px;\r\n}\r\n\r\n::-webkit-scrollbar-thumb {\r\n background: rgba(0, 0, 0, 0.2);\r\n border-radius: 4px;\r\n}\r\n\r\n::-webkit-scrollbar-thumb:hover {\r\n background: rgba(0, 0, 0, 0.3);\r\n}\r\n\r\n/* Dark mode scrollbar */\r\n[data-theme=\"dark\"] ::-webkit-scrollbar-track {\r\n background: rgba(255, 255, 255, 0.05);\r\n}\r\n\r\n[data-theme=\"dark\"] ::-webkit-scrollbar-thumb {\r\n background: rgba(255, 255, 255, 0.2);\r\n}\r\n\r\n[data-theme=\"dark\"] ::-webkit-scrollbar-thumb:hover {\r\n background: rgba(255, 255, 255, 0.3);\r\n}\r\n\r\n/* Focus styling for accessibility */\r\n*:focus {\r\n outline: 2px solid var(--primary-color);\r\n outline-offset: 2px;\r\n}\r\n\r\n/* Transition for smooth theme switching */\r\n* {\r\n transition: background-color 0.3s ease, color 0.3s ease, border-color 0.3s ease, box-shadow 0.3s ease;\r\n}\r\n"],"names":[],"sourceRoot":""}
|