runger_config 4.0.0 → 5.0.0

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