/** * arcrun `code` 零件 —— Worker host(可部署) * * POST / → { code, input?, limits? } * → QuickJS-wasm 沙箱(./sandbox.mjs 的 runCode) * → { success:true, data } | { success:false, error, error_type } * * 封裝=A(quickjs-emscripten singlefile variant):wasm 內嵌為 base64、同步載入, * bundler 友善、無需 [[wasm_modules]] 綁定、無需 nodejs_compat(sandbox 用 TextEncoder 計 bytes)。 * * 與其他 logic 零件不同:`code` 是自足 Worker(自帶 index.ts + sandbox.mjs + quickjs variant), * 不走 component-worker-template 的 TinyGo-wasm bundling 流程。部署見 DEPLOY.md。 */ import { Hono } from 'hono'; import { cors } from 'hono/cors'; // @ts-expect-error —— sandbox.mjs 為 runtime-agnostic JS 核心(Node 測試與 Worker 共用同一份) import { runCode } from './sandbox.mjs'; const app = new Hono(); app.use('*', cors()); app.get('/', (c) => c.json({ ok: true, component: 'code' })); app.post('/', async (c) => { let body: { code?: unknown; input?: unknown; limits?: Record }; try { body = await c.req.json(); } catch { return c.json({ success: false, error: 'request body must be JSON', error_type: 'ContractError' }, 400); } if (typeof body.code !== 'string') { return c.json({ success: false, error: 'code (string) is required', error_type: 'ContractError' }, 400); } try { const result = await runCode(body.code, body.input, { limits: body.limits }); // sandbox 永遠回結構化 envelope;success=false 仍以 200 帶 error_type 回(零件語義層錯,非 HTTP 錯) return c.json(result); } catch (e) { // 理論上 runCode 自己 try/catch;這層是最後保險,Worker 絕不掛。 return c.json( { success: false, error: e instanceof Error ? e.message : String(e), error_type: 'SandboxError' }, 500, ); } }); export default app;