runger_config 4.0.0 → 5.1.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 (44) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +8 -0
  3. data/bin/release +27 -0
  4. data/lib/generators/runger/app_config/app_config_generator.rb +6 -10
  5. data/lib/generators/runger/config/config_generator.rb +44 -41
  6. data/lib/generators/runger/install/install_generator.rb +35 -37
  7. data/lib/runger/auto_cast.rb +3 -3
  8. data/lib/runger/config.rb +114 -94
  9. data/lib/runger/dynamic_config.rb +21 -23
  10. data/lib/runger/ejson_parser.rb +24 -24
  11. data/lib/runger/env.rb +50 -52
  12. data/lib/runger/ext/deep_dup.rb +33 -36
  13. data/lib/runger/ext/deep_freeze.rb +28 -32
  14. data/lib/runger/ext/flatten_names.rb +23 -27
  15. data/lib/runger/ext/hash.rb +26 -29
  16. data/lib/runger/ext/string_constantize.rb +12 -15
  17. data/lib/runger/loaders/base.rb +11 -15
  18. data/lib/runger/loaders/doppler.rb +38 -42
  19. data/lib/runger/loaders/ejson.rb +65 -63
  20. data/lib/runger/loaders/env.rb +6 -10
  21. data/lib/runger/loaders/yaml.rb +69 -66
  22. data/lib/runger/loaders.rb +69 -71
  23. data/lib/runger/option_parser_builder.rb +16 -18
  24. data/lib/runger/optparse_config.rb +11 -10
  25. data/lib/runger/rails/autoload.rb +24 -26
  26. data/lib/runger/rails/config.rb +13 -17
  27. data/lib/runger/rails/loaders/credentials.rb +53 -57
  28. data/lib/runger/rails/loaders/secrets.rb +21 -25
  29. data/lib/runger/rails/loaders/yaml.rb +1 -6
  30. data/lib/runger/rails/loaders.rb +3 -3
  31. data/lib/runger/rails/settings.rb +49 -49
  32. data/lib/runger/rails.rb +9 -11
  33. data/lib/runger/railtie.rb +3 -2
  34. data/lib/runger/rbs.rb +29 -29
  35. data/lib/runger/settings.rb +82 -84
  36. data/lib/runger/testing/helpers.rb +26 -28
  37. data/lib/runger/testing.rb +2 -2
  38. data/lib/runger/tracing.rb +143 -136
  39. data/lib/runger/type_casting.rb +16 -11
  40. data/lib/runger/utils/which.rb +10 -12
  41. data/lib/runger/version.rb +1 -1
  42. data/lib/runger.rb +1 -1
  43. data/lib/runger_config.rb +34 -27
  44. metadata +20 -19
data/lib/runger/config.rb CHANGED
@@ -1,8 +1,8 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require "active_support/all"
4
- require "runger/optparse_config"
5
- require "runger/dynamic_config"
3
+ require 'active_support/all'
4
+ require 'runger/dynamic_config'
5
+ require 'runger/optparse_config'
6
6
 
7
7
  module Runger # :nodoc:
8
8
  using Runger::Ext::DeepDup
@@ -20,6 +20,8 @@ module Runger # :nodoc:
20
20
  # Provides `attr_config` method to describe
21
21
  # configuration parameters and set defaults
22
22
  class Config
23
+ include OptparseConfig
24
+ include DynamicConfig
23
25
  PARAM_NAME = /^[a-z_](\w+)?$/
24
26
 
25
27
  # List of names that couldn't be used as config names
@@ -53,9 +55,6 @@ module Runger # :nodoc:
53
55
 
54
56
  class ValidationError < Error; end
55
57
 
56
- include OptparseConfig
57
- include DynamicConfig
58
-
59
58
  class BlockCallback
60
59
  attr_reader :block
61
60
 
@@ -83,17 +82,18 @@ module Runger # :nodoc:
83
82
  new_defaults = hargs.deep_dup
84
83
  new_defaults.stringify_keys!
85
84
 
86
- defaults.merge! new_defaults
85
+ defaults.merge!(new_defaults)
87
86
 
88
87
  new_keys = ((args + new_defaults.keys) - config_attributes)
89
88
 
90
- validate_param_names! new_keys.map(&:to_s)
89
+ validate_param_names!(new_keys.map(&:to_s))
91
90
 
92
91
  new_keys.map!(&:to_sym)
93
92
 
94
93
  unless (reserved_names = (new_keys & RESERVED_NAMES)).empty?
95
- raise ArgumentError, "Can not use the following reserved names as config attrubutes: " \
96
- "#{reserved_names.sort.map(&:to_s).join(", ")}"
94
+ raise(ArgumentError,
95
+ 'Can not use the following reserved names as config attrubutes: ' \
96
+ "#{reserved_names.sort.map(&:to_s).join(', ')}")
97
97
  end
