anyway_config 2.5.4 → 2.6.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.
@@ -0,0 +1,144 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Anyway
4
+ # Contains a mapping between type IDs/names and deserializers
5
+ class TypeRegistry
6
+ class << self
7
+ def default
8
+ @default ||= TypeRegistry.new
9
+ end
10
+ end
11
+
12
+ def initialize
13
+ @registry = {}
14
+ end
15
+
16
+ def accept(name_or_object, &block)
17
+ if !block && !name_or_object.respond_to?(:call)
18
+ raise ArgumentError, "Please, provide a type casting block or an object implementing #call(val) method"
19
+ end
20
+
21
+ registry[name_or_object] = block || name_or_object
22
+ end
23
+
24
+ def deserialize(raw, type_id, array: false)
25
+ return if raw.nil?
26
+
27
+ caster =
28
+ if type_id.is_a?(Symbol) || type_id.nil?
29
+ registry.fetch(type_id) { raise ArgumentError, "Unknown type: #{type_id}" }
30
+ else
31
+ raise ArgumentError, "Type must implement #call(val): #{type_id}" unless type_id.respond_to?(:call)
32
+ type_id
33
+ end
34
+
35
+ if array
36
+ raw_arr = raw.is_a?(String) ? raw.split(/\s*,\s*/) : Array(raw)
37
+ raw_arr.map { it = _1;caster.call(it) }
38
+ else
39
+ caster.call(raw)
40
+ end
41
+ end
42
+
43
+ def dup
44
+ new_obj = self.class.allocate
45
+ new_obj.instance_variable_set(:@registry, registry.dup)
46
+ new_obj
47
+ end
48
+
49
+ private
50
+
51
+ attr_reader :registry
52
+ end
53
+
54
+ TypeRegistry.default.tap do |obj|
55
+ obj.accept(nil, &:itself)
56
+ obj.accept(:string, &:to_s)
57
+ obj.accept(:integer, &:to_i)
58
+ obj.accept(:float, &:to_f)
59
+
60
+ obj.accept(:date) do
61
+ require "date" unless defined?(::Date)
62
+
63
+ next _1 if _1.is_a?(::Date)
64
+
65
+ next _1.to_date if _1.respond_to?(:to_date)
66
+
67
+ ::Date.parse(_1)
68
+ end
69
+
70
+ obj.accept(:datetime) do
71
+ require "date" unless defined?(::Date)
72
+
73
+ next _1 if _1.is_a?(::DateTime)
74
+
75
+ next _1.to_datetime if _1.respond_to?(:to_datetime)
76
+
77
+ ::DateTime.parse(_1)
78
+ end
79
+
80
+ obj.accept(:uri) do
81
+ require "uri" unless defined?(::URI)
82
+
83
+ next _1 if _1.is_a?(::URI)
84
+
85
+ ::URI.parse(_1)
86
+ end
87
+
88
+ obj.accept(:boolean) do
89
+ _1.to_s.match?(/\A(true|t|yes|y|1)\z/i)
90
+ end
91
+ end
92
+
93
+ unless "".respond_to?(:safe_constantize)
94
+ require "anyway/ext/string_constantize"
95
+ using Anyway::Ext::StringConstantize
96
+ end
97
+
98
+ # TypeCaster is an object responsible for type-casting.
99
+ # It uses a provided types registry and mapping, and also
100
+ # accepts a fallback typecaster.
101
+ class TypeCaster
102
+ using Ext::DeepDup
103
+ using Ext::Hash
104
+
105
+ def initialize(mapping, registry: TypeRegistry.default, fallback: ::Anyway::AutoCast)
106
+ @mapping = mapping.deep_dup
107
+ @registry = registry
108
+ @fallback = fallback
109
+ end
110
+
111
+ def coerce(key, val, config: mapping)
112
+ caster_config = config[key.to_sym]
113
+
114
+ return fallback.coerce(key, val) unless caster_config
115
+
116
+ case caster_config
117
+ in Hash[array:, type:, **nil]
118
+ registry.deserialize(val, type, array: array)
119
+ in Hash[config: subconfig]
120
+ subconfig = subconfig.safe_constantize if subconfig.is_a?(::String)
121
+ raise ArgumentError, "Config is not found: #{subconfig}" unless subconfig
122
+
123
+ subconfig.new(val)
124
+ in Hash
125
+ return val unless val.is_a?(Hash)
126
+
127
+ caster_config.each do |k, v|
128
+ ks = k.to_s
129
+ next unless val.key?(ks)
130
+
131
+ val[ks] = coerce(k, val[ks], config: caster_config)
132
+ end
133
+
134
+ val
135
+ else
136
+ registry.deserialize(val, caster_config)
137
+ end
138
+ end
139
+
140
+ private
141
+
142
+ attr_reader :mapping, :registry, :fallback
143
+ end
144
+ end
@@ -13,9 +13,9 @@ module Anyway
13
13
 
