createNativeBridge
Creates a typed JavaScript bridge for WebKit message handlers. It can send fire-and-forget commands with call(), send typed request messages with request(), and resolve native responses through DOM events.
Each request gets a generated request ID and is stored until native code responds, the timeout expires, or the bridge is disposed. Instead of throwing for request failures, request() resolves to a discriminated BridgeResponse, so callers can handle success and failure with an explicit response.ok branch.
Importing
import { createNativeBridge } from '@almighty-shogun/webkit-native-bridge'Usage
The TypeScript side defines the bridge contract and sends requests through the configured WebKit message handler. The C++ side receives those messages, handles the native work, and dispatches a response event with the same request ID.
import { createNativeBridge } from '@almighty-shogun/webkit-native-bridge'
type Requests = {
getUser: {
body: { id: string }
response: { id: string; name: string }
errorCode: 'USER_NOT_FOUND'
errorDetails: { id: string }
}
ping: {
body: void
response: 'pong'
}
}
type Commands = 'close' | 'openSettings';
const bridge = createNativeBridge<Requests, Commands>({
handlerName: 'nativeBridge',
requestTimeout: 15000
});
bridge.call('openSettings');
const response = await bridge.request('getUser', { id: '1' });
if (response.ok) {
console.log(response.data.name);
} else {
console.error(response.error.code, response.message);
}
const ping = await bridge.request('ping');
bridge.dispose();// Sketch of the native-side flow. Exact WebKit APIs differ per platform.
void handleScriptMessage(const std::string& message) {
// request:<requestId>|getUser|{"id":"1"}
auto requestId = parseRequestId(message);
auto method = parseMethod(message);
if (method == "getUser") {
dispatchBridgeResponse(requestId, true, R"({"id":"1","name":"Ada"})");
return;
}
dispatchBridgeError(requestId, "UNKNOWN_METHOD", "Unsupported native method");
}
void dispatchBridgeResponse(
const std::string& requestId,
bool ok,
const std::string& payloadJson
) {
std::string script =
"window.dispatchEvent(new CustomEvent('webkit-native-bridge', {"
"detail: { requestId: '" + requestId + "', ok: true, payload: " + payloadJson + ", error: null }"
"}))";
webView.evaluateJavaScript(script);
}Parameters
options.eventName?: string
DOM event name used for native responses.
Default: webkit-native-bridge
options.handlerName?: string
WebKit message handler name under window.webkit.messageHandlers.
Default: nativeBridge
options.requestTimeout?: number | null
Request timeout in milliseconds. Use null to disable request timeouts.
Default: 30000
options.window?: NativeBridgeWindow
Window-like object. Useful for tests or custom runtimes.
Returns
call(method: TCommands): void
Sends a fire-and-forget command string to native code.
request(method, body, options): Promise<BridgeResponse>
Sends a typed request and resolves to a BridgeResponse.
postMessage(message: string): void
Sends a raw message through the configured WebKit handler.
handleResponse(detail: NativeResponseEventDetail): void
Manually resolves a pending request from a native response detail.
isAvailable(): boolean
Returns whether the configured WebKit message handler exists.
dispose(): void
Removes the response listener and resolves pending requests as disposed failures.
Type signature
declare function createNativeBridge<
TRequests extends NativeBridgeRequestMap = Record<never, never>,
TCommands extends string = never
>(options?: NativeBridgeOptions): NativeBridge<TRequests, TCommands>;