Documentation Index
Fetch the complete documentation index at: https://docs.go.gbgplc.com/llms.txt
Use this file to discover all available pages before exploring further.
Complete reference for every public type, method, and property in the GBGBridge framework.
Module: GBGBridge
Platforms: iOS 15.0+
Swift: 5.9+
Table of contents
Primary entry points
These are the types youโll interact with directly to wire the bridge into your app: a host that routes messages, a SwiftUI view that hosts the WebView, and a configurator for UIKit or custom WebView setups.
BridgeHost
The central coordinator that manages message routing between a WKWebView and your native code.
@MainActor
open class BridgeHost: NSObject, ObservableObject, WKScriptMessageHandler
Why it exists: BridgeHost is the main object you interact with. It decodes incoming messages from the WebView, routes requests to registered handlers, tracks pending requests, and sends responses and events back to the web journey.
Threading: @MainActor โ all access must be from the main thread. This is enforced by the Swift concurrency system. In SwiftUI, use @StateObject or @ObservedObject to hold a reference.
Initializers
BridgeHost offers two initializers. Most apps should use init(hostVersion:), which wires up typed capability slots automatically. Use init(configuration:) only when you need to declare capabilities explicitly via a dictionary.
init(hostVersion:) โ Recommended
public convenience init(hostVersion: String)
Creates a new bridge host with typed capability slots. Capability support is declared by setting handlers on the documentCapture and selfieCapture slots. The CapabilityQueryHandler is registered automatically with a rich provider that builds the response dynamically from typed slots and custom capabilities, including permissionState metadata.
| Parameter | Type | Description |
|---|
hostVersion | String | A version string for the host app (e.g., "1.0.0"). |
Example:
let host = BridgeHost(hostVersion: "1.0.0")
// Declare support by setting handlers
host.documentCapture.handler = { request in
return await host.documentCapture.awaitCompletion()
}
init(configuration:) โ Configuration-Based
public init(configuration: BridgeConfiguration)
Creates a new bridge host with explicit configuration. Capabilities are declared statically in the BridgeConfiguration dictionary. Automatically registers a built-in CapabilityQueryHandler that responds to "capability.query" requests. Typed slots exist but are not wired into the query handler โ use register(handler:) to add capability handlers.
| Parameter | Type | Description |
|---|
configuration | BridgeConfiguration | Declares the host version and supported capabilities. |
Example:
let host = BridgeHost(
configuration: BridgeConfiguration(
hostVersion: "1.0.0",
capabilities: [
"camera.capture": BridgeCapabilityInfo(supported: true, version: "1.0")
]
)
)
Published Properties
These properties are @Published and can be observed in SwiftUI views or via Combine subscribers.
receivedMessages
@Published public var receivedMessages: [BridgeMessage]
An ordered list of all messages received from the web journey (requests, responses, and events). Messages are appended in the order they arrive. Useful for debugging or building a message log UI.
pendingRequests
@Published public var pendingRequests: [BridgeMessage]
Requests from the web journey that have no registered handler. These are waiting for manual response via respond(to:status:data:error:). When a response is sent for a pending request, it is removed from this list.
capabilities
@Published public var capabilities: [String: Bool]
A simplified view of the declared capabilities, mapping capability identifiers to their supported status. Derived from the BridgeConfiguration at initialization.
lastError
@Published public var lastError: String?
The most recent error message, if any. Set when message decoding fails, JavaScript evaluation fails, or the WebView is not attached. Call clearError() to reset.
Typed Capability Slots
documentCapture
public let documentCapture: CaptureCapability
The typed slot for document capture (camera.document). Set handler to declare support. Routes requests for the "camera.document.capture" action.
selfieCapture
public let selfieCapture: CaptureCapability
The typed slot for selfie capture (camera.selfie). Set handler to declare support. Routes requests for the "camera.selfie.capture" action.
Properties
delegate
public weak var delegate: BridgeHostDelegate?
An optional delegate that receives notifications about all incoming messages and unhandled requests. Set this to observe bridge activity without registering handlers.
configuration
public private(set) var configuration: BridgeConfiguration
The configuration passed at initialization. Read-only after creation.
Methods
register(handler:)
public func register(handler: any BridgeCapabilityHandler)
Registers a capability handler. When a request arrives with an action matching the handlerโs action property, the handlerโs handle(request:responder:) method is called.
If a handler is already registered for the same action, it is replaced.
| Parameter | Type | Description |
|---|
handler | any BridgeCapabilityHandler | The handler to register. |
Example:
host.register(handler: DocumentCaptureHandler())
unregister(action:)
public func unregister(action: String)
Removes the handler registered for the given action. Subsequent requests for that action will be added to pendingRequests instead.
| Parameter | Type | Description |
|---|
action | String | The action identifier to unregister. |
registerCustomCapability(_:version:handler:)
public func registerCustomCapability(
_ id: String,
version: String? = nil,
handler: @escaping @Sendable (BridgeMessage, BridgeResponder) async -> Void
)
Registers a custom capability that appears in capability.query responses and handles requests for the given action. Use this for capabilities that donโt have a typed slot (e.g., NFC, biometrics).
If a typed slot is registered for the same action ID, the typed slot takes precedence in both query responses and request routing.
| Parameter | Type | Description |
|---|
id | String | The capability/action identifier (e.g., "nfc.read"). |
version | String? | Optional version string. Defaults to "1.0" in query responses. |
handler | @escaping @Sendable (BridgeMessage, BridgeResponder) async -> Void | The handler closure called when a matching request arrives. |
Example:
host.registerCustomCapability("nfc.read", version: "1.0") { request, responder in
// Handle NFC read request
responder.respond(status: .success, data: ["chipRead": .bool(true)], error: nil)
}
attach(webView:)
public func attach(webView: WKWebView)
Associates a WKWebView with this host. Messages sent via send(event:data:) and respond(to:...) are delivered to this WebView.
You do not need to call this method if you use BridgeWebView or BridgeWebViewConfigurator โ they call it automatically.
| Parameter | Type | Description |
|---|
webView | WKWebView | The WebView to attach. |
The host holds a weak reference to the WebView. If the WebView is deallocated, sending messages will set lastError.
clearError()
Resets lastError to nil.
send(event:data:)
public func send(event action: String, data: [String: JSONValue])
Sends an event message to the web journey. Events are fire-and-forget โ no response is expected.
| Parameter | Type | Description |
|---|
action | String | The event action identifier (e.g., "journey.progress"). |
data | [String: JSONValue] | The event payload data. |
Example:
host.send(event: "host.ready", data: [
"timestamp": .number(Date().timeIntervalSince1970)
])
Error cases: Sets lastError if the WebView is not attached or if JSON encoding fails.
respond(to:status:data:error:)
public func respond(
to correlationId: String,
status: BridgeResponseStatus,
data: [String: JSONValue]? = nil,
error: BridgeErrorPayload? = nil
)
Sends a response to a pending request. The correlationId must match a message in pendingRequests. The matched request is removed from pendingRequests upon sending. The responseโs action is automatically set to the original requestโs action.
| Parameter | Type | Description |
|---|
correlationId | String | The correlation ID of the request being responded to. |
status | BridgeResponseStatus | The response status. |
data | [String: JSONValue]? | Optional response data. |
error | BridgeErrorPayload? | Optional error details (typically set when status is .error). |
Example:
host.respond(
to: request.correlationId,
status: .success,
data: ["imagePath": .string("/tmp/capture.jpg")]
)
respond(to:action:status:data:error:)
public func respond(
to correlationId: String,
action: String,
status: BridgeResponseStatus,
data: [String: JSONValue]? = nil,
error: BridgeErrorPayload? = nil
)
Sends a response with an explicit action. This overload does not look up pendingRequests โ it sends directly. Use this from within a BridgeCapabilityHandler via the BridgeResponder, or when you need to respond to a request that may not be in the pending list.
| Parameter | Type | Description |
|---|
correlationId | String | The correlation ID of the request. |
action | String | The action identifier for the response. |
status | BridgeResponseStatus | The response status. |
data | [String: JSONValue]? | Optional response data. |
error | BridgeErrorPayload? | Optional error details. |
userContentController(_:didReceive:)
public func userContentController(
_ userContentController: WKUserContentController,
didReceive message: WKScriptMessage
)
WKScriptMessageHandler conformance. Called by WebKit when the web journey sends a message via window.webkit.messageHandlers.gbgBridge.postMessage(). You should not call this method directly.
BridgeWebView
A SwiftUI view that displays a web journey inside a bridge-connected WKWebView.
public struct BridgeWebView: UIViewRepresentable
Why it exists: Provides the simplest integration path for SwiftUI apps. Handles WebView creation, configuration, bootstrap script injection, message handler registration, and URL loading.
Initializer
public init(url: URL, host: BridgeHost)
| Parameter | Type | Description |
|---|
url | URL | The URL of the web journey to load. |
host | BridgeHost | The bridge host that manages messaging. |
Example:
BridgeWebView(
url: URL(string: "https://journey.example.com")!,
host: host
)
Properties
url
The journey URL. If this value changes, the WebView navigates to the new URL (unless the normalized URL is unchanged).
host
@ObservedObject public var host: BridgeHost
The bridge host. Observed so that SwiftUI can react to state changes (e.g., lastError, receivedMessages).
Coordinator
public final class Coordinator: NSObject, WKNavigationDelegate
The WebViewโs navigation delegate. Currently provides default behavior. You can subclass BridgeWebView.Coordinator for custom navigation handling.
BridgeWebViewConfigurator
A utility for configuring a WKWebView with the bridge infrastructure. Use this when you need more control than BridgeWebView provides โ for example, in UIKit-based apps or when you need a custom WebView configuration.
public struct BridgeWebViewConfigurator
Why it exists: Separates WebView setup from display. You can configure an existing WebView or create a new one with all bridge wiring in place.
Static Methods
configure(_:host:)
@MainActor
public static func configure(_ webView: WKWebView, host: BridgeHost)
Configures an existing WKWebView with the bridge:
- Injects the bootstrap user script at document start.
- Registers the
BridgeHost as the handler for the "gbgBridge" script message channel.
- Attaches the WebView to the host.
| Parameter | Type | Description |
|---|
webView | WKWebView | The WebView to configure. |
host | BridgeHost | The bridge host. |
Example:
let webView = WKWebView(frame: .zero, configuration: WKWebViewConfiguration())
BridgeWebViewConfigurator.configure(webView, host: host)
makeWebView(host:)
@MainActor
public static func makeWebView(host: BridgeHost) -> WKWebView
Creates and returns a new WKWebView that is fully configured with the bridge. Equivalent to creating a WKWebView and calling configure(_:host:).
| Parameter | Type | Description |
|---|
host | BridgeHost | The bridge host. |
Returns: A configured WKWebView instance.
Capabilities
CaptureCapability
A typed capability slot that represents a capture operation (document or selfie). Setting a handler declares support; the SDK handles routing, result encoding, and busy rejection automatically.
@MainActor
public class CaptureCapability: ObservableObject
Why it exists: Eliminates the need to manually build BridgeCapabilityInfo dictionaries, encode capture results into JSONValue, and keep capability declarations in sync with handler registrations. Setting a handler is the declaration.
Initializer
public init(id: String, actionId: String, version: String? = nil)
You typically donโt create CaptureCapability instances directly โ use the built-in slots on BridgeHost (documentCapture, selfieCapture).
Properties
| Property | Type | Description |
|---|
id | String | The capability identifier (e.g., "camera.document"). |
actionId | String | The bridge action this slot handles (e.g., "camera.document.capture"). |
handler | (@Sendable (BridgeMessage) async -> CaptureResult)? | The handler closure. Setting this declares support. |
isEnabled | Bool | Runtime toggle. When false, the slot reports as unsupported even if a handler is set. Default: true. @Published. |
isSupported | Bool | Computed: handler != nil && isEnabled. |
activeRequest | BridgeMessage? | The currently in-flight request, or nil. @Published. Use this to drive SwiftUI presentation (e.g., fullScreenCover). |
permissionState | PermissionState | The current permission state for this capability. Included in query responses. Default: .notDetermined. |
version | String? | Optional version override. Defaults to "1.0" in query responses when supported. |
Methods
These methods drive capability handling at runtime โ building query responses, awaiting capture completion, and signalling cancellation:
buildCapabilityInfo()
public func buildCapabilityInfo() -> BridgeCapabilityInfo
Returns a BridgeCapabilityInfo reflecting the slotโs current state. Used internally to build capability.query responses.
awaitCompletion()
public func awaitCompletion() async -> CaptureResult
Suspends the current handler until complete(_:) is called. Use this in handlers that drive SwiftUI-presented camera UI rather than imperative capture APIs.
Example:
host.documentCapture.handler = { [weak host] request in
guard let host else { return .cancelled(reason: "Host deallocated") }
return await host.documentCapture.awaitCompletion()
}
complete(_:)
public func complete(_ result: CaptureResult)
Resumes the pending handler with a capture result. Call from view-layer code (e.g., camera callback closures) to complete the flow.
Example:
// In a camera completion handler:
host.documentCapture.complete(.document(DocumentCaptureResult(
imageData: imageData,
width: 1920,
height: 1080
)))
CaptureResult
A strongly-typed result returned by capture handlers.
public enum CaptureResult: Sendable
Why it exists: Eliminates manual JSONValue dictionary construction. The SDK converts CaptureResult values to the bridge protocol format automatically.
| Case | Description |
|---|
.document(DocumentCaptureResult) | Successful document capture with image data and dimensions. |
.selfie(SelfieCaptureResult) | Successful selfie capture with preview image and encrypted blobs. |
.cancelled(reason: String) | User cancelled the operation. Sends a .cancelled response. |
.failed(code: String, message: String, recoverable: Bool) | Operation failed. Sends an .error response with a BridgeErrorPayload. |
DocumentCaptureResult
Result data for a successful document capture.
public struct DocumentCaptureResult: Sendable
Initializer
public init(imageData: Data, width: Int, height: Int, mimeType: String = "image/png")
| Parameter | Type | Default | Description |
|---|
imageData | Data | โ | The captured image data. Base64-encoded in the bridge response. |
width | Int | โ | Image width in pixels. |
height | Int | โ | Image height in pixels. |
mimeType | String | "image/png" | The MIME type of the image data. |
Bridge response data:
{
"imageBase64": "<base64-encoded image>",
"imageWidth": 1920,
"imageHeight": 1080,
"mimeType": "image/png"
}
SelfieCaptureResult
Result data for a successful selfie capture.
public struct SelfieCaptureResult: Sendable
Initializer
public init(
previewImageData: Data,
width: Int,
height: Int,
mimeType: String = "image/jpeg",
encryptedBlob: Data,
unencryptedBlob: Data
)
| Parameter | Type | Default | Description |
|---|
previewImageData | Data | โ | Preview image data. Base64-encoded in the bridge response. |
width | Int | โ | Image width in pixels. |
height | Int | โ | Image height in pixels. |
mimeType | String | "image/jpeg" | The MIME type of the preview image. |
encryptedBlob | Data | โ | Encrypted biometric data blob. Base64-encoded in the bridge response. |
unencryptedBlob | Data | โ | Unencrypted biometric data blob. Base64-encoded in the bridge response. |
Bridge response data:
{
"imageBase64": "<base64>",
"imageWidth": 640,
"imageHeight": 480,
"mimeType": "image/jpeg",
"encryptedBlobBase64": "<base64>",
"unencryptedBlobBase64": "<base64>"
}
PermissionState
The current authorization status for a native capability.
public enum PermissionState: String, Codable, Sendable
| Case | Raw Value | Description |
|---|
.granted | "granted" | Permission has been granted. |
.denied | "denied" | Permission has been explicitly denied. |
.notDetermined | "notDetermined" | Permission has not been requested yet. |
.restricted | "restricted" | Permission is restricted by device management. |
.notApplicable | "notApplicable" | Permission is not applicable for this capability. |
CameraDetector
A utility for detecting camera hardware availability and permission status.
public struct CameraDetector
Why it exists: Provides a simple way to populate permissionState on capture slots without writing AVFoundation boilerplate.
Static Methods
check()
public static func check() -> CameraDetector.Result
Checks camera hardware availability using AVCaptureDevice.default(for: .video) and permission status using AVCaptureDevice.authorizationStatus(for: .video).
Returns: A CameraDetector.Result with hardware and permission info.
CameraDetector.Result
public struct Result: Sendable {
public let hardwareAvailable: Bool
public let permissionState: PermissionState
}
| Property | Type | Description |
|---|
hardwareAvailable | Bool | Whether camera hardware was detected. false on Simulator. |
permissionState | PermissionState | Maps from AVAuthorizationStatus to PermissionState. |
Example:
let camera = CameraDetector.check()
host.documentCapture.permissionState = camera.permissionState
host.selfieCapture.permissionState = camera.permissionState
Configuration
BridgeConfiguration
Declares the host applicationโs version and supported capabilities.
public struct BridgeConfiguration: Sendable
Why it exists: Provides a single configuration object that BridgeHost uses to initialize capability state and respond to capability queries from the web journey.
Initializer
public init(
hostVersion: String,
capabilities: [String: BridgeCapabilityInfo],
bootstrapScript: String? = nil
)
| Parameter | Type | Default | Description |
|---|
hostVersion | String | โ | A version string for the host app (e.g., "1.0.0"). Reported to the web journey via capability queries. |
capabilities | [String: BridgeCapabilityInfo] | โ | A dictionary mapping capability identifiers to their support status and metadata. |
bootstrapScript | String? | nil | Optional custom JavaScript to inject at document start. If nil, a default script is used. |
Properties
| Property | Type | Description |
|---|
hostVersion | String | The host app version string. |
capabilities | [String: BridgeCapabilityInfo] | Capability declarations. |
bootstrapScript | String? | Custom bootstrap JavaScript, or nil for the default. |
BridgeCapabilityInfo
Metadata about a single capability.
public struct BridgeCapabilityInfo: Codable, Sendable
Why it exists: Allows the host to express not just whether a capability is supported, but also its version and any constraints (e.g., maximum resolution, supported document types).
Initializer
public init(
supported: Bool,
version: String? = nil,
constraints: [String: JSONValue]? = nil,
permissionState: String? = nil
)
| Parameter | Type | Default | Description |
|---|
supported | Bool | โ | Whether the capability is available. |
version | String? | nil | The capability implementation version. |
constraints | [String: JSONValue]? | nil | Arbitrary key-value constraints (e.g., "maxResolution": .number(4096)). |
permissionState | String? | nil | The native permission status (e.g., "granted", "denied"). Included in capability query responses when non-nil. |
Properties
| Property | Type | Description |
|---|
supported | Bool | Whether the capability is available. |
version | String? | Implementation version, if any. |
constraints | [String: JSONValue]? | Arbitrary constraints. |
permissionState | String? | Native permission status. Included in query responses when non-nil. |
Message models
Every value that crosses the bridge is wrapped in a BridgeMessage envelope, which carries a typed payload, a correlation ID, and a status. The types in this section describe that envelope and the shapes youโll embed inside it.
BridgeMessage
A structured envelope for all bridge communication.
public struct BridgeMessage: Codable, Identifiable, Sendable
Why it exists: Provides a consistent, type-safe format for all messages exchanged between the web journey and the native host. The Identifiable conformance enables use in SwiftUI lists.
Initializer
public init(
version: String,
correlationId: String,
type: BridgeMessageType,
timestamp: TimeInterval,
payload: BridgePayload
)
| Parameter | Type | Description |
|---|
version | String | Protocol version (currently "1.0"). |
correlationId | String | Unique identifier for request-response correlation. |
type | BridgeMessageType | Message type: .request, .response, or .event. |
timestamp | TimeInterval | Milliseconds since Unix epoch. |
payload | BridgePayload | The message payload. |
Properties
| Property | Type | Description |
|---|
version | String | Protocol version. |
correlationId | String | Correlation identifier. |
type | BridgeMessageType | Message type. |
timestamp | TimeInterval | Timestamp in milliseconds. |
payload | BridgePayload | Message payload. |
id | String | Computed. Format: "{correlationId}-{timestamp}-{type}". |
BridgePayload
The payload carried within a BridgeMessage.
public struct BridgePayload: Codable, Sendable
Initializer
public init(
action: String,
data: [String: JSONValue]?,
status: BridgeResponseStatus?,
error: BridgeErrorPayload?
)
| Parameter | Type | Description |
|---|
action | String | The action identifier (e.g., "camera.capture", "capability.query"). |
data | [String: JSONValue]? | Arbitrary typed JSON data. |
status | BridgeResponseStatus? | Response status (only present in response messages). |
error | BridgeErrorPayload? | Error details (only present when status is .error). |
Properties
| Property | Type | Description |
|---|
action | String | Action identifier. |
data | [String: JSONValue]? | Payload data. |
status | BridgeResponseStatus? | Response status. |
error | BridgeErrorPayload? | Error details. |
BridgeErrorPayload
Structured error information included in error responses.
public struct BridgeErrorPayload: Codable, Sendable
Why it exists: Provides machine-readable error codes alongside human-readable messages, plus a recoverable flag that tells the web journey whether it should retry or fail.
Initializer
public init(code: String, message: String, recoverable: Bool)
| Parameter | Type | Description |
|---|
code | String | A machine-readable error code (e.g., "CAMERA_DENIED", "NFC_UNAVAILABLE"). |
message | String | A human-readable error description. |
recoverable | Bool | Whether the error is recoverable (e.g., user can retry). |
Properties
| Property | Type | Description |
|---|
code | String | Error code. |
message | String | Error description. |
recoverable | Bool | Whether recovery is possible. |
BridgeMessageType
The type of a bridge message.
public enum BridgeMessageType: String, Codable, Sendable
| Case | Raw Value | Description |
|---|
.request | "request" | A request from the web journey to the native host. |
.response | "response" | A response from the native host to the web journey. |
.event | "event" | An asynchronous notification (either direction). |
BridgeResponseStatus
The status of a response message.
public enum BridgeResponseStatus: String, Codable, Sendable
| Case | Raw Value | When to use |
|---|
.success | "success" | The operation completed successfully. |
.error | "error" | The operation failed. Include a BridgeErrorPayload. |
.cancelled | "cancelled" | The user cancelled the operation. |
.unsupported | "unsupported" | The requested capability is not available. |
.acknowledged | "acknowledged" | The request was received; result will follow. |
JSONValue
A type-safe representation of arbitrary JSON values.
public enum JSONValue: Codable, Sendable
Why it exists: Swiftโs type system doesnโt natively represent heterogeneous JSON. JSONValue provides a recursive enum that maps directly to JSON types, enabling type-safe construction and pattern matching of arbitrary payloads.
| Case | Associated Value | JSON Equivalent |
|---|
.string(String) | A string value | "hello" |
.number(Double) | A numeric value | 42, 3.14 |
.bool(Bool) | A boolean value | true, false |
.object([String: JSONValue]) | A dictionary | { "key": "value" } |
.array([JSONValue]) | An array | [1, 2, 3] |
.null | No associated value | null |
Properties
anyValue
Converts the JSONValue to its Foundation equivalent (String, Double, Bool, [String: Any], [Any], or NSNull). Useful for interoperating with APIs that expect Any.
JSONValue automatically decodes from and encodes to standard JSON. The decoding order is: null โ bool โ number โ string โ object โ array.
Example โ constructing a payload:
let data: [String: JSONValue] = [
"name": .string("John Doe"),
"age": .number(30),
"verified": .bool(true),
"documents": .array([
.object(["type": .string("passport"), "number": .string("AB123456")])
]),
"metadata": .null
]
Protocols
BridgeCapabilityHandler
The interface for objects that handle specific bridge request actions.
public protocol BridgeCapabilityHandler: AnyObject, Sendable
Why it exists: Defines the contract for capability implementations. Each handler is responsible for a single action and receives a responder to send its result back to the web journey.
Requirements
action
var action: String { get }
The action identifier this handler responds to (e.g., "camera.document.capture", "nfc.read"). Must be unique per BridgeHost โ registering a handler with the same action replaces the previous one.
handle(request:responder:)
func handle(request: BridgeMessage, responder: BridgeResponder) async
Called when a request arrives with a matching action. Perform your native operation and call responder.respond(...) when done.
| Parameter | Type | Description |
|---|
request | BridgeMessage | The incoming request message. Access request.payload.data for request parameters. |
responder | BridgeResponder | A callback to send the response. Call exactly once. |
Threading: This method is async and runs in a Task dispatched by BridgeHost. You can safely await async operations, present UI (from the main actor), and perform background work.
Example:
public final class DocumentCaptureHandler: BridgeCapabilityHandler, @unchecked Sendable {
public let action = "camera.document.capture"
public func handle(request: BridgeMessage, responder: BridgeResponder) async {
// Extract parameters from the request
let side = request.payload.data?["side"] // .string("front") or .string("back")
// Perform capture (your implementation)
do {
let imageData = try await captureDocument()
responder.respond(
status: .success,
data: ["imageBase64": .string(imageData.base64EncodedString())],
error: nil
)
} catch {
responder.respond(
status: .error,
data: nil,
error: BridgeErrorPayload(
code: "CAPTURE_FAILED",
message: error.localizedDescription,
recoverable: true
)
)
}
}
}
BridgeResponder
A callback interface used to send a response from a capability handler back to the web journey.
public protocol BridgeResponder: Sendable
Why it exists: Decouples the handler from BridgeHost internals. Handlers donโt need to know about WebViews or JavaScript evaluation โ they simply call respond().
Requirements
respond(status:data:error:)
func respond(
status: BridgeResponseStatus,
data: [String: JSONValue]?,
error: BridgeErrorPayload?
)
Sends a response to the web journey for the associated request.
| Parameter | Type | Description |
|---|
status | BridgeResponseStatus | The response status. |
data | [String: JSONValue]? | Optional response payload. |
error | BridgeErrorPayload? | Optional error details. |
Threading: Safe to call from any thread. The internal implementation dispatches to the main actor.
Call this method exactly once per request. Calling it multiple times has no effect (the first call wins for request correlation).
BridgeHostDelegate
An observer protocol for monitoring bridge activity.
@MainActor
public protocol BridgeHostDelegate: AnyObject
Why it exists: Provides a way to observe all bridge messages and react to unhandled requests without registering a handler. Useful for logging, analytics, or building custom request handling logic.
Methods
bridgeHost(_:didReceive:)
func bridgeHost(_ host: BridgeHost, didReceive message: BridgeMessage)
Called for every message received from the web journey, regardless of type. Default implementation does nothing.
| Parameter | Type | Description |
|---|
host | BridgeHost | The bridge host that received the message. |
message | BridgeMessage | The received message. |
bridgeHost(_:unhandledRequest:)
func bridgeHost(_ host: BridgeHost, unhandledRequest message: BridgeMessage)
Called when a request arrives with no registered handler. The request is also added to host.pendingRequests. Default implementation does nothing.
| Parameter | Type | Description |
|---|
host | BridgeHost | The bridge host. |
message | BridgeMessage | The unhandled request. |
Built-in handlers
CapabilityQueryHandler
A built-in handler that responds to "capability.query" requests with the hostโs declared capabilities.
public final class CapabilityQueryHandler: BridgeCapabilityHandler, @unchecked Sendable
Why it exists: Capability negotiation is fundamental to the bridge protocol. This handler is automatically registered by BridgeHost so the web journey can always discover available capabilities.
Action: "capability.query"
Initializers
Simple Provider
public init(
capabilities: @escaping () -> [String: Bool],
hostVersion: String
)
Creates a query handler with a simple boolean capability map. Used by init(configuration:).
| Parameter | Type | Description |
|---|
capabilities | @escaping () -> [String: Bool] | A closure that returns the current capability map. Called on each query. |
hostVersion | String | The host version string to include in the response. |
Rich Provider
public init(
richCapabilities: @escaping () -> [String: BridgeCapabilityInfo],
hostVersion: String
)
Creates a query handler with full capability metadata including permissionState. Used by init(hostVersion:).
| Parameter | Type | Description |
|---|
richCapabilities | @escaping () -> [String: BridgeCapabilityInfo] | A closure that returns rich capability info. Called on each query. |
hostVersion | String | The host version string to include in the response. |
You rarely need to create either initializer directly. BridgeHost creates and registers the appropriate one automatically.
When the web journey sends a capability.query request, the response data contains:
{
"environment": "ios",
"hostVersion": "1.0.0",
"capabilities": {
"camera.document": {
"supported": true,
"version": "1.0",
"permissionState": "granted"
},
"camera.selfie": {
"supported": false,
"version": null
}
}
}
| Field | Type | Description |
|---|
environment | String | Always "ios" for this framework. |
hostVersion | String | The host version from configuration. |
capabilities | Object | Map of capability ID โ { supported, version, permissionState? }. |
capabilities[id].permissionState | String? | Present when the capability provides permission metadata (rich provider only). |