swaggard 2.0.0 → 4.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 +4 -4
- data/README.md +84 -132
- data/app/views/swaggard/swagger/index.html.erb +51 -53
- data/lib/swaggard/api_definition.rb +42 -28
- data/lib/swaggard/configuration.rb +1 -5
- data/lib/swaggard/engine.rb +0 -32
- data/lib/swaggard/swagger/operation.rb +32 -12
- data/lib/swaggard/swagger/parameters/base.rb +7 -6
- data/lib/swaggard/swagger/parameters/body.rb +9 -9
- data/lib/swaggard/swagger/parameters/form.rb +10 -1
- data/lib/swaggard/swagger/parameters/list.rb +6 -8
- data/lib/swaggard/swagger/parameters/query.rb +9 -9
- data/lib/swaggard/swagger/response.rb +15 -8
- data/lib/swaggard/swagger/response_header.rb +1 -1
- data/lib/swaggard/swagger/type.rb +2 -2
- data/lib/swaggard/version.rb +1 -1
- data/lib/swaggard.rb +9 -1
- data/spec/fixtures/api.json +1 -1
- data/spec/fixtures/dummy/config/application.rb +0 -1
- data/spec/fixtures/openapi_3_1_schema.json +1440 -0
- data/spec/integration/openapi_spec.rb +28 -0
- metadata +8 -43
- data/app/assets/fonts/swaggard/DroidSans-Bold.ttf +0 -0
- data/app/assets/fonts/swaggard/DroidSans.ttf +0 -0
- data/app/assets/javascripts/swaggard/application.js +0 -28
- data/app/assets/javascripts/swaggard/lang/ca.js +0 -53
- data/app/assets/javascripts/swaggard/lang/el.js +0 -56
- data/app/assets/javascripts/swaggard/lang/en.js +0 -56
- data/app/assets/javascripts/swaggard/lang/es.js +0 -53
- data/app/assets/javascripts/swaggard/lang/fr.js +0 -54
- data/app/assets/javascripts/swaggard/lang/geo.js +0 -56
- data/app/assets/javascripts/swaggard/lang/it.js +0 -52
- data/app/assets/javascripts/swaggard/lang/ja.js +0 -56
- data/app/assets/javascripts/swaggard/lang/ko-kr.js +0 -53
- data/app/assets/javascripts/swaggard/lang/pl.js +0 -53
- data/app/assets/javascripts/swaggard/lang/pt.js +0 -53
- data/app/assets/javascripts/swaggard/lang/ru.js +0 -56
- data/app/assets/javascripts/swaggard/lang/tr.js +0 -53
- data/app/assets/javascripts/swaggard/lang/zh-cn.js +0 -56
- data/app/assets/javascripts/swaggard/lib/backbone-min.js +0 -1
- data/app/assets/javascripts/swaggard/lib/handlebars-4.0.5.js +0 -3
- data/app/assets/javascripts/swaggard/lib/highlight.9.1.0.pack.js +0 -1
- data/app/assets/javascripts/swaggard/lib/highlight.9.1.0.pack_extended.js +0 -1
- data/app/assets/javascripts/swaggard/lib/jquery-1.8.0.min.js +0 -3
- data/app/assets/javascripts/swaggard/lib/jquery.ba-bbq.min.js +0 -1
- data/app/assets/javascripts/swaggard/lib/jquery.slideto.min.js +0 -1
- data/app/assets/javascripts/swaggard/lib/jquery.wiggle.min.js +0 -1
- data/app/assets/javascripts/swaggard/lib/jsoneditor.min.js +0 -5
- data/app/assets/javascripts/swaggard/lib/lodash.min.js +0 -2
- data/app/assets/javascripts/swaggard/lib/marked.js +0 -1
- data/app/assets/javascripts/swaggard/lib/object-assign-pollyfill.js +0 -1
- data/app/assets/javascripts/swaggard/lib/swagger-oauth.js +0 -1
- data/app/assets/javascripts/swaggard/swaggard.js +0 -72
- data/app/assets/javascripts/swaggard/swagger-ui.js +0 -25378
- data/app/assets/javascripts/swaggard/translator.js +0 -39
- data/app/assets/stylesheets/swaggard/application.css +0 -16
- data/app/assets/stylesheets/swaggard/application_print.css +0 -15
- data/app/assets/stylesheets/swaggard/print.css.scss +0 -4
- data/app/assets/stylesheets/swaggard/reset.css +0 -1
- data/app/assets/stylesheets/swaggard/screen.css.scss +0 -4
- data/app/assets/stylesheets/swaggard/typography.css.scss +0 -0
|
@@ -14,14 +14,13 @@ module Swaggard
|
|
|
14
14
|
:error_responses, :tag
|
|
15
15
|
|
|
16
16
|
def initialize(yard_object, tag, path, verb, path_params)
|
|
17
|
-
@name = yard_object.name
|
|
17
|
+
@name = yard_object.name.to_s
|
|
18
18
|
@tag = tag
|
|
19
19
|
@summary = (yard_object.docstring.lines.first || '').chomp
|
|
20
20
|
@parameters = []
|
|
21
21
|
@responses = []
|
|
22
22
|
|
|
23
23
|
@description = (yard_object.docstring.lines[1..-1] || []).map(&:chomp).reject(&:empty?).compact.join("\n")
|
|
24
|
-
@formats = Swaggard.configuration.api_formats
|
|
25
24
|
@http_method = verb
|
|
26
25
|
@path = path
|
|
27
26
|
|
|
@@ -78,17 +77,26 @@ module Swaggard
|
|
|
78
77
|
end
|
|
79
78
|
|
|
80
79
|
def to_doc
|
|
81
|
-
{
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
'
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
80
|
+
regular_params = @parameters.reject { |p| p.is_a?(Parameters::Body) || p.is_a?(Parameters::Form) }
|
|
81
|
+
body_param = @parameters.find { |p| p.is_a?(Parameters::Body) }
|
|
82
|
+
form_params = @parameters.select { |p| p.is_a?(Parameters::Form) }
|
|
83
|
+
|
|
84
|
+
doc = {
|
|
85
|
+
'tags' => [@tag.name],
|
|
86
|
+
'operationId' => @operation_id || @name,
|
|
87
|
+
'summary' => @summary,
|
|
88
|
+
'description' => @description,
|
|
89
|
+
'parameters' => regular_params.map(&:to_doc),
|
|
90
|
+
'responses' => Hash[@responses.map { |response| [response.status_code, response.to_doc] }]
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
if body_param && !body_param.empty?
|
|
94
|
+
doc['requestBody'] = body_param.to_request_body
|
|
95
|
+
elsif form_params.any?
|
|
96
|
+
doc['requestBody'] = build_form_request_body(form_params)
|
|
91
97
|
end
|
|
98
|
+
|
|
99
|
+
doc
|
|
92
100
|
end
|
|
93
101
|
|
|
94
102
|
def definitions
|
|
@@ -117,6 +125,18 @@ module Swaggard
|
|
|
117
125
|
@body_parameter
|
|
118
126
|
end
|
|
119
127
|
|
|
128
|
+
def build_form_request_body(form_params)
|
|
129
|
+
properties = form_params.each_with_object({}) do |param, props|
|
|
130
|
+
props[param.name] = param.form_property_doc
|
|
131
|
+
end
|
|
132
|
+
required = form_params.select(&:is_required?).map(&:name)
|
|
133
|
+
|
|
134
|
+
schema = { 'type' => 'object', 'properties' => properties }
|
|
135
|
+
schema['required'] = required if required.any?
|
|
136
|
+
|
|
137
|
+
{ 'content' => { 'application/x-www-form-urlencoded' => { 'schema' => schema } } }
|
|
138
|
+
end
|
|
139
|
+
|
|
120
140
|
def build_path_parameters(path_params)
|
|
121
141
|
return unless @tag.controller_class
|
|
122
142
|
|
|
@@ -7,13 +7,14 @@ module Swaggard
|
|
|
7
7
|
attr_writer :is_required
|
|
8
8
|
|
|
9
9
|
def to_doc
|
|
10
|
-
{
|
|
11
|
-
'name'
|
|
12
|
-
'in'
|
|
13
|
-
'required'
|
|
14
|
-
'
|
|
15
|
-
'description' => description
|
|
10
|
+
doc = {
|
|
11
|
+
'name' => @name,
|
|
12
|
+
'in' => @in,
|
|
13
|
+
'required' => @is_required,
|
|
14
|
+
'description' => description
|
|
16
15
|
}
|
|
16
|
+
doc['schema'] = { 'type' => @data_type } if @data_type
|
|
17
|
+
doc
|
|
17
18
|
end
|
|
18
19
|
|
|
19
20
|
end
|
|
@@ -25,15 +25,15 @@ module Swaggard
|
|
|
25
25
|
@definition.empty?
|
|
26
26
|
end
|
|
27
27
|
|
|
28
|
-
def
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
28
|
+
def to_request_body
|
|
29
|
+
{
|
|
30
|
+
'required' => @is_required,
|
|
31
|
+
'content' => {
|
|
32
|
+
'application/json' => {
|
|
33
|
+
'schema' => { '$ref' => "#/components/schemas/#{Swaggard.ref_name(@definition_id)}" }
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
37
|
end
|
|
38
38
|
|
|
39
39
|
def description=(description)
|
|
@@ -6,10 +6,19 @@ module Swaggard
|
|
|
6
6
|
class Form < Base
|
|
7
7
|
|
|
8
8
|
def initialize(string)
|
|
9
|
-
@in = 'formData'
|
|
10
9
|
parse(string)
|
|
11
10
|
end
|
|
12
11
|
|
|
12
|
+
def is_required?
|
|
13
|
+
@is_required
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
def form_property_doc
|
|
17
|
+
doc = { 'type' => @data_type }
|
|
18
|
+
doc['description'] = @description if @description.present?
|
|
19
|
+
doc
|
|
20
|
+
end
|
|
21
|
+
|
|
13
22
|
private
|
|
14
23
|
|
|
15
24
|
# Example: [Array] status Filter by status. (e.g. status[]=1&status[]=2&status[]=3)
|
|
@@ -11,14 +11,12 @@ module Swaggard
|
|
|
11
11
|
|
|
12
12
|
def to_doc
|
|
13
13
|
doc = super
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
{
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
}
|
|
21
|
-
)
|
|
14
|
+
doc['schema'] = {
|
|
15
|
+
'type' => 'array',
|
|
16
|
+
'items' => { 'type' => @data_type },
|
|
17
|
+
'enum' => @list_values
|
|
18
|
+
}
|
|
19
|
+
doc
|
|
22
20
|
end
|
|
23
21
|
|
|
24
22
|
private
|
|
@@ -11,16 +11,16 @@ module Swaggard
|
|
|
11
11
|
end
|
|
12
12
|
|
|
13
13
|
def to_doc
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
'in' => @in,
|
|
17
|
-
'required' => @is_required,
|
|
18
|
-
}.tap do |doc|
|
|
19
|
-
doc.merge!(@type.to_doc)
|
|
14
|
+
schema = @type.to_doc
|
|
15
|
+
schema['enum'] = @options if @options.any?
|
|
20
16
|
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
17
|
+
{
|
|
18
|
+
'name' => @name,
|
|
19
|
+
'in' => @in,
|
|
20
|
+
'required' => @is_required,
|
|
21
|
+
'description' => description,
|
|
22
|
+
'schema' => schema
|
|
23
|
+
}
|
|
24
24
|
end
|
|
25
25
|
|
|
26
26
|
private
|
|
@@ -50,13 +50,20 @@ module Swaggard
|
|
|
50
50
|
def to_doc
|
|
51
51
|
{ 'description' => description }.tap do |doc|
|
|
52
52
|
schema = if @response_root.present?
|
|
53
|
-
{ '$ref' => "#/
|
|
53
|
+
{ '$ref' => "#/components/schemas/#{Swaggard.ref_name(definition.id)}" }
|
|
54
54
|
elsif @response_model.response_class.present?
|
|
55
55
|
@response_model.to_doc
|
|
56
56
|
end
|
|
57
57
|
|
|
58
|
-
|
|
59
|
-
|
|
58
|
+
if schema || @example
|
|
59
|
+
media_type_object = {}
|
|
60
|
+
media_type_object['schema'] = schema if schema
|
|
61
|
+
media_type_object['example'] = example_to_doc if @example
|
|
62
|
+
doc['content'] = Swaggard.configuration.api_formats.each_with_object({}) do |format, content|
|
|
63
|
+
content["application/#{format}"] = media_type_object
|
|
64
|
+
end
|
|
65
|
+
end
|
|
66
|
+
|
|
60
67
|
if @headers.any?
|
|
61
68
|
doc['headers'] = Hash[@headers.map { |header| [header.name, header.to_doc] }]
|
|
62
69
|
end
|
|
@@ -64,10 +71,10 @@ module Swaggard
|
|
|
64
71
|
end
|
|
65
72
|
|
|
66
73
|
def example_to_doc
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
74
|
+
if File.exist?(@example)
|
|
75
|
+
JSON.parse(File.read(@example))
|
|
76
|
+
else
|
|
77
|
+
{ '$ref' => @example }
|
|
71
78
|
end
|
|
72
79
|
end
|
|
73
80
|
|
|
@@ -100,7 +107,7 @@ module Swaggard
|
|
|
100
107
|
if PRIMITIVE_TYPES.include?(@response_class)
|
|
101
108
|
{ 'type' => @response_class }
|
|
102
109
|
else
|
|
103
|
-
{ '$ref' => "#/
|
|
110
|
+
{ '$ref' => "#/components/schemas/#{Swaggard.ref_name(@response_class)}" }
|
|
104
111
|
end
|
|
105
112
|
end
|
|
106
113
|
end
|
|
@@ -46,9 +46,9 @@ module Swaggard
|
|
|
46
46
|
if basic_type?
|
|
47
47
|
BASIC_TYPES[@name.downcase].dup
|
|
48
48
|
elsif custom_type?
|
|
49
|
-
Swaggard.
|
|
49
|
+
{ '$ref' => "#/components/schemas/#{Swaggard.ref_name(@name)}" }
|
|
50
50
|
else
|
|
51
|
-
{ '$ref' => "#/
|
|
51
|
+
{ '$ref' => "#/components/schemas/#{Swaggard.ref_name(name)}" }
|
|
52
52
|
end
|
|
53
53
|
end
|
|
54
54
|
end
|
data/lib/swaggard/version.rb
CHANGED
data/lib/swaggard.rb
CHANGED
|
@@ -41,12 +41,20 @@ module Swaggard
|
|
|
41
41
|
::YARD::Tags::Library.define_tag('Ignore inherited attributes', :ignore_inherited)
|
|
42
42
|
end
|
|
43
43
|
|
|
44
|
+
# Sanitize a name for use as an OpenAPI component key and $ref fragment.
|
|
45
|
+
# Keys must match ^[a-zA-Z0-9\.\-_]+$ per the OAS 3.1 spec.
|
|
46
|
+
def ref_name(name)
|
|
47
|
+
name.to_s.gsub('::', '.').gsub('#', '_')
|
|
48
|
+
end
|
|
49
|
+
|
|
44
50
|
def get_doc(host = nil)
|
|
45
51
|
load!
|
|
46
52
|
|
|
47
53
|
doc = @api.to_doc
|
|
48
54
|
|
|
49
|
-
|
|
55
|
+
if host && configuration.host.blank?
|
|
56
|
+
doc['servers'] = [{ 'url' => "#{configuration.schemes.first}://#{host}#{configuration.api_base_path}" }]
|
|
57
|
+
end
|
|
50
58
|
|
|
51
59
|
doc
|
|
52
60
|
end
|
data/spec/fixtures/api.json
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"
|
|
1
|
+
{"openapi":"3.1.0","info":{"version":"0.1","title":"","description":"","contact":{"name":""},"license":{"name":""}},"servers":[{"url":"https://localhost:3000/"}],"tags":[{"name":"admin/pets","description":"This document describes the API for interacting with Pet resources"},{"name":"pets","description":"This document describes the API for interacting with Pet resources"}],"paths":{"/admin/pets":{"get":{"tags":["admin/pets"],"operationId":"index","summary":"return a list of Pets","description":"","parameters":[],"responses":{"default":{"description":"successful operation"}}}},"/pets":{"get":{"tags":["pets"],"operationId":"index","summary":"return a list of Pets","description":"","parameters":[],"responses":{"default":{"description":"successful operation"}}}},"/pets/{id}":{"get":{"tags":["pets"],"operationId":"show","summary":"return a Pet","description":"","parameters":[{"name":"id","in":"path","required":true,"description":"Scope response to id","schema":{"type":"string"}},{"name":"id","in":"query","required":false,"description":"The ID for the Pet","schema":{"type":"integer","format":"int32"}}],"responses":{"default":{"description":"successful operation"}}}}}}
|