scorpio 0.6.4 → 0.7.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (39) hide show
  1. checksums.yaml +4 -4
  2. data/.yardopts +6 -1
  3. data/CHANGELOG.md +10 -2
  4. data/LICENSE.md +2 -4
  5. data/README.md +81 -67
  6. data/documents/{github.com/OAI/OpenAPI-Specification/blob/oas3-schema/schemas/v3.0 → spec.openapis.org/oas/3.0}/schema.yaml +164 -628
  7. data/documents/spec.openapis.org/oas/3.1/dialect/base.schema.yaml +22 -0
  8. data/documents/spec.openapis.org/oas/3.1/meta/base.schema.yaml +71 -0
  9. data/documents/spec.openapis.org/oas/3.1/schema-base.yaml +21 -0
  10. data/documents/spec.openapis.org/oas/3.1/schema.yaml +980 -0
  11. data/documents/swagger.io/v2/schema.json +1 -1
  12. data/documents/www.googleapis.com/discovery/v1/apis/discovery/v1/rest.yml +44 -4
  13. data/lib/scorpio/google_api_document.rb +121 -193
  14. data/lib/scorpio/openapi/document.rb +63 -31
  15. data/lib/scorpio/openapi/operation.rb +114 -96
  16. data/lib/scorpio/openapi/operations_scope.rb +35 -19
  17. data/lib/scorpio/openapi/reference.rb +88 -23
  18. data/lib/scorpio/openapi/schema_elements/type_nullable.rb +38 -0
  19. data/lib/scorpio/openapi/schema_elements.rb +7 -0
  20. data/lib/scorpio/openapi/server.rb +34 -0
  21. data/lib/scorpio/openapi/tag.rb +19 -3
  22. data/lib/scorpio/openapi/v2/dialect.rb +66 -0
  23. data/lib/scorpio/openapi/v2.rb +124 -0
  24. data/lib/scorpio/openapi/v3_0/dialect.rb +76 -0
  25. data/lib/scorpio/openapi/v3_0.rb +130 -0
  26. data/lib/scorpio/openapi/v3_1.rb +243 -0
  27. data/lib/scorpio/openapi.rb +23 -203
  28. data/lib/scorpio/request.rb +67 -61
  29. data/lib/scorpio/resource_base.rb +57 -49
  30. data/lib/scorpio/response.rb +28 -10
  31. data/lib/scorpio/ur.rb +7 -3
  32. data/lib/scorpio/version.rb +1 -1
  33. data/lib/scorpio.rb +12 -6
  34. data/pages/Request_Configuration.md +69 -0
  35. data/pages/Security.md +50 -0
  36. data/scorpio.gemspec +6 -5
  37. metadata +28 -15
  38. data/documents/www.googleapis.com/discovery/v1/apis/discovery/v1/rest +0 -684
  39. data/lib/scorpio/openapi/v3/server.rb +0 -44
@@ -203,7 +203,7 @@
203
203
  "additionalProperties": {
204
204
  "$ref": "#/definitions/response"
205
205
  },
206
- "description": "One or more JSON representations for parameters"
206
+ "description": "One or more JSON representations for responses"
207
207
  },
