@kookapp/web-bridge
v0.0.6
Published
PostMessage-based bridge for iframe communication
Downloads
568
Keywords
Readme
WebBridge
A PostMessage-based bridge for iframe communication, providing symmetric callHandler and registerHandler APIs similar to jsbridge but for web environments.
Features
- Symmetric API: Both parent and iframe can call handlers and register responders
- PostMessage-based: Uses native Web APIs for cross-origin communication
- Origin Validation: Strict domain whitelist verification
- Type-Safe: Full TypeScript support with comprehensive type definitions
- Promise & Callback: Supports both async/await and callback patterns
- No Exceptions: Errors returned via result values, never throws exceptions (like globalBridge)
- Error Handling: Comprehensive error reporting through return values
Installation
npm install @kookapp/web-bridgeUsage
Parent Side (iframe外部)
import { ParentBridge } from '@kookapp/web-bridge'
// Initialize the bridge
const bridge = new ParentBridge({
allowedOrigins: ['https://iframe.example.com']
})
// Register a handler that can be called from iframe
bridge.registerHandler('getUserInfo', (data, callback) => {
const userInfo = { id: 1, name: 'John' }
callback(userInfo)
})
// Create a communication channel with an iframe
const iframeElement = document.getElementById('myIframe') as HTMLIFrameElement
const channel = bridge.createChannel(iframeElement)
// Call a handler inside iframe (using callback)
channel.callHandler('getIframeData', { type: 'user' }, (result) => {
if (result.error) {
console.error('Error:', result.error)
} else {
console.log('Result:', result)
}
})
// Or using async/await (without callback)
const result = await channel.callHandler('getIframeData', { type: 'user' })
if (result.error) {
console.error('Error:', result.error)
} else {
console.log('Result:', result)
}
// Clean up
// bridge.destroy()Child Side (iframe内部)
import { ChildBridge } from '@kookapp/web-bridge'
// Initialize the bridge
const bridge = new ChildBridge({
allowedOrigins: ['https://parent.example.com']
})
// Register a handler that can be called from parent
bridge.registerHandler('getIframeData', (data, callback) => {
const response = { data: 'from iframe', type: data.type }
callback(response)
})
// Call a handler on parent (using callback)
bridge.callHandler('getUserInfo', {}, (userInfo) => {
if (userInfo.error) {
console.error('Error:', userInfo.error)
} else {
console.log('User:', userInfo)
}
})
// Or using async/await
const userInfo = await bridge.callHandler('getUserInfo', {})
if (userInfo.error) {
console.error('Error:', userInfo.error)
} else {
console.log('User:', userInfo)
}API Reference
ParentBridge
class ParentBridge {
constructor(config: BridgeConfig)
registerHandler(handlerName: string, handler: Handler): void
createChannel(iframe: HTMLIFrameElement, options?: { origin: string }): IframeChannel
unregisterHandler(handlerName: string): void
destroy(): void
}IframeChannel
interface IframeChannel {
callHandler(handlerName: string, data?: any, callback?: (result: any) => void): Promise<any>
getIframe(): HTMLIFrameElement
isConnected(): boolean
destroy(): void
}ChildBridge
class ChildBridge {
constructor(config: BridgeConfig)
callHandler(handlerName: string, data?: any, callback?: (result: any) => void): Promise<any>
registerHandler(handlerName: string, handler: Handler): void
unregisterHandler(handlerName: string): void
destroy(): void
isConnected(): boolean
}BridgeConfig
interface BridgeConfig {
allowedOrigins: string[] // Domain whitelist (supports exact match, regex, and wildcard)
timeout?: number // Message timeout in ms (default: 5000)
debug?: boolean // Enable debug logging
maxRetries?: number // Maximum retry attempts (default: 0)
}Error Handling
WebBridge never throws exceptions - all errors are returned through the result value, keeping behavior consistent with globalBridge.
All errors are returned as objects with an error property:
// Using callback
bridge.callHandler('someHandler', {}, (result) => {
if (result.error) {
// Handle error cases:
// - Handler not found
// - Request timeout
// - Invalid message
// - Connection issues
console.error('Error:', result.error)
} else {
console.log('Success:', result)
}
})
// Using Promise (never rejects!)
const result = await bridge.callHandler('someHandler', {})
if (result.error) {
console.error('Error:', result.error)
} else {
console.log('Success:', result)
}Common error types:
- Handler not found:
{ error: 'Handler "handlerName" not found' } - Timeout:
{ error: 'Timeout: no response after 5000ms' } - Connection issues:
{ error: 'iframe contentWindow is not available' }
See ERROR_HANDLING.md for complete documentation.
Security
Origin Validation
- Exact match:
'https://example.com' - Regex pattern:
'^https://.*\\.example\\.com$' - Wildcard (dev only):
'*'
Origins are validated for both incoming and outgoing messages.
License
MIT
