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,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