anyway_config 2.0.2 → 2.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.
@@ -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: name, **options)
19
+ config.load_from_sources(new_empty_config, name:, **options)
20
20
  end
21
21
  end
22
22
 
@@ -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: key) { data.bury(type_cast.call(val), *paths) }
52
+ trace!(:env, *paths, key:) { data.bury(type_cast.call(val), *paths) }
53
53
  end
54
54
  end
55
55
  end
@@ -30,6 +30,12 @@ module Anyway
30
30
  end
31
31
  end
32
32
 
33
+ refine ::Object do
34
+ def deep_dup
35
+ dup
36
+ end
37
+ end
38
+
33
39
  using self
34
40
  end
35
41
  end
@@ -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)
@@ -55,9 +55,7 @@ module Anyway
55
55
  registry.each(&block)
56
56
  end
57
57
 
58
- def freeze
59
- registry.freeze
60
- end
58
+ def freeze() = registry.freeze
61
59
 
62
60
  private
63
61
 
@@ -7,7 +7,7 @@ module Anyway
7
7
 
8
8
  class << self
9
9
  def call(local: Anyway::Settings.use_local_files, **opts)
10
- new(local: local).call(**opts)
10
+ new(local:).call(**opts)
11
11
  end
12
12
  end
13
13
 
@@ -15,9 +15,7 @@ module Anyway
15
15
  @local = local
16
16
  end
17
17
 
18
- def use_local?
19
- @local == true
20
- end
18
+ def use_local?() = @local == true
21
19
  end
22
20
  end
23
21
  end
@@ -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
- base_config.deep_merge!(local_config)
20
+ Utils.deep_merge!(base_config, local_config)
21
21
  end
22
22
 
23
23
  private
@@ -26,14 +26,14 @@ module Anyway
26
26
  return {} unless File.file?(path)
27
27
  require "yaml" unless defined?(::YAML)
28
28
  if defined?(ERB)
29
- ::YAML.safe_load(ERB.new(File.read(path)).result, [], [], true)
29
+ ::YAML.load(ERB.new(File.read(path)).result) # rubocop:disable Security/YAMLLoad
30
30
  else
31
31
  ::YAML.load_file(path)
32
32
  end
33
33
  end
34
34
 
35
- alias load_base_yml parse_yml
36
- alias load_local_yml parse_yml
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
- config.deep_merge!(creds) if creds
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| config.deep_merge!(creds) if creds }
33
+ end.then { |creds| Utils.deep_merge!(config, creds) if creds }
34
34
  end
35
35
 
36
36
  config
@@ -15,7 +15,7 @@ module Anyway
15
15
  trace!(:secrets) do
16
16
  secrets.public_send(name)
17
17
  end.then do |secrets|
18
- config.deep_merge!(secrets) if secrets
18
+ Utils.deep_merge!(config, secrets) if secrets
19
19
  end
20
20
 
21
21
  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
@@ -5,16 +5,66 @@ module Anyway
5
5
  #
6
6
  # Settings contain the library-wide configuration.
7
7
  class Settings
8
+ # Future encapsulates settings that will be introduced in the upcoming version
9
+ # with the default values, which could break compatibility
10
+ class Future
11
+ class << self
12
+ def setting(name, default_value)
13
+ settings[name] = default_value
14
+
15
+ define_method(name) do
16
+ store[name]
17
+ end
18
+
19
+ define_method(:"#{name}=") do |val|
20
+ store[name] = val
21
+ end
22
+ end
23
+
24
+ def settings
25
+ @settings ||= {}
26
+ end
27
+ end
28
+
29
+ def initialize
30
+ @store = {}
31
+ end
32
+
33
+ def use(*names)
34
+ store.clear
35
+ names.each { store[_1] = self.class.settings[_1] }
36
+ end
37
+
38
+ private
39
+
40
+ attr_reader :store
41
+ end
42
+
8
43
  class << self
9
44
  # Define whether to load data from
10
45
  # *.yml.local (or credentials/local.yml.enc)
11
46
  attr_accessor :use_local_files
12
47
 
13
- # Return a path to YML config file given the config name
14
- attr_accessor :default_config_path
48
+ # A proc returning a path to YML config file given the config name
49
+ attr_reader :default_config_path
50
+
51
+ def default_config_path=(val)
52
+ if val.is_a?(Proc)
53
+ @default_config_path = val
54
+ return
55
+ end
56
+
57
+ val = val.to_s
58
+
59
+ @default_config_path = ->(name) { File.join(val, "#{name}.yml") }
60
+ end
15
61
 