14
14
  case val
15
15
  when Hash
16
- val.transform_values { call(_1) }
16
+ val.transform_values { call(it) }
17
17
  when ARRAY_RXP
18
- val.split(/\s*,\s*/).map { call(_1) }
18
+ val.split(/\s*,\s*/).map { call(it) }
19
19
  when /\A(true|t|yes|y)\z/i
20
20
  true
21
21
  when /\A(false|f|no|n)\z/i
data/lib/anyway/config.rb CHANGED
@@ -154,7 +154,7 @@ module Anyway # :nodoc:
154
154
  if block
155
155
  load_callbacks << BlockCallback.new(block)
156
156
  else
157
- load_callbacks.push(*names.map { NamedCallback.new(_1) })
157
+ load_callbacks.push(*names.map { NamedCallback.new(it) })
158
158
  end
159
159
  end
160
160
 
@@ -380,7 +380,7 @@ module Anyway # :nodoc:
380
380
  trace&.keep_if { |key| self.class.config_attributes.include?(key.to_sym) }
381
381
 
382
382
  # Run on_load callbacks
383
- self.class.load_callbacks.each { _1.apply_to(self) }
383
+ self.class.load_callbacks.each { it.apply_to(self) }
384
384
 
385
385
  # Set trace after we write all the values to
386
386
  # avoid changing the source to accessor
@@ -389,14 +389,14 @@ module Anyway # :nodoc:
389
389
  self
390
390
  end
391
391
 
392
- def load_from_sources(base_config, **options)
392
+ def load_from_sources(base_config, **)
393
393
  Anyway.loaders.each do |(_id, loader)|
394
- Utils.deep_merge!(base_config, loader.call(**options))
394
+ Utils.deep_merge!(base_config, loader.call(**))
395
395
  end
396
396
  base_config
397
397
  end
398
398
 
399
- def dig(*keys) = values.dig(*keys)
399
+ def dig(*) = values.dig(*)
400
400
 
401
401
  def to_h() = values.deep_dup.deep_freeze
402
402
 
@@ -6,8 +6,8 @@ module Anyway
6
6
  include Tracing
7
7
 
8
8
  class << self
9
- def call(local: Anyway::Settings.use_local_files, **opts)
10
- new(local:).call(**opts)
9
+ def call(local: Anyway::Settings.use_local_files, **)
10
+ new(local:).call(**)
11
11
  end
12
12
  end
13
13
 
@@ -26,12 +26,12 @@ module Anyway
26
26
  value.dig(...)
27
27
  end
28
28
 
29
- def record_value(val, *path, **opts)
29
+ def record_value(val, *path, **)
30
30
  key = path.pop
31
31
  trace = if val.is_a?(Hash)
32
- Trace.new.tap { _1.merge_values(val, **opts) }
32
+ Trace.new.tap { it.merge_values(val, **) }
33
33
  else
34
- Trace.new(:value, val, **opts)
34
+ Trace.new(:value, val, **)
35
35
  end
36
36
 
37
37
  target_trace = path.empty? ? self : value.dig(*path)
@@ -40,14 +40,14 @@ module Anyway
40
40
  val
41
41
  end
42
42
 
43
- def merge_values(hash, **opts)
43
+ def merge_values(hash, **)
44
44
  return hash unless hash
45
45
 
46
46
  hash.each do |key, val|
47
47
  if val.is_a?(Hash)
48
- value[key.to_s].merge_values(val, **opts)
48
+ value[key.to_s].merge_values(val, **)
49
49
  else
50
- value[key.to_s] = Trace.new(:value, val, **opts)
50
+ value[key.to_s] = Trace.new(:value, val, **)
51
51
  end
52
52
  end
53
53
 
@@ -84,7 +84,7 @@ module Anyway
84
84
 
85
85
  def to_h
86
86
  if trace?
87
- value.transform_values(&:to_h).tap { _1.default_proc = nil }
87
+ value.transform_values(&:to_h).tap { it.default_proc = nil }
88
88
  else
89
89
  {value:, source:}
90
90
  end
@@ -174,13 +174,13 @@ module Anyway
174
174
 
175
175
  module_function
176
176
 
