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.
Files changed (40) hide show
  1. package/README.md +202 -14
  2. package/bin/ezpm2gui.js +40 -44
  3. package/bin/ezpm2gui.ts +51 -0
  4. package/bin/generate-ecosystem.js +24 -22
  5. package/bin/generate-ecosystem.ts +56 -0
  6. package/dist/server/index.js +40 -20
  7. package/dist/server/routes/clusterManagement.d.ts +3 -0
  8. package/dist/server/routes/clusterManagement.js +152 -0
  9. package/dist/server/routes/deployApplication.d.ts +3 -0
  10. package/dist/server/routes/deployApplication.js +163 -0
  11. package/dist/server/routes/logStreaming.d.ts +5 -0
  12. package/dist/server/routes/logStreaming.js +102 -0
  13. package/dist/server/routes/modules.d.ts +3 -0
  14. package/dist/server/routes/modules.js +106 -0
  15. package/dist/server/routes/processConfig.d.ts +3 -0
  16. package/dist/server/routes/processConfig.js +118 -0
  17. package/dist/server/utils/pm2-connection.d.ts +16 -0
  18. package/dist/server/utils/pm2-connection.js +141 -0
  19. package/package.json +19 -5
  20. package/src/client/build/asset-manifest.json +6 -6
  21. package/src/client/build/index.html +1 -1
  22. package/src/client/build/static/css/main.672b8f26.css +2 -0
  23. package/src/client/build/static/css/main.672b8f26.css.map +1 -0
  24. package/src/client/build/static/js/main.1d7f99ff.js +156 -0
  25. package/src/client/build/static/js/{main.dde30e92.js.LICENSE.txt → main.1d7f99ff.js.LICENSE.txt} +19 -0
  26. package/src/client/build/static/js/main.1d7f99ff.js.map +1 -0
  27. package/ .npmignore +0 -39
  28. package/install.bat +0 -22
  29. package/install.sh +0 -23
  30. package/src/client/build/static/css/main.c1cbda3a.css +0 -2
  31. package/src/client/build/static/css/main.c1cbda3a.css.map +0 -1
  32. package/src/client/build/static/js/main.dde30e92.js +0 -3
  33. package/src/client/build/static/js/main.dde30e92.js.map +0 -1
  34. package/src/client/package-lock.json +0 -16192
  35. package/src/client/package.json +0 -39
  36. package/src/client/public/index.html +0 -20
  37. package/src/client/public/manifest.json +0 -25
  38. package/src/index.ts +0 -24
  39. package/src/server/index.ts +0 -240
  40. 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.0.0",
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": "npm run build:server && npm run build:client",
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": ["pm2", "gui", "monitor", "process-manager", "dashboard"],
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.3",
43
- "@types/react-dom": "^19.1.4",
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.c1cbda3a.css",
4
- "main.js": "/static/js/main.dde30e92.js",
3
+ "main.css": "/static/css/main.672b8f26.css",
4
+ "main.js": "/static/js/main.1d7f99ff.js",
5
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"
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.c1cbda3a.css",
11
- "static/js/main.dde30e92.js"
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.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>
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":""}