ezpm2gui 1.1.0 → 1.2.1

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 (28) hide show
  1. package/dist/server/config/project-configs.json +236 -0
  2. package/dist/server/index.js +32 -6
  3. package/dist/server/logs/deployment.log +12 -0
  4. package/dist/server/routes/deployApplication.js +174 -27
  5. package/dist/server/routes/logStreaming.js +174 -0
  6. package/dist/server/routes/remoteConnections.d.ts +3 -0
  7. package/dist/server/routes/remoteConnections.js +634 -0
  8. package/dist/server/services/ProjectSetupService.d.ts +72 -0
  9. package/dist/server/services/ProjectSetupService.js +327 -0
  10. package/dist/server/utils/dialog.d.ts +1 -0
  11. package/dist/server/utils/dialog.js +16 -0
  12. package/dist/server/utils/encryption.d.ts +12 -0
  13. package/dist/server/utils/encryption.js +72 -0
  14. package/dist/server/utils/remote-connection.d.ts +152 -0
  15. package/dist/server/utils/remote-connection.js +590 -0
  16. package/dist/server/utils/upload.d.ts +3 -0
  17. package/dist/server/utils/upload.js +39 -0
  18. package/package.json +65 -63
  19. package/src/client/build/asset-manifest.json +3 -3
  20. package/src/client/build/favicon.ico +2 -0
  21. package/src/client/build/index.html +1 -1
  22. package/src/client/build/logo192.svg +7 -0
  23. package/src/client/build/logo512.svg +7 -0
  24. package/src/client/build/manifest.json +5 -6
  25. package/src/client/build/static/js/{main.1d7f99ff.js → main.31323a04.js} +13 -13
  26. package/src/client/build/static/js/main.31323a04.js.map +1 -0
  27. package/src/client/build/static/js/main.1d7f99ff.js.map +0 -1
  28. /package/src/client/build/static/js/{main.1d7f99ff.js.LICENSE.txt → main.31323a04.js.LICENSE.txt} +0 -0
@@ -0,0 +1,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
+ "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
+ }
@@ -7,15 +7,16 @@ exports.createServer = createServer;
7
7
  const express_1 = __importDefault(require("express"));
8
8
  const http_1 = __importDefault(require("http"));
9
9
  const socket_io_1 = require("socket.io");
10
+ const path_1 = __importDefault(require("path"));
10
11
  const pm2_1 = __importDefault(require("pm2"));
11
12
  const os_1 = __importDefault(require("os"));
12
- // Import routes
13
- const clusterManagement_1 = __importDefault(require("./routes/clusterManagement"));
14
13
  const processConfig_1 = __importDefault(require("./routes/processConfig"));
15
14
  const deployApplication_1 = __importDefault(require("./routes/deployApplication"));
16
15
  const modules_1 = __importDefault(require("./routes/modules"));
16
+ const remoteConnections_1 = __importDefault(require("./routes/remoteConnections"));
17
17
  const logStreaming_1 = require("./routes/logStreaming");
18
18
  const pm2_connection_1 = require("./utils/pm2-connection");
19
+ const remote_connection_1 = require("./utils/remote-connection");
19
20
  /**
20
21
  * Create and configure the express server
21
22
  */
