Marc Knaup
02/09/2021, 12:02 PMlive
, test
and dev
.
In each environment I’d like to use different configuration values, for example a different API URL.
So basically I’d have three .kt
files with different values each and depending on what I’d like to build/deploy I need a different one of these to be used 🤔
Ideally the values are provided when starting the server (e.g. webpack dev server) so that they can depend on environment variables (e.g. on Heroku).turansky
02/09/2021, 12:13 PMMarc Knaup
02/09/2021, 12:14 PMBig Chungus
02/09/2021, 12:15 PMBig Chungus
02/09/2021, 12:15 PMMarc Knaup
02/09/2021, 12:15 PMMarc Knaup
02/09/2021, 12:17 PMBig Chungus
02/09/2021, 12:17 PMMarc Knaup
02/09/2021, 12:19 PMimport kotlinx.browser.*
public external interface Configuration {
public val publicApiUrl: String
}
public val configuration: Configuration =
window.asDynamic().appConfiguration.unsafeCast<Configuration>()
Marc Knaup
02/09/2021, 12:21 PMBig Chungus
02/09/2021, 12:22 PMexternal interface AppEnv {
val API_URL: String
}
inline val Window.env: AppEnv
get() = asDynamic().env.unsafeCast<AppEnv>()
suspend fun loadEnv(): AppEnv {
val env: AppEnv = fetch("/application.env").await().text().await()
.split("\n")
.filter(String::isNotBlank)
.joinToString(",", "{", "}") {
val (key, value) = it.split("=", limit = 2).let { c ->
c[0] to c[1]
}
"\"$key\": \"$value\""
}.let(JSON::parse)
window.asDynamic().env = env
requireNotNull(window.env.API_URL)
return env
}
Marc Knaup
02/09/2021, 12:22 PMfetch
request is unacceptable.Marc Knaup
02/09/2021, 12:22 PMBig Chungus
02/09/2021, 12:23 PMMarc Knaup
02/09/2021, 12:23 PMBig Chungus
02/09/2021, 12:23 PMMarc Knaup
02/09/2021, 12:23 PMindex
HTML file. It can be injected there.Marc Knaup
02/09/2021, 12:23 PMindex
file needs to be dynamic anyway for security.Big Chungus
02/09/2021, 12:24 PM<script>
window.env={}
</script>
Marc Knaup
02/09/2021, 12:24 PMBig Chungus
02/09/2021, 12:24 PMMarc Knaup
02/09/2021, 12:25 PMindex.html
is a template and built on-the-fly for each request.Marc Knaup
02/09/2021, 12:25 PMMarc Knaup
02/09/2021, 12:25 PMBig Chungus
02/09/2021, 12:25 PMMarc Knaup
02/09/2021, 12:26 PMMarc Knaup
02/09/2021, 12:26 PMindex.html
on the fly is also Kotlin/JS, running on Cloudflare 😄Marc Knaup
02/09/2021, 12:27 PMConfiguration
definition on the service side to make it type-safe.Marc Knaup
02/09/2021, 12:27 PMBig Chungus
02/09/2021, 12:29 PMclass Configuration(
val prop1: String,
val prop2:Int
) {
override fun toString() = """{
prop1:"$prop1",
prop2:$prop2,
}"""
}
val html = """
<script>
window.env=$configuration
</script>
"""
?Marc Knaup
02/09/2021, 12:30 PMBig Chungus
02/09/2021, 12:30 PMMarc Knaup
02/09/2021, 12:31 PMBig Chungus
02/09/2021, 12:31 PMMarc Knaup
02/09/2021, 12:31 PMexternal interface Configuration
in the web project.Marc Knaup
02/09/2021, 12:31 PMMarc Knaup
02/09/2021, 12:32 PMkotlinx-serialization
and just “assume” that the generated JSON is perfectly valid for the external interface
which doesn’t use kotlinx-serialization
.