dryer_routes 0.0.1
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 +7 -0
- data/Gemfile +2 -0
- data/LICENSE +18 -0
- data/README.md +156 -0
- data/dryer_routes.gemspec +29 -0
- data/lib/dryer/routes/build_from_resource.rb +27 -0
- data/lib/dryer/routes/hash_object.rb +18 -0
- data/lib/dryer/routes/registries/create.rb +11 -0
- data/lib/dryer/routes/registry.rb +103 -0
- data/lib/dryer/routes/resource_schema.rb +50 -0
- data/lib/dryer/routes/route.rb +45 -0
- data/lib/dryer/routes/simple_service.rb +13 -0
- data/lib/dryer/routes/version.rb +9 -0
- data/lib/dryer_routes.rb +1 -0
- metadata +113 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: a0daf5be57e9f83be3336908b4c91e317c379125dfe7ebf169d871069cbbc191
|
4
|
+
data.tar.gz: d7993a1caac99edfd196e4bfa9ed46b3e0c3f790d78e57759b4645939d6b07f2
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 01035ae9c9ac7ddd871d4f255222af12ffcda7f6b8559669ab33ef442110afdff4683ff722507c43606c57047170500fc8e8410279a8e984a0afd091b2db977f
|
7
|
+
data.tar.gz: 8629dc965328f7e627e8436e34cb4b20ef7ac00b291eed061d9959c43ec3df07a6d366b2f360bc615c4b9e33b8369ff1fa49e74f4363c984f4b686ba520bd6ca
|
data/Gemfile
ADDED
data/LICENSE
ADDED
@@ -0,0 +1,18 @@
|
|
1
|
+
MIT License
|
2
|
+
Copyright (c) 2023 John Bernier
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
4
|
+
a copy of this software and associated documentation files (the
|
5
|
+
"Software"), to deal in the Software without restriction, including
|
6
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
7
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
8
|
+
permit persons to whom the Software is furnished to do so, subject to
|
9
|
+
the following conditions:
|
10
|
+
The above copyright notice and this permission notice shall be
|
11
|
+
included in all copies or substantial portions of the Software.
|
12
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
13
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
14
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
15
|
+
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
16
|
+
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
17
|
+
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
18
|
+
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,156 @@
|
|
1
|
+
# Dryer Routes
|
2
|
+
Dryer Routes is a gem allows for request and response types to be added to a
|
3
|
+
Rails routes file via [dry-validation](https://dry-rb.org/gems/dry-validation/1.8/) contracts
|
4
|
+
|
5
|
+
## Installation
|
6
|
+
add the following to you gemfile
|
7
|
+
```
|
8
|
+
gem "dryer_routes"
|
9
|
+
```
|
10
|
+
|
11
|
+
## Usage
|
12
|
+
Add this code to `config/initializers/dry_routes.rb`
|
13
|
+
```
|
14
|
+
RouteRegistry = Dryer::Routes::Registry.new
|
15
|
+
```
|
16
|
+
|
17
|
+
And then in `config/routes.rb` you can register your app's routes, eg.
|
18
|
+
```
|
19
|
+
Rails.application.routes.draw do
|
20
|
+
RouteRegistry.register(
|
21
|
+
{
|
22
|
+
controller: UsersController,
|
23
|
+
url: "/users",
|
24
|
+
actions: {
|
25
|
+
create: {
|
26
|
+
method: :post,
|
27
|
+
request_contract: Contracts::Users::Post::Request,
|
28
|
+
response_contracts: {
|
29
|
+
200 => Contracts::Users::Post::Response,
|
30
|
+
}
|
31
|
+
}
|
32
|
+
}
|
33
|
+
},
|
34
|
+
{
|
35
|
+
controller: SessionsController,
|
36
|
+
url: "/sessions",
|
37
|
+
actions: {
|
38
|
+
create: {
|
39
|
+
method: :post,
|
40
|
+
request_contract: Contracts::Sessions::Post::Request,
|
41
|
+
response_contracts: {
|
42
|
+
200 => Contracts::Sessions::Post::Response,
|
43
|
+
}
|
44
|
+
}
|
45
|
+
}
|
46
|
+
}
|
47
|
+
)
|
48
|
+
RouteRegistry.to_rails_routes(self)
|
49
|
+
end
|
50
|
+
```
|
51
|
+
|
52
|
+
## Features
|
53
|
+
This gem helps organize and enforce typing for your routes, all relevant data
|
54
|
+
can be accessed through the gem keeping your code *dry*
|
55
|
+
|
56
|
+
### Easy to find route metadata
|
57
|
+
request contracts: `RouteRegistry.users.create.request_contract`
|
58
|
+
|
59
|
+
route url: `RouteRegistry.users.create.url`
|
60
|
+
|
61
|
+
response contracts: `RouteRegistry.users.create.response_contracts._200`
|
62
|
+
|
63
|
+
### Generating types in controller tests
|
64
|
+
```
|
65
|
+
class UsersControllerIntegreationTest < ActionDispatch::IntegrationTest
|
66
|
+
test "POST 200 - successfully creating a user" do
|
67
|
+
request = Dryer::Factories::BuildFromContract.call(
|
68
|
+
RouteRegistry.users.create.request_contract
|
69
|
+
)
|
70
|
+
post RouteRegistry.users.create.url, params: request.as_json
|
71
|
+
|
72
|
+
assert_response :success
|
73
|
+
|
74
|
+
assert_empty RouteRegistry.users.create.response_contracts._200.new.call(
|
75
|
+
JSON.parse(response.body)
|
76
|
+
).errors
|
77
|
+
end
|
78
|
+
end
|
79
|
+
```
|
80
|
+
Shameless plug for my other gem [dryer_factories](https://github.com/jbernie2/dryer-factories)
|
81
|
+
|
82
|
+
### Enforcing types in Controllers
|
83
|
+
By adding an `around_action` to `ApplicationController`, a controller's requests
|
84
|
+
and responses can be validated automatically eg:
|
85
|
+
```
|
86
|
+
class ApplicationController < ActionController::Base
|
87
|
+
include Dry::Monads[:result]
|
88
|
+
|
89
|
+
around_action :validate_request_and_response
|
90
|
+
|
91
|
+
def validate_request
|
92
|
+
request_errors = RouteRegistry.validate_request(request)
|
93
|
+
if request_errors.empty?
|
94
|
+
@validated_request_body = Dry::Monads::Success(request.params)
|
95
|
+
else
|
96
|
+
@validated_request_body = Dry::Monads::Failure(request_errors)
|
97
|
+
end
|
98
|
+
end
|
99
|
+
attr_reader :validated_request_body
|
100
|
+
|
101
|
+
def validate_response
|
102
|
+
response_errors = RouteRegistry.validate_response(
|
103
|
+
controller: request.controller_class,
|
104
|
+
method: request.request_method_symbol,
|
105
|
+
status: response.status,
|
106
|
+
body: JSON.parse(response.body)
|
107
|
+
)
|
108
|
+
if !response_errors.empty?
|
109
|
+
Rails.logger.error("
|
110
|
+
#{request.controller_class}##{request.request_method_symbol}
|
111
|
+
response errors: #{response_errors}
|
112
|
+
")
|
113
|
+
end
|
114
|
+
response
|
115
|
+
end
|
116
|
+
|
117
|
+
def validate_request_and_response
|
118
|
+
validate_request
|
119
|
+
if validated_request_body.success?
|
120
|
+
yield
|
121
|
+
validate_response
|
122
|
+
else
|
123
|
+
render json: {errors: validated_request_body.failure.to_h}, status: :bad_request
|
124
|
+
end
|
125
|
+
end
|
126
|
+
end
|
127
|
+
```
|
128
|
+
|
129
|
+
Allowing the controller to look like
|
130
|
+
```
|
131
|
+
class UsersController < ApplicationController
|
132
|
+
def create
|
133
|
+
validated_request_body.bind do |body|
|
134
|
+
# Do stuff
|
135
|
+
end
|
136
|
+
end
|
137
|
+
end
|
138
|
+
```
|
139
|
+
|
140
|
+
## Development
|
141
|
+
This gem is set up to be developed using [Nix](https://nixos.org/)
|
142
|
+
Once you have nix installed you can run
|
143
|
+
`make bundle`
|
144
|
+
to install all dependencies and
|
145
|
+
`make dev-shell`
|
146
|
+
to enter the development environment.
|
147
|
+
|
148
|
+
## Contributing
|
149
|
+
Please create a github issue to report any problems using the Gem.
|
150
|
+
Thanks for your help in making testing easier for everyone!
|
151
|
+
|
152
|
+
## Versioning
|
153
|
+
Dryer Routes follows Semantic Versioning 2.0 as defined at https://semver.org.
|
154
|
+
|
155
|
+
## License
|
156
|
+
This code is free to use under the terms of the MIT license.
|
@@ -0,0 +1,29 @@
|
|
1
|
+
Gem::Specification.new do |spec|
|
2
|
+
spec.name = 'dryer_routes'
|
3
|
+
spec.version = "0.0.1"
|
4
|
+
spec.authors = ['John Bernier']
|
5
|
+
spec.email = ['john.b.bernier@gmail.com']
|
6
|
+
spec.summary = 'Typed routing for rails leveraging dry-validation contracts'
|
7
|
+
spec.description = <<~DOC
|
8
|
+
An extension of the Dry family of gems (dry-rb.org).
|
9
|
+
This gem allows for rails routes to specify contracts for requests
|
10
|
+
and responses
|
11
|
+
DOC
|
12
|
+
spec.homepage = 'https://github.com/jbernie2/dryer-routes'
|
13
|
+
spec.license = 'MIT'
|
14
|
+
spec.platform = Gem::Platform::RUBY
|
15
|
+
spec.required_ruby_version = '>= 3.0.0'
|
16
|
+
spec.files = Dir[
|
17
|
+
'README.md',
|
18
|
+
'LICENSE',
|
19
|
+
'CHANGELOG.md',
|
20
|
+
'lib/**/*.rb',
|
21
|
+
'dryer_routes.gemspec',
|
22
|
+
'.github/*.md',
|
23
|
+
'Gemfile'
|
24
|
+
]
|
25
|
+
spec.add_dependency "dry-validation", "~> 1.10"
|
26
|
+
spec.add_dependency "dry-types", "~> 1.7"
|
27
|
+
spec.add_development_dependency "rspec", "~> 3.10"
|
28
|
+
spec.add_development_dependency "debug", "~> 1.8"
|
29
|
+
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
require_relative "./simple_service"
|
2
|
+
require_relative "./route"
|
3
|
+
|
4
|
+
module Dryer
|
5
|
+
module Routes
|
6
|
+
class BuildFromResource < SimpleService
|
7
|
+
def initialize(resource)
|
8
|
+
@resource = resource
|
9
|
+
end
|
10
|
+
|
11
|
+
def call
|
12
|
+
resource[:actions].map do |action, config|
|
13
|
+
Route.new(
|
14
|
+
controller: resource[:controller],
|
15
|
+
url: config[:url] || resource[:url],
|
16
|
+
method: config[:method],
|
17
|
+
controller_action: action,
|
18
|
+
request_contract: config[:request_contract],
|
19
|
+
response_contracts: config[:response_contracts]
|
20
|
+
)
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
attr_reader :resource
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
module Dryer
|
2
|
+
module Routes
|
3
|
+
class HashObject
|
4
|
+
def initialize(hash)
|
5
|
+
hash.each do |k,v|
|
6
|
+
key = k.is_a?(Numeric) ? "_#{k}" : k
|
7
|
+
|
8
|
+
self.instance_variable_set(
|
9
|
+
"@#{key}", v.is_a?(Hash) ? HashObject.new(v) : v
|
10
|
+
)
|
11
|
+
self.class.send(
|
12
|
+
:define_method, key, proc{self.instance_variable_get("@#{key}")}
|
13
|
+
)
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
@@ -0,0 +1,103 @@
|
|
1
|
+
require_relative "./build_from_resource.rb"
|
2
|
+
require_relative "./hash_object.rb"
|
3
|
+
require_relative "./resource_schema.rb"
|
4
|
+
|
5
|
+
module Dryer
|
6
|
+
module Routes
|
7
|
+
class Registry
|
8
|
+
|
9
|
+
def initialize
|
10
|
+
@resources = []
|
11
|
+
@routes = []
|
12
|
+
end
|
13
|
+
|
14
|
+
def register(*resources)
|
15
|
+
validate_resources!(resources)
|
16
|
+
@resources = resources
|
17
|
+
@routes = resources.map do |r|
|
18
|
+
BuildFromResource.call(r)
|
19
|
+
end.flatten
|
20
|
+
add_accessors_for_resources(resources)
|
21
|
+
@routes
|
22
|
+
end
|
23
|
+
|
24
|
+
def to_rails_routes(router)
|
25
|
+
@routes.map { |r| r.to_rails_route(router) }
|
26
|
+
end
|
27
|
+
|
28
|
+
def validate_request(request)
|
29
|
+
route_for(
|
30
|
+
controller: request.controller_class,
|
31
|
+
method: request.request_method_symbol
|
32
|
+
).then do |route|
|
33
|
+
if route && route.request_contract
|
34
|
+
route.request_contract.new.call(request.params).errors
|
35
|
+
else
|
36
|
+
[]
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
def validate_response(controller:, method:, status:, body:)
|
42
|
+
route_for(
|
43
|
+
controller: controller.class,
|
44
|
+
method: method.to_sym
|
45
|
+
).then do |route|
|
46
|
+
if route && route.response_contract_for(status)
|
47
|
+
route.response_contract_for(status).new.call(body).errors
|
48
|
+
else
|
49
|
+
[]
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
def route_for(controller:, method:)
|
55
|
+
@routes.filter do |r|
|
56
|
+
r.controller == controller
|
57
|
+
r.method == method
|
58
|
+
end.first
|
59
|
+
end
|
60
|
+
|
61
|
+
attr_reader :routes, :resources
|
62
|
+
|
63
|
+
private
|
64
|
+
attr_writer :routes, :resources
|
65
|
+
|
66
|
+
def add_accessors_for_resources(resources)
|
67
|
+
denormalize_resources(resources).inject(self) do |obj, (key, value)|
|
68
|
+
obj.define_singleton_method(key) { HashObject.new(value) }
|
69
|
+
obj
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
73
|
+
def denormalize_resources(resources)
|
74
|
+
resources.inject({}) do | h, resource |
|
75
|
+
h[
|
76
|
+
resource[:controller].controller_name.to_sym
|
77
|
+
] = denormalize_resource(resource)
|
78
|
+
h
|
79
|
+
end
|
80
|
+
end
|
81
|
+
|
82
|
+
def denormalize_resource(resource)
|
83
|
+
resource[:actions].each do |key, value|
|
84
|
+
resource[:actions][key][:url] =
|
85
|
+
resource[:actions][key][:url] || resource[:url]
|
86
|
+
end
|
87
|
+
resource.merge(resource[:actions])
|
88
|
+
end
|
89
|
+
|
90
|
+
def validate_resources!(resources)
|
91
|
+
errors = resources.map do |r|
|
92
|
+
ResourceSchema.new.call(r)
|
93
|
+
end.select { |r| !r.errors.empty? }
|
94
|
+
if !errors.empty?
|
95
|
+
messages = errors.inject({}) do |messages, e|
|
96
|
+
messages.merge(e.errors.to_h)
|
97
|
+
end
|
98
|
+
raise "Invalid arguments: #{messages}"
|
99
|
+
end
|
100
|
+
end
|
101
|
+
end
|
102
|
+
end
|
103
|
+
end
|
@@ -0,0 +1,50 @@
|
|
1
|
+
require 'dry-validation'
|
2
|
+
|
3
|
+
module Dryer
|
4
|
+
module Routes
|
5
|
+
class ResourceSchema < Dry::Validation::Contract
|
6
|
+
params do
|
7
|
+
required(:controller).filled(:class)
|
8
|
+
required(:url).filled(:string)
|
9
|
+
required(:actions).filled(:hash)
|
10
|
+
end
|
11
|
+
|
12
|
+
class ActionSchema < Dry::Validation::Contract
|
13
|
+
params do
|
14
|
+
required(:method).filled(:symbol)
|
15
|
+
optional(:request_contract)
|
16
|
+
optional(:response_contracts).hash()
|
17
|
+
end
|
18
|
+
|
19
|
+
rule(:request_contract) do
|
20
|
+
if value && !value.ancestors.include?(Dry::Validation::Contract)
|
21
|
+
key.failure('must be a dry-validation contract')
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
rule(:response_contracts) do
|
26
|
+
values[:response_contracts].each do |key, value|
|
27
|
+
if !value.ancestors.include?(Dry::Validation::Contract)
|
28
|
+
key(:response_contracts).failure(
|
29
|
+
'must be a dry-validation contract'
|
30
|
+
)
|
31
|
+
end
|
32
|
+
end if values[:response_contracts]
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
rule(:actions) do
|
37
|
+
values[:actions].each do |key, value|
|
38
|
+
res = ActionSchema.new.call(value)
|
39
|
+
if !res.success?
|
40
|
+
res.errors.to_h.each do |name, messages|
|
41
|
+
messages.each do |msg|
|
42
|
+
key([key_name, name]).failure(msg)
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
@@ -0,0 +1,45 @@
|
|
1
|
+
module Dryer
|
2
|
+
module Routes
|
3
|
+
class Route
|
4
|
+
def initialize(route_config)
|
5
|
+
@route_config = route_config
|
6
|
+
end
|
7
|
+
|
8
|
+
def to_rails_route(router)
|
9
|
+
router.send(
|
10
|
+
route_config[:method],
|
11
|
+
route_config[:url],
|
12
|
+
to: "#{
|
13
|
+
route_config[:controller].controller_path
|
14
|
+
}##{
|
15
|
+
route_config[:controller_action]
|
16
|
+
}"
|
17
|
+
)
|
18
|
+
end
|
19
|
+
|
20
|
+
def controller
|
21
|
+
route_config[:controller]
|
22
|
+
end
|
23
|
+
|
24
|
+
def method
|
25
|
+
route_config[:method]
|
26
|
+
end
|
27
|
+
|
28
|
+
def request_contract
|
29
|
+
route_config[:request_contract]
|
30
|
+
end
|
31
|
+
|
32
|
+
def response_contract_for(status)
|
33
|
+
route_config[:response_contracts][status]
|
34
|
+
end
|
35
|
+
|
36
|
+
def url
|
37
|
+
route_config[:url]
|
38
|
+
end
|
39
|
+
|
40
|
+
private
|
41
|
+
attr_reader :route_config
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
data/lib/dryer_routes.rb
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
require_relative "./dryer/routes/registry.rb"
|
metadata
ADDED
@@ -0,0 +1,113 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: dryer_routes
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.1
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- John Bernier
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2023-12-01 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: dry-validation
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - "~>"
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '1.10'
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - "~>"
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '1.10'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: dry-types
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - "~>"
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '1.7'
|
34
|
+
type: :runtime
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - "~>"
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '1.7'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: rspec
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - "~>"
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '3.10'
|
48
|
+
type: :development
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - "~>"
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '3.10'
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: debug
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - "~>"
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '1.8'
|
62
|
+
type: :development
|
63
|
+
prerelease: false
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - "~>"
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: '1.8'
|
69
|
+
description: "An extension of the Dry family of gems (dry-rb.org).\nThis gem allows
|
70
|
+
for rails routes to specify contracts for requests \nand responses\n"
|
71
|
+
email:
|
72
|
+
- john.b.bernier@gmail.com
|
73
|
+
executables: []
|
74
|
+
extensions: []
|
75
|
+
extra_rdoc_files: []
|
76
|
+
files:
|
77
|
+
- Gemfile
|
78
|
+
- LICENSE
|
79
|
+
- README.md
|
80
|
+
- dryer_routes.gemspec
|
81
|
+
- lib/dryer/routes/build_from_resource.rb
|
82
|
+
- lib/dryer/routes/hash_object.rb
|
83
|
+
- lib/dryer/routes/registries/create.rb
|
84
|
+
- lib/dryer/routes/registry.rb
|
85
|
+
- lib/dryer/routes/resource_schema.rb
|
86
|
+
- lib/dryer/routes/route.rb
|
87
|
+
- lib/dryer/routes/simple_service.rb
|
88
|
+
- lib/dryer/routes/version.rb
|
89
|
+
- lib/dryer_routes.rb
|
90
|
+
homepage: https://github.com/jbernie2/dryer-routes
|
91
|
+
licenses:
|
92
|
+
- MIT
|
93
|
+
metadata: {}
|
94
|
+
post_install_message:
|
95
|
+
rdoc_options: []
|
96
|
+
require_paths:
|
97
|
+
- lib
|
98
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
99
|
+
requirements:
|
100
|
+
- - ">="
|
101
|
+
- !ruby/object:Gem::Version
|
102
|
+
version: 3.0.0
|
103
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
104
|
+
requirements:
|
105
|
+
- - ">="
|
106
|
+
- !ruby/object:Gem::Version
|
107
|
+
version: '0'
|
108
|
+
requirements: []
|
109
|
+
rubygems_version: 3.4.13
|
110
|
+
signing_key:
|
111
|
+
specification_version: 4
|
112
|
+
summary: Typed routing for rails leveraging dry-validation contracts
|
113
|
+
test_files: []
|