jsapi 0.1.2 → 0.3.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 (46) hide show
  1. checksums.yaml +4 -4
  2. data/lib/jsapi/controller/methods.rb +4 -3
  3. data/lib/jsapi/controller/parameters.rb +2 -5
  4. data/lib/jsapi/controller/response.rb +48 -24
  5. data/lib/jsapi/dsl/parameter.rb +0 -10
  6. data/lib/jsapi/dsl/request_body.rb +0 -10
  7. data/lib/jsapi/dsl/response.rb +0 -10
  8. data/lib/jsapi/dsl/schema.rb +1 -1
  9. data/lib/jsapi/json/array.rb +2 -3
  10. data/lib/jsapi/json/null.rb +2 -2
  11. data/lib/jsapi/json/object.rb +6 -9
  12. data/lib/jsapi/json/string.rb +25 -11
  13. data/lib/jsapi/json/value.rb +4 -4
  14. data/lib/jsapi/meta/example/model.rb +3 -4
  15. data/lib/jsapi/meta/openapi/contact.rb +3 -5
  16. data/lib/jsapi/meta/openapi/extensions.rb +31 -0
  17. data/lib/jsapi/meta/openapi/external_documentation.rb +3 -4
  18. data/lib/jsapi/meta/openapi/info.rb +4 -2
  19. data/lib/jsapi/meta/openapi/license.rb +3 -4
  20. data/lib/jsapi/meta/openapi/link/model.rb +4 -2
  21. data/lib/jsapi/meta/openapi/oauth_flow.rb +4 -2
  22. data/lib/jsapi/meta/openapi/root.rb +36 -31
  23. data/lib/jsapi/meta/openapi/security_scheme/api_key.rb +4 -2
  24. data/lib/jsapi/meta/openapi/security_scheme/http/basic.rb +17 -12
  25. data/lib/jsapi/meta/openapi/security_scheme/http/bearer.rb +4 -2
  26. data/lib/jsapi/meta/openapi/security_scheme/http/other.rb +4 -2
  27. data/lib/jsapi/meta/openapi/security_scheme/oauth2.rb +5 -5
  28. data/lib/jsapi/meta/openapi/security_scheme/open_id_connect.rb +4 -2
  29. data/lib/jsapi/meta/openapi/server.rb +4 -2
  30. data/lib/jsapi/meta/openapi/server_variable.rb +4 -2
  31. data/lib/jsapi/meta/openapi/tag.rb +4 -2
  32. data/lib/jsapi/meta/openapi.rb +1 -0
  33. data/lib/jsapi/meta/operation.rb +6 -3
  34. data/lib/jsapi/meta/parameter/model.rb +56 -48
  35. data/lib/jsapi/meta/property.rb +3 -1
  36. data/lib/jsapi/meta/request_body/model.rb +6 -3
  37. data/lib/jsapi/meta/response/model.rb +28 -22
  38. data/lib/jsapi/meta/schema/additional_properties.rb +29 -0
  39. data/lib/jsapi/meta/schema/array.rb +9 -1
  40. data/lib/jsapi/meta/schema/base.rb +34 -29
  41. data/lib/jsapi/meta/schema/object.rb +10 -2
  42. data/lib/jsapi/meta/schema/reference.rb +0 -3
  43. data/lib/jsapi/meta/schema/string.rb +2 -6
  44. data/lib/jsapi/meta/schema.rb +3 -4
  45. data/lib/jsapi/version.rb +3 -3
  46. metadata +4 -2
@@ -7,21 +7,26 @@ module Jsapi
7
7
  module HTTP
8
8
  # Represents a security scheme based on \HTTP basic authentication.
9
9
  class Basic < Base
10
+ include Extensions
11
+
10
12
  # Returns a hash representing the security scheme object.
11
13
  def to_openapi(version)
12
14
  version = OpenAPI::Version.from(version)
13
- if version.major == 2
14
- {
15
- type: 'basic',
16
- description: description
17
- }
18
- else
19
- {
20
- type: 'http',
21
- scheme: 'basic',
22
- description: description
23
- }
24
- end.compact
15
+
16
+ with_openapi_extensions(
17
+ if version.major == 2
18
+ {
19
+ type: 'basic',
20
+ description: description
21
+ }
22
+ else
23
+ {
24
+ type: 'http',
25
+ scheme: 'basic',
26
+ description: description
27
+ }
28
+ end
29
+ )
25
30
  end
