configx 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
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: []