@drocketxx/pm2me 1.1.12 → 1.1.13

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 (68) hide show
  1. package/backend/db/index.js +6 -0
  2. package/backend/routes/api.js +14 -2
  3. package/package.json +1 -1
  4. package/apps/Delete-Test-App/README.md +0 -1
  5. package/apps/Delete-Test-App/dist/server.js +0 -57
  6. package/apps/Delete-Test-App/package.json +0 -19
  7. package/apps/Delete-Test-App/src/server.ts +0 -33
  8. package/apps/Delete-Test-App/tsconfig.json +0 -15
  9. package/apps/Delete-Test-App-2/README.md +0 -1
  10. package/apps/Delete-Test-App-2/dist/server.js +0 -57
  11. package/apps/Delete-Test-App-2/package.json +0 -19
  12. package/apps/Delete-Test-App-2/src/server.ts +0 -33
  13. package/apps/Delete-Test-App-2/tsconfig.json +0 -15
  14. package/apps/Delete-Test-App-2_deploy.log +0 -12
  15. package/apps/Delete-Test-App_deploy.log +0 -12
  16. package/apps/PM2Me-main/README.md +0 -236
  17. package/apps/PM2Me-main/backend/app.js +0 -109
  18. package/apps/PM2Me-main/backend/db/index.js +0 -40
  19. package/apps/PM2Me-main/backend/nodemon.json +0 -10
  20. package/apps/PM2Me-main/backend/package.json +0 -31
  21. package/apps/PM2Me-main/backend/public/assets/index-DZ4rSpP9.css +0 -1
  22. package/apps/PM2Me-main/backend/public/assets/index-KLmI9qSM.js +0 -13
  23. package/apps/PM2Me-main/backend/public/icon.png +0 -0
  24. package/apps/PM2Me-main/backend/public/index.html +0 -14
  25. package/apps/PM2Me-main/backend/public/vite.svg +0 -1
  26. package/apps/PM2Me-main/backend/routes/api.js +0 -932
  27. package/apps/PM2Me-main/backend/routes/auth.js +0 -44
  28. package/apps/PM2Me-main/backend/services/gitService.js +0 -110
  29. package/apps/PM2Me-main/backend/services/notificationService.js +0 -48
  30. package/apps/PM2Me-main/backend/services/pm2Service.js +0 -84
  31. package/apps/PM2Me-main/backend/services/systemService.js +0 -113
  32. package/apps/PM2Me-main/c:VsCodemyPM2Metmp_old_dashboard.vue +0 -390
  33. package/apps/PM2Me-main/package.json +0 -21
  34. package/apps/PM2Me-main/screenshot/001.png +0 -0
  35. package/apps/PM2Me-main/test_db.js +0 -8
  36. package/apps/PM2Me-main/tmp_old_dashboard.vue +0 -390
  37. package/apps/PM2Me-main_deploy.log +0 -25
  38. package/apps/PM2Me-test/README.md +0 -1
  39. package/apps/PM2Me-test/dist/server.js +0 -63
  40. package/apps/PM2Me-test/package.json +0 -19
  41. package/apps/PM2Me-test/src/server.ts +0 -33
  42. package/apps/PM2Me-test/tsconfig.json +0 -15
  43. package/apps/PM2Me-test-main/README.md +0 -1
  44. package/apps/PM2Me-test-main/dist/server.js +0 -63
  45. package/apps/PM2Me-test-main/package.json +0 -19
  46. package/apps/PM2Me-test-main/src/server.ts +0 -33
  47. package/apps/PM2Me-test-main/tsconfig.json +0 -15
  48. package/apps/PM2Me-test-main_deploy.log +0 -24
  49. package/apps/PM2Me-test-uat/README.md +0 -1
  50. package/apps/PM2Me-test-uat/dist/server.js +0 -63
  51. package/apps/PM2Me-test-uat/package.json +0 -19
  52. package/apps/PM2Me-test-uat/src/server.ts +0 -33
  53. package/apps/PM2Me-test-uat/tsconfig.json +0 -15
  54. package/apps/PM2Me-test-uat-updated/README.md +0 -1
  55. package/apps/PM2Me-test-uat-updated/dist/server.js +0 -63
  56. package/apps/PM2Me-test-uat-updated/package.json +0 -19
  57. package/apps/PM2Me-test-uat-updated/src/server.ts +0 -33
  58. package/apps/PM2Me-test-uat-updated/tsconfig.json +0 -15
  59. package/apps/PM2Me-test-uat-updated_deploy.log +0 -24
  60. package/apps/PM2Me-test-uat2/README.md +0 -1
  61. package/apps/PM2Me-test-uat2/dist/server.js +0 -63
  62. package/apps/PM2Me-test-uat2/package.json +0 -19
  63. package/apps/PM2Me-test-uat2/src/server.ts +0 -33
  64. package/apps/PM2Me-test-uat2/tsconfig.json +0 -15
  65. package/apps/PM2Me-test-uat2_deploy.log +0 -25
  66. package/apps/PM2Me-test-uat_deploy.log +0 -24
  67. package/apps/PM2Me-test_deploy.log +0 -24
  68. package/apps/PM2Me-test_health.log +0 -4
