Konfig
A gradle tool that helps inject values during build configurations and that can be retrieve at runtime.
In other words, it brings buildTypes with structured basic data to kotlin-multiplatform applications
Introduction
Ever wanted to have different build types in your multiplatform application? You feel like most of the time your configurations during development time won't match those during deployment? konfig
has you covered
Samples
In your build logic (gradle), you can inject values like this
konfig {
debug(
"change" to 1,
"link" to "http://debug.com"
)
staging(
"link" to "https://staging.com"
)
release(
"link" to "https://release.com"
)
}
and you can retrieve those values in your application as simple as
val kfg = konfig()
val link: String by kfg // onDebug:(debug.com), onStaging(staging.com), onRelease(release.com)
Setup:Gradle
Konfig comes with a gradle plugin as a well as a runtime library. Just do the following
Kotlin Multiplatform
plugins {
// . . . .
id("tz.co.asoft.konfig") version "0.0.2"
}
// . . .
dependencies {
implementation("tz.co.asoft:konfig:+") // please use the latest version possible
}
Konfig Plugin
Setting up the konfig plugin makes it easy to help configure your buildTypes.
DRY - Don't Repeat Yourself
Consider the following konfiguration
konfig{
debug(
"app_name" to "My Killer App",
"api_link" to "https://debug.com"
)
. . .
release(
"app_name" to "My Killer App",
"api_link" to "https://release.com"
)
}
This repetition can be solved by the common konfiguration. Like so
konfig{
common(
"app_name" to "My Killer App"
)
debug(
"api_link" to "https://debug.com"
)
. . .
release(
"api_link" to "https://release.com"
)
}
Just remember, common is a reserved builder. Don't think it creates a buildType with the name "common"
Nested Structures
konfig supports nested structures, and since it uses kotlinx-serialization-mapper extracting your nested structure is easy
konfig {
debug(
"license" to "MIT",
"devs" to listOf(
mapOf(
"name" to "John Doe",
"email" to "[email protected]"
),
mapOf(
"name" to "Jane Doe",
"email" to "[email protected]"
)
)
)
}
You can even go crazy and do something like
data class Dev(val name: String, val email: String)
konfig {
debug(
"license" to "MIT",
"devs" to listOf(
Dev(name = "John Doe", email = "[email protected]") // or just Dev("John Doe","[email protected]")
Dev(name = "Jane Doe", email = "[email protected]"),
)
)
}
And you can retrieve your data as easy as
val kfg = konfig()
val license: String by kfg
val devs: List<Map<String,String>> by kfg
val name by devs[0]
val email by devs[1]
println(name) // John Doe
println(email) // [email protected]
Naming your konfigs
You can name your konfigs if you wan't to, by default the names of the konfigs are as their buildType i.e debug -> debug, staging->stagin, release->release If you need to have a debug buildType named free, you can go just do as follows
konfig {
debug("free_debug",
"license" to "MIT"
)
debug("paid_debug"
"licence" to "aSoft Ltd"
)
}
Application Plugin
Very often, you need to automate how you collect your configurations. This should be as easy as setting up your configurations and run the build type you want. The application
plugin gives you exactly that. But since every platform has it's own way of doing things we will tackle each of it seprately
Android Application
Setup
To setup the android application, you must declare the gradle plugins as follows (the order is important)
plugins {
id("com.android.application")
kotlin("android")
id("tz.co.asoft.application")
}
// . . .
konfig{
debug()
staging()
release()
}
Gradle Tasks
For each of the konfigurations above, the following gradle tasks are set
- generate[Konfig]KonfigFile -> generates a json file with the set configuration
- installRun[Konfig] -> a gradle task that installs and runs the specific version on a device or emulator
JVM Application
This gradle plugin, applies the native java application plugin and ads a few tasks more
Setup
plugins {
kotlin("jvm")
id("tz.co.asoft.application")
}
application {
mainClassName = "path.to.class.NameKt" // required by the `application` plugin
}
// . . .
konfig{
debug()
staging()
release()
}
Gradle Tasks
- generate[Konfig]KonfigFile -> generate a json file for the konfigurations set
- fatJar[Konfig] -> generates a fat jar in the
build/libs
of the specific konfiguration - installDist[Konfig] -> generates a distributable in
build/binaries
which is package together with it dependencies - run[Konfig] -> runs the application depending on the buildType
Browser Application
This shouldn't be confused with Javascript Applications. As we currently do not support nodejs applications
Setup
plugins {
kotlin("js")
id("tz.co.asoft.application")
}
// . . .
konfig{
debug()
staging()
release()
}
Gradle Tasks
- generate[Konfig]KonfigFile -> generates a json konfig file for that konfiguration
- webpack[Konfig] -> creates a minified webpack bundle that can be deployed to any server
- run[Konfig] -> opens the browser and runs the konfiguration. You should note that all debug types are not minified for obvious reasons, the rest are minified
Multiplatform Application
This plugin helps you write multiplatform application in one code base
Setup
plugins {
id("com.android.application") version "4.1.0"
kotlin("multiplatform") version "1.4.10"
id("tz.co.asoft.application")
}
// . . .
konfig{
debug()
staging()
release()
}
Gradle Tasks
If you have an android target with the name "android", you will get the following tasks
- generateAndroid[Konfig]KonfigFile -> generate the json config file for the android target
- installRunAndroid[Konfig] -> install and runs the application on a phone or emulator
N.B: If your target has a different name, feel free to swap the name with the word androd on the tasks
If you have a jvm target with the name "jvm", you will get the following tasks
- generateJVM[Konfig]KonfigFile -> generate the json config file for the android target
- fatJarJvm[Konfig] -> generates a fat jar of the java app in the
build/libs
of the specific konfiguration - runJvm[Konfig] -> runs the jvm application
N.B: To run the JVM application from kotlin("multiplatform")
gradle plugin, you must declare an attribute "Main-Class" in your Konfig
If you have a browser target with the name "js", you will get the following tasks
- generateJs[Konfig]KonfigFile -> generates a json konfig file for that konfiguration
- webpackJs[Konfig] -> creates a minified webpack bundle that can be deployed to any server
- runJs[Konfig] -> opens the browser and runs the js app with the provided konfiguration. You should note that all debug types are not minified for obvious reasons, the rest are minified