runger_config 4.0.0 → 5.0.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.
Files changed (43) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +4 -0
  3. data/lib/generators/runger/app_config/app_config_generator.rb +6 -10
  4. data/lib/generators/runger/config/config_generator.rb +44 -41
  5. data/lib/generators/runger/install/install_generator.rb +35 -37
  6. data/lib/runger/auto_cast.rb +3 -3
  7. data/lib/runger/config.rb +114 -94
  8. data/lib/runger/dynamic_config.rb +21 -23
  9. data/lib/runger/ejson_parser.rb +24 -24
  10. data/lib/runger/env.rb +50 -52
  11. data/lib/runger/ext/deep_dup.rb +33 -36
  12. data/lib/runger/ext/deep_freeze.rb +28 -32
  13. data/lib/runger/ext/flatten_names.rb +23 -27
  14. data/lib/runger/ext/hash.rb +26 -29
  15. data/lib/runger/ext/string_constantize.rb +12 -15
  16. data/lib/runger/loaders/base.rb +11 -15
  17. data/lib/runger/loaders/doppler.rb +38 -42
  18. data/lib/runger/loaders/ejson.rb +65 -63
  19. data/lib/runger/loaders/env.rb +6 -10
  20. data/lib/runger/loaders/yaml.rb +69 -66
  21. data/lib/runger/loaders.rb +69 -71
  22. data/lib/runger/option_parser_builder.rb +16 -18
  23. data/lib/runger/optparse_config.rb +11 -10
  24. data/lib/runger/rails/autoload.rb +24 -26
  25. data/lib/runger/rails/config.rb +13 -17
  26. data/lib/runger/rails/loaders/credentials.rb +53 -57
  27. data/lib/runger/rails/loaders/secrets.rb +21 -25
  28. data/lib/runger/rails/loaders/yaml.rb +1 -6
  29. data/lib/runger/rails/loaders.rb +3 -3
  30. data/lib/runger/rails/settings.rb +49 -49
  31. data/lib/runger/rails.rb +9 -11
  32. data/lib/runger/railtie.rb +3 -2
  33. data/lib/runger/rbs.rb +29 -29
  34. data/lib/runger/settings.rb +82 -84
  35. data/lib/runger/testing/helpers.rb +26 -28
  36. data/lib/runger/testing.rb +2 -2
  37. data/lib/runger/tracing.rb +143 -136
  38. data/lib/runger/type_casting.rb +16 -11
  39. data/lib/runger/utils/which.rb +10 -12
  40. data/lib/runger/version.rb +1 -1
  41. data/lib/runger.rb +1 -1
  42. data/lib/runger_config.rb +34 -27
  43. metadata +18 -18
@@ -1,31 +1,29 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- module Runger
4
- # Adds ability to generate anonymous (class-less) config dynamicly
5
- # (like Rails.application.config_for but using more data sources).
6
- module DynamicConfig
7
- module ClassMethods
8
- # Load config as Hash by any name
9
- #
10
- # Example:
11
- #
12
- # my_config = Runger::Config.for(:my_app)
13
- # # will load data from config/my_app.yml, secrets.my_app, ENV["MY_APP_*"]
14
- #
15
- def for(name, auto_cast: true, **options)
16
- config = allocate
17
- options[:env_prefix] ||= name.to_s.upcase
18
- options[:config_path] ||= config.resolve_config_path(name, options[:env_prefix])
3
+ # Adds ability to generate anonymous (class-less) config dynamicly
4
+ # (like Rails.application.config_for but using more data sources).
5
+ module Runger::DynamicConfig
6
+ module ClassMethods
7
+ # Load config as Hash by any name
8
+ #
9
+ # Example:
10
+ #
11
+ # my_config = Runger::Config.for(:my_app)
12
+ # # will load data from config/my_app.yml, secrets.my_app, ENV["MY_APP_*"]
13
+ #
14
+ def for(name, auto_cast: true, **options)
15
+ config = allocate
16
+ options[:env_prefix] ||= name.to_s.upcase
17
+ options[:config_path] ||= config.resolve_config_path(name, options[:env_prefix])
19
18
 
20
- raw_config = config.load_from_sources(new_empty_config, name:, **options)
21
- return raw_config unless auto_cast
19
+ raw_config = config.load_from_sources(new_empty_config, name:, **options)
20
+ return raw_config unless auto_cast
22
21
 
