Yes, another application configuration library, but I assure you this is way better than any one of them out there. This is the Provider section of the Config Triad (Provision, Management, Provider).
C5Store is a comprehensive answer to the "what config library should I use for dynamic runtime configuration" question. Library is available here: https://github.com/normano/c5store
Why?
I've scoured around for configuration libraries in multiple languages and find them to be lacking in how they are defined, integration and flexbility with existing configuration sources, and then how to pass them around in an application.
I always found myself asking what configuration library should I use? Always have to cobble something together if I am not using a framework in a specific language.
Traditionally, one could use environment variables to pass runtime settings into an application. Shortcoming is that you need to restart if a setting changes. Environment variables are useful in the case of constant settings.
Dynamic runtime configuration landscape is chaos. No agreement on how to get settings from a file or network (db and otherwise) in to your application across multiple languages. Spring and ASP.net Core has done really well with configuration, but outside of that you are screwed and you need to use the language in order to reap the benefits.There are so many NodeJs libraries to load configuration and they have a myriad of ways. A lot of them are or seem unfinished or a copy of another library.
Why isn't there a way to load dynamic runtime configuration in multiple languages with the same APIs? I wanted a way to layout my defaults, override the defaults with external configuration, have external configuration be provided from multiple sources, subscribe and modify settings via subscription and pass around a read-only config object that I could grab values while traversing the config tree.
For my case, I only care for Java, Javascript and Rust and so that is why I targeted them. It is very easy to port them over to other languages.
What does it do?
Inherited Hierachical structure: A ton of configuration is defined in a tree and hierarchically. Can load in multiple configuration files in a particular order to override values. These configuration files define structure and "defaults".
Native Traversal: Instead of passing down nested Map<String, Object>, one passes down a "branch" or context.
External Configuration Providers: Load configuration from anywhere. A file provider is already provided that reads JSON and Yaml with the option to extend to TOML and properties. Consul, Vault, Sping Config Server, SQLlite or custom sources can be contacted by using a value provider (may need to implement it). Value providers can be scheduled to poll for changes at the time it is added.
Value Change Subscription: Subscribe to paths in the configuration tree, so the application can be changed without recompile.
Conclusion
I no longer have to ask myself what configuration library I should use and no worries about external configuration sources as I can implement a value provider and use them anywhere.