///|
/// `.env` の中身を読む。`KEY=value` の行だけを取り、`#` のコメント・空行・`export` を無視する。
/// 値は前後の空白を除き、`"…"` / `'…'` で囲まれていれば中身をそのまま(囲みの外の `# …` は捨てる)。
pub fn parse_dotenv(text : String) -> Map[String, String] {
let env : Map[String, String] = Map([])
for raw_line in text.split("\n") {
let line = raw_line.trim(chars=" \t\r").to_owned()
if line.is_empty() || line.has_prefix("#") {
continue
}
let line = if line.has_prefix("export ") {
line["export ".length():].trim_start(chars=" \t").to_owned()
} else {
line
}
guard line.find("=") is Some(eq) else { continue }
let key = line[:eq].trim(chars=" \t").to_owned()
guard !key.is_empty() && !key.contains(" ") else { continue }
env[key] = dotenv_value(line[eq + 1:].trim(chars=" \t").to_owned())
}
env
}
///|
fn dotenv_value(raw : String) -> String {
for quote in ['"', '\''] {
if raw.has_prefix(quote.to_string()) {
let inner = raw[quote.to_string().length():]
return match inner.find(quote.to_string()) {
Some(end) => inner[:end].to_owned()
None => inner.to_owned()
}
}
}
match raw.find(" #") {
Some(i) => raw[:i].trim_end(chars=" \t").to_owned()
None => raw
}
}
///|
/// 環境変数を優先し、無いキーだけを `.env` で補う。
pub fn merge_env(
env : Map[String, String],
dotenv : Map[String, String],
) -> Map[String, String] {
let merged : Map[String, String] = Map([])
for key, value in dotenv {
merged[key] = value
}
for key, value in env {
merged[key] = value
}
merged
}