scorpio 0.0.4 → 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +8 -0
- data/README.md +37 -14
- data/bin/documents_to_yml.rb +26 -0
- data/documents/swagger.io/v2/schema.json +1607 -0
- data/documents/swagger.io/v2/schema.yml +1079 -0
- data/documents/www.googleapis.com/discovery/v1/apis/discovery/v1/rest +684 -0
- data/{getRest.yml → documents/www.googleapis.com/discovery/v1/apis/discovery/v1/rest.yml} +34 -72
- data/lib/scorpio.rb +30 -1
- data/lib/scorpio/google_api_document.rb +232 -0
- data/lib/scorpio/json-schema-fragments.rb +191 -0
- data/lib/scorpio/json.rb +5 -0
- data/lib/scorpio/json/node.rb +214 -0
- data/lib/scorpio/model.rb +178 -91
- data/lib/scorpio/openapi.rb +81 -0
- data/lib/scorpio/schema.rb +133 -0
- data/lib/scorpio/schema_object_base.rb +227 -0
- data/lib/scorpio/typelike_modules.rb +52 -0
- data/lib/scorpio/version.rb +1 -1
- data/scorpio.gemspec +2 -1
- metadata +20 -8
@@ -1,13 +1,12 @@
|
|
1
|
-
|
1
|
+
---
|
2
2
|
kind: discovery#restDescription
|
3
|
-
etag: '"
|
3
|
+
etag: '"YWOzh2SDasdU84ArJnpYek-OMdg/K3nEDF6hixE8Pks2-9Ysn9j9prQ"'
|
4
4
|
discoveryVersion: v1
|
5
5
|
id: discovery:v1
|
6
6
|
name: discovery
|
7
7
|
version: v1
|
8
8
|
title: APIs Discovery Service
|
9
|
-
description: Provides information about other Google APIs, such as what APIs are available,
|
10
|
-
the resource, and method details for each API.
|
9
|
+
description: Provides information about other Google APIs, such as what APIs are available, the resource, and method details for each API.
|
11
10
|
ownerDomain: google.com
|
12
11
|
ownerName: Google
|
13
12
|
icons:
|
@@ -19,7 +18,7 @@ baseUrl: https://www.googleapis.com/discovery/v1/
|
|
19
18
|
basePath: "/discovery/v1/"
|
20
19
|
rootUrl: https://www.googleapis.com/
|
21
20
|
servicePath: discovery/v1/
|
22
|
-
batchPath: batch
|
21
|
+
batchPath: batch/discovery/v1
|
23
22
|
parameters:
|
24
23
|
alt:
|
25
24
|
type: string
|
@@ -36,8 +35,7 @@ parameters:
|
|
36
35
|
location: query
|
37
36
|
key:
|
38
37
|
type: string
|
39
|
-
description: API key. Your API key identifies your project and provides you with
|
40
|
-
API access, quota, and reports. Required unless you provide an OAuth 2.0 token.
|
38
|
+
description: API key. Your API key identifies your project and provides you with API access, quota, and reports. Required unless you provide an OAuth 2.0 token.
|
41
39
|
location: query
|
42
40
|
oauth_token:
|
43
41
|
type: string
|
@@ -50,14 +48,11 @@ parameters:
|
|
50
48
|
location: query
|
51
49
|
quotaUser:
|
52
50
|
type: string
|
53
|
-
description: Available to use for quota purposes for server-side applications.
|
54
|
-
Can be any arbitrary string assigned to a user, but should not exceed 40 characters.
|
55
|
-
Overrides userIp if both are provided.
|
51
|
+
description: Available to use for quota purposes for server-side applications. Can be any arbitrary string assigned to a user, but should not exceed 40 characters. Overrides userIp if both are provided.
|
56
52
|
location: query
|
57
53
|
userIp:
|
58
54
|
type: string
|
59
|
-
description: IP address of the site where the request originates. Use this if
|
60
|
-
you want to enforce per-user limits.
|
55
|
+
description: IP address of the site where the request originates. Use this if you want to enforce per-user limits.
|
61
56
|
location: query
|
62
57
|
schemas:
|
63
58
|
DirectoryList:
|
@@ -66,8 +61,7 @@ schemas:
|
|
66
61
|
properties:
|
67
62
|
discoveryVersion:
|
68
63
|
type: string
|
69
|
-
description: Indicate the version of the Discovery API used to generate this
|
70
|
-
doc.
|
64
|
+
description: Indicate the version of the Discovery API used to generate this doc.
|
71
65
|
default: v1
|
72
66
|
items:
|
73
67
|
type: array
|
@@ -131,20 +125,17 @@ schemas:
|
|
131
125
|
properties:
|
132
126
|
"$ref":
|
133
127
|
type: string
|
134
|
-
description: A reference to another schema. The value of this property is
|
135
|
-
the "id" of another schema.
|
128
|
+
description: A reference to another schema. The value of this property is the "id" of another schema.
|
136
129
|
additionalProperties:
|
137
130
|
"$ref": JsonSchema
|
138
|
-
description: If this is a schema for an object, this property is the schema
|
139
|
-
for any additional properties with dynamic keys on this object.
|
131
|
+
description: If this is a schema for an object, this property is the schema for any additional properties with dynamic keys on this object.
|
140
132
|
annotations:
|
141
133
|
type: object
|
142
134
|
description: Additional information about this property.
|
143
135
|
properties:
|
144
136
|
required:
|
145
137
|
type: array
|
146
|
-
description: A list of methods for which this property is required on
|
147
|
-
requests.
|
138
|
+
description: A list of methods for which this property is required on requests.
|
148
139
|
items:
|
149
140
|
type: string
|
150
141
|
default:
|
@@ -160,25 +151,21 @@ schemas:
|
|
160
151
|
type: string
|
161
152
|
enumDescriptions:
|
162
153
|
type: array
|
163
|
-
description: The descriptions for the enums. Each position maps to the corresponding
|
164
|
-
value in the "enum" array.
|
154
|
+
description: The descriptions for the enums. Each position maps to the corresponding value in the "enum" array.
|
165
155
|
items:
|
166
156
|
type: string
|
167
157
|
format:
|
168
158
|
type: string
|
169
|
-
description: 'An additional regular expression or key that helps constrain
|
170
|
-
the value. For more details see: http://tools.ietf.org/html/draft-zyp-json-schema-03#section-5.23'
|
159
|
+
description: 'An additional regular expression or key that helps constrain the value. For more details see: http://tools.ietf.org/html/draft-zyp-json-schema-03#section-5.23'
|
171
160
|
id:
|
172
161
|
type: string
|
173
162
|
description: Unique identifier for this schema.
|
174
163
|
items:
|
175
164
|
"$ref": JsonSchema
|
176
|
-
description: If this is a schema for an array, this property is the schema
|
177
|
-
for each element in the array.
|
165
|
+
description: If this is a schema for an array, this property is the schema for each element in the array.
|
178
166
|
location:
|
179
167
|
type: string
|
180
|
-
description: Whether this parameter goes in the query or the path for REST
|
181
|
-
requests.
|
168
|
+
description: Whether this parameter goes in the query or the path for REST requests.
|
182
169
|
maximum:
|
183
170
|
type: string
|
184
171
|
description: The maximum value of this parameter.
|
@@ -187,21 +174,16 @@ schemas:
|
|
187
174
|
description: The minimum value of this parameter.
|
188
175
|
pattern:
|
189
176
|
type: string
|
190
|
-
description: 'The regular expression this parameter must conform to. Uses
|
191
|
-
Java 6 regex format: http://docs.oracle.com/javase/6/docs/api/java/util/regex/Pattern.html'
|
177
|
+
description: 'The regular expression this parameter must conform to. Uses Java 6 regex format: http://docs.oracle.com/javase/6/docs/api/java/util/regex/Pattern.html'
|
192
178
|
properties:
|
193
179
|
type: object
|
194
|
-
description: If this is a schema for an object, list the schema for each property
|
195
|
-
of this object.
|
180
|
+
description: If this is a schema for an object, list the schema for each property of this object.
|
196
181
|
additionalProperties:
|
197
182
|
"$ref": JsonSchema
|
198
|
-
description: A single property of this object. The value is itself a JSON
|
199
|
-
Schema object describing this property.
|
183
|
+
description: A single property of this object. The value is itself a JSON Schema object describing this property.
|
200
184
|
readOnly:
|
201
185
|
type: boolean
|
202
|
-
description: The value is read-only, generated by the service. The value cannot
|
203
|
-
be modified by the client. If the value is included in a POST, PUT, or PATCH
|
204
|
-
request, it is ignored by the service.
|
186
|
+
description: The value is read-only, generated by the service. The value cannot be modified by the client. If the value is included in a POST, PUT, or PATCH request, it is ignored by the service.
|
205
187
|
repeated:
|
206
188
|
type: boolean
|
207
189
|
description: Whether this parameter may appear multiple times.
|
@@ -210,13 +192,10 @@ schemas:
|
|
210
192
|
description: Whether the parameter is required.
|
211
193
|
type:
|
212
194
|
type: string
|
213
|
-
description: 'The value type for this schema. A list of values can be found
|
214
|
-
here: http://tools.ietf.org/html/draft-zyp-json-schema-03#section-5.1'
|
195
|
+
description: 'The value type for this schema. A list of values can be found here: http://tools.ietf.org/html/draft-zyp-json-schema-03#section-5.1'
|
215
196
|
variant:
|
216
197
|
type: object
|
217
|
-
description: In a variant data type, the value of one property is used to
|
218
|
-
determine how to interpret the entire entity. Its value must exist in a
|
219
|
-
map of descriminant values to schema names.
|
198
|
+
description: In a variant data type, the value of one property is used to determine how to interpret the entire entity. Its value must exist in a map of descriminant values to schema names.
|
220
199
|
properties:
|
221
200
|
discriminant:
|
222
201
|
type: string
|
@@ -262,18 +241,15 @@ schemas:
|
|
262
241
|
batchPath:
|
263
242
|
type: string
|
264
243
|
description: The path for REST batch requests.
|
265
|
-
default: batch
|
266
244
|
canonicalName:
|
267
245
|
type: string
|
268
|
-
description: Indicates how the API name should be capitalized and split into
|
269
|
-
various parts. Useful for generating pretty class names.
|
246
|
+
description: Indicates how the API name should be capitalized and split into various parts. Useful for generating pretty class names.
|
270
247
|
description:
|
271
248
|
type: string
|
272
249
|
description: The description of this API.
|
273
250
|
discoveryVersion:
|
274
251
|
type: string
|
275
|
-
description: Indicate the version of the Discovery API used to generate this
|
276
|
-
doc.
|
252
|
+
description: Indicate the version of the Discovery API used to generate this doc.
|
277
253
|
default: v1
|
278
254
|
documentationLink:
|
279
255
|
type: string
|
@@ -284,8 +260,7 @@ schemas:
|
|
284
260
|
readOnly: true
|
285
261
|
exponentialBackoffDefault:
|
286
262
|
type: boolean
|
287
|
-
description: Enable exponential backoff for suitable methods in the generated
|
288
|
-
clients.
|
263
|
+
description: Enable exponential backoff for suitable methods in the generated clients.
|
289
264
|
features:
|
290
265
|
type: array
|
291
266
|
description: A list of supported features for this API.
|
@@ -324,9 +299,7 @@ schemas:
|
|
324
299
|
description: The name of this API.
|
325
300
|
ownerDomain:
|
326
301
|
type: string
|
327
|
-
description: The domain of the owner of this API. Together with the ownerName
|
328
|
-
and a packagePath values, this can be used to generate a library for this
|
329
|
-
API which would have a unique fully qualified name.
|
302
|
+
description: The domain of the owner of this API. Together with the ownerName and a packagePath values, this can be used to generate a library for this API which would have a unique fully qualified name.
|
330
303
|
ownerName:
|
331
304
|
type: string
|
332
305
|
description: The name of the owner of this API. See ownerDomain.
|
@@ -348,8 +321,7 @@ schemas:
|
|
348
321
|
description: The resources in this API.
|
349
322
|
additionalProperties:
|
350
323
|
"$ref": RestResource
|
351
|
-
description: An individual resource description. Contains methods and sub-resources
|
352
|
-
related to this resource.
|
324
|
+
description: An individual resource description. Contains methods and sub-resources related to this resource.
|
353
325
|
revision:
|
354
326
|
type: string
|
355
327
|
description: The version of this API.
|
@@ -382,15 +354,13 @@ schemas:
|
|
382
354
|
description: Description of this method.
|
383
355
|
etagRequired:
|
384
356
|
type: boolean
|
385
|
-
description: Whether this method requires an ETag to be specified. The ETag
|
386
|
-
is sent as an HTTP If-Match or If-None-Match header.
|
357
|
+
description: Whether this method requires an ETag to be specified. The ETag is sent as an HTTP If-Match or If-None-Match header.
|
387
358
|
httpMethod:
|
388
359
|
type: string
|
389
360
|
description: HTTP method used by this method.
|
390
361
|
id:
|
391
362
|
type: string
|
392
|
-
description: A unique ID for this method. This property can be used to match
|
393
|
-
methods between different versions of Discovery.
|
363
|
+
description: A unique ID for this method. This property can be used to match methods between different versions of Discovery.
|
394
364
|
mediaUpload:
|
395
365
|
type: object
|
396
366
|
description: Media upload parameters.
|
@@ -413,13 +383,11 @@ schemas:
|
|
413
383
|
properties:
|
414
384
|
multipart:
|
415
385
|
type: boolean
|
416
|
-
description: True if this endpoint supports uploading multipart
|
417
|
-
media.
|
386
|
+
description: True if this endpoint supports uploading multipart media.
|
418
387
|
default: 'true'
|
419
388
|
path:
|
420
389
|
type: string
|
421
|
-
description: The URI path to be used for upload. Should be used
|
422
|
-
in conjunction with the basePath property at the api-level.
|
390
|
+
description: The URI path to be used for upload. Should be used in conjunction with the basePath property at the api-level.
|
423
391
|
simple:
|
424
392
|
type: object
|
425
393
|
description: Supports uploading as a single HTTP request.
|
@@ -430,13 +398,10 @@ schemas:
|
|
430
398
|
default: 'true'
|
431
399
|
path:
|
432
400
|
type: string
|
433
|
-
description: The URI path to be used for upload. Should be used
|
434
|
-
in conjunction with the basePath property at the api-level.
|
401
|
+
description: The URI path to be used for upload. Should be used in conjunction with the basePath property at the api-level.
|
435
402
|
parameterOrder:
|
436
403
|
type: array
|
437
|
-
description: Ordered list of required parameters, serves as a hint to clients
|
438
|
-
on how to structure their method signatures. The array is ordered such that
|
439
|
-
the "most-significant" parameter appears first.
|
404
|
+
description: Ordered list of required parameters, serves as a hint to clients on how to structure their method signatures. The array is ordered such that the "most-significant" parameter appears first.
|
440
405
|
items:
|
441
406
|
type: string
|
442
407
|
parameters:
|
@@ -447,8 +412,7 @@ schemas:
|
|
447
412
|
description: Details for a single parameter in this method.
|
448
413
|
path:
|
449
414
|
type: string
|
450
|
-
description: The URI path of this REST method. Should be used in conjunction
|
451
|
-
with the basePath property at the api-level.
|
415
|
+
description: The URI path of this REST method. Should be used in conjunction with the basePath property at the api-level.
|
452
416
|
request:
|
453
417
|
type: object
|
454
418
|
description: The schema for the request.
|
@@ -482,9 +446,7 @@ schemas:
|
|
482
446
|
description: Whether this method supports subscriptions.
|
483
447
|
useMediaDownloadService:
|
484
448
|
type: boolean
|
485
|
-
description: Indicates that downloads from this method should use the download
|
486
|
-
service URL (i.e. "/download"). Only applies if the method supports media
|
487
|
-
download.
|
449
|
+
description: Indicates that downloads from this method should use the download service URL (i.e. "/download"). Only applies if the method supports media download.
|
488
450
|
RestResource:
|
489
451
|
id: RestResource
|
490
452
|
type: object
|
data/lib/scorpio.rb
CHANGED
@@ -1,6 +1,19 @@
|
|
1
1
|
require "scorpio/version"
|
2
|
+
require "pathname"
|
3
|
+
require "pp"
|
4
|
+
require "api_hammer/ycomb"
|
5
|
+
require "scorpio/json-schema-fragments"
|
2
6
|
|
3
7
|
module Scorpio
|
8
|
+
def self.root
|
9
|
+
@root ||= Pathname.new(__FILE__).dirname.parent.expand_path
|
10
|
+
end
|
11
|
+
|
12
|
+
# generally put in code paths that are not expected to be valid control flow paths.
|
13
|
+
# rather a NotImplementedCorrectlyError. but that's too long.
|
14
|
+
class Bug < NotImplementedError
|
15
|
+
end
|
16
|
+
|
4
17
|
proc { |v| define_singleton_method(:error_classes_by_status) { v } }.call({})
|
5
18
|
class Error < StandardError; end
|
6
19
|
class HTTPError < Error
|
@@ -53,13 +66,29 @@ module Scorpio
|
|
53
66
|
error_classes_by_status.freeze
|
54
67
|
|
55
68
|
autoload :Model, 'scorpio/model'
|
69
|
+
autoload :OpenAPI, 'scorpio/openapi'
|
70
|
+
autoload :Google, 'scorpio/google_api_document'
|
71
|
+
autoload :JSON, 'scorpio/json'
|
72
|
+
autoload :Schema, 'scorpio/schema'
|
56
73
|
|
57
74
|
class << self
|
58
75
|
def stringify_symbol_keys(hash)
|
59
76
|
unless hash.is_a?(Hash)
|
60
|
-
raise ArgumentError, "expected argument to be a Hash; got #{hash.class}: #{hash.
|
77
|
+
raise ArgumentError, "expected argument to be a Hash; got #{hash.class}: #{hash.pretty_inspect}"
|
61
78
|
end
|
62
79
|
hash.map { |k,v| {k.is_a?(Symbol) ? k.to_s : k => v} }.inject({}, &:update)
|
63
80
|
end
|
64
81
|
end
|
82
|
+
|
83
|
+
module FingerprintHash
|
84
|
+
def ==(other)
|
85
|
+
other.respond_to?(:fingerprint) && other.fingerprint == self.fingerprint
|
86
|
+
end
|
87
|
+
|
88
|
+
alias eql? ==
|
89
|
+
|
90
|
+
def hash
|
91
|
+
fingerprint.hash
|
92
|
+
end
|
93
|
+
end
|
65
94
|
end
|
@@ -0,0 +1,232 @@
|
|
1
|
+
require 'api_hammer/ycomb'
|
2
|
+
require 'scorpio/schema_object_base'
|
3
|
+
|
4
|
+
module Scorpio
|
5
|
+
module Google
|
6
|
+
apidoc_schema_doc = ::JSON.parse(Scorpio.root.join('documents/www.googleapis.com/discovery/v1/apis/discovery/v1/rest').read)
|
7
|
+
api_document_class = proc do |*key|
|
8
|
+
Scorpio.class_for_schema(Scorpio::JSON::Node.new_by_type(apidoc_schema_doc, ['schemas', *key]))
|
9
|
+
end
|
10
|
+
|
11
|
+
# naming these is not strictly necessary, but is nice to have.
|
12
|
+
# generated: puts Scorpio::Google::ApiDocument.document['schemas'].select { |k,v| v['type'] == 'object' }.keys.map { |k| "#{k[0].upcase}#{k[1..-1]} = api_document_class.call('#{k}')" }
|
13
|
+
DirectoryList = api_document_class.call('DirectoryList')
|
14
|
+
JsonSchema = api_document_class.call('JsonSchema')
|
15
|
+
RestDescription = api_document_class.call('RestDescription')
|
16
|
+
RestMethod = api_document_class.call('RestMethod')
|
17
|
+
RestResource = api_document_class.call('RestResource')
|
18
|
+
|
19
|
+
# not generated
|
20
|
+
RestMethodRequest = api_document_class.call('RestMethod', 'properties', 'request')
|
21
|
+
RestMethodResponse = api_document_class.call('RestMethod', 'properties', 'response')
|
22
|
+
|
23
|
+
# google does a weird thing where it defines a schema with a $ref property where a json-schema is to be used in the document (method request and response fields), instead of just setting the schema to be the json-schema schema. we'll share a module across those schema classes that really represent schemas. is this confusingly meta enough?
|
24
|
+
module SchemaLike
|
25
|
+
def to_openapi
|
26
|
+
dup_doc = ::JSON.parse(::JSON.generate(object.content))
|
27
|
+
# openapi does not want an id field on schemas
|
28
|
+
dup_doc.delete('id')
|
29
|
+
if dup_doc['properties'].is_a?(Hash)
|
30
|
+
required_properties = dup_doc['properties'].select do |key, value|
|
31
|
+
value.is_a?(Hash) ? value.delete('required') : nil
|
32
|
+
end.keys
|
33
|
+
# put required before properties
|
34
|
+
unless required_properties.empty?
|
35
|
+
dup_doc = dup_doc.map do |k, v|
|
36
|
+
base = k == 'properties' ? {'required' => required_properties } : {}
|
37
|
+
base.merge({k => v})
|
38
|
+
end.inject({}, &:update)
|
39
|
+
end
|
40
|
+
end
|
41
|
+
dup_doc
|
42
|
+
end
|
43
|
+
end
|
44
|
+
[JsonSchema, RestMethodRequest, RestMethodResponse].each { |klass| klass.send(:include, SchemaLike) }
|
45
|
+
|
46
|
+
class RestDescription
|
47
|
+
def to_openapi_document(options = {})
|
48
|
+
Scorpio::OpenAPI::Document.new(to_openapi_hash(options))
|
49
|
+
end
|
50
|
+
|
51
|
+
def to_openapi_hash(options = {})
|
52
|
+
# we will be modifying the api document (RestDescription). clone self and modify that one.
|
53
|
+
ad = self.class.new(::JSON.parse(::JSON.generate(object.document)))
|
54
|
+
ad_methods = []
|
55
|
+
if ad['methods']
|
56
|
+
ad_methods += ad['methods'].map do |mn, m|
|
57
|
+
m.tap do
|
58
|
+
m.send(:define_singleton_method, :resource_name) { }
|
59
|
+
m.send(:define_singleton_method, :method_name) { mn }
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
63
|
+
ad_methods += ad.resources.map do |rn, r|
|
64
|
+
(r['methods'] || {}).map do |mn, m|
|
65
|
+
m.tap do
|
66
|
+
m.send(:define_singleton_method, :resource_name) { rn }
|
67
|
+
m.send(:define_singleton_method, :method_name) { mn }
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end.inject([], &:+)
|
71
|
+
|
72
|
+
paths = ad_methods.group_by { |m| m['path'] }.map do |path, path_methods|
|
73
|
+
unless path =~ %r(\A/)
|
74
|
+
path = '/' + path
|
75
|
+
end
|
76
|
+
operations = path_methods.group_by { |m| m['httpMethod'] }.map do |http_method, http_method_methods|
|
77
|
+
if http_method_methods.size > 1
|
78
|
+
#raise("http method #{http_method} at path #{path} not unique: #{http_method_methods.pretty_inspect}")
|
79
|
+
end
|
80
|
+
method = http_method_methods.first
|
81
|
+
unused_path_params = Addressable::Template.new(path).variables
|
82
|
+
{http_method.downcase => {}.tap do |operation|
|
83
|
+
#operation['tags'] = []
|
84
|
+
#operation['summary'] =
|
85
|
+
operation['description'] = method['description'] if method['description']
|
86
|
+
if method.resource_name && options[:x]
|
87
|
+
operation['x-resource'] = method.resource_name
|
88
|
+
operation['x-resource-method'] = method.method_name
|
89
|
+
end
|
90
|
+
#operation['externalDocs'] =
|
91
|
+
operation['operationId'] = method['id'] || (method.resource_name ? "#{method.resource_name}.#{method.method_name}" : method.method_name)
|
92
|
+
#operation['produces'] =
|
93
|
+
#operation['consumes'] =
|
94
|
+
if method['parameters']
|
95
|
+
operation['parameters'] = method['parameters'].map do |name, parameter|
|
96
|
+
{}.tap do |op_param|
|
97
|
+
op_param['description'] = parameter.description if parameter.description
|
98
|
+
op_param['name'] = name
|
99
|
+
op_param['in'] = if parameter.location
|
100
|
+
parameter.location
|
101
|
+
elsif unused_path_params.include?(name)
|
102
|
+
'path'
|
103
|
+
else
|
104
|
+
'query'
|
105
|
+
# unused: header, formdata, body
|
106
|
+
end
|
107
|
+
unused_path_params.delete(name) if op_param['in'] == 'path'
|
108
|
+
op_param['required'] = parameter.key?('required') ? parameter['required'] : op_param['in'] == 'path' ? true : false
|
109
|
+
op_param['type'] = parameter.type || 'string'
|
110
|
+
op_param['format'] = parameter.format if parameter.format
|
111
|
+
end
|
112
|
+
end
|
113
|
+
end
|
114
|
+
if unused_path_params.any?
|
115
|
+
operation['parameters'] ||= []
|
116
|
+
operation['parameters'] += unused_path_params.map do |param_name|
|
117
|
+
{
|
118
|
+
'name' => param_name,
|
119
|
+
'in' => 'path',
|
120
|
+
'required' => true,
|
121
|
+
'type' => 'string',
|
122
|
+
}
|
123
|
+
end
|
124
|
+
end
|
125
|
+
if method['request']
|
126
|
+
operation['parameters'] ||= []
|
127
|
+
operation['parameters'] << {
|
128
|
+
'name' => 'body',
|
129
|
+
'in' => 'body',
|
130
|
+
'required' => true,
|
131
|
+
'schema' => method['request'],
|
132
|
+
}
|
133
|
+
end
|
134
|
+
if method['response']
|
135
|
+
operation['responses'] = {
|
136
|
+
'default' => {
|
137
|
+
'description' => 'default response',
|
138
|
+
'schema' => method['response'],
|
139
|
+
},
|
140
|
+
}
|
141
|
+
end
|
142
|
+
end}
|
143
|
+
end.inject({}, &:update)
|
144
|
+
|
145
|
+
{path => operations}
|
146
|
+
end.inject({}, &:update)
|
147
|
+
|
148
|
+
openapi = {
|
149
|
+
'swagger' => '2.0',
|
150
|
+
'info' => { #/definitions/info
|
151
|
+
'title' => ad.title || ad.name,
|
152
|
+
'description' => ad.description,
|
153
|
+
'version' => ad.version || '',
|
154
|
+
#'termsOfService' => '',
|
155
|
+
'contact' => {
|
156
|
+
'name' => ad.ownerName,
|
157
|
+
#'url' =>
|
158
|
+
#'email' => '',
|
159
|
+
}.reject { |_, v| v.nil? },
|
160
|
+
#'license' => {
|
161
|
+
#'name' => '',
|
162
|
+
#'url' => '',
|
163
|
+
#},
|
164
|
+
},
|
165
|
+
'host' => ad.rootUrl ? Addressable::URI.parse(ad.rootUrl).host : ad.baseUrl ? Addressable::URI.parse(ad.rootUrl).host : ad.name, # uhh ... got nothin' better
|
166
|
+
'basePath' => begin
|
167
|
+
path = ad.servicePath || ad.basePath || (ad.baseUrl ? Addressable::URI.parse(ad.baseUrl).path : '/')
|
168
|
+
path =~ %r(\A/) ? path : "/" + path
|
169
|
+
end,
|
170
|
+
'schemes' => ad.rootUrl ? [Addressable::URI.parse(ad.rootUrl).scheme] : ad.baseUrl ? [Addressable::URI.parse(ad.rootUrl).scheme] : [], #/definitions/schemesList
|
171
|
+
'consumes' => ['application/json'], # we'll just make this assumption
|
172
|
+
'produces' => ['application/json'],
|
173
|
+
'paths' => paths, #/definitions/paths
|
174
|
+
}
|
175
|
+
if ad.schemas
|
176
|
+
openapi['definitions'] = ad.schemas
|
177
|
+
ad.schemas.each do |name, schema|
|
178
|
+
openapi = ycomb do |rec|
|
179
|
+
proc do |object|
|
180
|
+
if object.respond_to?(:to_hash)
|
181
|
+
object.merge(object.map do |k, v|
|
182
|
+
if k == '$ref' && (v == schema['id'] || v == "#/schemas/#{name}" || v == name)
|
183
|
+
{k => "#/definitions/#{name}"}
|
184
|
+
else
|
185
|
+
ycomb do |toopenapirec|
|
186
|
+
proc do |toopenapiobject|
|
187
|
+
toopenapiobject = toopenapiobject.to_openapi if toopenapiobject.respond_to?(:to_openapi)
|
188
|
+
if toopenapiobject.respond_to?(:to_hash)
|
189
|
+
toopenapiobject.map { |k, v| {toopenapirec.call(k) => toopenapirec.call(v)} }.inject({}, &:update)
|
190
|
+
elsif toopenapiobject.respond_to?(:to_ary)
|
191
|
+
toopenapiobject.map(&toopenapirec)
|
192
|
+
elsif toopenapiobject.is_a?(Symbol)
|
193
|
+
toopenapiobject.to_s
|
194
|
+
elsif [String, TrueClass, FalseClass, NilClass, Numeric].any? { |c| toopenapiobject.is_a?(c) }
|
195
|
+
toopenapiobject
|
196
|
+
else
|
197
|
+
raise(TypeError, "bad (not jsonifiable) object: #{toopenapiobject.pretty_inspect}")
|
198
|
+
end
|
199
|
+
end
|
200
|
+
end.call({k => rec.call(v)})
|
201
|
+
end
|
202
|
+
end.inject({}, &:merge))
|
203
|
+
elsif object.respond_to?(:to_ary)
|
204
|
+
object.map(&rec)
|
205
|
+
else
|
206
|
+
object
|
207
|
+
end
|
208
|
+
end
|
209
|
+
end.call(openapi)
|
210
|
+
end
|
211
|
+
end
|
212
|
+
# check we haven't got anything that shouldn't go in a openapi document
|
213
|
+
openapi = ycomb do |rec|
|
214
|
+
proc do |object|
|
215
|
+
object = object.to_openapi if object.respond_to?(:to_openapi)
|
216
|
+
if object.respond_to?(:to_hash)
|
217
|
+
object.map { |k, v| {rec.call(k) => rec.call(v)} }.inject({}, &:update)
|
218
|
+
elsif object.respond_to?(:to_ary)
|
219
|
+
object.map(&rec)
|
220
|
+
elsif object.is_a?(Symbol)
|
221
|
+
object.to_s
|
222
|
+
elsif [String, TrueClass, FalseClass, NilClass, Numeric].any? { |c| object.is_a?(c) }
|
223
|
+
object
|
224
|
+
else
|
225
|
+
raise(TypeError, "bad (not jsonifiable) object: #{object.pretty_inspect}")
|
226
|
+
end
|
227
|
+
end
|
228
|
+
end.call(openapi)
|
229
|
+
end
|
230
|
+
end
|
231
|
+
end
|
232
|
+
end
|