jsapi 1.1.1 → 1.3

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 (40) hide show
  1. checksums.yaml +4 -4
  2. data/lib/jsapi/configuration.rb +2 -2
  3. data/lib/jsapi/controller/methods.rb +17 -4
  4. data/lib/jsapi/controller/parameters.rb +27 -10
  5. data/lib/jsapi/controller/response.rb +29 -5
  6. data/lib/jsapi/json/array.rb +4 -0
  7. data/lib/jsapi/json/object.rb +2 -0
  8. data/lib/jsapi/json/value.rb +5 -0
  9. data/lib/jsapi/meta/callback/base.rb +1 -1
  10. data/lib/jsapi/meta/definitions.rb +10 -6
  11. data/lib/jsapi/meta/example/base.rb +4 -6
  12. data/lib/jsapi/meta/link/base.rb +4 -2
  13. data/lib/jsapi/meta/oauth_flow.rb +11 -2
  14. data/lib/jsapi/meta/openapi/path_item.rb +46 -0
  15. data/lib/jsapi/meta/openapi/version.rb +6 -0
  16. data/lib/jsapi/meta/openapi.rb +2 -0
  17. data/lib/jsapi/meta/operation.rb +6 -14
  18. data/lib/jsapi/meta/parameter/base.rb +82 -59
  19. data/lib/jsapi/meta/request_body/base.rb +3 -2
  20. data/lib/jsapi/meta/response/base.rb +26 -8
  21. data/lib/jsapi/meta/schema/base.rb +1 -1
  22. data/lib/jsapi/meta/schema/discriminator.rb +14 -4
  23. data/lib/jsapi/meta/schema/object.rb +28 -9
  24. data/lib/jsapi/meta/schema/validation/maximum.rb +1 -1
  25. data/lib/jsapi/meta/schema/validation/minimum.rb +1 -1
  26. data/lib/jsapi/meta/security_scheme/api_key.rb +4 -5
  27. data/lib/jsapi/meta/security_scheme/base.rb +16 -0
  28. data/lib/jsapi/meta/security_scheme/http/basic.rb +3 -10
  29. data/lib/jsapi/meta/security_scheme/http/bearer.rb +8 -8
  30. data/lib/jsapi/meta/security_scheme/http/other.rb +3 -5
  31. data/lib/jsapi/meta/security_scheme/mutual_tls.rb +23 -0
  32. data/lib/jsapi/meta/security_scheme/oauth2.rb +29 -13
  33. data/lib/jsapi/meta/security_scheme/open_id_connect.rb +5 -8
  34. data/lib/jsapi/meta/security_scheme.rb +3 -0
  35. data/lib/jsapi/meta/server.rb +9 -1
  36. data/lib/jsapi/meta/tag.rb +34 -4
  37. data/lib/jsapi/model/base.rb +37 -1
  38. data/lib/jsapi/model/nestable.rb +27 -1
  39. data/lib/jsapi/version.rb +1 -1
  40. metadata +4 -2
@@ -9,6 +9,11 @@ module Jsapi
9
9
 
10
10
  delegate_missing_to :schema
11
11
 
12
+ ##
13
+ # :attr: content_type
14
+ # The content type used to describe complex parameters in \OpenAPI 3.0 and higher.
15
+ attribute :content_type, String
16
+
12
17
  ##
13
18
  # :attr: deprecated
14
19
  # Specifies whether or not the parameter is deprecated.
@@ -31,9 +36,10 @@ module Jsapi
31
36
  # - <code>"header"</code>
32
37
  # - <code>"path"</code>
33
38
  # - <code>"query"</code>
39
+ # - <code>"querystring"</code>
34
40
  #
35
41
  # The default location is <code>"query"</code>.
36
- attribute :in, String, values: %w[header path query], default: 'query'
42
+ attribute :in, String, values: %w[header path query querystring], default: 'query'
37
43
 
38
44
  ##
39
45
  # :attr_reader: name
@@ -54,8 +60,16 @@ module Jsapi
54
60
  @name = name.to_s
55
61
 
56
62
  keywords = keywords.dup
57
- super(keywords.extract!(:deprecated, :description, :examples, :in, :openapi_extensions))
58
-
63
+ super(
64
+ keywords.extract!(
65
+ :content_type,
66
+ :deprecated,
67
+ :description,
68
+ :examples,
69
+ :in,
70
+ :openapi_extensions
71
+ )
72
+ )
59
73
  add_example(value: keywords.delete(:example)) if keywords.key?(:example)