98
98
 
99
99
  config_attributes.push(*new_keys)
@@ -104,33 +104,39 @@ module Runger # :nodoc:
104
104
  # having `true` or `false` as default values
105
105
  new_defaults.each do |key, val|
106
106
  next unless val.is_a?(TrueClass) || val.is_a?(FalseClass)
107
- alias_method :"#{key}?", :"#{key}"
107
+
108
+ alias_method(:"#{key}?", :"#{key}")
108
109
  end
109
110
  end
110
111
 
111
112
  def defaults
112
113
  return @defaults if instance_variable_defined?(:@defaults)
113
114
 
114
- @defaults = if superclass < Runger::Config
115
- superclass.defaults.deep_dup
116
- else
117
- new_empty_config
118
- end
115
+ @defaults =
116
+ if superclass < Runger::Config
117
+ superclass.defaults.deep_dup
118
+ else
119
+ new_empty_config
120
+ end
119
121
  end
120
122
 
121
123
  def config_attributes
122
124
  return @config_attributes if instance_variable_defined?(:@config_attributes)
123
125
 
124
- @config_attributes = if superclass < Runger::Config
125
- superclass.config_attributes.dup
126
- else
127
- []
128
- end
126
+ @config_attributes =
127
+ if superclass < Runger::Config
128
+ superclass.config_attributes.dup
129
+ else
130
+ []
131
+ end
129
132
  end
130
133
 
131
134
  def required(*names, env: nil, **nested)
132
135
  unknown_names = names + nested.keys - config_attributes
133
- raise ArgumentError, "Unknown config param: #{unknown_names.join(",")}" if unknown_names.any?
136
+ if unknown_names.any?
137
+ raise(ArgumentError,
138
+ "Unknown config param: #{unknown_names.join(',')}")
139
+ end
134
140
 
135
141
  return unless Settings.matching_env?(env)
136
142
 
@@ -141,15 +147,19 @@ module Runger # :nodoc:
141
147
  def required_attributes
142
148
  return @required_attributes if instance_variable_defined?(:@required_attributes)
143
149
 
144
- @required_attributes = if superclass < Runger::Config
145
- superclass.required_attributes.dup
146
- else
147
- []
148
- end
150
+ @required_attributes =
151
+ if superclass < Runger::Config
152
+ superclass.required_attributes.dup
153
+ else
154
+ []
155
+ end
149
156
  end
150
157
 
151
158
  def on_load(*names, &block)
152
- raise ArgumentError, "Either methods or block should be specified, not both" if block && !names.empty?
159
+ if block && !names.empty?
160
+ raise(ArgumentError,
161
+ 'Either methods or block should be specified, not both')
162
+ end
153
163
 
154
164
  if block
155
165
  load_callbacks << BlockCallback.new(block)
@@ -161,11 +171,12 @@ module Runger # :nodoc:
161
171
  def load_callbacks
162
172
  return @load_callbacks if instance_variable_defined?(:@load_callbacks)
163
173
 
164
- @load_callbacks = if superclass <= Runger::Config
165
- superclass.load_callbacks.dup
166
- else
167
- []
168
- end
174
+ @load_callbacks =
175
+ if superclass <= Runger::Config
176
+ superclass.load_callbacks.dup
177
+ else
178
+ []
179
+ end
169
180
  end
170
181
 
171
182
  def config_name(val = nil)
@@ -192,11 +203,12 @@ module Runger # :nodoc:
192
203
 
193
204
  return @env_prefix if instance_variable_defined?(:@env_prefix)
194
205
 
195
- @env_prefix = if superclass < Runger::Config && superclass.explicit_config_name?
196
- superclass.env_prefix
197
- else
198
- config_name.upcase
199
- end
206
+ @env_prefix =
207
+ if superclass < Runger::Config && superclass.explicit_config_name?
208
+ superclass.env_prefix
209
+ else
210
+ config_name.upcase
211
+ end
200
212
  end
201
213
 
202
214
  def loader_options(val = nil)
@@ -204,34 +216,36 @@ module Runger # :nodoc:
204
216
 
205
217
  return @loader_options if instance_variable_defined?(:@loader_options)
206
218
 
207
- @loader_options = if superclass < Runger::Config
208
- superclass.loader_options
209
- else
210
- {}
211
- end
219
+ @loader_options =
220
+ if superclass < Runger::Config
221
+ superclass.loader_options
222
+ else
223
+ {}
224
+ end
212
225
  end
213
226
 
214
227
  def new_empty_config = {}
215
228
 
216
229
  def coerce_types(mapping)
