chamber 3.0.0rc1 → 3.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 (54) hide show
  1. checksums.yaml +4 -4
  2. checksums.yaml.gz.sig +0 -0
  3. data/README.md +5 -5
  4. data/lib/chamber/binary/runner.rb +10 -12
  5. data/lib/chamber/commands/base.rb +4 -4
  6. data/lib/chamber/commands/initialize.rb +5 -5
  7. data/lib/chamber/commands/securable.rb +5 -9
  8. data/lib/chamber/commands/show.rb +0 -1
  9. data/lib/chamber/context_resolver.rb +5 -4
  10. data/lib/chamber/encryption_methods/public_key.rb +26 -14
  11. data/lib/chamber/encryption_methods/ssl.rb +36 -28
  12. data/lib/chamber/errors/disallowed_class.rb +8 -0
  13. data/lib/chamber/errors/invalid_key_type.rb +8 -0
  14. data/lib/chamber/errors/missing_index.rb +13 -0
  15. data/lib/chamber/errors/missing_setting.rb +13 -0
  16. data/lib/chamber/errors/non_conforming_key.rb +8 -0
  17. data/lib/chamber/file.rb +18 -7
  18. data/lib/chamber/file_set.rb +5 -1
  19. data/lib/chamber/files/signature.rb +6 -6
  20. data/lib/chamber/filters/decryption_filter.rb +9 -11
  21. data/lib/chamber/filters/encryption_filter.rb +8 -9
  22. data/lib/chamber/filters/environment_filter.rb +16 -18
  23. data/lib/chamber/filters/failed_decryption_filter.rb +3 -3
  24. data/lib/chamber/filters/namespace_filter.rb +10 -12
  25. data/lib/chamber/filters/secure_filter.rb +3 -3
  26. data/lib/chamber/filters/translate_secure_keys_filter.rb +3 -3
  27. data/lib/chamber/instance.rb +4 -7
  28. data/lib/chamber/integrations/sinatra.rb +1 -1
  29. data/lib/chamber/keys/base.rb +11 -7
  30. data/lib/chamber/namespace_set.rb +2 -2
  31. data/lib/chamber/rails.rb +1 -1
  32. data/lib/chamber/refinements/deep_dup.rb +12 -36
  33. data/lib/chamber/refinements/enumerable.rb +8 -20
  34. data/lib/chamber/refinements/hash.rb +10 -36
  35. data/lib/chamber/rubinius_fix.rb +1 -1
  36. data/lib/chamber/settings.rb +39 -23
  37. data/lib/chamber/types/secured.rb +8 -8
  38. data/lib/chamber/version.rb +1 -1
  39. data/lib/chamber.rb +0 -5
  40. data.tar.gz.sig +0 -0
  41. metadata +29 -34
  42. metadata.gz.sig +0 -0
  43. data/lib/chamber/adapters/cloud/circle_ci.rb +0 -85
  44. data/lib/chamber/adapters/cloud/heroku.rb +0 -74
  45. data/lib/chamber/binary/circle_ci.rb +0 -123
  46. data/lib/chamber/binary/heroku.rb +0 -111
  47. data/lib/chamber/binary/travis.rb +0 -37
  48. data/lib/chamber/commands/cloud/base.rb +0 -35
  49. data/lib/chamber/commands/cloud/clear.rb +0 -25
  50. data/lib/chamber/commands/cloud/compare.rb +0 -26
  51. data/lib/chamber/commands/cloud/pull.rb +0 -29
  52. data/lib/chamber/commands/cloud/push.rb +0 -44
  53. data/lib/chamber/commands/travis/secure.rb +0 -37
  54. data/lib/chamber/refinements/array.rb +0 -20
@@ -1,15 +1,14 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require 'yaml'
4
+
4
5
  require 'chamber/errors/environment_conversion'
5
- require 'chamber/refinements/hash'
6
- require 'chamber/refinements/deep_dup'
7
6
 
8
7
  module Chamber
9
8
  module Filters
10
9
  class EnvironmentFilter