60
74
  keywords[:ref] = keywords.delete(:schema) if keywords.key?(:schema)
61
75
 
@@ -75,12 +89,13 @@ module Jsapi
75
89
  # Returns a hash representing the \OpenAPI parameter object.
76
90
  def to_openapi(version, definitions)
77
91
  version = OpenAPI::Version.from(version)
78
- schema = self.schema.resolve(definitions)
79
92
 
80
- openapi_parameter(
93
+ openapi_parameter_object(
81
94
  name,
82
- schema,
95
+ schema.resolve(definitions),
83
96
  version,
97
+ location: self.in,
98
+ content_type: content_type || ('text/plain' if self.in == 'querystring'),
84
99
  description: description,
85
100
  required: required?,
86
101
  deprecated: deprecated?,
@@ -92,39 +107,30 @@ module Jsapi
92
107
  # Returns an array of hashes representing the \OpenAPI parameter objects.
93
108
  def to_openapi_parameters(version, definitions)
94
109
  version = OpenAPI::Version.from(version)
110
+ is_querystring = self.in == 'querystring'
95
111
  schema = self.schema.resolve(definitions)
96
112
 
97
- if schema.object?
113
+ if schema.object? && (version < OpenAPI::V3_2 || !is_querystring)
98
114
  explode_parameter(
99
- name,
115
+ is_querystring ? nil : name,
100
116
  schema,
101
117
  version,
102
118
  definitions,
119
+ location: is_querystring ? 'query' : self.in,
103
120
  required: required?,
104
121
  deprecated: deprecated?
105
122
  )
106
123
  else
107
- [
108
- openapi_parameter(
109
- name,
110
- schema,
111
- version,
112
- description: description,
113
- required: required?,
114
- deprecated: deprecated?,
115
- allow_empty_value: allow_empty_value?,
116
- examples: examples
117
- )
118
- ]
119
- end
124
+ [to_openapi(version, definitions)]
125
+ end.compact
120
126
  end
121
127
 
122
128
  private
123
129
 
124
- def explode_parameter(name, schema, version, definitions, required:, deprecated:)
130
+ def explode_parameter(name, schema, version, definitions, location:, required:, deprecated:)
125
131
  schema.resolve_properties(definitions, context: :request).values.flat_map do |property|
126
132
  property_schema = property.schema.resolve(definitions)
127
- parameter_name = "#{name}[#{property.name}]"
133
+ parameter_name = name ? "#{name}[#{property.name}]" : property.name
128
134
  required = (required && property.required?).presence
129
135
  deprecated = (deprecated || property_schema.deprecated?).presence
130
136
 
@@ -134,62 +140,79 @@ module Jsapi
134
140
  property_schema,
135
141
  version,
136
142
  definitions,
143
+ location: location,
137
144
  required: required,
138
145
  deprecated: deprecated
139
146
  )
140
147
  else
141
148
  [
142
- openapi_parameter(
149
+ openapi_parameter_object(
143
150
  parameter_name,
144
151
  property_schema,
145
152
  version,
153
+ location: location,
146
154
  description: property_schema.description,
147
155
  required: required,
148
156
  deprecated: deprecated,
149
157
  allow_empty_value: property.schema.existence <= Existence::ALLOW_EMPTY
150
158
  )
151
159
  ]
152
- end
160
+ end.compact
153
161
  end
154
162
  end
155
163
 
156
- def openapi_parameter(name, schema, version,
157
- allow_empty_value:,
158
- deprecated:,
159
- description:,
160
- required:,
161
- examples: nil)
164
+ def openapi_parameter_object(name, schema, version,
165
+ allow_empty_value:,
166
+ deprecated:,
167
+ description:,
168
+ location:,
169
+ required:,
170
+ content_type: nil,
171
+ examples: nil)
162
172
 
163
- name = schema.array? ? "#{name}[]" : name
173
+ return if location == 'querystring' && version < OpenAPI::V3_2
174
+
175
+ if schema.object? && version == OpenAPI::V2_0
176
+ raise "OpenAPI 2.0 doesn't allow object parameters in #{location}"
177
+ end
178
+
179
+ name = "#{name}[]" if schema.array?
164
180
 
165
181
  with_openapi_extensions(
166
- if version.major == 2
167
- raise "OpenAPI 2.0 doesn't allow object parameters " \
168
- "in #{self.in}" if schema.object?
169
-
170
- {
171
- name: name,
172
- in: self.in,
173
- description: description,
174
- required: required.presence,
175
- allowEmptyValue: allow_empty_value.presence,
176
- collectionFormat: ('multi' if schema.array?)
177
- }.merge(schema.to_openapi(version))
178
- else
179
- {
180
- name: name,
181
- in: self.in,
182
- description: description,
183
- required: required.presence,
184
- allowEmptyValue: allow_empty_value.presence,
185
- deprecated: deprecated.presence,
186
- schema: schema.to_openapi(version).except(:deprecated),
187
- examples: examples&.transform_values(&:to_openapi).presence
188
-
189
- # NOTE: collectionFormat is replaced by 'style' and 'explode'.
190
- # The default values are equal to 'multi'.
191
- }
192
- end
182
+ name: name,
183
+ in: location,
184
+ description: description,
185
+ required: required.presence,
186
+ allowEmptyValue: allow_empty_value.presence,
187
+ **if version == OpenAPI::V2_0
188
+ {
189
+ collectionFormat: ('multi' if schema.array?),
190
+ **schema.to_openapi(version)
191
+ }
192
+ else
193
+ openapi_schema = schema.to_openapi(version).except(:deprecated)
194
+ openapi_examples = examples&.transform_values(&:to_openapi).presence
195
+ {
196
+ deprecated: deprecated.presence,
197
+ **if content_type.blank?
198
+ # simple scenario
199
+ {
200
+ schema: openapi_schema,
201
+ examples: openapi_examples
202
+ }
203
+ else
204
+ # complex scenario
205
+ {
206
+ content: {
207
+ content_type => {
208
+ schema: openapi_schema,
209
+ examples: openapi_examples
210
+ }.compact
211
+ }
212
+ }
213
+ end
214
+ }
215
+ end
193
216
  )
194
217
  end
195
218
  end
@@ -52,8 +52,9 @@ module Jsapi
52
52
  name: 'body',
53
53
  in: 'body',
54
54
  description: description,
55
- required: required?
56
- }.merge(schema.to_openapi(OpenAPI::V2_0))
55
+ required: required?,
56
+ **schema.to_openapi(OpenAPI::V2_0)
57
+ }
57
58
  )
