oas_rails 0.1.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/MIT-LICENSE +20 -0
- data/README.md +147 -0
- data/Rakefile +8 -0
- data/app/assets/config/oas_rails_manifest.js +1 -0
- data/app/assets/stylesheets/oas_rails/application.css +15 -0
- data/app/controllers/oas_rails/application_controller.rb +4 -0
- data/app/controllers/oas_rails/oas_rails_controller.rb +9 -0
- data/app/helpers/oas_rails/application_helper.rb +4 -0
- data/app/helpers/oas_rails/oas_rails_helper.rb +4 -0
- data/app/helpers/oas_rails/test_helper.rb +4 -0
- data/app/jobs/oas_rails/application_job.rb +4 -0
- data/app/mailers/oas_rails/application_mailer.rb +6 -0
- data/app/models/oas_rails/application_record.rb +5 -0
- data/app/views/layouts/oas_rails/application.html.erb +18 -0
- data/app/views/oas_rails/oas_rails/index.html.erb +1 -0
- data/app/views/oas_rails/test/show.html.erb +1 -0
- data/config/routes.rb +4 -0
- data/lib/generators/oas_rails/config/config_generator.rb +11 -0
- data/lib/generators/oas_rails/config/templates/oas_rails_initializer.rb +49 -0
- data/lib/oas_rails/configuration.rb +28 -0
- data/lib/oas_rails/contact.rb +12 -0
- data/lib/oas_rails/engine.rb +5 -0
- data/lib/oas_rails/info.rb +60 -0
- data/lib/oas_rails/license.rb +11 -0
- data/lib/oas_rails/media_type.rb +57 -0
- data/lib/oas_rails/oas_base.rb +29 -0
- data/lib/oas_rails/oas_route.rb +143 -0
- data/lib/oas_rails/operation.rb +118 -0
- data/lib/oas_rails/parameter.rb +47 -0
- data/lib/oas_rails/path_item.rb +25 -0
- data/lib/oas_rails/paths.rb +19 -0
- data/lib/oas_rails/request_body.rb +29 -0
- data/lib/oas_rails/response.rb +12 -0
- data/lib/oas_rails/responses.rb +20 -0
- data/lib/oas_rails/route_extractor.rb +87 -0
- data/lib/oas_rails/server.rb +10 -0
- data/lib/oas_rails/specification.rb +42 -0
- data/lib/oas_rails/tag.rb +17 -0
- data/lib/oas_rails/version.rb +3 -0
- data/lib/oas_rails/yard/oas_yard_factory.rb +160 -0
- data/lib/oas_rails.rb +120 -0
- metadata +159 -0
@@ -0,0 +1,160 @@
|
|
1
|
+
module OasRails
|
2
|
+
module Yard
|
3
|
+
class RequestBodyTag < ::YARD::Tags::Tag
|
4
|
+
attr_accessor :klass, :schema, :required
|
5
|
+
|
6
|
+
def initialize(tag_name, text, klass, schema: {}, required: false)
|
7
|
+
# initialize(tag_name, text, types = nil, name = nil)
|
8
|
+
super(tag_name, text, nil, nil)
|
9
|
+
@klass = klass
|
10
|
+
@schema = schema
|
11
|
+
@required = required
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
class RequestBodyExampleTag < ::YARD::Tags::Tag
|
16
|
+
attr_accessor :content
|
17
|
+
|
18
|
+
def initialize(tag_name, text, content: {})
|
19
|
+
super(tag_name, text, nil, nil)
|
20
|
+
@content = content
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
class ParameterTag < ::YARD::Tags::Tag
|
25
|
+
attr_accessor :schema, :required, :location
|
26
|
+
|
27
|
+
def initialize(tag_name, name, text, schema, location, required: false)
|
28
|
+
super(tag_name, text, nil, name)
|
29
|
+
@schema = schema
|
30
|
+
@required = required
|
31
|
+
@location = location
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
class ResponseTag < ::YARD::Tags::Tag
|
36
|
+
attr_accessor :schema
|
37
|
+
|
38
|
+
def initialize(tag_name, name, text, schema)
|
39
|
+
super(tag_name, text, nil, name)
|
40
|
+
@schema = schema
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
class OasYardFactory < ::YARD::Tags::DefaultFactory
|
45
|
+
## parse_tag is a prefix used by YARD
|
46
|
+
|
47
|
+
def parse_tag_with_request_body(tag_name, text)
|
48
|
+
match = text.match(/^(.*?)\s*\[(.*?)\]\s*(.*)$/)
|
49
|
+
if !match.nil?
|
50
|
+
text = match[1].strip
|
51
|
+
type, required = parse_type(match[2].strip)
|
52
|
+
|
53
|
+
if type.constantize == Hash
|
54
|
+
hash_string = match[3].strip
|
55
|
+
|
56
|
+
begin
|
57
|
+
hash = eval(hash_string)
|
58
|
+
hash = OasRails.hash_to_json_schema(hash)
|
59
|
+
rescue StandardError
|
60
|
+
hash = {}
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
RequestBodyTag.new(tag_name, text, type.constantize, schema: hash, required:)
|
65
|
+
else
|
66
|
+
Rails.logger.debug("Error parsing request_body tag: #{text}")
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
def parse_tag_with_request_body_example(tag_name, text)
|
71
|
+
match = text.match(/^(.*?)\s*\[(.*?)\]\s*(.*)$/)
|
72
|
+
if !match.nil?
|
73
|
+
text = match[1].strip
|
74
|
+
type = match[2]
|
75
|
+
|
76
|
+
if type.constantize == Hash
|
77
|
+
hash_string = match[3].strip
|
78
|
+
|
79
|
+
begin
|
80
|
+
hash = eval(hash_string)
|
81
|
+
rescue StandardError
|
82
|
+
hash = {}
|
83
|
+
end
|
84
|
+
end
|
85
|
+
RequestBodyExampleTag.new(tag_name, text, content: hash)
|
86
|
+
else
|
87
|
+
Rails.logger.debug("Error parsing request body example tag: #{text}")
|
88
|
+
end
|
89
|
+
end
|
90
|
+
|
91
|
+
def parse_tag_with_parameter(tag_name, text)
|
92
|
+
match = text.match(/^(.*?)\s*\[(.*?)\]\s*(.*)$/)
|
93
|
+
if !match.nil?
|
94
|
+
text = match[1].strip
|
95
|
+
name, location = parse_position_name(text)
|
96
|
+
type, required = parse_type(match[2].strip)
|
97
|
+
schema = OasRails.type_to_schema(type)
|
98
|
+
|
99
|
+
ParameterTag.new(tag_name, name, match[3].strip, schema, location, required:)
|
100
|
+
else
|
101
|
+
Rails.logger.debug("Error parsing request body example tag: #{text}")
|
102
|
+
end
|
103
|
+
end
|
104
|
+
|
105
|
+
def parse_tag_with_response(tag_name, text)
|
106
|
+
match = text.match(/^(.*?)\s*\[(.*?)\]\s*(.*)$/)
|
107
|
+
if !match.nil?
|
108
|
+
name, code = parse_position_name(match[1].strip)
|
109
|
+
|
110
|
+
begin
|
111
|
+
hash = parse_str_to_hash(match[3].strip)
|
112
|
+
hash = OasRails.hash_to_json_schema(hash)
|
113
|
+
rescue StandardError
|
114
|
+
hash = {}
|
115
|
+
end
|
116
|
+
|
117
|
+
ResponseTag.new(tag_name, code, name, hash)
|
118
|
+
else
|
119
|
+
Rails.logger.debug("Error parsing request body example tag: #{text}")
|
120
|
+
end
|
121
|
+
end
|
122
|
+
|
123
|
+
def parse_position_name(input)
|
124
|
+
return unless input =~ /^([^(]+)\((.*)\)$/
|
125
|
+
|
126
|
+
name = ::Regexp.last_match(1)
|
127
|
+
location = ::Regexp.last_match(2)
|
128
|
+
[name, location]
|
129
|
+
end
|
130
|
+
|
131
|
+
def parse_type(type_string)
|
132
|
+
if type_string.end_with?('!')
|
133
|
+
[type_string.chomp('!'), true]
|
134
|
+
else
|
135
|
+
[type_string, false]
|
136
|
+
end
|
137
|
+
end
|
138
|
+
|
139
|
+
def parse_str_to_hash(str)
|
140
|
+
str = str.gsub(/^\{|\}$/, '') # Remove leading { and trailing }
|
141
|
+
pairs = str.split(',').map(&:strip)
|
142
|
+
|
143
|
+
pairs.each_with_object({}) do |pair, hash|
|
144
|
+
key, value = pair.split(':').map(&:strip)
|
145
|
+
key = key.to_sym
|
146
|
+
hash[key] = case value
|
147
|
+
when 'String' then String
|
148
|
+
when 'Integer' then Integer
|
149
|
+
when 'Float' then Float
|
150
|
+
when 'Boolean' then [TrueClass, FalseClass]
|
151
|
+
when 'Array' then Array
|
152
|
+
when 'Hash' then Hash
|
153
|
+
when 'DateTime' then DateTime
|
154
|
+
else value
|
155
|
+
end
|
156
|
+
end
|
157
|
+
end
|
158
|
+
end
|
159
|
+
end
|
160
|
+
end
|
data/lib/oas_rails.rb
ADDED
@@ -0,0 +1,120 @@
|
|
1
|
+
require "yard"
|
2
|
+
require "method_source"
|
3
|
+
require "esquema"
|
4
|
+
|
5
|
+
require_relative 'oas_rails/version'
|
6
|
+
require_relative 'oas_rails/engine'
|
7
|
+
require_relative 'oas_rails/oas_base'
|
8
|
+
require_relative 'oas_rails/configuration'
|
9
|
+
require_relative 'oas_rails/specification'
|
10
|
+
require_relative 'oas_rails/route_extractor'
|
11
|
+
require_relative 'oas_rails/oas_route'
|
12
|
+
require_relative 'oas_rails/operation'
|
13
|
+
|
14
|
+
require_relative 'oas_rails/info'
|
15
|
+
require_relative 'oas_rails/contact'
|
16
|
+
require_relative 'oas_rails/paths'
|
17
|
+
require_relative 'oas_rails/path_item'
|
18
|
+
require_relative 'oas_rails/parameter'
|
19
|
+
require_relative 'oas_rails/tag'
|
20
|
+
require_relative 'oas_rails/license'
|
21
|
+
require_relative 'oas_rails/server'
|
22
|
+
require_relative "oas_rails/request_body"
|
23
|
+
require_relative "oas_rails/media_type"
|
24
|
+
require_relative 'oas_rails/yard/oas_yard_factory'
|
25
|
+
require_relative "oas_rails/response"
|
26
|
+
require_relative "oas_rails/responses"
|
27
|
+
|
28
|
+
module OasRails
|
29
|
+
class << self
|
30
|
+
def configure
|
31
|
+
yield config
|
32
|
+
end
|
33
|
+
|
34
|
+
def config
|
35
|
+
@config ||= Configuration.new
|
36
|
+
end
|
37
|
+
|
38
|
+
def configure_yard!
|
39
|
+
::YARD::Tags::Library.default_factory = Yard::OasYardFactory
|
40
|
+
yard_tags = {
|
41
|
+
'Request body' => [:request_body, :with_request_body],
|
42
|
+
'Request body Example' => [:request_body_example, :with_request_body_example],
|
43
|
+
'Parameter' => [:parameter, :with_parameter],
|
44
|
+
'Response' => [:response, :with_response],
|
45
|
+
'Endpoint Tags' => [:tags],
|
46
|
+
'Summary' => [:summary]
|
47
|
+
}
|
48
|
+
yard_tags.each do |tag_name, (method_name, handler)|
|
49
|
+
::YARD::Tags::Library.define_tag(tag_name, method_name, handler)
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
def configure_esquema!
|
54
|
+
Esquema.configure do |config|
|
55
|
+
config.exclude_associations = true
|
56
|
+
config.exclude_foreign_keys = true
|
57
|
+
config.excluded_columns = %i[id created_at updated_at deleted_at]
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
def detect_test_framework
|
62
|
+
if defined?(FactoryBot)
|
63
|
+
:factory_bot
|
64
|
+
elsif ActiveRecord::Base.connection.table_exists?('ar_internal_metadata')
|
65
|
+
:fixtures
|
66
|
+
else
|
67
|
+
:unknown
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
71
|
+
TYPE_MAPPING = {
|
72
|
+
'String' => 'string',
|
73
|
+
'Integer' => 'number',
|
74
|
+
'Float' => 'number',
|
75
|
+
'TrueClass' => 'boolean',
|
76
|
+
'FalseClass' => 'boolean',
|
77
|
+
'Boolean' => 'boolean',
|
78
|
+
'NilClass' => 'null',
|
79
|
+
'Hash' => 'object',
|
80
|
+
'Object' => 'object',
|
81
|
+
'DateTime' => 'string'
|
82
|
+
}.freeze
|
83
|
+
|
84
|
+
def type_to_schema(type_string)
|
85
|
+
if type_string.start_with?('Array<')
|
86
|
+
inner_type = type_string[/Array<(.+)>$/, 1]
|
87
|
+
{
|
88
|
+
"type" => "array",
|
89
|
+
"items" => type_to_schema(inner_type)
|
90
|
+
}
|
91
|
+
else
|
92
|
+
{ "type" => TYPE_MAPPING.fetch(type_string, 'string') }
|
93
|
+
end
|
94
|
+
end
|
95
|
+
|
96
|
+
def hash_to_json_schema(hash)
|
97
|
+
{
|
98
|
+
type: 'object',
|
99
|
+
properties: hash_to_properties(hash),
|
100
|
+
required: []
|
101
|
+
}
|
102
|
+
end
|
103
|
+
|
104
|
+
def hash_to_properties(hash)
|
105
|
+
hash.transform_values do |value|
|
106
|
+
if value.is_a?(Hash)
|
107
|
+
hash_to_json_schema(value)
|
108
|
+
elsif value.is_a?(Class)
|
109
|
+
{ type: ruby_type_to_json_type(value.name) }
|
110
|
+
else
|
111
|
+
{ type: ruby_type_to_json_type(value.class.name) }
|
112
|
+
end
|
113
|
+
end
|
114
|
+
end
|
115
|
+
|
116
|
+
def ruby_type_to_json_type(ruby_type)
|
117
|
+
TYPE_MAPPING.fetch(ruby_type, 'string')
|
118
|
+
end
|
119
|
+
end
|
120
|
+
end
|
metadata
ADDED
@@ -0,0 +1,159 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: oas_rails
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- a-chacon
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2024-07-27 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: esquema
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - "~>"
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: 0.1.2
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - "~>"
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: 0.1.2
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: method_source
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - "~>"
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '1.0'
|
34
|
+
type: :runtime
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - "~>"
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '1.0'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: rails
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - "~>"
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '7.0'
|
48
|
+
- - ">="
|
49
|
+
- !ruby/object:Gem::Version
|
50
|
+
version: 7.0.0
|
51
|
+
type: :runtime
|
52
|
+
prerelease: false
|
53
|
+
version_requirements: !ruby/object:Gem::Requirement
|
54
|
+
requirements:
|
55
|
+
- - "~>"
|
56
|
+
- !ruby/object:Gem::Version
|
57
|
+
version: '7.0'
|
58
|
+
- - ">="
|
59
|
+
- !ruby/object:Gem::Version
|
60
|
+
version: 7.0.0
|
61
|
+
- !ruby/object:Gem::Dependency
|
62
|
+
name: yard
|
63
|
+
requirement: !ruby/object:Gem::Requirement
|
64
|
+
requirements:
|
65
|
+
- - "~>"
|
66
|
+
- !ruby/object:Gem::Version
|
67
|
+
version: '0.9'
|
68
|
+
type: :runtime
|
69
|
+
prerelease: false
|
70
|
+
version_requirements: !ruby/object:Gem::Requirement
|
71
|
+
requirements:
|
72
|
+
- - "~>"
|
73
|
+
- !ruby/object:Gem::Version
|
74
|
+
version: '0.9'
|
75
|
+
description: |2+
|
76
|
+
# Open API Specification For Rails
|
77
|
+
|
78
|
+
OasRails is a Rails engine for generating **automatic interactive documentation for your Rails APIs**. It generates an **OAS 3.1** document and displays it using **[RapiDoc](https://rapidocweb.com)**.
|
79
|
+
|
80
|
+
## What Sets OasRails Apart?
|
81
|
+
|
82
|
+
- **Dynamic**: No command required to generate docs
|
83
|
+
- **Simple**: Complement default documentation with a few comments; no need to learn a complex DSL
|
84
|
+
- **Pure Ruby on Rails APIs**: No additional frameworks needed (e.g., Grape, RSpec)
|
85
|
+
|
86
|
+
email:
|
87
|
+
- andres.ch@protonmail.com
|
88
|
+
executables: []
|
89
|
+
extensions: []
|
90
|
+
extra_rdoc_files: []
|
91
|
+
files:
|
92
|
+
- MIT-LICENSE
|
93
|
+
- README.md
|
94
|
+
- Rakefile
|
95
|
+
- app/assets/config/oas_rails_manifest.js
|
96
|
+
- app/assets/stylesheets/oas_rails/application.css
|
97
|
+
- app/controllers/oas_rails/application_controller.rb
|
98
|
+
- app/controllers/oas_rails/oas_rails_controller.rb
|
99
|
+
- app/helpers/oas_rails/application_helper.rb
|
100
|
+
- app/helpers/oas_rails/oas_rails_helper.rb
|
101
|
+
- app/helpers/oas_rails/test_helper.rb
|
102
|
+
- app/jobs/oas_rails/application_job.rb
|
103
|
+
- app/mailers/oas_rails/application_mailer.rb
|
104
|
+
- app/models/oas_rails/application_record.rb
|
105
|
+
- app/views/layouts/oas_rails/application.html.erb
|
106
|
+
- app/views/oas_rails/oas_rails/index.html.erb
|
107
|
+
- app/views/oas_rails/test/show.html.erb
|
108
|
+
- config/routes.rb
|
109
|
+
- lib/generators/oas_rails/config/config_generator.rb
|
110
|
+
- lib/generators/oas_rails/config/templates/oas_rails_initializer.rb
|
111
|
+
- lib/oas_rails.rb
|
112
|
+
- lib/oas_rails/configuration.rb
|
113
|
+
- lib/oas_rails/contact.rb
|
114
|
+
- lib/oas_rails/engine.rb
|
115
|
+
- lib/oas_rails/info.rb
|
116
|
+
- lib/oas_rails/license.rb
|
117
|
+
- lib/oas_rails/media_type.rb
|
118
|
+
- lib/oas_rails/oas_base.rb
|
119
|
+
- lib/oas_rails/oas_route.rb
|
120
|
+
- lib/oas_rails/operation.rb
|
121
|
+
- lib/oas_rails/parameter.rb
|
122
|
+
- lib/oas_rails/path_item.rb
|
123
|
+
- lib/oas_rails/paths.rb
|
124
|
+
- lib/oas_rails/request_body.rb
|
125
|
+
- lib/oas_rails/response.rb
|
126
|
+
- lib/oas_rails/responses.rb
|
127
|
+
- lib/oas_rails/route_extractor.rb
|
128
|
+
- lib/oas_rails/server.rb
|
129
|
+
- lib/oas_rails/specification.rb
|
130
|
+
- lib/oas_rails/tag.rb
|
131
|
+
- lib/oas_rails/version.rb
|
132
|
+
- lib/oas_rails/yard/oas_yard_factory.rb
|
133
|
+
homepage: https://github.com/a-chacon/oas_rails
|
134
|
+
licenses:
|
135
|
+
- GPL-3.0-only
|
136
|
+
metadata:
|
137
|
+
homepage_uri: https://github.com/a-chacon/oas_rails
|
138
|
+
post_install_message:
|
139
|
+
rdoc_options: []
|
140
|
+
require_paths:
|
141
|
+
- lib
|
142
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
143
|
+
requirements:
|
144
|
+
- - ">="
|
145
|
+
- !ruby/object:Gem::Version
|
146
|
+
version: '3.0'
|
147
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
148
|
+
requirements:
|
149
|
+
- - ">="
|
150
|
+
- !ruby/object:Gem::Version
|
151
|
+
version: '0'
|
152
|
+
requirements: []
|
153
|
+
rubygems_version: 3.5.15
|
154
|
+
signing_key:
|
155
|
+
specification_version: 4
|
156
|
+
summary: OasRails is a Rails engine for generating automatic interactive documentation
|
157
|
+
for your Rails APIs. It generates an OAS document and displays it using a nice UI.
|
158
|
+
test_files: []
|
159
|
+
...
|