jsapi 1.4 → 2.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/lib/jsapi/controller/actions/class_methods.rb +61 -0
- data/lib/jsapi/controller/actions.rb +13 -0
- data/lib/jsapi/controller/authentication/class_methods.rb +65 -0
- data/lib/jsapi/controller/authentication/credentials/api_key.rb +24 -0
- data/lib/jsapi/controller/authentication/credentials/http/base.rb +25 -0
- data/lib/jsapi/controller/authentication/credentials/http/basic.rb +34 -0
- data/lib/jsapi/controller/authentication/credentials/http/bearer.rb +30 -0
- data/lib/jsapi/controller/authentication/credentials/http.rb +5 -0
- data/lib/jsapi/controller/authentication/credentials.rb +38 -0
- data/lib/jsapi/controller/authentication.rb +70 -0
- data/lib/jsapi/controller/base.rb +5 -4
- data/lib/jsapi/controller/methods/callbacks/callback.rb +80 -0
- data/lib/jsapi/controller/methods/callbacks/class_methods.rb +62 -0
- data/lib/jsapi/controller/methods/callbacks.rb +54 -0
- data/lib/jsapi/controller/methods.rb +209 -116
- data/lib/jsapi/controller/parameters.rb +24 -20
- data/lib/jsapi/controller/response.rb +71 -39
- data/lib/jsapi/controller.rb +2 -1
- data/lib/jsapi/dsl/base.rb +38 -5
- data/lib/jsapi/dsl/class_methods.rb +2 -2
- data/lib/jsapi/dsl/definitions.rb +41 -27
- data/lib/jsapi/dsl/operation.rb +10 -109
- data/lib/jsapi/dsl/parameter.rb +1 -1
- data/lib/jsapi/dsl/path.rb +41 -18
- data/lib/jsapi/dsl/request_body.rb +1 -1
- data/lib/jsapi/dsl/response.rb +9 -6
- data/lib/jsapi/dsl/schema.rb +11 -5
- data/lib/jsapi/dsl/shared_operation_methods.rb +140 -0
- data/lib/jsapi/dsl.rb +1 -2
- data/lib/jsapi/json/array.rb +2 -2
- data/lib/jsapi/json/object.rb +6 -6
- data/lib/jsapi/json.rb +4 -6
- data/lib/jsapi/media/range.rb +102 -0
- data/lib/jsapi/media/type.rb +70 -0
- data/lib/jsapi/media/type_and_subtype.rb +38 -0
- data/lib/jsapi/media.rb +9 -0
- data/lib/jsapi/messages.rb +19 -0
- data/lib/jsapi/meta/callback/base.rb +63 -8
- data/lib/jsapi/meta/content.rb +59 -0
- data/lib/jsapi/meta/definitions.rb +299 -153
- data/lib/jsapi/meta/example/base.rb +41 -8
- data/lib/jsapi/meta/existence.rb +4 -2
- data/lib/jsapi/meta/header/base.rb +4 -2
- data/lib/jsapi/meta/info.rb +3 -1
- data/lib/jsapi/meta/license.rb +11 -5
- data/lib/jsapi/meta/model/attributes/class_methods.rb +150 -0
- data/lib/jsapi/meta/model/attributes/frozen_error.rb +16 -0
- data/lib/jsapi/meta/model/attributes/type_caster.rb +56 -0
- data/lib/jsapi/meta/model/attributes.rb +24 -118
- data/lib/jsapi/meta/model/base.rb +2 -5
- data/lib/jsapi/meta/model/reference.rb +46 -10
- data/lib/jsapi/meta/model/wrappable.rb +23 -0
- data/lib/jsapi/meta/model/wrapper.rb +26 -0
- data/lib/jsapi/meta/model.rb +2 -1
- data/lib/jsapi/meta/oauth_flow.rb +1 -1
- data/lib/jsapi/meta/openapi/extensions.rb +5 -6
- data/lib/jsapi/meta/openapi/version.rb +16 -4
- data/lib/jsapi/meta/operation.rb +177 -71
- data/lib/jsapi/meta/parameter/base.rb +10 -6
- data/lib/jsapi/meta/parameter/wrapper.rb +13 -0
- data/lib/jsapi/meta/parameter.rb +3 -0
- data/lib/jsapi/meta/path.rb +59 -13
- data/lib/jsapi/meta/pathname.rb +6 -3
- data/lib/jsapi/meta/property.rb +10 -0
- data/lib/jsapi/meta/request_body/base.rb +69 -32
- data/lib/jsapi/meta/request_body/wrapper.rb +13 -0
- data/lib/jsapi/meta/request_body.rb +3 -0
- data/lib/jsapi/meta/rescue_handler.rb +18 -17
- data/lib/jsapi/meta/response/base.rb +82 -58
- data/lib/jsapi/meta/response/reference.rb +11 -1
- data/lib/jsapi/meta/response/wrapper.rb +26 -0
- data/lib/jsapi/meta/response.rb +3 -0
- data/lib/jsapi/meta/schema/additional_properties.rb +8 -0
- data/lib/jsapi/meta/schema/array.rb +20 -8
- data/lib/jsapi/meta/schema/base.rb +10 -9
- data/lib/jsapi/meta/schema/boundary.rb +1 -0
- data/lib/jsapi/meta/schema/numeric.rb +26 -20
- data/lib/jsapi/meta/schema/object.rb +60 -44
- data/lib/jsapi/meta/schema/reference.rb +1 -8
- data/lib/jsapi/meta/schema/string.rb +12 -6
- data/lib/jsapi/meta/schema/wrapper.rb +31 -0
- data/lib/jsapi/meta/schema.rb +22 -9
- data/lib/jsapi/meta/security_requirement.rb +2 -2
- data/lib/jsapi/meta/security_scheme/api_key.rb +5 -2
- data/lib/jsapi/meta/security_scheme/base.rb +7 -5
- data/lib/jsapi/meta/security_scheme/http/basic.rb +5 -7
- data/lib/jsapi/meta/security_scheme/http/bearer.rb +5 -5
- data/lib/jsapi/meta/security_scheme/http/other.rb +1 -3
- data/lib/jsapi/meta/security_scheme/mutual_tls.rb +1 -3
- data/lib/jsapi/meta/security_scheme/oauth2.rb +18 -13
- data/lib/jsapi/meta/security_scheme/open_id_connect.rb +4 -4
- data/lib/jsapi/meta/security_scheme.rb +4 -4
- data/lib/jsapi/meta/server.rb +4 -2
- data/lib/jsapi/meta/tag.rb +9 -3
- data/lib/jsapi/meta.rb +2 -1
- data/lib/jsapi/model/base.rb +1 -1
- data/lib/jsapi/status/base.rb +35 -0
- data/lib/jsapi/status/code.rb +113 -0
- data/lib/jsapi/status/default.rb +16 -0
- data/lib/jsapi/status/range.rb +35 -0
- data/lib/jsapi/status.rb +37 -0
- data/lib/jsapi/version.rb +1 -1
- data/lib/jsapi.rb +3 -3
- metadata +36 -10
- data/lib/jsapi/controller/parameters_invalid.rb +0 -27
- data/lib/jsapi/dsl/callback.rb +0 -21
- data/lib/jsapi/dsl/error.rb +0 -36
- data/lib/jsapi/invalid_argument_error.rb +0 -12
- data/lib/jsapi/invalid_value_error.rb +0 -12
- data/lib/jsapi/invalid_value_helper.rb +0 -17
- data/lib/jsapi/meta/model/type_caster.rb +0 -50
- data/lib/jsapi/meta/schema/delegator.rb +0 -26
|
@@ -7,22 +7,29 @@ module Jsapi
|
|
|
7
7
|
|
|
8
8
|
##
|
|
9
9
|
# :attr: base_path
|
|
10
|
-
# The base path of the API.
|
|
10
|
+
# The base path of the API.
|
|
11
|
+
#
|
|
12
|
+
# Applies to \OpenAPI 2.0.
|
|
11
13
|
attribute :base_path, Pathname
|
|
12
14
|
|
|
13
15
|
##
|
|
14
16
|
# :attr: callbacks
|
|
15
|
-
# The reusable
|
|
17
|
+
# The reusable callbacks. Maps strings to Callback objects or references.
|
|
18
|
+
#
|
|
19
|
+
# Applies to \OpenAPI 3.0 and higher.
|
|
16
20
|
attribute :callbacks, { String => Callback }
|
|
17
21
|
|
|
18
22
|
##
|
|
19
23
|
# :attr: defaults
|
|
20
|
-
# The
|
|
24
|
+
# The registered default values for different schema types. Maps schema
|
|
25
|
+
# types to Defaults object.
|
|
21
26
|
attribute :defaults, { String => Defaults }, keys: Schema::TYPES
|
|
22
27
|
|
|
23
28
|
##
|
|
24
29
|
# :attr: examples
|
|
25
|
-
# The reusable
|
|
30
|
+
# The reusable examples. Maps example names to Example objects or references.
|
|
31
|
+
#
|
|
32
|
+
# Applies to \OpenAPI 3.0 and higher.
|
|
26
33
|
attribute :examples, { String => Example }
|
|
27
34
|
|
|
28
35
|
##
|
|
@@ -32,12 +39,16 @@ module Jsapi
|
|
|
32
39
|
|
|
33
40
|
##
|
|
34
41
|
# :attr: headers
|
|
35
|
-
# The reusable
|
|
42
|
+
# The reusable headers. Maps header names to Header objects or references.
|
|
43
|
+
#
|
|
44
|
+
# Applies to \OpenAPI 3.0 and higher.
|
|
36
45
|
attribute :headers, { String => Header }
|
|
37
46
|
|
|
38
47
|
##
|
|
39
48
|
# :attr: host
|
|
40
|
-
# The host serving the API.
|
|
49
|
+
# The host serving the API.
|
|
50
|
+
#
|
|
51
|
+
# Applies to \OpenAPI 2.0.
|
|
41
52
|
attribute :host, String
|
|
42
53
|
|
|
43
54
|
##
|
|
@@ -47,7 +58,9 @@ module Jsapi
|
|
|
47
58
|
|
|
48
59
|
##
|
|
49
60
|
# :attr: links
|
|
50
|
-
# The reusable
|
|
61
|
+
# The reusable links. Maps link names to Link objects.
|
|
62
|
+
#
|
|
63
|
+
# Applies to \OpenAPI 3.0 and higher.
|
|
51
64
|
attribute :links, { String => Link }
|
|
52
65
|
|
|
53
66
|
##
|
|
@@ -57,42 +70,45 @@ module Jsapi
|
|
|
57
70
|
|
|
58
71
|
##
|
|
59
72
|
# :attr: operations
|
|
60
|
-
# The Operation objects.
|
|
73
|
+
# The operations. Maps operation names to Operation objects.
|
|
61
74
|
attribute :operations, { String => Operation }, accessors: %i[reader writer]
|
|
62
75
|
|
|
63
76
|
##
|
|
64
77
|
# :attr: parameters
|
|
65
|
-
# The reusable Parameter objects
|
|
78
|
+
# The reusable parameters. Maps parameter names to Parameter objects
|
|
79
|
+
# or references.
|
|
66
80
|
attribute :parameters, { String => Parameter }, accessors: %i[reader writer]
|
|
67
81
|
|
|
68
82
|
##
|
|
69
83
|
# :attr: paths
|
|
70
|
-
# The Path objects.
|
|
84
|
+
# The paths. Maps instances of Pathname to Path objects.
|
|
71
85
|
attribute :paths, { Pathname => Path }, accessors: %i[reader writer]
|
|
72
86
|
|
|
73
87
|
##
|
|
74
88
|
# :attr: rescue_handlers
|
|
75
|
-
# The
|
|
89
|
+
# The registered rescue handlers.
|
|
76
90
|
attribute :rescue_handlers, [RescueHandler]
|
|
77
91
|
|
|
78
92
|
##
|
|
79
93
|
# :attr: request_bodies
|
|
80
|
-
# The reusable
|
|
94
|
+
# The reusable request bodies. Maps request body names to RequestBody
|
|
95
|
+
# objects or references.
|
|
81
96
|
attribute :request_bodies, { String => RequestBody }
|
|
82
97
|
|
|
83
98
|
##
|
|
84
99
|
# :attr: responses
|
|
85
|
-
# The reusable Response objects
|
|
100
|
+
# The reusable responses. Maps response names to Response objects or
|
|
101
|
+
# references.
|
|
86
102
|
attribute :responses, { String => Response }
|
|
87
103
|
|
|
88
104
|
##
|
|
89
105
|
# :attr: schemas
|
|
90
|
-
# The reusable Schema objects.
|
|
106
|
+
# The reusable schemas. Maps schema names to Schema objects or references.
|
|
91
107
|
attribute :schemas, { String => Schema }
|
|
92
108
|
|
|
93
109
|
##
|
|
94
110
|
# :attr: schemes
|
|
95
|
-
# The
|
|
111
|
+
# The transfer protocols supported by the API. Can contain one or more of:
|
|
96
112
|
#
|
|
97
113
|
# - <code>"http"</code>
|
|
98
114
|
# - <code>"https"</code>
|
|
@@ -104,24 +120,26 @@ module Jsapi
|
|
|
104
120
|
|
|
105
121
|
##
|
|
106
122
|
# :attr: security_requirements
|
|
107
|
-
# The
|
|
123
|
+
# The top-level security requirements.
|
|
108
124
|
attribute :security_requirements, [SecurityRequirement]
|
|
109
125
|
|
|
110
126
|
alias add_security add_security_requirement
|
|
111
127
|
|
|
112
128
|
##
|
|
113
129
|
# :attr: security_schemes
|
|
114
|
-
# The
|
|
130
|
+
# The security schemes.
|
|
115
131
|
attribute :security_schemes, { String => SecurityScheme }
|
|
116
132
|
|
|
117
133
|
##
|
|
118
134
|
# :attr: servers
|
|
119
|
-
# The
|
|
135
|
+
# The servers providing the API.
|
|
136
|
+
#
|
|
137
|
+
# Applies to \OpenAPI 3.0 and higher.
|
|
120
138
|
attribute :servers, [Server]
|
|
121
139
|
|
|
122
140
|
##
|
|
123
141
|
# :attr: tags
|
|
124
|
-
# The
|
|
142
|
+
# The tags.
|
|
125
143
|
attribute :tags, [Tag]
|
|
126
144
|
|
|
127
145
|
# The class to which this instance is assigned.
|
|
@@ -144,30 +162,34 @@ module Jsapi
|
|
|
144
162
|
end
|
|
145
163
|
|
|
146
164
|
def add_operation(name, parent_path = nil, keywords = {}) # :nodoc:
|
|
147
|
-
|
|
165
|
+
try_modify_attribute!(:operations) do
|
|
166
|
+
parent_path, keywords = nil, parent_path if parent_path.is_a?(Hash)
|
|
148
167
|
|
|
149
|
-
|
|
150
|
-
|
|
168
|
+
name = name.nil? ? default_operation_name : name.to_s
|
|
169
|
+
parent_path ||= default_operation_name unless keywords[:path].present?
|
|
151
170
|
|
|
152
|
-
|
|
171
|
+
(@operations ||= {})[name] = Operation.new(name, parent_path, keywords)
|
|
172
|
+
end
|
|
153
173
|
end
|
|
154
174
|
|
|
155
175
|
def add_parameter(name, keywords = {}) # :nodoc:
|
|
156
|
-
|
|
176
|
+
try_modify_attribute!(:parameters) do
|
|
177
|
+
name = name.to_s
|
|
157
178
|
|
|
158
|
-
|
|
159
|
-
(@parameters ||= {})[name] = parameter
|
|
160
|
-
attribute_changed(:parameters)
|
|
179
|
+
(@parameters ||= {})[name] = Parameter.new(name, keywords)
|
|
161
180
|
end
|
|
162
181
|
end
|
|
163
182
|
|
|
164
183
|
def add_path(name, keywords = {}) # :nodoc:
|
|
165
|
-
|
|
166
|
-
|
|
184
|
+
try_modify_attribute!(:paths) do
|
|
185
|
+
pathname = Pathname.from(name)
|
|
186
|
+
|
|
187
|
+
(@paths ||= {})[pathname] = Path.new(pathname, self, keywords)
|
|
188
|
+
end
|
|
167
189
|
end
|
|
168
190
|
|
|
169
191
|
# Returns an array containing itself and all of the +Definitions+ instances
|
|
170
|
-
# inherited
|
|
192
|
+
# inherited or included.
|
|
171
193
|
def ancestors
|
|
172
194
|
@ancestors ||= [self].tap do |ancestors|
|
|
173
195
|
[@included_definitions, @parent].flatten.each do |definitions|
|
|
@@ -176,37 +198,145 @@ module Jsapi
|
|
|
176
198
|
end.uniq
|
|
177
199
|
end
|
|
178
200
|
|
|
201
|
+
##
|
|
202
|
+
# :method: common_description
|
|
203
|
+
# :args: pathname
|
|
204
|
+
# Returns the most accurate description for the specified path.
|
|
205
|
+
|
|
206
|
+
##
|
|
207
|
+
# :method: common_model
|
|
208
|
+
# :args: pathname
|
|
209
|
+
# Returns the common model of all operations in the specified path.
|
|
210
|
+
|
|
211
|
+
##
|
|
212
|
+
# :method: common_response_body
|
|
213
|
+
# :args: pathname
|
|
214
|
+
# Returns the common request body of all operations in the specified path.
|
|
215
|
+
|
|
216
|
+
##
|
|
217
|
+
# :method: common_servers
|
|
218
|
+
# :args: pathname
|
|
219
|
+
# Returns the most accurate servers for the specified path.
|
|
220
|
+
|
|
221
|
+
##
|
|
222
|
+
# :method: common_summary
|
|
223
|
+
# :args: pathname
|
|
224
|
+
# Returns the most accurate summary for the specified path.
|
|
225
|
+
|
|
226
|
+
%i[description model request_body servers summary].each do |name|
|
|
227
|
+
define_method(:"common_#{name}") do |arg|
|
|
228
|
+
arg = Pathname.from(arg || '')
|
|
229
|
+
|
|
230
|
+
cache_path_attribute(arg, name) do
|
|
231
|
+
arg.ancestors.lazy.filter_map do |pathname|
|
|
232
|
+
ancestors.lazy.filter_map do |definitions|
|
|
233
|
+
definitions.path(pathname)&.public_send(name).presence
|
|
234
|
+
end.first
|
|
235
|
+
end.first
|
|
236
|
+
end
|
|
237
|
+
end
|
|
238
|
+
end
|
|
239
|
+
|
|
240
|
+
##
|
|
241
|
+
# :method: common_parameters
|
|
242
|
+
# :args: pathname
|
|
243
|
+
# Returns the parameters that apply to all operations in the
|
|
244
|
+
# specified path.
|
|
245
|
+
|
|
246
|
+
##
|
|
247
|
+
# :method: common_responses
|
|
248
|
+
# :args: pathname
|
|
249
|
+
# Returns the responses that can be produced by all operations in the
|
|
250
|
+
# specified path.
|
|
251
|
+
|
|
252
|
+
%i[parameters responses].each do |name|
|
|
253
|
+
define_method(:"common_#{name}") do |arg|
|
|
254
|
+
arg = Pathname.from(arg || '')
|
|
255
|
+
|
|
256
|
+
cache_path_attribute(arg, name) do
|
|
257
|
+
arg.ancestors.flat_map do |pathname|
|
|
258
|
+
ancestors.filter_map do |definitions|
|
|
259
|
+
definitions.path(pathname)&.send(name)
|
|
260
|
+
end
|
|
261
|
+
end.reduce({}, &:reverse_merge).presence
|
|
262
|
+
end
|
|
263
|
+
end
|
|
264
|
+
end
|
|
265
|
+
|
|
266
|
+
##
|
|
267
|
+
# :method: common_security_requirements
|
|
268
|
+
# :args: pathname
|
|
269
|
+
# Returns the security requirements that apply to all operations in
|
|
270
|
+
# the specified path.
|
|
271
|
+
|
|
272
|
+
##
|
|
273
|
+
# :method: common_tags
|
|
274
|
+
# :args: pathname
|
|
275
|
+
# Returns the tags that apply to all operations in the specified path.
|
|
276
|
+
|
|
277
|
+
%i[security_requirements tags].each do |name|
|
|
278
|
+
define_method(:"common_#{name}") do |arg|
|
|
279
|
+
arg = Pathname.from(arg || '')
|
|
280
|
+
|
|
281
|
+
cache_path_attribute(arg, name) do
|
|
282
|
+
arg.ancestors.filter_map do |pathname|
|
|
283
|
+
ancestors.filter_map do |definitions|
|
|
284
|
+
definitions.path(pathname)&.send(name)
|
|
285
|
+
end
|
|
286
|
+
end.flatten.uniq.presence
|
|
287
|
+
end
|
|
288
|
+
end
|
|
289
|
+
end
|
|
290
|
+
|
|
179
291
|
# Returns the default value for +type+ within +context+.
|
|
180
292
|
def default_value(type, context: nil)
|
|
181
|
-
|
|
293
|
+
cached_attributes.dig(:defaults, type.to_s)&.value(context: context)
|
|
294
|
+
end
|
|
295
|
+
|
|
296
|
+
# The security requirements that apply by default to all operations.
|
|
297
|
+
def default_security_requirements
|
|
298
|
+
cached_attributes[:security_requirements]
|
|
182
299
|
end
|
|
183
300
|
|
|
184
301
|
# Returns the operation with the specified name.
|
|
185
302
|
def find_operation(name = nil)
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
303
|
+
name = name&.to_s
|
|
304
|
+
|
|
305
|
+
cache_operation(name) do
|
|
306
|
+
if name.present?
|
|
307
|
+
# Select the operation with the given name
|
|
308
|
+
cached_attributes.dig(:operations, name)
|
|
309
|
+
elsif operations.one?
|
|
310
|
+
# Select the one and only operation
|
|
311
|
+
operations.values.first
|
|
312
|
+
end
|
|
313
|
+
end
|
|
190
314
|
end
|
|
191
315
|
|
|
316
|
+
##
|
|
317
|
+
# :method: find_parameter
|
|
192
318
|
# Returns the reusable parameter with the specified name.
|
|
193
|
-
def find_parameter(name)
|
|
194
|
-
objects.dig(:parameters, name&.to_s)
|
|
195
|
-
end
|
|
196
319
|
|
|
320
|
+
##
|
|
321
|
+
# :method: find_request_body
|
|
197
322
|
# Returns the reusable request body with the specified name.
|
|
198
|
-
def find_request_body(name)
|
|
199
|
-
objects.dig(:request_bodies, name&.to_s)
|
|
200
|
-
end
|
|
201
323
|
|
|
324
|
+
##
|
|
325
|
+
# :method: find_response
|
|
202
326
|
# Returns the reusable response with the specified name.
|
|
203
|
-
def find_response(name)
|
|
204
|
-
objects.dig(:responses, name&.to_s)
|
|
205
|
-
end
|
|
206
327
|
|
|
328
|
+
##
|
|
329
|
+
# :method: find_schema
|
|
207
330
|
# Returns the reusable schema with the specified name.
|
|
208
|
-
|
|
209
|
-
|
|
331
|
+
|
|
332
|
+
##
|
|
333
|
+
# :method: find_security_scheme
|
|
334
|
+
# Returns the security scheme with the specified name.
|
|
335
|
+
|
|
336
|
+
%i[parameters request_bodies responses schemas security_schemes].each do |attribute_name|
|
|
337
|
+
define_method(:"find_#{attribute_name.to_s.singularize}") do |name|
|
|
338
|
+
cached_attributes.dig(attribute_name, name&.to_s)
|
|
339
|
+
end
|
|
210
340
|
end
|
|
211
341
|
|
|
212
342
|
# Includes +definitions+.
|
|
@@ -224,26 +354,44 @@ module Jsapi
|
|
|
224
354
|
self
|
|
225
355
|
end
|
|
226
356
|
|
|
227
|
-
#
|
|
228
|
-
def
|
|
357
|
+
# Invalidates cached ancestors.
|
|
358
|
+
def invalidate_ancestors
|
|
359
|
+
@ancestors = nil
|
|
360
|
+
@cache = nil
|
|
361
|
+
each_descendant(&:invalidate_ancestors)
|
|
362
|
+
end
|
|
363
|
+
|
|
364
|
+
# Invalidates cached attributes.
|
|
365
|
+
def invalidate_attributes
|
|
366
|
+
@cache = nil
|
|
367
|
+
each_descendant(&:invalidate_attributes)
|
|
368
|
+
end
|
|
369
|
+
|
|
370
|
+
# Invalidates the given path attribute.
|
|
371
|
+
def invalidate_path_attribute(pathname, name)
|
|
229
372
|
pathname = Pathname.from(pathname)
|
|
373
|
+
name = name.to_sym
|
|
374
|
+
|
|
375
|
+
cached_path_attributes.fetch(pathname, nil)&.delete(name)
|
|
376
|
+
@cache[:operations] = nil
|
|
230
377
|
|
|
231
|
-
|
|
232
|
-
|
|
378
|
+
each_descendant do |descendant|
|
|
379
|
+
descendant.invalidate_path_attribute(pathname, name)
|
|
380
|
+
end
|
|
233
381
|
end
|
|
234
382
|
|
|
235
383
|
# Returns a hash representing the \JSON \Schema document for +name+.
|
|
236
384
|
def json_schema_document(name)
|
|
237
385
|
find_schema(name)&.to_json_schema&.tap do |json_schema_document|
|
|
238
|
-
if (schemas =
|
|
386
|
+
if (schemas = cached_attributes[:schemas].except(name.to_s)).any?
|
|
239
387
|
json_schema_document[:definitions] = schemas.transform_values(&:to_json_schema)
|
|
240
388
|
end
|
|
241
|
-
end
|
|
389
|
+
end&.as_json
|
|
242
390
|
end
|
|
243
391
|
|
|
244
392
|
# Returns the methods or procs to be called when rescuing an exception.
|
|
245
393
|
def on_rescue_callbacks
|
|
246
|
-
|
|
394
|
+
cached_attributes[:on_rescues]
|
|
247
395
|
end
|
|
248
396
|
|
|
249
397
|
# Returns a hash representing the \OpenAPI document for +version+.
|
|
@@ -251,47 +399,63 @@ module Jsapi
|
|
|
251
399
|
# Raises an +ArgumentError+ if +version+ is not supported.
|
|
252
400
|
def openapi_document(version = nil)
|
|
253
401
|
version = OpenAPI::Version.from(version)
|
|
254
|
-
operations =
|
|
402
|
+
operations = cached_attributes[:operations].values
|
|
255
403
|
|
|
256
404
|
openapi_paths = operations.group_by(&:full_path).to_h do |key, value|
|
|
257
405
|
[
|
|
258
|
-
key
|
|
406
|
+
key,
|
|
259
407
|
OpenAPI::PathItem.new(
|
|
260
408
|
value,
|
|
261
|
-
description:
|
|
262
|
-
parameters:
|
|
263
|
-
summary:
|
|
264
|
-
servers:
|
|
409
|
+
description: common_description(key),
|
|
410
|
+
parameters: common_parameters(key),
|
|
411
|
+
summary: common_summary(key),
|
|
412
|
+
servers: common_servers(key)
|
|
265
413
|
).to_openapi(version, self)
|
|
266
414
|
]
|
|
267
415
|
end.presence
|
|
268
416
|
|
|
269
|
-
openapi_objects =
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
417
|
+
openapi_objects = (
|
|
418
|
+
%i[external_docs info parameters responses schemas
|
|
419
|
+
security_requirements security_schemes tags] +
|
|
420
|
+
if version == OpenAPI::V2_0
|
|
421
|
+
%i[base_path host schemes]
|
|
273
422
|
else
|
|
274
|
-
%i[callbacks examples
|
|
275
|
-
|
|
276
|
-
|
|
423
|
+
%i[callbacks examples headers links request_bodies servers]
|
|
424
|
+
end
|
|
425
|
+
).index_with do |key|
|
|
426
|
+
value = cached_attributes[key]
|
|
427
|
+
if key == :responses
|
|
428
|
+
value = value.reject do |_name, response|
|
|
429
|
+
response.resolve(self).nodoc?
|
|
430
|
+
end
|
|
431
|
+
end
|
|
432
|
+
object_to_openapi(value, version).presence
|
|
433
|
+
end
|
|
277
434
|
|
|
278
435
|
with_openapi_extensions(
|
|
279
|
-
if version
|
|
280
|
-
openapi_server =
|
|
436
|
+
if version == OpenAPI::V2_0
|
|
437
|
+
openapi_server = cached_attributes[:servers].first || default_server
|
|
281
438
|
uri = URI(openapi_server.url) if openapi_server
|
|
282
439
|
{
|
|
283
440
|
# Order according to the OpenAPI specification 2.x
|
|
284
441
|
swagger: '2.0',
|
|
285
442
|
info: openapi_objects[:info],
|
|
286
443
|
host: openapi_objects[:host] || uri&.hostname,
|
|
287
|
-
basePath: openapi_objects[:base_path]
|
|
444
|
+
basePath: openapi_objects[:base_path] || uri&.path,
|
|
288
445
|
schemes: openapi_objects[:schemes] || Array(uri&.scheme).presence,
|
|
289
|
-
consumes:
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
446
|
+
consumes:
|
|
447
|
+
Media::Range.reduce(
|
|
448
|
+
operations.filter_map do |operation|
|
|
449
|
+
operation.request_body&.resolve(self)&.default_media_range
|
|
450
|
+
end
|
|
451
|
+
).presence,
|
|
452
|
+
produces:
|
|
453
|
+
operations.flat_map do |operation|
|
|
454
|
+
operation.responses.values.filter_map do |response|
|
|
455
|
+
response = response.resolve(self)
|
|
456
|
+
response.default_media_type unless response.nodoc?
|
|
457
|
+
end
|
|
458
|
+
end.uniq.sort.presence,
|
|
295
459
|
paths: openapi_paths,
|
|
296
460
|
definitions: openapi_objects[:schemas],
|
|
297
461
|
parameters: openapi_objects[:parameters],
|
|
@@ -301,12 +465,7 @@ module Jsapi
|
|
|
301
465
|
else
|
|
302
466
|
{
|
|
303
467
|
# Order according to the OpenAPI specification 3.x
|
|
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,
|
|
468
|
+
openapi: version,
|
|
310
469
|
info: openapi_objects[:info],
|
|
311
470
|
servers:
|
|
312
471
|
openapi_objects[:servers] ||
|
|
@@ -329,50 +488,13 @@ module Jsapi
|
|
|
329
488
|
tags: openapi_objects[:tags],
|
|
330
489
|
externalDocs: openapi_objects[:external_docs]
|
|
331
490
|
).compact
|
|
332
|
-
)
|
|
333
|
-
end
|
|
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) || {}
|
|
491
|
+
).as_json
|
|
371
492
|
end
|
|
372
493
|
|
|
373
|
-
# Returns the first RescueHandler to handle +exception+, or nil
|
|
494
|
+
# Returns the first RescueHandler capable to handle +exception+, or nil
|
|
495
|
+
# if no one could be found.
|
|
374
496
|
def rescue_handler_for(exception)
|
|
375
|
-
|
|
497
|
+
cached_attributes[:rescue_handlers].find { |r| r.match?(exception) }
|
|
376
498
|
end
|
|
377
499
|
|
|
378
500
|
protected
|
|
@@ -387,7 +509,8 @@ module Jsapi
|
|
|
387
509
|
attr_reader :included_definitions
|
|
388
510
|
|
|
389
511
|
def attribute_changed(*) # :nodoc:
|
|
390
|
-
|
|
512
|
+
invalidate_attributes
|
|
513
|
+
super
|
|
391
514
|
end
|
|
392
515
|
|
|
393
516
|
# Invoked whenever it is included in another +Definitions+ instance.
|
|
@@ -404,21 +527,63 @@ module Jsapi
|
|
|
404
527
|
|
|
405
528
|
# rubocop:enable Lint/MissingSuper
|
|
406
529
|
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
@
|
|
411
|
-
@path_parameters = nil
|
|
412
|
-
each_descendant(&:invalidate_ancestors)
|
|
530
|
+
private
|
|
531
|
+
|
|
532
|
+
def cache
|
|
533
|
+
@cache ||= {}
|
|
413
534
|
end
|
|
414
535
|
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
536
|
+
def cached_attributes
|
|
537
|
+
cache[:attributes] ||= ancestors.each_with_object({}) do |ancestor, attr|
|
|
538
|
+
self.class.attribute_names.each do |key|
|
|
539
|
+
case value = ancestor.send(key)
|
|
540
|
+
when Array
|
|
541
|
+
(attr[key] ||= []).push(*value)
|
|
542
|
+
when Hash
|
|
543
|
+
if (hash = attr[key])
|
|
544
|
+
value.each { |k, v| hash[k] = v unless hash.key?(k) }
|
|
545
|
+
else
|
|
546
|
+
attr[key] = value.dup
|
|
547
|
+
end
|
|
548
|
+
else
|
|
549
|
+
attr[key] ||= value
|
|
550
|
+
end
|
|
551
|
+
end
|
|
552
|
+
end
|
|
419
553
|
end
|
|
420
554
|
|
|
421
|
-
|
|
555
|
+
def cached_operations
|
|
556
|
+
cache[:operations] ||= {}
|
|
557
|
+
end
|
|
558
|
+
|
|
559
|
+
def cached_path_attributes
|
|
560
|
+
cache[:path_attributes] ||=
|
|
561
|
+
cached_attributes[:operations]
|
|
562
|
+
.values
|
|
563
|
+
.map(&:full_path)
|
|
564
|
+
.flat_map(&:ancestors)
|
|
565
|
+
.uniq
|
|
566
|
+
.to_h { |pathname| [pathname, {}] }
|
|
567
|
+
end
|
|
568
|
+
|
|
569
|
+
def cache_operation(name)
|
|
570
|
+
operation = cached_operations[name]
|
|
571
|
+
return operation if operation
|
|
572
|
+
|
|
573
|
+
operation = yield
|
|
574
|
+
cached_operations[name] = Operation.wrap(operation, self) if operation
|
|
575
|
+
end
|
|
576
|
+
|
|
577
|
+
def cache_path_attribute(pathname, name)
|
|
578
|
+
path_attributes = cached_path_attributes[pathname]
|
|
579
|
+
return path_attributes[name] if path_attributes&.key?(name)
|
|
580
|
+
|
|
581
|
+
value = yield
|
|
582
|
+
return unless value || path_attributes
|
|
583
|
+
|
|
584
|
+
path_attributes ||= cached_path_attributes[pathname] = {}
|
|
585
|
+
path_attributes[name] = value
|
|
586
|
+
end
|
|
422
587
|
|
|
423
588
|
def circular_dependency?(other)
|
|
424
589
|
return true if other == self
|
|
@@ -450,25 +615,6 @@ module Jsapi
|
|
|
450
615
|
nil
|
|
451
616
|
end
|
|
452
617
|
|
|
453
|
-
def objects
|
|
454
|
-
@objects ||= ancestors.each_with_object({}) do |ancestor, objects|
|
|
455
|
-
self.class.attribute_names.each do |key|
|
|
456
|
-
case value = ancestor.send(key)
|
|
457
|
-
when Array
|
|
458
|
-
(objects[key] ||= []).push(*value)
|
|
459
|
-
when Hash
|
|
460
|
-
if (hash = objects[key])
|
|
461
|
-
value.each { |k, v| hash[k] = v unless hash.key?(k) }
|
|
462
|
-
else
|
|
463
|
-
objects[key] = value.dup
|
|
464
|
-
end
|
|
465
|
-
else
|
|
466
|
-
objects[key] ||= value
|
|
467
|
-
end
|
|
468
|
-
end
|
|
469
|
-
end
|
|
470
|
-
end
|
|
471
|
-
|
|
472
618
|
def object_to_openapi(object, version)
|
|
473
619
|
case object
|
|
474
620
|
when Array
|