/** * The ONE provider a code-land app mounts (blueprint §5.4). * * It carries everything the guarded hooks need and nothing else: which app * this is, where its wire lives, the keyed `$state` store, and the set of * mounted queries a successful action refreshes (§6.3 law 2). One provider, * one context — not one per hook. * * WHERE THE ADDRESS COMES FROM. A box-served app is served BY the wire, at * `/apps//serve/` (vendo/src/wire/box.ts servedProxyRoutes, * vendo/src/server.ts servedProxyPath). So the app's own URL already carries * both halves, and both are derived from it — no global, no build-time * injection, and it survives a host that mounts the wire under a base path * (Next.js `basePath`, the demos' `withBasePath`). The props are the escape * hatch for the interim (a dev server, the box's own `VENDO_HOST_URL`), and * an explicit prop always wins. */ import type { Json, ToolOutcome } from "../../core/index.js"; import { type KeyedState } from "./state.js"; import { type ReactNode } from "react"; /** What a mounted `useToolQuery` registers so an action can refresh it. */ export type QueryRefetch = () => Promise; /** The value every hook in this package reads. */ export interface VendoAppContextValue { /** The app whose guarded door the hooks call. Empty when it could not be * determined — the hooks then report an unavailable read instead of * guessing an id. */ appId: string; /** The wire's base, e.g. `/api/vendo`. Relative and same-origin by default, * so every call rides the viewer's own session. */ baseUrl: string; /** * THE ONE DOOR: `POST /apps/:appId/call`, through the same * `createVendoClient` the host's own chrome calls it with. Total — a * transport failure, a wire error envelope and a missing app id all arrive * as a contained `error` outcome, never a throw. */ call(ref: string, args: Json): Promise; /** The keyed `$state` namespace for this app instance. */ state: KeyedState; setState(key: string, value: Json): void; /** Called by `useToolQuery` on mount; returns its unregister. */ registerQuery(refetch: QueryRefetch): () => void; /** Re-run every mounted query. What a successful action triggers. */ refetchQueries(): Promise; /** * Say ONCE, per distinct miss, that a read resolved no data. * A binding that renders empty because a call was refused looks exactly like * one that renders empty because there is nothing to show; that silence cost * a live triage, so it stops being invisible here too. */ reportQueryMiss(key: string, message: string): void; } /** `/api/vendo/apps/app_1/serve/index.html` → `{ baseUrl, appId }`. */ export declare function appAddressFromPath(pathname: string): { baseUrl: string; appId: string; } | undefined; export interface VendoAppProviderProps { /** Overrides the id derived from the served URL. */ appId?: string; /** Overrides the wire base derived from the served URL, e.g. `/api/vendo` * or an absolute `http://localhost:3000/api/vendo` for a dev server. */ baseUrl?: string; children?: ReactNode; } /** The one provider. A generated app's entry point mounts this at its root. */ export declare function VendoAppProvider({ appId, baseUrl, children }: VendoAppProviderProps): import("react").JSX.Element; /** The context, for a component that needs the address or the whole store. */ export declare function useVendoApp(): VendoAppContextValue;