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,111 +1,109 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require "pathname"
4
-
5
- module Runger
6
- # Use Settings name to not confuse with Config.
7
- #
8
- # Settings contain the library-wide configuration.
9
- class Settings
10
- # Future encapsulates settings that will be introduced in the upcoming version
11
- # with the default values, which could break compatibility
12
- class Future
13
- class << self
14
- def setting(name, default_value)
15
- settings[name] = default_value
16
-
17
- define_method(name) do
18
- store[name]
19
- end
20
-
21
- define_method(:"#{name}=") do |val|
22
- store[name] = val
23
- end
24
- end
3
+ require 'pathname'
4
+
5
+ # Use Settings name to not confuse with Config.
6
+ #
7
+ # Settings contain the library-wide configuration.
8
+ class Runger::Settings
9
+ # Future encapsulates settings that will be introduced in the upcoming version
10
+ # with the default values, which could break compatibility
11
+ class Future
12
+ class << self
13
+ def setting(name, default_value)
14
+ settings[name] = default_value
25
15
 
26
- def settings
27
- @settings ||= {}
16
+ define_method(name) do
17
+ store[name]
28
18
  end
29
- end
30
19
 
31
- def initialize
32
- @store = {}
20
+ define_method(:"#{name}=") do |val|
21
+ store[name] = val
22
+ end
33
23
  end
34
24
 
35
- def use(*names)
36
- store.clear
37
- names.each { store[_1] = self.class.settings[_1] }
25
+ def settings
26
+ @settings ||= {}
38
27
  end
28
+ end
39
29
 
40
- setting :unwrap_known_environments, true
41
-
42
- private
30
+ def initialize
31
+ @store = {}
32
+ end
43
33
 
44
- attr_reader :store
34
+ def use(*names)
35
+ store.clear
36
+ names.each { store[_1] = self.class.settings[_1] }
45
37
  end
46
38
 
47
- class << self
48
- # Define whether to load data from
49
- # *.yml.local (or credentials/local.yml.enc)
50
- attr_accessor :use_local_files,
51
- :current_environment,
52
- :default_environmental_key,
53
- :known_environments
54
-
55
- # A proc returning a path to YML config file given the config name
56
- attr_reader :default_config_path
57
-
58
- def default_config_path=(val)
59
- if val.is_a?(Proc)
60
- @default_config_path = val
61
- return
62
- end
39
+ setting :unwrap_known_environments, true
63
40
 
64
- val = val.to_s
41
+ private
65
42
 
66
- @default_config_path = ->(name) { File.join(val, "#{name}.yml") }
43
+ attr_reader :store
44
+ end
45
+
46
+ class << self
47
+ # Define whether to load data from
48
+ # *.yml.local (or credentials/local.yml.enc)
49
+ attr_accessor :use_local_files,
50
+ :current_environment,
51
+ :default_environmental_key,
52
+ :known_environments
53
+
54
+ # A proc returning a path to YML config file given the config name
55
+ attr_reader :default_config_path
56
+
57
+ def default_config_path=(val)
58
+ if val.is_a?(Proc)
59
+ @default_config_path = val
60
+ return
67
61
  end
68
62
 
69
- # Enable source tracing
70
- attr_accessor :tracing_enabled
63
+ val = val.to_s
71
64
 
72
- def future
73
- @future ||= Future.new
74
- end
65
+ @default_config_path = ->(name) { File.join(val, "#{name}.yml") }
66
+ end
75
67
 
76
- def app_root
77
- Pathname.new(Dir.pwd)
78
- end
68
+ # Enable source tracing
69
+ attr_accessor :tracing_enabled
79
70
 
80
- def default_environmental_key?
81
- !default_environmental_key.nil?
82
- end
71
+ def future
72
+ @future ||= Future.new
73
+ end
83
74
 
84
- def matching_env?(env)
85
- return true if env.nil? || env.to_s == current_environment
86
-
87
- if env.is_a?(::Hash)
88
- envs = env[:except]
89
- excluded_envs = [envs].flat_map(&:to_s)
90
- excluded_envs.none?(current_environment)
91
- elsif env.is_a?(::Array)
92
- env.flat_map(&:to_s).include?(current_environment)
93
- else
94
- false
95
- end
75
+ def app_root
76
+ Pathname.new(Dir.pwd)
77
+ end
78
+
79
+ def default_environmental_key?
80
+ !default_environmental_key.nil?
81
+ end
82
+
83
+ def matching_env?(env)
84
+ return true if env.nil? || env.to_s == current_environment
85
+
86
+ if env.is_a?(::Hash)
87
+ envs = env[:except]
88
+ excluded_envs = [envs].flat_map(&:to_s)
89
+ excluded_envs.none?(current_environment)
90
+ elsif env.is_a?(::Array)
91
+ env.flat_map(&:to_s).include?(current_environment)
92
+ else
93
+ false
96
94
  end
