const { Client } = require('ssh2'); const fs = require('fs'); require('dotenv').config(); const getSSHConfig = () => { const config = { host: process.env.SSH_HOST, username: process.env.SSH_USER, port: 22, }; let privateKeyPath = process.env.SSH_KEY_PATH; if (privateKeyPath && privateKeyPath.endsWith('.pub')) { privateKeyPath = privateKeyPath.replace('.pub', ''); } if (privateKeyPath) { config.privateKey = fs.readFileSync(privateKeyPath); } else if (process.env.SSH_PASSWORD) { config.password = process.env.SSH_PASSWORD; } return config; }; const execCommand = (command) => { return new Promise((resolve, reject) => { const conn = new Client(); conn.on('ready', () => { conn.exec(command, (err, stream) => { if (err) { conn.end(); return reject(err); } let output = ''; let errorOutput = ''; stream.on('close', (code, signal) => { conn.end(); if (code !== 0) return reject(new Error(`Command failed with code ${code}: ${errorOutput}`)); resolve(output.trim()); }).on('data', (data) => { output += data; }).stderr.on('data', (data) => { errorOutput += data; }); }); }).on('error', (err) => { reject(err); }).connect(getSSHConfig()); }); }; const readFile = (filePath) => { return execCommand(`cat "${filePath}"`); }; const writeFile = (filePath, content) => { // Basic implementation: echo content to file. // WARNING: Not safe for large files or complex headers, but start simple. // Ideally use SFTP for robustness later. const escapedContent = content.replace(/"/g, '\\"'); return execCommand(`echo "${escapedContent}" > "${filePath}"`); }; module.exports = { execCommand, readFile, writeFile };