configx 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: 51b3ba99940f73078c374d7fb7804e231e58657903d6592ad9b594f42925d3b2
4
+ data.tar.gz: f51ed4cd4c47db8f05eb512d83d2d38bc0277e6acaed4aef54bd964e1bf87812
5
+ SHA512:
6
+ metadata.gz: 0d07f1c7ab54071b42411736e107635a6c75a2a867dc22e32c685e7964eaa9ab1c4204a988c797a6280b0dc71a8470d760b16fb8092e04142a138c9d3c8bc9fd
7
+ data.tar.gz: 5bf94989849a17a47c833a6599ca029123fdf1b96cb704baab1d028fcfd9ce6efb09b1ed7b50285bc41fce5c05a78e70ceeab36367f53e14631a77c892162559
data/.rspec ADDED
@@ -0,0 +1,3 @@
1
+ --format documentation
2
+ --color
3
+ --require spec_helper
data/.standard.yml ADDED
@@ -0,0 +1,3 @@
1
+ # For available configuration options, see:
2
+ # https://github.com/standardrb/standard
3
+ ruby_version: 3.3
data/LICENSE.txt ADDED
@@ -0,0 +1,21 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2024 Tëma Bolshakov
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in
13
+ all copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21
+ THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,178 @@
1
+ # ⚙️ConfigX
2
+
3
+ ConfigX is a simple configuration library that you can use with your application or libraries.
4
+
5
+ ConfigX is NOT that kind of library that allows you configuring any Ruby object, instead
6
+ it takes a different approach. It reads configuration from YAML files and environment variables
7
+ and load it into a ruby object. It's highly influenced by the [config] gem, but it does
8
+ not define a global objects and allows you having multiple independent configurations.
9
+
10
+ ## Installation
11
+
12
+ Install the gem and add to the application's Gemfile by executing:
13
+
14
+ $ bundle add configx
15
+
16
+ If bundler is not being used to manage dependencies, install the gem by executing:
17
+
18
+ $ gem install configx
19
+
20
+ ## Usage
21
+
22
+ Start using the library as simple as loading configuration from default locations:
23
+
24
+ ```ruby
25
+ config = ConfigX.load
26
+ ```
27
+
28
+ It loads configuration from the following locations in the specified order:
29
+
30
+ 1. `config/settings.yml`
31
+ 2. `config/settings/production.yml`
32
+ 3. `config/settings.local.yml`
33
+ 4. `config/settings/production.local.yml`
34
+ 5. Environment variables
35
+
36
+ All the configuration source are merged an intuitive way. For instance,
37
+
38
+ * **config/settings.yml**
39
+
40
+ ```yaml
41
+ ---
42
+ api:
43
+ enabled: false
44
+ endpoint: https://example.com
45
+ access_token:
46
+ ```
47
+
48
+ * **config/settings/production.yml**
49
+
50
+ ```yaml
51
+ ---
52
+ api:
53
+ enabled: true
54
+ ```
55
+
56
+ * Environment Variables
57
+
58
+ ```
59
+ export SETTINGS__API__ACCESS_TOKEN=foobar
60
+ ```
61
+
62
+ The resulting configuration will be:
63
+
64
+ ```ruby
65
+ config = ConfigX.load
66
+ config.api.enabled # => true
67
+ config.api.endpoint # => "https://example.com"
68
+ config.api.pretty_print # => "foobar"
69
+ ```
70
+
71
+ ### Customizing Configuration
72
+
73
+ You can customize the configuration by passing optional arguments to the `load` method:
74
+
75
+ ```ruby
76
+ ConfigX.load(
77
+ "development",
78
+ dir_name: 'settings',
79
+ file_name: 'settings',
80
+ config_root: 'config',
81
+ env_prefix: 'SETTINGS',
82
+ env_separator: '__'
83
+ )
84
+ ```
85
+
86
+ The first four options, `env` (positional), `dir_name`, `file_name`, and `config_root` are used to specify
87
+ the configuration files to read:
88
+
89
+ 1. `{config_root}/{file_name}.yml`
90
+ 2. `{config_root}/{file_name}/{env}.yml`
91
+ 3. `{config_root}/{file_name}.local.yml`
92
+ 4. `{config_root}/{file_name}/{env}.local.yml`
93
+
94
+
95
+ The `env_prefix` and `env_separator` options are used to specify how the environment variables should be constructed. In
96
+ the above example, they start from `SETTINGS` and use `__` as a separator.
97
+
98
+ For instance, the following environment variable:
99
+
100
+ ```
101
+ export SETTINGS__API__ACCESS_TOKEN=foobar
102
+ ```
103
+
104
+ corresponds to the following configuration:
105
+
106
+ ```yaml
107
+ ---
108
+ api:
109
+ access_token: foobar
110
+ ```
111
+
112
+ You can also pass boolean value to environment variables using convenient YAML syntax:
113
+
114
+ ```sh
115
+ export SETTINGS__API__ENABLED=true
116
+ export SETTINGS__API__ENABLED=false
117
+ export SETTINGS__API__ENABLED=on
118
+ export SETTINGS__API__ENABLED=off
119
+ ```
120
+
121
+ Environment variables have the highest priority and override the values from the configuration files.
122
+
123
+ ### Builder Interface
124
+
125
+ When you don't need to load configuration from the predefined default locations, you can use the builder interface
126
+ which enables you to load configuration from any source:
127
+
128
+ 1. Plain ruby Hash
129
+
130
+ ```ruby
131
+ config = ConfigX.builder
132
+ .add_source({api: {enabled: true}})
133
+ .load
134
+
135
+ config.api.enabled # => true
136
+ ```
137
+
138
+ 2. YAML file
139
+
140
+ ```ruby
141
+ config = ConfigX.builder
142
+ .add_source('config/settings.yml')
143
+ .load
144
+ ```
145
+
146
+ 3. Environment variables
147
+
148
+ ```ruby
149
+ config = ConfigX.builder
150
+ .add_source(ENV, prefix: "SETTINGS", separator: "__")
151
+ .load
152
+ ```
153
+
154
+ You can also use the builder interface to load configuration from multiple sources:
155
+
156
+ ```ruby
157
+ config = ConfigX.builder
158
+ .add_source({api: {enabled: true}})
159
+ .add_source('config/settings.yml')
160
+ .add_source(ENV, prefix: "SETTINGS", separator: "__")
161
+ .load
162
+ ```
163
+
164
+ ## Development
165
+
166
+ 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
+
168
+ To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and the created tag, and push the `.gem` file to [rubygems.org](https://rubygems.org).
169
+
170
+ ## Contributing
171
+
172
+ Bug reports and pull requests are welcome on GitHub at https://github.com/bolshakov/configx.
173
+
174
+ ## License
175
+
176
+ The gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).
177
+
178
+ [config]: https://rubygems.org/gems/config
data/Rakefile ADDED
@@ -0,0 +1,10 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "bundler/gem_tasks"
4
+ require "rspec/core/rake_task"
5
+
6
+ RSpec::Core::RakeTask.new(:spec)
7
+
8
+ require "standard/rake"
9
+
10
+ task default: %i[spec standard]
data/Steepfile ADDED
@@ -0,0 +1,31 @@
1
+ # D = Steep::Diagnostic
2
+ #
3
+ target :lib do
4
+ signature "sig"
5
+
6
+ check "lib" # Directory name
7
+ # check "Gemfile" # File name
8
+ # check "app/models/**/*.rb" # Glob
9
+ # # ignore "lib/templates/*.rb"
10
+ #
11
+ library "yaml"
12
+ library "pathname"
13
+
14
+ # library "strong_json" # Gems
15
+ #
16
+ # # configure_code_diagnostics(D::Ruby.default) # `default` diagnostics setting (applies by default)
17
+ # # configure_code_diagnostics(D::Ruby.strict) # `strict` diagnostics setting
18
+ # # configure_code_diagnostics(D::Ruby.lenient) # `lenient` diagnostics setting
19
+ # # configure_code_diagnostics(D::Ruby.silent) # `silent` diagnostics setting
20
+ # # configure_code_diagnostics do |hash| # You can setup everything yourself
21
+ # # hash[D::Ruby::NoMethod] = :information
22
+ # # end
23
+ end
24
+
25
+ # target :test do
26
+ # signature "sig", "sig-private"
27
+ #
28
+ # check "test"
29
+ #
30
+ # # library "pathname" # Standard libraries
31
+ # end
@@ -0,0 +1,57 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "deep_merge/core"
4
+
5
+ module ConfigX
6
+ class Builder
7
+ class << self
8
+ def source(source, **args)
9
+ case source
10
+ in Source then source
11
+ in Hash then HashSource.new(source)
12
+ in String then FileSource.new(source)
13
+ in Pathname then FileSource.new(source)
14
+ in ENV then EnvSource.new(ENV, **args)
15
+ end
16
+ end
17
+
18
+ # @see #initialize
19
+ def load(...)
20
+ new(...).load
21
+ end
22
+ end
23
+
24
+ # @example
25
+ # ConfigX.new("production").load
26
+ # ConfigX.new.load
27
+ #
28
+ def initialize
29
+ @sources = []
30
+ end
31
+
32
+ attr_reader :sources
33
+
34
+ def add_source(source, **args)
35
+ sources << self.class.source(source, **args)
36
+ self
37
+ end
38
+
39
+ # Loads config in the following order:
40
+ # 1. Reads default config
41
+ # 2. Reads all the config files provided in the order
42
+ # 3. Reads environment variables
43
+ def load
44
+ Config.new(read_from_sources)
45
+ end
46
+
47
+ def ==(other)
48
+ other.is_a?(self.class) && other.sources == sources
49
+ end
50
+
51
+ private def read_from_sources
52
+ sources.each_with_object({}) do |source, config|
53
+ DeepMerge.deep_merge!(source.load, config, overwrite_arrays: true)
54
+ end
55
+ end
56
+ end
57
+ end
@@ -0,0 +1,44 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "ostruct"
4
+ require "deep_merge/core"
5
+
6
+ module ConfigX
7
+ class Config < OpenStruct
8
+ def initialize(members)
9
+ super()
10
+
11
+ members.each do |key, value|
12
+ raise ArgumentError, "option keys should be strings" unless key.respond_to?(:to_s)
13
+
14
+ key = key.to_s
15
+
16
+ if value.is_a?(Hash)
17
+ value = self.class.new(value)
18
+ elsif value.is_a?(Array)
19
+ value = value.map do |element|
20
+ element.is_a?(Hash) ? self.class.new(element) : element
21
+ end
22
+ end
23
+
24
+ self[key] = value.freeze
25
+ end
26
+
27
+ freeze
28
+ end
29
+
30
+ def with_fallback(fallback)
31
+ DeepMerge.deep_merge!(
32
+ to_h,
33
+ fallback.to_h,
34
+ overwrite_arrays: true
35
+ ).then { Config.new(_1) }
36
+ end
37
+
38
+ def to_h
39
+ each_pair.each_with_object({}) do |(key, value), hash|
40
+ hash[key] = value.is_a?(Config) ? value.to_h : value
41
+ end
42
+ end
43
+ end
44
+ end
@@ -0,0 +1,113 @@
1
+ # frozen_string_literal: true
2
+
3
+ module ConfigX
4
+ # This class is responsible for loading configuration settings for an application.
5
+ # It follows a specific order in loading these settings:
6
+ # 1. Reads default config
7
+ # 2. Reads all the config files provided in the order
8
+ # 3. Reads environment variables
9
+ class ConfigFactory
10
+ class << self
11
+ # Default environment variable prefix
12
+ def default_env_prefix = "SETTINGS"
13
+
14
+ # Default environment variable separator
15
+ def default_env_separator = "__"
16
+
17
+ # Default directory name for environment-specific settings
18
+ def default_dir_name = "settings"
19
+
20
+ # Default environment name
21
+ def default_env = "production"
22
+
23
+ # Default config file name
24
+ def default_file_name = "settings"
25
+
26
+ # Default root directory for configuration
27
+ def default_config_root = "config"
28
+
29
+ # Load method to initialize and load the configuration
30
+ def load(...) = new(...).load
31
+ end
32
+
33
+ # Initializes a new instance of the ConfigFactory class.
34
+ # @param env [String] the environment name.
35
+ # @param env_prefix [String] the prefix for environment variables.
36
+ # @param env_separator [String] the separator for environment variables.
37
+ # @param dir_name [String] the directory name for settings.
38
+ # @param file_name [String] the file name for settings.
39
+ # @param config_root [String] the root directory for configuration.
40
+ def initialize(
41
+ env = self.class.default_env,
42
+ env_prefix: self.class.default_env_prefix,
43
+ env_separator: self.class.default_env_separator,
44
+ dir_name: self.class.default_dir_name,
45
+ file_name: self.class.default_file_name,
46
+ config_root: self.class.default_config_root
47
+ )
48
+ @env = env
49
+ @env_prefix = env_prefix
50
+ @env_separator = env_separator
51
+ @dir_name = dir_name
52
+ @file_name = file_name
53
+ @config_root = config_root
54
+ end
55
+
56
+ # Loads the configuration from the sources and additional sources.
57
+ # @param additional_sources [Array] additional sources to load configuration from.
58
+ # @return [Config] the loaded configuration.
59
+ def load(*additional_sources)
60
+ (sources + additional_sources)
61
+ .reduce(Builder.new) { |builder, source| builder.add_source(source) }
62
+ .load
63
+ end
64
+
65
+ private
66
+
67
+ # Returns the sources from which to load the configuration.
68
+ # @return [Array] the sources.
69
+ def sources
70
+ [
71
+ *setting_files,
72
+ Builder.source(ENV, prefix: env_prefix, separator: env_separator)
73
+ ]
74
+ end
75
+
76
+ # Returns the setting files.
77
+ # @return [Array] the setting files.
78
+ def setting_files
79
+ [
80
+ File.join(config_root, "#{file_name}.yml"),
81
+ File.join(config_root, dir_name, "#{env}.yml"),
82
+ *local_setting_files
83
+ ].freeze
84
+ end
85
+
86
+ # Returns the local setting files.
87
+ # @return [Array] the local setting files.
88
+ def local_setting_files
89
+ [
90
+ (File.join(config_root, "#{file_name}.local.yml") if env != "test"),
91
+ File.join(config_root, dir_name, "#{env}.local.yml")
92
+ ].compact
93
+ end
94
+
95
+ # The root directory for configuration.
96
+ attr_reader :config_root
97
+
98
+ # The directory name for environment-specific settings.
99
+ attr_reader :dir_name
100
+
101
+ # The environment name.
102
+ attr_reader :env
103
+
104
+ # The prefix for environment variables.
105
+ attr_reader :env_prefix
106
+
107
+ # The separator for environment variables.
108
+ attr_reader :env_separator
109
+
110
+ # The file name for settings.
111
+ attr_reader :file_name
112
+ end
113
+ end
@@ -0,0 +1,36 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "deep_merge/core"
4
+ require "yaml"
5
+
6
+ module ConfigX
7
+ class EnvSource < HashSource
8
+ def initialize(env, prefix:, separator:)
9
+ @env = env
10
+ @prefix = prefix
11
+ @separator = separator
12
+ end
13
+
14
+ def ==(other)
15
+ other.is_a?(self.class) &&
16
+ source == other.source &&
17
+ prefix == other.prefix &&
18
+ separator == other.separator
19
+ end
20
+
21
+ protected
22
+
23
+ def source
24
+ env.each_with_object({}) do |(key, value), config|
25
+ next unless key.start_with?(prefix + separator)
26
+
27
+ Array(key.split(separator)[1..])
28
+ .reverse_each
29
+ .reduce(YAML.load(value)) { |acc, k| {k.downcase => acc} }
30
+ .tap { DeepMerge.deep_merge!(_1, config) }
31
+ end
32
+ end
33
+
34
+ attr_reader :env, :prefix, :separator
35
+ end
36
+ end
@@ -0,0 +1,27 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "yaml"
4
+
5
+ module ConfigX
6
+ class FileSource < Source
7
+ def initialize(path)
8
+ @path = path
9
+ end
10
+
11
+ def load
12
+ if path && File.exist?(path)
13
+ YamlSource.new(File.read(path.to_s)).load
14
+ else
15
+ {}
16
+ end
17
+ end
18
+
19
+ def ==(other)
20
+ other.is_a?(self.class) && other.path == path
21
+ end
22
+
23
+ protected
24
+
25
+ attr_reader :path
26
+ end
27
+ end
@@ -0,0 +1,20 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "yaml"
4
+
5
+ module ConfigX
6
+ class HashSource < Source
7
+ attr_reader :source
8
+ protected :source
9
+
10
+ def initialize(source)
11
+ @source = source
12
+ end
13
+
14
+ def load = source
15
+
16
+ def ==(other)
17
+ other.is_a?(self.class) && source == other.source
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,7 @@
1
+ # frozen_string_literal: true
2
+
3
+ module ConfigX
4
+ class Source
5
+ def load = raise NotImplementedError
6
+ end
7
+ end
@@ -0,0 +1,5 @@
1
+ # frozen_string_literal: true
2
+
3
+ module ConfigX
4
+ VERSION = "0.1.0"
5
+ end
@@ -0,0 +1,19 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "yaml"
4
+
5
+ module ConfigX
6
+ class YamlSource < Source
7
+ def initialize(source)
8
+ @source = source
9
+ end
10
+
11
+ def load
12
+ YAML.load(source) || {}
13
+ end
14
+
15
+ private
16
+
17
+ attr_reader :source
18
+ end
19
+ end
data/lib/config_x.rb ADDED
@@ -0,0 +1,29 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "zeitwerk"
4
+ require_relative "config_x/version"
5
+
6
+ module ConfigX
7
+ class << self
8
+ # @api private
9
+ def loader
10
+ @loader ||= Zeitwerk::Loader.for_gem.tap do |loader|
11
+ loader.ignore("#{__dir__}/configx.rb")
12
+ end
13
+ end
14
+
15
+ def load(...) = ConfigFactory.load(...)
16
+
17
+ def builder = Builder.new
18
+
19
+ # Loads config from the given source
20
+ # @example
21
+ # config = ConfigX.from({api: {endpoint: "http://example.com", enabled: true}})
22
+ # config.api.endpoint # => "http://example.com"
23
+ # config.api.enabled # => true
24
+ #
25
+ def from(source, **args) = builder.add_source(source, **args).load
26
+ end
27
+ end
28
+
29
+ ConfigX.loader.setup
data/lib/configx.rb ADDED
@@ -0,0 +1,3 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "config_x"
@@ -0,0 +1,21 @@
1
+ module ConfigX
2
+ class Builder
3
+ type source = Source | Hash[untyped, untyped] | String | Pathname | Object
4
+
5
+ def self.load: -> Config
6
+ def self.source: [T < Source] (source, **untyped) -> T
7
+
8
+ def initialize: -> void
9
+
10
+ attr_reader sources: Array[Source]
11
+
12
+
13
+ def add_source: (source, **untyped) -> self
14
+
15
+ def load: -> Config
16
+
17
+ private
18
+
19
+ def read_from_sources: -> Hash[untyped, untyped]
20
+ end
21
+ end
@@ -0,0 +1,13 @@
1
+ module ConfigX
2
+ class Config
3
+ def initialize: (Hash[untyped, untyped]) -> void
4
+
5
+ def to_h: -> Hash[untyped, untyped]
6
+
7
+ def with_fallback: (Config) -> Config
8
+
9
+ def each_pair: -> Enumerable[[untyped, untyped]]
10
+
11
+ def []=: (untyped, untyped) -> untyped
12
+ end
13
+ end
@@ -0,0 +1,55 @@
1
+ module ConfigX
2
+ class ConfigFactory
3
+ def self.default_config_root: -> String
4
+
5
+ def self.default_dir_name: -> String
6
+
7
+ def self.default_env_prefix: -> String
8
+
9
+ def self.default_env_separator: -> String
10
+
11
+ def self.default_env: -> String
12
+
13
+ def self.default_file_name: -> String
14
+
15
+ def self.load: (
16
+ String env,
17
+ env_prefix: String,
18
+ env_separator: String,
19
+ dir_name: String,
20
+ file_name: String,
21
+ config_root: String
22
+ ) -> Config
23
+
24
+ def initialize: (
25
+ String env,
26
+ env_prefix: String,
27
+ env_separator: String,
28
+ dir_name: String,
29
+ file_name: String,
30
+ config_root: String
31
+ ) -> void
32
+
33
+ def load: -> Config
34
+
35
+ private
36
+
37
+ def local_setting_files: -> Array[String]
38
+
39
+ def setting_files: -> Array[String]
40
+
41
+ attr_reader config_root: String
42
+
43
+ attr_reader dir_name: String
44
+
45
+ attr_reader env_prefix: String
46
+
47
+ attr_reader env_separator: String
48
+
49
+ attr_reader env: String
50
+
51
+ attr_reader file_name: String
52
+
53
+ def sources: -> Array[Builder::source]
54
+ end
55
+ end
@@ -0,0 +1,11 @@
1
+ module ConfigX
2
+ class EnvSource < HashSource
3
+ type env = Hash[String, String]
4
+
5
+ def initialize: (env, prefix: String, separator: String) -> void
6
+
7
+ attr_reader env: env
8
+ attr_reader prefix: String
9
+ attr_reader separator: String
10
+ end
11
+ end
@@ -0,0 +1,7 @@
1
+ module ConfigX
2
+ class FileSource < Source
3
+ def initialize: (String | Pathname) -> void
4
+
5
+ attr_reader path: String | Pathname
6
+ end
7
+ end
@@ -0,0 +1,8 @@
1
+
2
+ module ConfigX
3
+ class HashSource < Source
4
+ def initialize: (Source::config_hash) -> void
5
+
6
+ attr_reader source: Source::config_hash
7
+ end
8
+ end
@@ -0,0 +1,8 @@
1
+
2
+ module ConfigX
3
+ class Source
4
+ type config_hash = Hash[untyped, untyped]
5
+
6
+ def load: -> config_hash
7
+ end
8
+ end
@@ -0,0 +1,10 @@
1
+
2
+ module ConfigX
3
+ class YamlSource < Source
4
+ def initialize: (String) -> void
5
+
6
+ private
7
+
8
+ attr_reader source: String
9
+ end
10
+ end
data/sig/config_x.rbs ADDED
@@ -0,0 +1,18 @@
1
+ module ConfigX
2
+ VERSION: String
3
+
4
+ def self.builder: -> Builder
5
+ def self.from: (Builder::source, **untyped) -> Config
6
+
7
+ def self.load: (
8
+ String env,
9
+ env_prefix: String,
10
+ env_separator: String,
11
+ dir_name: String,
12
+ file_name: String,
13
+ config_root: String
14
+ ) -> Config
15
+
16
+
17
+ def self.loader: -> Zeitwerk::Loader
18
+ end
@@ -0,0 +1,7 @@
1
+ module DeepMerge
2
+ def self.deep_merge!: [K1, V1, K2, V2] (
3
+ Hash[K1, V1] source,
4
+ Hash[K2, V2] destination,
5
+ ?overwrite_arrays: bool
6
+ ) -> Hash[K1 | K2, V1 | V2]
7
+ end
data/sig/shims/env.rbs ADDED
@@ -0,0 +1,17 @@
1
+ # module ENV
2
+ # extend Enumerable[[String, String]]
3
+ #
4
+ # # def self.[]: (::String) -> (::String | nil)
5
+ # # def self.[]=: (::String, ::String) -> ::String
6
+ # # def self.fetch: [A] (key: ::String, default: A) -> (A | ::String)
7
+ # # def self.fetch: (key: ::String) ?{ ::String -> A } -> (::String | A)
8
+ # # def self.delete: (::String) -> (::String | nil)
9
+ # # def self.key?: (::String) -> bool
10
+ # # def self.clear: () -> void
11
+ # # def self.to_h: () -> Hash[::String, ::String]
12
+ # # def self.each: () { (::String, ::String) -> void } -> void
13
+ # # def self.each_key: () { (::String) -> void } -> void
14
+ # # def self.each_value: () { (::String) -> void } -> void
15
+ # # def self.keys: () -> Array[::String]
16
+ # # def self.values: () -> Array[::String]
17
+ # end
@@ -0,0 +1,8 @@
1
+ module Zeitwerk
2
+ class Loader
3
+ def self.for_gem: -> instance
4
+
5
+ def ignore: (String) -> void
6
+ def setup: -> void
7
+ end
8
+ end
metadata ADDED
@@ -0,0 +1,105 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: configx
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Tëma Bolshakov
8
+ autorequire:
9
+ bindir: exe
10
+ cert_chain: []
11
+ date: 2024-06-05 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: deep_merge
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ">="
18
+ - !ruby/object:Gem::Version
19
+ version: '0'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ">="
25
+ - !ruby/object:Gem::Version
26
+ version: '0'
27
+ - !ruby/object:Gem::Dependency
28
+ name: zeitwerk
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: '0'
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ">="
39
+ - !ruby/object:Gem::Version
40
+ version: '0'
41
+ description: |
42
+ ConfigX is a Ruby library for configuration management. It provides battle-tested defaults
43
+ and an intuitive interface for managing settings from YAML files and environment variables.
44
+ It also offers flexibility for developers to build their own configurations.
45
+ email:
46
+ - tema@bolshakov.dev
47
+ executables: []
48
+ extensions: []
49
+ extra_rdoc_files: []
50
+ files:
51
+ - ".rspec"
52
+ - ".standard.yml"
53
+ - LICENSE.txt
54
+ - README.md
55
+ - Rakefile
56
+ - Steepfile
57
+ - lib/config_x.rb
58
+ - lib/config_x/builder.rb
59
+ - lib/config_x/config.rb
60
+ - lib/config_x/config_factory.rb
61
+ - lib/config_x/env_source.rb
62
+ - lib/config_x/file_source.rb
63
+ - lib/config_x/hash_source.rb
64
+ - lib/config_x/source.rb
65
+ - lib/config_x/version.rb
66
+ - lib/config_x/yaml_source.rb
67
+ - lib/configx.rb
68
+ - sig/config_x.rbs
69
+ - sig/config_x/builder.rbs
70
+ - sig/config_x/config.rbs
71
+ - sig/config_x/config_factory.rbs
72
+ - sig/config_x/env_source.rbs
73
+ - sig/config_x/file_source.rbs
74
+ - sig/config_x/hash_source.rbs
75
+ - sig/config_x/source.rbs
76
+ - sig/config_x/yaml_source.rbs
77
+ - sig/shims/deep_merge.rbs
78
+ - sig/shims/env.rbs
79
+ - sig/shims/zeitwerk/loader.rbs
80
+ homepage: https://github.com/bolshakov/configx
81
+ licenses:
82
+ - MIT
83
+ metadata:
84
+ homepage_uri: https://github.com/bolshakov/configx
85
+ source_code_uri: https://github.com/bolshakov/configx
86
+ post_install_message:
87
+ rdoc_options: []
88
+ require_paths:
89
+ - lib
90
+ required_ruby_version: !ruby/object:Gem::Requirement
91
+ requirements:
92
+ - - ">="
93
+ - !ruby/object:Gem::Version
94
+ version: 3.0.0
95
+ required_rubygems_version: !ruby/object:Gem::Requirement
96
+ requirements:
97
+ - - ">="
98
+ - !ruby/object:Gem::Version
99
+ version: '0'
100
+ requirements: []
101
+ rubygems_version: 3.5.10
102
+ signing_key:
103
+ specification_version: 4
104
+ summary: Configuration simplified
105
+ test_files: []