16
62
  # Enable source tracing
17
63
  attr_accessor :tracing_enabled
64
+
65
+ def future
66
+ @future ||= Future.new
67
+ end
18
68
  end
19
69
 
20
70
  # By default, use local files only in development (that's the purpose if the local files)
@@ -2,7 +2,7 @@
2
2
 
3
3
  require "anyway/testing/helpers"
4
4
 
5
- if defined?(RSpec)
5
+ if defined?(RSpec::Core)
6
6
  RSpec.configure do |config|
7
7
  config.include(
8
8
  Anyway::Testing::Helpers,
@@ -13,9 +13,7 @@ module Anyway
13
13
  end
14
14
 
15
15
  refine Thread::Backtrace::Location do
16
- def path_lineno
17
- "#{path}:#{lineno}"
18
- end
16
+ def path_lineno() = "#{path}:#{lineno}"
19
17
  end
20
18
  end)
21
19
 
@@ -34,13 +32,14 @@ module Anyway
34
32
  value.dig(...)
35
33
  end
36
34
 
37
- def record_value(val, *path, key, **opts)
38
- trace =
39
- if val.is_a?(Hash)
40
- Trace.new.tap { _1.merge_values(val, **opts) }
41
- else
42
- Trace.new(:value, val, **opts)
43
- end
35
+ def record_value(val, *path, **opts)
36
+ key = path.pop
37
+ if val.is_a?(Hash)
38
+ Trace.new.tap { _1.merge_values(val, **opts) }
39
+ else
40
+ Trace.new(:value, val, **opts)
41
+ end => trace
42
+
44
43
  target_trace = path.empty? ? self : value.dig(*path)
45
44
  target_trace.value[key.to_s] = trace
46
45
 
@@ -79,25 +78,19 @@ module Anyway
79
78
  value.keep_if(...)
80
79
  end
81
80
 
82
- def clear
83
- value.clear
84
- end
81
+ def clear() = value.clear
85
82
 
86
- def trace?
87
- type == :trace
88
- end
83
+ def trace?() = type == :trace
89
84
 
90
85
  def to_h
91
86
  if trace?
92
87
  value.transform_values(&:to_h).tap { _1.default_proc = nil }
93
88
  else
94
- {value: value, source: source}
89
+ {value, source}
95
90
  end
96
91
  end
97
92
 
98
- def dup
99
- self.class.new(type, value.dup, source)
100
- end
93
+ def dup() = self.class.new(type, value.dup, **source)
101
94
 
102
95
  def pretty_print(q)
103
96
  if trace?
@@ -146,11 +139,9 @@ module Anyway
146
139
  (Thread.current[:__anyway__trace_stack__] ||= [])
147
140
  end
148
141
 
149
- def current_trace
150
- trace_stack.last
151
- end
142
+ def current_trace() = trace_stack.last
152
143
 
153
- alias tracing? current_trace
144
+ alias_method :tracing?, :current_trace
154
145
 
155
146
  def source_stack
156
147
  (Thread.current[:__anyway__trace_source_stack__] ||= [])
@@ -178,12 +169,11 @@ module Anyway
178
169
 
179
170
  def trace!(type, *path, **opts)
180
171
  return yield unless Tracing.tracing?
181
- source = {type: type}.merge(opts)
182
172
  val = yield
183
173
  if val.is_a?(Hash)
184
- Tracing.current_trace.merge_values(val, **source)
174
+ Tracing.current_trace.merge_values(val, type:, **opts)
185
175
  else
186
- Tracing.current_trace.record_value(val, *path, **source)
176
+ Tracing.current_trace.record_value(val, *path, type:, **opts)
187
177
  end
188
178
  val
189
179
  end
@@ -0,0 +1,21 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Anyway
4
+ using Anyway::Ext::DeepDup
5
+
6
+ module Utils
7
+ def self.deep_merge!(source, other)
8
+ other.each do |key, other_value|
9
+ this_value = source[key]
10
+
11
+ if this_value.is_a?(::Hash) && other_value.is_a?(::Hash)
12
+ deep_merge!(this_value, other_value)
13
+ else
14
+ source[key] = other_value.deep_dup
15
+ end
16
+ end
17
+
18
+ source
19
+ end
20
+ end
21
+ end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Anyway # :nodoc:
4
- VERSION = "2.0.2"
4
+ VERSION = "2.1.0"
5
5
  end
@@ -3,7 +3,7 @@
3
3
  require "ruby-next"
4
4
 
5
5
  require "ruby-next/language/setup"