217
- Utils.deep_merge!(coercion_mapping, mapping)
230
+ ::Runger::Utils.deep_merge!(coercion_mapping, mapping)
218
231
 
219
232
  mapping.each do |key, val|
220
233
  type = val.is_a?(::Hash) ? val[:type] : val
221
234
  next if type != :boolean
222
235
 
223
- alias_method :"#{key}?", :"#{key}"
236
+ alias_method(:"#{key}?", :"#{key}")
224
237
  end
225
238
  end
226
239
 
227
240
  def coercion_mapping
228
241
  return @coercion_mapping if instance_variable_defined?(:@coercion_mapping)
229
242
 
230
- @coercion_mapping = if superclass < Runger::Config
231
- superclass.coercion_mapping.deep_dup
232
- else
233
- {}
234
- end
243
+ @coercion_mapping =
244
+ if superclass < Runger::Config
245
+ superclass.coercion_mapping.deep_dup
246
+ else
247
+ {}
248
+ end
235
249
  end
236
250
 
237
251
  def type_caster(val = nil)
@@ -250,11 +264,12 @@ module Runger # :nodoc:
250
264
 
251
265
  return @fallback_type_caster if instance_variable_defined?(:@fallback_type_caster)
252
266
 
253
- @fallback_type_caster = if superclass < Runger::Config
254
- superclass.fallback_type_caster.deep_dup
255
- else
256
- ::Runger::AutoCast
257
- end
267
+ @fallback_type_caster =
268
+ if superclass < Runger::Config
269
+ superclass.fallback_type_caster.deep_dup
270
+ else
271
+ ::Runger::AutoCast
272
+ end
258
273
  end
259
274
 
260
275
  def disable_auto_cast!
@@ -265,7 +280,7 @@ module Runger # :nodoc:
265
280
 
266
281
  def define_config_accessor(*names)
267
282
  names.each do |name|
268
- accessors_module.module_eval <<~RUBY, __FILE__, __LINE__ + 1
283
+ accessors_module.module_eval(<<~RUBY, __FILE__, __LINE__ + 1)
269
284
  def #{name}=(val)
270
285
  __trace__&.record_value(val, "#{name}", **Tracing.current_trace_source)