23
- AutoCast.call(raw_config)
24
- end
22
+ ::Runger::AutoCast.call(raw_config)
25
23
  end
24
+ end
26
25
 
27
- def self.included(base)
28
- base.extend ClassMethods
29
- end
26
+ def self.included(base)
27
+ base.extend(ClassMethods)
30
28
  end
31
29
  end
@@ -1,39 +1,39 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require "open3"
4
- require "runger/ext/hash"
3
+ require 'open3'
4
+ require 'runger/ext/hash'
5
5
 
6
6
  using Runger::Ext::Hash
7
7
 
8
- module Runger
9
- class EJSONParser
10
- attr_reader :bin_path
8
+ class Runger::EJSONParser
9
+ attr_reader :bin_path
11
10
 
12
- def initialize(bin_path = "ejson")
13
- @bin_path = bin_path
14
- end
11
+ def initialize(bin_path = 'ejson')
12
+ @bin_path = bin_path
13
+ end
15
14
 
16
- def call(file_path)
17
- return unless File.exist?(file_path)
15
+ def call(file_path)
16
+ return unless File.exist?(file_path)
18
17
 
19
- raw_content = nil
18
+ raw_content = nil
20
19
 
21
- stdout, stderr, status = Open3.capture3("#{bin_path} decrypt #{file_path}")
20
+ stdout, stderr, status = Open3.capture3("#{bin_path} decrypt #{file_path}")
22
21
 
23
- if status.success?
24
- raw_content = JSON.parse(stdout.chomp)
25
- else
26
- Kernel.warn "Failed to decrypt #{file_path}: #{stderr}"
27
- end
22
+ if status.success?
23
+ raw_content = JSON.parse(stdout.chomp)
24
+ else
25
+ Kernel.warn("Failed to decrypt #{file_path}: #{stderr}")
26
+ end
28
27
 
29
- return unless raw_content
28
+ return unless raw_content
30
29
 
31
- raw_content.deep_transform_keys do |key|
32
- if key[0] == "_"
33
- key[1..]
34
- else
35
- key
36
- end
30
+ raw_content.deep_transform_keys do |key|
31
+ if key[0] == '_'
32
+ # rubocop:disable Performance/ArraySemiInfiniteRangeSlice
33
+ key[1..]
34
+ # rubocop:enable Performance/ArraySemiInfiniteRangeSlice
35
+ else
36
+ key
37
37
  end
38
38
  end
39
39
  end
data/lib/runger/env.rb CHANGED
@@ -1,72 +1,70 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- module Runger
4
- # Parses environment variables and provides
5
- # method-like access
6
- class Env
7
- using Runger::Ext::DeepDup
8
- using Runger::Ext::Hash
9
-
10
- class << self
11
- def from_hash(hash, prefix: nil, memo: {})
12
- hash.each do |key, value|
13
- prefix_with_key = (prefix && !prefix.empty?) ? "#{prefix}_#{key.to_s.upcase}" : key.to_s.upcase
14
-
15
- if value.is_a?(Hash)
16
- from_hash(value, prefix: "#{prefix_with_key}_", memo:)
17
- else
18
- memo[prefix_with_key] = value.to_s
19
- end
3
+ # Parses environment variables and provides
4
+ # method-like access
5
+ class Runger::Env
6
+ using Runger::Ext::DeepDup
7
+ using Runger::Ext::Hash
8
+
9
+ class << self
10
+ def from_hash(hash, prefix: nil, memo: {})
11
+ hash.each do |key, value|
12
+ prefix_with_key = (prefix && !prefix.empty?) ? "#{prefix}_#{key.to_s.upcase}" : key.to_s.upcase
13
+
14
+ if value.is_a?(Hash)
15
+ from_hash(value, prefix: "#{prefix_with_key}_", memo:)
16
+ else
17
+ memo[prefix_with_key] = value.to_s
20
18
  end
21
-
22
- memo
23
19
  end
20
+
21
+ memo
24
22
  end
23
+ end
25
24
 
26
- include Tracing
25
+ include ::Runger::Tracing
27
26
 
28
- attr_reader :data, :traces, :type_cast, :env_container
27
+ attr_reader :data, :traces, :type_cast, :env_container
29
28
 
