#colleen
加载环境变量
package site.daydream.colleen.config
import io.github.cdimascio.dotenv.Dotenv
import site.daydream.colleen.logger
import java.io.File
/**
* Environment configuration loader
*
* Priority: System env > .env.local > .env.{profile} > .env
*/
class EnvLoader(
private val profileKey: String = "COLLEEN_ENV",
private val defaultProfile: String = "prod"
) {
private val cache = mutableMapOf<String, String>()
private var loaded = false
fun load(profile: String? = null) {
if (loaded) return
val activeProfile = profile ?: getActiveProfile()
// 这个日志很重要:防止生产环境配置错误
logger.info("Active profile: $activeProfile")
val files = listOf(".env", ".env.$activeProfile", ".env.local")
for (fileName in files) {
val file = File(System.getProperty("user.dir"), fileName)
if (file.exists() && file.isFile) {
loadFile(file, fileName)
}
}
applyToSystem()
loaded = true
}
operator fun get(key: String): String? {
return System.getenv(key) ?: System.getProperty(key) ?: cache[key]
}
fun require(key: String): String {
return checkNotNull(get(key)) { "Missing required variable: $key" }
}
fun getOrDefault(key: String, default: String): String = get(key) ?: default
fun getActiveProfile(): String = get(profileKey) ?: defaultProfile
fun isProfile(vararg profiles: String): Boolean {
return profiles.any { it.equals(getActiveProfile(), ignoreCase = true) }
}
fun requireAll(vararg keys: String) {
val missing = keys.filter { get(it).isNullOrBlank() }
check(missing.isEmpty()) { "Missing variables: ${missing.joinToString()}" }
}
operator fun contains(key: String): Boolean = !get(key).isNullOrBlank()
val isDev: Boolean get() = isProfile("dev", "development")
val isProd: Boolean get() = isProfile("prod", "production")
val isTest: Boolean get() = isProfile("test", "testing")
private fun loadFile(file: File, fileName: String) {
try {
Dotenv.configure()
.directory(file.parent)
.filename(file.name)
.ignoreIfMalformed()
.ignoreIfMissing()
.load()
.entries()
.forEach { (key, value) -> cache[key] = value }
} catch (e: Exception) {
// 这个日志很重要:文件存在但加载失败,可能是格式问题
logger.warn("Failed to load $fileName: ${e.message}")
}
}
private fun applyToSystem() {
cache.forEach { (key, value) ->
if (System.getenv(key) == null && System.getProperty(key) == null) {
System.setProperty(key, value)
}
}
}
}
object Env : EnvLoader()site/daydream/colleen/
├── config/
│ └── EnvLoader.kt
├── core/
├── http/
└── ...