swagger-blocks 1.0.1 → 1.1
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 +5 -13
- data/README.md +168 -75
- data/README_v1_2.md +141 -0
- data/lib/swagger/blocks.rb +432 -90
- data/lib/swagger/blocks/version.rb +1 -1
- data/spec/lib/swagger_blocks_spec.rb +2 -2
- data/spec/lib/swagger_v2_api_declaration.json +224 -0
- data/spec/lib/swagger_v2_blocks_spec.rb +256 -0
- metadata +21 -16
data/lib/swagger/blocks.rb
CHANGED
@@ -3,10 +3,12 @@ require 'swagger/blocks/version'
|
|
3
3
|
|
4
4
|
module Swagger
|
5
5
|
module Blocks
|
6
|
+
|
6
7
|
# Some custom error classes.
|
7
8
|
class Error < Exception; end
|
8
9
|
class DeclarationError < Error; end
|
9
10
|
class NotFoundError < Error; end
|
11
|
+
class NotSupportedError < Error; end
|
10
12
|
|
11
13
|
# Inject the swagger_root, swagger_api_root, and swagger_model class methods.
|
12
14
|
def self.included(base)
|
@@ -15,11 +17,26 @@ module Swagger
|
|
15
17
|
|
16
18
|
def self.build_root_json(swaggered_classes)
|
17
19
|
data = Swagger::Blocks::InternalHelpers.parse_swaggered_classes(swaggered_classes)
|
20
|
+
|
21
|
+
if data[:root_node].is_swagger_2_0?
|
22
|
+
data[:root_node].key(:paths, data[:path_nodes]) # Required, so no empty check.
|
23
|
+
if data[:schema_nodes] && !data[:schema_nodes].empty?
|
24
|
+
data[:root_node].key(:definitions, data[:schema_nodes])
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
18
28
|
data[:root_node].as_json
|
19
29
|
end
|
20
30
|
|
21
31
|
def self.build_api_json(resource_name, swaggered_classes)
|
22
32
|
data = Swagger::Blocks::InternalHelpers.parse_swaggered_classes(swaggered_classes)
|
33
|
+
if !data[:root_node].is_swagger_1_2?
|
34
|
+
raise NotSupportedError.new(
|
35
|
+
'build_api_json only supports Swagger 1.2, you do not need to call this method ' +
|
36
|
+
'for Swagger >= 2.0 definitions.'
|
37
|
+
)
|
38
|
+
end
|
39
|
+
|
23
40
|
api_node = data[:api_node_map][resource_name.to_sym]
|
24
41
|
raise Swagger::Blocks::NotFoundError.new(
|
25
42
|
"Not found: swagger_api_root named #{resource_name}") if !api_node
|
@@ -36,27 +53,48 @@ module Swagger
|
|
36
53
|
# Return [root_node, api_node_map] from all of the given swaggered_classes.
|
37
54
|
def self.parse_swaggered_classes(swaggered_classes)
|
38
55
|
root_nodes = []
|
56
|
+
|
39
57
|
api_node_map = {}
|
40
58
|
models_nodes = []
|
59
|
+
|
60
|
+
path_node_map = {}
|
61
|
+
schema_node_map = {}
|
41
62
|
swaggered_classes.each do |swaggered_class|
|
42
|
-
next
|
63
|
+
next unless swaggered_class.respond_to?(:_swagger_nodes, true)
|
43
64
|
swagger_nodes = swaggered_class.send(:_swagger_nodes)
|
44
|
-
root_node = swagger_nodes[:
|
65
|
+
root_node = swagger_nodes[:root_node]
|
45
66
|
root_nodes << root_node if root_node
|
46
|
-
api_node_map.merge!(swagger_nodes[:api_node_map])
|
47
|
-
models_nodes << swagger_nodes[:models_node] if swagger_nodes[:models_node]
|
48
|
-
end
|
49
|
-
root_node = self.get_resource_listing(root_nodes)
|
50
67
|
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
68
|
+
# 2.0
|
69
|
+
if swagger_nodes[:path_node_map]
|
70
|
+
path_node_map.merge!(swagger_nodes[:path_node_map])
|
71
|
+
end
|
72
|
+
if swagger_nodes[:schema_node_map]
|
73
|
+
schema_node_map.merge!(swagger_nodes[:schema_node_map])
|
74
|
+
end
|
75
|
+
|
76
|
+
# 1.2
|
77
|
+
if swagger_nodes[:api_node_map]
|
78
|
+
api_node_map.merge!(swagger_nodes[:api_node_map])
|
79
|
+
end
|
80
|
+
if swagger_nodes[:models_node]
|
81
|
+
models_nodes << swagger_nodes[:models_node]
|
82
|
+
end
|
83
|
+
end
|
84
|
+
data = {root_node: self.limit_root_node(root_nodes)}
|
85
|
+
if data[:root_node].is_swagger_2_0?
|
86
|
+
data[:path_nodes] = path_node_map
|
87
|
+
data[:schema_nodes] = schema_node_map
|
88
|
+
else
|
89
|
+
data[:api_node_map] = api_node_map
|
90
|
+
data[:models_nodes] = models_nodes
|
91
|
+
end
|
92
|
+
data
|
56
93
|
end
|
57
94
|
|
58
95
|
# Make sure there is exactly one root_node and return it.
|
59
|
-
|
96
|
+
# TODO should this merge the contents of the root nodes instead?
|
97
|
+
def self.limit_root_node(root_nodes)
|
60
98
|
if root_nodes.length == 0
|
61
99
|
raise Swagger::Blocks::DeclarationError.new(
|
62
100
|
'swagger_root must be declared')
|
@@ -71,17 +109,19 @@ module Swagger
|
|
71
109
|
module ClassMethods
|
72
110
|
private
|
73
111
|
|
74
|
-
# Defines a Swagger Resource Listing.
|
75
|
-
# http://goo.gl/PvwUXj#51-resource-listing
|
112
|
+
# v1.2: Defines a Swagger Resource Listing.
|
113
|
+
# v1.2: http://goo.gl/PvwUXj#51-resource-listing
|
114
|
+
# v2.0: Defines a Swagger Object
|
115
|
+
# v2.0: https://github.com/swagger-api/swagger-spec/blob/master/versions/2.0.md#swagger-object
|
76
116
|
def swagger_root(&block)
|
77
|
-
@swagger_root_node ||= Swagger::Blocks::
|
117
|
+
@swagger_root_node ||= Swagger::Blocks::RootNode.call(&block)
|
78
118
|
end
|
79
119
|
|
80
|
-
# Defines a Swagger API Declaration.
|
81
|
-
# http://goo.gl/PvwUXj#52-api-declaration
|
82
|
-
#
|
83
|
-
# @param resource_name [Symbol] An identifier for this API. All swagger_api_root declarations
|
84
|
-
# with the same resource_name will be
|
120
|
+
# v1.2: Defines a Swagger API Declaration.
|
121
|
+
# v1.2: http://goo.gl/PvwUXj#52-api-declaration
|
122
|
+
# v1.2:
|
123
|
+
# v1.2: @param resource_name [Symbol] An identifier for this API. All swagger_api_root declarations
|
124
|
+
# v1.2: with the same resource_name will be into a single API root node.
|
85
125
|
def swagger_api_root(resource_name, &block)
|
86
126
|
resource_name = resource_name.to_sym
|
87
127
|
|
@@ -96,30 +136,73 @@ module Swagger
|
|
96
136
|
api_node.instance_eval(&block)
|
97
137
|
else
|
98
138
|
# First time we've seen this `swagger_api_root :resource_name`.
|
99
|
-
api_node = Swagger::Blocks::ApiDeclarationNode.call(&block)
|
139
|
+
api_node = Swagger::Blocks::ApiDeclarationNode.call(version: '1.2', &block)
|
100
140
|
end
|
101
141
|
|
102
142
|
# Add it into the resource_name to node map (may harmlessly overwrite the same object).
|
103
143
|
@swagger_api_root_node_map[resource_name] = api_node
|
104
144
|
end
|
105
145
|
|
106
|
-
# Defines a Swagger
|
107
|
-
#
|
146
|
+
# v2.0: Defines a Swagger Path Item object
|
147
|
+
# https://github.com/swagger-api/swagger-spec/blob/master/versions/2.0.md#path-item-object
|
148
|
+
def swagger_path(path, &block)
|
149
|
+
path = path.to_sym
|
150
|
+
|
151
|
+
# TODO enforce that path name begins with a '/'
|
152
|
+
# (or x- , but need to research Vendor Extensions first)
|
153
|
+
|
154
|
+
@swagger_path_node_map ||= {}
|
155
|
+
|
156
|
+
path_node = @swagger_path_node_map[path]
|
157
|
+
if path_node
|
158
|
+
# Merge this path declaration into the previous one
|
159
|
+
path_node.instance_eval(&block)
|
160
|
+
else
|
161
|
+
# First time we've seen this path
|
162
|
+
@swagger_path_node_map[path] = Swagger::Blocks::PathNode.call(version: '2.0', &block)
|
163
|
+
end
|
164
|
+
end
|
165
|
+
|
166
|
+
# v1.2: Defines a Swagger Model.
|
167
|
+
# v1.2: http://goo.gl/PvwUXj#526-models-object
|
108
168
|
def swagger_model(name, &block)
|
109
169
|
@swagger_models_node ||= Swagger::Blocks::ModelsNode.new
|
170
|
+
@swagger_models_node.version = '1.2'
|
110
171
|
@swagger_models_node.model(name, &block)
|
111
172
|
end
|
112
173
|
|
174
|
+
# v2.0: Defines a Swagger Definition Schema,
|
175
|
+
# v2.0: https://github.com/swagger-api/swagger-spec/blob/master/versions/2.0.md#definitionsObject and
|
176
|
+
# v2.0: https://github.com/swagger-api/swagger-spec/blob/master/versions/2.0.md#schema-object
|
177
|
+
def swagger_schema(name, &block)
|
178
|
+
@swagger_schema_node_map ||= {}
|
179
|
+
|
180
|
+
schema_node = @swagger_schema_node_map[name]
|
181
|
+
if schema_node
|
182
|
+
# Merge this schema_node declaration into the previous one
|
183
|
+
schema_node.instance_eval(&block)
|
184
|
+
else
|
185
|
+
# First time we've seen this schema_node
|
186
|
+
@swagger_schema_node_map[name] = Swagger::Blocks::SchemaNode.call(version: '2.0', &block)
|
187
|
+
end
|
188
|
+
end
|
189
|
+
|
113
190
|
def _swagger_nodes
|
114
|
-
|
191
|
+
# Avoid initialization warnings.
|
192
|
+
@swagger_root_node ||= nil
|
193
|
+
@swagger_path_node_map ||= {}
|
194
|
+
@swagger_schema_node_map ||= nil
|
115
195
|
@swagger_api_root_node_map ||= {}
|
116
196
|
@swagger_models_node ||= nil
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
197
|
+
|
198
|
+
data = {root_node: @swagger_root_node}
|
199
|
+
data[:path_node_map] = @swagger_path_node_map
|
200
|
+
data[:schema_node_map] = @swagger_schema_node_map
|
201
|
+
data[:api_node_map] = @swagger_api_root_node_map
|
202
|
+
data[:models_node] = @swagger_models_node
|
203
|
+
data
|
122
204
|
end
|
205
|
+
|
123
206
|
end
|
124
207
|
|
125
208
|
# -----
|
@@ -127,29 +210,37 @@ module Swagger
|
|
127
210
|
# Base node for representing every object in the Swagger DSL.
|
128
211
|
class Node
|
129
212
|
attr_accessor :name
|
213
|
+
attr_writer :version
|
130
214
|
|
131
215
|
def self.call(options = {}, &block)
|
132
216
|
# Create a new instance and evaluate the block into it.
|
133
217
|
instance = new
|
134
218
|
instance.name = options[:name] if options[:name]
|
219
|
+
instance.version = options[:version]
|
135
220
|
instance.instance_eval(&block)
|
136
221
|
instance
|
137
222
|
end
|
138
223
|
|
139
224
|
def as_json
|
140
225
|
result = {}
|
226
|
+
|
141
227
|
self.data.each do |key, value|
|
142
228
|
if value.is_a?(Node)
|
143
229
|
result[key] = value.as_json
|
144
230
|
elsif value.is_a?(Array)
|
145
231
|
result[key] = []
|
146
232
|
value.each { |v| result[key] << (v.respond_to?(:as_json) ? v.as_json : v) }
|
233
|
+
elsif is_swagger_2_0? && value.is_a?(Hash)
|
234
|
+
result[key] = {}
|
235
|
+
value.each_pair {|k, v| result[key][k] = (v.respond_to?(:as_json) ? v.as_json : v) }
|
236
|
+
elsif is_swagger_2_0? && key.to_s.eql?('$ref') && (value.to_s !~ %r{^#/definitions/})
|
237
|
+
result[key] = "#/definitions/#{value}"
|
147
238
|
else
|
148
239
|
result[key] = value
|
149
240
|
end
|
150
241
|
end
|
151
242
|
return result if !name
|
152
|
-
# If
|
243
|
+
# If 'name' is given to this node, wrap the data with a root element with the given name.
|
153
244
|
{name => result}
|
154
245
|
end
|
155
246
|
|
@@ -160,118 +251,191 @@ module Swagger
|
|
160
251
|
def key(key, value)
|
161
252
|
self.data[key] = value
|
162
253
|
end
|
163
|
-
end
|
164
254
|
|
165
|
-
|
166
|
-
|
167
|
-
|
255
|
+
def version
|
256
|
+
return @version if instance_variable_defined?('@version') && @version
|
257
|
+
if data.has_key?(:swagger) && data[:swagger] == '2.0'
|
258
|
+
'2.0'
|
259
|
+
elsif data.has_key?(:swaggerVersion) && data[:swaggerVersion] == '1.2'
|
260
|
+
'1.2'
|
261
|
+
else
|
262
|
+
raise DeclarationError.new("You must specify swaggerVersion '1.2' or swagger '2.0'")
|
263
|
+
end
|
264
|
+
end
|
168
265
|
|
169
|
-
|
170
|
-
|
266
|
+
def is_swagger_1_2?
|
267
|
+
version == '1.2'
|
268
|
+
end
|
269
|
+
|
270
|
+
def is_swagger_2_0?
|
271
|
+
version == '2.0'
|
272
|
+
end
|
273
|
+
end
|
274
|
+
|
275
|
+
class RootNode < Node
|
171
276
|
def initialize(*args)
|
172
277
|
# An internal list of the user-defined names that uniquely identify each API tree.
|
278
|
+
# Only used in Swagger 1.2, but when initializing a root node we haven't seen the
|
279
|
+
# swaggerVersion/swagger key yet
|
173
280
|
@api_paths = []
|
174
281
|
super
|
175
282
|
end
|
176
283
|
|
177
284
|
def has_api_path?(api_path)
|
285
|
+
raise NotSupportedError unless is_swagger_1_2?
|
286
|
+
|
178
287
|
api_paths = self.data[:apis].map { |x| x.data[:path] }
|
179
288
|
api_paths.include?(api_path)
|
180
289
|
end
|
181
290
|
|
182
|
-
def info(&block)
|
183
|
-
self.data[:info] = InfoNode.call(&block)
|
184
|
-
end
|
185
|
-
|
186
291
|
def authorization(name, &block)
|
292
|
+
raise NotSupportedError unless is_swagger_1_2?
|
293
|
+
|
187
294
|
self.data[:authorizations] ||= Swagger::Blocks::ResourceListingAuthorizationsNode.new
|
295
|
+
self.data[:authorizations].version = version
|
188
296
|
self.data[:authorizations].authorization(name, &block)
|
189
297
|
end
|
190
298
|
|
299
|
+
def info(&block)
|
300
|
+
self.data[:info] = Swagger::Blocks::InfoNode.call(version: version, &block)
|
301
|
+
end
|
302
|
+
|
191
303
|
def api(&block)
|
304
|
+
raise NotSupportedError unless is_swagger_1_2?
|
305
|
+
|
192
306
|
self.data[:apis] ||= []
|
193
|
-
self.data[:apis] << Swagger::Blocks::ResourceNode.call(&block)
|
307
|
+
self.data[:apis] << Swagger::Blocks::ResourceNode.call(version: version, &block)
|
308
|
+
end
|
309
|
+
|
310
|
+
def parameter(param, &block)
|
311
|
+
raise NotSupportedError unless is_swagger_2_0?
|
312
|
+
|
313
|
+
# TODO validate 'param' is as per spec
|
314
|
+
self.data[:parameters] ||= {}
|
315
|
+
self.data[:parameters][param] = Swagger::Blocks::ParameterNode.call(version: version, &block)
|
316
|
+
end
|
317
|
+
|
318
|
+
def response(resp, &block)
|
319
|
+
raise NotSupportedError unless is_swagger_2_0?
|
320
|
+
|
321
|
+
# TODO validate 'resp' is as per spec
|
322
|
+
self.data[:responses] ||= {}
|
323
|
+
self.data[:responses][resp] = Swagger::Blocks::ResponseNode.call(version: version, &block)
|
324
|
+
end
|
325
|
+
|
326
|
+
def security_definition(name, &block)
|
327
|
+
raise NotSupportedError unless is_swagger_2_0?
|
328
|
+
|
329
|
+
self.data[:securityDefinitions] ||= {}
|
330
|
+
self.data[:securityDefinitions][name] = Swagger::Blocks::SecuritySchemeNode.call(version: version, &block)
|
331
|
+
end
|
332
|
+
|
333
|
+
def security(&block)
|
334
|
+
raise NotSupportedError unless is_swagger_2_0?
|
335
|
+
|
336
|
+
self.data[:security] ||= []
|
337
|
+
self.data[:security] << Swagger::Blocks::SecurityRequirementNode.call(version: version, &block)
|
194
338
|
end
|
195
339
|
end
|
196
340
|
|
197
|
-
# http://goo.gl/PvwUXj#512-resource-object
|
341
|
+
# v1.2: http://goo.gl/PvwUXj#512-resource-object
|
198
342
|
class ResourceNode < Node; end
|
199
343
|
|
200
|
-
# NOTE: in the spec this is different than API Declaration authorizations.
|
201
|
-
# http://goo.gl/PvwUXj#514-authorizations-object
|
344
|
+
# v1.2: NOTE: in the spec this is different than API Declaration authorizations.
|
345
|
+
# v1.2: http://goo.gl/PvwUXj#514-authorizations-object
|
202
346
|
class ResourceListingAuthorizationsNode < Node
|
203
347
|
def authorization(name, &block)
|
204
|
-
self.data[name] = Swagger::Blocks::ResourceListingAuthorizationNode.call(&block)
|
348
|
+
self.data[name] = Swagger::Blocks::ResourceListingAuthorizationNode.call(version: version, &block)
|
205
349
|
end
|
206
350
|
end
|
207
351
|
|
208
|
-
# NOTE: in the spec this is different than API Declaration authorization.
|
209
|
-
# http://goo.gl/PvwUXj#515-authorization-object
|
352
|
+
# v1.2: NOTE: in the spec this is different than API Declaration authorization.
|
353
|
+
# v1.2: http://goo.gl/PvwUXj#515-authorization-object
|
210
354
|
class ResourceListingAuthorizationNode < Node
|
211
355
|
GRANT_TYPES = [:implicit, :authorization_code].freeze
|
212
356
|
|
213
357
|
def scope(&block)
|
214
358
|
self.data[:scopes] ||= []
|
215
|
-
self.data[:scopes] << Swagger::Blocks::ScopeNode.call(&block)
|
359
|
+
self.data[:scopes] << Swagger::Blocks::ScopeNode.call(version: version, &block)
|
216
360
|
end
|
217
361
|
|
218
362
|
def grant_type(name, &block)
|
219
363
|
raise ArgumentError.new("#{name} not in #{GRANT_TYPES}") if !GRANT_TYPES.include?(name)
|
220
364
|
self.data[:grantTypes] ||= Swagger::Blocks::GrantTypesNode.new
|
365
|
+
self.data[:grantTypes].version = version
|
221
366
|
self.data[:grantTypes].implicit(&block) if name == :implicit
|
222
367
|
self.data[:grantTypes].authorization_code(&block) if name == :authorization_code
|
223
368
|
end
|
224
369
|
end
|
225
370
|
|
226
|
-
# http://goo.gl/PvwUXj#513-info-object
|
227
|
-
|
371
|
+
# v1.2: http://goo.gl/PvwUXj#513-info-object
|
372
|
+
# v2.0: https://github.com/swagger-api/swagger-spec/blob/master/versions/2.0.md#infoObject
|
373
|
+
class InfoNode < Node
|
374
|
+
def contact(&block)
|
375
|
+
raise NotSupportedError unless is_swagger_2_0?
|
376
|
+
|
377
|
+
self.data[:contact] = Swagger::Blocks::ContactNode.call(version: version, &block)
|
378
|
+
end
|
228
379
|
|
229
|
-
|
380
|
+
def license(&block)
|
381
|
+
raise NotSupportedError unless is_swagger_2_0?
|
382
|
+
|
383
|
+
self.data[:license] = Swagger::Blocks::LicenseNode.call(version: version, &block)
|
384
|
+
end
|
385
|
+
end
|
386
|
+
|
387
|
+
# v2.0: https://github.com/swagger-api/swagger-spec/blob/master/versions/2.0.md#contact-object
|
388
|
+
class ContactNode < Node; end
|
389
|
+
|
390
|
+
# v2.0: https://github.com/swagger-api/swagger-spec/blob/master/versions/2.0.md#license-object
|
391
|
+
class LicenseNode < Node; end
|
392
|
+
|
393
|
+
# v1.2: http://goo.gl/PvwUXj#516-scope-object
|
230
394
|
class ScopeNode < Node; end
|
231
395
|
|
232
|
-
# http://goo.gl/PvwUXj#517-grant-types-object
|
396
|
+
# v1.2: http://goo.gl/PvwUXj#517-grant-types-object
|
233
397
|
class GrantTypesNode < Node
|
234
398
|
def implicit(&block)
|
235
|
-
self.data[:implicit] = Swagger::Blocks::ImplicitNode.call(&block)
|
399
|
+
self.data[:implicit] = Swagger::Blocks::ImplicitNode.call(version: version, &block)
|
236
400
|
end
|
237
401
|
|
238
402
|
def authorization_code(&block)
|
239
|
-
self.data[:authorization_code] = Swagger::Blocks::AuthorizationCodeNode.call(&block)
|
403
|
+
self.data[:authorization_code] = Swagger::Blocks::AuthorizationCodeNode.call(version: version, &block)
|
240
404
|
end
|
241
405
|
end
|
242
406
|
|
243
|
-
# http://goo.gl/PvwUXj#518-implicit-object
|
407
|
+
# v1.2: http://goo.gl/PvwUXj#518-implicit-object
|
244
408
|
class ImplicitNode < Node
|
245
409
|
def login_endpoint(&block)
|
246
|
-
self.data[:loginEndpoint] = Swagger::Blocks::LoginEndpointNode.call(&block)
|
410
|
+
self.data[:loginEndpoint] = Swagger::Blocks::LoginEndpointNode.call(version: version, &block)
|
247
411
|
end
|
248
412
|
end
|
249
413
|
|
250
|
-
# http://goo.gl/PvwUXj#5110-login-endpoint-object
|
414
|
+
# v1.2: http://goo.gl/PvwUXj#5110-login-endpoint-object
|
251
415
|
class LoginEndpointNode < Node; end
|
252
416
|
|
253
|
-
# http://goo.gl/PvwUXj#519-authorization-code-object
|
417
|
+
# v1.2: http://goo.gl/PvwUXj#519-authorization-code-object
|
254
418
|
class AuthorizationCodeNode < Node
|
255
419
|
def token_request_endpoint(&block)
|
256
|
-
self.data[:tokenRequestEndpoint] = Swagger::Blocks::TokenRequestEndpointNode.call(&block)
|
420
|
+
self.data[:tokenRequestEndpoint] = Swagger::Blocks::TokenRequestEndpointNode.call(version: version, &block)
|
257
421
|
end
|
258
422
|
|
259
423
|
def token_endpoint(&block)
|
260
|
-
self.data[:tokenEndpoint] = Swagger::Blocks::TokenEndpointNode.call(&block)
|
424
|
+
self.data[:tokenEndpoint] = Swagger::Blocks::TokenEndpointNode.call(version: version, &block)
|
261
425
|
end
|
262
426
|
end
|
263
427
|
|
264
|
-
# http://goo.gl/PvwUXj#5111-token-request-endpoint-object
|
428
|
+
# v1.2: http://goo.gl/PvwUXj#5111-token-request-endpoint-object
|
265
429
|
class TokenRequestEndpointNode < Node; end
|
266
430
|
|
267
|
-
# http://goo.gl/PvwUXj#5112-token-endpoint-object
|
431
|
+
# v1.2: http://goo.gl/PvwUXj#5112-token-endpoint-object
|
268
432
|
class TokenEndpointNode < Node; end
|
269
433
|
|
270
434
|
# -----
|
271
|
-
# Nodes for API Declarations.
|
435
|
+
# v1.2: Nodes for API Declarations.
|
272
436
|
# -----
|
273
437
|
|
274
|
-
# http://goo.gl/PvwUXj#52-api-declaration
|
438
|
+
# v1.2: http://goo.gl/PvwUXj#52-api-declaration
|
275
439
|
class ApiDeclarationNode < Node
|
276
440
|
def api(&block)
|
277
441
|
self.data[:apis] ||= []
|
@@ -283,7 +447,7 @@ module Swagger
|
|
283
447
|
# http://goo.gl/PvwUXj#522-api-object
|
284
448
|
# - The API Object describes one or more operations on a single path. In the apis array,
|
285
449
|
# there MUST be only one API Object per path.
|
286
|
-
temp_api_node = Swagger::Blocks::ApiNode.call(&block)
|
450
|
+
temp_api_node = Swagger::Blocks::ApiNode.call(version: version, &block)
|
287
451
|
api_node = self.data[:apis].select do |api|
|
288
452
|
api.data[:path] == temp_api_node.data[:path]
|
289
453
|
end[0] # Embrace Ruby wtfs.
|
@@ -298,45 +462,104 @@ module Swagger
|
|
298
462
|
end
|
299
463
|
end
|
300
464
|
|
301
|
-
# http://goo.gl/PvwUXj#522-api-object
|
465
|
+
# v1.2: http://goo.gl/PvwUXj#522-api-object
|
302
466
|
class ApiNode < Node
|
303
467
|
def operation(&block)
|
304
468
|
self.data[:operations] ||= []
|
305
|
-
self.data[:operations] << Swagger::Blocks::OperationNode.call(&block)
|
469
|
+
self.data[:operations] << Swagger::Blocks::OperationNode.call(version: version, &block)
|
306
470
|
end
|
307
471
|
end
|
308
472
|
|
473
|
+
# v2.0: https://github.com/swagger-api/swagger-spec/blob/master/versions/2.0.md#path-item-object
|
474
|
+
class PathNode < Node
|
475
|
+
OPERATION_TYPES = [:get, :put, :post, :delete, :options, :head, :patch].freeze
|
476
|
+
|
477
|
+
# TODO support ^x- Vendor Extensions
|
478
|
+
def operation(op, &block)
|
479
|
+
op = op.to_sym
|
480
|
+
raise ArgumentError.new("#{name} not in #{OPERATION_TYPES}") if !OPERATION_TYPES.include?(op)
|
481
|
+
self.data[op] = Swagger::Blocks::OperationNode.call(version: version, &block)
|
482
|
+
end
|
483
|
+
end
|
484
|
+
|
485
|
+
# v1.2: http://goo.gl/PvwUXj#523-operation-object
|
486
|
+
# v2.0: https://github.com/swagger-api/swagger-spec/blob/master/versions/2.0.md#operation-object
|
309
487
|
class OperationNode < Node
|
488
|
+
|
310
489
|
def parameter(&block)
|
311
490
|
self.data[:parameters] ||= []
|
312
|
-
self.data[:parameters] << Swagger::Blocks::ParameterNode.call(&block)
|
491
|
+
self.data[:parameters] << Swagger::Blocks::ParameterNode.call(version: version, &block)
|
313
492
|
end
|
314
493
|
|
315
494
|
def response_message(&block)
|
495
|
+
raise NotSupportedError unless is_swagger_1_2?
|
496
|
+
|
316
497
|
self.data[:responseMessages] ||= []
|
317
|
-
self.data[:responseMessages] << Swagger::Blocks::Node.call(&block)
|
498
|
+
self.data[:responseMessages] << Swagger::Blocks::Node.call(version: version, &block)
|
318
499
|
end
|
319
500
|
|
320
501
|
def authorization(name, &block)
|
502
|
+
raise NotSupportedError unless is_swagger_1_2?
|
503
|
+
|
321
504
|
self.data[:authorizations] ||= Swagger::Blocks::ApiAuthorizationsNode.new
|
505
|
+
self.data[:authorizations].version = version
|
322
506
|
self.data[:authorizations].authorization(name, &block)
|
323
507
|
end
|
324
508
|
|
325
509
|
def items(&block)
|
326
|
-
|
510
|
+
raise NotSupportedError unless is_swagger_1_2?
|
511
|
+
|
512
|
+
self.data[:items] = Swagger::Blocks::ItemsNode.call(version: version, &block)
|
513
|
+
end
|
514
|
+
|
515
|
+
def response(resp, &block)
|
516
|
+
raise NotSupportedError unless is_swagger_2_0?
|
517
|
+
|
518
|
+
# TODO validate 'resp' is as per spec
|
519
|
+
self.data[:responses] ||= {}
|
520
|
+
self.data[:responses][resp] = Swagger::Blocks::ResponseNode.call(version: version, &block)
|
521
|
+
end
|
522
|
+
|
523
|
+
def externalDocs(&block)
|
524
|
+
raise NotSupportedError unless is_swagger_2_0?
|
525
|
+
|
526
|
+
self.data[:externalDocs] = Swagger::Blocks::ExternalDocsNode.call(version: version, &block)
|
527
|
+
end
|
528
|
+
|
529
|
+
def security(&block)
|
530
|
+
raise NotSupportedError unless is_swagger_2_0?
|
531
|
+
|
532
|
+
self.data[:security] ||= []
|
533
|
+
self.data[:security] << Swagger::Blocks::SecurityRequirementNode.call(version: version, &block)
|
534
|
+
end
|
535
|
+
end
|
536
|
+
|
537
|
+
# v2.0: https://github.com/swagger-api/swagger-spec/blob/master/versions/2.0.md#externalDocumentationObject
|
538
|
+
class ExternalDocsNode < Node; end
|
539
|
+
|
540
|
+
# v2.0: https://github.com/swagger-api/swagger-spec/blob/master/versions/2.0.md#securityRequirementObject
|
541
|
+
class SecurityRequirementNode < Node; end
|
542
|
+
|
543
|
+
# v2.0: https://github.com/swagger-api/swagger-spec/blob/master/versions/2.0.md#security-scheme-object
|
544
|
+
class SecuritySchemeNode < Node
|
545
|
+
# TODO support ^x- Vendor Extensions
|
546
|
+
|
547
|
+
def scope(name, description)
|
548
|
+
self.data[:scopes] ||= {}
|
549
|
+
self.data[:scopes][name] = description
|
327
550
|
end
|
328
551
|
end
|
329
552
|
|
330
|
-
# NOTE: in the spec this is different than Resource Listing's authorizations.
|
331
|
-
# http://goo.gl/PvwUXj#514-authorizations-object
|
553
|
+
# v1.2: NOTE: in the spec this is different than Resource Listing's authorizations.
|
554
|
+
# v1.2: http://goo.gl/PvwUXj#514-authorizations-object
|
332
555
|
class ApiAuthorizationsNode < Node
|
333
556
|
def authorization(name, &block)
|
334
|
-
self.data[name] ||= Swagger::Blocks::ApiAuthorizationNode.call(&block)
|
557
|
+
self.data[name] ||= Swagger::Blocks::ApiAuthorizationNode.call(version: version, &block)
|
335
558
|
end
|
336
559
|
end
|
337
560
|
|
338
|
-
# NOTE: in the spec this is different than Resource Listing's authorization.
|
339
|
-
# http://goo.gl/PvwUXj#515-authorization-object
|
561
|
+
# v1.2: NOTE: in the spec this is different than Resource Listing's authorization.
|
562
|
+
# v1.2: http://goo.gl/PvwUXj#515-authorization-object
|
340
563
|
class ApiAuthorizationNode < Node
|
341
564
|
def as_json
|
342
565
|
# Special case: the API Authorization object is weirdly the only array of hashes.
|
@@ -347,55 +570,174 @@ module Swagger
|
|
347
570
|
|
348
571
|
def scope(&block)
|
349
572
|
self.data[:_scopes] ||= []
|
350
|
-
self.data[:_scopes] << Swagger::Blocks::ApiAuthorizationScopeNode.call(&block)
|
573
|
+
self.data[:_scopes] << Swagger::Blocks::ApiAuthorizationScopeNode.call(version: version, &block)
|
351
574
|
end
|
352
575
|
end
|
353
576
|
|
354
|
-
# NOTE: in the spec this is different than Resource Listing's scope object.
|
355
|
-
# http://goo.gl/PvwUXj#5211-scope-object
|
577
|
+
# v1.2: NOTE: in the spec this is different than Resource Listing's scope object.
|
578
|
+
# v1.2: http://goo.gl/PvwUXj#5211-scope-object
|
356
579
|
class ApiAuthorizationScopeNode < Node; end
|
357
580
|
|
358
|
-
#
|
581
|
+
# v2.0: https://github.com/swagger-api/swagger-spec/blob/master/versions/2.0.md#responseObject
|
582
|
+
class ResponseNode < Node
|
583
|
+
def schema(&block)
|
584
|
+
self.data[:schema] = Swagger::Blocks::SchemaNode.call(version: version, &block)
|
585
|
+
end
|
586
|
+
|
587
|
+
def header(head, &block)
|
588
|
+
# TODO validate 'head' is as per spec
|
589
|
+
self.data[:headers] ||= {}
|
590
|
+
self.data[:headers][head] = Swagger::Blocks::HeaderNode.call(version: version, &block)
|
591
|
+
end
|
592
|
+
|
593
|
+
def example(exam, &block)
|
594
|
+
# TODO validate 'exam' is as per spec
|
595
|
+
self.data[:examples] ||= {}
|
596
|
+
self.data[:examples][exam] = Swagger::Blocks::ExampleNode.call(version: version, &block)
|
597
|
+
end
|
598
|
+
end
|
599
|
+
|
600
|
+
class AllOfNode < Node
|
601
|
+
def as_json
|
602
|
+
result = []
|
603
|
+
|
604
|
+
self.data.each do |value|
|
605
|
+
if value.is_a?(Node)
|
606
|
+
result << value.as_json
|
607
|
+
elsif value.is_a?(Array)
|
608
|
+
r = []
|
609
|
+
value.each { |v| r << (v.respond_to?(:as_json) ? v.as_json : v) }
|
610
|
+
result << r
|
611
|
+
elsif is_swagger_2_0? && value.is_a?(Hash)
|
612
|
+
r = {}
|
613
|
+
value.each_pair {|k, v| r[k] = (v.respond_to?(:as_json) ? v.as_json : v) }
|
614
|
+
result << r
|
615
|
+
else
|
616
|
+
result = value
|
617
|
+
end
|
618
|
+
end
|
619
|
+
return result if !name
|
620
|
+
# If 'name' is given to this node, wrap the data with a root element with the given name.
|
621
|
+
{name => result}
|
622
|
+
end
|
623
|
+
|
624
|
+
def data
|
625
|
+
@data ||= []
|
626
|
+
end
|
627
|
+
|
628
|
+
def key(key, value)
|
629
|
+
raise NotSupportedError
|
630
|
+
end
|
631
|
+
|
632
|
+
def schema(&block)
|
633
|
+
data << Swagger::Blocks::SchemaNode.call(version: version, &block)
|
634
|
+
end
|
635
|
+
end
|
636
|
+
|
637
|
+
# v2.0: https://github.com/swagger-api/swagger-spec/blob/master/versions/2.0.md#schema-object
|
638
|
+
class SchemaNode < Node
|
639
|
+
def items(&block)
|
640
|
+
self.data[:items] = Swagger::Blocks::ItemsNode.call(version: version, &block)
|
641
|
+
end
|
642
|
+
|
643
|
+
def allOf(&block)
|
644
|
+
self.data[:allOf] = Swagger::Blocks::AllOfNode.call(version: version, &block)
|
645
|
+
end
|
646
|
+
|
647
|
+
def property(name, &block)
|
648
|
+
self.data[:properties] ||= Swagger::Blocks::PropertiesNode.new
|
649
|
+
self.data[:properties].version = version
|
650
|
+
self.data[:properties].property(name, &block)
|
651
|
+
end
|
652
|
+
|
653
|
+
def xml(&block)
|
654
|
+
self.data[:xml] = Swagger::Blocks::XmlNode.call(version: version, &block)
|
655
|
+
end
|
656
|
+
|
657
|
+
def externalDocs(&block)
|
658
|
+
self.data[:externalDocs] = Swagger::Blocks::ExternalDocsNode.call(version: version, &block)
|
659
|
+
end
|
660
|
+
end
|
661
|
+
|
662
|
+
# v2.0: https://github.com/swagger-api/swagger-spec/blob/master/versions/2.0.md#headerObject
|
663
|
+
class HeaderNode < Node
|
664
|
+
def items(&block)
|
665
|
+
self.data[:items] = Swagger::Blocks::ItemsNode.call(version: version, &block)
|
666
|
+
end
|
667
|
+
end
|
668
|
+
|
669
|
+
# v2.0:
|
670
|
+
class XmlNode < Node; end
|
671
|
+
|
672
|
+
# v2.0:
|
673
|
+
class ExampleNode < Node; end
|
674
|
+
|
675
|
+
# v1.2:
|
676
|
+
# v2.0:
|
359
677
|
class ItemsNode < Node; end
|
360
678
|
|
361
|
-
# http://goo.gl/PvwUXj#524-parameter-object
|
362
|
-
|
679
|
+
# v1.2: http://goo.gl/PvwUXj#524-parameter-object
|
680
|
+
# v2.0: https://github.com/swagger-api/swagger-spec/blob/master/versions/2.0.md#parameter-object
|
681
|
+
class ParameterNode < Node
|
682
|
+
def schema(&block)
|
683
|
+
raise NotSupportedError unless is_swagger_2_0?
|
684
|
+
|
685
|
+
self.data[:schema] = Swagger::Blocks::SchemaNode.call(version: version, &block)
|
686
|
+
end
|
687
|
+
|
688
|
+
def items(&block)
|
689
|
+
raise NotSupportedError unless is_swagger_2_0?
|
690
|
+
|
691
|
+
self.data[:items] = Swagger::Blocks::ItemsNode.call(version: version, &block)
|
692
|
+
end
|
693
|
+
end
|
694
|
+
|
695
|
+
# v2.0: https://github.com/swagger-api/swagger-spec/blob/master/versions/2.0.md#tag-object
|
696
|
+
class TagNode < Node
|
697
|
+
|
698
|
+
# TODO support ^x- Vendor Extensions
|
699
|
+
|
700
|
+
def externalDocs(&block)
|
701
|
+
self.data[:externalDocs] = Swagger::Blocks::ExternalDocsNode.call(version: version, &block)
|
702
|
+
end
|
703
|
+
end
|
363
704
|
|
364
705
|
# -----
|
365
|
-
# Nodes for Models.
|
706
|
+
# v1.2: Nodes for Models.
|
366
707
|
# -----
|
367
708
|
|
368
|
-
# http://goo.gl/PvwUXj#526-models-object
|
709
|
+
# v1.2: http://goo.gl/PvwUXj#526-models-object
|
369
710
|
class ModelsNode < Node
|
370
711
|
def merge!(other_models_node)
|
371
712
|
self.data.merge!(other_models_node.data)
|
372
713
|
end
|
373
714
|
|
374
715
|
def model(name, &block)
|
375
|
-
self.data[name] ||= Swagger::Blocks::ModelNode.call(&block)
|
716
|
+
self.data[name] ||= Swagger::Blocks::ModelNode.call(version: version, &block)
|
376
717
|
end
|
377
718
|
end
|
378
719
|
|
379
|
-
# http://goo.gl/PvwUXj#527-model-object
|
720
|
+
# v1.2: http://goo.gl/PvwUXj#527-model-object
|
380
721
|
class ModelNode < Node
|
381
722
|
def property(name, &block)
|
382
723
|
self.data[:properties] ||= Swagger::Blocks::PropertiesNode.new
|
724
|
+
self.data[:properties].version = version
|
383
725
|
self.data[:properties].property(name, &block)
|
384
726
|
end
|
385
727
|
end
|
386
728
|
|
387
|
-
# http://goo.gl/PvwUXj#527-model-object
|
729
|
+
# v1.2: http://goo.gl/PvwUXj#527-model-object
|
388
730
|
class PropertiesNode < Node
|
389
731
|
def property(name, &block)
|
390
|
-
self.data[name] = Swagger::Blocks::PropertyNode.call(&block)
|
732
|
+
self.data[name] = Swagger::Blocks::PropertyNode.call(version: version, &block)
|
391
733
|
end
|
392
734
|
end
|
393
735
|
|
394
|
-
# http://goo.gl/PvwUXj#527-model-object
|
736
|
+
# v1.2: http://goo.gl/PvwUXj#527-model-object
|
395
737
|
class PropertyNode < Node
|
396
738
|
def items(&block)
|
397
|
-
self.data[:items] = Swagger::Blocks::ItemsNode.call(&block)
|
739
|
+
self.data[:items] = Swagger::Blocks::ItemsNode.call(version: version, &block)
|
398
740
|
end
|
399
741
|
end
|
400
742
|
end
|
401
|
-
end
|
743
|
+
end
|