rails-openapi-gen 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/CLAUDE.md +160 -0
- data/README.md +164 -0
- data/lib/rails_openapi_gen/configuration.rb +157 -0
- data/lib/rails_openapi_gen/engine.rb +11 -0
- data/lib/rails_openapi_gen/generators/yaml_generator.rb +302 -0
- data/lib/rails_openapi_gen/importer.rb +647 -0
- data/lib/rails_openapi_gen/parsers/comment_parser.rb +40 -0
- data/lib/rails_openapi_gen/parsers/comment_parsers/attribute_parser.rb +57 -0
- data/lib/rails_openapi_gen/parsers/comment_parsers/base_attribute_parser.rb +42 -0
- data/lib/rails_openapi_gen/parsers/comment_parsers/body_parser.rb +62 -0
- data/lib/rails_openapi_gen/parsers/comment_parsers/conditional_parser.rb +13 -0
- data/lib/rails_openapi_gen/parsers/comment_parsers/operation_parser.rb +50 -0
- data/lib/rails_openapi_gen/parsers/comment_parsers/param_parser.rb +62 -0
- data/lib/rails_openapi_gen/parsers/comment_parsers/query_parser.rb +62 -0
- data/lib/rails_openapi_gen/parsers/controller_parser.rb +153 -0
- data/lib/rails_openapi_gen/parsers/jbuilder_parser.rb +529 -0
- data/lib/rails_openapi_gen/parsers/routes_parser.rb +33 -0
- data/lib/rails_openapi_gen/parsers/template_processors/jbuilder_template_processor.rb +147 -0
- data/lib/rails_openapi_gen/parsers/template_processors/response_template_processor.rb +17 -0
- data/lib/rails_openapi_gen/railtie.rb +11 -0
- data/lib/rails_openapi_gen/tasks/openapi.rake +30 -0
- data/lib/rails_openapi_gen/version.rb +5 -0
- data/lib/rails_openapi_gen.rb +267 -0
- data/lib/tasks/openapi_import.rake +126 -0
- data/rails-openapi-gen.gemspec +30 -0
- metadata +155 -0
@@ -0,0 +1,17 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module RailsOpenapiGen
|
4
|
+
module Parsers
|
5
|
+
module TemplateProcessors
|
6
|
+
module ResponseTemplateProcessor
|
7
|
+
def extract_template_path(action_node, route)
|
8
|
+
raise NotImplementedError, "#{self.class} must implement #extract_template_path"
|
9
|
+
end
|
10
|
+
|
11
|
+
def find_default_template(route)
|
12
|
+
raise NotImplementedError, "#{self.class} must implement #find_default_template"
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
@@ -0,0 +1,30 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
namespace :openapi do
|
4
|
+
desc "Generate OpenAPI specification from Rails application"
|
5
|
+
task generate: :environment do
|
6
|
+
require "rails_openapi_gen"
|
7
|
+
RailsOpenapiGen.generate
|
8
|
+
end
|
9
|
+
|
10
|
+
desc "Check for missing @openapi comments and uncommitted changes"
|
11
|
+
task check: :environment do
|
12
|
+
require "rails_openapi_gen"
|
13
|
+
RailsOpenapiGen.check
|
14
|
+
end
|
15
|
+
|
16
|
+
desc "Import OpenAPI specification and add comments to Jbuilder templates"
|
17
|
+
task :import, [:openapi_file] => :environment do |_task, args|
|
18
|
+
require "rails_openapi_gen"
|
19
|
+
|
20
|
+
openapi_file = args[:openapi_file]
|
21
|
+
|
22
|
+
if openapi_file.nil? || openapi_file.empty?
|
23
|
+
puts "Usage: bin/rails openapi:import[PATH_TO_OPENAPI_FILE]"
|
24
|
+
puts "Example: bin/rails openapi:import[docs/api/openapi.yaml]"
|
25
|
+
exit 1
|
26
|
+
end
|
27
|
+
|
28
|
+
RailsOpenapiGen.import(openapi_file)
|
29
|
+
end
|
30
|
+
end
|
@@ -0,0 +1,267 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "rails_openapi_gen/version"
|
4
|
+
require "rails_openapi_gen/configuration"
|
5
|
+
require "rails_openapi_gen/parsers/comment_parser"
|
6
|
+
require "rails_openapi_gen/generators/yaml_generator"
|
7
|
+
require "rails_openapi_gen/importer"
|
8
|
+
|
9
|
+
# Rails integration is handled by Engine
|
10
|
+
|
11
|
+
# Load Rails Engine if Rails is available
|
12
|
+
if defined?(Rails::Engine)
|
13
|
+
require "rails_openapi_gen/engine"
|
14
|
+
|
15
|
+
# Only load parser-dependent components if parser gem is available
|
16
|
+
begin
|
17
|
+
require "parser/current"
|
18
|
+
require "rails_openapi_gen/parsers/routes_parser"
|
19
|
+
require "rails_openapi_gen/parsers/controller_parser"
|
20
|
+
require "rails_openapi_gen/parsers/jbuilder_parser"
|
21
|
+
rescue LoadError
|
22
|
+
# parser gem not available, skip these components
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
module RailsOpenapiGen
|
27
|
+
class Error < StandardError; end
|
28
|
+
|
29
|
+
class << self
|
30
|
+
# Generates OpenAPI specification from Rails application
|
31
|
+
# @return [void]
|
32
|
+
def generate
|
33
|
+
Generator.new.run
|
34
|
+
end
|
35
|
+
|
36
|
+
# Checks for missing OpenAPI comments and uncommitted changes
|
37
|
+
# @return [void]
|
38
|
+
def check
|
39
|
+
Checker.new.run
|
40
|
+
end
|
41
|
+
|
42
|
+
# Imports OpenAPI specification and generates @openapi comments in Jbuilder files
|
43
|
+
# @param openapi_file [String, nil] Path to OpenAPI specification file (defaults to openapi/openapi.yaml)
|
44
|
+
# @return [void]
|
45
|
+
def import(openapi_file = nil)
|
46
|
+
Importer.new(openapi_file).run
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
class Generator
|
51
|
+
# Runs the OpenAPI generation process
|
52
|
+
# @return [void]
|
53
|
+
def run
|
54
|
+
# Load configuration
|
55
|
+
RailsOpenapiGen.configuration.load_from_file
|
56
|
+
|
57
|
+
routes = Parsers::RoutesParser.new.parse
|
58
|
+
filtered_routes = routes.select { |route| RailsOpenapiGen.configuration.route_included?(route[:path]) }
|
59
|
+
|
60
|
+
schemas = {}
|
61
|
+
|
62
|
+
filtered_routes.each do |route|
|
63
|
+
controller_info = Parsers::ControllerParser.new(route).parse
|
64
|
+
|
65
|
+
if controller_info[:jbuilder_path]
|
66
|
+
jbuilder_result = Parsers::JbuilderParser.new(controller_info[:jbuilder_path]).parse
|
67
|
+
schema = build_schema(jbuilder_result[:properties])
|
68
|
+
schemas[route] = {
|
69
|
+
schema: schema,
|
70
|
+
parameters: controller_info[:parameters] || {},
|
71
|
+
operation: jbuilder_result[:operation]
|
72
|
+
}
|
73
|
+
end
|
74
|
+
end
|
75
|
+
|
76
|
+
Generators::YamlGenerator.new(schemas).generate
|
77
|
+
puts "✅ OpenAPI specification generated successfully!"
|
78
|
+
end
|
79
|
+
|
80
|
+
private
|
81
|
+
|
82
|
+
# Builds schema from parsed AST nodes
|
83
|
+
# @param ast [Array<Hash>] Array of parsed AST nodes
|
84
|
+
# @return [Hash] OpenAPI schema definition
|
85
|
+
def build_schema(ast)
|
86
|
+
# Check if this is an array response (json.array!)
|
87
|
+
if ast.any? { |node| node[:is_array_root] }
|
88
|
+
return build_array_schema(ast)
|
89
|
+
end
|
90
|
+
|
91
|
+
schema = { "type" => "object", "properties" => {}, "required" => [] }
|
92
|
+
|
93
|
+
ast.each do |node|
|
94
|
+
property = node[:property]
|
95
|
+
comment_data = node[:comment_data] || {}
|
96
|
+
|
97
|
+
# Skip array root items as they're handled separately
|
98
|
+
next if node[:is_array_root]
|
99
|
+
|
100
|
+
property_schema = build_property_schema(node)
|
101
|
+
|
102
|
+
schema["properties"][property] = property_schema
|
103
|
+
# Don't mark conditional properties as required, even if they have required:true
|
104
|
+
if comment_data[:required] == "true" && !node[:is_conditional]
|
105
|
+
schema["required"] << property
|
106
|
+
end
|
107
|
+
end
|
108
|
+
|
109
|
+
schema
|
110
|
+
end
|
111
|
+
|
112
|
+
# Builds array schema from AST nodes containing json.array!
|
113
|
+
# @param ast [Array<Hash>] Array of parsed AST nodes
|
114
|
+
# @return [Hash] OpenAPI array schema definition
|
115
|
+
def build_array_schema(ast)
|
116
|
+
# For json.array! responses, return array schema
|
117
|
+
item_properties = {}
|
118
|
+
required_fields = []
|
119
|
+
|
120
|
+
# Find the array root node to check for array_item_properties
|
121
|
+
array_root_node = ast.find { |node| node[:is_array_root] }
|
122
|
+
|
123
|
+
if array_root_node && array_root_node[:array_item_properties]
|
124
|
+
# Use properties from the parsed partial
|
125
|
+
array_root_node[:array_item_properties].each do |node|
|
126
|
+
property = node[:property]
|
127
|
+
comment_data = node[:comment_data] || {}
|
128
|
+
|
129
|
+
property_schema = build_property_schema(node)
|
130
|
+
item_properties[property] = property_schema
|
131
|
+
if comment_data[:required] == "true" && !node[:is_conditional]
|
132
|
+
required_fields << property
|
133
|
+
end
|
134
|
+
end
|
135
|
+
else
|
136
|
+
# Fall back to looking for non-root properties
|
137
|
+
ast.each do |node|
|
138
|
+
next if node[:is_array_root]
|
139
|
+
|
140
|
+
property = node[:property]
|
141
|
+
comment_data = node[:comment_data] || {}
|
142
|
+
|
143
|
+
property_schema = build_property_schema(node)
|
144
|
+
item_properties[property] = property_schema
|
145
|
+
if comment_data[:required] == "true" && !node[:is_conditional]
|
146
|
+
required_fields << property
|
147
|
+
end
|
148
|
+
end
|
149
|
+
end
|
150
|
+
|
151
|
+
{
|
152
|
+
"type" => "array",
|
153
|
+
"items" => {
|
154
|
+
"type" => "object",
|
155
|
+
"properties" => item_properties,
|
156
|
+
"required" => required_fields
|
157
|
+
}
|
158
|
+
}
|
159
|
+
end
|
160
|
+
|
161
|
+
# Builds property schema from a single AST node
|
162
|
+
# @param node [Hash] Parsed AST node containing property information
|
163
|
+
# @return [Hash] OpenAPI property schema
|
164
|
+
def build_property_schema(node)
|
165
|
+
comment_data = node[:comment_data] || {}
|
166
|
+
property_schema = {}
|
167
|
+
|
168
|
+
# Handle different property types
|
169
|
+
if node[:is_object] || node[:is_nested]
|
170
|
+
property_schema["type"] = "object"
|
171
|
+
|
172
|
+
# Build nested properties if they exist
|
173
|
+
if node[:nested_properties] && !node[:nested_properties].empty?
|
174
|
+
nested_schema = build_nested_object_schema(node[:nested_properties])
|
175
|
+
property_schema["properties"] = nested_schema["properties"]
|
176
|
+
property_schema["required"] = nested_schema["required"] if nested_schema["required"] && !nested_schema["required"].empty?
|
177
|
+
end
|
178
|
+
elsif node[:is_array]
|
179
|
+
property_schema["type"] = "array"
|
180
|
+
|
181
|
+
if node[:array_item_properties] && !node[:array_item_properties].empty?
|
182
|
+
# Build items schema from array iteration block
|
183
|
+
items_schema = build_nested_object_schema(node[:array_item_properties])
|
184
|
+
items_def = {
|
185
|
+
"type" => "object",
|
186
|
+
"properties" => items_schema["properties"]
|
187
|
+
}
|
188
|
+
items_def["required"] = items_schema["required"] if items_schema["required"] && !items_schema["required"].empty?
|
189
|
+
property_schema["items"] = items_def
|
190
|
+
elsif comment_data[:items]
|
191
|
+
# Use specified items type from comment
|
192
|
+
property_schema["items"] = { "type" => comment_data[:items] }
|
193
|
+
else
|
194
|
+
# Default to object items
|
195
|
+
property_schema["items"] = { "type" => "object" }
|
196
|
+
end
|
197
|
+
elsif comment_data[:type] && comment_data[:type] != "TODO: MISSING COMMENT"
|
198
|
+
property_schema["type"] = comment_data[:type]
|
199
|
+
|
200
|
+
# Handle array types
|
201
|
+
if comment_data[:type] == "array"
|
202
|
+
if comment_data[:items]
|
203
|
+
# Use specified items type
|
204
|
+
property_schema["items"] = { "type" => comment_data[:items] }
|
205
|
+
else
|
206
|
+
# Default to string items if no items type is specified
|
207
|
+
property_schema["items"] = { "type" => "string" }
|
208
|
+
end
|
209
|
+
end
|
210
|
+
else
|
211
|
+
# Only show TODO message if no @openapi comment exists at all
|
212
|
+
property_schema["type"] = "string"
|
213
|
+
if comment_data.nil? || comment_data.empty?
|
214
|
+
property_schema["description"] = "TODO: MISSING COMMENT - Add @openapi comment"
|
215
|
+
end
|
216
|
+
end
|
217
|
+
|
218
|
+
# Add common properties
|
219
|
+
property_schema["description"] = comment_data[:description] if comment_data[:description]
|
220
|
+
property_schema["enum"] = comment_data[:enum] if comment_data[:enum]
|
221
|
+
|
222
|
+
property_schema
|
223
|
+
end
|
224
|
+
|
225
|
+
# Builds schema for nested object properties
|
226
|
+
# @param nested_properties [Array<Hash>] Array of nested property nodes
|
227
|
+
# @return [Hash] Schema with properties and required fields
|
228
|
+
def build_nested_object_schema(nested_properties)
|
229
|
+
schema = { "properties" => {}, "required" => [] }
|
230
|
+
|
231
|
+
nested_properties.each do |node|
|
232
|
+
property = node[:property]
|
233
|
+
comment_data = node[:comment_data] || {}
|
234
|
+
|
235
|
+
property_schema = build_property_schema(node)
|
236
|
+
schema["properties"][property] = property_schema
|
237
|
+
if comment_data[:required] == "true" && !node[:is_conditional]
|
238
|
+
schema["required"] << property
|
239
|
+
end
|
240
|
+
end
|
241
|
+
|
242
|
+
schema
|
243
|
+
end
|
244
|
+
end
|
245
|
+
|
246
|
+
class Checker
|
247
|
+
# Runs checks for missing comments and uncommitted changes
|
248
|
+
# @return [void]
|
249
|
+
def run
|
250
|
+
system("bin/rails openapi:generate")
|
251
|
+
|
252
|
+
missing_comments = `grep -r "TODO: MISSING COMMENT" openapi/`.strip
|
253
|
+
unless missing_comments.empty?
|
254
|
+
puts "❌ Missing @openapi comments found!"
|
255
|
+
exit 1
|
256
|
+
end
|
257
|
+
|
258
|
+
diff = `git diff --name-only openapi/`.strip
|
259
|
+
unless diff.empty?
|
260
|
+
puts "❌ OpenAPI spec has uncommitted changes!"
|
261
|
+
exit 1
|
262
|
+
end
|
263
|
+
|
264
|
+
puts "✅ OpenAPI spec is up to date!"
|
265
|
+
end
|
266
|
+
end
|
267
|
+
end
|
@@ -0,0 +1,126 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
namespace :openapi do
|
4
|
+
desc "Import OpenAPI specification and add @openapi comments to Jbuilder files"
|
5
|
+
task :import, [:openapi_file] => :environment do |_task, args|
|
6
|
+
openapi_file = args[:openapi_file]
|
7
|
+
|
8
|
+
# Set debug mode if verbose flag is passed
|
9
|
+
ENV['DEBUG_OPENAPI_IMPORT'] = '1' if ENV['VERBOSE'] == 'true'
|
10
|
+
|
11
|
+
RailsOpenapiGen.import(openapi_file)
|
12
|
+
end
|
13
|
+
|
14
|
+
desc "Diagnose import issues by comparing OpenAPI paths with Rails routes"
|
15
|
+
task :diagnose_import, [:openapi_file] => :environment do |_task, args|
|
16
|
+
openapi_file = args[:openapi_file] || File.join(RailsOpenapiGen.configuration.output_directory,
|
17
|
+
RailsOpenapiGen.configuration.output_filename)
|
18
|
+
|
19
|
+
unless File.exist?(openapi_file)
|
20
|
+
puts "❌ OpenAPI file not found: #{openapi_file}"
|
21
|
+
exit 1
|
22
|
+
end
|
23
|
+
|
24
|
+
puts "🔍 Diagnosing OpenAPI import for: #{openapi_file}"
|
25
|
+
puts ""
|
26
|
+
|
27
|
+
# Load OpenAPI spec
|
28
|
+
openapi_spec = YAML.load_file(openapi_file)
|
29
|
+
openapi_paths = openapi_spec['paths'] || {}
|
30
|
+
|
31
|
+
# Get Rails routes
|
32
|
+
routes_parser = RailsOpenapiGen::Parsers::RoutesParser.new
|
33
|
+
rails_routes = routes_parser.parse
|
34
|
+
|
35
|
+
# Group routes by path for easier lookup
|
36
|
+
routes_by_path = rails_routes.group_by { |r| r[:path] }
|
37
|
+
|
38
|
+
puts "📊 Summary:"
|
39
|
+
puts " OpenAPI paths: #{openapi_paths.size}"
|
40
|
+
puts " Rails routes: #{rails_routes.size}"
|
41
|
+
puts ""
|
42
|
+
|
43
|
+
# Check each OpenAPI path
|
44
|
+
unmatched_paths = []
|
45
|
+
matched_paths = []
|
46
|
+
|
47
|
+
openapi_paths.each do |path, methods|
|
48
|
+
methods.each do |method, operation|
|
49
|
+
next if method == 'parameters'
|
50
|
+
|
51
|
+
# Convert OpenAPI path to Rails format
|
52
|
+
rails_path = path.gsub(/\{(\w+)\}/, ':\1')
|
53
|
+
|
54
|
+
# Try to find matching route
|
55
|
+
matching_routes = rails_routes.select do |route|
|
56
|
+
route[:method] == method.upcase &&
|
57
|
+
route[:path].gsub(/\/$/, '') == rails_path.gsub(/\/$/, '')
|
58
|
+
end
|
59
|
+
|
60
|
+
if matching_routes.empty?
|
61
|
+
unmatched_paths << { path: path, method: method.upcase, rails_path: rails_path }
|
62
|
+
else
|
63
|
+
matched_paths << { path: path, method: method.upcase, route: matching_routes.first }
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
# Report results
|
69
|
+
if matched_paths.any?
|
70
|
+
puts "✅ Matched paths (#{matched_paths.size}):"
|
71
|
+
matched_paths.each do |match|
|
72
|
+
route = match[:route]
|
73
|
+
controller_path = route[:controller].gsub('/', '::').camelize + "Controller"
|
74
|
+
action = route[:action]
|
75
|
+
puts " #{match[:method]} #{match[:path]} → #{controller_path}##{action}"
|
76
|
+
end
|
77
|
+
puts ""
|
78
|
+
end
|
79
|
+
|
80
|
+
if unmatched_paths.any?
|
81
|
+
puts "❌ Unmatched OpenAPI paths (#{unmatched_paths.size}):"
|
82
|
+
unmatched_paths.each do |unmatched|
|
83
|
+
puts " #{unmatched[:method]} #{unmatched[:path]}"
|
84
|
+
|
85
|
+
# Suggest similar routes
|
86
|
+
similar_routes = rails_routes.select do |route|
|
87
|
+
route[:method] == unmatched[:method] &&
|
88
|
+
route[:path].include?(unmatched[:rails_path].split('/').reject(&:empty?).first.to_s)
|
89
|
+
end
|
90
|
+
|
91
|
+
if similar_routes.any?
|
92
|
+
puts " Did you mean one of these?"
|
93
|
+
similar_routes.take(3).each do |route|
|
94
|
+
puts " - #{route[:path]}"
|
95
|
+
end
|
96
|
+
end
|
97
|
+
end
|
98
|
+
puts ""
|
99
|
+
end
|
100
|
+
|
101
|
+
# Check for Jbuilder templates
|
102
|
+
puts "📄 Checking Jbuilder templates:"
|
103
|
+
matched_paths.each do |match|
|
104
|
+
route = match[:route]
|
105
|
+
controller_parser = RailsOpenapiGen::Parsers::ControllerParser.new(route)
|
106
|
+
controller_info = controller_parser.parse
|
107
|
+
|
108
|
+
if controller_info[:jbuilder_path]
|
109
|
+
if File.exist?(controller_info[:jbuilder_path])
|
110
|
+
puts " ✅ #{match[:method]} #{match[:path]} → #{controller_info[:jbuilder_path]}"
|
111
|
+
else
|
112
|
+
puts " ❌ #{match[:method]} #{match[:path]} → #{controller_info[:jbuilder_path]} (file not found)"
|
113
|
+
end
|
114
|
+
else
|
115
|
+
puts " ⚠️ #{match[:method]} #{match[:path]} → No Jbuilder template found"
|
116
|
+
end
|
117
|
+
end
|
118
|
+
|
119
|
+
puts ""
|
120
|
+
puts "💡 Tips:"
|
121
|
+
puts " - Ensure your OpenAPI paths match your Rails routes exactly"
|
122
|
+
puts " - Use {id} in OpenAPI for :id in Rails routes"
|
123
|
+
puts " - Create Jbuilder templates for API endpoints that need them"
|
124
|
+
puts " - Run 'DEBUG_OPENAPI_IMPORT=1 rake openapi:import[#{openapi_file}]' for detailed import logs"
|
125
|
+
end
|
126
|
+
end
|
@@ -0,0 +1,30 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
Gem::Specification.new do |spec|
|
4
|
+
spec.name = "rails-openapi-gen"
|
5
|
+
spec.version = "0.0.1"
|
6
|
+
spec.authors = ["myzkey"]
|
7
|
+
spec.email = ["myzkey.dev@example.com"]
|
8
|
+
|
9
|
+
spec.summary = "Rails comment-driven OpenAPI generator"
|
10
|
+
spec.description = "Generates OpenAPI specs from Rails apps by parsing routes, controllers, and view templates with @openapi comment annotations"
|
11
|
+
spec.homepage = "https://github.com/myzkey/rails-openapi-gen"
|
12
|
+
spec.license = "MIT"
|
13
|
+
spec.required_ruby_version = ">= 2.7.0"
|
14
|
+
|
15
|
+
spec.metadata["homepage_uri"] = spec.homepage
|
16
|
+
spec.metadata["source_code_uri"] = spec.homepage
|
17
|
+
|
18
|
+
spec.files = Dir.glob("lib/**/*") + Dir.glob("*.md") + Dir.glob("*.gemspec")
|
19
|
+
spec.bindir = "exe"
|
20
|
+
spec.executables = spec.files.grep(%r{\Aexe/}) { |f| File.basename(f) }
|
21
|
+
spec.require_paths = ["lib"]
|
22
|
+
|
23
|
+
spec.add_dependency "rails", ">= 6.0"
|
24
|
+
spec.add_dependency "parser", "~> 3.2"
|
25
|
+
spec.add_dependency "yaml", "~> 0.2"
|
26
|
+
|
27
|
+
spec.add_development_dependency "rspec", "~> 3.12"
|
28
|
+
spec.add_development_dependency "rubocop", "~> 1.50"
|
29
|
+
spec.add_development_dependency "rake", "~> 13.0"
|
30
|
+
end
|
metadata
ADDED
@@ -0,0 +1,155 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: rails-openapi-gen
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.1
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- myzkey
|
8
|
+
autorequire:
|
9
|
+
bindir: exe
|
10
|
+
cert_chain: []
|
11
|
+
date: 2025-07-10 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.0'
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - ">="
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '6.0'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: parser
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - "~>"
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '3.2'
|
34
|
+
type: :runtime
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - "~>"
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '3.2'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: yaml
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - "~>"
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '0.2'
|
48
|
+
type: :runtime
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - "~>"
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '0.2'
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: rspec
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - "~>"
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '3.12'
|
62
|
+
type: :development
|
63
|
+
prerelease: false
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - "~>"
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: '3.12'
|
69
|
+
- !ruby/object:Gem::Dependency
|
70
|
+
name: rubocop
|
71
|
+
requirement: !ruby/object:Gem::Requirement
|
72
|
+
requirements:
|
73
|
+
- - "~>"
|
74
|
+
- !ruby/object:Gem::Version
|
75
|
+
version: '1.50'
|
76
|
+
type: :development
|
77
|
+
prerelease: false
|
78
|
+
version_requirements: !ruby/object:Gem::Requirement
|
79
|
+
requirements:
|
80
|
+
- - "~>"
|
81
|
+
- !ruby/object:Gem::Version
|
82
|
+
version: '1.50'
|
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
|
+
description: Generates OpenAPI specs from Rails apps by parsing routes, controllers,
|
98
|
+
and view templates with @openapi comment annotations
|
99
|
+
email:
|
100
|
+
- myzkey.dev@example.com
|
101
|
+
executables: []
|
102
|
+
extensions: []
|
103
|
+
extra_rdoc_files: []
|
104
|
+
files:
|
105
|
+
- CLAUDE.md
|
106
|
+
- README.md
|
107
|
+
- lib/rails_openapi_gen.rb
|
108
|
+
- lib/rails_openapi_gen/configuration.rb
|
109
|
+
- lib/rails_openapi_gen/engine.rb
|
110
|
+
- lib/rails_openapi_gen/generators/yaml_generator.rb
|
111
|
+
- lib/rails_openapi_gen/importer.rb
|
112
|
+
- lib/rails_openapi_gen/parsers/comment_parser.rb
|
113
|
+
- lib/rails_openapi_gen/parsers/comment_parsers/attribute_parser.rb
|
114
|
+
- lib/rails_openapi_gen/parsers/comment_parsers/base_attribute_parser.rb
|
115
|
+
- lib/rails_openapi_gen/parsers/comment_parsers/body_parser.rb
|
116
|
+
- lib/rails_openapi_gen/parsers/comment_parsers/conditional_parser.rb
|
117
|
+
- lib/rails_openapi_gen/parsers/comment_parsers/operation_parser.rb
|
118
|
+
- lib/rails_openapi_gen/parsers/comment_parsers/param_parser.rb
|
119
|
+
- lib/rails_openapi_gen/parsers/comment_parsers/query_parser.rb
|
120
|
+
- lib/rails_openapi_gen/parsers/controller_parser.rb
|
121
|
+
- lib/rails_openapi_gen/parsers/jbuilder_parser.rb
|
122
|
+
- lib/rails_openapi_gen/parsers/routes_parser.rb
|
123
|
+
- lib/rails_openapi_gen/parsers/template_processors/jbuilder_template_processor.rb
|
124
|
+
- lib/rails_openapi_gen/parsers/template_processors/response_template_processor.rb
|
125
|
+
- lib/rails_openapi_gen/railtie.rb
|
126
|
+
- lib/rails_openapi_gen/tasks/openapi.rake
|
127
|
+
- lib/rails_openapi_gen/version.rb
|
128
|
+
- lib/tasks/openapi_import.rake
|
129
|
+
- rails-openapi-gen.gemspec
|
130
|
+
homepage: https://github.com/myzkey/rails-openapi-gen
|
131
|
+
licenses:
|
132
|
+
- MIT
|
133
|
+
metadata:
|
134
|
+
homepage_uri: https://github.com/myzkey/rails-openapi-gen
|
135
|
+
source_code_uri: https://github.com/myzkey/rails-openapi-gen
|
136
|
+
post_install_message:
|
137
|
+
rdoc_options: []
|
138
|
+
require_paths:
|
139
|
+
- lib
|
140
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
141
|
+
requirements:
|
142
|
+
- - ">="
|
143
|
+
- !ruby/object:Gem::Version
|
144
|
+
version: 2.7.0
|
145
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
146
|
+
requirements:
|
147
|
+
- - ">="
|
148
|
+
- !ruby/object:Gem::Version
|
149
|
+
version: '0'
|
150
|
+
requirements: []
|
151
|
+
rubygems_version: 3.3.26
|
152
|
+
signing_key:
|
153
|
+
specification_version: 4
|
154
|
+
summary: Rails comment-driven OpenAPI generator
|
155
|
+
test_files: []
|