import { BUILTIN_COMPONENTS } from './constants'; import type { Bindings, ComponentRunner } from '../types'; /** * 建立零件載入器 * * 三層優先序: * 1. 內建零件(BUILTIN_COMPONENTS,純本地轉換,不需 R2) * 2. WASM_BUCKET R2 直讀 → {componentId}/{componentId}.wasm * 3. 找不到 → 結構化錯誤(含 R2 key 與修復說明) */ export function createComponentLoader(env: Bindings) { return async (componentId: string): Promise => { // 層 1:內建零件(無需 R2) const builtin = BUILTIN_COMPONENTS.get(componentId); if (builtin) return builtin; // 層 2:從 WASM_BUCKET R2 讀取 const wasmKey = `${componentId}/${componentId}.wasm`; const wasmObj = await env.WASM_BUCKET.get(wasmKey); if (wasmObj) { const wasmBuffer = await wasmObj.arrayBuffer(); return createWasmRunner(componentId, wasmBuffer, env); } // 層 3:找不到 throw new Error( `零件 ${componentId} 不存在。\n` + `請確認 ${wasmKey} 已上傳至 WASM_BUCKET。\n` + `修復:執行 acr parts 查看可用零件清單。` ); }; } /** * 建立 WASM 零件執行器 * 使用 WASI preview1 stdin/stdout JSON I/O 模型 */ function createWasmRunner( componentId: string, wasmBuffer: ArrayBuffer, _env: Bindings, ): ComponentRunner { return async (ctx: unknown): Promise => { // 動態 import wasm-executor(避免頂層 import 造成 Worker 啟動問題) const { executeWasm } = await import('./wasm-executor'); return executeWasm(componentId, wasmBuffer, ctx); }; }