# `extractRoutes` — host-side WASI route probe ## Purpose `extractRoutes` is step 6 of the TS->WASM compilation pipeline: it boots the produced `.wasm` artifact under a host-side WASI runner (the same `createWasiStdioRunner` `@suaveplan/api-sandbox-wasm-host-bridge` uses at deploy time), sends a single `{kind:"routes"}` envelope, and captures the `{kind:"routes", routes}` reply. The captured `routes: readonly SerializedRoute[]` array feeds the manifest step. Reusing the bridge's runner is deliberate. If the compiler probed routes via a bespoke WASI snapshot, a guest that booted under the probe but tripped on the bridge's snapshot (or vice-versa) would slip through. By going through the exact code path the host will run, the compile-time probe exercises the same instantiation, memory binding, stdio framing, and decode logic — eliminating "compiles but won't deploy" failure modes at the source. ## Features - Single-envelope round-trip — `runner.exchange({kind:"routes"}, "routes")` returns synchronously. - `pluginName` threads through into bridge error context so a malformed routes reply surfaces with the plugin's name attached. - `stdioTimeoutMs` knob bumps the per-step deadline for plugins that need to do heavy module-scope init before the routes reply. - Guaranteed cleanup: `runner.dispose()` runs in a `finally` block whether the exchange succeeded or threw. ## Usage: Basic ```ts import { extractRoutes, validateAbi } from "@suaveplan/wasm-compiler-javy"; const { module } = await validateAbi({ wasmBytes }); const { routes } = extractRoutes({ module, pluginName: "my-plugin" }); console.log(routes); // [{ method:"GET", path:"/hello" }, ...] ``` ## Usage: Advanced ```ts import { extractRoutes } from "@suaveplan/wasm-compiler-javy"; const { routes } = extractRoutes({ module, pluginName: "my-plugin", stdioTimeoutMs: 30_000, // give a slow plugin 30s of init headroom }); if (routes.length === 0) { throw new Error("plugin declares no routes — refusing to ship"); } ``` ## API Reference - `extractRoutes(options: ExtractRoutesOptions): ExtractRoutesResult` — entrypoint. - `ExtractRoutesOptions: { module: WebAssembly.Module; pluginName: string; stdioTimeoutMs?: number }`. - `ExtractRoutesResult: { routes: readonly SerializedRoute[] }`. ## Implementation Notes The runner expects a `WasmSandboxHandle` for dispose chaining but accepts an `undefined` sandbox — the compile-time probe has no sandbox to chain against, so the field is omitted. Should the reply envelope come back with an unexpected `kind` (e.g. an `{kind:"error"}` from the plugin choking on its own `routes` getter), the function raises `ABI_VALIDATION_FAILED` with `context.reason="routes_reply_kind"` and the received kind. Empty `routes` arrays are deliberately NOT raised here — the manifest step owns that check via `WASM_COMPILER.MANIFEST_MISSING_ROUTES` so this function remains a pure probe.