Kotlin: provide & consume
The Kotlin API mirrors the JS one. Every entry point takes a BridgeKit instance, defaulting
to the shared BridgeKit.default — so tests substitute instances and feature code uses the
one it was handed.
Provide a contract
Section titled “Provide a contract”Implement the generated interface, then register a lazy factory:
class ConnectHostProvider(private val deps: ConnectDeps) : ConnectHost { override suspend fun isLoggedIn(): Boolean = deps.session.isLoggedIn() override suspend fun installEsim(params: InstallEsimParams): InstallEsimResult = deps.esim.install(params) override fun showLogin() { deps.nav.toLogin() } override fun otpCodes(): Flow<String> = deps.sms.codes() override val connectivity = MutableStateFlow(Connectivity(online = true))}
val binding = bridgekit.provide(ConnectHostContract, Scope.global) { ConnectHostProvider(deps) }// later:binding.close()- The factory is lazy — invoked on first resolution unless
eager = true. - One live binding per
(contract, scope); a duplicateprovidereplaces with a dev warning. binding.close()is handle-scoped and a no-op if already superseded.
Consume a contract
Section titled “Consume a contract”consume returns a typed proxy. It suspends until (dispatcher connected AND contract
provided), bounded by the readiness timeout:
val lia = bridgekit.consume(LiaFeatureContract) // suspend, readiness-boundedval count = lia.getUnreadCount()lia.sessionStatus.collect { value -> /* BridgeValue<SessionStatus> */ }Non-suspending and explicit alternatives:
val maybe = bridgekit.tryConsume(LiaFeatureContract) // null if not readyif (bridgekit.isProvided(LiaFeatureContract)) { /* ... */ }bridgekit.awaitProvided(LiaFeatureContract, timeout) // explicit waitState is BridgeValue<T>
Section titled “State is BridgeValue<T>”Consumed state carries availability:
lia.sessionStatus.collect { v -> when (v) { is BridgeValue.Available -> render(v.value) is BridgeValue.Initial -> render(v.value) // seeded initial, no provider yet is BridgeValue.Unprovided -> showStale(v.lastKnown) // binding closed }}The DI-friendly instance pattern
Section titled “The DI-friendly instance pattern”Generated proxy factories and lifecycle extensions take bridgekit: BridgeKit = BridgeKit.default. Feature code uses the instance it received — BridgeKitModule.register
passes one (see Auto-discovery) — and tests pass a
BridgeKit(testTransport).
class LiaController(private val bridgekit: BridgeKit) { suspend fun unread() = bridgekit.consume(LiaFeatureContract).getUnreadCount()}