26
31
  end
27
32
  end
@@ -11,6 +11,8 @@ module Jsapi
11
11
  # Thus, a security scheme of this class is skipped when generating
12
12
  # an \OpenAPI 2.0 document.
13
13
  class Bearer < Base
14
+ include Extensions
15
+
14
16
  ##
15
17
  # :attr: bearer_format
16
18
  # The optional format of the bearer token.
@@ -22,12 +24,12 @@ module Jsapi
22
24
  version = OpenAPI::Version.from(version)
23
25
  return if version.major == 2
24
26
 
25
- {
27
+ with_openapi_extensions(
26
28
  type: 'http',
27
29
  scheme: 'bearer',
28
30
  bearerFormat: bearer_format,
29
31
  description: description
30
- }.compact
32
+ )
31
33
  end
32
34
  end
33
35
  end
@@ -12,6 +12,8 @@ module Jsapi
12
12
  # a security scheme of this class is skipped when generating an
13
13
  # \OpenAPI 2.0 document.
14
14
  class Other < Base
15
+ include Extensions
16
+
15
17
  ##
16
18
  # :attr: scheme
17
19
  # The mandatory \HTTP authentication scheme.
@@ -23,11 +25,11 @@ module Jsapi
23
25
  version = OpenAPI::Version.from(version)
24
26
  return if version.major == 2
25
27
 
26
- {
28
+ with_openapi_extensions(
27
29
  type: 'http',
28
30
  scheme: scheme,
29
31
  description: description
30
- }.compact
32
+ )
31
33
  end
32
34
  end
33
35
  end
@@ -6,6 +6,8 @@ module Jsapi
6
6
  module SecurityScheme
7
7
  # Represents a security scheme based on \OAuth2.
8
8
  class OAuth2 < Base
9
+ include Extensions
10
+
9
11
  ##
10
12
  # :attr: oauth_flows
11
13
  # The hash containing the OAuth flows. Possible keys are:
@@ -22,10 +24,8 @@ module Jsapi
22
24
  # Returns a hash representing the security scheme object.
23
25
  def to_openapi(version)
24
26
  version = Version.from(version)
25
- {
26
- type: 'oauth2',
27
- description: description
28
- }.tap do |h|
27
+
28
+ with_openapi_extensions(type: 'oauth2', description: description).tap do |h|
29
29
  if oauth_flows&.any?
30
30
  if version.major == 2
31
31
  key, oauth_flow = oauth_flows.first
@@ -37,7 +37,7 @@ module Jsapi
37
37
  end
38
38
  end
39
39
  end
40
- end.compact
40
+ end
41
41
  end
42
42
  end
43
43
  end
@@ -9,6 +9,8 @@ module Jsapi
9
9
  # OpenID Connect was introduced with \OpenAPI 3.0. Thus, a security scheme of
10
10
  # this class is skipped when generating an \OpenAPI 2.0 document.
11
11
  class OpenIDConnect < Base
12
+ include Extensions
13
+
12
14
  ##
13
15
  # :attr: open_id_connect_url
14
16
  attribute :open_id_connect_url, String
@@ -19,11 +21,11 @@ module Jsapi
19
21
  version = Version.from(version)
20
22
  return if version.major == 2
21
23
 
22
- {
24
+ with_openapi_extensions(
23
25
  type: 'openIdConnect',
24
26
  openIdConnectUrl: open_id_connect_url,
25
27
  description: description
26
- }.compact
28
+ )
27
29
  end
28
30
  end
29
31
  end
@@ -5,6 +5,8 @@ module Jsapi
5
5
  module OpenAPI
6
6
  # Represents a server object.
7
7
  class Server < Base
8
+ include Extensions
9
+
8
10
  ##
9
11
  # :attr: description
10
12
  # The optional description of the server.
@@ -22,11 +24,11 @@ module Jsapi
22
24
 
23
25
  # Returns a hash representing the server object.
24
26
  def to_openapi(*)
