Files
idea.llm.gitea.repo.docker.…/app/main/ssh-service.js
2026-02-27 08:55:41 -06:00

197 lines
4.1 KiB
JavaScript

const { Client } = require('ssh2');
const fs = require('fs');
const path = require('path');
class SSHService {
constructor(config) {
this.config = config;
this.client = null;
}
connect() {
return new Promise((resolve, reject) => {
this.client = new Client();
this.client.on('ready', () => {
resolve();
});
this.client.on('error', (err) => {
reject(err);
});
this.client.connect({
host: this.config.host,
port: this.config.port || 22,
username: this.config.username,
password: this.config.password
});
});
}
disconnect() {
if (this.client) {
this.client.end();
this.client = null;
}
}
exec(command) {
return new Promise((resolve, reject) => {
if (!this.client) {
reject(new Error('Not connected'));
return;
}
this.client.exec(command, (err, stream) => {
if (err) {
reject(err);
return;
}
let output = '';
let errorOutput = '';
stream.on('close', (code) => {
if (code !== 0 && errorOutput) {
reject(new Error(errorOutput));
} else {
resolve(output);
}
});
stream.on('data', (data) => {
output += data.toString();
});
stream.stderr.on('data', (data) => {
errorOutput += data.toString();
});
});
});
}
uploadFile(localPath, remotePath) {
return new Promise((resolve, reject) => {
if (!this.client) {
reject(new Error('Not connected'));
return;
}
this.client.sftp((err, sftp) => {
if (err) {
reject(err);
return;
}
const readStream = fs.createReadStream(localPath);
const writeStream = sftp.createWriteStream(remotePath);
writeStream.on('close', () => {
resolve();
});
writeStream.on('error', (err) => {
reject(err);
});
readStream.pipe(writeStream);
});
});
}
downloadFile(remotePath, localPath) {
return new Promise((resolve, reject) => {
if (!this.client) {
reject(new Error('Not connected'));
return;
}
this.client.sftp((err, sftp) => {
if (err) {
reject(err);
return;
}
// Ensure local directory exists
const localDir = path.dirname(localPath);
if (!fs.existsSync(localDir)) {
fs.mkdirSync(localDir, { recursive: true });
}
const readStream = sftp.createReadStream(remotePath);
const writeStream = fs.createWriteStream(localPath);
writeStream.on('close', () => {
resolve();
});
writeStream.on('error', (err) => {
reject(err);
});
readStream.on('error', (err) => {
reject(err);
});
readStream.pipe(writeStream);
});
});
}
readRemoteFile(remotePath) {
return new Promise((resolve, reject) => {
if (!this.client) {
reject(new Error('Not connected'));
return;
}
this.client.sftp((err, sftp) => {
if (err) {
reject(err);
return;
}
sftp.readFile(remotePath, 'utf-8', (err, data) => {
if (err) {
reject(err);
} else {
resolve(data);
}
});
});
});
}
listDirectory(remotePath) {
return new Promise((resolve, reject) => {
if (!this.client) {
reject(new Error('Not connected'));
return;
}
this.client.sftp((err, sftp) => {
if (err) {
reject(err);
return;
}
sftp.readdir(remotePath, (err, list) => {
if (err) {
reject(err);
} else {
resolve(list.map(item => ({
name: item.filename,
isDirectory: item.attrs.isDirectory(),
size: item.attrs.size,
mtime: item.attrs.mtime
})));
}
});
});
});
}
}
module.exports = { SSHService };