anyway_config 2.0.6 → 2.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +199 -181
- data/README.md +69 -9
- data/lib/.rbnext/1995.next/anyway/config.rb +391 -0
- data/lib/.rbnext/1995.next/anyway/dynamic_config.rb +27 -0
- data/lib/.rbnext/1995.next/anyway/env.rb +56 -0
- data/lib/.rbnext/1995.next/anyway/loaders/base.rb +21 -0
- data/lib/.rbnext/1995.next/anyway/tracing.rb +181 -0
- data/lib/.rbnext/2.7/anyway/config.rb +12 -14
- data/lib/.rbnext/2.7/anyway/rails/loaders/yaml.rb +30 -0
- data/lib/.rbnext/2.7/anyway/settings.rb +79 -0
- data/lib/.rbnext/2.7/anyway/tracing.rb +8 -6
- data/lib/.rbnext/{2.8 → 3.0}/anyway/config.rb +12 -14
- data/lib/.rbnext/{2.8 → 3.0}/anyway/loaders.rb +0 -0
- data/lib/.rbnext/{2.8 → 3.0}/anyway/loaders/base.rb +0 -0
- data/lib/.rbnext/{2.8 → 3.0}/anyway/tracing.rb +8 -6
- data/lib/anyway/config.rb +26 -28
- data/lib/anyway/dynamic_config.rb +1 -1
- data/lib/anyway/env.rb +1 -1
- data/lib/anyway/ext/deep_dup.rb +6 -0
- data/lib/anyway/ext/hash.rb +0 -12
- data/lib/anyway/loaders/base.rb +1 -1
- data/lib/anyway/loaders/yaml.rb +3 -3
- data/lib/anyway/rails/loaders/credentials.rb +2 -2
- data/lib/anyway/rails/loaders/secrets.rb +1 -1
- data/lib/anyway/rails/loaders/yaml.rb +11 -0
- data/lib/anyway/rails/settings.rb +6 -0
- data/lib/anyway/settings.rb +52 -2
- data/lib/anyway/tracing.rb +4 -4
- data/lib/anyway/utils/deep_merge.rb +21 -0
- data/lib/anyway/version.rb +1 -1
- data/lib/anyway_config.rb +2 -0
- metadata +18 -10
@@ -34,11 +34,13 @@ module Anyway
|
|
34
34
|
|
35
35
|
def record_value(val, *path, **opts)
|
36
36
|
key = path.pop
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
37
|
+
(__m__ = if val.is_a?(Hash)
|
38
|
+
Trace.new.tap { |_1|
|
39
|
+
_1.merge_values(val, **opts)
|
40
|
+
}
|
41
|
+
else
|
42
|
+
Trace.new(:value, val, **opts)
|
43
|
+
end) && (((trace = __m__) || true) || Kernel.raise(NoMatchingPatternError, __m__.inspect))
|
42
44
|
|
43
45
|
target_trace = path.empty? ? self : value.dig(*path)
|
44
46
|
target_trace.value[key.to_s] = trace
|
@@ -141,7 +143,7 @@ module Anyway
|
|
141
143
|
|
142
144
|
def current_trace() ; trace_stack.last; end
|
143
145
|
|
144
|
-
|
146
|
+
alias_method :tracing?, :current_trace
|
145
147
|
|
146
148
|
def source_stack
|
147
149
|
(Thread.current[:__anyway__trace_source_stack__] ||= [])
|
@@ -19,7 +19,7 @@ module Anyway # :nodoc:
|
|
19
19
|
# Provides `attr_config` method to describe
|
20
20
|
# configuration parameters and set defaults
|
21
21
|
class Config
|
22
|
-
PARAM_NAME = /^[a-z_](
|
22
|
+
PARAM_NAME = /^[a-z_](\w+)?$/
|
23
23
|
|
24
24
|
# List of names that couldn't be used as config names
|
25
25
|
# (the class instance methods we use)
|
@@ -40,12 +40,14 @@ module Anyway # :nodoc:
|
|
40
40
|
raise_validation_error
|
41
41
|
reload
|
42
42
|
resolve_config_path
|
43
|
+
tap
|
43
44
|
to_h
|
44
45
|
to_source_trace
|
45
46
|
write_config_attr
|
46
47
|
].freeze
|
47
48
|
|
48
49
|
class Error < StandardError; end
|
50
|
+
|
49
51
|
class ValidationError < Error; end
|
50
52
|
|
51
53
|
include OptparseConfig
|
@@ -142,9 +144,9 @@ module Anyway # :nodoc:
|
|
142
144
|
end
|
143
145
|
|
144
146
|
def on_load(*names, &block)
|
145
|
-
raise ArgumentError, "Either methods or block should be specified, not both" if
|
147
|
+
raise ArgumentError, "Either methods or block should be specified, not both" if block && !names.empty?
|
146
148
|
|
147
|
-
if
|
149
|
+
if block
|
148
150
|
load_callbacks << BlockCallback.new(block)
|
149
151
|
else
|
150
152
|
load_callbacks.push(*names.map { NamedCallback.new(_1) })
|
@@ -201,8 +203,7 @@ module Anyway # :nodoc:
|
|
201
203
|
accessors_module.module_eval <<~RUBY, __FILE__, __LINE__ + 1
|
202
204
|
def #{name}=(val)
|
203
205
|
__trace__&.record_value(val, \"#{name}\", **Tracing.current_trace_source)
|
204
|
-
|
205
|
-
@#{name} = values[:#{name}] = val
|
206
|
+
values[:#{name}] = val
|
206
207
|
end
|
207
208
|
|
208
209
|
def #{name}
|
@@ -229,7 +230,7 @@ module Anyway # :nodoc:
|
|
229
230
|
# handle two cases:
|
230
231
|
# - SomeModule::Config => "some_module"
|
231
232
|
# - SomeConfig => "some"
|
232
|
-
unless name =~ /^(\w+)(
|
233
|
+
unless name =~ /^(\w+)(::)?Config$/
|
233
234
|
raise "Couldn't infer config name, please, specify it explicitly" \
|
234
235
|
"via `config_name :my_config`"
|
235
236
|
end
|
@@ -288,17 +289,14 @@ module Anyway # :nodoc:
|
|
288
289
|
trace = Tracing.capture do
|
289
290
|
Tracing.trace!(:defaults) { base_config }
|
290
291
|
|
291
|
-
|
292
|
-
|
293
|
-
|
294
|
-
env_prefix: env_prefix,
|
295
|
-
config_path: resolve_config_path(config_name, env_prefix)
|
296
|
-
)
|
292
|
+
config_path = resolve_config_path(config_name, env_prefix)
|
293
|
+
|
294
|
+
load_from_sources(base_config, name: config_name, env_prefix: env_prefix, config_path: config_path)
|
297
295
|
|
298
296
|
if overrides
|
299
297
|
Tracing.trace!(:load) { overrides }
|
300
298
|
|
301
|
-
|
299
|
+
Utils.deep_merge!(base_config, overrides)
|
302
300
|
end
|
303
301
|
end
|
304
302
|
|
@@ -321,7 +319,7 @@ module Anyway # :nodoc:
|
|
321
319
|
|
322
320
|
def load_from_sources(base_config, **options)
|
323
321
|
Anyway.loaders.each do |(_id, loader)|
|
324
|
-
|
322
|
+
Utils.deep_merge!(base_config, loader.call(**options))
|
325
323
|
end
|
326
324
|
base_config
|
327
325
|
end
|
File without changes
|
File without changes
|
@@ -34,11 +34,13 @@ module Anyway
|
|
34
34
|
|
35
35
|
def record_value(val, *path, **opts)
|
36
36
|
key = path.pop
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
37
|
+
(__m__ = if val.is_a?(Hash)
|
38
|
+
Trace.new.tap {
|
39
|
+
_1.merge_values(val, **opts)
|
40
|
+
}
|
41
|
+
else
|
42
|
+
Trace.new(:value, val, **opts)
|
43
|
+
end) && (((trace = __m__) || true) || Kernel.raise(NoMatchingPatternError, __m__.inspect))
|
42
44
|
|
43
45
|
target_trace = path.empty? ? self : value.dig(*path)
|
44
46
|
target_trace.value[key.to_s] = trace
|
@@ -141,7 +143,7 @@ module Anyway
|
|
141
143
|
|
142
144
|
def current_trace() ; trace_stack.last; end
|
143
145
|
|
144
|
-
|
146
|
+
alias_method :tracing?, :current_trace
|
145
147
|
|
146
148
|
def source_stack
|
147
149
|
(Thread.current[:__anyway__trace_source_stack__] ||= [])
|
data/lib/anyway/config.rb
CHANGED
@@ -19,7 +19,7 @@ module Anyway # :nodoc:
|
|
19
19
|
# Provides `attr_config` method to describe
|
20
20
|
# configuration parameters and set defaults
|
21
21
|
class Config
|
22
|
-
PARAM_NAME = /^[a-z_](
|
22
|
+
PARAM_NAME = /^[a-z_](\w+)?$/
|
23
23
|
|
24
24
|
# List of names that couldn't be used as config names
|
25
25
|
# (the class instance methods we use)
|
@@ -40,12 +40,14 @@ module Anyway # :nodoc:
|
|
40
40
|
raise_validation_error
|
41
41
|
reload
|
42
42
|
resolve_config_path
|
43
|
+
tap
|
43
44
|
to_h
|
44
45
|
to_source_trace
|
45
46
|
write_config_attr
|
46
47
|
].freeze
|
47
48
|
|
48
49
|
class Error < StandardError; end
|
50
|
+
|
49
51
|
class ValidationError < Error; end
|
50
52
|
|
51
53
|
include OptparseConfig
|
@@ -106,21 +108,21 @@ module Anyway # :nodoc:
|
|
106
108
|
def defaults
|
107
109
|
return @defaults if instance_variable_defined?(:@defaults)
|
108
110
|
|
109
|
-
if superclass < Anyway::Config
|
111
|
+
@defaults = if superclass < Anyway::Config
|
110
112
|
superclass.defaults.deep_dup
|
111
113
|
else
|
112
114
|
new_empty_config
|
113
|
-
end
|
115
|
+
end
|
114
116
|
end
|
115
117
|
|
116
118
|
def config_attributes
|
117
119
|
return @config_attributes if instance_variable_defined?(:@config_attributes)
|
118
120
|
|
119
|
-
if superclass < Anyway::Config
|
121
|
+
@config_attributes = if superclass < Anyway::Config
|
120
122
|
superclass.config_attributes.dup
|
121
123
|
else
|
122
124
|
[]
|
123
|
-
end
|
125
|
+
end
|
124
126
|
end
|
125
127
|
|
126
128
|
def required(*names)
|
@@ -134,17 +136,17 @@ module Anyway # :nodoc:
|
|
134
136
|
def required_attributes
|
135
137
|
return @required_attributes if instance_variable_defined?(:@required_attributes)
|
136
138
|
|
137
|
-
if superclass < Anyway::Config
|
139
|
+
@required_attributes = if superclass < Anyway::Config
|
138
140
|
superclass.required_attributes.dup
|
139
141
|
else
|
140
142
|
[]
|
141
|
-
end
|
143
|
+
end
|
142
144
|
end
|
143
145
|
|
144
146
|
def on_load(*names, &block)
|
145
|
-
raise ArgumentError, "Either methods or block should be specified, not both" if
|
147
|
+
raise ArgumentError, "Either methods or block should be specified, not both" if block && !names.empty?
|
146
148
|
|
147
|
-
if
|
149
|
+
if block
|
148
150
|
load_callbacks << BlockCallback.new(block)
|
149
151
|
else
|
150
152
|
load_callbacks.push(*names.map { NamedCallback.new(_1) })
|
@@ -154,11 +156,11 @@ module Anyway # :nodoc:
|
|
154
156
|
def load_callbacks
|
155
157
|
return @load_callbacks if instance_variable_defined?(:@load_callbacks)
|
156
158
|
|
157
|
-
if superclass <= Anyway::Config
|
159
|
+
@load_callbacks = if superclass <= Anyway::Config
|
158
160
|
superclass.load_callbacks.dup
|
159
161
|
else
|
160
162
|
[]
|
161
|
-
end
|
163
|
+
end
|
162
164
|
end
|
163
165
|
|
164
166
|
def config_name(val = nil)
|
@@ -185,11 +187,11 @@ module Anyway # :nodoc:
|
|
185
187
|
|
186
188
|
return @env_prefix if instance_variable_defined?(:@env_prefix)
|
187
189
|
|
188
|
-
if superclass < Anyway::Config && superclass.explicit_config_name?
|
190
|
+
@env_prefix = if superclass < Anyway::Config && superclass.explicit_config_name?
|
189
191
|
superclass.env_prefix
|
190
192
|
else
|
191
193
|
config_name.upcase
|
192
|
-
end
|
194
|
+
end
|
193
195
|
end
|
194
196
|
|
195
197
|
def new_empty_config() = {}
|
@@ -201,8 +203,7 @@ module Anyway # :nodoc:
|
|
201
203
|
accessors_module.module_eval <<~RUBY, __FILE__, __LINE__ + 1
|
202
204
|
def #{name}=(val)
|
203
205
|
__trace__&.record_value(val, \"#{name}\", **Tracing.current_trace_source)
|
204
|
-
|
205
|
-
@#{name} = values[:#{name}] = val
|
206
|
+
values[:#{name}] = val
|
206
207
|
end
|
207
208
|
|
208
209
|
def #{name}
|
@@ -215,9 +216,9 @@ module Anyway # :nodoc:
|
|
215
216
|
def accessors_module
|
216
217
|
return @accessors_module if instance_variable_defined?(:@accessors_module)
|
217
218
|
|
218
|
-
Module.new.tap do |mod|
|
219
|
+
@accessors_module = Module.new.tap do |mod|
|
219
220
|
include mod
|
220
|
-
end
|
221
|
+
end
|
221
222
|
end
|
222
223
|
|
223
224
|
def build_config_name
|
@@ -229,7 +230,7 @@ module Anyway # :nodoc:
|
|
229
230
|
# handle two cases:
|
230
231
|
# - SomeModule::Config => "some_module"
|
231
232
|
# - SomeConfig => "some"
|
232
|
-
unless name =~ /^(\w+)(
|
233
|
+
unless name =~ /^(\w+)(::)?Config$/
|
233
234
|
raise "Couldn't infer config name, please, specify it explicitly" \
|
234
235
|
"via `config_name :my_config`"
|
235
236
|
end
|
@@ -285,22 +286,19 @@ module Anyway # :nodoc:
|
|
285
286
|
def load(overrides = nil)
|
286
287
|
base_config = self.class.defaults.deep_dup
|
287
288
|
|
288
|
-
Tracing.capture do
|
289
|
+
trace = Tracing.capture do
|
289
290
|
Tracing.trace!(:defaults) { base_config }
|
290
291
|
|
291
|
-
|
292
|
-
|
293
|
-
|
294
|
-
env_prefix: env_prefix,
|
295
|
-
config_path: resolve_config_path(config_name, env_prefix)
|
296
|
-
)
|
292
|
+
config_path = resolve_config_path(config_name, env_prefix)
|
293
|
+
|
294
|
+
load_from_sources(base_config, name: config_name, env_prefix:, config_path:)
|
297
295
|
|
298
296
|
if overrides
|
299
297
|
Tracing.trace!(:load) { overrides }
|
300
298
|
|
301
|
-
|
299
|
+
Utils.deep_merge!(base_config, overrides)
|
302
300
|
end
|
303
|
-
end
|
301
|
+
end
|
304
302
|
|
305
303
|
base_config.each do |key, val|
|
306
304
|
write_config_attr(key.to_sym, val)
|
@@ -321,7 +319,7 @@ module Anyway # :nodoc:
|
|
321
319
|
|
322
320
|
def load_from_sources(base_config, **options)
|
323
321
|
Anyway.loaders.each do |(_id, loader)|
|
324
|
-
|
322
|
+
Utils.deep_merge!(base_config, loader.call(**options))
|
325
323
|
end
|
326
324
|
base_config
|
327
325
|
end
|
@@ -16,7 +16,7 @@ module Anyway
|
|
16
16
|
config = allocate
|
17
17
|
options[:env_prefix] ||= name.to_s.upcase
|
18
18
|
options[:config_path] ||= config.resolve_config_path(name, options[:env_prefix])
|
19
|
-
config.load_from_sources(new_empty_config, name
|
19
|
+
config.load_from_sources(new_empty_config, name:, **options)
|
20
20
|
end
|
21
21
|
end
|
22
22
|
|
data/lib/anyway/env.rb
CHANGED
@@ -49,7 +49,7 @@ module Anyway
|
|
49
49
|
path = key.sub(/^#{prefix}_/, "").downcase
|
50
50
|
|
51
51
|
paths = path.split("__")
|
52
|
-
trace!(:env, *paths, key:
|
52
|
+
trace!(:env, *paths, key:) { data.bury(type_cast.call(val), *paths) }
|
53
53
|
end
|
54
54
|
end
|
55
55
|
end
|
data/lib/anyway/ext/deep_dup.rb
CHANGED
data/lib/anyway/ext/hash.rb
CHANGED
@@ -5,18 +5,6 @@ module Anyway
|
|
5
5
|
# Extend Hash through refinements
|
6
6
|
module Hash
|
7
7
|
refine ::Hash do
|
8
|
-
# From ActiveSupport http://api.rubyonrails.org/classes/Hash.html#method-i-deep_merge
|
9
|
-
def deep_merge!(other_hash)
|
10
|
-
merge!(other_hash) do |key, this_value, other_value|
|
11
|
-
if this_value.is_a?(::Hash) && other_value.is_a?(::Hash)
|
12
|
-
this_value.deep_merge!(other_value)
|
13
|
-
this_value
|
14
|
-
else
|
15
|
-
other_value
|
16
|
-
end
|
17
|
-
end
|
18
|
-
end
|
19
|
-
|
20
8
|
def stringify_keys!
|
21
9
|
keys.each do |key|
|
22
10
|
value = delete(key)
|
data/lib/anyway/loaders/base.rb
CHANGED
data/lib/anyway/loaders/yaml.rb
CHANGED
@@ -17,7 +17,7 @@ module Anyway
|
|
17
17
|
local_path = local_config_path(config_path)
|
18
18
|
local_config = trace!(:yml, path: relative_config_path(local_path).to_s) { load_local_yml(local_path) }
|
19
19
|
|
20
|
-
|
20
|
+
Utils.deep_merge!(base_config, local_config)
|
21
21
|
end
|
22
22
|
|
23
23
|
private
|
@@ -32,8 +32,8 @@ module Anyway
|
|
32
32
|
end
|
33
33
|
end
|
34
34
|
|
35
|
-
|
36
|
-
|
35
|
+
alias_method :load_base_yml, :parse_yml
|
36
|
+
alias_method :load_local_yml, :parse_yml
|
37
37
|
|
38
38
|
def local_config_path(path)
|
39
39
|
path.sub(/\.yml/, ".local.yml")
|
@@ -24,13 +24,13 @@ module Anyway
|
|
24
24
|
) do
|
25
25
|
::Rails.application.credentials.public_send(name)
|
26
26
|
end.then do |creds|
|
27
|
-
|
27
|
+
Utils.deep_merge!(config, creds) if creds
|
28
28
|
end
|
29
29
|
|
30
30
|
if use_local?
|
31
31
|
trace!(:credentials, store: LOCAL_CONTENT_PATH) do
|
32
32
|
local_credentials(name)
|
33
|
-
end.then { |creds|
|
33
|
+
end.then { |creds| Utils.deep_merge!(config, creds) if creds }
|
34
34
|
end
|
35
35
|
|
36
36
|
config
|
@@ -5,11 +5,22 @@ module Anyway
|
|
5
5
|
module Loaders
|
6
6
|
class YAML < Anyway::Loaders::YAML
|
7
7
|
def load_base_yml(*)
|
8
|
+
parsed_yml = super
|
9
|
+
return parsed_yml unless environmental?(parsed_yml)
|
10
|
+
|
8
11
|
super[::Rails.env] || {}
|
9
12
|
end
|
10
13
|
|
11
14
|
private
|
12
15
|
|
16
|
+
def environmental?(parsed_yml)
|
17
|
+
return true unless Settings.future.unwrap_known_environments
|
18
|
+
# likely
|
19
|
+
return true if parsed_yml.key?(::Rails.env)
|
20
|
+
# less likely
|
21
|
+
::Rails.application.config.anyway_config.known_environments.any? { parsed_yml.key?(_1) }
|
22
|
+
end
|
23
|
+
|
13
24
|
def relative_config_path(path)
|
14
25
|
Pathname.new(path).relative_path_from(::Rails.root)
|
15
26
|
end
|
@@ -9,8 +9,13 @@ end
|
|
9
9
|
|
10
10
|
module Anyway
|
11
11
|
class Settings
|
12
|
+
class Future
|
13
|
+
setting :unwrap_known_environments, true
|
14
|
+
end
|
15
|
+
|
12
16
|
class << self
|
13
17
|
attr_reader :autoload_static_config_path, :autoloader
|
18
|
+
attr_accessor :known_environments
|
14
19
|
|
15
20
|
if defined?(::Zeitwerk)
|
16
21
|
def autoload_static_config_path=(val)
|
@@ -56,5 +61,6 @@ module Anyway
|
|
56
61
|
end
|
57
62
|
|
58
63
|
self.default_config_path = ->(name) { ::Rails.root.join("config", "#{name}.yml") }
|
64
|
+
self.known_environments = %w[test development production]
|
59
65
|
end
|
60
66
|
end
|