04 - Koin Adapter
1. Why
Sinew's core packages never register themselves in a DI container: each exposes constructors and factories, and the app wires them. On Flutter, sinew_riverpod_providers saves Riverpod apps that wiring. A Kotlin app on Koin writes the same few single { … } lines in every project. sinew-koin would ship them, as an optional adapter.
2. Shape
// in the app
startKoin {
modules(
sinewModules(config = SinewConfig(…), tokenSource = { get<SessionTokenSource>() }),
appModules,
)
}
// then: get<HttpClient>(named("main")), get<SecureStore>(), get<FieldCipher>(), get<NetworkChecker>(), …
| Rule | Why |
|---|---|
| The adapter only declares what the app would declare anyway. No logic. | It must be safe to drop it and wire by hand |
| One client per backend, registered under a qualifier the app names | Matches how the app already selects clients |
CrashReporter.install stays an explicit call in the app's startup | Installing a global is the app's decision |
| A Hilt adapter would be a separate Later item | Different DI tools, different packages |
3. API
| Name | Signature (pseudocode) |
|---|---|
sinewModules | sinewModules(config: SinewConfig, tokenSource: Scope.() -> TokenSource, backends: Map<String, SinewConfig> = {}): List<Module> |
| qualifiers | named(backendName) for each client |
4. Open questions
None left. Settled in review (2026-10-02):
- No
sinew-koinpackage. The wiring is about ten lines, so it's documented as an example in the Kotlin Architecture note instead. A package would add versioning and releases for little gain.