chamber 3.0.0rc1 → 3.0.0

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