All Projects → binaryage → env-config

binaryage / env-config

Licence: other
A Clojure(Script) library for config map overrides via environmental variables

Programming Languages

clojure
4091 projects
shell
77523 projects

Projects that are alternatives of or similar to env-config

Environ Config
Python Application Configuration With Environment Variables
Stars: ✭ 210 (+677.78%)
Mutual labels:  config, environment
environment
🌳 Environment variable configuration for Node.js made easy.
Stars: ✭ 12 (-55.56%)
Mutual labels:  config, environment
Env
Simple lib to parse environment variables to structs
Stars: ✭ 2,164 (+7914.81%)
Mutual labels:  config, environment
ini
📝 Go INI config management. support multi file load, data override merge. parse ENV variable, parse variable reference. Dotenv file parse and loader. INI配置读取管理,支持多文件加载,数据覆盖合并, 解析ENV变量, 解析变量引用。DotEnv 解析加载
Stars: ✭ 72 (+166.67%)
Mutual labels:  config, environment
cfg-rs
A Configuration Library for Rust Applications
Stars: ✭ 18 (-33.33%)
Mutual labels:  config, environment
salak.rs
A multi layered configuration loader and zero-boilerplate configuration parser.
Stars: ✭ 27 (+0%)
Mutual labels:  config, environment
react-native-envs-poc
Manage staging & production environments in React Native
Stars: ✭ 32 (+18.52%)
Mutual labels:  config, environment
dotfiles
My personal app/env configs and dotfiles.
Stars: ✭ 27 (+0%)
Mutual labels:  config, environment
marvin-vagrant-dev
No description or website provided.
Stars: ✭ 26 (-3.7%)
Mutual labels:  environment
eRCaGuy dotfiles
.bashrc file, terminal prompt that shows current git branch, Arduino setup, Eclipse setup, git diff with line numbers, helpful scripts, improved Linux productivity, etc.
Stars: ✭ 84 (+211.11%)
Mutual labels:  config
env
A lightweight package for loading OS environment variables into structs for Go projects
Stars: ✭ 24 (-11.11%)
Mutual labels:  config
gatsby-plugin-dynamic-routes
Creating dynamic routes based on your environment and/or renaming existing routes
Stars: ✭ 14 (-48.15%)
Mutual labels:  environment
.emacs.d
My emacs settings directory.
Stars: ✭ 28 (+3.7%)
Mutual labels:  config
surge
Network toolbox Surge rules, modules and configuration files, For pure self use.
Stars: ✭ 207 (+666.67%)
Mutual labels:  config
thema
A CUE-based framework for portable, evolvable schema
Stars: ✭ 41 (+51.85%)
Mutual labels:  config
BlueSense
🌈 BlueSense is a long-term project for monitoring Shanghai environment data.
Stars: ✭ 26 (-3.7%)
Mutual labels:  environment
installme-osx
My personal script to setup a new OSX
Stars: ✭ 57 (+111.11%)
Mutual labels:  config
Config-for-Clash-Surge
Clash Surge Shadowrocket Quantumult Config
Stars: ✭ 480 (+1677.78%)
Mutual labels:  config
nvim-projectconfig
neovim projectconfig
Stars: ✭ 48 (+77.78%)
Mutual labels:  config
nii-nvim
A minimal neovim configuration
Stars: ✭ 69 (+155.56%)
Mutual labels:  config

env-config

GitHub license Clojars Project Travis

This is a Clojure(Script) library for enabling easy and consistent config map overrides via environment variables.

This is useful for library authors who want to add some flexibility how their libraries can be configured.

Intro

Usually library configuration is achieved via a config map specifying keywords with individual config values. This config map can be provided directly (e.g. passed via an api call), via a build configuration or by some other means. For example in ClojureScript it could be passed via :compiler > :external-config.

Sometimes for ad-hoc tweaks it would be preferable to be able to override config values by defining environment variables instead of touching build tool configuration (which is usually under source control).

This library helps you do that consistently:

  1. we define a naming scheme how env variables map to config keys
  2. we define a coercion protocol which determines how strings from env variables are converted to Clojure values

