diff --git a/README.md b/README.md index 8349a08..94b964e 100644 --- a/README.md +++ b/README.md @@ -1,31 +1,34 @@ # ⚙️ConfigX -ConfigX is a simple configuration library that you can use with your application or libraries. - -ConfigX is NOT that kind of library that allows you configuring any Ruby object, instead -it takes a different approach. It reads configuration from YAML files and environment variables -and load it into a ruby object. It's highly influenced by the [config] gem, but it does -not define a global objects and allows you having multiple independent configurations. +ConfigX is a lightweight configuration library that helps you manage settings for applications or libraries. +Unlike other configuration libraries, ConfigX does not allow configuring arbitrary Ruby objects. Instead, +it focuses on loading configuration from YAML files and environment variables into structured Ruby objects. +Inspired by the [config] gem, ConfigX avoids defining global objects and supports multiple +independent configurations. ## Installation -Install the gem and add to the application's Gemfile by executing: +To install, add the gem to your Gemfile: - $ bundle add configx +```bash +$ bundle add configx +``` -If bundler is not being used to manage dependencies, install the gem by executing: +Or, if you’re not using Bundler: - $ gem install configx +```bash +$ gem install configx +``` ## Usage -Start using the library as simple as loading configuration from default locations: +To load configuration from the default locations, use: ```ruby config = ConfigX.load ``` -It loads configuration from the following locations in the specified order: +This loads configuration from the following sources in order: 1. `config/settings.yml` 2. `config/settings/production.yml` @@ -33,7 +36,7 @@ It loads configuration from the following locations in the specified order: 4. `config/settings/production.local.yml` 5. Environment variables -All the configuration source are merged an intuitive way. For instance, +The configuration is merged in an intuitive way, with environment variables taking precedence. For example: * **config/settings.yml** @@ -59,7 +62,7 @@ api: export SETTINGS__API__ACCESS_TOKEN=foobar ``` -The resulting configuration will be: +Results in: ```ruby config = ConfigX.load @@ -70,7 +73,7 @@ config.api.access_token # => "foobar" ### Customizing Configuration -You can customize the configuration by passing optional arguments to the `load` method: +You can customize how configurations are loaded: ```ruby ConfigX.load( @@ -83,25 +86,26 @@ ConfigX.load( ) ``` -The first four options, `env` (positional), `dir_name`, `file_name`, and `config_root` are used to specify -the configuration files to read: +Explanation of options: + +* `env`, `dir_name`, `file_name`, and `config_root` specify where to look for configuration files. + +In this example ConfigX will look for configuration files in the following order: 1. `{config_root}/{file_name}.yml` 2. `{config_root}/{file_name}/{env}.yml` 3. `{config_root}/{file_name}.local.yml` 4. `{config_root}/{file_name}/{env}.local.yml` +* `env_prefix` and `env_separator` define how environment variables map to configuration keys. -The `env_prefix` and `env_separator` options are used to specify how the environment variables should be constructed. In -the above example, they start from `SETTINGS` and use `__` as a separator. - -For instance, the following environment variable: +For example, with the following environment variable: ``` export SETTINGS__API__ACCESS_TOKEN=foobar ``` -corresponds to the following configuration: +ConfigX loads it into: ```yaml --- @@ -109,18 +113,77 @@ api: access_token: foobar ``` -You can also pass boolean value to environment variables using convenient YAML syntax: +### Environment Variable Parsing + +ConfigX automatically parses environment variable values and converts them to the appropriate types where possible. +It handles strings, booleans, numbers, and even arrays. The following types are supported: + +#### Booleans: -```sh +```bash export SETTINGS__API__ENABLED=true export SETTINGS__API__ENABLED=false export SETTINGS__API__ENABLED=on export SETTINGS__API__ENABLED=off ``` -Environment variables have the highest priority and override the values from the configuration files. +These values will be parsed into their corresponding boolean types (`true` or `false`): + +```ruby +config.api.enabled # => true or false +``` + +#### Numbers: + +```bash +export SETTINGS__API__RETRY_COUNT=5 +export SETTINGS__API__TIMEOUT=30.5 +``` + +Numeric values will be parsed as either integers or floats: + +```ruby +config.api.retry_count # => 5 +config.api.timeout # => 30.5 +``` + + +#### Arrays: -Sometimes you may want to just load configuration from a single source, for example, from for testing purposes: +Arrays can be specified by using comma-separated values: + +```bash +export SETTINGS__API__SERVERS='["server1","server2","server3"]' +``` + +This will be parsed as an array: + +```ruby +config.api.servers # => ["server1", "server2", "server3"] +``` + + +#### Strings: + +Regular string values remain unchanged: + +```bash +export SETTINGS__API__ACCESS_TOKEN="my_secret_token" +``` + +This will simply be loaded as a string: + +```ruby +config.api.access_token # => "my_secret_token" +``` + +Environment variables have the highest precedence and will override values from YAML configuration files. +This ensures that any environment-specific settings can be applied without modifying the configuration +files themselves. + +### Loading Single Sources + +To load configuration from a specific source (e.g., during testing): ```ruby config = ConfigX.from({api: {enabled: true}}) @@ -129,8 +192,7 @@ config.api.enabled # => true ### Typed Config -ConfigX allows you to define typed configuration using the `ConfigX::Config` class which uses the `dry-struct` library -under the hood. +ConfigX supports typed configurations using `ConfigX::Config`, which leverages [dry-struct]: ```ruby class Config < ConfigX::Config @@ -142,7 +204,7 @@ class Config < ConfigX::Config end ``` -You can then load the configuration using the `load` method: +Load the typed configuration with: ```ruby config = ConfigX.load(config_class: Config) @@ -150,8 +212,8 @@ config.api.enabled #=> true config.api.endpoint #=> "https://example.com" ``` -Using typed configuration allows you to define the structure of the configuration and automatically cast values to the -specified types. +Typed configurations enforce structure and type-checking. + ## Development After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake spec` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment. @@ -167,3 +229,4 @@ Bug reports and pull requests are welcome on GitHub at https://github.com/bolsha The gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT). [config]: https://rubygems.org/gems/config +[dry-struct]: https://dry-rb.org/gems/dry-struct/ diff --git a/spec/config_x/env_source_spec.rb b/spec/config_x/env_source_spec.rb index 85ca851..a185f6d 100644 --- a/spec/config_x/env_source_spec.rb +++ b/spec/config_x/env_source_spec.rb @@ -59,7 +59,8 @@ "MY_CONFIG__SIX" => "42", "MY_CONFIG__SEVEN" => "64.4", "MY_CONFIG__EIGHT" => "foo,bar", - "MY_CONFIG__NINE" => '["foo","bar"]' + "MY_CONFIG__NINE" => '["foo","bar"]', + "MY_CONFIG__TEN" => "- foo\n- bar" } end @@ -73,7 +74,8 @@ "six" => 42, "seven" => 64.4, "eight" => "foo,bar", - "nine" => ["foo", "bar"] + "nine" => ["foo", "bar"], + "ten" => ["foo", "bar"] }) end end