25
- {
27
+ with_openapi_extensions(
26
28
  url: url,
27
29
  description: description,
28
30
  variables: variables&.transform_values(&:to_openapi)
29
- }.compact
31
+ )
30
32
  end
31
33
  end
32
34
  end
@@ -5,6 +5,8 @@ module Jsapi
5
5
  module OpenAPI
6
6
  # Represents a server variable object.
7
7
  class ServerVariable < Base
8
+ include Extensions
9
+
8
10
  ##
9
11
  # :attr: default
10
12
  # The default value of the server variable.
@@ -22,11 +24,11 @@ module Jsapi
22
24
 
23
25
  # Returns a hash representing the server variable object.
24
26
  def to_openapi(*)
25
- {
27
+ with_openapi_extensions(
26
28
  default: default,
27
29
  enum: enum.presence, # must not be empty
28
30
  description: description
29
- }.compact
31
+ )
30
32
  end
31
33
  end
32
34
  end
@@ -5,6 +5,8 @@ module Jsapi
5
5
  module OpenAPI
6
6
  # Represents a tag object.
7
7
  class Tag < Base
8
+ include Extensions
9
+
8
10
  ##
9
11
  # :attr: description
10
12
  # The description of the tag.
@@ -22,11 +24,11 @@ module Jsapi
22
24
 
23
25
  # Returns a hash representing the tag object.
24
26
  def to_openapi(*)
25
- {
27
+ with_openapi_extensions(
26
28
  name: name,
27
29
  description: description,
28
30
  externalDocs: external_docs&.to_openapi
29
- }.compact
31
+ )
30
32
  end
31
33
  end
32
34
  end
@@ -1,5 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require_relative 'openapi/extensions'
3
4
  require_relative 'openapi/version'
4
5
  require_relative 'openapi/callback'
5
6
  require_relative 'openapi/contact'
@@ -3,6 +3,8 @@
3
3
  module Jsapi
4
4
  module Meta
5
5
  class Operation < Base
6
+ include OpenAPI::Extensions
7
+
6
8
  ##
7
9
  # :attr: callbacks
8
10
  # The optional callbacks. Applies to \OpenAPI 3.0 and higher.
@@ -133,7 +135,8 @@ module Jsapi
133
135
  # Returns a hash representing the \OpenAPI operation object.
134
136
  def to_openapi(version, definitions)
135
137
  version = OpenAPI::Version.from(version)
136
- {
138
+
139
+ with_openapi_extensions(
137
140
  operationId: name,
138
141
  tags: tags,
139
142
  summary: summary,
@@ -141,7 +144,7 @@ module Jsapi
141
144
  externalDocs: external_docs&.to_openapi,
142
145
  deprecated: deprecated?.presence,
143
146
  security: security_requirements&.map(&:to_openapi)
144
- }.tap do |hash|
147
+ ).tap do |hash|
145
148
  if version.major == 2
146
149
  hash[:consumes] = consumed_mime_types if consumed_mime_types
147
150
  hash[:produces] = produced_mime_types if produced_mime_types
@@ -170,7 +173,7 @@ module Jsapi
170
173
  callback.to_openapi(version, definitions)
171
174
  end
172
175
  end
173
- end.compact
176
+ end
174
177
  end
175
178
  end
176
179
  end
@@ -4,6 +4,8 @@ module Jsapi
4
4
  module Meta
5
5
  module Parameter
6
6
  class Model < Base
7
+ include OpenAPI::Extensions
8
+
7
9
  ##
8
10
  # :attr: deprecated
9
11
  # Specifies whether or not the parameter is deprecated.
@@ -47,12 +49,14 @@ module Jsapi
47
49
  def initialize(name, keywords = {})
48
50
  raise ArgumentError, "parameter name can't be blank" if name.blank?
49
51
 
52
+ @name = name.to_s
53
+
50
54
  keywords = keywords.dup
51
55
  super(keywords.extract!(:deprecated, :description, :examples, :in))
52
56
 
53
57
  add_example(value: keywords.delete(:example)) if keywords.key?(:example)
58
+ keywords[:ref] = keywords.delete(:schema) if keywords.key?(:schema)
54
59
 
