Initial Commit
This commit is contained in:
@@ -0,0 +1,52 @@
|
||||
# Route discovery
|
||||
|
||||
<!-- begin:auto-docs -->
|
||||
_(no submodules)_
|
||||
<!-- end:auto-docs -->
|
||||
|
||||
## Purpose
|
||||
|
||||
`discoverRoutes(exports, pluginName)` calls the guest's `__suaveplan_routes` export exactly once at bridge-init time, unpacks the `(pointer, length)` pair the guest returns as a packed `bigint`, reads the JSON-encoded `SerializedRoute[]` from linear memory, frees the guest-allocated buffer, and returns the typed array. The bridge uses this list to build the `PipelineRoute` array installed on the host.
|
||||
|
||||
## Features
|
||||
|
||||
- Single bridge-init call — the result is cached by `createSandboxedWasmPluginModule`; the guest is never asked for its routes again.
|
||||
- Trap-protected: a fault inside `__suaveplan_routes` surfaces as `SAND_WASM_BRIDGE.HANDLER_TRAPPED` with `context.phase: "routes"` and a classified `trapKind`.
|
||||
- Malformed-payload aware: bytes that fail Zod validation surface as `SAND_WASM_BRIDGE.UNMARSHAL_FAILED` (re-thrown from `unmarshalRoutes`).
|
||||
- Empty-list tolerant: a guest returning `(0, 0)` is treated as "no routes" rather than as an error, so plugins with lifecycle-only hooks remain valid.
|
||||
- Frees the guest's buffer before returning — the bridge never leaves linear-memory pages owned by the guest's allocator dangling after init.
|
||||
|
||||
## Usage: Basic
|
||||
|
||||
```ts
|
||||
import { discoverRoutes } from "@suaveplan/api-sandbox-wasm-host-bridge/route-discovery";
|
||||
|
||||
const routes = discoverRoutes(exports, "example");
|
||||
```
|
||||
|
||||
## Usage: Advanced
|
||||
|
||||
```ts
|
||||
import { discoverRoutes } from "@suaveplan/api-sandbox-wasm-host-bridge/route-discovery";
|
||||
import type { SerializedRoute } from "@suaveplan/api-types/sandbox-bridge";
|
||||
|
||||
function buildRouteIndex(
|
||||
exports: import("@suaveplan/api-sandbox-wasm-host-bridge/wasm-abi").WasmAbiExports,
|
||||
plugin: string,
|
||||
): ReadonlyMap<string, SerializedRoute> {
|
||||
const routes = discoverRoutes(exports, plugin);
|
||||
const index = new Map<string, SerializedRoute>();
|
||||
for (const route of routes) {
|
||||
index.set(`${route.method} ${route.path}`, route);
|
||||
}
|
||||
return index;
|
||||
}
|
||||
```
|
||||
|
||||
## API Reference
|
||||
|
||||
- `discoverRoutes(exports: WasmAbiExports, pluginName: string): readonly SerializedRoute[]`.
|
||||
|
||||
## Implementation Notes
|
||||
|
||||
The empty-list case (`pointer === 0 || length === 0`) is reached when the guest's `__suaveplan_routes` returns the literal `bigint` `0n`. We still attempt to free the buffer when `pointer !== 0` to be defensive — a guest that returns `(ptr, 0)` may have legitimately allocated a zero-length buffer that the host still owns the responsibility to release. The freeBuffer helper is a no-op when `pointer === 0`, so the double-guard is safe.
|
||||
Reference in New Issue
Block a user