UNPKG

n8n-nodes-filemanager

Version:

Manage files and folders on disk with create, copy, move, remove, and rename operations for n8n workflows

445 lines 20.9 kB
"use strict"; var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { if (k2 === undefined) k2 = k; var desc = Object.getOwnPropertyDescriptor(m, k); if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { desc = { enumerable: true, get: function() { return m[k]; } }; } Object.defineProperty(o, k2, desc); }) : (function(o, m, k, k2) { if (k2 === undefined) k2 = k; o[k2] = m[k]; })); var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { Object.defineProperty(o, "default", { enumerable: true, value: v }); }) : function(o, v) { o["default"] = v; }); var __importStar = (this && this.__importStar) || (function () { var ownKeys = function(o) { ownKeys = Object.getOwnPropertyNames || function (o) { var ar = []; for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k; return ar; }; return ownKeys(o); }; return function (mod) { if (mod && mod.__esModule) return mod; var result = {}; if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]); __setModuleDefault(result, mod); return result; }; })(); Object.defineProperty(exports, "__esModule", { value: true }); exports.FileManager = void 0; const n8n_workflow_1 = require("n8n-workflow"); const fs_1 = require("fs"); const path = __importStar(require("path")); const child_process_1 = require("child_process"); const zlib_1 = require("zlib"); class FileManager { constructor() { this.description = { displayName: 'File Manager', name: 'fileManager', icon: 'fa:folder-open', group: ['transform'], version: 1, usableAsTool: true, description: 'Manage files and folders on disk', defaults: { name: 'File Manager' }, inputs: ["main"], outputs: ["main"], properties: [ { displayName: 'Operation', name: 'operation', type: 'options', noDataExpression: true, options: [ { name: 'Append', value: 'append' }, { name: 'Change Permissions', value: 'chmod' }, { name: 'Compress', value: 'compress' }, { name: 'Copy', value: 'copy' }, { name: 'Create', value: 'create' }, { name: 'Exists', value: 'exists' }, { name: 'Extract', value: 'extract' }, { name: 'List', value: 'list' }, { name: 'Metadata', value: 'metadata' }, { name: 'Move', value: 'move' }, { name: 'Read', value: 'read' }, { name: 'Remove', value: 'remove' }, { name: 'Rename', value: 'rename' }, { name: 'Search', value: 'search' }, { name: 'Write', value: 'write' }, ], default: 'remove', }, { displayName: 'Source Path', name: 'sourcePath', type: 'string', default: '', placeholder: '/path/to/source', description: 'Path of the source file or folder', required: true, }, { displayName: 'Destination Path', name: 'destinationPath', type: 'string', default: '', placeholder: '/path/to/destination', description: 'Target path for copy, move, rename, compress, and extract operations', required: true, displayOptions: { show: { operation: ['compress', 'copy', 'extract', 'move', 'rename'], }, }, }, { displayName: 'Recursive', name: 'recursive', type: 'boolean', default: true, description: 'Whether to delete folders recursively', displayOptions: { show: { operation: ['remove'], }, }, }, { displayName: 'Target Path', name: 'targetPath', type: 'string', default: '', placeholder: '/path/to/target', description: 'Path of the file or folder to operate on', required: true, displayOptions: { show: { operation: ['read', 'write', 'append', 'list', 'exists', 'metadata', 'chmod'], }, }, }, { displayName: 'Data', name: 'data', type: 'string', default: '', description: 'Content to write or append to the file', displayOptions: { show: { operation: ['write', 'append'], }, }, }, { displayName: 'Encoding', name: 'encoding', type: 'string', default: 'utf8', description: 'File encoding', displayOptions: { show: { operation: ['read', 'write', 'append'], }, }, }, { displayName: 'Mode', name: 'mode', type: 'number', default: 0o644, description: 'Unix permission bits, e.g. 644', displayOptions: { show: { operation: ['chmod'], }, }, }, { displayName: 'Base Path', name: 'basePath', type: 'string', default: '', placeholder: '/start/path', description: 'Directory to start searching from', required: true, displayOptions: { show: { operation: ['search'], }, }, }, { displayName: 'Pattern', name: 'pattern', type: 'string', default: '', placeholder: '.*\\.txt$', description: 'Regex pattern to match file paths', required: true, displayOptions: { show: { operation: ['search'], }, }, }, ], }; } async execute() { const inputItems = this.getInputData(); const returnItems = []; for (let i = 0; i < inputItems.length; i++) { try { const operation = this.getNodeParameter('operation', i); switch (operation) { case 'remove': { const sourcePath = this.getNodeParameter('sourcePath', i); let isDir = false; try { const stats = await fs_1.promises.lstat(sourcePath); isDir = stats.isDirectory(); } catch { isDir = false; } if (isDir) { const recursive = this.getNodeParameter('recursive', i); if (recursive) { await fs_1.promises.rm(sourcePath, { recursive: true, force: true }); } else { await fs_1.promises.rmdir(sourcePath); } } else { await fs_1.promises.unlink(sourcePath); } break; } case 'copy': { const sourcePath = this.getNodeParameter('sourcePath', i); const destinationPath = this.getNodeParameter('destinationPath', i); let isDir = false; try { const stats = await fs_1.promises.lstat(sourcePath); isDir = stats.isDirectory(); } catch { isDir = false; } if (isDir) { const copyDirectory = async (src, dest) => { await fs_1.promises.mkdir(dest, { recursive: true }); const entries = await fs_1.promises.readdir(src, { withFileTypes: true }); for (const entry of entries) { const srcPath = path.join(src, entry.name); const destPath = path.join(dest, entry.name); if (entry.isDirectory()) { await copyDirectory(srcPath, destPath); } else if (entry.isSymbolicLink()) { const symlink = await fs_1.promises.readlink(srcPath); await fs_1.promises.symlink(symlink, destPath); } else { await fs_1.promises.copyFile(srcPath, destPath); } } }; await copyDirectory(sourcePath, destinationPath); } else { await fs_1.promises.copyFile(sourcePath, destinationPath); } break; } case 'move': { const sourcePath = this.getNodeParameter('sourcePath', i); const destinationPath = this.getNodeParameter('destinationPath', i); await fs_1.promises.rename(sourcePath, destinationPath); break; } case 'compress': { const sourcePath = this.getNodeParameter('sourcePath', i); const destinationPath = this.getNodeParameter('destinationPath', i); await new Promise((resolve, reject) => { const tar = (0, child_process_1.spawn)('tar', ['-czf', destinationPath, path.basename(sourcePath)], { cwd: path.dirname(sourcePath), }); tar.on('error', reject); tar.on('close', (code) => { if (code !== 0) reject(new Error(`tar exited with code ${code}`)); else resolve(); }); }); break; } case 'extract': { const sourcePath = this.getNodeParameter('sourcePath', i); const destinationPath = this.getNodeParameter('destinationPath', i); await fs_1.promises.mkdir(destinationPath, { recursive: true }); await new Promise((resolve, reject) => { const input = (0, fs_1.createReadStream)(sourcePath); const gunzip = (0, zlib_1.createGunzip)(); const tar = (0, child_process_1.spawn)('tar', ['-xf', '-', '-C', destinationPath]); tar.on('error', reject); tar.on('close', (code) => { if (code !== 0) reject(new Error(`tar exited with code ${code}`)); else resolve(); }); input.pipe(gunzip).pipe(tar.stdin).on('error', reject); }); break; } case 'create': { const sourcePath = this.getNodeParameter('sourcePath', i); const ext = path.extname(sourcePath); if (ext) { await fs_1.promises.writeFile(sourcePath, '', 'utf8'); } else { await fs_1.promises.mkdir(sourcePath, { recursive: true }); } break; } case 'rename': { const sourcePath = this.getNodeParameter('sourcePath', i); const destinationPath = this.getNodeParameter('destinationPath', i); await fs_1.promises.rename(sourcePath, destinationPath); break; } case 'read': { const targetPath = this.getNodeParameter('targetPath', i); const encoding = this.getNodeParameter('encoding', i); const data = await fs_1.promises.readFile(targetPath, { encoding }); inputItems[i].json.data = data; inputItems[i].json.targetPath = targetPath; break; } case 'write': { const targetPath = this.getNodeParameter('targetPath', i); const content = this.getNodeParameter('data', i); const encoding = this.getNodeParameter('encoding', i); await fs_1.promises.writeFile(targetPath, content, { encoding }); inputItems[i].json.targetPath = targetPath; break; } case 'append': { const targetPath = this.getNodeParameter('targetPath', i); const content = this.getNodeParameter('data', i); const encoding = this.getNodeParameter('encoding', i); await fs_1.promises.appendFile(targetPath, content, { encoding }); inputItems[i].json.targetPath = targetPath; break; } case 'chmod': { const targetPath = this.getNodeParameter('targetPath', i); const mode = this.getNodeParameter('mode', i); await fs_1.promises.chmod(targetPath, mode); inputItems[i].json.targetPath = targetPath; inputItems[i].json.mode = mode; break; } case 'list': { const targetPath = this.getNodeParameter('targetPath', i); const files = await fs_1.promises.readdir(targetPath); inputItems[i].json.list = files; inputItems[i].json.targetPath = targetPath; break; } case 'exists': { const targetPath = this.getNodeParameter('targetPath', i); let exists = true; try { await fs_1.promises.access(targetPath); } catch { exists = false; } inputItems[i].json.exists = exists; inputItems[i].json.targetPath = targetPath; break; } case 'metadata': { const targetPath = this.getNodeParameter('targetPath', i); const stats = await fs_1.promises.lstat(targetPath); inputItems[i].json.size = stats.size; inputItems[i].json.mtime = stats.mtime; inputItems[i].json.atime = stats.atime; inputItems[i].json.isDirectory = stats.isDirectory(); inputItems[i].json.isFile = stats.isFile(); inputItems[i].json.targetPath = targetPath; break; } case 'search': { const basePath = this.getNodeParameter('basePath', i); const pattern = this.getNodeParameter('pattern', i); const regex = new RegExp(pattern); const matches = []; const walk = async (dir) => { const entries = await fs_1.promises.readdir(dir, { withFileTypes: true }); for (const entry of entries) { const full = path.join(dir, entry.name); if (regex.test(full)) matches.push(full); if (entry.isDirectory()) await walk(full); } }; await walk(basePath); inputItems[i].json.paths = matches; inputItems[i].json.basePath = basePath; break; } default: throw new n8n_workflow_1.NodeOperationError(this.getNode(), `Unknown operation "${operation}"`); } inputItems[i].json.operation = operation; inputItems[i].json.success = true; if (['compress', 'copy', 'extract', 'move', 'rename', 'remove', 'create'].includes(operation)) { inputItems[i].json.sourcePath = this.getNodeParameter('sourcePath', i); } if (['compress', 'copy', 'extract', 'move', 'rename'].includes(operation)) { inputItems[i].json.destinationPath = this.getNodeParameter('destinationPath', i); } if (['read', 'write', 'append', 'list', 'exists', 'metadata', 'chmod'].includes(operation)) { inputItems[i].json.targetPath = this.getNodeParameter('targetPath', i); } if (operation === 'search') { inputItems[i].json.basePath = this.getNodeParameter('basePath', i); inputItems[i].json.pattern = this.getNodeParameter('pattern', i); } returnItems.push(inputItems[i]); } catch (error) { if (this.continueOnFail()) { returnItems.push({ json: inputItems[i].json, error, pairedItem: i, }); continue; } if (error instanceof n8n_workflow_1.NodeOperationError) { throw error; } throw new n8n_workflow_1.NodeOperationError(this.getNode(), error, { itemIndex: i }); } } return [returnItems]; } } exports.FileManager = FileManager; //# sourceMappingURL=FileManager.node.js.map