import { NextRequest, NextResponse } from 'next/server' import { Script, createContext } from 'vm' // Explicitly export allowed methods export const dynamic = 'force-dynamic' // Disable static optimization export const runtime = 'nodejs' // Use Node.js runtime /** * Resolves environment variables and tags in code * @param code - Code with variables * @param params - Parameters that may contain variable values * @param envVars - Environment variables from the workflow * @returns Resolved code */ function resolveCodeVariables( code: string, params: Record, envVars: Record = {} ): string { let resolvedCode = code // Resolve environment variables with {{var_name}} syntax const envVarMatches = resolvedCode.match(/\{\{([^}]+)\}\}/g) || [] for (const match of envVarMatches) { const varName = match.slice(2, -2).trim() // Priority: 1. Environment variables from workflow, 2. Params, 3. process.env const varValue = envVars[varName] || params[varName] || process.env[varName] || '' resolvedCode = resolvedCode.replace(match, varValue) } // Resolve tags with syntax const tagMatches = resolvedCode.match(/<([^>]+)>/g) || [] for (const match of tagMatches) { const tagName = match.slice(1, -1).trim() const tagValue = params[tagName] || '' resolvedCode = resolvedCode.replace(match, tagValue) } return resolvedCode } export async function POST(req: NextRequest) { const startTime = Date.now() let stdout = '' try { const body = await req.json() const { code, params = {}, timeout = 3000, envVars = {} } = body // Resolve variables in the code with workflow environment variables const resolvedCode = resolveCodeVariables(code, params, envVars) // Create a secure context with console logging const context = createContext({ params, environmentVariables: envVars, // Make environment variables available in the context console: { log: (...args: any[]) => { const logMessage = args .map((arg) => (typeof arg === 'object' ? JSON.stringify(arg, null, 2) : String(arg))) .join(' ') + '\n' stdout += logMessage }, error: (...args: any[]) => { const errorMessage = args .map((arg) => (typeof arg === 'object' ? JSON.stringify(arg, null, 2) : String(arg))) .join(' ') + '\n' console.error('❌ Code Console Error:', errorMessage.trim()) stdout += 'ERROR: ' + errorMessage }, }, }) const script = new Script(` (async () => { try { ${resolvedCode} } catch (error) { console.error(error); throw error; } })() `) const result = await script.runInContext(context, { timeout, displayErrors: true, }) const executionTime = Date.now() - startTime const response = { success: true, output: { result, stdout, executionTime, }, } return NextResponse.json(response) } catch (error: any) { const executionTime = Date.now() - startTime const errorResponse = { success: false, error: error.message || 'Code execution failed', output: { result: null, stdout, executionTime, }, } return NextResponse.json(errorResponse, { status: 500 }) } }