UNPKG

@badc0d3/piece-bash-runner

Version:

Run bash commands with NFS/SMB mounting support in Activepieces

191 lines (189 loc) 7.47 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.runBashCommand = void 0; const pieces_framework_1 = require("@activepieces/pieces-framework"); const child_process_1 = require("child_process"); const util_1 = require("util"); const fs_1 = require("fs"); const execAsync = (0, util_1.promisify)(child_process_1.exec); exports.runBashCommand = (0, pieces_framework_1.createAction)({ name: 'run-bash-command', displayName: 'Run Bash Command', description: 'Execute bash commands with optional NFS/SMB mounting', props: { command: pieces_framework_1.Property.LongText({ displayName: 'Bash Command', description: 'The bash command or script to execute', required: true, defaultValue: `#!/bin/bash # Example: List files and show system info echo "Current directory: $(pwd)" echo "Files:" ls -la echo "" echo "System info:" uname -a`, }), mountConfig: pieces_framework_1.Property.Object({ displayName: 'Mount Configuration (Optional)', description: 'Configure NFS or SMB mount before running command', required: false, }), mountType: pieces_framework_1.Property.StaticDropdown({ displayName: 'Mount Type', description: 'Type of network mount (leave empty for no mount)', required: false, options: { options: [ { label: 'None', value: '' }, { label: 'NFS', value: 'nfs' }, { label: 'SMB/CIFS', value: 'smb' }, ], }, defaultValue: '', }), mountSource: pieces_framework_1.Property.ShortText({ displayName: 'Mount Source', description: 'Network path (e.g., server:/path or //server/share)', required: false, }), mountPoint: pieces_framework_1.Property.ShortText({ displayName: 'Mount Point', description: 'Local mount point (e.g., /mnt/network)', required: false, defaultValue: '/mnt/network', }), mountOptions: pieces_framework_1.Property.ShortText({ displayName: 'Mount Options', description: 'Additional mount options', required: false, defaultValue: '', }), mountUsername: pieces_framework_1.Property.ShortText({ displayName: 'Username (SMB only)', description: 'Username for SMB authentication', required: false, }), mountPassword: pieces_framework_1.Property.ShortText({ displayName: 'Password (SMB only)', description: 'Password for SMB authentication (use secure storage in production)', required: false, }), workingDirectory: pieces_framework_1.Property.ShortText({ displayName: 'Working Directory', description: 'Directory to execute the command in', required: false, defaultValue: '/tmp', }), timeout: pieces_framework_1.Property.Number({ displayName: 'Timeout (seconds)', description: 'Maximum execution time in seconds', required: false, defaultValue: 30, }), captureOutput: pieces_framework_1.Property.Checkbox({ displayName: 'Capture Output', description: 'Capture stdout and stderr separately', required: false, defaultValue: true, }), }, async run(context) { const { command, mountType, mountSource, mountPoint, mountOptions, mountUsername, mountPassword, workingDirectory, timeout, captureOutput } = context.propsValue; let mountCleanup = ''; let fullCommand = ''; try { // Create working directory if it doesn't exist if (!(0, fs_1.existsSync)(workingDirectory)) { (0, fs_1.mkdirSync)(workingDirectory, { recursive: true }); } // Handle mount configuration if provided if (mountType && mountType !== '' && mountSource) { // Create mount point if it doesn't exist if (!(0, fs_1.existsSync)(mountPoint)) { (0, fs_1.mkdirSync)(mountPoint, { recursive: true }); } // Build mount command based on type let mountCommand = ''; if (mountType === 'nfs') { const nfsOptions = mountOptions || 'rw,sync'; mountCommand = `mount -t nfs -o ${nfsOptions} ${mountSource} ${mountPoint}`; } else if (mountType === 'smb') { let smbOptions = mountOptions || 'rw'; if (mountUsername) { smbOptions += `,username=${mountUsername}`; if (mountPassword) { smbOptions += `,password=${mountPassword}`; } } mountCommand = `mount -t cifs -o ${smbOptions} ${mountSource} ${mountPoint}`; } // Set up cleanup command mountCleanup = `umount ${mountPoint} 2>/dev/null || true`; // Combine mount, command, and cleanup fullCommand = ` # Mount network drive ${mountCommand} # Execute user command cd ${workingDirectory} ${command} # Cleanup will happen in finally block `; } else { // No mount needed, just run the command fullCommand = `cd ${workingDirectory} && ${command}`; } // Execute the command const { stdout, stderr } = await execAsync(fullCommand, { timeout: (timeout || 30) * 1000, maxBuffer: 10 * 1024 * 1024, // 10MB buffer shell: '/bin/bash', }); // Clean up mount if needed if (mountCleanup) { try { await execAsync(mountCleanup); } catch (e) { // Ignore unmount errors } } if (captureOutput) { return { success: true, output: stdout || '', stdout: stdout || '', stderr: stderr || '', executionTime: new Date().toISOString(), }; } return { success: true, output: stdout || '', executionTime: new Date().toISOString(), }; } catch (error) { // Try to clean up mount on error if (mountCleanup) { try { await execAsync(mountCleanup); } catch (e) { // Ignore unmount errors } } return { success: false, error: error.message, stdout: error.stdout || '', stderr: error.stderr || '', code: error.code || 1, executionTime: new Date().toISOString(), }; } }, }); //# sourceMappingURL=run-bash-command.js.map