55
- @name = name.to_s
56
60
  @schema = Schema.new(keywords)
57
61
  end
58
62
 
@@ -85,32 +89,34 @@ module Jsapi
85
89
  else
86
90
  parameter_name = schema.array? ? "#{name}[]" : name
87
91
  [
88
- if version.major == 2
89
- {
90
- name: parameter_name,
91
- in: self.in,
92
- description: description,
93
- required: required?.presence,
94
- allowEmptyValue: allow_empty_value?.presence,
95
- collectionFormat: ('multi' if schema.array?)
96
- }.merge(schema.to_openapi(version))
97
- else
98
- {
99
- name: parameter_name,
100
- in: self.in,
101
- description: description,
102
- required: required?.presence,
103
- allowEmptyValue: allow_empty_value?.presence,
104
- deprecated: deprecated?.presence,
105
- schema: schema.to_openapi(version),
106
- examples: examples&.transform_values(&:to_openapi)
107
-
108
- # NOTE: collectionFormat is replaced by style and explode.
109
- # The default values for query parameters are:
110
- # - style: 'form'
111
- # - explode: true
112
- }
113
- end.compact
92
+ with_openapi_extensions(
93
+ if version.major == 2
94
+ {
95
+ name: parameter_name,
96
+ in: self.in,
97
+ description: description,
98
+ required: required?.presence,
99
+ allowEmptyValue: allow_empty_value?.presence,
100
+ collectionFormat: ('multi' if schema.array?)
101
+ }.merge(schema.to_openapi(version))
102
+ else
103
+ {
104
+ name: parameter_name,
105
+ in: self.in,
106
+ description: description,
107
+ required: required?.presence,
108
+ allowEmptyValue: allow_empty_value?.presence,
109
+ deprecated: deprecated?.presence,
110
+ schema: schema.to_openapi(version),
111
+ examples: examples&.transform_values(&:to_openapi)
112
+
113
+ # NOTE: collectionFormat is replaced by style and explode.
114
+ # The default values for query parameters are:
115
+ # - style: 'form'
116
+ # - explode: true
117
+ }
118
+ end
119
+ )
114
120
  ]
115
121
  end
116
122
  end
@@ -139,27 +145,29 @@ module Jsapi
139
145
  description = property_schema.description
140
146
  allow_empty_value = property.schema.existence <= Existence::ALLOW_EMPTY
141
147
  [
142
- if version.major == 2
143
- {
144
- name: parameter_name,
145
- in: self.in,
146
- description: description,
147
- required: required,
148
- allowEmptyValue: allow_empty_value.presence,
149
- collectionFormat: ('multi' if property_schema.array?)
150
- }.merge(property_schema.to_openapi(version))
151
- else
152
- {
153
- name: parameter_name,
154
- in: self.in,
155
- description: description,
156
- required: required,
157
- allowEmptyValue: allow_empty_value.presence,
158
- deprecated: deprecated,
159
- schema: property_schema.to_openapi(version).except(:deprecated),
160
- examples: examples&.transform_values(&:to_openapi)
161
- }
162
- end.compact
148
+ with_openapi_extensions(
149
+ if version.major == 2
150
+ {
151
+ name: parameter_name,
152
+ in: self.in,
153
+ description: description,
154
+ required: required,
155
+ allowEmptyValue: allow_empty_value.presence,
156
+ collectionFormat: ('multi' if property_schema.array?)
157
+ }.merge(property_schema.to_openapi(version))
158
+ else
159
+ {
160
+ name: parameter_name,
161
+ in: self.in,
162
+ description: description,
163
+ required: required,
164
+ allowEmptyValue: allow_empty_value.presence,
165
+ deprecated: deprecated,
166
+ schema: property_schema.to_openapi(version).except(:deprecated),
167
+ examples: examples&.transform_values(&:to_openapi)
168
+ }
169
+ end
170
+ )
163
171
  ]
164
172
  end
165
173
  end
@@ -34,10 +34,12 @@ module Jsapi
34
34
  def initialize(name, keywords = {})
35
35
  raise ArgumentError, "property name can't be blank" if name.blank?
36
36
 