208
208
  "externalDocs": {
209
209
  "type": "object",
@@ -1,11 +1,12 @@
1
1
  ---
2
2
  kind: discovery#restDescription
3
- etag: '"YWOzh2SDasdU84ArJnpYek-OMdg/K3nEDF6hixE8Pks2-9Ysn9j9prQ"'
3
+ etag: '"-2NioU2H8y8siEzrBOV_qzRI6kQ/vabF8Q1ADCm_Bt9EBq9rkrRawQA"'
4
+ revision: '20200806'
4
5
  discoveryVersion: v1
5
6
  id: discovery:v1
6
7
  name: discovery
7
8
  version: v1
8
- title: APIs Discovery Service
9
+ title: API Discovery Service
9
10
  description: Provides information about other Google APIs, such as what APIs are available, the resource, and method details for each API.
10
11
  ownerDomain: google.com
11
12
  ownerName: Google
@@ -48,11 +49,11 @@ parameters:
48
49
  location: query
49
50
  quotaUser:
50
51
  type: string
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.
52
+ description: An opaque string that represents a user for quota purposes. Must not exceed 40 characters.
52
53
  location: query
53
54
  userIp:
54
55
  type: string
55
- description: IP address of the site where the request originates. Use this if you want to enforce per-user limits.
56
+ description: Deprecated. Please use quotaUser instead.
56
57
  location: query
57
58
  schemas:
58
59
  DirectoryList:
@@ -210,6 +211,14 @@ schemas:
210
211
  type: string
211
212
  type_value:
212
213
  type: string
214
+ enumDeprecated:
215
+ type: array
216
+ description: The deprecation status for the enums. Each position maps to the corresponding value in the "enum" array.
217
+ items:
218
+ type: boolean
219
+ deprecated:
220
+ type: boolean
221
+ description: Whether the parameter is deprecated.
213
222
  RestDescription:
214
223
  id: RestDescription
215
224
  type: object
@@ -345,6 +354,25 @@ schemas:
345
354
  description: The version of this API.
346
355
  version_module:
347
356
  type: boolean
357
+ endpoints:
358
+ type: array
359
+ description: A list of location-based endpoint objects for this API. Each object contains the endpoint URL, location, description and deprecation status.
360
+ items:
361
+ type: object
362
+ description: A single endpoint object
363
+ properties:
364
+ location:
365
+ type: string
366
+ description: The location of the endpoint
367
+ deprecated:
368
+ type: boolean
369
+ description: Whether this endpoint is deprecated
370
+ endpointUrl:
371
+ type: string
372
+ description: The URL of the endpoint target host
373
+ description:
374
+ type: string
375
+ description: A string describing the host designated by the URL
348
376
  RestMethod:
349
377
  id: RestMethod
350
378
  type: object
@@ -447,6 +475,15 @@ schemas:
447
475
  useMediaDownloadService:
448
476
  type: boolean
449
477
  description: Indicates that downloads from this method should use the download service URL (i.e. "/download"). Only applies if the method supports media download.
478
+ apiVersion:
479
+ type: string
480
+ description: The API Version of this method, as passed in via the `X-Goog-Api-Version` header or `$apiVersion` query parameter.
481
+ flatPath:
482
+ type: string
483
+ description: The URI path of this REST method in (RFC 6570) format without level 2 features ({+var}). Supplementary to the path property.
484
+ deprecated:
485
+ type: boolean
486
+ description: Whether this method is deprecated.
450
487
  RestResource:
451
488
  id: RestResource
452
489
  type: object
@@ -463,6 +500,9 @@ schemas:
463
500
  additionalProperties:
464
501
  "$ref": RestResource
465
502
  description: Description for any sub-resources on this resource.
503
+ deprecated:
504
+ type: boolean
505
+ description: Whether this resource is deprecated.
466
506
  resources:
467
507
  apis:
468
508
  methods:
@@ -2,20 +2,22 @@
2
2
 
3
3
  module Scorpio
4
4
  module Google
5
- discovery_rest_description_doc = ::JSON.parse(Scorpio.root.join('documents/www.googleapis.com/discovery/v1/apis/discovery/v1/rest').read)
6
- discovery_rest_description = JSI::MetaSchemaNode.new(
5
+ discovery_rest_description_doc = YAML.safe_load(Scorpio.root.join('documents/www.googleapis.com/discovery/v1/apis/discovery/v1/rest.yml').read)
6
+ DISCOVERY_REST_DESCRIPTION = JSI.new_metaschema_node(
7
7
  discovery_rest_description_doc,
8
- metaschema_root_ptr: JSI::Ptr['schemas']['JsonSchema'],
9
- root_schema_ptr: JSI::Ptr['schemas']['RestDescription'],
10
- schema_implementation_modules: [JSI::Schema::Draft04],
8
+ dialect: JSI::Schema::Draft04::DIALECT,
9
+ metaschema_root_ref: "#/schemas/JsonSchema",
10
+ root_schema_ref: "#/schemas/RestDescription",
11
11
  )
12
12
 
13
13
  # naming these is not strictly necessary, but is nice to have.
14
- DirectoryList = discovery_rest_description.schemas['DirectoryList'].jsi_schema_module
15
- JsonSchema = discovery_rest_description.schemas['JsonSchema'].jsi_schema_module
16
- RestDescription = discovery_rest_description.schemas['RestDescription'].jsi_schema_module
17
- RestMethod = discovery_rest_description.schemas['RestMethod'].jsi_schema_module
18
- RestResource = discovery_rest_description.schemas['RestResource'].jsi_schema_module
14
+
15
+
16
+ DirectoryList = DISCOVERY_REST_DESCRIPTION.schemas['DirectoryList'].jsi_schema_module
17
+ JsonSchema = DISCOVERY_REST_DESCRIPTION.schemas['JsonSchema'].jsi_schema_module
18
+ RestDescription = DISCOVERY_REST_DESCRIPTION.schemas['RestDescription'].jsi_schema_module
19
+ RestMethod = DISCOVERY_REST_DESCRIPTION.schemas['RestMethod'].jsi_schema_module
20
+ RestResource = DISCOVERY_REST_DESCRIPTION.schemas['RestResource'].jsi_schema_module
19
21
 
20
22
  module RestDescription
21
23
  Resources = properties['resources']
@@ -24,197 +26,123 @@ module Scorpio
24
26
  module RestMethod
25
27
  Request = properties['request']
26
28
  Response = properties['response']
29
+
30
+ # these only contain a $ref to a schema, but that is enough to use them as schemas
31
+ Request.describes_schema!(JSI::Schema::Draft04::DIALECT)
32
+ Response.describes_schema!(JSI::Schema::Draft04::DIALECT)
27
33
  end
28
34
 
29
- # 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?
30
- module SchemaLike
31
- def to_openapi
32
- # openapi does not want an id field on schemas
33
- dup_doc = jsi_node_content.reject { |k, _| k == 'id' }
34
- if dup_doc['properties'].is_a?(Hash)
35
- required_properties = []
36
- dup_doc['properties'].each do |key, value|
37
- if value.is_a?(Hash) && value.key?('required')
38
- required_properties.push(key) if value['required']
39
- dup_doc = dup_doc.merge({'properties' => value.reject { |vk, _| vk == 'required' }})
40
- end
41
- end
42
- # put required before properties
43
- unless required_properties.empty?
44
- dup_doc = dup_doc.map do |k, v|
45
- base = k == 'properties' ? {'required' => required_properties } : {}
46
- base.merge({k => v})
47
- end.inject({}, &:update)
48
- end
35
+ module HasMethodsAndResources
36
+ def operations
37
+ return @operations if instance_variable_defined?(:@operations)
38
+ @operations = OpenAPI::OperationsScope.new(each_operation)
39
+ end
40
+
41
+ def each_operation(&block)
42
+ return(to_enum(__method__)) unless block
43
+
44
+ (self['methods'] || {}).each_value(&block)
45
+
46
+ (self['resources'] || {}).each_value do |resource|
47
+ resource.each_operation(&block)
49
48
  end
50
- dup_doc
51
49
  end
52
50
  end
53
- [JsonSchema, RestMethod::Request, RestMethod::Response].each { |m| m.send(:include, SchemaLike) }
54
51
 
55
52
  module RestDescription
56
- def to_openapi_document(options = {})
57
- Scorpio::OpenAPI::Document.from_instance(to_openapi_hash(options))
58
- end
59
-
60
- def to_openapi_hash(options = {})
61
- ad = self
62
- ad_methods = []
63
- if ad['methods']
64
- ad_methods += ad['methods'].map do |mn, m|
65
- m.tap do
66
- m.send(:define_singleton_method, :resource_name) { }
67
- m.send(:define_singleton_method, :method_name) { mn }
68
- end
69
- end
70
- end
71
- ad_methods += ad.resources.map do |rn, r|
72
- (r['methods'] || {}).map do |mn, m|
73
- m.tap do
74
- m.send(:define_singleton_method, :resource_name) { rn }
75
- m.send(:define_singleton_method, :method_name) { mn }
76
- end
77
- end
78
- end.inject([], &:+)
79
-
80
- paths = ad_methods.group_by { |m| m['path'] }.map do |path, path_methods|
81
- unless path =~ %r(\A/)
82
- path = '/' + path
83
- end
84
- operations = path_methods.group_by { |m| m['httpMethod'] }.map do |http_method, http_method_methods|
85
- if http_method_methods.size > 1
86
- #raise("http method #{http_method} at path #{path} not unique: #{http_method_methods.pretty_inspect}")
87
- end
88
- method = http_method_methods.first
89
- unused_path_params = Addressable::Template.new(path).variables
90
- {http_method.downcase => {}.tap do |operation|
91
- operation['tags'] = method.resource_name ? [method.resource_name] : []
92
- #operation['summary'] =
93
- operation['description'] = method['description'] if method['description']
94
- #operation['externalDocs'] =
95
- operation['operationId'] = method['id'] || (method.resource_name ? "#{method.resource_name}.#{method.method_name}" : method.method_name)
96
- #operation['produces'] =
97
- #operation['consumes'] =
98
- if method['parameters']
99
- operation['parameters'] = method['parameters'].map do |name, parameter|
100
- {}.tap do |op_param|
101
- op_param['description'] = parameter.description if parameter.description
102
- op_param['name'] = name
103
- op_param['in'] = if parameter.location
104
- parameter.location
105
- elsif unused_path_params.include?(name)
106
- 'path'
107
- else
108
- 'query'
109
- # unused: header, formdata, body
110
- end
111
- unused_path_params.delete(name) if op_param['in'] == 'path'
112
- op_param['required'] = parameter.key?('required') ? parameter['required'] : op_param['in'] == 'path' ? true : false
113
- op_param['type'] = parameter.type || 'string'
114
- op_param['format'] = parameter['format'] if parameter['format']
115
- end
116
- end
117
- end
118
- if unused_path_params.any?
119
- operation['parameters'] ||= []
120
- operation['parameters'] += unused_path_params.map do |param_name|
121
- {
122
- 'name' => param_name,
123
- 'in' => 'path',
124
- 'required' => true,
125
- 'type' => 'string',
126
- }
127
- end
128
- end
129
- if method['request']
130
- operation['parameters'] ||= []
131
- operation['parameters'] << {
132
- 'name' => 'body',
133
- 'in' => 'body',
134
- 'required' => true,
135
- 'schema' => method['request'],
136
- }
137
- end
138
- if method['response']
139
- operation['responses'] = {
140
- 'default' => {
141
- 'description' => 'default response',
142
- 'schema' => method['response'],
143
- },
144
- }
145
- end
146
- end}
147
- end.inject({}, &:update)
148
-
149
- {path => operations}
150
- end.inject({}, &:update)
151
-
152
- openapi = {
153
- 'swagger' => '2.0',
154
- 'info' => { #/definitions/info
155
- 'title' => ad.title || ad.name,
156
- 'description' => ad.description,
157
- 'version' => ad.version || '',
158
- #'termsOfService' => '',
159
- 'contact' => {
160
- 'name' => ad.ownerName,
161
- #'url' =>
162
- #'email' => '',
163
- }.reject { |_, v| v.nil? },
164
- #'license' => {
165
- #'name' => '',
166
- #'url' => '',
167
- #},
168
- },
169
- 'host' => ad.rootUrl ? Addressable::URI.parse(ad.rootUrl).host : ad.baseUrl ? Addressable::URI.parse(ad.baseUrl).host : ad.name, # uhh ... got nothin' better
170
- 'basePath' => begin
171
- path = ad.servicePath || ad.basePath || (ad.baseUrl ? Addressable::URI.parse(ad.baseUrl).path : '/')
172
- path =~ %r(\A/) ? path : "/" + path
173
- end,
174
- 'schemes' => ad.rootUrl ? [Addressable::URI.parse(ad.rootUrl).scheme] : ad.baseUrl ? [Addressable::URI.parse(ad.rootUrl).scheme] : [], #/definitions/schemesList
175
- 'consumes' => ['application/json'], # we'll just make this assumption
176
- 'produces' => ['application/json'],
177
- 'tags' => paths.flat_map { |_, p| p.flat_map { |_, op| (op['tags'] || []).map { |n| {'name' => n} } } }.uniq,
178
- 'paths' => paths, #/definitions/paths
179
- }
180
- if ad.schemas
181
- openapi['definitions'] = ad.schemas
182
- ad.schemas.each do |name, schema|
183
- openapi = JSI::Util.ycomb do |rec|
184
- proc do |object|
185
- if object.respond_to?(:to_hash)
186
- object.merge(object.map do |k, v|
187
- if k == '$ref' && (v == schema['id'] || v == "#/schemas/#{name}" || v == name)
188
- {k => "#/definitions/#{name}"}
189
- else
190
- JSI::Util.ycomb do |toopenapirec|
191
- proc do |toopenapiobject|
192
- toopenapiobject = toopenapiobject.to_openapi if toopenapiobject.respond_to?(:to_openapi)
193
- if toopenapiobject.respond_to?(:to_hash)
194
- toopenapiobject.map { |k2, v2| {toopenapirec.call(k2) => toopenapirec.call(v2)} }.inject({}, &:update)
195
- elsif toopenapiobject.respond_to?(:to_ary)
196
- toopenapiobject.map(&toopenapirec)
197
- elsif toopenapiobject.is_a?(Symbol)
198
- toopenapiobject.to_s
199
- elsif [String, TrueClass, FalseClass, NilClass, Numeric].any? { |c| toopenapiobject.is_a?(c) }
200
- toopenapiobject
201
- else
202
- raise(TypeError, "bad (not jsonifiable) object: #{toopenapiobject.pretty_inspect}")
203
- end
204
- end
205
- end.call({k => rec.call(v)})
206
- end
207
- end.inject({}, &:merge))
208
- elsif object.respond_to?(:to_ary)
209
- object.map(&rec)
210
- else
211
- object
212
- end
213
- end
214
- end.call(openapi)
215
- end
53
+ include(OpenAPI::Document)
54
+ include(HasMethodsAndResources)
55
+
56
+ attr_writer(:base_url)
57
+
58
+ def base_url(scheme: nil, server: nil, server_variables: nil)
59
+ return @base_url if instance_variable_defined?(:@base_url)
60
+ JSI::Util.uri(rootUrl ? File.join(rootUrl, servicePath) : baseUrl) # baseUrl is deprecated
61
+ end
62
+
63
+ def title
64
+ self['title'] # override OpenAPI::Document#title
65
+ end
66
+ end
67
+
68
+ module RestResource
69
+ include(HasMethodsAndResources)
70
+ end
71
+
72
+ module RestMethod
73
+ include(OpenAPI::Operation)
74
+
75
+ def tagged?(tag_name)
76
+ resource_names.include?(tag_name)
77
+ end
78
+
79
+ def resource_names
80
+ # resource name is the property name where a RestResource is. kind of hax but it works.
81
+ jsi_parent_nodes.select { |n| n.is_a?(RestResource) }.map { |r| r.jsi_ptr.tokens.last }
82
+ end
83
+
84
+ def path_template_str
85
+ path
86
+ end
87
+
88
+ def parameters
89
+ (self['parameters'] || {}).map do |name, schema|
90
+ param = {'name' => name}
91
+ param['in'] = schema.location if schema.key?('location')
92
+ param['schema'] = schema
93
+ #param['description'] = schema.description if schema.key?('description')
94
+ #param['required'] = schema.required if schema.key?('required')
95
+ param
216
96
  end
217
- JSI::Util.as_json(openapi)
97
+ end
98
+
99
+ def request_media_type
100
+ 'application/json'
101
+ end
102
+
103
+ def http_method
104
+ httpMethod
105
+ end
106
+
107
+ def openapi_document
108
+ rest_description
109
+ end
110
+
111
+ def rest_description
112
+ jsi_parent_nodes.detect { |p| p.is_a?(RestDescription) }
113
+ end
114
+
115
+ def scheme
116
+ nil
117
+ end
118
+
119
+ def server
120
+ nil
121
+ end
122
+
123
+ def server_variables
124
+ nil
125
+ end
126
+
127
+ def operationId
128
+ id
129
+ end
130
+
131
+ # @param media_type unused
132
+ def request_schema(media_type: nil)
133
+ request
134
+ end
135
+
136
+ def request_schemas
137
+ request ? [request] : []
138
+ end
139
+
140
+ def response_schema(status: nil, media_type: nil)
141
+ response
142
+ end
143
+
144
+ def response_schemas
145
+ response ? [response] : []
218
146
  end
219
147
  end
220
148
  end
@@ -12,17 +12,21 @@ module Scorpio
12
12
  # instantiating it.
13
13
  #
14
14
  # @param instance [#to_hash] the document to represent as a Scorpio OpenAPI Document
15
- # @return [Scorpio::OpenAPI::V2::Document, Scorpio::OpenAPI::V3::Document]
16
- def from_instance(instance)
15
+ # @return [JSI::Base + Scorpio::OpenAPI::Document]
16
+ def new_document(instance, **new_param)
17
17
  if instance.is_a?(Scorpio::OpenAPI::Document)
18
18
  instance
19
19
  elsif instance.is_a?(JSI::Base)
20
- raise(TypeError, "instance is unexpected JSI type: #{instance.class.inspect}")
20
+ raise(TypeError, -"instance is unexpected JSI type: #{instance.class.inspect}")
21
21
  elsif instance.respond_to?(:to_hash)
22
- if instance['swagger'] =~ /\A2(\.|\z)/
23
- instance = Scorpio::OpenAPI::V2::Document.new_jsi(instance)
24
- elsif instance['openapi'] =~ /\A3(\.|\z)/
25
- instance = Scorpio::OpenAPI::V3::Document.new_jsi(instance)
22
+ if (instance['swagger'].is_a?(String) && instance['swagger'] =~ /\A2(\.|\z)/) || instance['swagger'] == 2
23
+ Scorpio::OpenAPI::V2::Document.new_jsi(instance, **new_param)
24
+ elsif (instance['openapi'].is_a?(String) && instance['openapi'] =~ /\A3\.0(\.|\z)/) || instance['openapi'] == 3.0
25
+ Scorpio::OpenAPI::V3_0::Document.new_jsi(instance, **new_param)
26
+ elsif (instance['openapi'].is_a?(String) && instance['openapi'] =~ /\A3\.1(\.|\z)/) || instance['openapi'] == 3.1
27
+ Scorpio::OpenAPI::V3_1.new_document(instance, **new_param)
28
+ elsif instance['kind'] == 'discovery#restDescription'
29
+ Scorpio::Google::RestDescription.new_jsi(instance, register: true, **new_param)
26
30
  else
27
31
  raise(ArgumentError, "instance does not look like a recognized openapi document")
28
32
  end
@@ -30,6 +34,18 @@ module Scorpio
30
34
  raise(TypeError, "instance does not look like a hash (json object)")
31
35
  end
32
36
  end
37
+
38
+ # @deprecated after v0.8.0. use `new_document`.
39
+ def from_instance(instance, **kw)
40
+ Scorpio.new_document(instance, **kw)
41
+ end
42
+ end
43
+
44
+ module Descendent
45
+ # @return [Scorpio::OpenAPI::Document]
46
+ def openapi_document
47
+ jsi_ancestor_nodes.detect { |n| n.is_a?(OpenAPI::Document) } || raise(Error, -"not inside an OpenAPI document (#{inspect})")
48
+ end
33
49
  end
34
50
 
35
51
  module Configurables
@@ -42,13 +58,25 @@ module Scorpio
42
58
  attr_writer :user_agent
43
59
  def user_agent
44
60
  return @user_agent if instance_variable_defined?(:@user_agent)
45
- "Scorpio/#{Scorpio::VERSION} (https://github.com/notEthan/scorpio) Faraday/#{Faraday::VERSION} Ruby/#{RUBY_VERSION}"
61
+ Request::DEFAULT_USER_AGENT
62
+ end
63
+
64
+ attr_writer(:accept)
65
+ def accept
66
+ return @accept if instance_variable_defined?(:@accept)
67
+ nil
68
+ end
69
+
70
+ attr_writer(:authorization)
71
+ def authorization
72
+ return @authorization if instance_variable_defined?(:@authorization)
73
+ nil
46
74
  end
47
75
 
48
76
  attr_writer :faraday_builder
49
77
  def faraday_builder
50
78
  return @faraday_builder if instance_variable_defined?(:@faraday_builder)
51
- -> (_) { }
79
+ nil
52
80
  end
53
81
 
54
82
  attr_writer :faraday_adapter
@@ -66,26 +94,37 @@ module Scorpio
66
94
  include Configurables
67
95
 
68
96
  def v2?
69
- is_a?(V2::Document)
97
+ is_a?(OpenAPI::V2::Document)
70
98
  end
71
99
 
72
100
  def v3?
73
- is_a?(V3::Document)
101
+ is_a?(OpenAPI::Document::V3Methods)
74
102
  end
75
103
 
76
104
  def operations
77
105
  return @operations if instance_variable_defined?(:@operations)
78
- @operations = OperationsScope.new(self)
106
+ @operations = OperationsScope.new(each_operation)
107
+ end
108
+
109
+ def each_operation(&block)
110
+ return(to_enum(__method__)) unless block
111
+
112
+ paths.each do |path, path_item|
113
+ path_item.each do |http_method, operation|
114
+ if operation.is_a?(Scorpio::OpenAPI::Operation)
115
+ yield(operation)
116
+ end
117
+ end
118
+ end
79
119
  end
80
- end
81
120
 
82
- module V3
83
- raise(Bug, 'const_defined? Scorpio::OpenAPI::V3::Document') unless const_defined?(:Document)
121
+ def title
122
+ info && info.title
123
+ end
124
+ end
84
125
 
85
- # A document that defines or describes an API conforming to the OpenAPI Specification v3.
86
- #
87
- # https://github.com/OAI/OpenAPI-Specification/blob/master/versions/3.0.2.md#oasObject
88
- module Document
126
+ module Document
127
+ module V3Methods
89
128
  module Configurables
90
129
  def scheme
91
130
  nil
@@ -112,23 +151,15 @@ module Scorpio
112
151
  end
113
152
  end
114
153
 
115
- attr_writer :request_media_type
116
- def request_media_type
117
- return @request_media_type if instance_variable_defined?(:@request_media_type)
118
- nil
119
- end
154
+ attr_accessor(:request_media_type)
120
155
  end
121
156
  include Configurables
157
+ include(OpenAPI::Document)
122
158
  end
123
159
  end
124
160
 
125
- module V2
126
- raise(Bug, 'const_defined? Scorpio::OpenAPI::V2::Document') unless const_defined?(:Document)
127
-
128
- # A document that defines or describes an API conforming to the OpenAPI Specification v2 (aka Swagger).
129
- #
130
- # The root document is known as the Swagger Object.
131
- module Document
161
+ module Document
162
+ module V2Methods
132
163
  module Configurables
133
164
  attr_writer :scheme
134
165
  def scheme
@@ -174,6 +205,7 @@ module Scorpio
174
205
  end
175
206
  end
176
207
  include Configurables
208
+ include(OpenAPI::Document)
177
209
  end
178
210
  end
179
211
  end