@@ -1,44 +0,0 @@
1
- import express from 'express';
2
- import db from '../db/index.js';
3
- import bcrypt from 'bcrypt';
4
- import jwt from 'jsonwebtoken';
5
-
6
- const router = express.Router();
7
- const JWT_SECRET = process.env.JWT_SECRET || 'super-secret-pm2me-key-2026';
8
-
9
- router.post('/login', async (req, res) => {
10
- const { password } = req.body;
11
- const adminConfig = db.data.admin;
12
-
13
- if (!adminConfig || !adminConfig.passwordHash) {
14
- // If no password is set, the first login attempts sets it
15
- const hash = await bcrypt.hash(password, 10);
16
- db.data.admin.passwordHash = hash;
17
- await db.write();
18
- const token = jwt.sign({ role: 'admin' }, JWT_SECRET, { expiresIn: '1d' });
19
- return res.json({ token, message: 'Admin password set successfully and logged in' });
20
- }
21
-
22
- const match = await bcrypt.compare(password, adminConfig.passwordHash);
23
- if (!match) {
24
- return res.status(401).json({ error: 'Invalid password' });
25
- }
26
-
27
- const token = jwt.sign({ role: 'admin' }, JWT_SECRET, { expiresIn: '1d' });
28
- res.json({ token });
29
- });
30
-
31
- export const authenticateToken = (req, res, next) => {
32
- const authHeader = req.headers['authorization'];
33
- const token = authHeader && authHeader.split(' ')[1];
34
-
35
- if (!token) return res.sendStatus(401);
36
-
37
- jwt.verify(token, JWT_SECRET, (err, user) => {
38
- if (err) return res.sendStatus(403);
39
- req.user = user;
40
- next();
41
- });
42
- };
43
-
44
- export default router;
@@ -1,110 +0,0 @@
1
- import simpleGit from 'simple-git';
2
- import fs from 'fs';
3
- import path from 'path';
4
-
5
- const getFinalUrl = (repoUrl, token) => {
6
- let finalUrl = repoUrl;
7
- if (token) {
8
- try {
9
- const urlObj = new URL(repoUrl);
10
- urlObj.password = token;
11
- urlObj.username = 'oauth2';
12
- finalUrl = urlObj.toString();
13
- } catch (e) {
14
- console.error('Invalid URL for cloning', e);
15
- }
16
- }
17
- return finalUrl;
18
- };
19
-
20
- export const syncRepo = async (repoUrl, targetPath, branchName, token = null) => {
21
- const finalUrl = getFinalUrl(repoUrl, token);
22
- const envOptions = { ...process.env, GIT_TERMINAL_PROMPT: '0' }; // Prevent hanging on auth prompts or merge editors
23
-
24
- const isGitRepo = fs.existsSync(path.join(targetPath, '.git'));
25
-
26
- const freshClone = async () => {
27
- if (fs.existsSync(targetPath)) {
28
- fs.rmSync(targetPath, { recursive: true, force: true });
29
- }
30
- fs.mkdirSync(targetPath, { recursive: true });
31
- const git = simpleGit().env(envOptions);
32
- await git.clone(finalUrl, targetPath, ['--branch', branchName]);
33
- const gitLocal = simpleGit(targetPath);
34
- const log = await gitLocal.log(['-1']);
35
- const commitHash = log.latest.hash;
36
- const commitMessage = log.latest.message;
37
- return { message: 'Cloned repository cleanly', commitHash: commitHash.trim(), commitMessage: commitMessage.trim() };
38
- };
39
-
40
- if (!isGitRepo) {
41
- try {
42
- return await freshClone();
43
- } catch (err) {
44
- throw new Error(`Git Clone Error: ${err.message}`);
45
- }
46
- } else {
47
- try {
48
- const git = simpleGit(targetPath).env(envOptions);
49
- await git.remote(['set-url', 'origin', finalUrl]);
50
- await git.fetch('origin', branchName);
51
- await git.checkout(branchName);
52
- await git.reset(['--hard', 'FETCH_HEAD']);
53
- await git.clean('f', ['-d']);
54
- const log = await git.log(['-1']);
55
- const commitHash = log.latest.hash;
56
- const commitMessage = log.latest.message;
57
- return { message: 'Pulled latest changes cleanly', commitHash: commitHash.trim(), commitMessage: commitMessage.trim() };
58
- } catch (err) {
59
- console.warn(`Git Sync failed, attempting fresh clone. Reason: ${err.message}`);
60
- try {
61
- return await freshClone();
62
- } catch (cloneErr) {
63
- throw new Error(`Git Sync & Retreat Clone Error: ${cloneErr.message}`);
64
- }
65
- }
66
- }
67
- };
68
-
69
- export const getBranches = async (repoUrl, token = null) => {
70
- const finalUrl = getFinalUrl(repoUrl, token);
71
- const git = simpleGit().env({ ...process.env, GIT_TERMINAL_PROMPT: '0' });
72
- const branches = await git.listRemote(['--heads', finalUrl]);
73
- // Parse branch output, simplistic split
74
- return branches.split('\n').filter(Boolean).map(line => line.split('refs/heads/')[1]);
75
- };
76
-
77
- /**
78
- * Get the number of commits that the local branch is behind its remote origin counterpart.
79
- */
80
- export const getBehindCount = async (repoUrl, targetPath, branchName, token = null) => {
81
- const isGitRepo = fs.existsSync(path.join(targetPath, '.git'));
82
- if (!isGitRepo) return 0;
83
-
84
- const finalUrl = getFinalUrl(repoUrl, token);
85
- const git = simpleGit(targetPath).env({ ...process.env, GIT_TERMINAL_PROMPT: '0' });
86
-
87
- try {
88
- await git.remote(['set-url', 'origin', finalUrl]);
89
- await git.fetch(['origin', branchName]);
90
- const count = await git.raw(['rev-list', '--count', `HEAD..origin/${branchName}`]);
91
- return parseInt(count.trim(), 10) || 0;
92
- } catch (err) {
93
- console.error(`Git behind count error for ${targetPath}:`, err.message);
94
- return 0;
95
- }
96
- };
97
-
98
- export const checkout = async (targetPath, ref) => {
99
- const git = simpleGit(targetPath).env({ ...process.env, GIT_TERMINAL_PROMPT: '0' });
100
- try {
101
- await git.checkout(ref);
102
- const log = await git.log(['-1']);
103
- return {
104
- hash: log.latest.hash.trim(),
105
- message: log.latest.message.trim()
106
- };
107
- } catch (err) {
108
- throw new Error(`Git Checkout Error: ${err.message}`);
109
- }
110
- };
@@ -1,48 +0,0 @@
1
- import db from '../db/index.js';
2
-
3
- export const sendDiscordNotification = async (message) => {
4
- const { discordWebhook } = db.data.settings;
5
- if (!discordWebhook) return;
6
-
7
- try {
8
- await fetch(discordWebhook, {
9
- method: 'POST',
10
- headers: { 'Content-Type': 'application/json' },
11
- body: JSON.stringify({ content: message })
12
- });
13
- } catch (err) {
14
- console.error('Discord notification failed:', err);
15
- }
16
- };
17
-
18
- export const sendTelegramNotification = async (message) => {
19
- const { telegramBotToken, telegramChatId } = db.data.settings;
20
- if (!telegramBotToken || !telegramChatId) return;
21
-
22
- try {
23
- const url = `https://api.telegram.org/bot${telegramBotToken}/sendMessage`;
24
- await fetch(url, {
25
- method: 'POST',
26
- headers: { 'Content-Type': 'application/json' },
27
- body: JSON.stringify({ chat_id: telegramChatId, text: message })
28
- });
29
- } catch (err) {
30
- console.error('Telegram notification failed:', err);
31
- }
32
- };
33
-
34
- export const notifyAll = async (appName, status, error = null) => {
35
- let message = '';
36
- if (status === 'success') {
37
- message = `✅ **Deployment Success**\nApp \`${appName}\` has been successfully deployed and is now running.`;
38
- } else if (status === 'failed') {
39
- message = `❌ **Deployment Failed**\nApp \`${appName}\` failed to deploy.\nError: ${error}`;
40
- } else {
41
- message = `ℹ️ **App Status Update**\nApp \`${appName}\` is now ${status}.`;
42
- }
43
-
44
- await Promise.all([
45
- sendDiscordNotification(message),
46
- sendTelegramNotification(message)
47
- ]);
48
- };
@@ -1,84 +0,0 @@
1
- import pm2 from 'pm2';
2
-
3
- export const connectPM2 = () => {
4
- return new Promise((resolve, reject) => {
5
- pm2.connect((err) => {
6
- if (err) return reject(err);
7
- resolve(true);
8
- });
9
- });
10
- };
11
-
12
- export const listApps = () => {
13
- return new Promise((resolve, reject) => {
14
- pm2.list((err, list) => {
15
- if (err) return reject(err);
16
- resolve(list);
17
- });
18
- });
19
- };
20
-
21
- export const startApp = (options) => {
22
- return new Promise((resolve, reject) => {
23
- pm2.start(options, (err, apps) => {
24
- if (err) return reject(err);
25
- resolve(apps);
26
- });
27
- });
28
- };
29
-
30
- export const stopApp = (nameOrId) => {
31
- return new Promise((resolve, reject) => {
32
- pm2.stop(nameOrId, (err, proc) => {
33
- if (err) return reject(err);
34
- resolve(proc);
35
- });
36
- });
37
- };
38
-
39
- export const restartApp = (nameOrId, options = {}) => {
40
- return new Promise((resolve, reject) => {
41
- if (options && options.updateEnv) {
42
- // To update env, restart should be called via start with appropriate options
43
- pm2.start({ ...options, name: nameOrId, updateEnv: true }, (err, proc) => {
44
- if (err) return reject(err);
45
- resolve(proc);
46
- });
47
- } else {
48
- pm2.restart(nameOrId, (err, proc) => {
49
- if (err) return reject(err);
50
- resolve(proc);
51
- });
52
- }
53
- });
54
- };
55
-
56
- export const reloadApp = (nameOrId, options = {}) => {
57
- return new Promise((resolve, reject) => {
58
- if (options && options.updateEnv) {
59
- // pm2.reload doesn't accept options directly in all versions, start with updateEnv enforces a reload/restart
60
- pm2.start({ ...options, name: nameOrId, updateEnv: true }, (err, proc) => {
61
- if (err) return reject(err);
62
- resolve(proc);
63
- });
64
- } else {
65
- pm2.reload(nameOrId, (err, proc) => {
66
- if (err) return reject(err);
67
- resolve(proc);
68
- });
69
- }
70
- });
71
- };
72
-
73
- export const deleteApp = (nameOrId) => {
74
- return new Promise((resolve, reject) => {
75
- pm2.delete(nameOrId, (err, proc) => {
76
- if (err) return reject(err);
77
- resolve(proc);
78
- });
79
- });
80
- };
81
-
82
- export const disconnectPM2 = () => {
83
- pm2.disconnect();
84
- };
@@ -1,113 +0,0 @@
1
- import os from 'os';
2
- import { exec } from 'child_process';
3
- import util from 'util';
4
-
5
- const execPromise = util.promisify(exec);
6
- let lastNetworkStats = { rx: 0, tx: 0, time: Date.now() };
7
-
8
- // Cache for slow stats
9
- let cachedDiskStats = { total: 0, free: 0, used: 0, percentage: 0, lastFetch: 0 };
10
- const DISK_CACHE_TTL = 60000; // 60 seconds
11
-
12
- export const getSystemStats = async () => {
13
- const uptime = os.uptime();
14
- const totalMem = os.totalmem();
15
- const freeMem = os.freemem();
16
- const usedMem = totalMem - freeMem;
17
- const memUsage = (usedMem / totalMem) * 100;
18
-
19
- // CPU Usage (Load average or heuristic)
20
- const cpus = os.cpus();
21
- const cpuModel = cpus[0].model;
22
- const loadAvg = os.loadavg();
23
- let cpuUsage = os.platform() === 'win32' ? 0 : (loadAvg[0] / cpus.length) * 100;
24
- let diskUsage = { total: 0, free: 0, used: 0, percentage: 0 };
25
-
26
- // Network Usage
27
- let networkUsage = { down: 0, up: 0 };
28
-
29
- if (os.platform() === 'win32') {
30
- try {
31
- const now = Date.now();
32
- const promises = [];
33
-
34
- // 1. CPU Usage (Every time)
35
- const cpuPromise = execPromise('powershell -Command "(Get-Counter \'\\Processor(_Total)\\% Processor Time\' -ErrorAction SilentlyContinue).CounterSamples.CookedValue"')
36
- .then(({ stdout }) => {
37
- const realCpu = parseFloat(stdout.trim());
38
- if (!isNaN(realCpu)) cpuUsage = realCpu;
39
- })
40
- .catch(e => console.error('CPU fetch failed:', e));
41
- promises.push(cpuPromise);
42
-
43
- // 2. Network Stats (Every time)
44
- const netPromise = execPromise('powershell -Command "Get-NetAdapterStatistics | Select-Object ReceivedBytes, SentBytes | ConvertTo-Json"')
45
- .then(({ stdout }) => {
46
- const netData = JSON.parse(stdout);
47
- let totalRx = 0;
48
- let totalTx = 0;
49
- if (Array.isArray(netData)) {
50
- netData.forEach(adapter => {
51
- totalRx += adapter.ReceivedBytes || 0;
52
- totalTx += adapter.SentBytes || 0;
53
- });
54
- } else if (netData) {
55
- totalRx = netData.ReceivedBytes || 0;
56
- totalTx = netData.SentBytes || 0;
57
- }
58
- const timeDiff = (now - lastNetworkStats.time) / 1000;
59
- if (timeDiff > 0 && lastNetworkStats.rx > 0) {
60
- networkUsage.down = Math.max(0, (totalRx - lastNetworkStats.rx) / timeDiff);
61
- networkUsage.up = Math.max(0, (totalTx - lastNetworkStats.tx) / timeDiff);
62
- }
63
- lastNetworkStats = { rx: totalRx, tx: totalTx, time: now };
64
- })
65
- .catch(e => console.error('Network fetch failed:', e));
66
- promises.push(netPromise);
67
-
68
- // 3. Disk Stats (Cached)
69
- if (now - cachedDiskStats.lastFetch > DISK_CACHE_TTL) {
70
- const diskPromise = execPromise('powershell -Command "Get-Volume -DriveLetter C | Select-Object Size, SizeRemaining | ConvertTo-Json"')
71
- .then(({ stdout }) => {
72
- const data = JSON.parse(stdout);
73
- if (data.Size > 0) {
74
- cachedDiskStats = {
75
- total: data.Size,
76
- free: data.SizeRemaining,
77
- used: data.Size - data.SizeRemaining,
78
- percentage: ((data.Size - data.SizeRemaining) / data.Size) * 100,
79
- lastFetch: now
80
- };
81
- }
82
- })
83
- .catch(e => console.error('Disk fetch failed:', e));
84
- promises.push(diskPromise);
85
- }
86
-
87
- // Run all in parallel
88
- await Promise.all(promises);
89
- diskUsage = cachedDiskStats; // Use either fresh or current cache
90
- } catch (e) {
91
- console.error('Failed to get system stats via PowerShell:', e);
92
- }
93
- }
94
-
95
- return {
96
- platform: os.platform(),
97
- hostname: os.hostname(),
98
- uptime,
99
- cpu: {
100
- model: cpuModel,
101
- usage: cpuUsage,
102
- cores: cpus.length
103
- },
104
- memory: {
105
- total: totalMem,
106
- free: freeMem,
107
- used: usedMem,
108
- percentage: memUsage
109
- },
110
- disk: diskUsage,
111
- network: networkUsage
112
- };
113
- };