2022-02-21 20:40:13 +01:00
|
|
|
module env
|
|
|
|
|
|
|
|
import os
|
|
|
|
|
|
|
|
// The prefix that every environment variable should have
|
|
|
|
const prefix = 'VIETER_'
|
|
|
|
|
|
|
|
// The suffix an environment variable in order for it to be loaded from a file
|
|
|
|
// instead
|
|
|
|
const file_suffix = '_FILE'
|
|
|
|
|
|
|
|
pub struct ServerConfig {
|
|
|
|
pub:
|
2022-02-21 20:51:41 +01:00
|
|
|
log_level string [default: WARN]
|
|
|
|
log_file string [default: 'vieter.log']
|
|
|
|
pkg_dir string
|
2022-02-21 20:40:13 +01:00
|
|
|
download_dir string
|
2022-02-21 20:51:41 +01:00
|
|
|
api_key string
|
|
|
|
repo_dir string
|
2022-02-21 22:32:54 +01:00
|
|
|
repos_file string
|
2022-02-21 20:40:13 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
pub struct BuildConfig {
|
|
|
|
pub:
|
2022-02-22 08:14:20 +01:00
|
|
|
api_key string
|
|
|
|
address string
|
2022-02-21 20:40:13 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
fn get_env_var(field_name string) ?string {
|
2022-02-21 20:51:41 +01:00
|
|
|
env_var_name := '$env.prefix$field_name.to_upper()'
|
|
|
|
env_file_name := '$env.prefix$field_name.to_upper()$env.file_suffix'
|
2022-02-21 20:40:13 +01:00
|
|
|
env_var := os.getenv(env_var_name)
|
|
|
|
env_file := os.getenv(env_file_name)
|
|
|
|
|
|
|
|
// If both aren't set, we report them missing
|
|
|
|
if env_var == '' && env_file == '' {
|
|
|
|
return error('Either $env_var_name or $env_file_name is required.')
|
|
|
|
}
|
|
|
|
|
|
|
|
// If they're both set, we report a conflict
|
|
|
|
if env_var != '' && env_file != '' {
|
|
|
|
return error('Only one of $env_var_name or $env_file_name can be defined.')
|
|
|
|
}
|
|
|
|
|
2022-02-21 22:22:36 +01:00
|
|
|
// If it's the env var itself, we return it.
|
|
|
|
// I'm pretty sure this also prevents variable ending in _FILE (e.g.
|
|
|
|
// VIETER_LOG_FILE) from being mistakingely read as an _FILE suffixed env
|
|
|
|
// var.
|
2022-02-21 20:40:13 +01:00
|
|
|
if env_var != '' {
|
|
|
|
return env_var
|
|
|
|
}
|
|
|
|
|
|
|
|
// Otherwise, we process the file
|
|
|
|
return os.read_file(env_file) or {
|
|
|
|
error('Failed to read file defined in $env_file_name: ${err.msg}.')
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-02-22 08:14:20 +01:00
|
|
|
// load<T> attempts to create the given type from environment variables. For
|
|
|
|
// each field, the corresponding env var is its name in uppercase prepended
|
|
|
|
// with the hardcoded prefix. If this one isn't present, it looks for the env
|
|
|
|
// var with the file_suffix suffix.
|
2022-02-21 20:40:13 +01:00
|
|
|
pub fn load<T>() ?T {
|
|
|
|
res := T{}
|
|
|
|
|
|
|
|
$for field in T.fields {
|
|
|
|
res.$(field.name) = get_env_var(field.name) or {
|
|
|
|
// We use the default instead, if it's present
|
|
|
|
mut default := ''
|
|
|
|
|
|
|
|
for attr in field.attrs {
|
|
|
|
if attr.starts_with('default: ') {
|
|
|
|
default = attr[9..]
|
|
|
|
break
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if default == '' {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
|
|
|
default
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return res
|
|
|
|
}
|