ezpm2gui 1.8.0 → 1.9.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 (31) hide show
  1. package/README.md +355 -330
  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/project-configs.json +235 -235
  7. package/dist/server/index.js +4 -4
  8. package/dist/server/routes/deployApplication.js +4 -4
  9. package/dist/server/routes/logStreaming.js +35 -4
  10. package/dist/server/routes/remoteConnections.js +44 -12
  11. package/dist/server/utils/encryption.d.ts +22 -0
  12. package/dist/server/utils/encryption.js +53 -0
  13. package/dist/server/utils/remote-connection.js +3 -3
  14. package/dist/server/utils/remote-metrics-db.js +59 -59
  15. package/package.json +86 -86
  16. package/scripts/postinstall.js +36 -36
  17. package/src/client/build/asset-manifest.json +6 -6
  18. package/src/client/build/favicon.ico +2 -2
  19. package/src/client/build/index.html +1 -1
  20. package/src/client/build/logo192.svg +7 -7
  21. package/src/client/build/logo512.svg +7 -7
  22. package/src/client/build/manifest.json +24 -24
  23. package/src/client/build/static/css/main.2836d066.css +5 -0
  24. package/src/client/build/static/css/main.2836d066.css.map +1 -0
  25. package/src/client/build/static/js/{main.28a4a583.js → main.d5c19622.js} +3 -3
  26. package/src/client/build/static/js/{main.28a4a583.js.map → main.d5c19622.js.map} +1 -1
  27. package/dist/server/config/cron-jobs.json +0 -1
  28. package/dist/server/config/remote-connections.json +0 -3
  29. package/src/client/build/static/css/main.9decb204.css +0 -5
  30. package/src/client/build/static/css/main.9decb204.css.map +0 -1
  31. /package/src/client/build/static/js/{main.28a4a583.js.LICENSE.txt → main.d5c19622.js.LICENSE.txt} +0 -0
@@ -1,235 +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
- },
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
- }
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
+ }
@@ -41,15 +41,15 @@ function createServer() {
41
41
  origin: '*',
42
42
  methods: ['GET', 'POST']
43
43
  },
44
- // Increase ping timeout to prevent false positive disconnections
45
- pingTimeout: 10000, // How long to wait for a pong response (default: 5000ms)
44
+ // Increase ping timeout to prevent false positive disconnections in VPN/remote scenarios
45
+ pingTimeout: 20000, // How long to wait for a pong response (increased from 10s to 20s)
46
46
  pingInterval: 25000, // How often to send ping packets (default: 25000ms)
47
47
  // Allow reconnection attempts
48
48
  allowEIO3: true,
49
49
  // Transport configuration
50
50
  transports: ['websocket', 'polling'],
51
51
  // Upgrade timeout
52
- upgradeTimeout: 10000
52
+ upgradeTimeout: 20000 // Increased from 10s to 20s for slow VPN connections
53
53
  });
54
54
  // Configure middleware
55
55
  app.use(express_1.default.json());
@@ -448,7 +448,7 @@ function createServer() {
448
448
  // Only start the server if this file is run directly
449
449
  if (require.main === module) {
450
450
  const PORT = parseInt(process.env.PORT || '3101', 10);
451
- const HOST = process.env.HOST || '::';
451
+ const HOST = process.env.HOST || 'localhost';
452
452
  const server = createServer();
453
453
  server.listen(PORT, HOST, () => {
454
454
  console.log(`Server running on http://${HOST}:${PORT}`);
@@ -161,8 +161,8 @@ router.post('/generate-ecosystem', (req, res) => {
161
161
  env: pm2Env.env || {}
162
162
  };
163
163
  });
164
- const ecosystemConfig = `module.exports = {
165
- apps: ${JSON.stringify(apps, null, 2)}
164
+ const ecosystemConfig = `module.exports = {
165
+ apps: ${JSON.stringify(apps, null, 2)}
166
166
  };`;
167
167
  // Create the file (either at specified path or default location)
168
168
  const filePath = req.body.path || path_1.default.join(process.cwd(), 'ecosystem.config.js');
@@ -215,8 +215,8 @@ router.get('/generate-ecosystem-preview', (req, res) => {
215
215
  env: pm2Env.env || {}
216
216
  };
217
217
  });
218
- const ecosystemConfig = `module.exports = {
219
- apps: ${JSON.stringify(apps, null, 2)}
218
+ const ecosystemConfig = `module.exports = {
219
+ apps: ${JSON.stringify(apps, null, 2)}
220
220
  };`;
221
221
  pm2_1.default.disconnect();
222
222
  res.json({
@@ -74,8 +74,19 @@ const getRemoteLogStream = async (io, connectionId, processId) => {
74
74
  return activeRemoteStreams[streamKey];
75
75
  }
76
76
  const connection = remote_connection_1.remoteConnectionManager.getConnection(connectionId);
77
- if (!connection || !connection.isConnected()) {
78
- throw new Error('Connection not found or not connected');
77
+ if (!connection) {
78
+ throw new Error('Connection not found');
79
+ }
80
+ // Ensure connection is active before starting log stream
81
+ if (!connection.isConnected()) {
82
+ console.log(`Connection ${connectionId} not active, attempting to connect...`);
83
+ try {
84
+ await connection.connect();
85
+ console.log(`Successfully connected to ${connectionId} for log streaming`);
86
+ }
87
+ catch (error) {
88
+ throw new Error(`Failed to connect: ${error instanceof Error ? error.message : 'Unknown error'}`);
89
+ }
79
90
  }
80
91
  // Get process info using the multi-path fallback so pm2 is found regardless of PATH
81
92
  console.log(`Getting process info for: ${processId}`);
@@ -185,9 +196,24 @@ const getRemoteLogStream = async (io, connectionId, processId) => {
185
196
  processName,
186
197
  error: error.message
187
198
  });
199
+ // Clean up on error
200
+ if (activeRemoteStreams[streamKey]) {
201
+ delete activeRemoteStreams[streamKey];
202
+ }
188
203
  });
189
204
  logStream.on('close', (code) => {
190
205
  console.log(`PM2 logs stream closed for ${processName} with code:`, code);
206
+ // Notify clients that the stream has closed
207
+ io.to(streamKey).emit('remote-log-closed', {
208
+ connectionId,
209
+ processId,
210
+ processName,
211
+ code
212
+ });
213
+ // Clean up the stream reference
214
+ if (activeRemoteStreams[streamKey]) {
215
+ delete activeRemoteStreams[streamKey];
216
+ }
191
217
  });
192
218
  streams.combined = logStream;
193
219
  }
@@ -274,10 +300,15 @@ const setupLogStreaming = (io) => {
274
300
  const streams = activeRemoteStreams[streamKey];
275
301
  if (streams) {
276
302
  console.log(`Stopping remote log streams: ${streamKey}`);
277
- if (streams.stdout && streams.stdout.kill) {
303
+ // Kill the log stream properly
304
+ if (streams.combined && typeof streams.combined.kill === 'function') {
305
+ streams.combined.kill();
306
+ }
307
+ // Also handle legacy stdout/stderr streams if they exist
308
+ if (streams.stdout && typeof streams.stdout.kill === 'function') {
278
309
  streams.stdout.kill();
279
310
  }
280
- if (streams.stderr && streams.stderr.kill) {
311
+ if (streams.stderr && typeof streams.stderr.kill === 'function') {
281
312
  streams.stderr.kill();
282
313
  }
283
314
  delete activeRemoteStreams[streamKey];