rails-openapi 1.0.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 +7 -0
- data/lib/rails/openapi/engine.rb +143 -0
- data/lib/rails/openapi/router.rb +214 -0
- data/lib/rails/openapi/version.rb +7 -0
- data/lib/rails/openapi.rb +6 -0
- data/sig/rails/openapi.rbs +6 -0
- metadata +149 -0
checksums.yaml
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
---
|
|
2
|
+
SHA256:
|
|
3
|
+
metadata.gz: 6012b8d66ea54b85a1856f9072bdefd89714d92a2b101798d86f9c19a4a15961
|
|
4
|
+
data.tar.gz: 0c2206e467404c49f60c7e022058fc7cf8751537339a80f4458d32ad29bbe75d
|
|
5
|
+
SHA512:
|
|
6
|
+
metadata.gz: 0ef32988bf178e4f9e37e798bc86e4ff1ccc129b41e104017f93ffcd185ee3c8ec7684430e3ffedc3c79eac07f85614662ec815cc7f118dcd9a522dd2c1e30cd
|
|
7
|
+
data.tar.gz: '087a18d21c99dba35f372f344b3226c536d656b8c4d33971761018b8e0db187574adad1c9904357ff8f68c619ae1cbf7ef4d2bdafd6e96d88ec37ed6d4546fe7'
|
|
@@ -0,0 +1,143 @@
|
|
|
1
|
+
module Rails
|
|
2
|
+
module Openapi
|
|
3
|
+
# Defines a base class from which OpenAPI engines can be created.
|
|
4
|
+
# Uses namespace isolation to ensure routes don't conflict with any
|
|
5
|
+
# pre-existing routes from the main rails application.
|
|
6
|
+
class Engine < ::Rails::Engine
|
|
7
|
+
isolate_namespace Rails::Openapi
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
# Helper method to create a new engine based on a module namespace prefix and an OpenAPI spec file
|
|
11
|
+
def self.Engine namespace:, schema:, publish_schema: true
|
|
12
|
+
# Convert the module prefix into a constant if passed in as a string
|
|
13
|
+
base_module = Object.const_get namespace if String === namespace
|
|
14
|
+
|
|
15
|
+
# Ensure the OpenAPI spec file is in an acceptable format
|
|
16
|
+
begin
|
|
17
|
+
require "yaml"
|
|
18
|
+
document = YAML.safe_load schema
|
|
19
|
+
unless document.is_a?(Hash) && document["openapi"].present?
|
|
20
|
+
raise "The schema argument could not be parsed as an OpenAPI schema"
|
|
21
|
+
end
|
|
22
|
+
unless Gem::Version.new(document["openapi"]) >= Gem::Version.new("3.0")
|
|
23
|
+
raise "The schema argument must be an OpenAPI 3.0+ schema. You passed in a schema with version #{document["openapi"]}"
|
|
24
|
+
end
|
|
25
|
+
rescue Psych::SyntaxError
|
|
26
|
+
raise $!, "Problem parsing OpenAPI schema: #{$!.message.lines.first.strip}", $@
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
# Builds a routing tree based on the OpenAPI spec file.
|
|
30
|
+
# We'll add each endpoint to the routing tree and additionally
|
|
31
|
+
# store it in an array to be used below.
|
|
32
|
+
router = Router.new
|
|
33
|
+
endpoints = []
|
|
34
|
+
document["paths"].each do |url, actions|
|
|
35
|
+
actions.each do |verb, definition|
|
|
36
|
+
next if verb == "parameters"
|
|
37
|
+
route = Endpoint.new(verb.downcase.to_sym, url, definition)
|
|
38
|
+
router << route
|
|
39
|
+
endpoints << route
|
|
40
|
+
end
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
# Creates the engine that will be used to actually route the
|
|
44
|
+
# contents of the OpenAPI spec file. The engine will eventually be
|
|
45
|
+
# attached to the base module (argument to this current method).
|
|
46
|
+
#
|
|
47
|
+
# Exposes `::router` and `::endpoints` methods to allow other parts
|
|
48
|
+
# of the code to tie requests back to their spec file definitions.
|
|
49
|
+
engine = Class.new Engine do
|
|
50
|
+
@router = router
|
|
51
|
+
@endpoints = {}
|
|
52
|
+
@schema = document.freeze
|
|
53
|
+
|
|
54
|
+
class << self
|
|
55
|
+
attr_reader :router
|
|
56
|
+
|
|
57
|
+
attr_reader :endpoints
|
|
58
|
+
|
|
59
|
+
attr_reader :schema
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
# Rack app for serving the original OpenAPI file
|
|
63
|
+
openapi_app = Class.new do
|
|
64
|
+
def inspect
|
|
65
|
+
"Rails::Openapi::Engine"
|
|
66
|
+
end
|
|
67
|
+
define_method :call do |env|
|
|
68
|
+
[
|
|
69
|
+
200,
|
|
70
|
+
{"Content-Type" => "application/json"},
|
|
71
|
+
[engine.schema.to_json]
|
|
72
|
+
]
|
|
73
|
+
end
|
|
74
|
+
end
|
|
75
|
+
|
|
76
|
+
# Adds routes to the engine by passing the Mapper to the top
|
|
77
|
+
# of the routing tree. `self` inside the block refers to an
|
|
78
|
+
# instance of `ActionDispatch::Routing::Mapper`.
|
|
79
|
+
routes.draw do
|
|
80
|
+
scope module: base_module.name.underscore, format: false do
|
|
81
|
+
get "openapi.json", to: openapi_app.new, as: :openapi_schema if publish_schema
|
|
82
|
+
router.draw self
|
|
83
|
+
end
|
|
84
|
+
end
|
|
85
|
+
end
|
|
86
|
+
|
|
87
|
+
# Assign the engine as a class on the base module
|
|
88
|
+
base_module.const_set :Engine, engine
|
|
89
|
+
|
|
90
|
+
# Creates a hash that maps routes back to their OpenAPI spec file
|
|
91
|
+
# equivalents. This is accomplished by mocking a request for each
|
|
92
|
+
# OpenAPI spec file endpoint and determining which controller and
|
|
93
|
+
# action the request is routed to. OpenAPI spec file definitions
|
|
94
|
+
# are then attached to that controller/action pair.
|
|
95
|
+
endpoints.each do |route|
|
|
96
|
+
# Mocks a request using the route's URL
|
|
97
|
+
url = ::ActionDispatch::Journey::Router::Utils.normalize_path route.path
|
|
98
|
+
env = ::Rack::MockRequest.env_for url, method: route[:method].upcase
|
|
99
|
+
req = ::ActionDispatch::Request.new env
|
|
100
|
+
|
|
101
|
+
# Maps the OpenAPI spec endpoint to the destination controller
|
|
102
|
+
# action by routing the request.
|
|
103
|
+
begin
|
|
104
|
+
mapped = engine.routes.router.recognize(req) {}.first[2].defaults
|
|
105
|
+
rescue
|
|
106
|
+
Rails.logger.error "Could not resolve the OpenAPI route for #{req.method} #{req.url}"
|
|
107
|
+
next
|
|
108
|
+
end
|
|
109
|
+
key = "#{mapped[:controller]}##{mapped[:action]}"
|
|
110
|
+
engine.endpoints[key] = route
|
|
111
|
+
end
|
|
112
|
+
engine.endpoints.freeze
|
|
113
|
+
|
|
114
|
+
# Defines a helper module on the base module that can be used to
|
|
115
|
+
# properly generate OpenAPI-aware controllers. Any controllers
|
|
116
|
+
# referenced from a OpenAPI spec file should include this module.
|
|
117
|
+
mod = Module.new do
|
|
118
|
+
@base = base_module
|
|
119
|
+
def self.included controller
|
|
120
|
+
base_module = @base
|
|
121
|
+
# Returns a reference to the Rails engine generated for this OpenAPI spec file
|
|
122
|
+
define_method :openapi_engine do
|
|
123
|
+
base_module.const_get :Engine
|
|
124
|
+
end
|
|
125
|
+
# Returns the OpenAPI schema used to generate the Rails engine as a Hash
|
|
126
|
+
define_method :openapi_schema do
|
|
127
|
+
base_module.const_get(:Engine).schema
|
|
128
|
+
end
|
|
129
|
+
# Returns the OpenAPI spec's endpoint definition for current request
|
|
130
|
+
define_method :openapi_endpoint do
|
|
131
|
+
openapi_engine.endpoints["#{request.path_parameters[:controller]}##{request.path_parameters[:action]}"]
|
|
132
|
+
end
|
|
133
|
+
# Allows the helper methods to also be used in views
|
|
134
|
+
controller.helper_method :openapi_engine, :openapi_schema, :openapi_endpoint
|
|
135
|
+
end
|
|
136
|
+
end
|
|
137
|
+
base_module.const_set :OpenapiHelper, mod
|
|
138
|
+
|
|
139
|
+
# Returns the new engine
|
|
140
|
+
base_module.const_get :Engine
|
|
141
|
+
end
|
|
142
|
+
end
|
|
143
|
+
end
|
|
@@ -0,0 +1,214 @@
|
|
|
1
|
+
module Rails
|
|
2
|
+
module Openapi
|
|
3
|
+
# Internally represents individual routes
|
|
4
|
+
Endpoint = Struct.new(:method, :url, :definition, :_path) do
|
|
5
|
+
def initialize *opts
|
|
6
|
+
super
|
|
7
|
+
self[:_path] = path
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
# Translates path params from {bracket} syntax to :symbol syntax
|
|
11
|
+
def path
|
|
12
|
+
self[:url].gsub(/\{([^}]+)\}/, ':\\1')
|
|
13
|
+
end
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
# Defines RESTful routing conventions
|
|
17
|
+
RESOURCE_ROUTES = {
|
|
18
|
+
get: :index,
|
|
19
|
+
post: :create,
|
|
20
|
+
put: :update,
|
|
21
|
+
patch: :update,
|
|
22
|
+
delete: :destroy
|
|
23
|
+
}.freeze
|
|
24
|
+
PARAM_ROUTES = {
|
|
25
|
+
get: :show,
|
|
26
|
+
post: :update,
|
|
27
|
+
patch: :update,
|
|
28
|
+
put: :update,
|
|
29
|
+
delete: :destroy
|
|
30
|
+
}.freeze
|
|
31
|
+
|
|
32
|
+
class Router
|
|
33
|
+
attr_accessor :endpoints
|
|
34
|
+
|
|
35
|
+
def initialize prefix = [], parent = nil
|
|
36
|
+
@parent = parent
|
|
37
|
+
@prefix = prefix.freeze
|
|
38
|
+
@endpoints = []
|
|
39
|
+
@subroutes = Hash.new do |hash, k|
|
|
40
|
+
hash[k] = Router.new(@prefix + [k], self)
|
|
41
|
+
end
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
# Adds an individual endpoint to the routing tree
|
|
45
|
+
def << route
|
|
46
|
+
raise "Argument must be an Endpoint" unless Endpoint === route
|
|
47
|
+
_base, *subroute = route[:_path].split "/" # Split out first element
|
|
48
|
+
if subroute.count == 0
|
|
49
|
+
route[:_path] = ""
|
|
50
|
+
@endpoints << route
|
|
51
|
+
else
|
|
52
|
+
route[:_path] = subroute.join "/"
|
|
53
|
+
self[subroute[0]] << route
|
|
54
|
+
end
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
# Returns a specific branch of the routing tree
|
|
58
|
+
def [] path
|
|
59
|
+
@subroutes[path]
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
# Returns the routing path
|
|
63
|
+
def path
|
|
64
|
+
"/" + @prefix.join("/")
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
# Returns the mode used for collecting routes
|
|
68
|
+
def route_mode
|
|
69
|
+
mode = :resource
|
|
70
|
+
mode = :namespace if @endpoints.count == 0
|
|
71
|
+
mode = :action if @subroutes.count == 0 && @parent && @parent.route_mode == :resource
|
|
72
|
+
mode = :param if /^:/.match?(@prefix.last)
|
|
73
|
+
mode
|
|
74
|
+
end
|
|
75
|
+
|
|
76
|
+
# Returns the mode used for actions in this router
|
|
77
|
+
def action_mode
|
|
78
|
+
if /^:/.match?(@prefix[-1])
|
|
79
|
+
:member
|
|
80
|
+
else
|
|
81
|
+
:collection
|
|
82
|
+
end
|
|
83
|
+
end
|
|
84
|
+
|
|
85
|
+
# Determines the action for a specific route
|
|
86
|
+
def action_for route
|
|
87
|
+
raise "Argument must be an Endpoint" unless Endpoint === route
|
|
88
|
+
action = @prefix[-1]&.underscore || ""
|
|
89
|
+
action = PARAM_ROUTES[route[:method]] if action_mode == :member
|
|
90
|
+
action = RESOURCE_ROUTES[route[:method]] if route_mode == :resource && action_mode == :collection
|
|
91
|
+
action
|
|
92
|
+
end
|
|
93
|
+
|
|
94
|
+
# Draws the routes for this router
|
|
95
|
+
def draw map
|
|
96
|
+
case route_mode
|
|
97
|
+
when :resource
|
|
98
|
+
|
|
99
|
+
# Find collection-level resource actions
|
|
100
|
+
actions = @endpoints.map { |r| action_for r }.select { |a| Symbol === a }
|
|
101
|
+
|
|
102
|
+
# Find parameter-level resource actions
|
|
103
|
+
@subroutes.select { |k, _| /^:/ === k }.values.each do |subroute|
|
|
104
|
+
actions += subroute.endpoints.map { |r| subroute.action_for r }.select { |a| Symbol === a }
|
|
105
|
+
end
|
|
106
|
+
|
|
107
|
+
# Determine if this is a collection or a singleton resource
|
|
108
|
+
type = @subroutes.any? { |k, _| /^:/ === k } ? :resources : :resource
|
|
109
|
+
if type == :resource && actions.include?(:index)
|
|
110
|
+
# Remap index to show for singleton resources
|
|
111
|
+
actions.delete :index
|
|
112
|
+
actions << :show
|
|
113
|
+
end
|
|
114
|
+
|
|
115
|
+
# Draw the resource
|
|
116
|
+
map.send type, @prefix.last&.to_sym || "/", controller: @prefix.last&.underscore || "main", only: actions, as: @prefix.last&.underscore || "main", format: nil do
|
|
117
|
+
# Draw custom actions
|
|
118
|
+
draw_actions! map
|
|
119
|
+
|
|
120
|
+
# Handle the edge case in which POST is used instead of PUT/PATCH
|
|
121
|
+
draw_post_updates! map
|
|
122
|
+
|
|
123
|
+
# Draw a namespace (unless at the top)
|
|
124
|
+
if @prefix.join("/").blank?
|
|
125
|
+
draw_subroutes! map
|
|
126
|
+
else
|
|
127
|
+
map.scope module: @prefix.last do
|
|
128
|
+
draw_subroutes! map
|
|
129
|
+
end
|
|
130
|
+
end
|
|
131
|
+
end
|
|
132
|
+
|
|
133
|
+
when :namespace
|
|
134
|
+
|
|
135
|
+
# Draw a namespace (unless at the top)
|
|
136
|
+
if @prefix.join("/").blank?
|
|
137
|
+
draw_subroutes! map
|
|
138
|
+
else
|
|
139
|
+
map.namespace @prefix.last do
|
|
140
|
+
draw_subroutes! map
|
|
141
|
+
end
|
|
142
|
+
end
|
|
143
|
+
|
|
144
|
+
when :param
|
|
145
|
+
|
|
146
|
+
# Draw subroutes directly
|
|
147
|
+
draw_subroutes! map
|
|
148
|
+
draw_actions! map
|
|
149
|
+
|
|
150
|
+
when :action
|
|
151
|
+
# Draw actions directly
|
|
152
|
+
draw_actions! map
|
|
153
|
+
|
|
154
|
+
end
|
|
155
|
+
end
|
|
156
|
+
|
|
157
|
+
# Returns the routing tree in text format
|
|
158
|
+
def to_s
|
|
159
|
+
output = ""
|
|
160
|
+
|
|
161
|
+
path = "/" + @prefix.join("/")
|
|
162
|
+
@endpoints.each do |route|
|
|
163
|
+
output += "#{route[:method].to_s.upcase} #{path}\n"
|
|
164
|
+
end
|
|
165
|
+
@subroutes.each do |k, subroute|
|
|
166
|
+
output += subroute.to_s
|
|
167
|
+
end
|
|
168
|
+
|
|
169
|
+
output
|
|
170
|
+
end
|
|
171
|
+
|
|
172
|
+
# Outputs a visual representation of the routing tree
|
|
173
|
+
def _debug_routing_tree
|
|
174
|
+
puts path + " - #{route_mode}"
|
|
175
|
+
@endpoints.each do |route|
|
|
176
|
+
puts "\t#{route[:method].to_s.upcase} to ##{action_for route} (#{action_mode})"
|
|
177
|
+
end
|
|
178
|
+
@subroutes.each { |k, subroute| subroute._debug_routing_tree }
|
|
179
|
+
end
|
|
180
|
+
|
|
181
|
+
protected
|
|
182
|
+
|
|
183
|
+
# Some APIs use the POST verb instead of PUT/PATCH for updating resources
|
|
184
|
+
def draw_post_updates! map
|
|
185
|
+
@subroutes.select { |k, _| /^:/ === k }.each do |param, subroute|
|
|
186
|
+
if subroute.endpoints.select { |r| r[:method] == :post }.any?
|
|
187
|
+
map.match param, via: :post, action: :update, on: :collection
|
|
188
|
+
end
|
|
189
|
+
end
|
|
190
|
+
end
|
|
191
|
+
|
|
192
|
+
def draw_actions! map
|
|
193
|
+
@endpoints.each do |route|
|
|
194
|
+
# Params hash for the route to be added
|
|
195
|
+
params = {}
|
|
196
|
+
params[:via] = route[:method]
|
|
197
|
+
params[:action] = action_for route
|
|
198
|
+
params[:on] = action_mode unless action_mode == :member
|
|
199
|
+
params[:as] = @prefix.last&.underscore
|
|
200
|
+
|
|
201
|
+
# Skip actions that are handled in the resource level
|
|
202
|
+
next if Symbol === params[:action]
|
|
203
|
+
|
|
204
|
+
# Add this individual route
|
|
205
|
+
map.match @prefix.last, params
|
|
206
|
+
end
|
|
207
|
+
end
|
|
208
|
+
|
|
209
|
+
def draw_subroutes! map
|
|
210
|
+
@subroutes.values.each { |r| r.draw map }
|
|
211
|
+
end
|
|
212
|
+
end
|
|
213
|
+
end
|
|
214
|
+
end
|
metadata
ADDED
|
@@ -0,0 +1,149 @@
|
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
|
2
|
+
name: rails-openapi
|
|
3
|
+
version: !ruby/object:Gem::Version
|
|
4
|
+
version: 1.0.0
|
|
5
|
+
platform: ruby
|
|
6
|
+
authors:
|
|
7
|
+
- Kenaniah Cerny
|
|
8
|
+
autorequire:
|
|
9
|
+
bindir: exe
|
|
10
|
+
cert_chain: []
|
|
11
|
+
date: 2022-07-29 00:00:00.000000000 Z
|
|
12
|
+
dependencies:
|
|
13
|
+
- !ruby/object:Gem::Dependency
|
|
14
|
+
name: rails
|
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
|
16
|
+
requirements:
|
|
17
|
+
- - ">="
|
|
18
|
+
- !ruby/object:Gem::Version
|
|
19
|
+
version: '6'
|
|
20
|
+
type: :runtime
|
|
21
|
+
prerelease: false
|
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
23
|
+
requirements:
|
|
24
|
+
- - ">="
|
|
25
|
+
- !ruby/object:Gem::Version
|
|
26
|
+
version: '6'
|
|
27
|
+
- !ruby/object:Gem::Dependency
|
|
28
|
+
name: bundler
|
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
|
30
|
+
requirements:
|
|
31
|
+
- - ">="
|
|
32
|
+
- !ruby/object:Gem::Version
|
|
33
|
+
version: '0'
|
|
34
|
+
type: :development
|
|
35
|
+
prerelease: false
|
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
37
|
+
requirements:
|
|
38
|
+
- - ">="
|
|
39
|
+
- !ruby/object:Gem::Version
|
|
40
|
+
version: '0'
|
|
41
|
+
- !ruby/object:Gem::Dependency
|
|
42
|
+
name: colorize
|
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
|
44
|
+
requirements:
|
|
45
|
+
- - ">="
|
|
46
|
+
- !ruby/object:Gem::Version
|
|
47
|
+
version: '0'
|
|
48
|
+
type: :development
|
|
49
|
+
prerelease: false
|
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
51
|
+
requirements:
|
|
52
|
+
- - ">="
|
|
53
|
+
- !ruby/object:Gem::Version
|
|
54
|
+
version: '0'
|
|
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.0.0
|
|
62
|
+
type: :development
|
|
63
|
+
prerelease: false
|
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
65
|
+
requirements:
|
|
66
|
+
- - ">="
|
|
67
|
+
- !ruby/object:Gem::Version
|
|
68
|
+
version: 1.0.0
|
|
69
|
+
- !ruby/object:Gem::Dependency
|
|
70
|
+
name: minitest
|
|
71
|
+
requirement: !ruby/object:Gem::Requirement
|
|
72
|
+
requirements:
|
|
73
|
+
- - ">="
|
|
74
|
+
- !ruby/object:Gem::Version
|
|
75
|
+
version: '5.0'
|
|
76
|
+
type: :development
|
|
77
|
+
prerelease: false
|
|
78
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
79
|
+
requirements:
|
|
80
|
+
- - ">="
|
|
81
|
+
- !ruby/object:Gem::Version
|
|
82
|
+
version: '5.0'
|
|
83
|
+
- !ruby/object:Gem::Dependency
|
|
84
|
+
name: rake
|
|
85
|
+
requirement: !ruby/object:Gem::Requirement
|
|
86
|
+
requirements:
|
|
87
|
+
- - ">="
|
|
88
|
+
- !ruby/object:Gem::Version
|
|
89
|
+
version: '13.0'
|
|
90
|
+
type: :development
|
|
91
|
+
prerelease: false
|
|
92
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
93
|
+
requirements:
|
|
94
|
+
- - ">="
|
|
95
|
+
- !ruby/object:Gem::Version
|
|
96
|
+
version: '13.0'
|
|
97
|
+
- !ruby/object:Gem::Dependency
|
|
98
|
+
name: standard
|
|
99
|
+
requirement: !ruby/object:Gem::Requirement
|
|
100
|
+
requirements:
|
|
101
|
+
- - "~>"
|
|
102
|
+
- !ruby/object:Gem::Version
|
|
103
|
+
version: '1.3'
|
|
104
|
+
type: :development
|
|
105
|
+
prerelease: false
|
|
106
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
107
|
+
requirements:
|
|
108
|
+
- - "~>"
|
|
109
|
+
- !ruby/object:Gem::Version
|
|
110
|
+
version: '1.3'
|
|
111
|
+
description:
|
|
112
|
+
email:
|
|
113
|
+
- kenaniah@gmail.com
|
|
114
|
+
executables: []
|
|
115
|
+
extensions: []
|
|
116
|
+
extra_rdoc_files: []
|
|
117
|
+
files:
|
|
118
|
+
- lib/rails/openapi.rb
|
|
119
|
+
- lib/rails/openapi/engine.rb
|
|
120
|
+
- lib/rails/openapi/router.rb
|
|
121
|
+
- lib/rails/openapi/version.rb
|
|
122
|
+
- sig/rails/openapi.rbs
|
|
123
|
+
homepage: https://github.com/kenaniah/rails-openapi
|
|
124
|
+
licenses:
|
|
125
|
+
- MIT
|
|
126
|
+
metadata:
|
|
127
|
+
homepage_uri: https://github.com/kenaniah/rails-openapi
|
|
128
|
+
source_code_uri: https://github.com/kenaniah/rails-openapi
|
|
129
|
+
changelog_uri: https://github.com/kenaniah/rails-openapi/blob/main/CHANGELOG.md
|
|
130
|
+
post_install_message:
|
|
131
|
+
rdoc_options: []
|
|
132
|
+
require_paths:
|
|
133
|
+
- lib
|
|
134
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
|
135
|
+
requirements:
|
|
136
|
+
- - ">="
|
|
137
|
+
- !ruby/object:Gem::Version
|
|
138
|
+
version: 2.6.0
|
|
139
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
|
140
|
+
requirements:
|
|
141
|
+
- - ">="
|
|
142
|
+
- !ruby/object:Gem::Version
|
|
143
|
+
version: '0'
|
|
144
|
+
requirements: []
|
|
145
|
+
rubygems_version: 3.2.33
|
|
146
|
+
signing_key:
|
|
147
|
+
specification_version: 4
|
|
148
|
+
summary: Creates rails engines from OpenAPI specification files
|
|
149
|
+
test_files: []
|