import { execa } from "execa"; import PQueue from "p-queue"; // Configure the queue with a concurrency limit const scriptQueue = new PQueue({ concurrency: 5 }); export type ScriptParams = { scriptPath: string; args?: string[]; onProgress?: (data: string) => void; }; export type ScriptResult = { success: boolean; stdout: string; stderr: string; error?: string; }; /** * Executes a bash script with queue management */ export async function executeScript( params: ScriptParams, ): Promise { // Add the script execution to the queue // hardcoded the allowed script path for security reasons var allowedScriptPaths = [ "/tmp/api_scripts/hello_test.sh", "/tmp/api_scripts/video_add_watermark.sh", ]; if (!allowedScriptPaths.includes(params.scriptPath)) { return { success: false, stdout: "", stderr: "", error: "Script path is not allowed", }; } const result = await scriptQueue.add(async () => { try { // Execute the bash script const { stdout, stderr } = await execa( "bash", [params.scriptPath, ...(params.args || [])], { buffer: true, // Changed to true to ensure we get the complete output }, ); // If onProgress is provided, we can use it to stream script output if (params.onProgress && stdout) { params.onProgress(stdout.toString()); } return { success: true, stdout: stdout ? stdout.toString() : "", stderr: stderr ? stderr.toString() : "", }; } catch (error: any) { // Handle script execution errors return { success: false, stdout: error.stdout ? error.stdout.toString() : "", stderr: error.stderr ? error.stderr.toString() : "", error: error.message || "Failed to execute script", }; } }); return result as ScriptResult; } // Get current queue size and pending tasks export function getQueueStats() { return { size: scriptQueue.size, pending: scriptQueue.pending, isPaused: scriptQueue.isPaused, }; } // Pause the queue (no further tasks will be executed until resumed) export function pauseQueue() { scriptQueue.pause(); } // Resume the queue export function resumeQueue() { scriptQueue.start(); }