271
286
  values[:#{name}] = val
@@ -281,31 +296,33 @@ module Runger # :nodoc:
281
296
  def accessors_module
282
297
  return @accessors_module if instance_variable_defined?(:@accessors_module)
283
298
 
284
- @accessors_module = Module.new.tap do |mod|
285
- include mod
286
- end
299
+ @accessors_module =
300
+ Module.new.tap do |mod|
301
+ include mod
302
+ end
287
303
  end
288
304
 
289
305
  def build_config_name
290
306
  unless name
291
- raise "Please, specify config name explicitly for anonymous class " \
292
- "via `config_name :my_config`"
307
+ raise('Please, specify config name explicitly for anonymous class ' \
308
+ 'via `config_name :my_config`')
293
309
  end
294
310
 
295
- unless name.underscore.gsub("/", "_") =~ /(\w+)_config\z/
296
- raise "Couldn't infer config name, please, specify it explicitly " \
297
- "via `config_name :my_config`"
311
+ unless name.underscore.tr('/', '_') =~ /(\w+)_config\z/
312
+ raise("Couldn't infer config name, please, specify it explicitly " \
313
+ 'via `config_name :my_config`')
298
314
  end
299
315
 
300
- Regexp.last_match[1].delete_suffix("_config").tap(&:downcase!)
316
+ Regexp.last_match[1].delete_suffix('_config').tap(&:downcase!)
301
317
  end
302
318
 
303
319
  def validate_param_names!(names)
304
- invalid_names = names.reject { |name| name =~ PARAM_NAME }
320
+ invalid_names = names.grep_v(PARAM_NAME)
305
321
  return if invalid_names.empty?
306
322
 
307
- raise ArgumentError, "Invalid attr_config name: #{invalid_names.join(", ")}.\n" \
308
- "Valid names must satisfy /#{PARAM_NAME.source}/."
323
+ raise(ArgumentError,
324
+ "Invalid attr_config name: #{invalid_names.join(', ')}.\n" \
325
+ "Valid names must satisfy /#{PARAM_NAME.source}/.")
309
326
  end
310
327
  end
311
328
 
@@ -325,7 +342,7 @@ module Runger # :nodoc:
325
342
  def initialize(overrides = nil)
326
343
  @config_name = self.class.config_name
327
344
 
328
- raise ArgumentError, "Config name is missing" unless @config_name
345
+ raise(ArgumentError, 'Config name is missing') unless @config_name
329
346
 
330
347
  @env_prefix = self.class.env_prefix
331
348
  @values = {}
@@ -348,25 +365,26 @@ module Runger # :nodoc:
348
365
  def load(overrides = nil)
349
366
  base_config = self.class.defaults.deep_dup
350
367
 
351
- trace = Tracing.capture do
352
- Tracing.trace!(:defaults) { base_config }
368
+ trace =
369
+ Tracing.capture do
370
+ Tracing.trace!(:defaults) { base_config }
353
371
 
354
- config_path = resolve_config_path(config_name, env_prefix)
372
+ config_path = resolve_config_path(config_name, env_prefix)
355
373
 
356
- load_from_sources(
357
- base_config,
358
- name: config_name,
359
- env_prefix:,
360
- config_path:,
361
- **self.class.loader_options
362
- )
374
+ load_from_sources(
375
+ base_config,
376
+ name: config_name,
377
+ env_prefix:,
378
+ config_path:,
379
+ **self.class.loader_options,
380
+ )
363
381
 
364
- if overrides
365
- Tracing.trace!(:load) { overrides }
382
+ if overrides
383
+ Tracing.trace!(:load) { overrides }
366
384
 
367
- Utils.deep_merge!(base_config, overrides)
385
+ ::Runger::Utils.deep_merge!(base_config, overrides)
386
+ end
368
387
  end
369
- end
370
388
 
371
389
  base_config.each do |key, val|
372
390
  write_config_attr(key.to_sym, val)
@@ -385,9 +403,9 @@ module Runger # :nodoc:
385
403
  self
386
404
  end
387
405
 
388
- def load_from_sources(base_config, **)
406
+ def load_from_sources(base_config, **options)
389
407
  Runger.loaders.each do |(_id, loader)|
390
- Utils.deep_merge!(base_config, loader.call(**))
408
+ ::Runger::Utils.deep_merge!(base_config, loader.call(**options))
391
409
  end
392
410
  base_config
393
411
  end
@@ -406,7 +424,7 @@ module Runger # :nodoc:
406
424
  end
407
425
 
408
426
  def resolve_config_path(name, env_prefix)
409
- Runger.env.fetch(env_prefix).delete("conf") || Settings.default_config_path.call(name)
427
+ Runger.env.fetch(env_prefix).delete('conf') || Settings.default_config_path.call(name)
410
428
  end
411
429
 
412
430
  def deconstruct_keys(keys) = values.deconstruct_keys(keys)
@@ -414,20 +432,21 @@ module Runger # :nodoc:
414
432
  def to_source_trace = __trace__&.to_h
415
433
 
416
434
  def inspect
417
- "#<#{self.class}:0x#{vm_object_id.rjust(16, "0")} config_name=\"#{config_name}\" env_prefix=\"#{env_prefix}\" " \
418
- "values=#{values.inspect}>"
435
+ "#<#{self.class}:0x#{vm_object_id.rjust(16,
436
+ '0')} config_name=\"#{config_name}\" env_prefix=\"#{env_prefix}\" " \
437
+ "values=#{values.inspect}>"
419
438
  end
420
439
 
421
440
  def pretty_print(q)
422
- q.object_group self do
441
+ q.object_group(self) do
423
442
  q.nest(1) do
424
443
  q.breakable
425
444
  q.text "config_name=#{config_name.inspect}"
426
445
  q.breakable
427
446
  q.text "env_prefix=#{env_prefix.inspect}"
428
447
  q.breakable
429
- q.text "values:"
430
- q.pp __trace__
448
+ q.text 'values:'
449
+ q.pp(__trace__)
431
450
  end
432
451
  end
433
452
  end
@@ -442,11 +461,12 @@ module Runger # :nodoc:
442
461
 
443
462
  def validate_required_attributes!
444
463
  self.class.required_attributes.select do |name|
445
- val = values.dig(*name.to_s.split(".").map(&:to_sym))
464
+ val = values.dig(*name.to_s.split('.').map(&:to_sym))
446
465
  val.nil? || (val.is_a?(String) && val.empty?)
447
466
  end.then do |missing|
448
467
  next if missing.empty?
449
- raise_validation_error "The following config parameters for `#{self.class.name}(config_name: #{self.class.config_name})` are missing or empty: #{missing.join(", ")}"
468
+
469
+ raise_validation_error("The following config parameters for `#{self.class.name}(config_name: #{self.class.config_name})` are missing or empty: #{missing.join(', ')}")
450
470
  end
451
471
  end
452
472
 
@@ -459,7 +479,7 @@ module Runger # :nodoc:
459
479
  end
460
480
 
461
481
  def raise_validation_error(msg)
462
- raise ValidationError, msg
482
+ raise(ValidationError, msg)
463
483
  end
464
484
 
465
485
  def __type_caster__
@@ -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