97
95
  end
96
+ end
98
97
 
99
- # By default, use RUNGER_ENV
100
- self.current_environment = ENV["RUNGER_ENV"]
98
+ # By default, use RUNGER_ENV
99
+ self.current_environment = ENV.fetch('RUNGER_ENV', nil)
101
100
 
102
- # By default, use local files only in development (that's the purpose if the local files)
103
- self.use_local_files = (ENV["RUNGER_ENV"] == "development" || ENV["RACK_ENV"] == "development" || ENV["RAILS_ENV"] == "development" || (defined?(Rails) && Rails.env.development?))
101
+ # By default, use local files only in development (that's the purpose if the local files)
102
+ self.use_local_files = (ENV['RUNGER_ENV'] == 'development' || ENV['RACK_ENV'] == 'development' || ENV['RAILS_ENV'] == 'development' || (defined?(Rails) && Rails.env.development?))
104
103
 
105
- # By default, consider configs are stored in the ./config folder
106
- self.default_config_path = ->(name) { "./config/#{name}.yml" }
104
+ # By default, consider configs are stored in the ./config folder
105
+ self.default_config_path = ->(name) { "./config/#{name}.yml" }
107
106
 
108
- # Tracing is enabled by default
109
- self.tracing_enabled = true
110
- end
107
+ # Tracing is enabled by default
108
+ self.tracing_enabled = true
111
109
  end
@@ -1,36 +1,34 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- module Runger
4
- module Testing
5
- module Helpers
6
- # Sets the ENV variables to the provided
7
- # values and restore outside the block
8
- #
9
- # Also resets Runger.env before and after calling the block
10
- # to make sure that the values are not cached.
11
- #
12
- # NOTE: to remove the env value, pass `nil` as the value
13
- def with_env(data)
14
- was_values = []
3
+ module Runger::Testing::Helpers
4
+ # Sets the ENV variables to the provided
5
+ # values and restore outside the block
6
+ #
7
+ # Also resets Runger.env before and after calling the block
8
+ # to make sure that the values are not cached.
9
+ #
10
+ # NOTE: to remove the env value, pass `nil` as the value
11
+ def with_env(data)
12
+ was_values = []
15
13
 
16
- data.each do |key, val|
17
- was_values << [key, ENV[key]]
18
- next ENV.delete(key) if val.nil?
19
- ENV[key] = val
20
- end
14
+ data.each do |key, val|
15
+ was_values << [key, ENV.fetch(key, nil)]
16
+ next ENV.delete(key) if val.nil?
21
17
 
22
- # clear cached env values
23
- Runger.env.clear
24
- yield
25
- ensure
26
- was_values.each do |(key, val)|
27
- next ENV.delete(key) if val.nil?
28
- ENV[key] = val
29
- end
18
+ ENV[key] = val
19
+ end
20
+
21
+ # clear cached env values
22
+ Runger.env.clear
23
+ yield
24
+ ensure
25
+ was_values.each do |(key, val)|
26
+ next ENV.delete(key) if val.nil?
30
27
 
31
- # clear cache again
32
- Runger.env.clear
33
- end
28
+ ENV[key] = val
34
29
  end
30
+
31
+ # clear cache again
32
+ Runger.env.clear
35
33
  end
36
34
  end
@@ -1,13 +1,13 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require "runger/testing/helpers"
3
+ require 'runger/testing/helpers'
4
4
 
5
5
  if defined?(RSpec::Core) && RSpec.respond_to?(:configure)
6
6
  RSpec.configure do |config|
7
7
  config.include(
8
8
  Runger::Testing::Helpers,
9
9
  type: :config,
10
- file_path: %r{spec/configs}
10
+ file_path: %r{spec/configs},
11
11
  )
12
12
  end
13
13
  end
@@ -1,188 +1,195 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- module Runger
4
- # Provides method to trace values association
5
- module Tracing
6
- using Runger::Ext::DeepDup
7
-
8
- using(Module.new do
9
- refine Thread::Backtrace::Location do
10
- def path_lineno = "#{path}:#{lineno}"
11
- end
12
- end)
3
+ # Provides method to trace values association
4
+ module Runger::Tracing
5
+ using Runger::Ext::DeepDup
13
6
 
14
- class Trace
15
- UNDEF = Object.new
7
+ using(Module.new do
8
+ refine Thread::Backtrace::Location do
9
+ def path_lineno = "#{path}:#{lineno}"
10
+ end
11
+ end)
16
12
 
17
- attr_reader :type, :value, :source
13
+ class Trace
14
+ UNDEF = Object.new
18
15
 