37
+ @name = name.to_s
38
+
37
39
  keywords = keywords.dup
38
40
  super(keywords.extract!(:read_only, :source, :write_only))
41
+ keywords[:ref] = keywords.delete(:schema) if keywords.key?(:schema)
39
42
 
40
- @name = name.to_s
41
43
  @schema = Schema.new(keywords)
42
44
  end
43
45
 
@@ -4,6 +4,8 @@ module Jsapi
4
4
  module Meta
5
5
  module RequestBody
6
6
  class Model < Base
7
+ include OpenAPI::Extensions
8
+
7
9
  ##
8
10
  # :attr: description
9
11
  # The optional description of the request body.
@@ -26,6 +28,7 @@ module Jsapi
26
28
  super(keywords.extract!(:description, :examples))
27
29
 
28
30
  add_example(value: keywords.delete(:example)) if keywords.key?(:example)
31
+ keywords[:ref] = keywords.delete(:schema) if keywords.key?(:schema)
29
32
 
30
33
  @schema = Schema.new(keywords)
31
34
  end
@@ -43,12 +46,12 @@ module Jsapi
43
46
  in: 'body',
44
47
  description: description,
45
48
  required: required?
46
- }.merge(schema.to_openapi('2.0')).compact
49
+ }.merge(schema.to_openapi('2.0')).merge(openapi_extensions).compact
47
50
  end
48
51
 
49
52
  # Returns a hash representing the \OpenAPI 3.x request body object.
50
53
  def to_openapi(version)
51
- {
54
+ with_openapi_extensions(
52
55
  description: description,
53
56
  content: {
54
57
  'application/json' => {
@@ -57,7 +60,7 @@ module Jsapi
57
60
  }.compact
58
61
  },
59
62
  required: required?
60
- }.compact
63
+ )
61
64
  end
62
65
  end
63
66
  end
@@ -4,6 +4,8 @@ module Jsapi
4
4
  module Meta
5
5
  module Response
6
6
  class Model < Base
7
+ include OpenAPI::Extensions
8
+
7
9
  ##
8
10
  # :attr: description
9
11
  # The optional description of the response.
@@ -36,6 +38,7 @@ module Jsapi
36
38
  super(keywords.extract!(:description, :examples, :locale))
37
39
 
38
40
  add_example(value: keywords.delete(:example)) if keywords.key?(:example)
41
+ keywords[:ref] = keywords.delete(:schema) if keywords.key?(:schema)
39
42
 
40
43
  @schema = Schema.new(**keywords)
41
44
  end
@@ -43,28 +46,31 @@ module Jsapi
43
46
  # Returns a hash representing the \OpenAPI response object.
44
47
  def to_openapi(version, definitions)
45
48
  version = OpenAPI::Version.from(version)
46
- if version.major == 2
47
- {
48
- description: description,
49
- schema: schema.to_openapi(version),
50
- examples: (
51
- if (example = examples&.values&.first).present?
52
- { 'application/json' => example.resolve(definitions).value }
53
- end
54
- )
55
- }
56
- else
57
- {
58
- description: description,
59
- content: {
60
- 'application/json' => {
61
- schema: schema.to_openapi(version),
62
- examples: examples&.transform_values(&:to_openapi)
63
- }.compact
64
- },
65
- links: links&.transform_values(&:to_openapi)
66
- }
67
- end.compact
49
+
50
+ with_openapi_extensions(
51
+ if version.major == 2
52
+ {
53
+ description: description,
54
+ schema: schema.to_openapi(version),
55
+ examples: (
56
+ if (example = examples&.values&.first).present?
57
+ { 'application/json' => example.resolve(definitions).value }
58
+ end
59
+ )
60
+ }
61
+ else
62
+ {
63
+ description: description,
64
+ content: {
65
+ 'application/json' => {
66
+ schema: schema.to_openapi(version),
67
+ examples: examples&.transform_values(&:to_openapi)
68
+ }.compact
69
+ },
70
+ links: links&.transform_values(&:to_openapi)
71
+ }
72
+ end
73
+ )
68
74
  end
69
75
  end
70
76
  end
