apia-open_api 0.1.8 → 0.1.9
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/lib/apia/open_api/objects/path.rb +46 -3
- data/lib/apia/open_api/rack.rb +1 -1
- data/lib/apia/open_api/specification.rb +69 -1
- data/lib/apia/open_api/version.rb +1 -1
- metadata +1 -1
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: ab4263122239dfce8e477f4279cbe4a03743f0e6fa4c1236c0480082d517ec8c
|
4
|
+
data.tar.gz: 8542223956ac7fc5fc4817cc627c0d5ec96876cd1f671a4e26422deae3818387
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 05131ea1ca348bce2d637314eba336e07bb4553f71ef3fd107c23ee854f107f09b26d24c0cdfdebb259ef450421bbcdc8864b6ac8fc057e32ac8570d590f24eb
|
7
|
+
data.tar.gz: 95cad90b7979f85e4cc085bb25ea7f33583766f8b05ef94a8ac91a93701e27e6b757bc3e63141211a9fab5dad16f57872b98dd3ad1c5a77fefa4c25c9b4f3bb1
|
@@ -36,20 +36,29 @@ module Apia
|
|
36
36
|
@api_authenticator = api_authenticator
|
37
37
|
@route_spec = {
|
38
38
|
operationId: convert_route_to_id,
|
39
|
-
|
39
|
+
summary: @route.endpoint.definition.name,
|
40
|
+
description: @route.endpoint.definition.description,
|
41
|
+
tags: route.group ? get_group_tags(route.group) : [name]
|
40
42
|
}
|
41
43
|
end
|
42
44
|
|
43
45
|
def add_to_spec
|
46
|
+
add_scopes_description
|
44
47
|
path = @route.path
|
48
|
+
|
45
49
|
if @route.request_method == :get
|
46
50
|
add_parameters
|
47
51
|
else
|
48
52
|
add_request_body
|
49
53
|
end
|
50
54
|
|
51
|
-
|
52
|
-
|
55
|
+
path = "/#{path}"
|
56
|
+
# Remove the `:` from the url parameters in the path
|
57
|
+
# This is because some tools based on the OpenAPI spec don't like the `:` in the path
|
58
|
+
path = path.gsub(/:([^\/]+)/, '\1')
|
59
|
+
|
60
|
+
@spec[:paths][path] ||= {}
|
61
|
+
@spec[:paths][path][@route.request_method.to_s] = @route_spec
|
53
62
|
|
54
63
|
add_responses
|
55
64
|
end
|
@@ -79,6 +88,24 @@ module Apia
|
|
79
88
|
).add_to_spec
|
80
89
|
end
|
81
90
|
|
91
|
+
# Adds a description of the scopes to the route specification.
|
92
|
+
#
|
93
|
+
# This method checks if the route's endpoint definition has any scopes.
|
94
|
+
# If there are scopes, it appends a description of the scopes to the existing route specification description.
|
95
|
+
# The description of the scopes is formatted as a markdown list, with each scope represented as a bullet point.
|
96
|
+
def add_scopes_description
|
97
|
+
return unless @route.endpoint.definition.scopes.any?
|
98
|
+
|
99
|
+
@route_spec[:description] =
|
100
|
+
<<~DESCRIPTION
|
101
|
+
#{@route_spec[:description]}
|
102
|
+
## Scopes
|
103
|
+
#{@route.endpoint.definition.scopes.map do |scope|
|
104
|
+
"- `#{scope}`"
|
105
|
+
end.join("\n")}
|
106
|
+
DESCRIPTION
|
107
|
+
end
|
108
|
+
|
82
109
|
# It's worth creating a 'nice' operationId for each route, as this is used as the
|
83
110
|
# basis for the method name when calling the endpoint using a generated client.
|
84
111
|
def convert_route_to_id
|
@@ -126,6 +153,22 @@ module Apia
|
|
126
153
|
"#{first_part}#{last_part}"
|
127
154
|
end
|
128
155
|
|
156
|
+
# Returns an array of tags representing the group hierarchy for a given group.
|
157
|
+
#
|
158
|
+
# @param group [Group] The group for which to retrieve the tags.
|
159
|
+
# @return [Array<String>] An array of tags representing the group hierarchy.
|
160
|
+
def get_group_tags(group)
|
161
|
+
tags = []
|
162
|
+
current_group = group
|
163
|
+
|
164
|
+
while current_group
|
165
|
+
tags.unshift(current_group.name)
|
166
|
+
current_group = current_group.parent
|
167
|
+
end
|
168
|
+
|
169
|
+
tags
|
170
|
+
end
|
171
|
+
|
129
172
|
end
|
130
173
|
end
|
131
174
|
end
|
data/lib/apia/open_api/rack.rb
CHANGED
@@ -41,7 +41,7 @@ module Apia
|
|
41
41
|
specification = Specification.new(api_class, base_url, @options[:name])
|
42
42
|
body = specification.json
|
43
43
|
|
44
|
-
[200, { "
|
44
|
+
[200, { "content-type" => "application/json", "content-length" => body.bytesize.to_s }, [body]]
|
45
45
|
end
|
46
46
|
|
47
47
|
end
|
@@ -26,7 +26,9 @@ module Apia
|
|
26
26
|
components: {
|
27
27
|
schemas: {}
|
28
28
|
},
|
29
|
-
security: []
|
29
|
+
security: [],
|
30
|
+
tags: [],
|
31
|
+
"x-tagGroups": []
|
30
32
|
}
|
31
33
|
|
32
34
|
# path_ids is used to keep track of all the IDs of all the paths we've generated, to avoid duplicates
|
@@ -41,11 +43,20 @@ module Apia
|
|
41
43
|
|
42
44
|
private
|
43
45
|
|
46
|
+
def sort_hash_by_nested_tag(hash)
|
47
|
+
hash.sort_by do |_, nested_hash|
|
48
|
+
nested_hash.values.first[:tags]&.first
|
49
|
+
end.to_h
|
50
|
+
end
|
51
|
+
|
44
52
|
def build_spec
|
45
53
|
add_info
|
46
54
|
add_servers
|
47
55
|
add_paths
|
48
56
|
add_security
|
57
|
+
add_tag_groups
|
58
|
+
|
59
|
+
@spec[:paths] = sort_hash_by_nested_tag(@spec[:paths])
|
49
60
|
end
|
50
61
|
|
51
62
|
def add_info
|
@@ -85,6 +96,63 @@ module Apia
|
|
85
96
|
end
|
86
97
|
end
|
87
98
|
|
99
|
+
def get_tag_group_index(tag)
|
100
|
+
@spec[:"x-tagGroups"].each_with_index do |group, index|
|
101
|
+
return index if !group.nil? && group[:name] == tag
|
102
|
+
end
|
103
|
+
|
104
|
+
nil
|
105
|
+
end
|
106
|
+
|
107
|
+
# Adds tag groups to the OpenAPI specification.
|
108
|
+
#
|
109
|
+
# This method iterates over the paths in the specification and adds tag groups
|
110
|
+
# based on the tags specified for each method.
|
111
|
+
# It ensures that each tag is included in the `tags` array of the specification,
|
112
|
+
# and creates tag groups based on the order of the tags.
|
113
|
+
# Tag groups are represented by the `x-tagGroups` property in the specification.
|
114
|
+
# Tag groups are nested groups and are used to group tags together in documentation.
|
115
|
+
# A Tag *must* be included in a tag group. So if it is not part of a group / has no parent tag,
|
116
|
+
# it will be added to a group with the same name as the tag.
|
117
|
+
#
|
118
|
+
# @return [void]
|
119
|
+
def add_tag_groups
|
120
|
+
@spec[:paths].each_value do |methods|
|
121
|
+
methods.each_value do |method_spec|
|
122
|
+
method_spec[:tags].each_with_index do |tag, tag_index|
|
123
|
+
unless @spec[:tags].any? { |t| t[:name] == tag }
|
124
|
+
@spec[:tags] << { name: tag }
|
125
|
+
end
|
126
|
+
|
127
|
+
next if tag_index.zero?
|
128
|
+
|
129
|
+
tags = method_spec[:tags]
|
130
|
+
|
131
|
+
parent_tag = tags[tag_index - 1]
|
132
|
+
parent_index = get_tag_group_index(parent_tag)
|
133
|
+
|
134
|
+
if parent_index.nil? && tags.size > 1
|
135
|
+
@spec[:"x-tagGroups"] << { name: parent_tag, tags: [parent_tag] }
|
136
|
+
parent_index = @spec[:"x-tagGroups"].size - 1
|
137
|
+
end
|
138
|
+
|
139
|
+
unless @spec[:"x-tagGroups"][parent_index][:tags].include?(tag)
|
140
|
+
@spec[:"x-tagGroups"][parent_index][:tags] << tag
|
141
|
+
end
|
142
|
+
end
|
143
|
+
end
|
144
|
+
end
|
145
|
+
|
146
|
+
@spec[:tags].each do |tag|
|
147
|
+
unless @spec[:"x-tagGroups"].any? { |group| group[:tags].include?(tag[:name]) }
|
148
|
+
@spec[:"x-tagGroups"] << { name: tag[:name], tags: [tag[:name]] }
|
149
|
+
end
|
150
|
+
end
|
151
|
+
|
152
|
+
@spec[:"x-tagGroups"].sort_by! { |group| group[:name] }
|
153
|
+
@spec[:"x-tagGroups"].each { |group| group[:tags].sort! }
|
154
|
+
end
|
155
|
+
|
88
156
|
end
|
89
157
|
end
|
90
158
|
end
|