19
- def initialize(type = :trace, value = UNDEF, **source)
20
- @type = type
21
- @source = source
22
- @value = (value == UNDEF) ? Hash.new { |h, k| h[k] = Trace.new(:trace) } : value
23
- end
16
+ attr_reader :type, :value, :source
24
17
 
25
- def dig(...)
26
- value.dig(...)
27
- end
18
+ def initialize(type = :trace, value = UNDEF, **source)
19
+ @type = type
20
+ @source = source
21
+ @value = (value == UNDEF) ? Hash.new { |h, k| h[k] = Trace.new(:trace) } : value
22
+ end
23
+
24
+ def dig(...)
25
+ value.dig(...)
26
+ end
28
27
 
29
- def record_value(val, *path, **)
30
- key = path.pop
31
- trace = if val.is_a?(Hash)
32
- Trace.new.tap { _1.merge_values(val, **) }
28
+ def record_value(val, *path, **options)
29
+ key = path.pop
30
+ trace =
31
+ if val.is_a?(Hash)
32
+ Trace.new.tap { _1.merge_values(val, **options) }
33
33
  else
34
- Trace.new(:value, val, **)
34
+ Trace.new(:value, val, **options)
35
35
  end
36
36
 
37
- target_trace = path.empty? ? self : value.dig(*path)
38
- target_trace.record_key(key.to_s, trace)
37
+ target_trace = path.empty? ? self : value.dig(*path)
38
+ target_trace.record_key(key.to_s, trace)
39
39
 
40
- val
41
- end
40
+ val
41
+ end
42
42
 
43
- def merge_values(hash, **)
44
- return hash unless hash
43
+ def merge_values(hash, **options)
44
+ return hash unless hash
45
45
 
46
- hash.each do |key, val|
47
- if val.is_a?(Hash)
48
- value[key.to_s].merge_values(val, **)
49
- else
50
- value[key.to_s] = Trace.new(:value, val, **)
51
- end
46
+ hash.each do |key, val|
47
+ if val.is_a?(Hash)
48
+ value[key.to_s].merge_values(val, **options)
49
+ else
50
+ value[key.to_s] = Trace.new(:value, val, **options)
52
51
  end
53
-
54
- hash
55
52
  end
56
53
 
57
- def record_key(key, key_trace)
58
- @value = Hash.new { |h, k| h[k] = Trace.new(:trace) } unless value.is_a?(::Hash)
54
+ hash
55
+ end
59
56
 
60
- value[key] = key_trace
61
- end
57
+ def record_key(key, key_trace)
58
+ @value = Hash.new { |h, k| h[k] = Trace.new(:trace) } unless value.is_a?(::Hash)
62
59
 
63
- def merge!(another_trace)
64
- raise ArgumentError, "You can only merge into a :trace type, and this is :#{type}" unless trace?
65
- raise ArgumentError, "You can only merge a :trace type, but trying :#{type}" unless another_trace.trace?
60
+ value[key] = key_trace
61
+ end
66
62
 
67
- another_trace.value.each do |key, sub_trace|
68
- if sub_trace.trace?
69
- value[key].merge! sub_trace
70
- else
71
- value[key] = sub_trace
72
- end
73
- end
63
+ def merge!(another_trace)
64
+ unless trace?
65
+ raise(ArgumentError,
66
+ "You can only merge into a :trace type, and this is :#{type}")
67
+ end
68
+ unless another_trace.trace?
69
+ raise(ArgumentError,
70
+ "You can only merge a :trace type, but trying :#{type}")
74
71
  end
75
72
 
76
- def keep_if(...)
77
- raise ArgumentError, "You can only filter :trace type, and this is :#{type}" unless trace?
78
- value.keep_if(...)
73
+ another_trace.value.each do |key, sub_trace|
74
+ if sub_trace.trace?
75
+ value[key].merge!(sub_trace)
76
+ else
77
+ value[key] = sub_trace
78
+ end
79
79
  end
80
+ end
80
81
 
81
- def clear = value.clear
82
+ def keep_if(...)
83
+ raise(ArgumentError, "You can only filter :trace type, and this is :#{type}") unless trace?
82
84
 
83
- def trace? = type == :trace
85
+ value.keep_if(...)
86
+ end
84
87
 
85
- def to_h
86
- if trace?
87
- value.transform_values(&:to_h).tap { _1.default_proc = nil }
88
- else
89
- {value:, source:}
90
- end
88
+ def clear = value.clear
89
+
90
+ def trace? = type == :trace
91
+
92
+ def to_h
93
+ if trace?
94
+ value.transform_values(&:to_h).tap { _1.default_proc = nil }
95
+ else
96
+ { value:, source: }
91
97
  end
98
+ end
92
99
 