11
- using ::Chamber::Refinements::Hash
12
- using ::Chamber::Refinements::DeepDup
10
+ attr_accessor :data,
11
+ :secure_key_token
13
12
 
14
13
  ###
15
14
  # Internal: Allows the existing environment to be injected into the passed in
@@ -95,9 +94,6 @@ class EnvironmentFilter
95
94
  new(**args).__send__(:execute)
96
95
  end
97
96
 
98
- attr_accessor :data,
99
- :secure_key_token
100
-
101
97
  def initialize(data:, secure_key_prefix:, **_args)
102
98
  self.data = data
103
99
  self.secure_key_token = /\A#{Regexp.escape(secure_key_prefix)}/
@@ -113,9 +109,11 @@ class EnvironmentFilter
113
109
  { key => execute(value, environment_keys) }
114
110
  end,
115
111
  lambda do |key, value, environment_key|
116
- { key => convert_environment_value(environment_key,
117
- ENV[environment_key],
118
- value) }
112
+ {
113
+ key => convert_environment_value(environment_key,
114
+ ENV.fetch(environment_key, nil),
115
+ value),
116
+ }
119
117
  end,
120
118
  )
121
119
  end
@@ -127,14 +125,14 @@ class EnvironmentFilter
127
125
 
128
126
  settings.each_pair do |key, value|
129
127
  environment_key = key.to_s.gsub(secure_key_token, '')
130
- environment_keys = parent_keys.deep_dup.push(environment_key)
128
+ environment_keys = parent_keys.dup.push(environment_key)
131
129
 
132
130
  if value.respond_to? :each_pair
133
- environment_hash.deep_merge!(hash_block.call(key, value, environment_keys))
131
+ environment_hash.merge!(hash_block.call(key, value, environment_keys))
134
132
  else
135
133
  environment_key = environment_keys.join('_').upcase
136
134
 
137
- environment_hash.deep_merge!(value_block.call(key, value, environment_key))
135
+ environment_hash.merge!(value_block.call(key, value, environment_key))
138
136
  end
139
137
  end
140
138
 
@@ -171,13 +169,13 @@ class EnvironmentFilter
171
169
  environment_value
172
170
  end
173
171
  rescue ArgumentError
174
- raise Chamber::Errors::EnvironmentConversion, <<-HEREDOC
175
- We attempted to convert '#{environment_key}' from '#{environment_value}' to a '#{settings_value.class.name}'.
172
+ raise Chamber::Errors::EnvironmentConversion, <<~HEREDOC
173
+ We attempted to convert '#{environment_key}' from '#{environment_value}' to a '#{settings_value.class.name}'.
176
174
 
177
- Unfortunately, this did not go as planned. Please either verify that your value is convertable
178
- or change the original YAML value to be something more generic (like a String).
175
+ Unfortunately, this did not go as planned. Please either verify that your value is convertable
176
+ or change the original YAML value to be something more generic (like a String).
179
177
 
180
- For more information, see https://github.com/thekompanee/chamber/wiki/Environment-Variable-Coercions
178
+ For more information, see https://github.com/thekompanee/chamber/wiki/Environment-Variable-Coercions
181
179
  HEREDOC
182
180
  end
183
181
  end
@@ -10,13 +10,13 @@ class FailedDecryptionFilter
10
10
 
11
11
  BASE64_STRING_PATTERN = %r{\A[A-Za-z0-9+/]{342}==\z}.freeze
12
12
 
13
+ attr_accessor :data,
14
+ :secure_key_token
15
+
13
16
  def self.execute(**args)
14
17
  new(**args).__send__(:execute)
15
18
  end
16
19
 
17
- attr_accessor :data,
18
- :secure_key_token
19
-
20
20
  def initialize(data:, secure_key_prefix:, **_args)
21
21
  self.data = data.deep_dup
22
22
  self.secure_key_token = /\A#{Regexp.escape(secure_key_prefix)}/
@@ -1,21 +1,21 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'chamber/refinements/hash'
4
3
  require 'chamber/refinements/deep_dup'
4
+ require 'chamber/refinements/hash'
5
5
 
6
6
  module Chamber
7
7
  module Filters
