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 AppHostProvider(private val deps: AppDeps) : AppHost { override suspend fun isLoggedIn(): Boolean = deps.session.isLoggedIn() override suspend fun saveFile(params: SaveFileParams): SaveFileResult = deps.files.save(params) override fun showLogin() { deps.nav.toLogin() } override fun notifications(): Flow<String> = deps.push.messages() override val connectivity = MutableStateFlow(Connectivity(online = true))}
val binding = bridgekit.provide(AppHostContract, Scope.global) { AppHostProvider(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 inbox = bridgekit.consume(InboxFeatureContract) // suspend, readiness-boundedval count = inbox.getUnreadCount()inbox.sessionStatus.collect { value -> /* BridgeValue<SessionStatus> */ }Non-suspending and explicit alternatives:
val maybe = bridgekit.tryConsume(InboxFeatureContract) // null if not readyif (bridgekit.isProvided(InboxFeatureContract)) { /* ... */ }bridgekit.awaitProvided(InboxFeatureContract, timeout) // explicit waitState is BridgeValue<T>
Section titled “State is BridgeValue<T>”Consumed state carries availability:
inbox.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 InboxController(private val bridgekit: BridgeKit) { suspend fun unread() = bridgekit.consume(InboxFeatureContract).getUnreadCount()}