58
59
  end
59
60
 
@@ -8,12 +8,13 @@ module Jsapi
8
8
  include OpenAPI::Extensions
9
9
 
10
10
  JSON_TYPE = %r{(^application/|^text/|\+)json$}.freeze # :nodoc:
11
+ JSON_SEQ_TYPE = 'application/json-seq' # :nodoc:
11
12
 
12
13
  delegate_missing_to :schema
13
14
 
14
15
  ##
15
16
  # :attr: content_type
16
- # The content type. <code>"application/json"</code> by default.
17
+ # The content type, <code>"application/json"</code> by default.
17
18
  attribute :content_type, String, default: 'application/json'
18
19
 
19
20
  ##
@@ -46,12 +47,17 @@ module Jsapi
46
47
  # The Schema of the response.
47
48
  attribute :schema, accessors: %i[reader]
48
49
 
50
+ ##
51
+ # :attr: summary
52
+ # The short description of the response. Applies to \OpenAPI 3.2 and higher.
53
+ attribute :summary, String
54
+
49
55
  def initialize(keywords = {})
50
56
  keywords = keywords.dup
51
57
  super(
52
58
  keywords.extract!(
53
59
  :content_type, :description, :examples, :headers,
54
- :links, :locale, :openapi_extensions
60
+ :links, :locale, :openapi_extensions, :summary
55
61
  )
56
62
  )
57
63
  add_example(value: keywords.delete(:example)) if keywords.key?(:example)
@@ -66,12 +72,17 @@ module Jsapi
66
72
  content_type.match?(JSON_TYPE)
67
73
  end
68
74
 
75
+ # Returns true if content type is <code>"application/json-seq"</code>.
76
+ def json_seq_type?
77
+ content_type == JSON_SEQ_TYPE
78
+ end
79
+
69
80
  # Returns a hash representing the \OpenAPI response object.
70
81
  def to_openapi(version, definitions)
71
82
  version = OpenAPI::Version.from(version)
72
83
 