8
8
  class NamespaceFilter
9
- using ::Chamber::Refinements::Hash
10
9
  using ::Chamber::Refinements::DeepDup
10
+ using ::Chamber::Refinements::Hash
11
+
12
+ attr_accessor :data,
13
+ :namespaces
11
14
 
12
15
  def self.execute(**args)
13
16
  new(**args).__send__(:execute)
14
17
  end
15
18
 
16
- attr_accessor :data,
17
- :namespaces
18
-
19
19
  def initialize(data:, namespaces:, **_args)
20
20
  self.data = data.deep_dup
21
21
  self.namespaces = namespaces
@@ -24,19 +24,17 @@ class NamespaceFilter
24
24
  protected
25
25
 
26
26
  def execute
27
- if data_is_namespaced?
28
- namespaces.each_with_object({}) do |namespace, filtered_data|
29
- filtered_data.deep_merge!(data[namespace]) if data[namespace]
30
- end
31
- else
32
- data
27
+ return data unless data_is_namespaced?
28
+
29
+ namespaces.each_with_object({}) do |namespace, filtered_data|
30
+ filtered_data.deep_merge!(data[namespace]) if data[namespace]
33
31
  end
34
32
  end
35
33
 
36
34
  private
37
35
 
38
36
  def data_is_namespaced?
39
- @data_is_namespaced ||= data.keys.any? { |key| namespaces.include? key.to_s }
37
+ @data_is_namespaced ||= data.keys.any? { |key| namespaces.include?(key.to_s) }
40
38
  end
41
39
  end
42
40
  end
@@ -7,13 +7,13 @@ module Filters
7
7
  class SecureFilter
8
8
  using ::Chamber::Refinements::DeepDup
9
9
 
10
+ attr_accessor :data,
11
+ :secure_key_token
12
+
10
13
  def self.execute(**args)
11
14
  new(**args).__send__(:execute)
12
15
  end
13
16
 
14
- attr_accessor :data,
15
- :secure_key_token
16
-
17
17
  def initialize(data:, secure_key_prefix:, **_args)
18
18
  self.data = data.deep_dup
19
19
  self.secure_key_token = /\A#{Regexp.escape(secure_key_prefix)}/
@@ -7,13 +7,13 @@ module Filters
7
7
  class TranslateSecureKeysFilter
8
8
  using ::Chamber::Refinements::DeepDup
9
9
 
10
+ attr_accessor :data,
11
+ :secure_key_token
12
+
10
13
  def self.execute(**args)
11
14
  new(**args).__send__(:execute)
12
15
  end
13
16
 
14
- attr_accessor :data,
15
- :secure_key_token
16
-
17
17
  def initialize(data:, secure_key_prefix:, **_args)
18
18
  self.data = data.deep_dup
19
19
  self.secure_key_token = /\A#{Regexp.escape(secure_key_prefix)}/
@@ -3,12 +3,9 @@
3
3
  require 'chamber/configuration'
4
4
  require 'chamber/file_set'
5
5
  require 'chamber/settings'
6
- require 'chamber/refinements/hash'
7
6
 
8
7
  module Chamber
9
8
  class Instance
10
- using ::Chamber::Refinements::Hash
11
-
12
9
  attr_accessor :configuration,
13
10
  :files
14
11
 
@@ -66,11 +63,11 @@ class Instance
66
63
  end
67
64
 
68
65
  def encrypt(data, **args)
69
- config = configuration.to_hash.deep_merge(**args)
66
+ config = configuration.to_hash.merge(**args)
70
67
 
71
68
  Settings
