anyway_config 2.2.3 → 2.3.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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +10 -0
- data/README.md +34 -1
- data/lib/.rbnext/2.7/anyway/config.rb +28 -4
- data/lib/.rbnext/2.7/anyway/loaders/yaml.rb +84 -0
- data/lib/.rbnext/2.7/anyway/settings.rb +16 -1
- data/lib/.rbnext/2.7/anyway/tracing.rb +9 -8
- data/lib/.rbnext/3.0/anyway/config.rb +28 -4
- data/lib/.rbnext/3.0/anyway/tracing.rb +9 -8
- data/lib/.rbnext/3.1/anyway/config.rb +28 -4
- data/lib/.rbnext/3.1/anyway/tracing.rb +9 -8
- data/lib/anyway/config.rb +28 -4
- data/lib/anyway/loaders/yaml.rb +25 -3
- data/lib/anyway/rails/loaders/yaml.rb +1 -28
- data/lib/anyway/rails/settings.rb +8 -8
- data/lib/anyway/settings.rb +16 -1
- data/lib/anyway/tracing.rb +9 -8
- data/lib/anyway/version.rb +1 -1
- data/sig/anyway_config.rbs +27 -12
- metadata +3 -3
- data/lib/.rbnext/2.7/anyway/rails/loaders/yaml.rb +0 -36
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: fe4f769be22bc9cb820fd1159b88a565b2fb71e13ad617d90aaafbcb1673f995
|
4
|
+
data.tar.gz: 175e468716722b43b6c7d163a97b6523801f6658118d1c56bb5a4a0255807ef9
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 7c323f89197ca35405ca77ee1e58a8b3fbbf4b0d6b57e7ccce380311a13994d18121966428a2681cb55a5892c2eff52ec347a6e3568072ea8f85d1cf7f75aa80
|
7
|
+
data.tar.gz: 25ee0b877318a2335c2019a414684d5b15e3755ceff90e51de3a0b821ee48f86a119f9753eaddac5dfb4724e38876ec5f18b68b065db7aa4b23d20b837666929
|
data/CHANGELOG.md
CHANGED
@@ -2,6 +2,15 @@
|
|
2
2
|
|
3
3
|
## master
|
4
4
|
|
5
|
+
## 2.3.0 (2022-03-11)
|
6
|
+
|
7
|
+
- Add ability to load configurations under specific environments in pure Ruby apps. ([@fargelus][]).
|
8
|
+
|
9
|
+
Before loading environment configurations you need to specify variable `Anyway::Settings.current_environment`. In Rails apps this variable is same as `Rails.env` value.
|
10
|
+
After adding yaml loader will try to load params under this environment.
|
11
|
+
|
12
|
+
Also required env option was added to `Anyway::Config`.
|
13
|
+
|
5
14
|
## 2.2.3 (2022-01-21)
|
6
15
|
|
7
16
|
- Fix Ruby 3.1 compatibility. ([@palkan][])
|
@@ -449,3 +458,4 @@ No we're dependency-free!
|
|
449
458
|
[@envek]: https://github.com/Envek
|
450
459
|
[@progapandist]: https://github.com/progapandist
|
451
460
|
[@skryukov]: https://github.com/skryukov
|
461
|
+
[@fargelus]: https://github.com/fargelus
|
data/README.md
CHANGED
@@ -297,6 +297,24 @@ end
|
|
297
297
|
MyConfig.new(api_secret: "") #=> raises Anyway::Config::ValidationError
|
298
298
|
```
|
299
299
|
|
300
|
+
`Required` method supports additional `env` parameter which indicates necessity to run validations under specified
|
301
|
+
environments. `Env` parameter could be present in symbol, string, array or hash formats:
|
302
|
+
|
303
|
+
```ruby
|
304
|
+
class EnvConfig < Anyway::Config
|
305
|
+
required :password, env: "production"
|
306
|
+
required :maps_api_key, env: :production
|
307
|
+
required :smtp_host, env: %i[production staging]
|
308
|
+
required :aws_bucket, env: %w[production staging]
|
309
|
+
required :anycable_rpc_host, env: {except: :development}
|
310
|
+
required :anycable_redis_url, env: {except: %i[development test]}
|
311
|
+
required :anycable_broadcast_adapter, env: {except: %w[development test]}
|
312
|
+
end
|
313
|
+
```
|
314
|
+
|
315
|
+
If your current `Anyway::Settings.current_environment` is mismatch keys that specified
|
316
|
+
`Anyway::Config::ValidationError` error will be raised.
|
317
|
+
|
300
318
|
If you need more complex validation or need to manipulate with config state right after it has been loaded, you can use _on load callbacks_ and `#raise_validation_error` method:
|
301
319
|
|
302
320
|
```ruby
|
@@ -529,7 +547,22 @@ The default data loading mechanism for non-Rails applications is the following (
|
|
529
547
|
|
530
548
|
1) **YAML configuration files**: `./config/<config-name>.yml`.
|
531
549
|
|
532
|
-
In pure Ruby apps, we
|
550
|
+
In pure Ruby apps, we also can load data under specific _environments_ (`test`, `development`, `production`, etc.).
|
551
|
+
If you want to enable this feature you must specify `Anyway::Settings.current_environment` variable for load config under specific environment.
|
552
|
+
|
553
|
+
```ruby
|
554
|
+
Anyway::Settings.current_environment = "development"
|
555
|
+
```
|
556
|
+
|
557
|
+
YAML files should be in this format:
|
558
|
+
|
559
|
+
```yml
|
560
|
+
development:
|
561
|
+
host: localhost
|
562
|
+
port: 3000
|
563
|
+
```
|
564
|
+
|
565
|
+
If `Anyway::Settings.current_environment` is missed we assume that the YAML contains values for a single environment:
|
533
566
|
|
534
567
|
```yml
|
535
568
|
host: localhost
|
@@ -47,6 +47,8 @@ module Anyway # :nodoc:
|
|
47
47
|
__type_caster__
|
48
48
|
].freeze
|
49
49
|
|
50
|
+
ENV_OPTION_EXCLUDE_KEY = :except
|
51
|
+
|
50
52
|
class Error < StandardError; end
|
51
53
|
|
52
54
|
class ValidationError < Error; end
|
@@ -126,14 +128,36 @@ module Anyway # :nodoc:
|
|
126
128
|
end
|
127
129
|
end
|
128
130
|
|
129
|
-
def required(*names)
|
130
|
-
|
131
|
-
|
132
|
-
end
|
131
|
+
def required(*names, env: nil)
|
132
|
+
unknown_names = names - config_attributes
|
133
|
+
raise ArgumentError, "Unknown config param: #{unknown_names.join(",")}" if unknown_names.any?
|
133
134
|
|
135
|
+
names = filter_by_env(names, env)
|
134
136
|
required_attributes.push(*names)
|
135
137
|
end
|
136
138
|
|
139
|
+
def filter_by_env(names, env)
|
140
|
+
return names if env.nil? || env.to_s == current_env
|
141
|
+
|
142
|
+
filtered_names = if env.is_a?(Hash)
|
143
|
+
names_with_exclude_env_option(names, env)
|
144
|
+
elsif env.is_a?(Array)
|
145
|
+
names if env.flat_map(&:to_s).include?(current_env)
|
146
|
+
end
|
147
|
+
|
148
|
+
filtered_names || []
|
149
|
+
end
|
150
|
+
|
151
|
+
def current_env
|
152
|
+
Settings.current_environment.to_s
|
153
|
+
end
|
154
|
+
|
155
|
+
def names_with_exclude_env_option(names, env)
|
156
|
+
envs = env[ENV_OPTION_EXCLUDE_KEY]
|
157
|
+
excluded_envs = [envs].flat_map(&:to_s)
|
158
|
+
names if excluded_envs.none?(current_env)
|
159
|
+
end
|
160
|
+
|
137
161
|
def required_attributes
|
138
162
|
return @required_attributes if instance_variable_defined?(:@required_attributes)
|
139
163
|
|
@@ -0,0 +1,84 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "pathname"
|
4
|
+
require "anyway/ext/hash"
|
5
|
+
|
6
|
+
using RubyNext
|
7
|
+
using Anyway::Ext::Hash
|
8
|
+
|
9
|
+
module Anyway
|
10
|
+
module Loaders
|
11
|
+
class YAML < Base
|
12
|
+
def call(config_path:, **_options)
|
13
|
+
rel_config_path = relative_config_path(config_path).to_s
|
14
|
+
base_config = trace!(:yml, path: rel_config_path) do
|
15
|
+
config = load_base_yml(config_path)
|
16
|
+
environmental?(config) ? config_with_env(config) : config
|
17
|
+
end
|
18
|
+
|
19
|
+
return base_config unless use_local?
|
20
|
+
|
21
|
+
local_path = local_config_path(config_path)
|
22
|
+
local_config = trace!(:yml, path: relative_config_path(local_path).to_s) { load_local_yml(local_path) }
|
23
|
+
Utils.deep_merge!(base_config, local_config)
|
24
|
+
end
|
25
|
+
|
26
|
+
private
|
27
|
+
|
28
|
+
def environmental?(parsed_yml)
|
29
|
+
# strange, but still possible
|
30
|
+
return true if Settings.default_environmental_key? && parsed_yml.key?(Settings.default_environmental_key)
|
31
|
+
# possible
|
32
|
+
return true if !Settings.future.unwrap_known_environments && Settings.current_environment
|
33
|
+
# for other environments
|
34
|
+
return true if Settings.known_environments&.any? { |_1| parsed_yml.key?(_1) }
|
35
|
+
# preferred
|
36
|
+
parsed_yml.key?(Settings.current_environment)
|
37
|
+
end
|
38
|
+
|
39
|
+
def config_with_env(config)
|
40
|
+
env_config = config[Settings.current_environment] || {}
|
41
|
+
return env_config unless Settings.default_environmental_key?
|
42
|
+
|
43
|
+
default_config = config[Settings.default_environmental_key] || {}
|
44
|
+
Utils.deep_merge!(default_config, env_config)
|
45
|
+
end
|
46
|
+
|
47
|
+
def parse_yml(path)
|
48
|
+
return {} unless File.file?(path)
|
49
|
+
require "yaml" unless defined?(::YAML)
|
50
|
+
|
51
|
+
# By default, YAML load will return `false` when the yaml document is
|
52
|
+
# empty. When this occurs, we return an empty hash instead, to match
|
53
|
+
# the interface when no config file is present.
|
54
|
+
begin
|
55
|
+
if defined?(ERB)
|
56
|
+
::YAML.load(ERB.new(File.read(path)).result, aliases: true) || {} # rubocop:disable Security/YAMLLoad
|
57
|
+
else
|
58
|
+
::YAML.load_file(path, aliases: true) || {}
|
59
|
+
end
|
60
|
+
rescue ArgumentError
|
61
|
+
if defined?(ERB)
|
62
|
+
::YAML.load(ERB.new(File.read(path)).result) || {} # rubocop:disable Security/YAMLLoad
|
63
|
+
else
|
64
|
+
::YAML.load_file(path) || {}
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
alias_method :load_base_yml, :parse_yml
|
70
|
+
alias_method :load_local_yml, :parse_yml
|
71
|
+
|
72
|
+
def local_config_path(path)
|
73
|
+
path.sub(/\.yml/, ".local.yml")
|
74
|
+
end
|
75
|
+
|
76
|
+
def relative_config_path(path)
|
77
|
+
Pathname.new(path).then do |path|
|
78
|
+
return path if path.relative?
|
79
|
+
path.relative_path_from(Settings.app_root)
|
80
|
+
end
|
81
|
+
end
|
82
|
+
end
|
83
|
+
end
|
84
|
+
end
|
@@ -1,5 +1,7 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
+
require "pathname"
|
4
|
+
|
3
5
|
module Anyway
|
4
6
|
# Use Settings name to not confuse with Config.
|
5
7
|
#
|
@@ -35,6 +37,8 @@ module Anyway
|
|
35
37
|
names.each { |_1| store[_1] = self.class.settings[_1] }
|
36
38
|
end
|
37
39
|
|
40
|
+
setting :unwrap_known_environments, true
|
41
|
+
|
38
42
|
private
|
39
43
|
|
40
44
|
attr_reader :store
|
@@ -43,7 +47,10 @@ module Anyway
|
|
43
47
|
class << self
|
44
48
|
# Define whether to load data from
|
45
49
|
# *.yml.local (or credentials/local.yml.enc)
|
46
|
-
attr_accessor :use_local_files
|
50
|
+
attr_accessor :use_local_files,
|
51
|
+
:current_environment,
|
52
|
+
:default_environmental_key,
|
53
|
+
:known_environments
|
47
54
|
|
48
55
|
# A proc returning a path to YML config file given the config name
|
49
56
|
attr_reader :default_config_path
|
@@ -65,6 +72,14 @@ module Anyway
|
|
65
72
|
def future
|
66
73
|
@future ||= Future.new
|
67
74
|
end
|
75
|
+
|
76
|
+
def app_root
|
77
|
+
Pathname.new(Dir.pwd)
|
78
|
+
end
|
79
|
+
|
80
|
+
def default_environmental_key?
|
81
|
+
!default_environmental_key.nil?
|
82
|
+
end
|
68
83
|
end
|
69
84
|
|
70
85
|
# By default, use local files only in development (that's the purpose if the local files)
|
@@ -6,12 +6,6 @@ module Anyway
|
|
6
6
|
using Anyway::Ext::DeepDup
|
7
7
|
|
8
8
|
using(Module.new do
|
9
|
-
refine Hash do
|
10
|
-
def inspect
|
11
|
-
"{#{map { |k, v| "#{k}: #{v.inspect}" }.join(", ")}}"
|
12
|
-
end
|
13
|
-
end
|
14
|
-
|
15
9
|
refine Thread::Backtrace::Location do
|
16
10
|
def path_lineno() ; "#{path}:#{lineno}"; end
|
17
11
|
end
|
@@ -100,8 +94,15 @@ module Anyway
|
|
100
94
|
q.group do
|
101
95
|
q.text k
|
102
96
|
q.text " =>"
|
103
|
-
|
104
|
-
|
97
|
+
if v.trace?
|
98
|
+
q.text " { "
|
99
|
+
q.pp v
|
100
|
+
q.breakable " "
|
101
|
+
q.text "}"
|
102
|
+
else
|
103
|
+
q.breakable " "
|
104
|
+
q.pp v
|
105
|
+
end
|
105
106
|
end
|
106
107
|
end
|
107
108
|
end
|
@@ -47,6 +47,8 @@ module Anyway # :nodoc:
|
|
47
47
|
__type_caster__
|
48
48
|
].freeze
|
49
49
|
|
50
|
+
ENV_OPTION_EXCLUDE_KEY = :except
|
51
|
+
|
50
52
|
class Error < StandardError; end
|
51
53
|
|
52
54
|
class ValidationError < Error; end
|
@@ -126,14 +128,36 @@ module Anyway # :nodoc:
|
|
126
128
|
end
|
127
129
|
end
|
128
130
|
|
129
|
-
def required(*names)
|
130
|
-
|
131
|
-
|
132
|
-
end
|
131
|
+
def required(*names, env: nil)
|
132
|
+
unknown_names = names - config_attributes
|
133
|
+
raise ArgumentError, "Unknown config param: #{unknown_names.join(",")}" if unknown_names.any?
|
133
134
|
|
135
|
+
names = filter_by_env(names, env)
|
134
136
|
required_attributes.push(*names)
|
135
137
|
end
|
136
138
|
|
139
|
+
def filter_by_env(names, env)
|
140
|
+
return names if env.nil? || env.to_s == current_env
|
141
|
+
|
142
|
+
filtered_names = if env.is_a?(Hash)
|
143
|
+
names_with_exclude_env_option(names, env)
|
144
|
+
elsif env.is_a?(Array)
|
145
|
+
names if env.flat_map(&:to_s).include?(current_env)
|
146
|
+
end
|
147
|
+
|
148
|
+
filtered_names || []
|
149
|
+
end
|
150
|
+
|
151
|
+
def current_env
|
152
|
+
Settings.current_environment.to_s
|
153
|
+
end
|
154
|
+
|
155
|
+
def names_with_exclude_env_option(names, env)
|
156
|
+
envs = env[ENV_OPTION_EXCLUDE_KEY]
|
157
|
+
excluded_envs = [envs].flat_map(&:to_s)
|
158
|
+
names if excluded_envs.none?(current_env)
|
159
|
+
end
|
160
|
+
|
137
161
|
def required_attributes
|
138
162
|
return @required_attributes if instance_variable_defined?(:@required_attributes)
|
139
163
|
|
@@ -6,12 +6,6 @@ module Anyway
|
|
6
6
|
using Anyway::Ext::DeepDup
|
7
7
|
|
8
8
|
using(Module.new do
|
9
|
-
refine Hash do
|
10
|
-
def inspect
|
11
|
-
"{#{map { |k, v| "#{k}: #{v.inspect}" }.join(", ")}}"
|
12
|
-
end
|
13
|
-
end
|
14
|
-
|
15
9
|
refine Thread::Backtrace::Location do
|
16
10
|
def path_lineno() ; "#{path}:#{lineno}"; end
|
17
11
|
end
|
@@ -100,8 +94,15 @@ module Anyway
|
|
100
94
|
q.group do
|
101
95
|
q.text k
|
102
96
|
q.text " =>"
|
103
|
-
|
104
|
-
|
97
|
+
if v.trace?
|
98
|
+
q.text " { "
|
99
|
+
q.pp v
|
100
|
+
q.breakable " "
|
101
|
+
q.text "}"
|
102
|
+
else
|
103
|
+
q.breakable " "
|
104
|
+
q.pp v
|
105
|
+
end
|
105
106
|
end
|
106
107
|
end
|
107
108
|
end
|
@@ -47,6 +47,8 @@ module Anyway # :nodoc:
|
|
47
47
|
__type_caster__
|
48
48
|
].freeze
|
49
49
|
|
50
|
+
ENV_OPTION_EXCLUDE_KEY = :except
|
51
|
+
|
50
52
|
class Error < StandardError; end
|
51
53
|
|
52
54
|
class ValidationError < Error; end
|
@@ -126,14 +128,36 @@ module Anyway # :nodoc:
|
|
126
128
|
end
|
127
129
|
end
|
128
130
|
|
129
|
-
def required(*names)
|
130
|
-
|
131
|
-
|
132
|
-
end
|
131
|
+
def required(*names, env: nil)
|
132
|
+
unknown_names = names - config_attributes
|
133
|
+
raise ArgumentError, "Unknown config param: #{unknown_names.join(",")}" if unknown_names.any?
|
133
134
|
|
135
|
+
names = filter_by_env(names, env)
|
134
136
|
required_attributes.push(*names)
|
135
137
|
end
|
136
138
|
|
139
|
+
def filter_by_env(names, env)
|
140
|
+
return names if env.nil? || env.to_s == current_env
|
141
|
+
|
142
|
+
filtered_names = if env.is_a?(Hash)
|
143
|
+
names_with_exclude_env_option(names, env)
|
144
|
+
elsif env.is_a?(Array)
|
145
|
+
names if env.flat_map(&:to_s).include?(current_env)
|
146
|
+
end
|
147
|
+
|
148
|
+
filtered_names || []
|
149
|
+
end
|
150
|
+
|
151
|
+
def current_env
|
152
|
+
Settings.current_environment.to_s
|
153
|
+
end
|
154
|
+
|
155
|
+
def names_with_exclude_env_option(names, env)
|
156
|
+
envs = env[ENV_OPTION_EXCLUDE_KEY]
|
157
|
+
excluded_envs = [envs].flat_map(&:to_s)
|
158
|
+
names if excluded_envs.none?(current_env)
|
159
|
+
end
|
160
|
+
|
137
161
|
def required_attributes
|
138
162
|
return @required_attributes if instance_variable_defined?(:@required_attributes)
|
139
163
|
|
@@ -6,12 +6,6 @@ module Anyway
|
|
6
6
|
using Anyway::Ext::DeepDup
|
7
7
|
|
8
8
|
using(Module.new do
|
9
|
-
refine Hash do
|
10
|
-
def inspect
|
11
|
-
"{#{map { |k, v| "#{k}: #{v.inspect}" }.join(", ")}}"
|
12
|
-
end
|
13
|
-
end
|
14
|
-
|
15
9
|
refine Thread::Backtrace::Location do
|
16
10
|
def path_lineno() = "#{path}:#{lineno}"
|
17
11
|
end
|
@@ -100,8 +94,15 @@ module Anyway
|
|
100
94
|
q.group do
|
101
95
|
q.text k
|
102
96
|
q.text " =>"
|
103
|
-
|
104
|
-
|
97
|
+
if v.trace?
|
98
|
+
q.text " { "
|
99
|
+
q.pp v
|
100
|
+
q.breakable " "
|
101
|
+
q.text "}"
|
102
|
+
else
|
103
|
+
q.breakable " "
|
104
|
+
q.pp v
|
105
|
+
end
|
105
106
|
end
|
106
107
|
end
|
107
108
|
end
|
data/lib/anyway/config.rb
CHANGED
@@ -47,6 +47,8 @@ module Anyway # :nodoc:
|
|
47
47
|
__type_caster__
|
48
48
|
].freeze
|
49
49
|
|
50
|
+
ENV_OPTION_EXCLUDE_KEY = :except
|
51
|
+
|
50
52
|
class Error < StandardError; end
|
51
53
|
|
52
54
|
class ValidationError < Error; end
|
@@ -126,14 +128,36 @@ module Anyway # :nodoc:
|
|
126
128
|
end
|
127
129
|
end
|
128
130
|
|
129
|
-
def required(*names)
|
130
|
-
|
131
|
-
|
132
|
-
end
|
131
|
+
def required(*names, env: nil)
|
132
|
+
unknown_names = names - config_attributes
|
133
|
+
raise ArgumentError, "Unknown config param: #{unknown_names.join(",")}" if unknown_names.any?
|
133
134
|
|
135
|
+
names = filter_by_env(names, env)
|
134
136
|
required_attributes.push(*names)
|
135
137
|
end
|
136
138
|
|
139
|
+
def filter_by_env(names, env)
|
140
|
+
return names if env.nil? || env.to_s == current_env
|
141
|
+
|
142
|
+
filtered_names = if env.is_a?(Hash)
|
143
|
+
names_with_exclude_env_option(names, env)
|
144
|
+
elsif env.is_a?(Array)
|
145
|
+
names if env.flat_map(&:to_s).include?(current_env)
|
146
|
+
end
|
147
|
+
|
148
|
+
filtered_names || []
|
149
|
+
end
|
150
|
+
|
151
|
+
def current_env
|
152
|
+
Settings.current_environment.to_s
|
153
|
+
end
|
154
|
+
|
155
|
+
def names_with_exclude_env_option(names, env)
|
156
|
+
envs = env[ENV_OPTION_EXCLUDE_KEY]
|
157
|
+
excluded_envs = [envs].flat_map(&:to_s)
|
158
|
+
names if excluded_envs.none?(current_env)
|
159
|
+
end
|
160
|
+
|
137
161
|
def required_attributes
|
138
162
|
return @required_attributes if instance_variable_defined?(:@required_attributes)
|
139
163
|
|
data/lib/anyway/loaders/yaml.rb
CHANGED
@@ -10,18 +10,40 @@ module Anyway
|
|
10
10
|
module Loaders
|
11
11
|
class YAML < Base
|
12
12
|
def call(config_path:, **_options)
|
13
|
-
|
13
|
+
rel_config_path = relative_config_path(config_path).to_s
|
14
|
+
base_config = trace!(:yml, path: rel_config_path) do
|
15
|
+
config = load_base_yml(config_path)
|
16
|
+
environmental?(config) ? config_with_env(config) : config
|
17
|
+
end
|
14
18
|
|
15
19
|
return base_config unless use_local?
|
16
20
|
|
17
21
|
local_path = local_config_path(config_path)
|
18
22
|
local_config = trace!(:yml, path: relative_config_path(local_path).to_s) { load_local_yml(local_path) }
|
19
|
-
|
20
23
|
Utils.deep_merge!(base_config, local_config)
|
21
24
|
end
|
22
25
|
|
23
26
|
private
|
24
27
|
|
28
|
+
def environmental?(parsed_yml)
|
29
|
+
# strange, but still possible
|
30
|
+
return true if Settings.default_environmental_key? && parsed_yml.key?(Settings.default_environmental_key)
|
31
|
+
# possible
|
32
|
+
return true if !Settings.future.unwrap_known_environments && Settings.current_environment
|
33
|
+
# for other environments
|
34
|
+
return true if Settings.known_environments&.any? { parsed_yml.key?(_1) }
|
35
|
+
# preferred
|
36
|
+
parsed_yml.key?(Settings.current_environment)
|
37
|
+
end
|
38
|
+
|
39
|
+
def config_with_env(config)
|
40
|
+
env_config = config[Settings.current_environment] || {}
|
41
|
+
return env_config unless Settings.default_environmental_key?
|
42
|
+
|
43
|
+
default_config = config[Settings.default_environmental_key] || {}
|
44
|
+
Utils.deep_merge!(default_config, env_config)
|
45
|
+
end
|
46
|
+
|
25
47
|
def parse_yml(path)
|
26
48
|
return {} unless File.file?(path)
|
27
49
|
require "yaml" unless defined?(::YAML)
|
@@ -54,7 +76,7 @@ module Anyway
|
|
54
76
|
def relative_config_path(path)
|
55
77
|
Pathname.new(path).then do |path|
|
56
78
|
return path if path.relative?
|
57
|
-
path.relative_path_from(
|
79
|
+
path.relative_path_from(Settings.app_root)
|
58
80
|
end
|
59
81
|
end
|
60
82
|
end
|
@@ -3,34 +3,7 @@
|
|
3
3
|
module Anyway
|
4
4
|
module Rails
|
5
5
|
module Loaders
|
6
|
-
class YAML < Anyway::Loaders::YAML
|
7
|
-
def load_base_yml(*)
|
8
|
-
parsed_yml = super
|
9
|
-
return parsed_yml unless environmental?(parsed_yml)
|
10
|
-
|
11
|
-
env_config = parsed_yml[::Rails.env] || {}
|
12
|
-
return env_config if Anyway::Settings.default_environmental_key.blank?
|
13
|
-
|
14
|
-
default_config = parsed_yml[Anyway::Settings.default_environmental_key] || {}
|
15
|
-
Utils.deep_merge!(default_config, env_config)
|
16
|
-
end
|
17
|
-
|
18
|
-
private
|
19
|
-
|
20
|
-
def environmental?(parsed_yml)
|
21
|
-
return true unless Settings.future.unwrap_known_environments
|
22
|
-
# likely
|
23
|
-
return true if parsed_yml.key?(::Rails.env)
|
24
|
-
# less likely
|
25
|
-
return true if ::Rails.application.config.anyway_config.known_environments.any? { parsed_yml.key?(_1) }
|
26
|
-
# strange, but still possible
|
27
|
-
Anyway::Settings.default_environmental_key.present? && parsed_yml.key?(Anyway::Settings.default_environmental_key)
|
28
|
-
end
|
29
|
-
|
30
|
-
def relative_config_path(path)
|
31
|
-
Pathname.new(path).relative_path_from(::Rails.root)
|
32
|
-
end
|
33
|
-
end
|
6
|
+
class YAML < Anyway::Loaders::YAML; end
|
34
7
|
end
|
35
8
|
end
|
36
9
|
end
|
@@ -9,16 +9,8 @@ end
|
|
9
9
|
|
10
10
|
module Anyway
|
11
11
|
class Settings
|
12
|
-
class Future
|
13
|
-
setting :unwrap_known_environments, true
|
14
|
-
end
|
15
|
-
|
16
12
|
class << self
|
17
13
|
attr_reader :autoload_static_config_path, :autoloader
|
18
|
-
attr_accessor :known_environments
|
19
|
-
|
20
|
-
# Define a key for environmental yaml files to read default values from
|
21
|
-
attr_accessor :default_environmental_key
|
22
14
|
|
23
15
|
if defined?(::Zeitwerk)
|
24
16
|
def autoload_static_config_path=(val)
|
@@ -62,6 +54,14 @@ module Anyway
|
|
62
54
|
:no_op
|
63
55
|
end
|
64
56
|
end
|
57
|
+
|
58
|
+
def current_environment
|
59
|
+
::Rails.env.to_s
|
60
|
+
end
|
61
|
+
|
62
|
+
def app_root
|
63
|
+
::Rails.root
|
64
|
+
end
|
65
65
|
end
|
66
66
|
|
67
67
|
self.default_config_path = ->(name) { ::Rails.root.join("config", "#{name}.yml") }
|
data/lib/anyway/settings.rb
CHANGED
@@ -1,5 +1,7 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
+
require "pathname"
|
4
|
+
|
3
5
|
module Anyway
|
4
6
|
# Use Settings name to not confuse with Config.
|
5
7
|
#
|
@@ -35,6 +37,8 @@ module Anyway
|
|
35
37
|
names.each { store[_1] = self.class.settings[_1] }
|
36
38
|
end
|
37
39
|
|
40
|
+
setting :unwrap_known_environments, true
|
41
|
+
|
38
42
|
private
|
39
43
|
|
40
44
|
attr_reader :store
|
@@ -43,7 +47,10 @@ module Anyway
|
|
43
47
|
class << self
|
44
48
|
# Define whether to load data from
|
45
49
|
# *.yml.local (or credentials/local.yml.enc)
|
46
|
-
attr_accessor :use_local_files
|
50
|
+
attr_accessor :use_local_files,
|
51
|
+
:current_environment,
|
52
|
+
:default_environmental_key,
|
53
|
+
:known_environments
|
47
54
|
|
48
55
|
# A proc returning a path to YML config file given the config name
|
49
56
|
attr_reader :default_config_path
|
@@ -65,6 +72,14 @@ module Anyway
|
|
65
72
|
def future
|
66
73
|
@future ||= Future.new
|
67
74
|
end
|
75
|
+
|
76
|
+
def app_root
|
77
|
+
Pathname.new(Dir.pwd)
|
78
|
+
end
|
79
|
+
|
80
|
+
def default_environmental_key?
|
81
|
+
!default_environmental_key.nil?
|
82
|
+
end
|
68
83
|
end
|
69
84
|
|
70
85
|
# By default, use local files only in development (that's the purpose if the local files)
|
data/lib/anyway/tracing.rb
CHANGED
@@ -6,12 +6,6 @@ module Anyway
|
|
6
6
|
using Anyway::Ext::DeepDup
|
7
7
|
|
8
8
|
using(Module.new do
|
9
|
-
refine Hash do
|
10
|
-
def inspect
|
11
|
-
"{#{map { |k, v| "#{k}: #{v.inspect}" }.join(", ")}}"
|
12
|
-
end
|
13
|
-
end
|
14
|
-
|
15
9
|
refine Thread::Backtrace::Location do
|
16
10
|
def path_lineno() = "#{path}:#{lineno}"
|
17
11
|
end
|
@@ -100,8 +94,15 @@ module Anyway
|
|
100
94
|
q.group do
|
101
95
|
q.text k
|
102
96
|
q.text " =>"
|
103
|
-
|
104
|
-
|
97
|
+
if v.trace?
|
98
|
+
q.text " { "
|
99
|
+
q.pp v
|
100
|
+
q.breakable " "
|
101
|
+
q.text "}"
|
102
|
+
else
|
103
|
+
q.breakable " "
|
104
|
+
q.pp v
|
105
|
+
end
|
105
106
|
end
|
106
107
|
end
|
107
108
|
end
|
data/lib/anyway/version.rb
CHANGED
data/sig/anyway_config.rbs
CHANGED
@@ -3,8 +3,11 @@ module Anyway
|
|
3
3
|
def self.loaders: -> Loaders::Registry
|
4
4
|
|
5
5
|
class Settings
|
6
|
-
def self.default_config_path=: (^(untyped) -> String val) ->
|
6
|
+
def self.default_config_path=: (String | Pathname | ^(untyped) -> String val) -> void
|
7
7
|
def self.future: -> Future
|
8
|
+
def self.current_environment: -> String?
|
9
|
+
def self.default_environmental_key: -> String?
|
10
|
+
def self.known_environments: -> Array[String]?
|
8
11
|
|
9
12
|
class Future
|
10
13
|
def self.setting: (untyped name, untyped default_value) -> untyped
|
@@ -19,14 +22,14 @@ module Anyway
|
|
19
22
|
end
|
20
23
|
|
21
24
|
def inspect: -> String
|
22
|
-
def self.capture: ?{ -> Hash[untyped, untyped] } ->
|
25
|
+
def self.capture: ?{ -> Hash[untyped, untyped]? } -> Trace
|
23
26
|
def self.trace_stack: -> Array[untyped]
|
24
27
|
def self.current_trace: -> Trace?
|
25
28
|
def self.source_stack: -> Array[untyped]
|
26
|
-
def self.current_trace_source: -> {type:
|
27
|
-
def self.with_trace_source: (untyped src) -> untyped
|
28
|
-
def trace!: (Symbol, *
|
29
|
-
def self.trace!: (Symbol, *
|
29
|
+
def self.current_trace_source: -> ({type: Symbol} & Hash[Symbol, untyped])
|
30
|
+
def self.with_trace_source: (untyped src) { -> void } -> untyped
|
31
|
+
def trace!: [V] (Symbol, *String paths, **untyped) ?{ -> V} -> V
|
32
|
+
def self.trace!: [V] (Symbol, *String paths, **untyped) ?{ -> V} -> V
|
30
33
|
end
|
31
34
|
|
32
35
|
module RBSGenerator
|
@@ -56,6 +59,7 @@ module Anyway
|
|
56
59
|
type hashType = Hash[Symbol, valueType | arrayType | hashType]
|
57
60
|
|
58
61
|
type mappingType = valueType | arrayType | hashType
|
62
|
+
type envType = String | Symbol | Array[String | Symbol] | {except: String | Symbol | Array[String | Symbol]}
|
59
63
|
|
60
64
|
class Config
|
61
65
|
extend RBSGenerator
|
@@ -67,7 +71,7 @@ module Anyway
|
|
67
71
|
def self.attr_config: (*Symbol args, **untyped) -> void
|
68
72
|
def self.defaults: -> Hash[String, untyped]
|
69
73
|
def self.config_attributes: -> Array[Symbol]?
|
70
|
-
def self.required: (*Symbol names) -> void
|
74
|
+
def self.required: (*Symbol names, ?env: envType) -> void
|
71
75
|
def self.required_attributes: -> Array[Symbol]
|
72
76
|
def self.on_load: (*Symbol callbacks) ?{ () -> void } -> void
|
73
77
|
def self.config_name: (?(Symbol | String) val) -> String?
|
@@ -80,9 +84,11 @@ module Anyway
|
|
80
84
|
attr_reader env_prefix: String
|
81
85
|
|
82
86
|
def initialize: (?Hash[Symbol | String, untyped] overrides) -> void
|
87
|
+
| (NilClass) -> void
|
83
88
|
def reload: (?Hash[Symbol | String, untyped] overrides) -> Config
|
84
89
|
def clear: -> void
|
85
90
|
def load: (Hash[Symbol | String, untyped] overrides) -> Config
|
91
|
+
| (NilClass) -> Config
|
86
92
|
def dig: (*(Symbol | String) keys) -> untyped
|
87
93
|
def to_h: -> Hash[untyped, untyped]
|
88
94
|
def dup: -> Config
|
@@ -117,12 +123,21 @@ module Anyway
|
|
117
123
|
def use_local?: -> bool
|
118
124
|
end
|
119
125
|
|
126
|
+
interface _Loader
|
127
|
+
def call: (**untyped) -> Hash[untyped, untyped]
|
128
|
+
end
|
129
|
+
|
120
130
|
class Registry
|
121
|
-
def prepend: (Symbol id,
|
122
|
-
|
123
|
-
def
|
124
|
-
|
125
|
-
def
|
131
|
+
def prepend: (Symbol id, _Loader loader) -> void
|
132
|
+
| (Symbol id) { (**untyped) -> Hash[untyped, untyped] } -> void
|
133
|
+
def append: (Symbol id, _Loader loader) -> void
|
134
|
+
| (Symbol id) { (**untyped) -> Hash[untyped, untyped] } -> void
|
135
|
+
def insert_before: (Symbol another_id, Symbol id, _Loader loader) -> void
|
136
|
+
| (Symbol another_id, Symbol id) { (**untyped) -> Hash[untyped, untyped] } -> void
|
137
|
+
def insert_after: (Symbol another_id, Symbol id, _Loader loader) -> void
|
138
|
+
| (Symbol another_id, Symbol id) { (**untyped) -> Hash[untyped, untyped] } -> void
|
139
|
+
def override: (Symbol id, _Loader loader) -> void
|
140
|
+
| (Symbol id) { (**untyped) -> Hash[untyped, untyped] } -> void
|
126
141
|
def delete: (Symbol id) -> void
|
127
142
|
end
|
128
143
|
end
|
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.
|
4
|
+
version: 2.3.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: 2022-
|
11
|
+
date: 2022-03-11 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: ruby-next-core
|
@@ -108,7 +108,7 @@ files:
|
|
108
108
|
- README.md
|
109
109
|
- lib/.rbnext/2.7/anyway/auto_cast.rb
|
110
110
|
- lib/.rbnext/2.7/anyway/config.rb
|
111
|
-
- lib/.rbnext/2.7/anyway/
|
111
|
+
- lib/.rbnext/2.7/anyway/loaders/yaml.rb
|
112
112
|
- lib/.rbnext/2.7/anyway/rbs.rb
|
113
113
|
- lib/.rbnext/2.7/anyway/settings.rb
|
114
114
|
- lib/.rbnext/2.7/anyway/tracing.rb
|
@@ -1,36 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
module Anyway
|
4
|
-
module Rails
|
5
|
-
module Loaders
|
6
|
-
class YAML < Anyway::Loaders::YAML
|
7
|
-
def load_base_yml(*)
|
8
|
-
parsed_yml = super
|
9
|
-
return parsed_yml unless environmental?(parsed_yml)
|
10
|
-
|
11
|
-
env_config = parsed_yml[::Rails.env] || {}
|
12
|
-
return env_config if Anyway::Settings.default_environmental_key.blank?
|
13
|
-
|
14
|
-
default_config = parsed_yml[Anyway::Settings.default_environmental_key] || {}
|
15
|
-
Utils.deep_merge!(default_config, env_config)
|
16
|
-
end
|
17
|
-
|
18
|
-
private
|
19
|
-
|
20
|
-
def environmental?(parsed_yml)
|
21
|
-
return true unless Settings.future.unwrap_known_environments
|
22
|
-
# likely
|
23
|
-
return true if parsed_yml.key?(::Rails.env)
|
24
|
-
# less likely
|
25
|
-
return true if ::Rails.application.config.anyway_config.known_environments.any? { |_1| parsed_yml.key?(_1) }
|
26
|
-
# strange, but still possible
|
27
|
-
Anyway::Settings.default_environmental_key.present? && parsed_yml.key?(Anyway::Settings.default_environmental_key)
|
28
|
-
end
|
29
|
-
|
30
|
-
def relative_config_path(path)
|
31
|
-
Pathname.new(path).relative_path_from(::Rails.root)
|
32
|
-
end
|
33
|
-
end
|
34
|
-
end
|
35
|
-
end
|
36
|
-
end
|