/** * arcrun API component Worker (cron) * * POST / → JSON input → WASM (WASI preview1 stdin/stdout) → JSON output * * cron 純計算(cron 表達式 → 下一個觸發時間),沒有 host function 需求。 * 方案 A:import cypher-executor/src/lib/wasi-shim.ts 的 `createWasiShim`, * 不提供任何 hostFunctions(WASM 側也沒 `//go:wasmimport u6u` 宣告)。 */ import componentWasm from '../component.wasm' assert { type: 'webassembly' }; import { Hono } from 'hono'; import { cors } from 'hono/cors'; import { createWasiShim } from '../../../cypher-executor/src/lib/wasi-shim'; const app = new Hono(); app.use('*', cors()); app.get('/', (c) => c.json({ ok: true, component: 'cron' })); app.post('/', async (c) => { let input: unknown; try { input = await c.req.json(); } catch { return c.json({ success: false, error: 'request body must be JSON' }, 400); } try { const result = await runWasm(input); return c.json(result); } catch (e) { return c.json( { success: false, error: e instanceof Error ? e.message : String(e) }, 500, ); } }); export default app; // ── WASM runner ────────────────────────────────────────────────────────────── async function runWasm(input: unknown): Promise { const shim = createWasiShim(JSON.stringify(input)); const instance = await WebAssembly.instantiate( componentWasm as WebAssembly.Module, shim.imports, ); shim.setMemory(instance.exports.memory as WebAssembly.Memory); const start = (instance.exports._start ?? instance.exports.main) as () => void; if (typeof start !== 'function') { throw new Error('WASM missing _start or main export'); } try { start(); } catch (e) { if (!(e instanceof Error && e.message === 'wasm exit: 0')) throw e; } const stdout = shim.getStdout().trim(); if (!stdout) throw new Error('WASM component produced no output'); return JSON.parse(stdout); }