Example

We want to support nested config maps. Let's look at example env variables with some nesting:

OOPS/COMPILER/MAX_ITERATIONS=10
OOPS/RUNTIME/DEBUG=true
OOPS/RUNTIME/WELCOME-MESSAGE=hello
OOPS/RUNTIME/DATA=~{:some (str "data" " via" " read-string")}
OOPS/RUNTIME/KEY=:some-keyword
OOPS/RUNTIME=something   <= this will cause a naming conflic warning

A call to (env-config.core/make-config "oops" (get-env-vars)) will return:

{:compiler {:max-iterations 10}
 :runtime {:debug true
           :welcome-message "hello"
           :key :some-keyword
           :data {:some "data via read-string"}}

You can observe several properties:

  1. forward slashes are used as separators
  2. to follow Clojure conventions, names are converted to lower-case and underscores turned into dashes
  3. prefix "oops" is stripped because it was specified as a library prefix
  4. values are naturally coerced to booleans, numbers, keywords, etc.
  5. you can use full power of read-string if you prepend value with ~

Also please note that existence of a variable name which is a prefix of another variable name will cause naming conflict warning and will be ignored (OOPS/RUNTIME is prefix of OOPS/RUNTIME/DEBUG in our example above).

Some shells like Bash do not allow slashes in variable names, you can use two underscores instead of a slash.

Integration

You probably want to merge the config coming from env-config over your standard config coming from a build tool.

For inspiration look at the commit which integrated env-config into cljs-oops library.

Please note that make-config-with-logging does not read environment directly. You have to pass it a map with variables.

I used this simple implementation to get them:

(defn get-env-vars []
  (-> {}
      (into (System/getenv))
      (into (System/getProperties))))

Logging

I needed a way how to report issues with naming conflicts or for example problems when evaluting values via read-string.

I didn't want to introduce another dependency so I decided to build internal subsystem for collecting "reports". It is up to you to inspect reports and communicate them somehow.

For convenience I have implemented a helper function which dynamically checks for availability of clojure.tools.logging and uses it for logging reports.

To get standard logging for free include dependency on clojure.tools.logging into your project and use make-config-with-logging to obtain your configs.

Coercion

We provide a standard set of coercion handlers. As you can see from the default-coercers list the rules are pretty simple. You might want to provide your own handlers.

Writing own coercion handlers

Coercion handlers are asked in the order in which they were specified to make-config. Each handler is passed key path in the config map and raw string value coming from environment.

The handler should answer either:

  1. nil which means "I'm not interested, pass it to someone else"
  2. :omit which means "ignore this value due to an error"
  3. a value wrapped in Coerced instance (to distinguish it from nil and :omit)

If no handler was interested we use the raw value as-is.

Look at the example of the most complex standard coercer:

(defn code-coercer [path val]
  (if (string-starts-with? val "~")
    (let [code (.substring val 1)]
      (try
        (->Coerced (read-string code))
        (catch Throwable e
          (report/report-warning! (str "unable to read-string from " (make-var-description (meta path)) ", "
                                       "attempted to eval code: '" code "', "
                                       "got problem: " (.getMessage e) "."))
          :omit)))))

Please note that the path vector has attached some metadata with original raw values which may be handy when reporting warnings/errors. You should use env-config.impl.report functionality to report errors in a standard way.

FAQ

My shell does not support variable names with slashes. What now?

You can use two underscores instead of a slash. Or alternatively you might want to use env command to launch your command with defined variables without shell naming restrictions. See this stack overflow answer.

For example:

env OOPS/COMPILER/MAX_ITERATIONS=10 OOPS/RUNTIME/DEBUG=true command

I personally use fish shell and prefer slashes to visually communicate the nested config structure.

Can this be used in self-hosted mode?

Yes, thanks to arichiardi. Since v0.2.0 you can use this library to configure scripts running under Planck or Lumo.

Note that the project description data, including the texts, logos, images, and/or trademarks, for each open source project belongs to its rightful owner. If you wish to add or remove any projects, please contact us at [email protected].