Web SDK
TypeScript
The full type surface of @today/webview-bridge.
@today/webview-bridge ships its own types. The complete public surface:
// ── Client ────────────────────────────────────────────────────────────────
export interface WebViewBridgeOptions {
/** Override the global lookup name. Defaults to "todayWebViewBridge". */
channelName?: string
/** Inject a channel directly, bypassing the window lookup (tests / custom transports). */
channel?: NativeChannel
}
export interface WebViewBridge {
isAvailable(): boolean
readonly platform: Platform
track(event: string, properties?: TrackProperties): void
getHeaders(): Promise<Record<string, string>>
refreshToken(): Promise<RefreshTokenResult>
// Host mints the session cookie itself; the bearer is never returned to JS.
// Resolves false with no host, an unsupported host, or a failed mint.
establishSession(options?: { refresh?: boolean }): Promise<boolean>
fetch(input: RequestInfo | URL, init?: RequestInit): Promise<Response>
}
export function createWebViewBridge(options?: WebViewBridgeOptions): WebViewBridge
// ── Values ──────────────────────────────────────────────────────────────────
export type Platform = 'ios' | 'android' | 'macos' | 'windows' | 'web'
export type TrackProperties = Record<string, string | number | boolean>
export interface RefreshTokenResult {
authorization: string // ready-to-use header value, e.g. "Bearer <token>"
}
// ── Errors ────────────────────────────────────────────────────────────────
export class BridgeError extends Error {}
export class BridgeUnavailableError extends BridgeError {} // no native host
export class BridgeProtocolError extends BridgeError {} // host replied with a malformed payloadThe raw channel (advanced)
You normally never touch the channel directly — the client wraps it. If you are
writing the native shim or a test double, this is the shape the SDK expects to
find on window:
interface NativeChannel {
// The known BridgeMessage members, or any `{ type: string }`. An unrecognised
// `type` resolves to `undefined` (never rejects), which is what keeps
// capability rollout additive and forward-compatible.
postMessage(message: BridgeMessage | { type: string }): Promise<unknown>
}
// The wire payload field names stay `ename` / `parameters` for the analytics
// pipeline; the public `track(event, properties)` maps onto them.
type BridgeMessage =
| { type: 'track'; ename: string; parameters?: TrackProperties }
| { type: 'headers' }
| { type: 'refreshToken' }
| { type: 'establishSession'; refresh?: boolean }
declare global {
interface Window {
// iOS — WKScriptMessageHandlerWithReply
webkit?: {
messageHandlers?: {
todayWebViewBridge?: NativeChannel
}
}
// Android — injected shim object
todayWebViewBridge?: NativeChannel
// Host-injected synchronous platform tag (authoritative for iOS vs macOS)
__todayWebView?: { platform?: Platform }
}
}
export {}Both transports expose the same postMessage(message): Promise shape. That
uniformity is the whole point of the channel design — see the
Message envelope and
Native Reference.