@@ -32,7 +33,7 @@ function createServer() {
32
33
  // Configure middleware
33
34
  app.use(express_1.default.json());
34
35
  // Serve static files from the React app build directory
35
- const staticPath = 'D:/Personal/ezpm2gui/src/client/build';
36
+ const staticPath = path_1.default.join(__dirname, '../../src/client/build');
36
37
  console.log('Serving static files from:', staticPath);
37
38
  const fs = require('fs');
38
39
  if (fs.existsSync(staticPath)) {
@@ -41,11 +42,11 @@ function createServer() {
41
42
  else {
42
43
  console.error('Static files directory not found at:', staticPath);
43
44
  }
44
- // Register routes
45
- app.use('/api/cluster', clusterManagement_1.default);
45
+ // Register routes app.use('/api/cluster', clusterManagementRoutes);
46
46
  app.use('/api/config', processConfig_1.default);
47
47
  app.use('/api/deploy', deployApplication_1.default);
48
48
  app.use('/api/modules', modules_1.default);
49
+ app.use('/api/remote', remoteConnections_1.default);
49
50
  // Setup log streaming with Socket.IO
50
51
  (0, logStreaming_1.setupLogStreaming)(io); // PM2 API endpoints
51
52
  app.get('/api/processes', async (req, res) => {
@@ -90,7 +91,7 @@ function createServer() {
90
91
  pm2_1.default.restart(id, cb);
91
92
  break;
92
93
  case 'delete':
93
- pm2_1.default.del(id, cb);
94
+ pm2_1.default.delete(id, cb);
94
95
  break;
95
96
  default:
96
97
  cb(new Error('Invalid action'));
@@ -236,4 +237,29 @@ if (require.main === module) {
236
237
  server.listen(PORT, () => {
237
238
  console.log(`Server running on http://${HOST}:${PORT}`);
238
239
  });
240
+ // Handle shutdown gracefully
241
+ process.on('SIGINT', async () => {
242
+ console.log('\nGracefully shutting down...');
243
+ try {
244
+ await (0, pm2_connection_1.disconnectFromPM2)();
245
+ await remote_connection_1.remoteConnectionManager.closeAllConnections();
246
+ }
247
+ catch (error) {
248
+ console.error('Error during shutdown:', error);
249
+ }
250
+ server.close();
251
+ process.exit(0);
252
+ });
253
+ process.on('SIGTERM', async () => {
254
+ console.log('\nGracefully shutting down...');
255
+ try {
256
+ await (0, pm2_connection_1.disconnectFromPM2)();
257
+ await remote_connection_1.remoteConnectionManager.closeAllConnections();
258
+ }
259
+ catch (error) {
260
+ console.error('Error during shutdown:', error);
261
+ }
262
+ server.close();
263
+ process.exit(0);
264
+ });
239
265
  }
@@ -0,0 +1,12 @@
1
+ [2025-05-25T18:02:41.395Z] Starting setup for python project at: D:\Projects\FaceDetection
2
+ [2025-05-25T18:02:41.396Z] Executing step: Check Python version
3
+ [2025-05-25T18:02:41.954Z] Step "Check Python version" completed with exit code: 0
4
+ [2025-05-25T18:02:41.955Z] Executing step: Create virtual environment
5
+ [2025-05-25T18:03:20.998Z] Step "Create virtual environment" completed with exit code: 0
6
+ [2025-05-25T18:03:20.999Z] Executing step: Activate virtual environment (Windows)
7
+ [2025-05-25T18:03:21.176Z] Step "Activate virtual environment (Windows)" completed with exit code: 0
8
+ [2025-05-25T18:03:21.176Z] Executing step: Upgrade pip
9
+ [2025-05-25T18:03:48.644Z] Step "Upgrade pip" completed with exit code: 0
10
+ [2025-05-25T18:03:48.645Z] Executing step: Install requirements
11
+ [2025-05-25T18:04:56.318Z] Step "Install requirements" completed with exit code: 0
12
+ [2025-05-25T18:04:56.322Z] Setup completed. Success: true
@@ -7,10 +7,11 @@ const express_1 = require("express");
7
7
  const pm2_1 = __importDefault(require("pm2"));
8
8
  const path_1 = __importDefault(require("path"));
9
9
  const fs_1 = __importDefault(require("fs"));
10
+ const ProjectSetupService_1 = require("../services/ProjectSetupService");
10
11
  const router = (0, express_1.Router)();
11
12
  // Deploy a new application
12
- router.post('/', (req, res) => {
13
- const { name, script, cwd, instances, exec_mode, autorestart, watch, max_memory_restart, env } = req.body;
13
+ router.post('/', async (req, res) => {
14
+ const { name, script, cwd, instances, exec_mode, autorestart, watch, max_memory_restart, env, appType, autoSetup = true } = req.body;
14
15
  // Validate required fields
15
16
  if (!name || !script) {
16
17
  return res.status(400).json({ error: 'Name and script path are required' });
@@ -19,37 +20,103 @@ router.post('/', (req, res) => {
19
20
  if (!fs_1.default.existsSync(script)) {
20
21
  return res.status(400).json({ error: `Script file not found: ${script}` });
21
22
  }
22
- // Create deployment configuration
23
- const appConfig = {
24
- name,
25
- script,
26
- cwd: cwd || path_1.default.dirname(script),
27
- instances: parseInt(instances) || 1,
28
- exec_mode: exec_mode || 'fork',
29
- autorestart: autorestart !== undefined ? autorestart : true,
30
- watch: watch || false,
31
- max_memory_restart: max_memory_restart || '150M',
32
- env: env || {}
33
- };
34
- pm2_1.default.connect((err) => {
35
- if (err) {
36
- console.error(err);
37
- return res.status(500).json({ error: 'Failed to connect to PM2' });
23
+ try {
24
+ const projectPath = cwd || path_1.default.dirname(script);
25
+ let setupResult = null;
26
+ let finalEnv = env || {};
27
+ let interpreterPath = '';
28
+ // Auto-detect project type if not provided
29
+ let detectedType = appType;
30
+ if (!detectedType) {
31
+ detectedType = ProjectSetupService_1.projectSetupService.detectProjectType(projectPath);
32
+ if (detectedType) {
33
+ console.log(`Auto-detected project type: ${detectedType}`);
34
+ }
38
35
  }
39
- pm2_1.default.start(appConfig, (err) => {
40
- pm2_1.default.disconnect();
41
- if (err) {
42
- console.error('PM2 start error:', err);
36
+ // Run project setup if auto-setup is enabled and project type is detected
37
+ if (autoSetup && detectedType && ['node', 'python', 'dotnet'].includes(detectedType)) {
38
+ console.log(`Running setup for ${detectedType} project...`);
39
+ try {
40
+ setupResult = await ProjectSetupService_1.projectSetupService.setupProject(projectPath, detectedType);
41
+ if (!setupResult.success) {
42
+ return res.status(500).json({
43
+ error: 'Project setup failed',
44
+ details: setupResult.errors,
45
+ warnings: setupResult.warnings,
46
+ steps: setupResult.steps
47
+ });
48
+ }
49
+ // Merge environment variables from setup
50
+ finalEnv = { ...setupResult.environment, ...finalEnv };
51
+ // Set interpreter path for Python projects
52
+ if (setupResult.interpreterPath) {
53
+ interpreterPath = setupResult.interpreterPath;
54
+ }
55
+ console.log('Project setup completed successfully');
56
+ }
57
+ catch (setupError) {
58
+ console.error('Setup error:', setupError);
43
59
  return res.status(500).json({
44
- error: `Failed to deploy application: ${err.message || 'Unknown error'}`
60
+ error: 'Project setup failed',
61
+ details: setupError instanceof Error ? setupError.message : 'Unknown setup error'
45
62
  });
46
63
  }
47
- res.json({
48
- success: true,
49
- message: `Application ${name} deployed successfully`
64
+ }
65
+ // Create deployment configuration
66
+ const appConfig = {
67
+ name,
68
+ script,
69
+ cwd: projectPath,
70
+ instances: parseInt(instances) || 1,
71
+ exec_mode: exec_mode || 'fork',
72
+ autorestart: autorestart !== undefined ? autorestart : true,
73
+ watch: watch || false,
74
+ max_memory_restart: max_memory_restart || '150M',
75
+ env: finalEnv
76
+ };
77
+ // Set interpreter for Python projects
78
+ if (detectedType === 'python' && interpreterPath) {
79
+ appConfig.interpreter = interpreterPath;
80
+ }
81
+ else if (detectedType === 'dotnet') {
82
+ appConfig.interpreter = 'dotnet';
83
+ // For .NET projects, update script to point to the published DLL if available
84
+ const publishedDll = path_1.default.join(projectPath, 'publish', `${path_1.default.basename(projectPath)}.dll`);
85
+ if (fs_1.default.existsSync(publishedDll)) {
86
+ appConfig.script = publishedDll;
87
+ }
88
+ }
89
+ pm2_1.default.connect((err) => {
90
+ if (err) {
91
+ console.error(err);
92
+ return res.status(500).json({ error: 'Failed to connect to PM2' });
93
+ }
94
+ pm2_1.default.start(appConfig, (err) => {
95
+ pm2_1.default.disconnect();
96
+ if (err) {
97
+ console.error('PM2 start error:', err);
98
+ return res.status(500).json({
99
+ error: `Failed to deploy application: ${err.message || 'Unknown error'}`
100
+ });
101
+ }
102
+ res.json({
103
+ success: true,
104
+ message: `Application ${name} deployed successfully`,
105
+ setupResult: setupResult ? {
106
+ steps: setupResult.steps,
107
+ warnings: setupResult.warnings
108
+ } : null
109
+ });
50
110
  });
51
111
  });
52
- });
112
+ }
113
+ catch (error) {
114
+ console.error('Deployment error:', error);
115
+ return res.status(500).json({
116
+ error: 'Deployment failed',
117
+ details: error instanceof Error ? error.message : 'Unknown error'
118
+ });
119
+ }
53
120
  });
54
121
  // Generate ecosystem.config.js file
55
122
  router.post('/generate-ecosystem', (req, res) => {
@@ -160,4 +227,84 @@ router.get('/generate-ecosystem-preview', (req, res) => {
160
227
  }
161
228
  });
162
229
  });
230
+ // Detect project type
231
+ router.post('/detect-project', (req, res) => {
232
+ const { projectPath } = req.body;
233
+ if (!projectPath) {
234
+ return res.status(400).json({ error: 'Project path is required' });
235
+ }
236
+ if (!fs_1.default.existsSync(projectPath)) {
237
+ return res.status(400).json({ error: 'Project path does not exist' });
238
+ }
239
+ try {
240
+ const projectType = ProjectSetupService_1.projectSetupService.detectProjectType(projectPath);
241
+ const config = projectType ? ProjectSetupService_1.projectSetupService.getProjectConfig(projectType) : null;
242
+ res.json({
243
+ success: true,
244
+ projectType,
245
+ config: config ? {
246
+ name: config.name,
247
+ defaultConfig: config.defaultConfig,
248
+ setupSteps: config.setup.steps.length
249
+ } : null
250
+ });
251
+ }
252
+ catch (error) {
253
+ res.status(500).json({
254
+ error: 'Failed to detect project type',
255
+ details: error instanceof Error ? error.message : 'Unknown error'
256
+ });
257
+ }
258
+ });
259
+ // Setup project (without deployment)
260
+ router.post('/setup-project', async (req, res) => {
261
+ const { projectPath, projectType } = req.body;
262
+ if (!projectPath || !projectType) {
263
+ return res.status(400).json({ error: 'Project path and type are required' });
264
+ }
265
+ if (!fs_1.default.existsSync(projectPath)) {
266
+ return res.status(400).json({ error: 'Project path does not exist' });
267
+ }
268
+ try {
269
+ const setupResult = await ProjectSetupService_1.projectSetupService.setupProject(projectPath, projectType);
270
+ res.json({
271
+ success: setupResult.success,
272
+ steps: setupResult.steps,
273
+ errors: setupResult.errors,
274
+ warnings: setupResult.warnings,
275
+ environment: setupResult.environment,
276
+ interpreterPath: setupResult.interpreterPath
277
+ });
278
+ }
279
+ catch (error) {
280
+ res.status(500).json({
281
+ error: 'Project setup failed',
282
+ details: error instanceof Error ? error.message : 'Unknown error'
283
+ });
284
+ }
285
+ });
286
+ // Get supported project types
287
+ router.get('/project-types', (req, res) => {
288
+ try {
289
+ const types = ProjectSetupService_1.projectSetupService.getSupportedProjectTypes();
290
+ const typeConfigs = types.map(type => {
291
+ const config = ProjectSetupService_1.projectSetupService.getProjectConfig(type);
292
+ return {
293
+ type,
294
+ name: config === null || config === void 0 ? void 0 : config.name,
295
+ defaultConfig: config === null || config === void 0 ? void 0 : config.defaultConfig
296
+ };
297
+ });
298
+ res.json({
299
+ success: true,
300
+ types: typeConfigs
301
+ });
302
+ }
303
+ catch (error) {
304
+ res.status(500).json({
305
+ error: 'Failed to get project types',
306
+ details: error instanceof Error ? error.message : 'Unknown error'
307
+ });
308
+ }
309
+ });
163
310
  exports.default = router;