Initial Commit

This commit is contained in:
2026-05-27 23:29:53 +01:00
commit fbc70f96e6
10000 changed files with 1102152 additions and 0 deletions

View File

@@ -0,0 +1,49 @@
# `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.