const { execFile } = require("child_process"); const process = require("process"); const PM2_EXEC_OPTIONS = { timeout: 5000, maxBuffer: 10 * 1024 * 1024, }; /** * Truncate command output to keep error messages compact. * @param {string | Buffer} output Command output. * @returns {string} The truncated output text. */ function truncateOutput(output) { const text = (output || "").toString().trim(); if (text.length > 200) { return text.substring(0, 200) + "..."; } return text; } /** * Query PM2 for the current process list. * @returns {Promise<{id: string, name: string, status: string}[]>} The normalized PM2 process list. */ function getPM2ProcessList() { return new Promise((resolve, reject) => { execFile( process.platform === "win32" ? "pm2.cmd" : "pm2", ["jlist"], PM2_EXEC_OPTIONS, (error, stdout, stderr) => { if (error) { const details = truncateOutput(stderr) || error.code || error.message; reject(new Error(`Unable to query PM2 process list (${details}).`)); return; } try { const parsed = JSON.parse((stdout || "").toString()); if (!Array.isArray(parsed)) { reject(new Error("Unexpected PM2 process list output.")); return; } resolve( parsed .map((item) => { const id = item?.pm_id != null ? String(item.pm_id) : null; const name = item?.name || null; if (!id && !name) { return null; } return { id: id || name, name: name || id, status: item?.pm2_env?.status?.toString().toLowerCase() || "unknown", }; }) .filter(Boolean) ); } catch (parseError) { reject(new Error(truncateOutput(stderr) || "Unable to parse PM2 process list output.")); } } ); }); } module.exports = { getPM2ProcessList, };