import { createContext, useCallback, useContext, useMemo, type ReactNode } from "react"; import type { ZodType, input as ZodInput, output as ZodOutput } from "zod"; import { callPluginRpc, type PluginRpcContract } from "../rpc.js"; export interface PluginRpcContextValue { invoke(method: string, input: unknown): Promise; } const PluginRpcContext = createContext(null); export function usePluginRpcContextValue(): PluginRpcContextValue | null { return useContext(PluginRpcContext); } export function PluginRpcProvider({ children, invoke, }: { children: ReactNode; invoke(method: string, input: unknown): Promise; }) { const value = useMemo(() => ({ invoke }), [invoke]); return {children}; } export function useRpc( contract: PluginRpcContract, ): (input: ZodInput) => Promise> { const context = usePluginRpcContextValue(); if (!context) throw new Error("useRpc must run inside a contributed plugin surface"); return useCallback( (input: ZodInput) => callPluginRpc(contract, context.invoke, input), [context, contract], ); }