jsapi 1.2 → 1.4
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/jsapi/configuration.rb +2 -2
- data/lib/jsapi/controller/methods.rb +17 -4
- data/lib/jsapi/controller/parameters.rb +26 -13
- data/lib/jsapi/controller/response.rb +29 -5
- data/lib/jsapi/dsl/class_methods.rb +11 -0
- data/lib/jsapi/dsl/definitions.rb +14 -0
- data/lib/jsapi/dsl/path.rb +43 -0
- data/lib/jsapi/dsl.rb +1 -0
- data/lib/jsapi/meta/callback/base.rb +1 -1
- data/lib/jsapi/meta/definitions.rb +98 -24
- data/lib/jsapi/meta/example/base.rb +4 -6
- data/lib/jsapi/meta/link/base.rb +4 -2
- data/lib/jsapi/meta/oauth_flow.rb +11 -2
- data/lib/jsapi/meta/openapi/path_item.rb +68 -0
- data/lib/jsapi/meta/openapi/version.rb +6 -0
- data/lib/jsapi/meta/openapi.rb +2 -0
- data/lib/jsapi/meta/operation.rb +29 -17
- data/lib/jsapi/meta/parameter/base.rb +82 -59
- data/lib/jsapi/meta/path.rb +56 -0
- data/lib/jsapi/meta/pathname.rb +60 -0
- data/lib/jsapi/meta/request_body/base.rb +3 -2
- data/lib/jsapi/meta/response/base.rb +26 -8
- data/lib/jsapi/meta/schema/base.rb +1 -1
- data/lib/jsapi/meta/schema/discriminator.rb +14 -4
- data/lib/jsapi/meta/schema/object.rb +28 -9
- data/lib/jsapi/meta/schema/validation/maximum.rb +1 -1
- data/lib/jsapi/meta/schema/validation/minimum.rb +1 -1
- data/lib/jsapi/meta/security_scheme/api_key.rb +4 -5
- data/lib/jsapi/meta/security_scheme/base.rb +16 -0
- data/lib/jsapi/meta/security_scheme/http/basic.rb +3 -10
- data/lib/jsapi/meta/security_scheme/http/bearer.rb +8 -8
- data/lib/jsapi/meta/security_scheme/http/other.rb +3 -5
- data/lib/jsapi/meta/security_scheme/mutual_tls.rb +23 -0
- data/lib/jsapi/meta/security_scheme/oauth2.rb +29 -13
- data/lib/jsapi/meta/security_scheme/open_id_connect.rb +5 -8
- data/lib/jsapi/meta/security_scheme.rb +3 -0
- data/lib/jsapi/meta/server.rb +9 -1
- data/lib/jsapi/meta/tag.rb +34 -4
- data/lib/jsapi/meta.rb +2 -0
- data/lib/jsapi/version.rb +1 -1
- metadata +7 -2
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 87f305e41facfb84c96e5e2406b636aa9e10a27545a25d42a5029f4d4dd93488
|
|
4
|
+
data.tar.gz: 6723179cd4981c590a4e8f0c45808d9b69a0436be48e1e89f06c7ef0a4b56ddb
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 7ddefbaaa678ed70e29055dbe4452ee0f4f738fa2386e8e3f5dbaa42e682ca973fa0bd04e5c6b22b2570bfd290fd4fcfbb42c8f7e50650ffda50d0cfbb160cc7
|
|
7
|
+
data.tar.gz: 3fc210ea9c236f319f1c94dcb741d7d910eb7edb90020aafcbbee2a033bd232a9bb88dd26fc306869f7c3be715487f4655a517e5968f63461a6bbad57074099a
|
data/lib/jsapi/configuration.rb
CHANGED
|
@@ -4,11 +4,11 @@ module Jsapi
|
|
|
4
4
|
# Holds the \Jsapi configuration.
|
|
5
5
|
class Configuration
|
|
6
6
|
# The path where the API definitions are located relative to +Rails.root+.
|
|
7
|
-
# The default is <code>"
|
|
7
|
+
# The default is <code>"jsapi/api_defs"</code>.
|
|
8
8
|
attr_accessor :api_defs_path
|
|
9
9
|
|
|
10
10
|
def initialize # :nodoc:
|
|
11
|
-
@api_defs_path = '
|
|
11
|
+
@api_defs_path = 'jsapi/api_defs'
|
|
12
12
|
end
|
|
13
13
|
|
|
14
14
|
# Returns the absolute +Pathname+ for +args+ within +api_defs_path+.
|
|
@@ -15,7 +15,9 @@ module Jsapi
|
|
|
15
15
|
# Performs an API operation by calling the given block. The request parameters are
|
|
16
16
|
# passed as an instance of the operation's model class to the block. The object
|
|
17
17
|
# returned by the block is implicitly rendered according to the appropriate +response+
|
|
18
|
-
# specification when the content type is a JSON MIME type.
|
|
18
|
+
# specification when the content type is a JSON MIME type. When content type is
|
|
19
|
+
# <code>application/json-seq</code>, the object returned by the block is streamed in
|
|
20
|
+
# JSON sequence text format.
|
|
19
21
|
#
|
|
20
22
|
# api_operation('foo') do |api_params|
|
|
21
23
|
# # ...
|
|
@@ -153,18 +155,29 @@ module Jsapi
|
|
|
153
155
|
end
|
|
154
156
|
|
|
155
157
|
# Write response
|
|
156
|
-
return unless response_model.json_type?
|
|
158
|
+
return unless response_model.json_type? || response_model.json_seq_type?
|
|
157
159
|
|
|
158
160
|
response = Response.new(result, response_model, definitions, omit: omit)
|
|
159
161
|
self.content_type = response_model.content_type
|
|
160
|
-
|
|
162
|
+
|
|
163
|
+
if response_model.json_seq_type?
|
|
164
|
+
self.response.status = status
|
|
165
|
+
|
|
166
|
+
self.response.stream.tap do |stream|
|
|
167
|
+
response.write_json_seq_to(stream)
|
|
168
|
+
ensure
|
|
169
|
+
stream.close
|
|
170
|
+
end
|
|
171
|
+
else
|
|
172
|
+
render(json: response, status: status)
|
|
173
|
+
end
|
|
161
174
|
end
|
|
162
175
|
|
|
163
176
|
def _api_params(operation, definitions, strong:)
|
|
164
177
|
(operation.model || Model::Base).new(
|
|
165
178
|
Parameters.new(
|
|
166
179
|
params.except(:action, :controller, :format).permit!,
|
|
167
|
-
request
|
|
180
|
+
request,
|
|
168
181
|
operation,
|
|
169
182
|
definitions,
|
|
170
183
|
strong: strong
|
|
@@ -14,18 +14,30 @@ module Jsapi
|
|
|
14
14
|
# If +strong+ is true+ parameters that can be mapped are accepted only. That means that
|
|
15
15
|
# the instance created is invalid if +params+ contains any parameters that can't be
|
|
16
16
|
# mapped to a parameter or a request body property of +operation+.
|
|
17
|
-
def initialize(params,
|
|
18
|
-
|
|
19
|
-
|
|
17
|
+
def initialize(params, request, operation, definitions, strong: false)
|
|
18
|
+
params = params.to_h
|
|
19
|
+
unassigned_params = params.dup
|
|
20
|
+
|
|
21
|
+
@params_to_be_validated = strong == true ? params.dup : {}
|
|
20
22
|
@raw_attributes = {}
|
|
21
|
-
@raw_additional_attributes = {}
|
|
22
23
|
|
|
23
24
|
# Parameters
|
|
24
|
-
operation.
|
|
25
|
-
parameter_model = parameter_model.resolve(definitions)
|
|
26
|
-
|
|
25
|
+
operation.resolved_parameters(definitions).each do |name, parameter_model|
|
|
27
26
|
@raw_attributes[name] = JSON.wrap(
|
|
28
|
-
parameter_model.in
|
|
27
|
+
case parameter_model.in
|
|
28
|
+
when 'header'
|
|
29
|
+
request.headers[name]
|
|
30
|
+
when 'querystring'
|
|
31
|
+
query_params = request.query_parameters
|
|
32
|
+
keys = query_params.keys
|
|
33
|
+
|
|
34
|
+
unassigned_params.except!(*keys)
|
|
35
|
+
@params_to_be_validated.except!(*keys)
|
|
36
|
+
|
|
37
|
+
parameter_model.object? ? params.slice(*keys) : query_params.to_query
|
|
38
|
+
else
|
|
39
|
+
unassigned_params.delete(name)
|
|
40
|
+
end,
|
|
29
41
|
parameter_model.schema.resolve(definitions),
|
|
30
42
|
definitions,
|
|
31
43
|
context: :request
|
|
@@ -37,23 +49,24 @@ module Jsapi
|
|
|
37
49
|
&.schema&.resolve(definitions)
|
|
38
50
|
if request_body_schema&.object?
|
|
39
51
|
request_body = JSON.wrap(
|
|
40
|
-
|
|
52
|
+
unassigned_params,
|
|
41
53
|
request_body_schema,
|
|
42
54
|
definitions,
|
|
43
55
|
context: :request
|
|
44
56
|
)
|
|
45
57
|
@raw_attributes.merge!(request_body.raw_attributes)
|
|
46
58
|
@raw_additional_attributes = request_body.raw_additional_attributes
|
|
59
|
+
@params_to_be_validated.except!(*@raw_additional_attributes.keys)
|
|
60
|
+
else
|
|
61
|
+
@raw_additional_attributes = {}
|
|
47
62
|
end
|
|
48
63
|
end
|
|
49
64
|
|
|
50
65
|
# Validates the request parameters. Returns true if the parameters are valid, false
|
|
51
66
|
# otherwise. Detected errors are added to +errors+.
|
|
52
67
|
def validate(errors)
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
!@strong || validate_parameters(@params, attributes, errors)
|
|
56
|
-
].all?
|
|
68
|
+
validate_attributes(errors) &&
|
|
69
|
+
validate_parameters(@params_to_be_validated, attributes, errors)
|
|
57
70
|
end
|
|
58
71
|
|
|
59
72
|
private
|
|
@@ -50,11 +50,27 @@ module Jsapi
|
|
|
50
50
|
# Returns the \JSON representation of the response as a string.
|
|
51
51
|
def to_json(*)
|
|
52
52
|
schema = @response.schema.resolve(@definitions)
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
53
|
+
with_locale { jsonify(@object, schema) }.to_json
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
# Writes the response in \JSON sequence text format to +stream+.
|
|
57
|
+
def write_json_seq_to(stream)
|
|
58
|
+
schema = @response.schema.resolve(@definitions)
|
|
59
|
+
with_locale do
|
|
60
|
+
items, item_schema =
|
|
61
|
+
if schema.array? && @object.respond_to?(:each)
|
|
62
|
+
[@object, schema.items.resolve(@definitions)]
|
|
63
|
+
else
|
|
64
|
+
[[@object], schema]
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
items.each do |item|
|
|
68
|
+
stream.write("\u001E") # Record separator (see RFC 7464)
|
|
69
|
+
stream.write(jsonify(item, item_schema).to_json)
|
|
70
|
+
stream.write("\n")
|
|
71
|
+
end
|
|
72
|
+
end
|
|
73
|
+
nil
|
|
58
74
|
end
|
|
59
75
|
|
|
60
76
|
private
|
|
@@ -138,6 +154,14 @@ module Jsapi
|
|
|
138
154
|
|
|
139
155
|
properties.presence
|
|
140
156
|
end
|
|
157
|
+
|
|
158
|
+
def with_locale(&block)
|
|
159
|
+
if @response.locale
|
|
160
|
+
I18n.with_locale(@response.locale, &block)
|
|
161
|
+
else
|
|
162
|
+
yield
|
|
163
|
+
end
|
|
164
|
+
end
|
|
141
165
|
end
|
|
142
166
|
end
|
|
143
167
|
end
|
|
@@ -147,6 +147,17 @@ module Jsapi
|
|
|
147
147
|
api_definitions { parameter(name, **keywords, &block) }
|
|
148
148
|
end
|
|
149
149
|
|
|
150
|
+
# Groups operations by path.
|
|
151
|
+
#
|
|
152
|
+
# api_path 'api' do
|
|
153
|
+
# operation 'foo'
|
|
154
|
+
# operation 'bar'
|
|
155
|
+
# end
|
|
156
|
+
#
|
|
157
|
+
def api_path(name, &block)
|
|
158
|
+
api_definitions { path(name, &block) }
|
|
159
|
+
end
|
|
160
|
+
|
|
150
161
|
# Defines a reusable request body.
|
|
151
162
|
#
|
|
152
163
|
# api_request_body 'foo', type: 'string'
|
|
@@ -155,6 +155,20 @@ module Jsapi
|
|
|
155
155
|
end
|
|
156
156
|
end
|
|
157
157
|
|
|
158
|
+
# Groups operations by path.
|
|
159
|
+
#
|
|
160
|
+
# path 'api' do
|
|
161
|
+
# operation 'foo'
|
|
162
|
+
# operation 'bar'
|
|
163
|
+
# end
|
|
164
|
+
#
|
|
165
|
+
def path(name = nil, &block)
|
|
166
|
+
define('path', name&.inspect) do
|
|
167
|
+
path_model = @meta_model.add_path(name)
|
|
168
|
+
Path.new(path_model, &block) if block
|
|
169
|
+
end
|
|
170
|
+
end
|
|
171
|
+
|
|
158
172
|
# Specifies a reusable request body.
|
|
159
173
|
#
|
|
160
174
|
# request_body 'foo', type: 'string'
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Jsapi
|
|
4
|
+
module DSL
|
|
5
|
+
class Path < Base
|
|
6
|
+
# Specifies an operation within the current path.
|
|
7
|
+
#
|
|
8
|
+
# operation 'foo' do
|
|
9
|
+
# parameter 'bar', type: 'string'
|
|
10
|
+
# response do
|
|
11
|
+
# property 'foo', type: 'string'
|
|
12
|
+
# end
|
|
13
|
+
# end
|
|
14
|
+
#
|
|
15
|
+
def operation(name = nil, **keywords, &block)
|
|
16
|
+
define('operation', name&.inspect) do
|
|
17
|
+
operation_model = @meta_model.owner.add_operation(name, @meta_model.name, keywords)
|
|
18
|
+
Operation.new(operation_model, &block) if block
|
|
19
|
+
end
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
# Specifies a parameter applicable for all operations in this path.
|
|
23
|
+
#
|
|
24
|
+
# parameter 'foo', type: 'string'
|
|
25
|
+
#
|
|
26
|
+
# See Meta::Path#parameters for further information.
|
|
27
|
+
def parameter(name, **keywords, &block)
|
|
28
|
+
define('parameter', name.inspect) do
|
|
29
|
+
parameter_model = @meta_model.add_parameter(name, keywords)
|
|
30
|
+
Parameter.new(parameter_model, &block) if block
|
|
31
|
+
end
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
# Specifies a nested path.
|
|
35
|
+
def path(name = nil, &block)
|
|
36
|
+
define('path', name&.inspect) do
|
|
37
|
+
path_model = @meta_model.owner.add_path(@meta_model.name + name.to_s)
|
|
38
|
+
Path.new(path_model, &block) if block
|
|
39
|
+
end
|
|
40
|
+
end
|
|
41
|
+
end
|
|
42
|
+
end
|
|
43
|
+
end
|
data/lib/jsapi/dsl.rb
CHANGED
|
@@ -23,7 +23,7 @@ module Jsapi
|
|
|
23
23
|
# Returns a hash representing the \OpenAPI callback object.
|
|
24
24
|
def to_openapi(version, definitions)
|
|
25
25
|
operations.transform_values do |operation|
|
|
26
|
-
|
|
26
|
+
OpenAPI::PathItem.new([operation]).to_openapi(version, definitions)
|
|
27
27
|
end
|
|
28
28
|
end
|
|
29
29
|
end
|
|
@@ -8,7 +8,7 @@ module Jsapi
|
|
|
8
8
|
##
|
|
9
9
|
# :attr: base_path
|
|
10
10
|
# The base path of the API. Applies to \OpenAPI 2.0.
|
|
11
|
-
attribute :base_path,
|
|
11
|
+
attribute :base_path, Pathname
|
|
12
12
|
|
|
13
13
|
##
|
|
14
14
|
# :attr: callbacks
|
|
@@ -65,6 +65,11 @@ module Jsapi
|
|
|
65
65
|
# The reusable Parameter objects.
|
|
66
66
|
attribute :parameters, { String => Parameter }, accessors: %i[reader writer]
|
|
67
67
|
|
|
68
|
+
##
|
|
69
|
+
# :attr: paths
|
|
70
|
+
# The Path objects.
|
|
71
|
+
attribute :paths, { Pathname => Path }, accessors: %i[reader writer]
|
|
72
|
+
|
|
68
73
|
##
|
|
69
74
|
# :attr: rescue_handlers
|
|
70
75
|
# The RescueHandler objects.
|
|
@@ -138,15 +143,27 @@ module Jsapi
|
|
|
138
143
|
@parent&.inherited(self)
|
|
139
144
|
end
|
|
140
145
|
|
|
141
|
-
def add_operation(name = nil, keywords = {}) # :nodoc:
|
|
146
|
+
def add_operation(name, parent_path = nil, keywords = {}) # :nodoc:
|
|
147
|
+
parent_path, keywords = nil, parent_path if parent_path.is_a?(Hash)
|
|
148
|
+
|
|
142
149
|
name = name.nil? ? default_operation_name : name.to_s
|
|
143
|
-
|
|
144
|
-
|
|
150
|
+
parent_path ||= default_operation_name unless keywords[:path].present?
|
|
151
|
+
|
|
152
|
+
(@operations ||= {})[name] = Operation.new(name, parent_path, keywords)
|
|
145
153
|
end
|
|
146
154
|
|
|
147
155
|
def add_parameter(name, keywords = {}) # :nodoc:
|
|
148
156
|
name = name.to_s
|
|
149
|
-
|
|
157
|
+
|
|
158
|
+
Parameter.new(name, keywords).tap do |parameter|
|
|
159
|
+
(@parameters ||= {})[name] = parameter
|
|
160
|
+
attribute_changed(:parameters)
|
|
161
|
+
end
|
|
162
|
+
end
|
|
163
|
+
|
|
164
|
+
def add_path(name, keywords = {}) # :nodoc:
|
|
165
|
+
pathname = Pathname.from(name)
|
|
166
|
+
(@paths ||= {})[pathname] ||= Path.new(pathname, self, keywords)
|
|
150
167
|
end
|
|
151
168
|
|
|
152
169
|
# Returns an array containing itself and all of the +Definitions+ instances
|
|
@@ -207,6 +224,14 @@ module Jsapi
|
|
|
207
224
|
self
|
|
208
225
|
end
|
|
209
226
|
|
|
227
|
+
# Resets the memoized parameters for the given path.
|
|
228
|
+
def invalidate_path_parameters(pathname)
|
|
229
|
+
pathname = Pathname.from(pathname)
|
|
230
|
+
|
|
231
|
+
@path_parameters&.delete(pathname)
|
|
232
|
+
each_descendant { |descendant| descendant.invalidate_path_parameters(pathname) }
|
|
233
|
+
end
|
|
234
|
+
|
|
210
235
|
# Returns a hash representing the \JSON \Schema document for +name+.
|
|
211
236
|
def json_schema_document(name)
|
|
212
237
|
find_schema(name)&.to_json_schema&.tap do |json_schema_document|
|
|
@@ -228,13 +253,18 @@ module Jsapi
|
|
|
228
253
|
version = OpenAPI::Version.from(version)
|
|
229
254
|
operations = objects[:operations].values
|
|
230
255
|
|
|
231
|
-
openapi_paths =
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
256
|
+
openapi_paths = operations.group_by(&:full_path).to_h do |key, value|
|
|
257
|
+
[
|
|
258
|
+
key.to_s,
|
|
259
|
+
OpenAPI::PathItem.new(
|
|
260
|
+
value,
|
|
261
|
+
description: path_description(key),
|
|
262
|
+
parameters: path_parameters(key),
|
|
263
|
+
summary: path_summary(key),
|
|
264
|
+
servers: path_servers(key)
|
|
265
|
+
).to_openapi(version, self)
|
|
266
|
+
]
|
|
267
|
+
end.presence
|
|
238
268
|
|
|
239
269
|
openapi_objects =
|
|
240
270
|
if version.major == 2
|
|
@@ -254,7 +284,7 @@ module Jsapi
|
|
|
254
284
|
swagger: '2.0',
|
|
255
285
|
info: openapi_objects[:info],
|
|
256
286
|
host: openapi_objects[:host] || uri&.hostname,
|
|
257
|
-
basePath: openapi_objects[:base_path] || uri&.path,
|
|
287
|
+
basePath: openapi_objects[:base_path]&.to_s || uri&.path,
|
|
258
288
|
schemes: openapi_objects[:schemes] || Array(uri&.scheme).presence,
|
|
259
289
|
consumes: operations.filter_map do |operation|
|
|
260
290
|
operation.consumes(self)
|
|
@@ -271,10 +301,16 @@ module Jsapi
|
|
|
271
301
|
else
|
|
272
302
|
{
|
|
273
303
|
# Order according to the OpenAPI specification 3.x
|
|
274
|
-
openapi:
|
|
304
|
+
openapi:
|
|
305
|
+
case version.minor
|
|
306
|
+
when 0 then '3.0.3'
|
|
307
|
+
when 1 then '3.1.1'
|
|
308
|
+
when 2 then '3.2.0'
|
|
309
|
+
end,
|
|
275
310
|
info: openapi_objects[:info],
|
|
276
|
-
servers:
|
|
277
|
-
[
|
|
311
|
+
servers:
|
|
312
|
+
openapi_objects[:servers] ||
|
|
313
|
+
[default_server&.to_openapi(version)].compact.presence,
|
|
278
314
|
paths: openapi_paths,
|
|
279
315
|
components: {
|
|
280
316
|
schemas: openapi_objects[:schemas],
|
|
@@ -296,6 +332,44 @@ module Jsapi
|
|
|
296
332
|
)
|
|
297
333
|
end
|
|
298
334
|
|
|
335
|
+
##
|
|
336
|
+
# :method: path_description
|
|
337
|
+
# :args: pathname
|
|
338
|
+
# Returns the most accurate description for the given path.
|
|
339
|
+
|
|
340
|
+
##
|
|
341
|
+
# :method: path_servers
|
|
342
|
+
# :args: pathname
|
|
343
|
+
# Returns the most accurate Server objects for the given path.
|
|
344
|
+
|
|
345
|
+
##
|
|
346
|
+
# :method: path_summary
|
|
347
|
+
# :args: pathname
|
|
348
|
+
# Returns the most accurate summary for the given path.
|
|
349
|
+
|
|
350
|
+
%i[description servers summary].each do |name|
|
|
351
|
+
define_method(:"path_#{name}") do |arg|
|
|
352
|
+
Pathname.from(arg).ancestors.each do |pathname|
|
|
353
|
+
ancestors.each do |ancestor|
|
|
354
|
+
value = ancestor.path(pathname)&.public_send(name)
|
|
355
|
+
return value if value.present?
|
|
356
|
+
end
|
|
357
|
+
end
|
|
358
|
+
nil
|
|
359
|
+
end
|
|
360
|
+
end
|
|
361
|
+
|
|
362
|
+
# Returns a hash containing the Parameter objects that are applicable to all
|
|
363
|
+
# operations in the given path.
|
|
364
|
+
# :args: pathname
|
|
365
|
+
def path_parameters(arg)
|
|
366
|
+
arg = Pathname.from(arg || '')
|
|
367
|
+
|
|
368
|
+
(@path_parameters ||= {})[arg] ||= arg.ancestors.flat_map do |pathname|
|
|
369
|
+
ancestors.filter_map { |ancestor| ancestor.path(pathname)&.parameters }
|
|
370
|
+
end.reduce(&:reverse_merge) || {}
|
|
371
|
+
end
|
|
372
|
+
|
|
299
373
|
# Returns the first RescueHandler to handle +exception+, or nil if no one could be found.
|
|
300
374
|
def rescue_handler_for(exception)
|
|
301
375
|
objects[:rescue_handlers].find { |r| r.match?(exception) }
|
|
@@ -334,15 +408,14 @@ module Jsapi
|
|
|
334
408
|
def invalidate_ancestors
|
|
335
409
|
@ancestors = nil
|
|
336
410
|
@objects = nil
|
|
337
|
-
@
|
|
338
|
-
|
|
411
|
+
@path_parameters = nil
|
|
412
|
+
each_descendant(&:invalidate_ancestors)
|
|
339
413
|
end
|
|
340
414
|
|
|
341
415
|
# Invalidates cached objects.
|
|
342
416
|
def invalidate_objects
|
|
343
417
|
@objects = nil
|
|
344
|
-
|
|
345
|
-
@dependent_definitions&.each(&:invalidate_objects)
|
|
418
|
+
each_descendant(&:invalidate_objects)
|
|
346
419
|
end
|
|
347
420
|
|
|
348
421
|
private
|
|
@@ -361,10 +434,6 @@ module Jsapi
|
|
|
361
434
|
end
|
|
362
435
|
end
|
|
363
436
|
|
|
364
|
-
def default_operation_path
|
|
365
|
-
@default_operation_path ||= "/#{default_operation_name}"
|
|
366
|
-
end
|
|
367
|
-
|
|
368
437
|
def default_server
|
|
369
438
|
@default_server ||=
|
|
370
439
|
if (name = @owner.try(:name))
|
|
@@ -376,6 +445,11 @@ module Jsapi
|
|
|
376
445
|
end
|
|
377
446
|
end
|
|
378
447
|
|
|
448
|
+
def each_descendant(&block)
|
|
449
|
+
[*@children, *dependent_definitions].each(&block)
|
|
450
|
+
nil
|
|
451
|
+
end
|
|
452
|
+
|
|
379
453
|
def objects
|
|
380
454
|
@objects ||= ancestors.each_with_object({}) do |ancestor, objects|
|
|
381
455
|
self.class.attribute_names.each do |key|
|
|
@@ -29,13 +29,11 @@ module Jsapi
|
|
|
29
29
|
|
|
30
30
|
# Returns a hash representing the \OpenAPI example object.
|
|
31
31
|
def to_openapi(*)
|
|
32
|
-
with_openapi_extensions(
|
|
33
|
-
|
|
34
|
-
result[:
|
|
35
|
-
else
|
|
36
|
-
result[:value] = value
|
|
32
|
+
with_openapi_extensions(
|
|
33
|
+
{ summary: summary, description: description }.tap do |result|
|
|
34
|
+
result[external? ? :externalValue : :value] = value
|
|
37
35
|
end
|
|
38
|
-
|
|
36
|
+
)
|
|
39
37
|
end
|
|
40
38
|
end
|
|
41
39
|
end
|
data/lib/jsapi/meta/link/base.rb
CHANGED
|
@@ -33,13 +33,15 @@ module Jsapi
|
|
|
33
33
|
attribute :server, Server
|
|
34
34
|
|
|
35
35
|
# Returns a hash representing the \OpenAPI link object.
|
|
36
|
-
def to_openapi(*)
|
|
36
|
+
def to_openapi(version, *)
|
|
37
|
+
version = OpenAPI::Version.from(version)
|
|
38
|
+
|
|
37
39
|
with_openapi_extensions(
|
|
38
40
|
operationId: operation_id,
|
|
39
41
|
parameters: parameters.presence,
|
|
40
42
|
requestBody: request_body,
|
|
41
43
|
description: description,
|
|
42
|
-
server: server&.to_openapi
|
|
44
|
+
server: server&.to_openapi(version)
|
|
43
45
|
)
|
|
44
46
|
end
|
|
45
47
|
end
|
|
@@ -18,12 +18,20 @@ module Jsapi
|
|
|
18
18
|
# The authorization URL to be used for the flow.
|
|
19
19
|
attribute :authorization_url, String
|
|
20
20
|
|
|
21
|
+
##
|
|
22
|
+
# :attr: device_authorization_url
|
|
23
|
+
# The device authorization URL to be used for the flow.
|
|
24
|
+
#
|
|
25
|
+
# Note that the device authorization URL was introduced with \OpenAPI 3.2.
|
|
26
|
+
# It is omitted when generating an \OpenAPI document with a lower version.
|
|
27
|
+
attribute :device_authorization_url, String
|
|
28
|
+
|
|
21
29
|
##
|
|
22
30
|
# :attr: refresh_url
|
|
23
31
|
# The refresh URL to be used for the flow.
|
|
24
32
|
#
|
|
25
33
|
# Note that the refresh URL was introduced with \OpenAPI 3.0. It is
|
|
26
|
-
#
|
|
34
|
+
# omitted when generating an \OpenAPI document with a lower version.
|
|
27
35
|
attribute :refresh_url, String
|
|
28
36
|
|
|
29
37
|
##
|
|
@@ -42,8 +50,9 @@ module Jsapi
|
|
|
42
50
|
|
|
43
51
|
with_openapi_extensions(
|
|
44
52
|
authorizationUrl: authorization_url,
|
|
53
|
+
deviceAuthorizationUrl: (device_authorization_url if version >= OpenAPI::V3_2),
|
|
45
54
|
tokenUrl: token_url,
|
|
46
|
-
refreshUrl: (refresh_url if version
|
|
55
|
+
refreshUrl: (refresh_url if version >= OpenAPI::V3_0),
|
|
47
56
|
scopes: scopes.transform_values(&:description)
|
|
48
57
|
)
|
|
49
58
|
end
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Jsapi
|
|
4
|
+
module Meta
|
|
5
|
+
module OpenAPI
|
|
6
|
+
class PathItem # :nodoc:
|
|
7
|
+
def initialize(operations, keywords = {})
|
|
8
|
+
@operations = operations
|
|
9
|
+
@summary = keywords[:summary]
|
|
10
|
+
@description = keywords[:description]
|
|
11
|
+
@servers = keywords[:servers]
|
|
12
|
+
@parameters = keywords[:parameters]
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
def to_openapi(version, definitions)
|
|
16
|
+
version = OpenAPI::Version.from(version)
|
|
17
|
+
|
|
18
|
+
{}.tap do |fields|
|
|
19
|
+
if version >= OpenAPI::V3_0
|
|
20
|
+
fields[:summary] = @summary if @summary.present?
|
|
21
|
+
fields[:description] = @description if @description.present?
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
# Operations
|
|
25
|
+
@operations&.each do |operation|
|
|
26
|
+
method = operation.method
|
|
27
|
+
standardized_method = method.downcase
|
|
28
|
+
|
|
29
|
+
if standard_method?(standardized_method, version)
|
|
30
|
+
fields[standardized_method] = operation.to_openapi(version, definitions)
|
|
31
|
+
elsif version >= OpenAPI::V3_2
|
|
32
|
+
additional_operations = fields[:additionalOperations] ||= {}
|
|
33
|
+
additional_operations[method] = operation.to_openapi(version, definitions)
|
|
34
|
+
end
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
# Servers
|
|
38
|
+
if version >= OpenAPI::V3_0 && @servers.present?
|
|
39
|
+
fields[:servers] = @servers.map { |server| server.to_openapi(version) }
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
# Parameters
|
|
43
|
+
if @parameters.present?
|
|
44
|
+
fields[:parameters] = @parameters.values.map do |parameter|
|
|
45
|
+
parameter.to_openapi(version, definitions)
|
|
46
|
+
end
|
|
47
|
+
end
|
|
48
|
+
end
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
private
|
|
52
|
+
|
|
53
|
+
def standard_method?(method, version)
|
|
54
|
+
case method
|
|
55
|
+
when 'delete', 'get', 'head', 'options', 'patch', 'post', 'put'
|
|
56
|
+
true
|
|
57
|
+
when 'trace'
|
|
58
|
+
version >= OpenAPI::V3_0
|
|
59
|
+
when 'query'
|
|
60
|
+
version >= OpenAPI::V3_2
|
|
61
|
+
else
|
|
62
|
+
false
|
|
63
|
+
end
|
|
64
|
+
end
|
|
65
|
+
end
|
|
66
|
+
end
|
|
67
|
+
end
|
|
68
|
+
end
|
|
@@ -19,6 +19,8 @@ module Jsapi
|
|
|
19
19
|
new(3, 0)
|
|
20
20
|
when '3.1'
|
|
21
21
|
new(3, 1)
|
|
22
|
+
when '3.2'
|
|
23
|
+
new(3, 2)
|
|
22
24
|
else
|
|
23
25
|
raise ArgumentError, "unsupported OpenAPI version: #{version.inspect}"
|
|
24
26
|
end
|
|
@@ -46,6 +48,10 @@ module Jsapi
|
|
|
46
48
|
minor <=> other.minor
|
|
47
49
|
end
|
|
48
50
|
|
|
51
|
+
def inspect
|
|
52
|
+
"<#{self.class.name} #{self}>"
|
|
53
|
+
end
|
|
54
|
+
|
|
49
55
|
def to_s # :nodoc:
|
|
50
56
|
"#{major}.#{minor}"
|
|
51
57
|
end
|
data/lib/jsapi/meta/openapi.rb
CHANGED
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
require_relative 'openapi/extensions'
|
|
4
4
|
require_relative 'openapi/version'
|
|
5
|
+
require_relative 'openapi/path_item'
|
|
5
6
|
|
|
6
7
|
module Jsapi
|
|
7
8
|
module Meta
|
|
@@ -9,6 +10,7 @@ module Jsapi
|
|
|
9
10
|
V2_0 = Version.new(2, 0)
|
|
10
11
|
V3_0 = Version.new(3, 0)
|
|
11
12
|
V3_1 = Version.new(3, 1)
|
|
13
|
+
V3_2 = Version.new(3, 2)
|
|
12
14
|
end
|
|
13
15
|
end
|
|
14
16
|
end
|