
Compile-time dependency injection compositor offering annotation-driven DI, graph validation at compile time, generated entry points, singleton support, and fast incremental builds for safe, efficient dependency wiring.
Spike is a Kotlin Multiplatform dependency injection compositor that ensures compile-time safety and fast, incremental compilation through KSP. It is designed to be straightforward to use and universally applicable across all Kotlin platforms.
[versions]
spike = "<see 'tag' above>"
[libraries]
spike = { module = "io.github.diareuse:spike", version.ref = "spike" }
spike-ktor = { module = "io.github.diareuse:spike-ktor", version.ref = "spike" }
spike-compiler = { module = "io.github.diareuse:spike-compiler", version.ref = "spike" }
spike-androidx = { module = "io.github.diareuse:spike-androidx", version.ref = "spike" }
spike-androidx-compose = { module = "io.github.diareuse:spike-androidx-compose", version.ref = "spike" }--- or ---
dependencies {
val spike = "see 'tag' above"
ksp("io.github.diareuse:spike-compiler:$spike")
implementation("io.github.diareuse:spike:$spike")
implementation("io.github.diareuse:spike-ktor:$spike")
implementation("io.github.diareuse:spike-androidx:$spike")
implementation("io.github.diareuse:spike-androidx-compose:$spike")
}val spike = "see 'tag' above"
kotlin {
// …
sourceSets {
androidMain.dependencies {
// if not using jetpack compose
implementation("io.github.diareuse:spike-androidx:$spike")
}
commonMain.dependencies {
implementation("io.github.diareuse:spike:$spike")
// if using jetpack compose
implementation("io.github.diareuse:spike-androidx-compose:$spike")
}
}
}
dependencies {
add("kspAndroid", "io.github.diareuse:spike-compiler:$spike")
add("kspJs", "io.github.diareuse:spike-compiler:$spike")
add("kspWasmJs", "io.github.diareuse:spike-compiler:$spike")
add("kspJvm", "io.github.diareuse:spike-compiler:$spike")
// and all other targets…
}Spike offers specific integrations to simplify its usage across various frameworks. Check out their respective documentation for more details:
spike-androidx) - Support for Multiplatform AndroidX
ViewModels.spike-androidx-compose) - Jetpack
Compose integration for Spike ViewModels.spike-ktor) - Seamless dependency injection for Ktor
applications.Spike uses annotations to define your dependency graph. The core annotations are:
@Include: Includes a class or a provider function in the dependency graph.@Inject: Explicitly marks a constructor for dependency injection when multiple constructors are
present.@Singleton: Marks a class as a singleton (only instantiated once per entry point).@EntryPoint: Defines an entry point interface for the dependency graph.Here's an example of how to define your components:
interface Heater
// Use bindAs to bind a class to an interface
@Include(bindAs = Heater::class)
class ElectricHeater : Heater
// Spike can inject standard `Lazy<T>` or `spike.Provider<T>` automatically
@Include
class CoffeeMaker(
private val heater: Heater,
private val pumpProvider: spike.Provider<Pump>,
private val logger: Lazy<CoffeeLogger>
) {
fun brew() {
val pump = pumpProvider.get()
// ...
}
}
// You can also use @Include on functions to provide external or third-party classes!
@Include
fun provideCoffeeLogger(): CoffeeLogger = ConsoleCoffeeLogger()
@Include
class Pump {
// If a class has multiple constructors, annotate one with @Inject
@Inject
constructor()
constructor(capacity: Int)
}
// Mark a class with @Singleton to share the same instance within an entry point
@Singleton
@Include
class ShopInventoryTo access your dependency graph, you need to create an interface and annotate it with @EntryPoint.
A companion object is required so Spike can generate an extension function on it.
@EntryPoint
interface CoffeeShop {
val coffeeMaker: CoffeeMaker
val inventory: ShopInventory
companion object
}After building your project, Spike generates a factory extension on your entry point's companion object. You can use it to create your graph and access the dependencies:
fun main() {
val coffeeShop = CoffeeShop() // invokes generated extension on CoffeeShop.Companion
val coffeeMaker = coffeeShop.coffeeMaker
coffeeMaker.brew()
}Spike is a Kotlin Multiplatform dependency injection compositor that ensures compile-time safety and fast, incremental compilation through KSP. It is designed to be straightforward to use and universally applicable across all Kotlin platforms.
[versions]
spike = "<see 'tag' above>"
[libraries]
spike = { module = "io.github.diareuse:spike", version.ref = "spike" }
spike-ktor = { module = "io.github.diareuse:spike-ktor", version.ref = "spike" }
spike-compiler = { module = "io.github.diareuse:spike-compiler", version.ref = "spike" }
spike-androidx = { module = "io.github.diareuse:spike-androidx", version.ref = "spike" }
spike-androidx-compose = { module = "io.github.diareuse:spike-androidx-compose", version.ref = "spike" }--- or ---
dependencies {
val spike = "see 'tag' above"
ksp("io.github.diareuse:spike-compiler:$spike")
implementation("io.github.diareuse:spike:$spike")
implementation("io.github.diareuse:spike-ktor:$spike")
implementation("io.github.diareuse:spike-androidx:$spike")
implementation("io.github.diareuse:spike-androidx-compose:$spike")
}val spike = "see 'tag' above"
kotlin {
// …
sourceSets {
androidMain.dependencies {
// if not using jetpack compose
implementation("io.github.diareuse:spike-androidx:$spike")
}
commonMain.dependencies {
implementation("io.github.diareuse:spike:$spike")
// if using jetpack compose
implementation("io.github.diareuse:spike-androidx-compose:$spike")
}
}
}
dependencies {
add("kspAndroid", "io.github.diareuse:spike-compiler:$spike")
add("kspJs", "io.github.diareuse:spike-compiler:$spike")
add("kspWasmJs", "io.github.diareuse:spike-compiler:$spike")
add("kspJvm", "io.github.diareuse:spike-compiler:$spike")
// and all other targets…
}Spike offers specific integrations to simplify its usage across various frameworks. Check out their respective documentation for more details:
spike-androidx) - Support for Multiplatform AndroidX
ViewModels.spike-androidx-compose) - Jetpack
Compose integration for Spike ViewModels.spike-ktor) - Seamless dependency injection for Ktor
applications.Spike uses annotations to define your dependency graph. The core annotations are:
@Include: Includes a class or a provider function in the dependency graph.@Inject: Explicitly marks a constructor for dependency injection when multiple constructors are
present.@Singleton: Marks a class as a singleton (only instantiated once per entry point).@EntryPoint: Defines an entry point interface for the dependency graph.Here's an example of how to define your components:
interface Heater
// Use bindAs to bind a class to an interface
@Include(bindAs = Heater::class)
class ElectricHeater : Heater
// Spike can inject standard `Lazy<T>` or `spike.Provider<T>` automatically
@Include
class CoffeeMaker(
private val heater: Heater,
private val pumpProvider: spike.Provider<Pump>,
private val logger: Lazy<CoffeeLogger>
) {
fun brew() {
val pump = pumpProvider.get()
// ...
}
}
// You can also use @Include on functions to provide external or third-party classes!
@Include
fun provideCoffeeLogger(): CoffeeLogger = ConsoleCoffeeLogger()
@Include
class Pump {
// If a class has multiple constructors, annotate one with @Inject
@Inject
constructor()
constructor(capacity: Int)
}
// Mark a class with @Singleton to share the same instance within an entry point
@Singleton
@Include
class ShopInventoryTo access your dependency graph, you need to create an interface and annotate it with @EntryPoint.
A companion object is required so Spike can generate an extension function on it.
@EntryPoint
interface CoffeeShop {
val coffeeMaker: CoffeeMaker
val inventory: ShopInventory
companion object
}After building your project, Spike generates a factory extension on your entry point's companion object. You can use it to create your graph and access the dependencies:
fun main() {
val coffeeShop = CoffeeShop() // invokes generated extension on CoffeeShop.Companion
val coffeeMaker = coffeeShop.coffeeMaker
coffeeMaker.brew()
}