177
- def trace!(type, *path, **opts)
177
+ def trace!(type, *path, **)
178
178
  return yield unless Tracing.tracing?
179
179
  val = yield
180
180
  if val.is_a?(Hash)
181
- Tracing.current_trace.merge_values(val, type:, **opts)
181
+ Tracing.current_trace.merge_values(val, type:, **)
182
182
  elsif !path.empty?
183
- Tracing.current_trace.record_value(val, *path, type:, **opts)
183
+ Tracing.current_trace.record_value(val, *path, type:, **)
184
184
  end
185
185
  val
186
186
  end
@@ -34,7 +34,7 @@ module Anyway
34
34
 
35
35
  if array
36
36
  raw_arr = raw.is_a?(String) ? raw.split(/\s*,\s*/) : Array(raw)
37
- raw_arr.map { caster.call(_1) }
37
+ raw_arr.map { caster.call(it) }
38
38
  else
39
39
  caster.call(raw)
40
40
  end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Anyway # :nodoc:
4
- VERSION = "2.5.4"
4
+ VERSION = "2.6.0"
5
5
  end
@@ -0,0 +1,24 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "rails/commands/credentials/credentials_command"
4
+
5
+ module Rails
6
+ module Command
7
+ class LocalCredentialsCommand < CredentialsCommand
8
+ desc "edit", "Open the decrypted local credentials in `$VISUAL` or `$EDITOR` for editing"
9
+ def edit
10
+ load_environment_config!
11
+ load_generators
12
+
13
+ @content_path = "config/credentials/local.yml.enc"
14
+ @key_path = "config/credentials/local.key"
15
+
16
+ ensure_encryption_key_has_been_added
17
+ ensure_credentials_have_been_added
18
+ ensure_diffing_driver_is_configured
19
+
20
+ change_credentials_in_system_editor
21
+ end
22
+ end
23
+ end
24
+ 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.5.4
4
+ version: 2.6.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: 2023-10-16 00:00:00.000000000 Z
11
+ date: 2023-12-18 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.14.0
19
+ version: '0.15'
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.14.0
26
+ version: '0.15'
27
27
  - !ruby/object:Gem::Dependency
28
28
  name: ammeter
29
29
  requirement: !ruby/object:Gem::Requirement
@@ -70,16 +70,16 @@ dependencies:
70
70
  name: ruby-next
71
71
  requirement: !ruby/object:Gem::Requirement
72
72
  requirements:
73
- - - ">="
73
+ - - "~>"
74
74
  - !ruby/object:Gem::Version
75
- version: 0.14.0
75
+ version: '1.0'
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
- version: 0.14.0
82
+ version: '1.0'
83
83
  - !ruby/object:Gem::Dependency
84
84
  name: webmock
85
85
  requirement: !ruby/object:Gem::Requirement
@@ -138,6 +138,13 @@ files:
138
138
  - lib/.rbnext/3.1/anyway/env.rb
139
139
  - lib/.rbnext/3.1/anyway/loaders/base.rb
140
140
  - lib/.rbnext/3.1/anyway/tracing.rb
141
+ - lib/.rbnext/3.2/anyway/config.rb
142
+ - lib/.rbnext/3.2/anyway/loaders/base.rb
143
+ - lib/.rbnext/3.2/anyway/tracing.rb
144
+ - lib/.rbnext/3.4/anyway/auto_cast.rb
145
+ - lib/.rbnext/3.4/anyway/config.rb
146
+ - lib/.rbnext/3.4/anyway/tracing.rb
147
+ - lib/.rbnext/3.4/anyway/type_casting.rb
141
148
  - lib/anyway.rb
142
149
  - lib/anyway/auto_cast.rb
143
150
  - lib/anyway/config.rb
@@ -185,6 +192,7 @@ files:
185
192
  - lib/generators/anyway/install/USAGE
186
193
  - lib/generators/anyway/install/install_generator.rb
187
194
  - lib/generators/anyway/install/templates/application_config.rb.tt
195
+ - lib/rails/commands/local_credentials/local_credentials_command.rb
188
196
  - sig/anyway_config.rbs
189
197
  - sig/manifest.yml
190
198
  homepage: http://github.com/palkan/anyway_config
@@ -212,7 +220,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
212
220
  - !ruby/object:Gem::Version
213
221
  version: '0'
214
222
  requirements: []
215
- rubygems_version: 3.4.8
223
+ rubygems_version: 3.4.20
216
224
  signing_key:
217
225
  specification_version: 4
218
226
  summary: Configuration DSL for Ruby libraries and applications