import fs from "fs-extra";
import path from "path";
import { createHash } from "crypto";
export class FileOperations {
constructor(securityManager) {
this.security = securityManager;
}
async readFile(filePath) {
try {
const validPath = this.security.validatePath(filePath);
await this.security.checkPermissions(validPath, 'read');
await this.security.validateFileSize(validPath);
const content = await fs.readFile(validPath, 'utf8');
const stats = await fs.stat(validPath);
return {
content: [{
type: "text",
text: `📄 File: ${path.basename(validPath)} (${stats.size} bytes)\n\n${content}`
}]
};
} catch (error) {
return {
content: [{
type: "text",
text: `❌ Error reading file: ${error.message}`
}]
};
}
}
async writeFile(filePath, content, backup = true) {
try {
const validPath = this.security.validatePath(filePath);
await this.security.checkPermissions(validPath, 'write');
let backupPath = null;
if (backup) {
backupPath = await this.security.createBackup(validPath);
}
await fs.ensureDir(path.dirname(validPath));
await fs.writeFile(validPath, content, 'utf8');
const stats = await fs.stat(validPath);
const message = `✅ File written successfully: ${path.basename(validPath)} (${stats.size} bytes)`;
return {
content: [{
type: "text",
text: backupPath ? `${message}\n💾 Backup created: ${backupPath}` : message
}]
};
} catch (error) {
return {
content: [{
type: "text",
text: `❌ Error writing file: ${error.message}`
}]
};
}
}
async appendFile(filePath, content) {
try {
const validPath = this.security.validatePath(filePath);
await this.security.checkPermissions(validPath, 'write');
await fs.ensureDir(path.dirname(validPath));
await fs.appendFile(validPath, content, 'utf8');
const stats = await fs.stat(validPath);
return {
content: [{
type: "text",
text: `✅ Content appended successfully to: ${path.basename(validPath)} (${stats.size} bytes total)`
}]
};
} catch (error) {
return {
content: [{
type: "text",
text: `❌ Error appending to file: ${error.message}`
}]
};
}
}
async copyFile(source, destination) {
try {
const validSource = this.security.validatePath(source);
const validDest = this.security.validatePath(destination);
await this.security.checkPermissions(validSource, 'read');
await this.security.checkPermissions(validDest, 'write');
await this.security.validateFileSize(validSource);
await fs.ensureDir(path.dirname(validDest));
await fs.copy(validSource, validDest);
const stats = await fs.stat(validDest);
return {
content: [{
type: "text",
text: `✅ File copied successfully: ${path.basename(validSource)} → ${path.basename(validDest)} (${stats.size} bytes)`
}]
};
} catch (error) {
return {
content: [{
type: "text",
text: `❌ Error copying file: ${error.message}`
}]
};
}
}
async moveFile(source, destination) {
try {
const validSource = this.security.validatePath(source);
const validDest = this.security.validatePath(destination);
await this.security.checkPermissions(validSource, 'read');
await this.security.checkPermissions(validSource, 'delete');
await this.security.checkPermissions(validDest, 'write');
await fs.ensureDir(path.dirname(validDest));
await fs.move(validSource, validDest);
const stats = await fs.stat(validDest);
return {
content: [{
type: "text",
text: `✅ File moved successfully: ${path.basename(validSource)} → ${path.basename(validDest)} (${stats.size} bytes)`
}]
};
} catch (error) {
return {
content: [{
type: "text",
text: `❌ Error moving file: ${error.message}`
}]
};
}
}
async deleteFile(filePath, backup = true) {
try {
const validPath = this.security.validatePath(filePath);
await this.security.checkPermissions(validPath, 'delete');
let backupPath = null;
if (backup) {
backupPath = await this.security.createBackup(validPath);
}
await fs.remove(validPath);
const message = `✅ File deleted successfully: ${path.basename(validPath)}`;
return {
content: [{
type: "text",
text: backupPath ? `${message}\n💾 Backup created: ${backupPath}` : message
}]
};
} catch (error) {
return {
content: [{
type: "text",
text: `❌ Error deleting file: ${error.message}`
}]
};
}
}
async getFileInfo(filePath) {
try {
const validPath = this.security.validatePath(filePath);
await this.security.checkPermissions(validPath, 'read');
const stats = await fs.stat(validPath);
const hash = createHash('md5');
const content = await fs.readFile(validPath);
hash.update(content);
const fileInfo = {
path: validPath,
name: path.basename(validPath),
size: stats.size,
sizeHuman: this.formatFileSize(stats.size),
created: stats.birthtime,
modified: stats.mtime,
accessed: stats.atime,
isFile: stats.isFile(),
isDirectory: stats.isDirectory(),
permissions: stats.mode,
hash: hash.digest('hex')
};
return {
content: [{
type: "text",
text: `📊 File Information:\n${JSON.stringify(fileInfo, null, 2)}`
}]
};
} catch (error) {
return {
content: [{
type: "text",
text: `❌ Error getting file info: ${error.message}`
}]
};
}
}
formatFileSize(bytes) {
const sizes = ['Bytes', 'KB', 'MB', 'GB'];
if (bytes === 0) return '0 Bytes';
const i = parseInt(Math.floor(Math.log(bytes) / Math.log(1024)));
return Math.round(bytes / Math.pow(1024, i) * 100) / 100 + ' ' + sizes[i];
}
}