Initial Commit
This commit is contained in:
@@ -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.
|
||||
Reference in New Issue
Block a user