72
69
  .new(
73
- **config.deep_merge(
70
+ **config.merge(
74
71
  settings: data,
75
72
  pre_filters: [Filters::EncryptionFilter],
76
73
  post_filters: [],
@@ -80,11 +77,11 @@ class Instance
80
77
  end
81
78
 
82
79
  def decrypt(data, **args)
83
- config = configuration.to_hash.deep_merge(**args)
80
+ config = configuration.to_hash.merge(**args)
84
81
 
85
82
  Settings
86
83
  .new(
87
- **config.deep_merge(
84
+ **config.merge(
88
85
  settings: data,
89
86
  pre_filters: [Filters::NamespaceFilter],
90
87
  post_filters: [
@@ -7,7 +7,7 @@ module Integrations
7
7
  module Sinatra
8
8
  def self.registered(app)
9
9
  app.configure do |inner_app|
10
- env = inner_app.environment || ENV['RACK_ENV']
10
+ env = inner_app.environment || ENV.fetch('RACK_ENV', nil)
11
11
  root = inner_app.root
12
12
 
13
13
  if defined?(Padrino)
@@ -3,14 +3,14 @@
3
3
  module Chamber
4
4
  module Keys
5
5
  class Base
6
- def self.resolve(**args)
7
- new(**args).resolve
8
- end
9
-
10
6
  attr_accessor :rootpath
11
7
  attr_reader :filenames,
12
8
  :namespaces
13
9
 
10
+ def self.resolve(**args)
11
+ new(**args).resolve
12
+ end
13
+
14
14
  def initialize(rootpath:, namespaces:, filenames: nil)
15
15
  self.rootpath = Pathname.new(rootpath)
16
16
  self.namespaces = namespaces
@@ -20,7 +20,11 @@ class Base
20
20
  def resolve
21
21
  key_paths.each_with_object({}) do |path, memo|
22
22
  namespace = namespace_from_path(path) || '__default'
23
- value = path.readable? ? path.read : ENV[environment_variable_from_path(path)]
23
+ value = if path.readable?
24
+ path.read
25
+ else
26
+ ENV.fetch(environment_variable_from_path(path), nil)
27
+ end
24
28
 
25
29
  memo[namespace.downcase.to_sym] = value if value
26
30
  end
@@ -39,13 +43,13 @@ class Base
39
43
  namespaces.map { |n| namespace_to_key_path(n) }
40
44
  end
41
45
 
42
- # rubocop:disable Performance/ChainArrayAllocation
46
+ # rubocop:disable Performance/MapCompact
43
47
  def filenames=(other)
44
48
  @filenames = Array(other)
45
49
  .map { |o| Pathname.new(o) }
46
50
  .compact
47
51
  end
48
- # rubocop:enable Performance/ChainArrayAllocation
52
+ # rubocop:enable Performance/MapCompact
49
53
 
50
54
  def namespaces=(other)
51
55
  @namespaces = other + %w{signature}
@@ -14,6 +14,8 @@ module Chamber
14
14
  class NamespaceSet
15
15
  include Enumerable
16
16
 
17
+ attr_reader :raw_namespaces
18
+
17
19
  ###
18
20
  # Internal: Allows for more compact NamespaceSet creation by giving a list of
19
21
  # namespace values.
@@ -28,8 +30,6 @@ class NamespaceSet
28
30
  new(namespace_values)
29
31
  end
30
32
 
31
- attr_reader :raw_namespaces
32
-
33
33
  ###
34
34
  # Internal: Creates a new NamespaceSet from arrays, hashes and sets.
35
35
  #
data/lib/chamber/rails.rb CHANGED
@@ -1,3 +1,3 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'chamber/integrations/rails' if defined?(::Rails)
3
+ require 'chamber/integrations/rails' if defined?(Rails)
@@ -4,50 +4,26 @@ module Chamber
4
4
  module Refinements
5
5
  module DeepDup
6
6
  refine ::Array do
7
- unless method_defined?(:deep_dup)
8
- def deep_dup
9
- map do |i|
10
- if i.respond_to?(:deep_dup)
11
- i.deep_dup
12
- else
13
- begin
14
- i.dup
15
- rescue ::TypeError
16
- # Hack for < Ruby 2.4 since FalseClass, TrueClass, Fixnum, etc can't be
17
- # dupped
18
- i
19
- end
20
- end
21
- end
22
- end
7
+ def deep_dup
8
+ map { |i| i.respond_to?(:deep_dup) ? i.deep_dup : i.dup }
23
9
  end
24
10
  end
25
11
 
26
12
  refine ::Object do
27
- unless method_defined?(:deep_dup)
28
- def deep_dup
29
- begin
30
- dup
31
- rescue ::TypeError
32
- # Hack for < Ruby 2.4 since FalseClass, TrueClass, Fixnum, etc can't be
33
- # dupped
34
- self
35
- end
36
- end
13
+ def deep_dup
14
+ dup
37
15
  end
38
16
  end
39
17
 
40
18
  refine ::Hash do
41
- unless method_defined?(:deep_dup)
42
- def deep_dup
43
- dup.tap do |hash|
44
- each_pair do |key, value|
45
- if key.frozen? && key.is_a?(::String)
46
- hash[key] = value.deep_dup
47
- else
48
- hash.delete(key)
49
- hash[key.deep_dup] = value.deep_dup
50
- end
19
+ def deep_dup
20
+ dup.tap do |hash|
21
+ each_pair do |key, value|
22
+ if key.frozen? && key.is_a?(::String)
23
+ hash[key] = value.deep_dup
24
+ else
25
+ hash.delete(key)
26
+ hash[key.deep_dup] = value.deep_dup
51
27
  end
52
28
  end
53
29
  end
@@ -1,34 +1,22 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require 'chamber/errors/non_conforming_key'
4
+
3
5
  module Chamber
4
6
  module Refinements
5
7
  class Enumerable
6
- def self.deep_transform_keys(object, &block)
8
+ def self.deep_validate_keys(object, &block)
7
9
  case object
8
10
  when ::Hash
9
- object.each_with_object({}) do |(key, value), result|
10
- result[yield(key)] = deep_transform_keys(value, &block)
11
- end
12
- when ::Array
13
- object.map { |e| deep_transform_keys(e, &block) }
14
- else
15
- object
16
- end
17
- end
11
+ object.each do |(key, value)|
12
+ fail ::Chamber::Errors::NonConformingKey unless key == yield(key)
18
13
 
19
- def self.deep_transform_values(key, value, &block)
20
- case value
21
- when ::Hash
22
- value.each_with_object({}) do |(k, v), memo|
23
- memo[k] = deep_transform_values(k, v, &block)
14
+ deep_validate_keys(value, &block)
24
15
  end
25
16
  when ::Array
26
- yield(
27
- key,
28
- value.map { |v| deep_transform_values(nil, v, &block) }
29
- )
17
+ object.map { |v| deep_validate_keys(v, &block) }
30
18
  else
31
- yield(key, value)
19
+ object
32
20
  end
33
21
  end
34
22
  end
@@ -1,47 +1,21 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'rspectacular'
4
- require 'chamber/refinements/hash'
5
- require 'chamber/refinements/enumerable'
6
-
7
3
  module Chamber
8
4
  module Refinements
9
5
  module Hash
10
6
  refine ::Hash do
11
- def deep_strip!
12
- each do |key, value|
13
- if value.respond_to?(:strip)
14
- self[key] = value.strip
15
- elsif value.respond_to?(:deep_strip!)
16
- self[key] = value.deep_strip!
17
- end
18
- end
19
- end
20
-
21
- def deep_transform_keys(&block)
22
- Refinements::Enumerable.deep_transform_keys(self, &block)
23
- end
24
-
25
- def deep_transform_values(&block)
26
- Refinements::Enumerable.deep_transform_values(nil, self, &block)
27
- end
28
-
29
- unless method_defined?(:deep_merge)
30
- def deep_merge(other, &block)
31
- dup.deep_merge!(other, &block)
32
- end
7
+ def deep_merge(other_hash, &block)
8
+ dup.deep_merge!(other_hash, &block)
33
9
  end
34
10
 
35
- unless method_defined?(:deep_merge!)
36
- def deep_merge!(other, &block)
37
- merge!(other) do |key, value_1, value_2|
38
- if value_1.is_a?(::Hash) && value_2.is_a?(::Hash)
39
- value_1.deep_merge(value_2, &block)
40
- elsif block
41
- yield(key, value_1, value_2)
42
- else
43
- value_2
44
- end
11
+ def deep_merge!(other_hash, &block)
12
+ merge!(other_hash) do |key, this_val, other_val|
13
+ if this_val.is_a?(::Hash) && other_val.is_a?(::Hash)
14
+ this_val.deep_merge(other_val, &block)
15
+ elsif block
16
+ yield(key, this_val, other_val)
17
+ else
18
+ other_val
45
19
  end
46
20
  end
47
21
  end
@@ -5,7 +5,7 @@ require 'pathname'
5
5
  unless Pathname.instance_methods.include?(:write)
6
6
  class Pathname
7
7
  def write(*args)
8
- IO.write @path, *args
8
+ IO.write @path, *args # rubocop:disable Security/IoMethods
9
9
  end
10
10
  end
11
11
  end
@@ -1,5 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require 'chamber/errors/missing_index'
4
+ require 'chamber/errors/missing_setting'
3
5
  require 'chamber/namespace_set'
4
6
  require 'chamber/filters/namespace_filter'
5
7
  require 'chamber/filters/encryption_filter'
@@ -10,6 +12,7 @@ require 'chamber/filters/translate_secure_keys_filter'
10
12
  require 'chamber/filters/insecure_filter'
11
13
  require 'chamber/filters/failed_decryption_filter'
12
14
  require 'chamber/refinements/deep_dup'
15
+ require 'chamber/refinements/enumerable'
13
16
  require 'chamber/refinements/hash'
14
17
 
15
18
  ###
@@ -26,7 +29,6 @@ class Settings
26
29
  :pre_filters,
27
30
  :secure_key_prefix
28
31
  attr_reader :namespaces
29
- attr_writer :raw_data
30
32
 
31
33
  # rubocop:disable Metrics/ParameterLists
32
34
  def initialize(
@@ -46,9 +48,12 @@ class Settings
46
48
  settings: {},
47
49
  **_args
48
50
  )
49
- self.decryption_keys = decryption_keys
50
- self.encryption_keys = encryption_keys
51
- self.namespaces = namespaces
51
+
52
+ ::Chamber::Refinements::Enumerable.deep_validate_keys(settings, &:to_s)
53
+
54
+ self.decryption_keys = (decryption_keys || {}).transform_keys(&:to_s)
55
+ self.encryption_keys = (encryption_keys || {}).transform_keys(&:to_s)
56
+ self.namespaces = NamespaceSet.new(namespaces)
52
57
  self.post_filters = post_filters
53
58
  self.pre_filters = pre_filters
54
59
  self.raw_data = settings.deep_dup
@@ -114,7 +119,7 @@ class Settings
114
119
  # Returns a Hash
115
120
  #
116
121
  def to_hash
117
- data.dup
122
+ data.deep_dup
118
123
  end
119
124
 
120
125
  ###
@@ -147,11 +152,11 @@ class Settings
147
152
  flattened_name_hash = {}
148
153
 
149
154
  hash.each_pair do |key, value|
150
- flattened_name_components = parent_keys.deep_dup.push(key)
155
+ flattened_name_components = parent_keys.dup.push(key)
151
156
 
152
157
  if value.respond_to?(:each_pair)
153
- flattened_name_hash
154
- .deep_merge!(to_flattened_name_hash(value, flattened_name_components))
158
+ flattened_name_hash.merge! to_flattened_name_hash(value,
159
+ flattened_name_components)
155
160
  else
156
161
  flattened_name_hash[flattened_name_components] = value
157
162
  end
@@ -197,7 +202,7 @@ class Settings
197
202
  other_settings = case other
198
203
  when Settings
199
204
  other
200
- when ::Hash
205
+ when Hash
201
206
  Settings.new(settings: other)
202
207
  end
203
208
 
@@ -233,10 +238,13 @@ class Settings
233
238
  end
234
239
 
235
240
  def [](key)
236
- warn "WARNING: Bracket access will require strings instead of symbols in Chamber 3.0. You attempted to access the '#{key}' setting. See https://github.com/thekompanee/chamber/wiki/Upgrading-To-Chamber-3.0#removal-of-bracket-indifferent-access for full details." if key.is_a?(::Symbol) # rubocop:disable Layout/LineLength
237
- warn "WARNING: Accessing a non-existent key ('#{key}') with brackets will fail in Chamber 3.0. See https://github.com/thekompanee/chamber/wiki/Upgrading-To-Chamber-3.0#bracket-access-now-fails-on-non-existent-keys for full details." unless data.has_key?(key) # rubocop:disable Layout/LineLength
241
+ fail ::Chamber::Errors::InvalidKeyType, 'Bracket access with anything other than a String is unsupported.' unless key.is_a?(::String)
238
242
 
239
243
  data.fetch(key)
244
+ rescue ::KeyError => error
245
+ missing_setting_name = error.message.gsub(/.*key not found: "([^"]+)".*/, '\1')
246
+
247
+ raise ::Chamber::Errors::MissingSetting.new(missing_setting_name, [])
240
248
  end
241
249
 
242
250
  def dig!(*args)
@@ -245,23 +253,33 @@ class Settings
245
253
 
246
254
  data_value.fetch(key)
247
255
  end
256
+ rescue ::KeyError => error
257
+ missing_setting_name = error.message.gsub(/.*key not found: "([^"]+)".*/, '\1')
258
+
259
+ raise ::Chamber::Errors::MissingSetting.new(missing_setting_name, args)
260
+ rescue ::IndexError => error
261
+ missing_index_number = error.message.gsub(/.*index (\d+) outside.*/, '\1')
262
+
263
+ raise ::Chamber::Errors::MissingIndex.new(missing_index_number, args)
248
264
  end
249
265
 
250
266
  def dig(*args)
251
267
  dig!(*args)
252
- rescue ::KeyError, ::IndexError # rubocop:disable Lint/ShadowedException
268
+ rescue ::Chamber::Errors::MissingSetting,
269
+ ::Chamber::Errors::MissingIndex
270
+
253
271
  nil
254
272
  end
255
273
 
256
274
  def securable
257
- Settings.new(**metadata.deep_merge(
275
+ Settings.new(**metadata.merge(
258
276
  settings: raw_data,
259
277
  pre_filters: [Filters::SecureFilter],
260
278
  ))
261
279
  end
262
280
 
263
281
  def secure
264
- Settings.new(**metadata.deep_merge(
282
+ Settings.new(**metadata.merge(
265
283
  settings: raw_data,
266
284
  pre_filters: [Filters::EncryptionFilter],
267
285
  post_filters: [Filters::TranslateSecureKeysFilter],
@@ -269,7 +287,7 @@ class Settings
269
287
  end
270
288
 
271
289
  def insecure
272
- Settings.new(**metadata.deep_merge(
290
+ Settings.new(**metadata.merge(
273
291
  settings: raw_data,
274
292
  pre_filters: [Filters::InsecureFilter],
275
293
  post_filters: [Filters::TranslateSecureKeysFilter],
@@ -278,23 +296,21 @@ class Settings
278
296
 
279
297
  protected
280
298
 
281
- def namespaces=(raw_namespaces)
282
- @namespaces = NamespaceSet.new(raw_namespaces)
283
- end
299
+ attr_writer :namespaces,
300
+ :raw_data
284
301
 
285
302
  # rubocop:disable Naming/MemoizedInstanceVariableName
286
303
  def raw_data
287
304
  @filtered_raw_data ||= pre_filters.inject(@raw_data) do |filtered_data, filter|
288
- filter.execute(**{ data: filtered_data }.deep_merge(metadata))
305
+ filter.execute(**{ data: filtered_data }.merge(metadata))
289
306
  end
290
307
  end
291
308
  # rubocop:enable Naming/MemoizedInstanceVariableName
292
309
 
293
310
  def data
294
- @data ||= post_filters
295
- .inject(raw_data) do |filtered_data, filter|
296
- filter.execute(**{ data: filtered_data }.deep_merge(metadata))
297
- end
311
+ @data ||= post_filters.inject(raw_data) do |filtered_data, filter|
312
+ filter.execute(**{ data: filtered_data }.merge(metadata))
313
+ end
298
314
  end
299
315
 
300
316
  def metadata