re_sorcery 0.1.0 → 0.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 0b2890e5efcd2dbd01d5f849d9ba9887ac5c78077057b6406ae458ef3c048337
4
- data.tar.gz: 3971c5c49f0c6d6bc0ac407b6b79091e1e2e9d16fa7d80c7deab0e12d3a94954
3
+ metadata.gz: f72b419777c7c5f2f57db936293ccb8fd1fbc7fd4b2ca5de14c21ac4be9ee7f7
4
+ data.tar.gz: 88d0385f9d01c64b0ad1e95fcb6350bb78ea301d0b6f291c0cb967b99d17a46e
5
5
  SHA512:
6
- metadata.gz: 6281d8f26287f854baccd61aa8e800dd27720053262b99380c5f2a26b4336b8bef238f7073722f8789d4da9b84f17a021df2e74030b64be995425c6cf5ae9f70
7
- data.tar.gz: 546cc421b749cd28393494f10190bd34e9e7ed1ff5170b91a07724fccc94ece8351e03fc3d672e98e3c1e9908aa21abbdf91fc8eb86d0db2426ea9131eb7f0dd
6
+ metadata.gz: 4fff11e2b74ec4c68f5c6de80815495583097d5fda2994a016382b93deaf4f0abe7492f292cf8a1831b514c0a68cd296680196051ca94be3b9c81a98f205489b
7
+ data.tar.gz: b4446f2fec6609d8a5042ced152cee096bbd44d3d041de781275017ee7153f6633e5eeef917f8ea8daac131f9750853d756013c4fae48bb98410a95e56f2164e
data/Gemfile.lock CHANGED
@@ -1,28 +1,32 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- re_sorcery (0.1.0)
4
+ re_sorcery (0.3.0)
5
+ addressable (~> 2.8, >= 2.8.1)
5
6
 
6
7
  GEM
7
8
  remote: https://rubygems.org/
8
9
  specs:
10
+ addressable (2.8.1)
11
+ public_suffix (>= 2.0.2, < 6.0)
9
12
  coderay (1.1.3)
10
13
  method_source (1.0.0)
11
- minitest (5.14.4)
12
- pry (0.14.1)
14
+ minitest (5.17.0)
15
+ pry (0.14.2)
13
16
  coderay (~> 1.1)
14
17
  method_source (~> 1.0)
15
- rake (10.5.0)
18
+ public_suffix (5.0.1)
19
+ rake (13.0.6)
16
20
 
17
21
  PLATFORMS
18
- ruby
22
+ arm64-darwin-21
19
23
 
20
24
  DEPENDENCIES
21
- bundler (~> 2.0)
22
- re_sorcery!
23
- minitest (~> 5.0)
25
+ bundler (~> 2.3)
26
+ minitest (~> 5.16)
24
27
  pry
25
- rake (~> 10.0)
28
+ rake (~> 13.0)
29
+ re_sorcery!
26
30
 
27
31
  BUNDLED WITH
28
- 2.0.2
32
+ 2.3.7
data/README.md CHANGED
@@ -15,11 +15,14 @@ and link validation before sending resources to the client.
15
15
  `Array` of `<link>` objects).