30
- def initialize(type_cast: AutoCast, env_container: ENV)
31
- @type_cast = type_cast
32
- @data = {}
33
- @traces = {}
34
- @env_container = env_container
35
- end
36
-
37
- def clear
38
- data.clear
39
- traces.clear
40
- end
29
+ def initialize(type_cast: ::Runger::AutoCast, env_container: ENV)
30
+ @type_cast = type_cast
31
+ @data = {}
32
+ @traces = {}
33
+ @env_container = env_container
34
+ end
41
35
 
42
- def fetch(prefix)
43
- return data[prefix].deep_dup if data.key?(prefix)
36
+ def clear
37
+ data.clear
38
+ traces.clear
39
+ end
44
40
 
45
- Tracing.capture do
46
- data[prefix] = parse_env(prefix)
47
- end.then do |trace|
48
- traces[prefix] = trace
49
- end
41
+ def fetch(prefix)
42
+ return data[prefix].deep_dup if data.key?(prefix)
50
43
 
51
- data[prefix].deep_dup
44
+ ::Runger::Tracing.capture do
45
+ data[prefix] = parse_env(prefix)
46
+ end.then do |trace|
47
+ traces[prefix] = trace
52
48
  end
53
49
 
54
- def fetch_with_trace(prefix)
55
- [fetch(prefix), traces[prefix]]
56
- end
50
+ data[prefix].deep_dup
51
+ end
57
52
 
58
- private
53
+ def fetch_with_trace(prefix)
54
+ [fetch(prefix), traces[prefix]]
55
+ end
59
56
 
60
- def parse_env(prefix)
61
- match_prefix = prefix.empty? ? prefix : "#{prefix}_"
62
- env_container.each_pair.with_object({}) do |(key, val), data|
63
- next unless key.start_with?(match_prefix)
57
+ private
64
58
 