6
- RubyNext::Language.setup_gem_load_path
6
+ RubyNext::Language.setup_gem_load_path(transpile: true)
7
7
 
8
8
  require "anyway/version"
9
9
 
@@ -11,6 +11,8 @@ require "anyway/ext/deep_dup"
11
11
  require "anyway/ext/deep_freeze"
12
12
  require "anyway/ext/hash"
13
13
 
14
+ require "anyway/utils/deep_merge"
15
+
14
16
  require "anyway/settings"
15
17
  require "anyway/tracing"
16
18
  require "anyway/config"
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: anyway_config
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.0.2
4
+ version: 2.1.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Vladimir Dementyev
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2020-04-24 00:00:00.000000000 Z
11
+ date: 2020-12-28 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: ruby-next-core
@@ -16,14 +16,14 @@ dependencies:
16
16
  requirements:
17
17
  - - ">="
18
18
  - !ruby/object:Gem::Version
19
- version: 0.5.1
19
+ version: 0.11.0
20
20
  type: :runtime
21
21
  prerelease: false
22
22
  version_requirements: !ruby/object:Gem::Requirement
23
23
  requirements:
24
24
  - - ">="
25
25
  - !ruby/object:Gem::Version
26
- version: 0.5.1
26
+ version: 0.11.0
27
27
  - !ruby/object:Gem::Dependency
28
28
  name: ammeter
29
29
  requirement: !ruby/object:Gem::Requirement
@@ -70,14 +70,14 @@ dependencies:
70
70
  name: rspec
71
71
  requirement: !ruby/object:Gem::Requirement
72
72
  requirements:
73
- - - "~>"
73
+ - - ">="
74
74
  - !ruby/object:Gem::Version
75
75
  version: '3.8'
76
76
  type: :development
77
77
  prerelease: false
78
78
  version_requirements: !ruby/object:Gem::Requirement
79
79
  requirements:
80
- - - "~>"
80
+ - - ">="
81
81
  - !ruby/object:Gem::Version
82
82
  version: '3.8'
83
83
  - !ruby/object:Gem::Dependency
@@ -86,14 +86,14 @@ dependencies:
86
86
  requirements:
87
87
  - - ">="
88
88
  - !ruby/object:Gem::Version
89
- version: '0.5'
89
+ version: '0.8'
90
90
  type: :development
91
91
  prerelease: false
92
92
  version_requirements: !ruby/object:Gem::Requirement
93
93
  requirements:
94
94
  - - ">="
95
95
  - !ruby/object:Gem::Version
96
- version: '0.5'
96
+ version: '0.8'
97
97
  description: "\n Configuration DSL for Ruby libraries and applications.\n Allows
98
98
  you to easily follow the twelve-factor application principles (https://12factor.net/config).\n
99
99
  \ "
@@ -106,10 +106,21 @@ files:
106
106
  - CHANGELOG.md
107
107
  - LICENSE.txt
108
108
  - README.md
109
+ - lib/.rbnext/1995.next/anyway/config.rb
110
+ - lib/.rbnext/1995.next/anyway/dynamic_config.rb
111
+ - lib/.rbnext/1995.next/anyway/env.rb
112
+ - lib/.rbnext/1995.next/anyway/loaders/base.rb
113
+ - lib/.rbnext/1995.next/anyway/tracing.rb
109
114
  - lib/.rbnext/2.7/anyway/auto_cast.rb
110
115
  - lib/.rbnext/2.7/anyway/config.rb
111
116
  - lib/.rbnext/2.7/anyway/option_parser_builder.rb
117
+ - lib/.rbnext/2.7/anyway/rails/loaders/yaml.rb
118
+ - lib/.rbnext/2.7/anyway/settings.rb
112
119
  - lib/.rbnext/2.7/anyway/tracing.rb
120
+ - lib/.rbnext/3.0/anyway/config.rb
121
+ - lib/.rbnext/3.0/anyway/loaders.rb
122
+ - lib/.rbnext/3.0/anyway/loaders/base.rb
123
+ - lib/.rbnext/3.0/anyway/tracing.rb
113
124
  - lib/anyway.rb
114
125
  - lib/anyway/auto_cast.rb
115
126
  - lib/anyway/config.rb
@@ -136,6 +147,7 @@ files:
136
147
  - lib/anyway/testing.rb
137
148
  - lib/anyway/testing/helpers.rb
138
149
  - lib/anyway/tracing.rb
150
+ - lib/anyway/utils/deep_merge.rb
139
151
  - lib/anyway/version.rb
140
152
  - lib/anyway_config.rb
141
153
  - lib/generators/anyway/app_config/USAGE