73
84
  with_openapi_extensions(
74
- if version.major == 2
85
+ if version == OpenAPI::V2_0
75
86
  {
76
87
  description: description,
77
88
  schema: schema.to_openapi(version),
@@ -86,17 +97,24 @@ module Jsapi
86
97
  }
87
98
  else
88
99
  {
100
+ summary: (summary if version >= OpenAPI::V3_2),
89
101
  description: description,
102
+ headers: headers.transform_values do |header|
103
+ header.to_openapi(version)
104
+ end.presence,
90
105
  content: {
91
106
  content_type => {
92
- schema: schema.to_openapi(version),
107
+ **if json_seq_type? && schema.array? && version >= OpenAPI::V3_2
108
+ { itemSchema: schema.items.to_openapi(version) }
109
+ else
110
+ { schema: schema.to_openapi(version) }
111
+ end,
93
112
  examples: examples.transform_values(&:to_openapi).presence
94
113
  }.compact
95
114
  },
96
- headers: headers.transform_values do |header|
97
- header.to_openapi(version)
98
- end.presence,
99
- links: links.transform_values(&:to_openapi).presence
115
+ links: links.transform_values do |link|
116
+ link.to_openapi(version)
117
+ end.presence
100
118
  }
101
119
  end
102
120
  )
@@ -121,7 +121,7 @@ module Jsapi
121
121
  deprecated: deprecated?.presence
122
122
  }
123
123
  else
