// speedy-functions.js import express from "express"; import { VM, VMScript } from "vm2"; import { JSDOM } from "jsdom"; import cheerio from "cheerio"; import FileReader from "filereader"; // ────── 1. one-time constants ────────────────────────────────────────── const PORT = +(process.env.PORT ?? 5000); const TIMEOUT_MS = 5_000; const HTTP_STATUS_CODES = Object.freeze({ OK: 200, BAD_REQUEST: 400, UNAUTHORIZED: 401, FORBIDDEN: 403, NOT_FOUND: 404, INTERNAL_SERVER_ERROR: 500, BAD_GATEWAY: 502, SERVICE_UNAVAILABLE: 503, GATEWAY_TIMEOUT: 504, }); const States = Object.freeze({ SUCCESS: "SUCCESS", NOT_A_FUNCTION: "NOT_A_FUNCTION", SCRIPT_ERROR: "ERROR", TIMEOUT: "TIMEOUT", }); // convenience helpers const Response = (body = "", headers = {}, status = HTTP_STATUS_CODES.OK) => ({ body, status, headers, }); const JsonResponse = (body = {}, headers = {}, status = HTTP_STATUS_CODES.OK) => Response( JSON.stringify(body), { "Content-Type": "application/json", ...headers }, status ); const HtmlResponse = (body = "", headers = {}, status = HTTP_STATUS_CODES.OK) => Response(body, { "Content-Type": "text/html", ...headers }, status); const TextResponse = (body = "", headers = {}, status = HTTP_STATUS_CODES.OK) => Response(body, { "Content-Type": "text/plain", ...headers }, status); // ────── 2. one-time imports ──────────────────────────────────────────── const fetch = (await import("node-fetch")).default; // ────── 3. tiny script cache (precompiled) ───────────────────────────── const scriptCache = new Map(); // code-string -> VMScript const cachedScript = (code) => { if (!scriptCache.has(code)) { scriptCache.set(code, new VMScript(code)); } return scriptCache.get(code); }; // ────── 4. shared VM options (lightweight to clone) ──────────────────── const baseSandbox = { fetch, parseHTML: (html) => new JSDOM(html).window.document, JSDOM, cheerio, HTTP_STATUS_CODES, Response, JsonResponse, HtmlResponse, TextResponse, FileReader, }; function createVm(logs, requestObject, env, funcName) { return new VM({ timeout: TIMEOUT_MS, sandbox: { ...baseSandbox, console: { log: (...args) => ( logs.push(args), /* bubble to host */ console.log(...args) ), error: (...args) => (logs.push(args), console.error(...args)), }, requestObject, environment: env, FUNCTION_NAME: funcName, }, require: { external: true }, }); } // ────── 5. evaluator ─────────────────────────────────────────────────── async function executeUserCode( code, requestObject, env = {}, funcName = "userFunc" ) { const logs = []; const startTime = process.hrtime(); const vm = createVm( logs, requestObject, JSON.parse(JSON.stringify(env)), funcName ); try { const userFn = vm.run(cachedScript(code)); if (typeof userFn !== "function") { return { status: States.NOT_A_FUNCTION, result: null, logs, environment: vm.sandbox.environment, }; } const result = await Promise.resolve( userFn(requestObject, vm.sandbox.environment) ); const endTime = process.hrtime(startTime); const executionTime = (endTime[0] * 1e9 + endTime[1]) / 1e6; // in milliseconds return { status: States.SUCCESS, result, logs, environment: vm.sandbox.environment, execution_time: executionTime, }; } catch (err) { const status = /timed out/i.test(err.message) ? States.TIMEOUT : States.SCRIPT_ERROR; const endTime = process.hrtime(startTime); const executionTime = (endTime[0] * 1e9 + endTime[1]) / 1e6; // in milliseconds return { status, result: err.message ?? err, logs, environment: vm.sandbox.environment, execution_time: executionTime, }; } } // ────── 6. API surface ──────────────────────────────────────────────── const app = express(); app.use(express.json({ limit: "50mb" })); app.use((_, res, next) => { res.set({ "Access-Control-Allow-Origin": "*", "Access-Control-Allow-Headers": "Origin, X-Requested-With, Content-Type, Accept", }); next(); }); app.post("/execute", async ({ body }, res) => { const { code = "", request = {}, environment = {}, name } = body; const payload = await executeUserCode(code, request, environment, name); res.json(payload); }); app.listen(PORT, () => console.log(`⚡ server ready on :${PORT}`));