93
- def dup = self.class.new(type, value.dup, **source)
94
-
95
- def pretty_print(q)
96
- if trace?
97
- q.nest(2) do
98
- q.breakable ""
99
- q.seplist(value, nil, :each) do |k, v|
100
- q.group do
101
- q.text k
102
- q.text " =>"
103
- if v.trace?
104
- q.text " { "
105
- q.pp v
106
- q.breakable " "
107
- q.text "}"
108
- else
109
- q.breakable " "
110
- q.pp v
111
- end
100
+ def dup = self.class.new(type, value.dup, **source)
101
+
102
+ def pretty_print(q)
103
+ if trace?
104
+ q.nest(2) do
105
+ q.breakable('')
106
+ q.seplist(value, nil, :each) do |k, v|
107
+ q.group do
108
+ q.text k
109
+ q.text ' =>'
110
+ if v.trace?
111
+ q.text ' { '
112
+ q.pp(v)
113
+ q.breakable(' ')
114
+ q.text '}'
115
+ else
116
+ q.breakable(' ')
117
+ q.pp(v)
112
118
  end
113
119
  end
114
120
  end
115
- else
116
- q.pp value
117
- q.group(0, " (", ")") do
118
- q.seplist(source, lambda { q.breakable " " }, :each) do |k, v|
119
- q.group do
120
- q.text k.to_s
121
- q.text "="
122
- q.text v.to_s
123
- end
121
+ end
122
+ else
123
+ q.pp(value)
124
+ q.group(0, ' (', ')') do
125
+ q.seplist(source, lambda { q.breakable(' ') }, :each) do |k, v|
126
+ q.group do
127
+ q.text k.to_s
128
+ q.text '='
129
+ q.text v.to_s
124
130
  end
125
131
  end
126
132
  end
127
133
  end
128
134
  end
135
+ end
129
136
 
130
- class << self
131
- def capture
132
- unless Settings.tracing_enabled
133
- yield
134
- return
135
- end
136
-
137
- trace = Trace.new
138
- trace_stack.push trace
137
+ class << self
138
+ def capture
139
+ unless ::Runger::Settings.tracing_enabled
139
140
  yield
140
- trace_stack.last
141
- ensure
142
- trace_stack.pop
141
+ return
143
142
  end
144
143
 
145
- def trace_stack
146
- (Thread.current[:__runger__trace_stack__] ||= [])
147
- end
144
+ trace = Trace.new
145
+ trace_stack.push(trace)
146
+ yield
147
+ trace_stack.last
148
+ ensure
149
+ trace_stack.pop
150
+ end
148
151
 
149
- def current_trace = trace_stack.last
152
+ def trace_stack
153
+ (Thread.current[:__runger__trace_stack__] ||= [])
154
+ end
150
155
 
151
- alias_method :tracing?, :current_trace
156
+ def current_trace = trace_stack.last
152
157
 
153
- def source_stack
154
- (Thread.current[:__runger__trace_source_stack__] ||= [])
155
- end
158
+ alias tracing? current_trace
156
159
 
157
- def current_trace_source
158
- source_stack.last || accessor_source(caller_locations(2, 1).first)
159
- end
160
+ def source_stack
161
+ (Thread.current[:__runger__trace_source_stack__] ||= [])
162
+ end
160
163
 
161
- def with_trace_source(src)
162
- source_stack << src
163
- yield
164
- ensure
165
- source_stack.pop
166
- end
164
+ def current_trace_source
165
+ source_stack.last || accessor_source(caller_locations(2, 1).first)
166
+ end
167
+
168
+ def with_trace_source(src)
169
+ source_stack << src
170
+ yield
171
+ ensure
172
+ source_stack.pop
173
+ end
167
174
 
168
- private
175
+ private
169
176
 
170
- def accessor_source(location)
171
- {type: :accessor, called_from: location.path_lineno}
172
- end
177
+ def accessor_source(location)
178
+ { type: :accessor, called_from: location.path_lineno }
173
179
  end
180
+ end
174
181
 
175
- module_function
182
+ module_function
176
183
 
177
- def trace!(type, *path, **)
178
- return yield unless Tracing.tracing?
179
- val = yield
180
- if val.is_a?(Hash)
181
- Tracing.current_trace.merge_values(val, type:, **)
182
- elsif !path.empty?
183
- Tracing.current_trace.record_value(val, *path, type:, **)
184
- end
185
- val
184
+ def trace!(type, *path, **options)
185
+ return yield unless ::Runger::Tracing.tracing?
186
+
187
+ val = yield
188
+ if val.is_a?(Hash)
189
+ ::Runger::Tracing.current_trace.merge_values(val, type:, **options)
190
+ elsif !path.empty?
191
+ ::Runger::Tracing.current_trace.record_value(val, *path, type:, **options)
186
192
  end
193
+ val
187
194
  end
188
195
  end