koin-annotations
koin-annotations copied to clipboard
Config check breaks when definition is in native sourceSet
Describe the bug I have the KMP network module with structure like this:
shared:network/
├── commonMain/
│ └── com/
│ └── example/
│ └── network/
│ ├── di/
│ │ └── NetworkModule.kt
│ └── firebase/
│ └── IFirebaseAppCheckTokenProvider.kt
├── androidMain/
│ └── com/
│ └── example/
│ └── network/
│ └── firebase/
│ └── FirebaseAppCheckTokenProvider.kt
└── iosMain/
└── com/
└── example/
└── network/
└── firebase/
└── FirebaseAppCheckTokenProvider.kt
ComponentScan is enabled for the entire module:
@Module
@ComponentScan("com.example.network")
class NetworkModule
commonMain holds the interface:
internal interface IFirebaseAppCheckTokenProvider {
suspend fun getToken(): Result<String>
}
That is implemented in androidMain and iosMain sourceSets:
@Single
internal class FirebaseAppCheckTokenProvider : IFirebaseAppCheckTokenProvider {
// Some implementation
}
For some reason, I'm getting the "Missing Definition type" error:
e: [ksp] --> Missing Definition type 'com.example.network.firebase.IFirebaseAppCheckTokenProvider' for 'com.example.network.client.getDefaultHttpClient'. Fix your configuration to define type 'IFirebaseAppCheckTokenProvider'.
When looking into the generated code, I see that, indeed, commonMain doesn't contain the IFirebaseAppCheckTokenProvider definition but android/ios does have a complete generated module with IFirebaseAppCheckTokenProvider inside it.
commonMain:
public val com_example_network_di_NetworkModule : Module get() = module {
factory() { com.example.network.client.getDefaultHttpClient(firebaseAppCheckTokenProvider=get()) } bind(io.ktor.client.HttpClient::class)
}
public val com.example.network.di.NetworkModule.module : org.koin.core.module.Module get() = com_example_network_di_NetworkModule
android:
public val com_example_network_di_NetworkModule : Module = module {
single() { com.example.network.firebase.FirebaseAppCheckTokenProvider() } bind(com.example.network.firebase.IFirebaseAppCheckTokenProvider::class)
factory() { com.example.network.client.getDefaultHttpClient(firebaseAppCheckTokenProvider=get()) } bind(io.ktor.client.HttpClient::class)
}
public val com.example.network.di.NetworkModule.module : org.koin.core.module.Module get() = com_example_network_di_NetworkModule
What would you suggest to do in this case to make KOIN_CONFIG_CHECK work?
Koin project used and used version (please complete the following information):
koin-core version 3.5.6
koin-annotations version 1.4.0-RC4
The only working way how to have implementations in native source sets is to define expect class for it:
internal interface IFirebaseAppCheckTokenProvider {
suspend fun getToken(): Result<String>
}
@Single(binds = [IFirebaseAppCheckTokenProvider::class])
internal expect class FirebaseAppCheckTokenProvider
and then in native sourceSets:
@Single(binds = [IFirebaseAppCheckTokenProvider::class])
internal actual class FirebaseAppCheckTokenProvider : IFirebaseAppCheckTokenProvider {
// impl logic
}
But I feel there should be an easier way to do this, and I'm missing something.
You seems to enforce bind type binds = [IFirebaseAppCheckTokenProvider::class], right?
Did you take a look at this sample here? https://github.com/InsertKoinIO/KMP-App-Template?tab=readme-ov-file#sharing-multiplatform-native-components
Sharing patterns doc is updated: https://insert-koin.io/docs/reference/koin-annotations/kmp#sharing-patterns
Let's reopen if you see something