65
- path = key.sub(/^#{match_prefix}/, "").downcase
59
+ def parse_env(prefix)
60
+ match_prefix = prefix.empty? ? prefix : "#{prefix}_"
61
+ env_container.each_pair.with_object({}) do |(key, val), data|
62
+ next unless key.start_with?(match_prefix)
66
63
 
67
- paths = path.split("__")
68
- trace!(:env, *paths, key:) { data.bury(type_cast.call(val), *paths) }
69
- end
64
+ path = key.sub(/^#{match_prefix}/, '').downcase
65
+
66
+ paths = path.split('__')
67
+ trace!(:env, *paths, key:) { data.bury(type_cast.call(val), *paths) }
70
68
  end
71
69
  end
72
70
  end
@@ -1,48 +1,45 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- module Runger
4
- module Ext
5
- # Extend Object through refinements
6
- module DeepDup
7
- refine ::Hash do
8
- # Based on ActiveSupport http://api.rubyonrails.org/classes/Hash.html#method-i-deep_dup
9
- def deep_dup
10
- each_with_object(dup) do |(key, value), hash|
11
- hash[key] = if value.is_a?(::Hash) || value.is_a?(::Array)
12
- value.deep_dup
13
- else
14
- value
15
- end
3
+ # Extend Object through refinements
4
+ module Runger::Ext::DeepDup
5
+ refine ::Hash do
6
+ # Based on ActiveSupport http://api.rubyonrails.org/classes/Hash.html#method-i-deep_dup
7
+ def deep_dup
8
+ each_with_object(dup) do |(key, value), hash|
9
+ hash[key] =
10
+ if value.is_a?(::Hash) || value.is_a?(::Array)
11
+ value.deep_dup
12
+ else
13
+ value
16
14
  end
17
- end
18
- end
19
-
20
- refine ::Array do
21
- # From ActiveSupport http://api.rubyonrails.org/classes/Array.html#method-i-deep_dup
22
- def deep_dup
23
- map do |value|
24
- if value.is_a?(::Hash) || value.is_a?(::Array)
25
- value.deep_dup
26
- else
27
- value
28
- end
29
- end
30
- end
31
15
  end
16
+ end
17
+ end
32
18
 
33
- refine ::Object do
34
- def deep_dup
35
- dup
19
+ refine ::Array do
20
+ # From ActiveSupport http://api.rubyonrails.org/classes/Array.html#method-i-deep_dup
21
+ def deep_dup
22
+ map do |value|
23
+ if value.is_a?(::Hash) || value.is_a?(::Array)
24
+ value.deep_dup
25
+ else
26
+ value
36
27
  end
37
28
  end
29
+ end
30
+ end
38
31
 
39
- refine ::Module do
40
- def deep_dup
41
- self
42
- end
43
- end
32
+ refine ::Object do
33
+ def deep_dup
34
+ dup
35
+ end
36
+ end
44
37
 
45
- using self
38
+ refine ::Module do
39
+ def deep_dup
40
+ self
46
41
  end
47
42
  end
43
+
44
+ using self
48
45
  end
@@ -1,44 +1,40 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- module Runger
4
- module Ext
5
- # Add #deep_freeze to hashes and arrays
6
- module DeepFreeze
7
- refine ::Hash do
8
- def deep_freeze
9
- freeze
10
- each_value do |value|
11
- value.deep_freeze if value.is_a?(::Hash) || value.is_a?(::Array)
12
- end
13
- end
3
+ # Add #deep_freeze to hashes and arrays
4
+ module Runger::Ext::DeepFreeze
5
+ refine ::Hash do
6
+ def deep_freeze
7
+ freeze
8
+ each_value do |value|
9
+ value.deep_freeze if value.is_a?(::Hash) || value.is_a?(::Array)
14
10
  end
11
+ end
12
+ end
15
13
 
16
- refine ::Array do
17
- def deep_freeze
18
- freeze
19
- each do |value|
20
- value.deep_freeze if value.is_a?(::Hash) || value.is_a?(::Array)
21
- end
22
- end
14
+ refine ::Array do
15
+ def deep_freeze
16
+ freeze
17
+ each do |value|
18
+ value.deep_freeze if value.is_a?(::Hash) || value.is_a?(::Array)
23
19
  end
20
+ end
21
+ end
24
22
 
25
- begin
26
- require "active_support/core_ext/hash/indifferent_access"
27
- rescue LoadError
28
- end
23
+ begin
24
+ require 'active_support/core_ext/hash/indifferent_access'
25
+ rescue LoadError
26
+ end
29
27
 
30
- if defined?(::ActiveSupport::HashWithIndifferentAccess)
31
- refine ::ActiveSupport::HashWithIndifferentAccess do
32
- def deep_freeze
33
- freeze
34
- each_value do |value|
35
- value.deep_freeze if value.is_a?(::Hash) || value.is_a?(::Array)
36
- end
37
- end
28
+ if defined?(::ActiveSupport::HashWithIndifferentAccess)
29
+ refine ::ActiveSupport::HashWithIndifferentAccess do
30
+ def deep_freeze
31
+ freeze
32
+ each_value do |value|
33
+ value.deep_freeze if value.is_a?(::Hash) || value.is_a?(::Array)
38
34
  end
39
35
  end
40
-
41
- using self
42
36
  end
43
37
  end
38
+
39
+ using self
44
40
  end
@@ -1,37 +1,33 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- module Runger
4
- module Ext
5
- # Convert Hash with mixed array and hash values to an
6
- # array of paths.
7
- module FlattenNames
8
- refine ::Array do
9
- def flatten_names(prefix, buf)
10
- if empty?
11
- buf << :"#{prefix}"
12
- return buf
13
- end
14
-
15
- each_with_object(buf) do |name, acc|
16
- if name.is_a?(::Symbol)
17
- acc << :"#{prefix}.#{name}"
18
- else
19
- name.flatten_names(prefix, acc)
20
- end
21
- end
22
- end
3
+ # Convert Hash with mixed array and hash values to an
4
+ # array of paths.
5
+ module Runger::Ext::FlattenNames
6
+ refine ::Array do
7
+ def flatten_names(prefix, buf)
8
+ if empty?
9
+ buf << :"#{prefix}"
10
+ return buf
23
11
  end
24
12
 
25
- refine ::Hash do
26
- def flatten_names(prefix = nil, buf = [])
27
- each_with_object(buf) do |(k, v), acc|
28
- parent = prefix ? "#{prefix}.#{k}" : k
29
- v.flatten_names(parent, acc)
30
- end
13
+ each_with_object(buf) do |name, acc|
14
+ if name.is_a?(::Symbol)
15
+ acc << :"#{prefix}.#{name}"
16
+ else
17
+ name.flatten_names(prefix, acc)
31
18
  end
32
19
  end
20
+ end
21
+ end
33
22
 
34
- using self
23
+ refine ::Hash do
24
+ def flatten_names(prefix = nil, buf = [])
25
+ each_with_object(buf) do |(k, v), acc|
26
+ parent = prefix ? "#{prefix}.#{k}" : k
27
+ v.flatten_names(parent, acc)
28
+ end
35
29
  end
36
30
  end
31
+
32
+ using self
37
33
  end
@@ -1,40 +1,37 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- module Runger
4
- module Ext
5
- # Extend Hash through refinements
6
- module Hash
7
- refine ::Hash do
8
- def stringify_keys!
9
- keys.each do |key|
10
- value = delete(key)
11
- self[key.to_s] = value
12
- end
13
-
14
- self
15
- end
3
+ # Extend Hash through refinements
4
+ module Runger::Ext::Hash
5
+ refine ::Hash do
6
+ def stringify_keys!
7
+ keys.each do |key|
8
+ value = delete(key)
9
+ self[key.to_s] = value
10
+ end
16
11
 
17
- def bury(val, *path)
18
- raise ArgumentError, "No path specified" if path.empty?
19
- raise ArgumentError, "Path cannot contain nil" if path.compact.size != path.size
12
+ self
13
+ end
20
14
 
21
- last_key = path.pop
22
- hash = path.reduce(self) do |hash, k|
23
- hash[k] = {} unless hash.key?(k) && hash[k].is_a?(::Hash)
24
- hash[k]
25
- end
15
+ def bury(val, *path)
16
+ raise(ArgumentError, 'No path specified') if path.empty?
17
+ raise(ArgumentError, 'Path cannot contain nil') if path.compact.size != path.size
26
18
 
27
- hash[last_key] = val
19
+ last_key = path.pop
20
+ hash =
21
+ path.reduce(self) do |hash, k|
22
+ hash[k] = {} unless hash.key?(k) && hash[k].is_a?(::Hash)
23
+ hash[k]
28
24
  end
29
25
 
30
- def deep_transform_keys(&block)
31
- each_with_object({}) do |(key, value), result|
32
- result[yield(key)] = value.is_a?(::Hash) ? value.deep_transform_keys(&block) : value
33
- end
34
- end
35
- end
26
+ hash[last_key] = val
27
+ end
36
28
 
37
- using self
29
+ def deep_transform_keys(&block)
30
+ each_with_object({}) do |(key, value), result|
31
+ result[yield(key)] = value.is_a?(::Hash) ? value.deep_transform_keys(&block) : value
32
+ end
38
33
  end
39
34
  end
35
+
36
+ using self
40
37
  end
@@ -1,23 +1,20 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- module Runger
4
- module Ext
5
- # Add simple safe_constantize method to String
6
- module StringConstantize
7
- refine String do
8
- def safe_constantize
9
- names = split("::")
3
+ # Add simple safe_constantize method to String
4
+ module Runger::Ext::StringConstantize
5
+ refine String do
6
+ def safe_constantize
7
+ names = split('::')
10
8
 
11
- return nil if names.empty?
9
+ return nil if names.empty?
12
10
 
13
- # Remove the first blank element in case of '::ClassName' notation.
14
- names.shift if names.size > 1 && names.first.empty?
11
+ # Remove the first blank element in case of '::ClassName' notation.
12
+ names.shift if names.size > 1 && names.first.empty?
15
13
 
16
- names.inject(Object) do |constant, name|
17
- break if constant.nil?
18
- constant.const_get(name, false) if constant.const_defined?(name, false)
19
- end
20
- end
14
+ names.inject(Object) do |constant, name|
15
+ break if constant.nil?
16
+
17
+ constant.const_get(name, false) if constant.const_defined?(name, false)
21
18
  end
22
19
  end
23
20
  end
@@ -1,21 +1,17 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- module Runger
4
- module Loaders
5
- class Base
6
- include Tracing
3
+ class Runger::Loaders::Base
4
+ include ::Runger::Tracing
7
5
 
8
- class << self
9
- def call(local: Runger::Settings.use_local_files, **)
10
- new(local:).call(**)
11
- end
12
- end
13
-
14
- def initialize(local:)
15
- @local = local
16
- end
17
-
18
- def use_local? = @local == true
6
+ class << self
7
+ def call(local: Runger::Settings.use_local_files, **options)
8
+ new(local:).call(**options)
19
9
  end
20
10
  end
11
+
12
+ def initialize(local:)
13
+ @local = local
14
+ end
15
+
16
+ def use_local? = @local == true
21
17
  end