124
- # OpenAPI 3.1
124
+ # OpenAPI 3.1 and higher
125
125
  {
126
126
  type: nullable? ? [type, 'null'] : type,
127
127
  examples: examples.presence,
@@ -4,8 +4,16 @@ module Jsapi
4
4
  module Meta
5
5
  module Schema
6
6
  class Discriminator < Model::Base
7
+ include OpenAPI::Extensions
8
+
9
+ ##
10
+ # :attr: default_mapping
11
+ # Applies to \OpenAPI 3.2 and higher.
12
+ attribute :default_mapping, String
13
+
7
14
  ##
8
15
  # :attr: mappings
16
+ # Applies to \OpenAPI 3.0 and higher.
9
17
  attribute :mappings, { Object => String }
10
18
 
11
19
  ##
@@ -15,12 +23,14 @@ module Jsapi
15
23
  # Returns a hash representing the \OpenAPI discriminator object.
16
24
  def to_openapi(version, *)
17
25
  version = OpenAPI::Version.from(version)
18
- return property_name if version.major == 2
26
+ return property_name if version < OpenAPI::V3_0
19
27
 
20
- {
28
+ result = {
21
29
  propertyName: property_name,
22
- mapping: mappings.transform_keys(&:to_s).presence
23
- }.compact
30
+ mapping: mappings.transform_keys(&:to_s).presence,
31
+ defaultMapping: (default_mapping if version >= OpenAPI::V3_2)
32
+ }
33
+ version >= OpenAPI::V3_1 ? with_openapi_extensions(result) : result.compact
24
34
  end
25
35
  end
26
36
  end
@@ -57,17 +57,36 @@ module Jsapi
57
57
 
58
58
  properties = resolve_properties(definitions, context: context)
59
59
 
60
- property = properties[discriminator.property_name]
61
- raise InvalidValueError.new('discriminator property',
62
- discriminator.property_name,
63
- valid_values: properties.keys) if property.nil?
60
+ discriminating_property = properties[discriminator.property_name]
61
+ if discriminating_property.nil?
62
+ raise InvalidValueError.new('discriminator property',
63
+ discriminator.property_name,
64
+ valid_values: properties.keys)
65
+ end
66
+
67
+ discriminating_value = discriminating_property.reader.call(object)
68
+ if discriminating_value.nil?
69
+ discriminating_value = discriminating_property.default_value(
70
+ definitions,
71
+ context: context
72
+ )
73
+ if discriminating_value.nil? && discriminator.default_mapping.nil?
74
+ raise "discriminating value can't be nil"
75
+ end
76
+ end
64
77
 
65
- value = property.reader.call(object)
66
- value = property.default_value(definitions, context: context) if value.nil?
67
- raise "#{discriminator.property_name} can't be nil" if value.nil?
78
+ schema_name = discriminator.mapping(discriminating_value) || discriminating_value
68
79
 
69
- schema = definitions.find_schema(discriminator.mapping(value) || value)
70
- raise "inheriting schema couldn't be found: #{value.inspect}" if schema.nil?
80
+ schema = definitions.find_schema(schema_name)
81
+ if schema.nil?
82
+ default_mapping = discriminator.default_mapping
83
+ schema = definitions.find_schema(default_mapping) unless default_mapping.nil?
84
+
85
+ if schema.nil?
86
+ raise "inheriting schema couldn't be found: " \
87
+ "#{[schema_name, default_mapping].compact.map(&:inspect).join(' or ')}"
88
+ end
89
+ end
71
90
 
72
91
  schema.resolve(definitions).resolve_schema(object, definitions, context: context)
73
92
  end
@@ -43,7 +43,7 @@ module Jsapi
43
43
 
44
44
  def to_openapi_validation(version)
45
45
  version = OpenAPI::Version.from(version)
46
- return to_json_schema_validation if version.major == 3 && version.minor == 1
46
+ return to_json_schema_validation if version >= OpenAPI::V3_1
47
47
  return super unless exclusive
48
48
 
49
49
  { maximum: value, exclusiveMaximum: true }
@@ -43,7 +43,7 @@ module Jsapi
43
43
 
44
44
  def to_openapi_validation(version)
45
45
  version = OpenAPI::Version.from(version)
46
- return to_json_schema_validation if version.major == 3 && version.minor == 1
46
+ return to_json_schema_validation if version >= OpenAPI::V3_1
47
47
  return super unless exclusive
48
48
 
49
49
  { minimum: value, exclusiveMinimum: true }
@@ -24,12 +24,11 @@ module Jsapi
24
24
  attribute :name, String
25
25
 
26
26
  # Returns a hash representing the \OpenAPI security scheme object.
27
- def to_openapi(*)
27
+ def to_openapi(version, *)
28
+ version = OpenAPI::Version.from(version)
29
+
28
30
  with_openapi_extensions(
29
- type: 'apiKey',
30
- name: name,
31
- in: self.in,
32
- description: description
31
+ base_openapi_fields('apiKey', version).merge(name: name, in: self.in)
33
32
  )
34
33
  end
35
34
  end
@@ -8,6 +8,22 @@ module Jsapi
8
8
  # :attr: description
9
9
  # The description of the security scheme.
10
10
  attribute :description, String
11
+
12
+ ##
13
+ # :attr: deprecated
14
+ # Specifies whether or not the security scheme is deprecated.
15
+ # Applies to \OpenAPI 3.2 and higher.
16
+ attribute :deprecated, values: [true, false]
17
+
18
+ private
19
+
20
+ def base_openapi_fields(type, version)
21
+ {
22
+ type: type,
23
+ description: description,
24
+ deprecated: (deprecated?.presence if version >= OpenAPI::V3_2)
25
+ }
26
+ end
11
27
  end
12
28
  end
13
29
  end
@@ -13,17 +13,10 @@ module Jsapi
13
13
  version = OpenAPI::Version.from(version)
14
14
 
15
15
  with_openapi_extensions(
16
- if version.major == 2
17
- {
18
- type: 'basic',
19
- description: description
20
- }
16
+ if version < OpenAPI::V3_0
17
+ base_openapi_fields('basic', version)
21
18
  else
22
- {
23
- type: 'http',
24
- scheme: 'basic',
25
- description: description
26
- }
19
+ base_openapi_fields('http', version).merge(scheme: 'basic')
27
20
  end
28
21
  )
29
22
  end
@@ -7,7 +7,7 @@ module Jsapi
7
7
  # Specifies a security scheme based on bearer authentication.
8
8
  #
9
9
  # Note that Bearer authentication was introduced with \OpenAPI 3.0. Thus, a security
10
- # scheme of this class is skipped when generating an \OpenAPI 2.0 document.
10
+ # scheme of this class is omitted when generating an \OpenAPI 2.0 document.
11
11
  class Bearer < Base
12
12
  include OpenAPI::Extensions
13
13
 
@@ -16,17 +16,17 @@ module Jsapi
16
16
  # The format of the bearer token.
17
17
  attribute :bearer_format, String
18
18
 
19
- # Returns a hash representing the \OpenAPI security scheme object, or
20
- # +nil+ if <code>version.major</code> is 2.
19
+ # Returns a hash representing the \OpenAPI security scheme object, or +nil+
20
+ # if <code>version</code> is less than \OpenAPI 3.0.
21
21
  def to_openapi(version, *)
22
22
  version = OpenAPI::Version.from(version)
23
- return if version.major == 2
23
+ return if version < OpenAPI::V3_0
24
24
 
25
25
  with_openapi_extensions(
26
- type: 'http',
27
- scheme: 'bearer',
28
- bearerFormat: bearer_format,
29
- description: description
26
+ base_openapi_fields('http', version).merge(
27
+ scheme: 'bearer',
28
+ bearerFormat: bearer_format
29
+ )
30
30
  )
31
31
  end
32
32
  end
@@ -18,15 +18,13 @@ module Jsapi
18
18
  attribute :scheme, String
19
19
 
20
20
  # Returns a hash representing the \OpenAPI security scheme object, or +nil+
21
- # if <code>version.major</code> is 2.
21
+ # if <code>version</code> is less than \OpenAPI 3.0.
22
22
  def to_openapi(version, *)
23
23
  version = OpenAPI::Version.from(version)
24
- return if version.major == 2
24
+ return if version < OpenAPI::V3_0
25
25
 
26
26
  with_openapi_extensions(
27
- type: 'http',
28
- scheme: scheme,
29
- description: description
27
+ base_openapi_fields('http', version).merge(scheme: scheme)
30
28
  )
31
29
  end
32
30
  end
@@ -0,0 +1,23 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Jsapi
4
+ module Meta
5
+ module SecurityScheme
6
+ # Specifies a security scheme based on MutualTLS.
7
+ class MutualTLS < Base
8
+ include OpenAPI::Extensions
9
+
10
+ # Returns a hash representing the \OpenAPI security scheme object, or +nil+
11
+ # if <code>version</code> is less than \OpenAPI 3.1.
12
+ def to_openapi(version, *)
13
+ version = OpenAPI::Version.from(version)
14
+ return if version < OpenAPI::V3_1
15
+
16
+ with_openapi_extensions(
17
+ base_openapi_fields('mutualTLS', version)
18
+ )
19
+ end
20
+ end
21
+ end
22
+ end
23
+ end
@@ -9,34 +9,50 @@ module Jsapi
9
9
 
10
10
  ##
11
11
  # :attr: oauth_flows
12
- # The hash containing the OAuth flows. Possible keys are:
12
+ # Maps one or more of the following keys to OAuthFlow objects.
13
13
  #
14
14
  # - <code>"authorization_code"</code>
15
15
  # - <code>"client_credentials"</code>
16
+ # - <code>"device_authorization"</code>
16
17
  # - <code>"implicit"</code>
17
18
  # - <code>"password"</code>
18
19
  #
19
- # Values are OAuthFlow objects.
20
+ # Note that <code>"device_authorization"</code> was introduced with \OpenAPI 3.2.
21
+ # This entry is omitted when generating an \OpenAPI document with a lower version.
20
22
  attribute :oauth_flows, { String => OAuthFlow },
21
- keys: %w[authorization_code client_credentials implicit password]
23
+ keys: %w[authorization_code
24
+ client_credentials
25
+ device_authorization
26
+ implicit
27
+ password]
28
+ ##
29
+ # :attr: oauth2_metadata_url
30
+ # The URL of the OAuth2 authorization server metadata.
31
+ # Applies to \OpenAPI 3.2 and higher.
32
+ attribute :oauth2_metadata_url, String
22
33
 
23
34
  # Returns a hash representing the \OpenAPI security scheme object.
24
35
  def to_openapi(version, *)
25
36
  version = OpenAPI::Version.from(version)
26
37
 
27
- with_openapi_extensions(type: 'oauth2', description: description).tap do |h|
28
- if oauth_flows.any?
29
- if version.major == 2
30
- key, oauth_flow = oauth_flows.first
31
- h[:flow] = key.to_s
32
- h.merge!(oauth_flow.to_openapi(version))
33
- else
34
- h[:flows] = oauth_flows.to_h do |key, value|
38
+ with_openapi_extensions(
39
+ base_openapi_fields('oauth2', version).tap do |fields|
40
+ flows = oauth_flows
41
+ flows = flows.except('device_authorization') unless version >= OpenAPI::V3_2
42
+
43
+ if version >= OpenAPI::V3_0
44
+ fields[:flows] = flows.to_h do |key, value|
35
45
  [key.to_s.camelize(:lower).to_sym, value.to_openapi(version)]
36
- end
46
+ end if flows.any?
47
+
48
+ fields[:oauth2MetadataUrl] = oauth2_metadata_url if version >= OpenAPI::V3_2
49
+ elsif flows.one?
50
+ key, flow = flows.first
51
+ fields[:flow] = key.to_s
52
+ fields.merge!(flow.to_openapi(version))
37
53
  end
38
54
  end
39
- end
55
+ )
40
56
  end
41
57
  end
42
58
  end