16
16
  - Each entry in the `:payload` is type checked using a `Decoder` (inspired by [Elm's Decoders]).
17
17
  - A `<link>` is a `Hash` with four fields:
18
- - `:href`, which is either a `URI` or a `String` that parses as a valid `URI`;
18
+ - `:href`, which is either a `URI` or a `String` that parses as a valid `URI` ([Addressable] is
19
+ used for URI-parsing, as it handles URI templates.)
19
20
  - `:rel`, which is a white-listed `String`;
20
21
  - `:method`, which is also a white-listed `String`; and
21
22
  - `:type`, which is a `String`.
22
23
 
24
+ [Addressable]: https://github.com/sporkmonger/addressable
25
+
23
26
  Demo:
24
27
 
25
28
  ```ruby
@@ -33,12 +36,17 @@ class StaticResource
33
36
  end
34
37
  end
35
38
 
36
- StaticResource.new.resource
37
- # #<ReSorcery::Result::Ok @value={
38
- # :payload=>{:string=>"a string", :number=>42},
39
- # :links=>[{:rel=>"self", :href=>"/here", :method=>"get", :type=>"application/json"},
40
- # {:rel=>"create", :href=>"/here", :method=>"post", :type=>"application/json"}]
41
- # }>
39
+ StaticResource.new.as_json
40
+ # {
41
+ # :payload=>{
42
+ # :string=>"a string",
43
+ # :number=>42
44
+ # },
45
+ # :links=>[
46
+ # {:rel=>"self", :href=>"/here", :method=>"get", :type=>"application/json"},
47
+ # {:rel=>"create", :href=>"/here", :method=>"post", :type=>"application/json"}
48
+ # ]
49
+ # }
42
50
  ```
43
51
 
44
52
  ## Installation
@@ -90,8 +98,8 @@ User.new(name: "Spencer", id: 1, admin: true).as_json #=> {
90
98
 
91
99
  # An invalid `name` raises an error when calling `as_json`
92
100
  User.new(name: :Invalid, id: 1).as_json
93
- # ReSorcery::Error::InvalidResourceError: Error at field `name` of `User`: Expected a(n) String, but
94
- # got a(n) Symbol
101
+ # ReSorcery::Error::InvalidResourceError:
102
+ # Error at field `name` of `User`: Expected kind String, but got Symbol
95
103
  ```
96
104
 
97
105
  The implementation of `ReSorcery#as_json` raises an exception on invalid data, instead of serving
@@ -14,26 +14,46 @@ module ReSorcery
14
14
  # link_methods ['get', 'post', 'put']
15
15
  # end
16
16
  #
17
- # @see `Configuration::CONFIGURABLES` for a list of what can be configured and
18
- # what value each configurable takes.
17
+ # @see `Configuration::CONFIGURABLES`, whose keys define the list of
18
+ # configuration methods. Each entry contains a `:decoder` key, which is used
19
+ # to check the value passed to the configuration method, and a `:default`
20
+ # key, which is the default value for that entry.
19
21
  #
20
22
  module Configuration
21
23
  extend Decoder::BuiltinDecoders
22
24
 
25
+ UNIQUE_STRING_OR_SYMBOL = non_empty_array(is(String, Symbol).map(&:to_s)).map(&:uniq)
26
+ DEFAULT_LINK_METHOD_DECODER = is(Proc)
27
+ .and { |p| p.arity == 1 || "default_link_method Proc must accept exactly one argument" }
28
+
23
29
  CONFIGURABLES = {
24
- link_rels: array(String),
25
- link_methods: array(String),
30
+ link_rels: {
31
+ decoder: UNIQUE_STRING_OR_SYMBOL,
32
+ default: %w[self create update destroy].freeze,
33
+ }.freeze,
34
+ link_methods: {
35
+ decoder: UNIQUE_STRING_OR_SYMBOL,
36
+ default: %w[get post patch put delete].freeze,
37
+ }.freeze,
38
+ default_link_method: {
39
+ decoder: DEFAULT_LINK_METHOD_DECODER,
40
+ default: ->(link_methods) { link_methods.first }.freeze,
41
+ }.freeze,
42
+ default_link_type: {
43
+ decoder: is(String),
44
+ default: "application/json",
45
+ }.freeze,
26
46
  }.freeze
27
47
 
28
48
  def configuration
29
- @configuration ||= {}
49
+ @configuration ||= CONFIGURABLES.transform_values { |v| v.fetch(:default) }
30
50
  end
31
51
 
32
- def configure(&block)
52
+ def configure(&)
33
53
  raise Error::InvalidConfigurationError, @configured if configured?
34
54
 
35
55
  @configured = "configured at #{caller_locations.first}"
36
- instance_exec(&block)
56
+ instance_exec(&)
37
57
  end
38
58
 
39
59
  private
@@ -42,7 +62,8 @@ module ReSorcery
42
62
  @configured ||= false
43
63
  end
44
64
 
45
- CONFIGURABLES.each do |name, decoder|
65
+ CONFIGURABLES.each do |name, metadata|
66
+ decoder = metadata.fetch(:decoder)
46
67
  define_method(name) do |value|
47
68
  decoder.test(value).cata(
48
69
  ok: ->(v) { configuration[name] = v },
@@ -1,5 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require 'set'
4
+
3
5
  module ReSorcery
4
6
  class Decoder
5
7
  # Common decoders implemented here for convenience
@@ -9,17 +11,60 @@ module ReSorcery
9
11
  private
10
12
 
11
13
  # A Decoder that always succeeds with a given value
14
+ #
15
+ # Useful for starting decoder chains that build up successful values.
12
16
  def succeed(value)
13
17
  Decoder.new { ok(value) }
14
18
  end
15
19
 
16
20
  # A decoder that always fails with some error message
21
+ #
22
+ # Useful for starting decoder chains that search for a successful value.
17
23
  def fail(message = '`fail` Decoder always fails')
18
24
  ArgCheck['message', message, String]
19
25
 
20
26
  Decoder.new { message }
21
27
  end
22
28
 
29
+ # Test if an object is_a?(first_mod) (or is one of a list of modules)
30
+ #
31
+ # Note that classes are also modules.
32
+ #
33
+ # In general prefer `#is`.
34
+ #
35
+ # @param [Module] first_mod
36
+ # @param [Array<Module>] others
37
+ # @return [Decoder]
38
+ def mod(first_mod, *others)
39
+ all_mods = ([first_mod] + others).map.with_index { |o, i| ArgCheck["mods[#{i}]", o, Module] }
40
+ raise ReSorcery::Error::ArgumentError, "Do not use `nil`" if all_mods.include?(NilClass)
41
+
42
+ mods = all_mods.select { |m| ((m.ancestors - [m]) & all_mods).empty? }
43
+
44
+ msg = lambda {
45
+ prefix = mods.count == 1 ? "Expected" : "Expected one of"
46
+ "#{prefix} (#{mods.join(' | ')}) but received"
47
+ }
48
+
49
+ Decoder.new { |u| mods.any? { |m| u.is_a?(m) } || "#{msg.call}: #{u.class}" }
50
+ end
51
+
52
+ # Test if an object is one of a specific set of things
53
+ #
54
+ # In general prefer `#is`.
55
+ def one_of_exactly(thing, *others)
56
+ things = ([thing] + others).to_set
57
+ nillish = things.include?(nil)
58
+ raise ReSorcery::Error::ArgumentError, "Do not use `nil`" if nillish
59
+
60
+ msg = lambda {
61
+ prefix = things.count == 1 ? "Expected exactly" : "Expected one of exactly"
62
+ "#{prefix} (#{things.map(&:inspect).join(' | ')}) but received"
63
+ }
64
+
65
+ Decoder.new { |u| things.include?(u) || "#{msg.call}: #{u.inspect}" }
66
+ end
67
+
23
68
  # Test if an object is a thing (or one of a list of things)
24
69
  #
25
70
  # Convenience method for creating common types of `Decoder`s.
@@ -44,7 +89,11 @@ module ReSorcery
44
89
  # @return [Decoder]
45
90
  def is(thing, *others)
46
91
  things = [thing] + others
47
- decoders = things.map { |t| make_decoder_from(t) }
92
+ groups = things.group_by { |t| [t.is_a?(Decoder), t.is_a?(Module)] }
93
+ decoders =
94
+ groups.fetch([true, false], []) +
95
+ (groups[[false, true]].nil? ? [] : [mod(*groups[[false, true]])]) +
96
+ (groups[[false, false]].nil? ? [] : [one_of_exactly(*groups[[false, false]])])
48
97
 
49
98
  Decoder.new do |instance|
50
99
  test_multiple(decoders, instance).map_error do |errors|
@@ -73,6 +122,19 @@ module ReSorcery
73
122
  end
74
123
  end
75
124
 
125
+ # Like #array, but test the array contains at least one item
126
+ #
127
+ # @param thing @see `is` for details
128
+ # @param others @see `is` for details
129
+ # @return [Decoder]
130
+ def non_empty_array(thing, *others)
131
+ array(thing, *others).and_then do |a|
132
+ Decoder.new do
133
+ a.empty? ? "Expected a non-empty array, but received an empty array" : ok(a)
134
+ end
135
+ end
136
+ end
137
+
76
138
  # Test that an object is a Maybe whose `value` passes some `Decoder`
77
139
  #
78
140
  # @param thing @see `is` for details
@@ -42,6 +42,7 @@ module ReSorcery
42
42
 
43
43
  def initialize(&block)
44
44
  @block = block
45
+ freeze
45
46
  end
46
47
 
47
48
  # Use the decoder to `test` that an `unknown` object satisfies some property
@@ -51,15 +52,15 @@ module ReSorcery
51
52
  # @param [unknown] unknown
52
53
  # @return [Result]
53
54
  def test(unknown)
54
- result = @block.call(unknown)
55
- case result
55
+ block_result = @block.call(unknown)
56
+ case block_result
56
57
  when Result::Ok, Result::Err
57
- result
58
+ block_result
58
59
  when TrueClass
59
60
  ok(unknown)
60
61
  else
61
- err(result)
62
- end.and_then { |r| r.nil? ? err("`nil` was returned on a successful test!") : ok(r) }
62
+ err(block_result)
63
+ end
63
64
  end
64
65
 
65
66
  # Apply some block within the context of a successful decoder
@@ -77,6 +78,14 @@ module ReSorcery
77
78
  # The second decoder can be chosen based on the (successful) result of the
78
79
  # first decoder.
79
80
  #
81
+ # Note: the second decoder decodes the "original" unknown value, not the
82
+ # potentially-changed result of the first decoder.
83
+ #
84
+ # Decoder.new { |u| u.is_a?(Symbol) || "Not symbol" }
85
+ # .map(&:to_s)
86
+ # .and_then { |v| Decoder.new { |u| true } } # v is a String & u is a Symbol
87
+ # .test(:a_symbol)
88
+ #
80
89
  # The block must return a `Decoder`.
81
90
  def and_then(decoder = nil, &block)
82
91
  ArgCheck['decoder', decoder, Decoder] unless decoder.nil?
@@ -89,6 +98,24 @@ module ReSorcery
89
98
  end
90
99
  end
91
100
 
101
+ # Chain decoders and maintain any transformed value
102
+ #
103
+ # pos = is(String, Symbol)
104
+ # .map(&:to_sym)
105
+ # .and { |s, u| [:a, :b, :c].include?(s) || "Invalid option: #{u.inspect}" }
106
+ #
107
+ # pos.test(:a) == ok(:a)
108
+ # pos.test("a") == ok(:a)
109
+ # pos.test("d") == err('Invalid option: "d"')
110
+ #
111
+ def and
112
+ and_then do |value|
113
+ Decoder.new do |unknown|
114
+ Decoder.new { yield(value, unknown) }.test(value)
115
+ end
116
+ end
117
+ end
118
+
92
119
  # If the `Decoder` failed, try another `Decoder`
93
120
  #
94
121
  # The block must return a `Decoder`.
@@ -97,18 +124,11 @@ module ReSorcery
97
124
 
98
125
  Decoder.new do |unknown|
99
126
  test(unknown).or_else do |value|
100
- decoder ||= ArgCheck['block.call(value)', block.call(value), Decoder]
101
-
102
- decoder.test(unknown)
127
+ (decoder || ArgCheck['block.call(value)', block.call(value), Decoder]).test(unknown)
103
128
  end
104
129
  end
105
130
  end
106
131
 
107
- # Chain decoders like `and_then`, but always with a specific decoder
108
- def and(&block)
109
- and_then { Decoder.new(&block) }
110
- end
111
-
112
132
  # Chain decoders like and_then, but use the chain to build an object
113
133
  def assign(key, other)
114
134
  ArgCheck['key', key, Symbol]
@@ -1,5 +1,8 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require "uri"
4
+ require "addressable/uri"
5
+
3
6
  module ReSorcery
4
7
  module Fielded
5
8
  module ExpandInternalFields
@@ -23,7 +26,7 @@ module ReSorcery
23
26
  ok(obj)
24
27
  when Array
25
28
  expand_for_array(obj)
26
- when URI
29
+ when URI, Addressable::URI
27
30
  ok(obj.to_s)
28
31
  when Hash
29
32
  err("`Hash` cannot be safely expanded as a `field`. Use a `Fielded` class instead.")
@@ -26,6 +26,10 @@ module ReSorcery
26
26
 
27
27
  (@fields ||= {})[name] = { type: is(type), pro: pro }
28
28
  end
29
+
30
+ def fields
31
+ (superclass&.include?(Fielded) ? superclass.send(:fields) : {}).merge(@fields || {})
32
+ end
29
33
  end
30
34
 
31
35
  def self.included(base)
@@ -39,11 +43,10 @@ module ReSorcery
39
43
  #
40
44
  # @return [Result<String, Hash>]
41
45
  def fields
42
- self.class.instance_exec { @fields ||= [] }.inject(ok({})) do |result_hash, (name, field_hash)|
43
- result_hash.and_then do |ok_hash|
46
+ self.class.send(:fields).inject(ok({})) do |result_hash, (name, field_hash)|
47
+ result_hash.assign(name) do
44
48
  field_hash[:type].test(instance_exec(&field_hash[:pro]))
45
49
  .and_then { |tested| ExpandInternalFields.expand(tested) }
46
- .map { |fielded| ok_hash.merge(name => fielded) }
47
50
  .map_error { |error| "Error at field `#{name}` of `#{self.class}`: #{error}" }
48
51
  end
49
52
  end
@@ -1,60 +1,72 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require "uri"
4
+ require "addressable/uri"
5
+
3
6
  module ReSorcery
4
7
  module Linked
5
8
  class LinkClassFactory
6
- extend Decoder::BuiltinDecoders
7
-
8
- def self.valid_rels
9
- ReSorcery.configuration.fetch(
10
- :link_rels,
11
- %w[
12
- self
13
- create
14
- update
15
- destroy
16
- ],
17
- )
18
- end
9
+ class << self
10
+ include Decoder::BuiltinDecoders
19
11
 
20
- def self.valid_methods
21
- ReSorcery.configuration.fetch(
22
- :link_methods,
23
- %w[
24
- get
25
- post
26
- patch
27
- put
28
- delete
29
- ],
30
- )
31
- end
12
+ def make_link_class
13
+ fields = build_fields
32
14
 
33
- URI_ABLE = is(String, URI).and do |s|
34
- next true if s.is_a?(URI)
15
+ Class.new do
16
+ include Fielded
35
17
 
36
- begin
37
- ok(URI.parse(s))
38
- rescue URI::InvalidURIError
39
- err("Not a valid URI: #{s}")
18
+ def initialize(args)
19
+ @args = args
20
+ end
21
+
22
+ fields.each { |(name, decoder, value)| field name, decoder, value }
23
+ end
40
24
  end
41
- end
42
25
 
43
- def self.make_link_class
44
- default_method = valid_methods.first
45
- this = self
26
+ private
27
+
28
+ def valid_rels
29
+ ReSorcery.configuration.fetch(:link_rels)
30
+ end
46
31
 
47
- Class.new do
48
- include Fielded
32
+ def valid_methods
33
+ ReSorcery.configuration.fetch(:link_methods)
34
+ end
49
35
 
50
- def initialize(args)
51
- @args = args
36
+ def uri_able
37
+ is(URI, Addressable::URI).or_else do
38
+ is(String).and_then do
39
+ Decoder.new do |u|
40
+ ok(Addressable::URI.parse(u))
41
+ rescue Addressable::URI::InvalidURIError
42
+ err("Not a valid URI: #{u}")
43
+ end
44
+ end
52
45
  end
46
+ end
47
+
48
+ def str_or_sym
49
+ is(String, Symbol).map(&:to_s)
50
+ end
51
+
52
+ def rel_decoder
53
+ str_or_sym.and_then { |v| Decoder.new { is(*valid_rels).test(v) } }
54
+ end
55
+
56
+ def method_decoder
57
+ str_or_sym.and_then { |v| Decoder.new { is(*valid_methods).test(v) } }
58
+ end
59
+
60
+ def build_fields
61
+ default_method = ReSorcery.configuration.fetch(:default_link_method).call(valid_methods)
62
+ default_type = ReSorcery.configuration.fetch(:default_link_type)
53
63
 
54
- field :rel, is(*this.valid_rels), -> { @args[:rel] }
55
- field :href, URI_ABLE, -> { @args[:href] }
56
- field :method, is(*this.valid_methods), -> { @args.fetch(:method, default_method) }
57
- field :type, String, -> { @args.fetch(:type, 'application/json') }
64
+ [
65
+ [:rel, rel_decoder, -> { @args[:rel] }],
66
+ [:href, uri_able, -> { @args[:href] }],
67
+ [:method, method_decoder, -> { @args.fetch(:method, default_method) }],
68
+ [:type, String, -> { @args.fetch(:type, default_type) }],
69
+ ]
58
70
  end
59
71
  end
60
72
  end
@@ -65,9 +65,10 @@ module ReSorcery
65
65
  # Define a `Link` for an object
66
66
  #
67
67
  # @see `ReSorcery::Linked::Link#initialize` for param types
68
- def link(rel, href, method = 'get', type = 'application/json')
68
+ def link(rel, href, method = nil, type = nil)
69
69
  klass = Linked.link_class
70
- (@_created_links ||= []) << klass.new(rel: rel, href: href, method: method, type: type).fields
70
+ args = {rel:, href:, method:, type:}.compact
71
+ (@_created_links ||= []) << klass.new(**args).fields
71
72
  end
72
73
  end
73
74
  end
@@ -3,6 +3,14 @@
3
3
  module ReSorcery
4
4
  module Result
5
5
  class Ok
6
+ class << self
7
+ def new(value)
8
+ return Result::Err.new("`nil` was provided as a successful result value!") if value.nil?
9
+
10
+ super
11
+ end
12
+ end
13
+
6
14
  def initialize(value)
7
15
  @value = value
8
16
  end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module ReSorcery
4
- VERSION = "0.1.0"
4
+ VERSION = "0.3.0"
5
5
  end
data/re_sorcery.gemspec CHANGED
@@ -14,21 +14,26 @@ Gem::Specification.new do |spec|
14
14
 
15
15
  # spec.metadata["allowed_push_host"] = "TODO: Set to 'http://mygemserver.com'"
16
16
 
17
+ spec.required_ruby_version = '~> 3.1'
18
+
17
19
  spec.metadata["homepage_uri"] = spec.homepage
18
- # spec.metadata["source_code_uri"] = "TODO: Put your gem's public repo URL here."
20
+ spec.metadata["source_code_uri"] = "https://github.com/spejamchr/re_sorcery"
19
21
  # spec.metadata["changelog_uri"] = "TODO: Put your gem's CHANGELOG.md URL here."
22
+ spec.metadata['rubygems_mfa_required'] = 'true'
20
23
 
21
24
  # Specify which files should be added to the gem when it is released.
22
25
  # The `git ls-files -z` loads the files in the RubyGem that have been added into git.
23
- spec.files = Dir.chdir(File.expand_path(__dir__)) do
26
+ spec.files = Dir.chdir(File.expand_path(__dir__)) do
24
27
  `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
25
28
  end
26
29
  spec.bindir = "exe"
27
30
  spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
28
31
  spec.require_paths = ["lib"]
29
32
 
30
- spec.add_development_dependency "bundler", "~> 2.0"
31
- spec.add_development_dependency "minitest", "~> 5.0"
33
+ spec.add_runtime_dependency "addressable", "~> 2.8", ">= 2.8.1"
34
+
35
+ spec.add_development_dependency "bundler", "~> 2.3"
36
+ spec.add_development_dependency "minitest", "~> 5.16"
32
37
  spec.add_development_dependency "pry"
33
- spec.add_development_dependency "rake", "~> 10.0"
38
+ spec.add_development_dependency "rake", "~> 13.0"
34
39
  end
metadata CHANGED
@@ -1,43 +1,63 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: re_sorcery
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0
4
+ version: 0.3.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Spencer Christiansen
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2021-12-21 00:00:00.000000000 Z
11
+ date: 2023-03-25 00:00:00.000000000 Z
12
12
  dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: addressable
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '2.8'
20
+ - - ">="
21
+ - !ruby/object:Gem::Version
22
+ version: 2.8.1
23
+ type: :runtime
24
+ prerelease: false
25
+ version_requirements: !ruby/object:Gem::Requirement
26
+ requirements:
27
+ - - "~>"
28
+ - !ruby/object:Gem::Version
29
+ version: '2.8'
30
+ - - ">="
31
+ - !ruby/object:Gem::Version
32
+ version: 2.8.1
13
33
  - !ruby/object:Gem::Dependency
14
34
  name: bundler
15
35
  requirement: !ruby/object:Gem::Requirement
16
36
  requirements:
17
37
  - - "~>"
18
38
  - !ruby/object:Gem::Version
19
- version: '2.0'
39
+ version: '2.3'
20
40
  type: :development
21
41
  prerelease: false
22
42
  version_requirements: !ruby/object:Gem::Requirement
23
43
  requirements:
24
44
  - - "~>"
25
45
  - !ruby/object:Gem::Version
26
- version: '2.0'
46
+ version: '2.3'
27
47
  - !ruby/object:Gem::Dependency
28
48
  name: minitest
29
49
  requirement: !ruby/object:Gem::Requirement
30
50
  requirements:
31
51
  - - "~>"
32
52
  - !ruby/object:Gem::Version
33
- version: '5.0'
53
+ version: '5.16'
34
54
  type: :development
35
55
  prerelease: false
36
56
  version_requirements: !ruby/object:Gem::Requirement
37
57
  requirements:
38
58
  - - "~>"
39
59
  - !ruby/object:Gem::Version
40
- version: '5.0'
60
+ version: '5.16'
41
61
  - !ruby/object:Gem::Dependency
42
62
  name: pry
43
63
  requirement: !ruby/object:Gem::Requirement
@@ -58,14 +78,14 @@ dependencies:
58
78
  requirements:
59
79
  - - "~>"
60
80
  - !ruby/object:Gem::Version
61
- version: '10.0'
81
+ version: '13.0'
62
82
  type: :development
63
83
  prerelease: false
64
84
  version_requirements: !ruby/object:Gem::Requirement
65
85
  requirements:
66
86
  - - "~>"
67
87
  - !ruby/object:Gem::Version
68
- version: '10.0'
88
+ version: '13.0'
69
89
  description:
70
90
  email:
71
91
  - jc.spencer92@gmail.com
@@ -106,22 +126,24 @@ licenses:
106
126
  - MIT
107
127
  metadata:
108
128
  homepage_uri: https://github.com/spejamchr/re_sorcery
129
+ source_code_uri: https://github.com/spejamchr/re_sorcery
130
+ rubygems_mfa_required: 'true'
109
131
  post_install_message:
110
132
  rdoc_options: []
111
133
  require_paths:
112
134
  - lib
113
135
  required_ruby_version: !ruby/object:Gem::Requirement
114
136
  requirements:
115
- - - ">="
137
+ - - "~>"
116
138
  - !ruby/object:Gem::Version
117
- version: '0'
139
+ version: '3.1'
118
140
  required_rubygems_version: !ruby/object:Gem::Requirement
119
141
  requirements:
120
142
  - - ">="
121
143
  - !ruby/object:Gem::Version
122
144
  version: '0'
123
145
  requirements: []
124
- rubygems_version: 3.0.3.1
146
+ rubygems_version: 3.3.7
125
147
  signing_key:
126
148
  specification_version: 4
127
149
  summary: Create resources with run-time payload type checking and link validation