@@ -0,0 +1,29 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Jsapi
4
+ module Meta
5
+ module Schema
6
+ class AdditionalProperties < Meta::Base
7
+ #
8
+ # :attr: schema
9
+ # The Schema of additional properties.
10
+ attribute :schema, Schema, writer: false
11
+
12
+ ##
13
+ # :attr: source
14
+ # The method to read additional properties when serializing an object.
15
+ # The default method is +additional_properties+.
16
+ attribute :source, Symbol, default: :additional_properties
17
+
18
+ delegate_missing_to :schema
19
+
20
+ def initialize(keywords = {})
21
+ keywords = keywords.dup
22
+ super(keywords.extract!(:source))
23
+
24
+ @schema = Schema.new(keywords)
25
+ end
26
+ end
27
+ end
28
+ end
29
+ end
@@ -7,7 +7,7 @@ module Jsapi
7
7
  ##
8
8
  # :attr: items
9
9
  # The Schema defining the kind of items.
10
- attribute :items, Schema
10
+ attribute :items, Schema, writer: false
11
11
 
12
12
  ##
13
13
  # :attr: max_items
@@ -19,6 +19,14 @@ module Jsapi
19
19
  # The minimum length of an array.
20
20
  attribute :min_items, writer: false
21
21
 
22
+ def items=(keywords = {}) # :nodoc:
23
+ if keywords.key?(:schema)
24
+ keywords = keywords.dup
25
+ keywords[:ref] = keywords.delete(:schema)
26
+ end
27
+ @items = Schema.new(keywords)
28
+ end
29
+
22
30
  def max_items=(value) # :nodoc:
23
31
  add_validation('max_items', Validation::MaxItems.new(value))
24
32
  @max_items = value
@@ -4,6 +4,8 @@ module Jsapi
4
4
  module Meta
5
5
  module Schema
6
6
  class Base < Meta::Base
7
+ include OpenAPI::Extensions
8
+
7
9
  TYPES = %w[array boolean integer number object string].freeze # :nodoc:
8
10
 
9
11
  TYPES.each do |type|
@@ -96,37 +98,40 @@ module Jsapi
96
98
  # Returns a hash representing the \OpenAPI schema object.
97
99
  def to_openapi(version)
98
100
  version = OpenAPI::Version.from(version)
99
- if version.major == 2
100
- # OpenAPI 2.0
101
- {
102
- type: type,
103
- example: examples&.first
104
- }
105
- elsif version.minor.zero?
106
- # OpenAPI 3.0
107
- {
108
- type: type,
109
- nullable: nullable?.presence,
110
- examples: examples,
111
- deprecated: deprecated?.presence
112
- }
113
- else
114
- # OpenAPI 3.1
115
- {
116
- type: nullable? ? [type, 'null'] : type,
117
- examples: examples,
118
- deprecated: deprecated?.presence
119
- }
120
- end.tap do |hash|
121
- hash[:title] = title
122
- hash[:description] = description
123
- hash[:default] = default
124
- hash[:externalDocs] = external_docs&.to_openapi
125
101
 
126
- validations.each_value do |validation|
127
- hash.merge!(validation.to_openapi_validation(version))
102
+ with_openapi_extensions(
103
+ if version.major == 2
104
+ # OpenAPI 2.0
105
+ {
106
+ type: type,
107
+ example: examples&.first
108
+ }
109
+ elsif version.minor.zero?
110
+ # OpenAPI 3.0
111
+ {
112
+ type: type,
113
+ nullable: nullable?.presence,
114
+ examples: examples,
115
+ deprecated: deprecated?.presence
116
+ }
117
+ else
118
+ # OpenAPI 3.1
119
+ {
120
+ type: nullable? ? [type, 'null'] : type,
121
+ examples: examples,
122
+ deprecated: deprecated?.presence
123
+ }
124
+ end.tap do |hash|
125
+ hash[:title] = title
126
+ hash[:description] = description
127
+ hash[:default] = default
128
+ hash[:externalDocs] = external_docs&.to_openapi
129
+
130
+ validations.each_value do |validation|
131
+ hash.merge!(validation.to_openapi_validation(version))
132
+ end
128
133
  end
129
- end.compact
134
+ )
130
135
  end
131
136
 
132
137
  def type # :nodoc: