jsapi 1.4.1 → 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 +188 -71
- 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 +39 -6
- data/lib/jsapi/media/type.rb +8 -4
- data/lib/jsapi/media.rb +5 -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 +291 -141
- data/lib/jsapi/meta/example/base.rb +41 -8
- data/lib/jsapi/meta/existence.rb +1 -1
- 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 +2 -2
- data/lib/jsapi/meta/operation.rb +177 -71
- data/lib/jsapi/meta/parameter/base.rb +9 -5
- 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 +3 -0
- 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 +86 -49
- 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/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 +2 -3
- metadata +32 -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
|
|
230
374
|
|
|
231
|
-
|
|
232
|
-
|
|
375
|
+
cached_path_attributes.fetch(pathname, nil)&.delete(name)
|
|
376
|
+
@cache[:operations] = nil
|
|
377
|
+
|
|
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,17 +399,17 @@ 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
|
|
@@ -274,25 +422,40 @@ module Jsapi
|
|
|
274
422
|
else
|
|
275
423
|
%i[callbacks examples headers links request_bodies servers]
|
|
276
424
|
end
|
|
277
|
-
).index_with
|
|
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
|
|
278
434
|
|
|
279
435
|
with_openapi_extensions(
|
|
280
436
|
if version == OpenAPI::V2_0
|
|
281
|
-
openapi_server =
|
|
437
|
+
openapi_server = cached_attributes[:servers].first || default_server
|
|
282
438
|
uri = URI(openapi_server.url) if openapi_server
|
|
283
439
|
{
|
|
284
440
|
# Order according to the OpenAPI specification 2.x
|
|
285
441
|
swagger: '2.0',
|
|
286
442
|
info: openapi_objects[:info],
|
|
287
443
|
host: openapi_objects[:host] || uri&.hostname,
|
|
288
|
-
basePath: openapi_objects[:base_path]
|
|
444
|
+
basePath: openapi_objects[:base_path] || uri&.path,
|
|
289
445
|
schemes: openapi_objects[:schemes] || Array(uri&.scheme).presence,
|
|
290
|
-
consumes:
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
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,
|
|
296
459
|
paths: openapi_paths,
|
|
297
460
|
definitions: openapi_objects[:schemas],
|
|
298
461
|
parameters: openapi_objects[:parameters],
|
|
@@ -302,7 +465,7 @@ module Jsapi
|
|
|
302
465
|
else
|
|
303
466
|
{
|
|
304
467
|
# Order according to the OpenAPI specification 3.x
|
|
305
|
-
openapi: version
|
|
468
|
+
openapi: version,
|
|
306
469
|
info: openapi_objects[:info],
|
|
307
470
|
servers:
|
|
308
471
|
openapi_objects[:servers] ||
|
|
@@ -325,50 +488,13 @@ module Jsapi
|
|
|
325
488
|
tags: openapi_objects[:tags],
|
|
326
489
|
externalDocs: openapi_objects[:external_docs]
|
|
327
490
|
).compact
|
|
328
|
-
)
|
|
329
|
-
end
|
|
330
|
-
|
|
331
|
-
##
|
|
332
|
-
# :method: path_description
|
|
333
|
-
# :args: pathname
|
|
334
|
-
# Returns the most accurate description for the given path.
|
|
335
|
-
|
|
336
|
-
##
|
|
337
|
-
# :method: path_servers
|
|
338
|
-
# :args: pathname
|
|
339
|
-
# Returns the most accurate Server objects for the given path.
|
|
340
|
-
|
|
341
|
-
##
|
|
342
|
-
# :method: path_summary
|
|
343
|
-
# :args: pathname
|
|
344
|
-
# Returns the most accurate summary for the given path.
|
|
345
|
-
|
|
346
|
-
%i[description servers summary].each do |name|
|
|
347
|
-
define_method(:"path_#{name}") do |arg|
|
|
348
|
-
Pathname.from(arg).ancestors.each do |pathname|
|
|
349
|
-
ancestors.each do |ancestor|
|
|
350
|
-
value = ancestor.path(pathname)&.public_send(name)
|
|
351
|
-
return value if value.present?
|
|
352
|
-
end
|
|
353
|
-
end
|
|
354
|
-
nil
|
|
355
|
-
end
|
|
356
|
-
end
|
|
357
|
-
|
|
358
|
-
# Returns a hash containing the Parameter objects that are applicable to all
|
|
359
|
-
# operations in the given path.
|
|
360
|
-
# :args: pathname
|
|
361
|
-
def path_parameters(arg)
|
|
362
|
-
arg = Pathname.from(arg || '')
|
|
363
|
-
|
|
364
|
-
(@path_parameters ||= {})[arg] ||= arg.ancestors.flat_map do |pathname|
|
|
365
|
-
ancestors.filter_map { |ancestor| ancestor.path(pathname)&.parameters }
|
|
366
|
-
end.reduce(&:reverse_merge) || {}
|
|
491
|
+
).as_json
|
|
367
492
|
end
|
|
368
493
|
|
|
369
|
-
# 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.
|
|
370
496
|
def rescue_handler_for(exception)
|
|
371
|
-
|
|
497
|
+
cached_attributes[:rescue_handlers].find { |r| r.match?(exception) }
|
|
372
498
|
end
|
|
373
499
|
|
|
374
500
|
protected
|
|
@@ -383,7 +509,8 @@ module Jsapi
|
|
|
383
509
|
attr_reader :included_definitions
|
|
384
510
|
|
|
385
511
|
def attribute_changed(*) # :nodoc:
|
|
386
|
-
|
|
512
|
+
invalidate_attributes
|
|
513
|
+
super
|
|
387
514
|
end
|
|
388
515
|
|
|
389
516
|
# Invoked whenever it is included in another +Definitions+ instance.
|
|
@@ -400,21 +527,63 @@ module Jsapi
|
|
|
400
527
|
|
|
401
528
|
# rubocop:enable Lint/MissingSuper
|
|
402
529
|
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
@
|
|
407
|
-
@path_parameters = nil
|
|
408
|
-
each_descendant(&:invalidate_ancestors)
|
|
530
|
+
private
|
|
531
|
+
|
|
532
|
+
def cache
|
|
533
|
+
@cache ||= {}
|
|
409
534
|
end
|
|
410
535
|
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
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
|
|
415
553
|
end
|
|
416
554
|
|
|
417
|
-
|
|
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
|
|
418
587
|
|
|
419
588
|
def circular_dependency?(other)
|
|
420
589
|
return true if other == self
|
|
@@ -446,25 +615,6 @@ module Jsapi
|
|
|
446
615
|
nil
|
|
447
616
|
end
|
|
448
617
|
|
|
449
|
-
def objects
|
|
450
|
-
@objects ||= ancestors.each_with_object({}) do |ancestor, objects|
|
|
451
|
-
self.class.attribute_names.each do |key|
|
|
452
|
-
case value = ancestor.send(key)
|
|
453
|
-
when Array
|
|
454
|
-
(objects[key] ||= []).push(*value)
|
|
455
|
-
when Hash
|
|
456
|
-
if (hash = objects[key])
|
|
457
|
-
value.each { |k, v| hash[k] = v unless hash.key?(k) }
|
|
458
|
-
else
|
|
459
|
-
objects[key] = value.dup
|
|
460
|
-
end
|
|
461
|
-
else
|
|
462
|
-
objects[key] ||= value
|
|
463
|
-
end
|
|
464
|
-
end
|
|
465
|
-
end
|
|
466
|
-
end
|
|
467
|
-
|
|
468
618
|
def object_to_openapi(object, version)
|
|
469
619
|
case object
|
|
470
620
|
when Array
|