etcher 1.4.0 → 1.6.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- checksums.yaml.gz.sig +0 -0
- data/README.adoc +96 -32
- data/etcher.gemspec +1 -1
- data/lib/etcher/finder.rb +21 -0
- data/lib/etcher/registry.rb +24 -4
- data/lib/etcher/transformers/string.rb +32 -0
- data/lib/etcher/transformers/time.rb +26 -0
- data.tar.gz.sig +0 -0
- metadata +6 -3
- metadata.gz.sig +0 -0
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 3e462682ab4cb1a7149595a36e1d2893f329db37813209655c53a6fd767e9751
|
4
|
+
data.tar.gz: 2f1a5bd597dfa8590d6ad48f9bd92de9688023b14a40c3856842d4539c9e3ca7
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 37067ae8933e3512d3be4a0e10147cad3813a76c969c414801b915b31c164bd1154b11dff58bb1196857e7f30b5fc9455ade7f305824ddf2a0c61c7149eec610
|
7
|
+
data.tar.gz: d37ae593f29bc0a8c2402dc39bc4d6df37478baec964480b76bbd94a23b00ff17d4236d21deff7e57b92cd18ed1d0f5cc29f00f7b7c907c0c6158c7ecf8543a7
|
checksums.yaml.gz.sig
CHANGED
Binary file
|
data/README.adoc
CHANGED
@@ -111,7 +111,7 @@ transformer = lambda do |attributes, key = :user|
|
|
111
111
|
end
|
112
112
|
|
113
113
|
Etcher::Registry.new(contract:, model:, transformers: [transformer])
|
114
|
-
.add_loader(
|
114
|
+
.add_loader(:environment, %w[USER HOME])
|
115
115
|
.then { |registry| Etcher.new(registry).call }
|
116
116
|
|
117
117
|
# Success(#<data user="DEMO", home="/Users/demo">)
|
@@ -297,11 +297,29 @@ There are a few guidelines to using them:
|
|
297
297
|
* All nested keys will be flattened after being loaded. This means a key structure of `{demo: {one: "test"}}` will be flattened to `demo_one: "test"` which adheres to the {demeter_link} when a new recored is _etched_ for you.
|
298
298
|
* The order in which you define your loaders matters. This means the first loader defined will be processed first, then the second, and so forth. Loaders defined last take precedence over previously defined loaders when overriding the same keys.
|
299
299
|
|
300
|
-
|
300
|
+
For convenience, all loaders -- only packaged with this gem -- can be registered by symbol instead of constant/instance. Example:
|
301
|
+
|
302
|
+
[source,ruby]
|
303
|
+
----
|
304
|
+
registry = Etcher::Registry.new
|
305
|
+
|
306
|
+
# Environment
|
307
|
+
registry.add_loader :environment
|
308
|
+
|
309
|
+
# JSON
|
310
|
+
registry.add_loader :json, "path/to/configuration.json"
|
311
|
+
|
312
|
+
# YAML
|
313
|
+
registry.add_loader :yaml, "path/to/configuration.yml"
|
314
|
+
----
|
315
|
+
|
316
|
+
Any positional or keyword arguments will be passed to the loader's constructor. _This only works when using `Registry#add_loader`, though._
|
317
|
+
|
318
|
+
The next sections will help you learn about the supported loaders and how to build your own custom loader.
|
301
319
|
|
302
320
|
==== Environment
|
303
321
|
|
304
|
-
Use `Etcher::Loaders::Environment` to load configuration information from your {environment_link}. By default, this object wraps `ENV`, uses an empty array for keys
|
322
|
+
Use `:environment` or `Etcher::Loaders::Environment` to load configuration information from your {environment_link}. By default, this object wraps `ENV`, uses an empty array for included keys, and answers a filtered hash where all keys are downcased. _If you don't specify keys to include, then an empty hash is answered back_. Here's a few examples:
|
305
323
|
|
306
324
|
[source,ruby]
|
307
325
|
----
|
@@ -414,16 +432,15 @@ registry = Etcher::Registry[transformers: [MyTransformer]]
|
|
414
432
|
registry = Etcher::Registry.new.add_transformer MyTransformer
|
415
433
|
----
|
416
434
|
|
417
|
-
|
435
|
+
The guidelines for using transformers are:
|
418
436
|
|
419
|
-
* They can be initialized with whatever requirements you
|
437
|
+
* They can be initialized with whatever requirements you need.
|
420
438
|
* They must respond to `#call` which takes a required `attributes` positional argument and answers a modified version of these attributes (`Hash`) wrapped as a monad.
|
421
|
-
*
|
439
|
+
* When using a proc/lambda, the first, _required_, parameter should be the `attributes` parameter followed by an _optional_ positional `key` parameter with a default value. This allows you to quickly refactor the key later while also reducing key duplication throughout your implementation.
|
440
|
+
* When using a class, the `key` should be your first positional parameter with a default value. Additional parameters can be supplied after if desired.
|
422
441
|
* The `attributes` passed to your transformer will have symbolized keys so you don't need to transform them further.
|
423
442
|
|
424
|
-
|
425
|
-
|
426
|
-
The following capitalizes all values (which may or may not be good depending on your data structure).
|
443
|
+
For example, the following capitalizes all values (which may or may not be good depending on your data structure):
|
427
444
|
|
428
445
|
[source,ruby]
|
429
446
|
----
|
@@ -435,28 +452,7 @@ Capitalize.call(name: "test")
|
|
435
452
|
# Success({:name=>"Test"})
|
436
453
|
----
|
437
454
|
|
438
|
-
The following
|
439
|
-
|
440
|
-
[source,ruby]
|
441
|
-
----
|
442
|
-
require "dry/monads"
|
443
|
-
|
444
|
-
CurrentTime = lambda do |attributes, key = :at, at: Time.now|
|
445
|
-
attributes.fetch(key) { at }
|
446
|
-
.then { |value| Dry::Monads::Success attributes.merge!(key => value) }
|
447
|
-
end
|
448
|
-
|
449
|
-
CurrentTime.call({})
|
450
|
-
# Success({:at=>2023-04-23 15:22:23.746408 -0600})
|
451
|
-
|
452
|
-
CurrentTime.call({at: Time.utc(2023, 10, 15)})
|
453
|
-
# Success({:at=>2023-10-15 00:00:00 UTC})
|
454
|
-
|
455
|
-
CurrentTime.call({}, at: Time.utc(2023, 1, 10))
|
456
|
-
# Success({:at=>2023-01-10 00:00:00 UTC})
|
457
|
-
----
|
458
|
-
|
459
|
-
The following obtains the current Git user's email address from the global Git configuration using the {gitt_link} gem.
|
455
|
+
The following obtains the current Git user's email address from the global Git configuration using the {gitt_link} gem:
|
460
456
|
|
461
457
|
[source,ruby]
|
462
458
|
----
|
@@ -485,11 +481,79 @@ To use all of the above, you'd only need to register and use them:
|
|
485
481
|
|
486
482
|
[source,ruby]
|
487
483
|
----
|
488
|
-
registry = Etcher::Registry[transformers: [Capitalize,
|
484
|
+
registry = Etcher::Registry[transformers: [Capitalize, GitEmail.new]]
|
489
485
|
etcher = Etcher.new(registry)
|
490
486
|
etcher.call
|
491
487
|
----
|
492
488
|
|
489
|
+
For convenience, all transformers -- only packaged with this gem -- can be registered by symbol instead of constant/instance. Example:
|
490
|
+
|
491
|
+
[source,ruby]
|
492
|
+
----
|
493
|
+
registry = Etcher::Registry.new
|
494
|
+
|
495
|
+
# String
|
496
|
+
registry.add_transformer :string, :project_uri
|
497
|
+
|
498
|
+
# Time
|
499
|
+
registry.add_transformer :time
|
500
|
+
----
|
501
|
+
|
502
|
+
Any positional or keyword arguments will be passed to the transformers's constructor. _This only works when using `Registry#add_transformer`, though._ The following sections provide more details on each.
|
503
|
+
|
504
|
+
==== String
|
505
|
+
|
506
|
+
Use `Etcher::Transformers::String` to transform any key in your configuration by using the configuration's existing keys. Example:
|
507
|
+
|
508
|
+
[source,ruby]
|
509
|
+
----
|
510
|
+
attributes = {
|
511
|
+
organization_uri: "https://acme.io",
|
512
|
+
project_name: "test",
|
513
|
+
project_uri: "%<organization_uri>s/projects/%<project_name>s"
|
514
|
+
}
|
515
|
+
|
516
|
+
transformer = Etcher::Transformers::String.new :project_uri
|
517
|
+
|
518
|
+
transformer.call attributes
|
519
|
+
# Success(
|
520
|
+
{
|
521
|
+
organization_uri: "https://acme.io",
|
522
|
+
project_name: "test",
|
523
|
+
project_uri: "https://acme.io/projects/test"
|
524
|
+
}
|
525
|
+
)
|
526
|
+
|
527
|
+
attributes.delete :project_name
|
528
|
+
transformer.call attributes
|
529
|
+
# Failure("Unable to transform :project_uri, missing specifier: \"<project_name>\".")
|
530
|
+
----
|
531
|
+
|
532
|
+
==== Time
|
533
|
+
|
534
|
+
Use `Etcher::Transformers::Time` to transform the `loaded_at` key in your configuration when you want to know the current time at which the configuration was loaded. Handy for situations where you need to calculate relative time or format time based on when your configuration was loaded.
|
535
|
+
|
536
|
+
Even though `loaded_at` is the default key and `Time.now.utc` is the default fallback, you're not limited to using different keys and fallbacks. Example:
|
537
|
+
|
538
|
+
[source,ruby]
|
539
|
+
----
|
540
|
+
transformer = Etcher::Transformers::Time.new
|
541
|
+
transformer.call({})
|
542
|
+
# Success({:loaded_at=>2024-05-23 22:18:27.92767 UTC})
|
543
|
+
|
544
|
+
transformer = Etcher::Transformers::Time.new :now
|
545
|
+
transformer.call({})
|
546
|
+
# Success({:now=>2024-05-23 22:18:49.93189 UTC})
|
547
|
+
|
548
|
+
transformer = Etcher::Transformers::Time.new :now, fallback: Time.utc(2000, 1, 1)
|
549
|
+
transformer.call({})
|
550
|
+
# Success({:now=>2000-01-01 00:00:00 UTC})
|
551
|
+
|
552
|
+
transformer = Etcher::Transformers::Time.new
|
553
|
+
transformer.call({loaded_at: Time.utc(2000, 1, 1)})
|
554
|
+
# Success({:loaded_at=>2000-01-01 00:00:00 UTC})
|
555
|
+
----
|
556
|
+
|
493
557
|
=== Overrides
|
494
558
|
|
495
559
|
Overrides are what you pass to the Etcher instance when called. Example:
|
data/etcher.gemspec
CHANGED
@@ -0,0 +1,21 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "dry/monads"
|
4
|
+
|
5
|
+
# Finds internal constant if moniker matches, otherwise answers a failure.
|
6
|
+
module Etcher
|
7
|
+
include Dry::Monads[:result]
|
8
|
+
|
9
|
+
Finder = lambda do |namespace, moniker|
|
10
|
+
Etcher.const_get(namespace)
|
11
|
+
.constants
|
12
|
+
.find { |constant| constant.downcase == moniker }
|
13
|
+
.then do |constant|
|
14
|
+
return Dry::Monads::Success Etcher.const_get("#{namespace}::#{constant}") if constant
|
15
|
+
|
16
|
+
Dry::Monads::Failure "Unable to select #{moniker.inspect} within #{namespace.downcase}."
|
17
|
+
end
|
18
|
+
rescue NameError
|
19
|
+
Dry::Monads::Failure "Invalid namespace: #{namespace.inspect}."
|
20
|
+
end
|
21
|
+
end
|
data/lib/etcher/registry.rb
CHANGED
@@ -3,17 +3,37 @@
|
|
3
3
|
module Etcher
|
4
4
|
# Provides a registry of customization for loading and resolving a configuration.
|
5
5
|
Registry = Data.define :contract, :model, :loaders, :transformers do
|
6
|
+
def self.find namespace, moniker, logger: LOGGER
|
7
|
+
case Finder.call namespace, moniker
|
8
|
+
in Success(constant) then constant
|
9
|
+
in Failure(message) then logger.abort message
|
10
|
+
else logger.abort "Unable to find constant in registry."
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
6
14
|
def initialize contract: Contract, model: Hash, loaders: [], transformers: []
|
7
15
|
super
|
8
16
|
end
|
9
17
|
|
10
|
-
def add_loader
|
11
|
-
|
18
|
+
def add_loader(loader, *, **)
|
19
|
+
if loader.is_a? Symbol
|
20
|
+
self.class.find(:Loaders, loader).then { |constant| loaders.append constant.new(*, **) }
|
21
|
+
else
|
22
|
+
loaders.append loader
|
23
|
+
end
|
24
|
+
|
12
25
|
self
|
13
26
|
end
|
14
27
|
|
15
|
-
def add_transformer
|
16
|
-
|
28
|
+
def add_transformer(transformer, *, **)
|
29
|
+
if transformer.is_a? Symbol
|
30
|
+
self.class.find(:Transformers, transformer).then do |constant|
|
31
|
+
transformers.append constant.new(*, **)
|
32
|
+
end
|
33
|
+
else
|
34
|
+
transformers.append transformer
|
35
|
+
end
|
36
|
+
|
17
37
|
self
|
18
38
|
end
|
19
39
|
end
|
@@ -0,0 +1,32 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "dry/monads"
|
4
|
+
|
5
|
+
module Etcher
|
6
|
+
module Transformers
|
7
|
+
# Formats given key using existing and/or ancillary attributes.
|
8
|
+
class String
|
9
|
+
include Dry::Monads[:result]
|
10
|
+
|
11
|
+
def initialize key, **ancillary
|
12
|
+
@key = key
|
13
|
+
@ancillary = ancillary
|
14
|
+
end
|
15
|
+
|
16
|
+
def call attributes
|
17
|
+
value = attributes[key]
|
18
|
+
|
19
|
+
return Success attributes unless value
|
20
|
+
|
21
|
+
Success attributes.merge(key => format(value, **attributes, **ancillary))
|
22
|
+
rescue KeyError => error
|
23
|
+
Failure "Unable to transform #{key.inspect}, missing specifier: " \
|
24
|
+
"\"#{error.message[/<.+>/]}\"."
|
25
|
+
end
|
26
|
+
|
27
|
+
private
|
28
|
+
|
29
|
+
attr_reader :key, :ancillary
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "dry/monads"
|
4
|
+
|
5
|
+
module Etcher
|
6
|
+
module Transformers
|
7
|
+
# Conditionally transforms current time for key.
|
8
|
+
class Time
|
9
|
+
include Dry::Monads[:result]
|
10
|
+
|
11
|
+
def initialize key = :loaded_at, fallback: ::Time.now.utc
|
12
|
+
@key = key
|
13
|
+
@fallback = fallback
|
14
|
+
end
|
15
|
+
|
16
|
+
def call attributes
|
17
|
+
attributes.fetch(key) { fallback }
|
18
|
+
.then { |value| Success attributes.merge!(key => value) }
|
19
|
+
end
|
20
|
+
|
21
|
+
private
|
22
|
+
|
23
|
+
attr_reader :key, :fallback
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
data.tar.gz.sig
CHANGED
Binary file
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: etcher
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.
|
4
|
+
version: 1.6.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Brooke Kuhlmann
|
@@ -35,7 +35,7 @@ cert_chain:
|
|
35
35
|
3n5C8/6Zh9DYTkpcwPSuIfAga6wf4nXc9m6JAw8AuMLaiWN/r/2s4zJsUHYERJEu
|
36
36
|
gZGm4JqtuSg8pYjPeIJxS960owq+SfuC+jxqmRA54BisFCv/0VOJi7tiJVY=
|
37
37
|
-----END CERTIFICATE-----
|
38
|
-
date: 2024-05-
|
38
|
+
date: 2024-05-31 00:00:00.000000000 Z
|
39
39
|
dependencies:
|
40
40
|
- !ruby/object:Gem::Dependency
|
41
41
|
name: cogger
|
@@ -150,11 +150,14 @@ files:
|
|
150
150
|
- lib/etcher.rb
|
151
151
|
- lib/etcher/builder.rb
|
152
152
|
- lib/etcher/contract.rb
|
153
|
+
- lib/etcher/finder.rb
|
153
154
|
- lib/etcher/loaders/environment.rb
|
154
155
|
- lib/etcher/loaders/json.rb
|
155
156
|
- lib/etcher/loaders/yaml.rb
|
156
157
|
- lib/etcher/registry.rb
|
157
158
|
- lib/etcher/resolver.rb
|
159
|
+
- lib/etcher/transformers/string.rb
|
160
|
+
- lib/etcher/transformers/time.rb
|
158
161
|
- lib/etcher/types.rb
|
159
162
|
homepage: https://alchemists.io/projects/etcher
|
160
163
|
licenses:
|
@@ -182,7 +185,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
182
185
|
- !ruby/object:Gem::Version
|
183
186
|
version: '0'
|
184
187
|
requirements: []
|
185
|
-
rubygems_version: 3.5.
|
188
|
+
rubygems_version: 3.5.11
|
186
189
|
signing_key:
|
187
190
|
specification_version: 4
|
188
191
|
summary: A monadic configuration loader, transformer, and validator.
|
metadata.gz.sig
CHANGED
Binary file
|