Anatomy of generated Swift
Each contract produces a single <PascalName>Contract.swift. Here is the real output for the
example.host contract, dissected piece by piece.
1. Header & imports
Section titled “1. Header & imports”// Generated by bridgekit. DO NOT EDIT.// Contract hash: 8e552bd7import BridgeKitThe contract hash is embedded in the header. The only import is BridgeKit (the runtime
module). Generated files never import NitroModules or any app-specific module.
2. Object types
Section titled “2. Object types”public struct GetCountryAndLanguageResult { public var country: String public var language: String public init(country: String, language: String) { self.country = country self.language = language }}
public struct GetLiteralParams { public var key: String public init(key: String) { self.key = key }}
public struct TrackEventParams { public var eventName: String public init(eventName: String) { self.eventName = eventName }}
public struct OpenUrlParams { public var url: String public init(url: String) { self.url = url }}Object schemas become public struct with stored properties and a memberwise public init.
Discriminated unions become Swift enum with associated values. Literal unions become
enum with a raw String value.
3. Provider protocol (the side that implements)
Section titled “3. Provider protocol (the side that implements)”public protocol ExampleHost: AnyObject { func getCountryAndLanguage() throws -> GetCountryAndLanguageResult func getLiteral(_ params: GetLiteralParams) throws -> String func getAppVersion() throws -> String func trackEvent(_ params: TrackEventParams) func openUrl(_ params: OpenUrlParams)}This is the protocol your implementation class conforms to. The method shapes follow the contract kind:
| Contract kind | Generated Swift signature |
|---|---|
fire | func m(_ params: P?) |
query | func m(_ params: P?) async throws -> R |
querySync | func m(_ params: P?) throws -> R |
stream | func m(_ params: P?) -> AsyncStream<T> |
state (provider) | var m: AsyncStream<T> { get } |
AnyObject is required by the Nitro layer. throw on sync specs surfaces errors back to
the caller rather than crashing.
4. Client protocol (the side that consumes)
Section titled “4. Client protocol (the side that consumes)”public protocol ExampleHostClient: AnyObject { func getCountryAndLanguage() throws -> GetCountryAndLanguageResult func getLiteral(_ params: GetLiteralParams) throws -> String func getAppVersion() throws -> String func trackEvent(_ params: TrackEventParams) func openUrl(_ params: OpenUrlParams)}For state members the client protocol wraps availability:
// state example — not in example.host but shown for completeness:// provider: var connectivity: AsyncStream<Connectivity> { get }// client: var connectivity: AsyncStream<BridgeValue<Connectivity>> { get }Clients see AsyncStream<BridgeValue<T>> — availability is part of the value
(Available / Initial / Replacing / Unprovided). See Using BridgeKit from
Swift for how to iterate these streams.
5. The contract object
Section titled “5. The contract object”class ExampleHostContract: BridgeContractDefinition<any ExampleHost, any ExampleHostClient> { override var id: String { "example.host" } override var contractHash: String { "8e552bd7" } override var memberHashes: [String: String] { [ "methods.getAppVersion": "71ff3fa0", "methods.getCountryAndLanguage": "27aee930", "methods.getLiteral": "494175a7", "methods.openUrl": "fb545690", "methods.trackEvent": "99cf4370", ] }
override func inbound(_ impl: any ExampleHost) -> InboundContractAdapter { ExampleHostInboundAdapter(impl: impl) }
override func outbound(_ caller: OutboundCaller) -> any ExampleHostClient { ExampleHostOutboundProxy(caller: caller) }}BridgeContractDefinition<P, C> is the open generic base class for all generated contract
objects. The type parameters are protocol existentials (any ExampleHost, any ExampleHostClient)
because Swift protocol existentials do not satisfy AnyObject generic constraints directly.
Two halves, mirror images:
inbound(_:)routes engine calls into your typed provider (used when this platform provides the contract to JS).outbound(_:)builds the typed proxy backed byOutboundCaller(used when this platform consumes a JS-provided contract).
Type mapping
Section titled “Type mapping”DSL (t.*) | Swift |
|---|---|
t.string() | String |
t.number() | Double |
t.boolean() | Bool |
t.int64() | Int64 |
t.date() | Date |
t.binary() | Data |
t.object({…}) | public struct |
t.optional(T) | T? |
t.array(T) | [T] |
t.record(T) | [String: T] |
t.stream(T) | AsyncStream<T> |
t.state(T, init) | provider: AsyncStream<T>, client: AsyncStream<BridgeValue<T>> |
t.literals([…]) | enum with String raw value |
t.enum([…]) | enum with Int raw value |
t.union(…) | enum with associated values |
What you commit
Section titled “What you commit”The .swift file bridgekit generate --platform swift writes is the final artifact — there
is no post-processing step. Commit it and add it to your Xcode target’s Compile Sources;
Xcode does not glob a directory.
Declarations carry no explicit access modifier, so they are internal to whichever target
compiles them. That is deliberate: the generated code is part of your app, not a module you
link against, which is why your own Swift only ever imports BridgeKit. See
Installation for the target settings this requires.