Marker contract hooks
When you author a contract with the marker API, defineContract returns a
ContractHook — a callable, Zustand-style hook that is also a BridgeContract. It is
the most ergonomic way to consume a contract.
export const useDemoHost = defineContract('bridgekit.demo-host', { methods: { ping: Async<{ message: string }, { reply: string; epoch: number }>(), increment: Async<number>(), say: Void<{ text: string }>() }, streams: { ticker: Stream<number>(), echoes: Stream<string>() }, state: { counter: State<number>(0) },});Calling the hook
Section titled “Calling the hook”// Full snapshot — methods, stream accessors, and a `state` map:const { ping, increment, say, ticker, echoes, state } = useDemoHost();
// Selector form (subscribe to a slice):const counterHandle = useDemoHost((c) => c.state.counter);The derived consumer merges three things:
- method signatures —
ping,increment,say(typed from the markers), - stream accessors —
ticker(),echoes()returning subscribable streams, - a
statemap — each entry is aStateHandle<V>.
StateHandle<V>
Section titled “StateHandle<V>”interface StateHandle<V> { get(): V; // imperative, synchronous, local subscribe(cb: (v: V) => void): () => void; // returns an unsubscribe}const counter = state.counter; // StateHandle<number>const now = counter.get(); // synchronous readconst off = counter.subscribe(setCount);// subscribe, returns unsubscribeThe full hook surface
Section titled “The full hook surface”interface ContractHook<T> { (): DerivedConsumer<T>; // no-arg snapshot <U>(selector: (c: DerivedConsumer<T>) => U): U; // selector getState(): DerivedConsumer<T>; // imperative, non-React scoped(scope): ContractHook<T>; // bind a scope useProvide(impl: Partial<DerivedConsumer<T>>): void; // provide from JS readonly id: string; readonly hash: string; readonly descriptor: MarkerContractDescriptor;}getState() — outside React
Section titled “getState() — outside React”const { ping } = useDemoHost.getState();const { reply } = await ping({ message: 'hi' });scoped(scope) — a scoped variant
Section titled “scoped(scope) — a scoped variant”const featureHost = useDemoHost.scoped({ kind: 'feature', feature: 'demo' });const { counter } = featureHost().state;useProvide(impl) — provide from JS
Section titled “useProvide(impl) — provide from JS”The reverse-direction provider, expressed on the same hook:
useDemoReverse.useProvide({ greetFromJs: ({ name }) => Promise.resolve(`Hi ${name}`), onNativeEvent: ({ type }) => { log(type); },});