swagger-blocks 1.0.1 → 1.1
Sign up to get free protection for your applications and to get access to all the features.
- 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
|