jsapi 0.1.1

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 (121) hide show
  1. checksums.yaml +7 -0
  2. data/lib/jsapi/controller/base.rb +21 -0
  3. data/lib/jsapi/controller/error_result.rb +21 -0
  4. data/lib/jsapi/controller/methods.rb +144 -0
  5. data/lib/jsapi/controller/parameters.rb +86 -0
  6. data/lib/jsapi/controller/parameters_invalid.rb +25 -0
  7. data/lib/jsapi/controller/response.rb +84 -0
  8. data/lib/jsapi/controller.rb +13 -0
  9. data/lib/jsapi/dsl/callbacks.rb +32 -0
  10. data/lib/jsapi/dsl/class_methods.rb +85 -0
  11. data/lib/jsapi/dsl/definitions.rb +102 -0
  12. data/lib/jsapi/dsl/error.rb +38 -0
  13. data/lib/jsapi/dsl/examples.rb +30 -0
  14. data/lib/jsapi/dsl/node.rb +62 -0
  15. data/lib/jsapi/dsl/openapi/callback.rb +23 -0
  16. data/lib/jsapi/dsl/openapi/root.rb +12 -0
  17. data/lib/jsapi/dsl/openapi.rb +4 -0
  18. data/lib/jsapi/dsl/operation.rb +118 -0
  19. data/lib/jsapi/dsl/parameter.rb +10 -0
  20. data/lib/jsapi/dsl/request_body.rb +10 -0
  21. data/lib/jsapi/dsl/response.rb +33 -0
  22. data/lib/jsapi/dsl/schema.rb +87 -0
  23. data/lib/jsapi/dsl.rb +24 -0
  24. data/lib/jsapi/json/array.rb +35 -0
  25. data/lib/jsapi/json/boolean.rb +17 -0
  26. data/lib/jsapi/json/integer.rb +15 -0
  27. data/lib/jsapi/json/null.rb +27 -0
  28. data/lib/jsapi/json/number.rb +15 -0
  29. data/lib/jsapi/json/object.rb +53 -0
  30. data/lib/jsapi/json/string.rb +29 -0
  31. data/lib/jsapi/json/value.rb +47 -0
  32. data/lib/jsapi/json.rb +41 -0
  33. data/lib/jsapi/meta/attributes/class_methods.rb +112 -0
  34. data/lib/jsapi/meta/attributes/type_caster.rb +48 -0
  35. data/lib/jsapi/meta/attributes.rb +4 -0
  36. data/lib/jsapi/meta/base.rb +41 -0
  37. data/lib/jsapi/meta/base_reference.rb +33 -0
  38. data/lib/jsapi/meta/definitions.rb +226 -0
  39. data/lib/jsapi/meta/example/model.rb +44 -0
  40. data/lib/jsapi/meta/example/reference.rb +15 -0
  41. data/lib/jsapi/meta/example.rb +19 -0
  42. data/lib/jsapi/meta/existence.rb +69 -0
  43. data/lib/jsapi/meta/invalid_argument_error.rb +11 -0
  44. data/lib/jsapi/meta/openapi/callback/model.rb +36 -0
  45. data/lib/jsapi/meta/openapi/callback/reference.rb +16 -0
  46. data/lib/jsapi/meta/openapi/callback.rb +21 -0
  47. data/lib/jsapi/meta/openapi/contact.rb +34 -0
  48. data/lib/jsapi/meta/openapi/external_documentation.rb +28 -0
  49. data/lib/jsapi/meta/openapi/info.rb +52 -0
  50. data/lib/jsapi/meta/openapi/license.rb +28 -0
  51. data/lib/jsapi/meta/openapi/link/model.rb +48 -0
  52. data/lib/jsapi/meta/openapi/link/reference.rb +16 -0
  53. data/lib/jsapi/meta/openapi/link.rb +21 -0
  54. data/lib/jsapi/meta/openapi/oauth_flow.rb +50 -0
  55. data/lib/jsapi/meta/openapi/root.rb +134 -0
  56. data/lib/jsapi/meta/openapi/security_requirement.rb +27 -0
  57. data/lib/jsapi/meta/openapi/security_scheme/api_key.rb +38 -0
  58. data/lib/jsapi/meta/openapi/security_scheme/base.rb +16 -0
  59. data/lib/jsapi/meta/openapi/security_scheme/http/basic.rb +31 -0
  60. data/lib/jsapi/meta/openapi/security_scheme/http/bearer.rb +37 -0
  61. data/lib/jsapi/meta/openapi/security_scheme/http/other.rb +37 -0
  62. data/lib/jsapi/meta/openapi/security_scheme/http.rb +31 -0
  63. data/lib/jsapi/meta/openapi/security_scheme/oauth2.rb +47 -0
  64. data/lib/jsapi/meta/openapi/security_scheme/open_id_connect.rb +33 -0
  65. data/lib/jsapi/meta/openapi/security_scheme.rb +51 -0
  66. data/lib/jsapi/meta/openapi/server.rb +34 -0
  67. data/lib/jsapi/meta/openapi/server_variable.rb +34 -0
  68. data/lib/jsapi/meta/openapi/tag.rb +34 -0
  69. data/lib/jsapi/meta/openapi/version.rb +41 -0
  70. data/lib/jsapi/meta/openapi.rb +16 -0
  71. data/lib/jsapi/meta/operation.rb +186 -0
  72. data/lib/jsapi/meta/parameter/model.rb +170 -0
  73. data/lib/jsapi/meta/parameter/reference.rb +30 -0
  74. data/lib/jsapi/meta/parameter.rb +19 -0
  75. data/lib/jsapi/meta/property.rb +62 -0
  76. data/lib/jsapi/meta/reference_error.rb +12 -0
  77. data/lib/jsapi/meta/request_body/model.rb +65 -0
  78. data/lib/jsapi/meta/request_body/reference.rb +14 -0
  79. data/lib/jsapi/meta/request_body.rb +19 -0
  80. data/lib/jsapi/meta/rescue_handler.rb +26 -0
  81. data/lib/jsapi/meta/response/model.rb +72 -0
  82. data/lib/jsapi/meta/response/reference.rb +17 -0
  83. data/lib/jsapi/meta/response.rb +19 -0
  84. data/lib/jsapi/meta/schema/array.rb +42 -0
  85. data/lib/jsapi/meta/schema/base.rb +146 -0
  86. data/lib/jsapi/meta/schema/boolean.rb +9 -0
  87. data/lib/jsapi/meta/schema/boundary.rb +37 -0
  88. data/lib/jsapi/meta/schema/conversion.rb +28 -0
  89. data/lib/jsapi/meta/schema/delegator.rb +26 -0
  90. data/lib/jsapi/meta/schema/discriminator.rb +36 -0
  91. data/lib/jsapi/meta/schema/integer.rb +9 -0
  92. data/lib/jsapi/meta/schema/number.rb +9 -0
  93. data/lib/jsapi/meta/schema/numeric.rb +56 -0
  94. data/lib/jsapi/meta/schema/object.rb +85 -0
  95. data/lib/jsapi/meta/schema/reference.rb +38 -0
  96. data/lib/jsapi/meta/schema/string.rb +58 -0
  97. data/lib/jsapi/meta/schema/validation/base.rb +29 -0
  98. data/lib/jsapi/meta/schema/validation/enum.rb +26 -0
  99. data/lib/jsapi/meta/schema/validation/max_items.rb +26 -0
  100. data/lib/jsapi/meta/schema/validation/max_length.rb +26 -0
  101. data/lib/jsapi/meta/schema/validation/maximum.rb +51 -0
  102. data/lib/jsapi/meta/schema/validation/min_items.rb +26 -0
  103. data/lib/jsapi/meta/schema/validation/min_length.rb +26 -0
  104. data/lib/jsapi/meta/schema/validation/minimum.rb +51 -0
  105. data/lib/jsapi/meta/schema/validation/multiple_of.rb +24 -0
  106. data/lib/jsapi/meta/schema/validation/pattern.rb +30 -0
  107. data/lib/jsapi/meta/schema/validation.rb +12 -0
  108. data/lib/jsapi/meta/schema.rb +61 -0
  109. data/lib/jsapi/meta.rb +23 -0
  110. data/lib/jsapi/model/attributes.rb +22 -0
  111. data/lib/jsapi/model/base.rb +34 -0
  112. data/lib/jsapi/model/error.rb +15 -0
  113. data/lib/jsapi/model/errors.rb +51 -0
  114. data/lib/jsapi/model/naming.rb +28 -0
  115. data/lib/jsapi/model/nestable.rb +37 -0
  116. data/lib/jsapi/model/nested_error.rb +54 -0
  117. data/lib/jsapi/model/validations.rb +27 -0
  118. data/lib/jsapi/model.rb +15 -0
  119. data/lib/jsapi/version.rb +8 -0
  120. data/lib/jsapi.rb +8 -0
  121. metadata +162 -0
@@ -0,0 +1,47 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Jsapi
4
+ module Meta
5
+ module OpenAPI
6
+ module SecurityScheme
7
+ # Represents a security scheme based on \OAuth2.
8
+ class OAuth2 < Base
9
+ ##
10
+ # :attr: oauth_flows
11
+ # The hash containing the OAuth flows. Possible keys are:
12
+ #
13
+ # - <code>"authorization_code"</code>
14
+ # - <code>"client_credentials"</code>
15
+ # - <code>"implicit"</code>
16
+ # - <code>"password"</code>
17
+ #
18
+ # Values are OAuthFlow objects.
19
+ attribute :oauth_flows,
20
+ { String => OAuthFlow },
21
+ keys: %w[authorization_code client_credentials implicit password]
22
+
23
+ # Returns a hash representing the security scheme object.
24
+ def to_openapi(version)
25
+ version = Version.from(version)
26
+ {
27
+ type: 'oauth2',
28
+ description: description
29
+ }.tap do |h|
30
+ if oauth_flows&.any?
31
+ if version.major == 2
32
+ key, oauth_flow = oauth_flows.first
33
+ h[:flow] = key.to_s
34
+ h.merge!(oauth_flow.to_openapi(version))
35
+ else
36
+ h[:flows] = oauth_flows.to_h do |key, value|
37
+ [key.to_s.camelize(:lower).to_sym, value.to_openapi(version)]
38
+ end
39
+ end
40
+ end
41
+ end.compact
42
+ end
43
+ end
44
+ end
45
+ end
46
+ end
47
+ end
@@ -0,0 +1,33 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Jsapi
4
+ module Meta
5
+ module OpenAPI
6
+ module SecurityScheme
7
+ # Represents a security scheme based on OpenID Connect.
8
+ #
9
+ # OpenID Connect was introduced with \OpenAPI 3.0. Thus, a security
10
+ # scheme of this class is skipped when generating an \OpenAPI 2.0
11
+ # document.
12
+ class OpenIDConnect < Base
13
+ ##
14
+ # :attr: open_id_connect_url
15
+ attribute :open_id_connect_url, String
16
+
17
+ # Returns a hash representing the security scheme object, or +nil+
18
+ # if <code>version.major</code> is 2.
19
+ def to_openapi(version)
20
+ version = Version.from(version)
21
+ return if version.major == 2
22
+
23
+ {
24
+ type: 'openIdConnect',
25
+ openIdConnectUrl: open_id_connect_url,
26
+ description: description
27
+ }.compact
28
+ end
29
+ end
30
+ end
31
+ end
32
+ end
33
+ end
@@ -0,0 +1,51 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative 'security_scheme/base'
4
+ require_relative 'security_scheme/api_key'
5
+ require_relative 'security_scheme/http'
6
+ require_relative 'security_scheme/oauth2'
7
+ require_relative 'security_scheme/open_id_connect'
8
+
9
+ module Jsapi
10
+ module Meta
11
+ module OpenAPI
12
+ module SecurityScheme
13
+ class << self
14
+ # Creates a security scheme. The +:type+ keyword specifies the type
15
+ # of the security scheme to be created. Possible types are:
16
+ #
17
+ # - <code>"api_key"</code>
18
+ # - <code>"basic"</code>
19
+ # - <code>"http"</code>
20
+ # - <code>"oauth2"</code>
21
+ # - <code>"open_id_connect"</code>
22
+ #
23
+ # Raises an InvalidArgumentError if the given type is invalid.
24
+ def new(keywords = {})
25
+ type = keywords[:type]
26
+ keywords = keywords.except(:type)
27
+
28
+ case type&.to_s
29
+ when 'api_key'
30
+ APIKey.new(keywords)
31
+ when 'basic' # OpenAPI 2.0
32
+ HTTP.new(keywords.merge(scheme: 'basic'))
33
+ when 'http' # OpenAPI 3.x
34
+ HTTP.new(keywords)
35
+ when 'oauth2'
36
+ OAuth2.new(keywords)
37
+ when 'open_id_connect' # OpenAPI 3.x
38
+ OpenIDConnect.new(keywords)
39
+ else
40
+ raise InvalidArgumentError.new(
41
+ 'type',
42
+ type,
43
+ %w[api_key basic http oauth2 open_id_connect]
44
+ )
45
+ end
46
+ end
47
+ end
48
+ end
49
+ end
50
+ end
51
+ end
@@ -0,0 +1,34 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Jsapi
4
+ module Meta
5
+ module OpenAPI
6
+ # Represents a server object.
7
+ class Server < Base
8
+ ##
9
+ # :attr: description
10
+ # The optional description of the server.
11
+ attribute :description, String
12
+
13
+ ##
14
+ # :attr: url
15
+ # The absolute or relative URL of the server.
16
+ attribute :url, String
17
+
18
+ ##
19
+ # :attr_reader: variables
20
+ # The optional server variables.
21
+ attribute :variables, { String => ServerVariable }
22
+
23
+ # Returns a hash representing the server object.
24
+ def to_openapi(*)
25
+ {
26
+ url: url,
27
+ description: description,
28
+ variables: variables&.transform_values(&:to_openapi)
29
+ }.compact
30
+ end
31
+ end
32
+ end
33
+ end
34
+ end
@@ -0,0 +1,34 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Jsapi
4
+ module Meta
5
+ module OpenAPI
6
+ # Represents a server variable object.
7
+ class ServerVariable < Base
8
+ ##
9
+ # :attr: default
10
+ # The default value of the server variable.
11
+ attribute :default, String
12
+
13
+ ##
14
+ # :attr: description
15
+ # The optional description of the server variable.
16
+ attribute :description, String
17
+
18
+ ##
19
+ # :attr: enum
20
+ # The values of the server variable.
21
+ attribute :enum, [String]
22
+
23
+ # Returns a hash representing the server variable object.
24
+ def to_openapi(*)
25
+ {
26
+ default: default,
27
+ enum: enum.presence, # must not be empty
28
+ description: description
29
+ }.compact
30
+ end
31
+ end
32
+ end
33
+ end
34
+ end
@@ -0,0 +1,34 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Jsapi
4
+ module Meta
5
+ module OpenAPI
6
+ # Represents a tag object.
7
+ class Tag < Base
8
+ ##
9
+ # :attr: description
10
+ # The description of the tag.
11
+ attribute :description, String
12
+
13
+ ##
14
+ # :attr: external_docs
15
+ # The ExternalDocumentation object.
16
+ attribute :external_docs, ExternalDocumentation
17
+
18
+ ##
19
+ # :attr: name
20
+ # The name of the tag.
21
+ attribute :name, String
22
+
23
+ # Returns a hash representing the tag object.
24
+ def to_openapi(*)
25
+ {
26
+ name: name,
27
+ description: description,
28
+ externalDocs: external_docs&.to_openapi
29
+ }.compact
30
+ end
31
+ end
32
+ end
33
+ end
34
+ end
@@ -0,0 +1,41 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Jsapi
4
+ module Meta
5
+ module OpenAPI
6
+ class Version
7
+ def self.from(version)
8
+ return version if version.is_a?(Version)
9
+
10
+ case version
11
+ when '2.0', 2, nil
12
+ new(2, 0)
13
+ when '3.0', 3
14
+ new(3, 0)
15
+ when '3.1'
16
+ new(3, 1)
17
+ else
18
+ raise ArgumentError, "unsupported OpenAPI version: #{version.inspect}"
19
+ end
20
+ end
21
+
22
+ attr_reader :major, :minor
23
+
24
+ def initialize(major, minor)
25
+ @major = major
26
+ @minor = minor
27
+ end
28
+
29
+ def ==(other) # :nodoc:
30
+ other.is_a?(self.class) &&
31
+ @major == other.major &&
32
+ @minor == other.minor
33
+ end
34
+
35
+ def to_s # :nodoc:
36
+ "#{major}.#{minor}"
37
+ end
38
+ end
39
+ end
40
+ end
41
+ end
@@ -0,0 +1,16 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative 'openapi/version'
4
+ require_relative 'openapi/callback'
5
+ require_relative 'openapi/contact'
6
+ require_relative 'openapi/license'
7
+ require_relative 'openapi/info'
8
+ require_relative 'openapi/external_documentation'
9
+ require_relative 'openapi/oauth_flow'
10
+ require_relative 'openapi/security_scheme'
11
+ require_relative 'openapi/security_requirement'
12
+ require_relative 'openapi/server_variable'
13
+ require_relative 'openapi/server'
14
+ require_relative 'openapi/link'
15
+ require_relative 'openapi/tag'
16
+ require_relative 'openapi/root'
@@ -0,0 +1,186 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Jsapi
4
+ module Meta
5
+ class Operation < Base
6
+ ##
7
+ # :attr: callbacks
8
+ # The optional callbacks. Applies to \OpenAPI 3.x.
9
+ attribute :callbacks, { String => OpenAPI::Callback }
10
+
11
+ ##
12
+ # :attr: consumed_mime_types
13
+ # The MIME types consumed by the operation.
14
+ # Applies to \OpenAPI 2.0 only.
15
+ attribute :consumed_mime_types, [String]
16
+
17
+ alias :consumes :consumed_mime_types
18
+ alias :consumes= :consumed_mime_types=
19
+ alias :add_consumes :add_consumed_mime_type
20
+
21
+ ##
22
+ # :attr: deprecated
23
+ # Specifies whether or not the operation is deprecated.
24
+ attribute :deprecated, values: [true, false]
25
+
26
+ ##
27
+ # :attr: description
28
+ # The optional description of the operation.
29
+ attribute :description, String
30
+
31
+ ##
32
+ # :attr: external_docs
33
+ # The optional OpenAPI::ExternalDocumentation object.
34
+ attribute :external_docs, OpenAPI::ExternalDocumentation
35
+
36
+ ##
37
+ # :attr: method
38
+ # The HTTP verb of the operation. Possible values are:
39
+ #
40
+ # - <code>"delete"</code>
41
+ # - <code>"get"</code>
42
+ # - <code>"head"</code>
43
+ # - <code>"options"</code>
44
+ # - <code>"patch"</code>
45
+ # - <code>"post"</code>
46
+ # - <code>"put"</code>
47
+ #
48
+ # The default HTTP verb is <code>"get"</code>.
49
+ attribute :method,
50
+ values: %w[delete get head options patch post put],
51
+ default: 'get'
52
+
53
+ ##
54
+ # :attr: model
55
+ # The model class to access top-level parameters by. The default
56
+ # model class is Model::Base.
57
+ attribute :model, Class, default: Model::Base
58
+
59
+ ##
60
+ # :attr_reader: name
61
+ # The name of the operation.
62
+ attribute :name, writer: false
63
+
64
+ ##
65
+ # :attr: parameters
66
+ # The parameters of the operation.
67
+ attribute :parameters, { String => Parameter },
68
+ default: {},
69
+ writer: false
70
+
71
+ ##
72
+ # :attr: path
73
+ # The relative path of the operation.
74
+ attribute :path, String
75
+
76
+ ##
77
+ # :attr: consumed_mime_types
78
+ # The MIME types produced by the operation.
79
+ # Applies to \OpenAPI 2.0 only.
80
+ attribute :produced_mime_types, [String]
81
+
82
+ alias :produces :produced_mime_types
83
+ alias :produces= :produced_mime_types=
84
+ alias :add_produces :add_produced_mime_type
85
+
86
+ ##
87
+ # :attr: request_body
88
+ # The optional request body of the operation.
89
+ attribute :request_body, RequestBody
90
+
91
+ ##
92
+ # :attr: responses
93
+ # The responses of the operation.
94
+ attribute :responses, { String => Response },
95
+ default: {},
96
+ default_key: 'default'
97
+
98
+ ##
99
+ # :attr: schemes
100
+ # The transfer protocols supported by the operation. Possible
101
+ # values are:
102
+ #
103
+ # - <code>"http"</code>
104
+ # - <code>"https"</code>
105
+ # - <code>"ws"</code>
106
+ # - <code>"wss"</code>
107
+ #
108
+ # Applies to \OpenAPI 2.0 only.
109
+ attribute :schemes, [String], values: %w[http https ws wss]
110
+
111
+ ##
112
+ # :attr: security_requirements
113
+ # The OpenAPI::SecurityRequirement objects.
114
+ attribute :security_requirements, [OpenAPI::SecurityRequirement]
115
+
116
+ alias add_security add_security_requirement
117
+
118
+ ##
119
+ # :attr: servers
120
+ # The OpenAPI::Server objects. Applies to \OpenAPI 3.x.
121
+ attribute :servers, [OpenAPI::Server]
122
+
123
+ ##
124
+ # :attr: summary
125
+ # The optional summary of the operation.
126
+ attribute :summary, String
127
+
128
+ ##
129
+ # :attr: tags
130
+ # The tags used to group operations in an \OpenAPI document.
131
+ attribute :tags, [String]
132
+
133
+ def initialize(name = nil, keywords = {})
134
+ @name = name&.to_s
135
+ super(keywords)
136
+ end
137
+
138
+ def add_parameter(name, keywords = {}) # :nodoc:
139
+ (@parameters ||= {})[name.to_s] = Parameter.new(name, keywords)
140
+ end
141
+
142
+ # Returns a hash representing the \OpenAPI operation object.
143
+ def to_openapi(version, definitions)
144
+ version = OpenAPI::Version.from(version)
145
+ {
146
+ operationId: name,
147
+ tags: tags,
148
+ summary: summary,
149
+ description: description,
150
+ externalDocs: external_docs&.to_openapi,
151
+ deprecated: deprecated?.presence,
152
+ security: security_requirements&.map(&:to_openapi)
153
+ }.tap do |hash|
154
+ if version.major == 2
155
+ hash[:consumes] = consumed_mime_types if consumed_mime_types
156
+ hash[:produces] = produced_mime_types if produced_mime_types
157
+ hash[:schemes] = schemes if schemes
158
+ elsif servers
159
+ hash[:servers] = servers.map(&:to_openapi)
160
+ end
161
+ # Parameters (and request body)
162
+ hash[:parameters] = parameters.values.flat_map do |parameter|
163
+ parameter.to_openapi(version, definitions)
164
+ end
165
+ if request_body
166
+ if version.major == 2
167
+ hash[:parameters] << request_body.resolve(definitions).to_openapi_parameter
168
+ else
169
+ hash[:request_body] = request_body.to_openapi(version)
170
+ end
171
+ end
172
+ # Responses
173
+ hash[:responses] = responses.transform_values do |response|
174
+ response.to_openapi(version, definitions)
175
+ end
176
+ # Callbacks
177
+ if callbacks && version.major > 2
178
+ hash[:callbacks] = callbacks.transform_values do |callback|
179
+ callback.to_openapi(version, definitions)
180
+ end
181
+ end
182
+ end.compact
183
+ end
184
+ end
185
+ end
186
+ end
@@ -0,0 +1,170 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Jsapi
4
+ module Meta
5
+ module Parameter
6
+ class Model < Base
7
+ ##
8
+ # :attr: deprecated
9
+ # Specifies whether or not the parameter is deprecated.
10
+ attribute :deprecated, values: [true, false]
11
+
12
+ ##
13
+ # :attr: description
14
+ # The optional description of the parameter.
15
+ attribute :description, String
16
+
17
+ ##
18
+ # :attr_reader: examples
19
+ # The optional examples.
20
+ attribute :examples, { String => Example }, default_key: 'default'
21
+
22
+ ##
23
+ # :attr: in
24
+ # The location of the parameter. Possible values are:
25
+ #
26
+ # - <code>"path"</code>
27
+ # - <code>"query"</code>
28
+ #
29
+ # The default location is <code>"query"</code>.
30
+ attribute :in, String, values: %w[path query], default: 'query'
31
+
32
+ ##
33
+ # :attr_reader: name
34
+ # The name of the parameter.
35
+ attribute :name, writer: false
36
+
37
+ ##
38
+ # :attr_reader: schema
39
+ # The Schema of the parameter.
40
+ attribute :schema, writer: false
41
+
42
+ delegate_missing_to :schema
43
+
44
+ # Creates a new parameter.
45
+ #
46
+ # Raises an +ArgumentError+ if +name+ is blank.
47
+ def initialize(name, keywords = {})
48
+ raise ArgumentError, "parameter name can't be blank" if name.blank?
49
+
50
+ keywords = keywords.dup
51
+ super(keywords.extract!(:deprecated, :description, :examples, :in))
52
+
53
+ add_example(value: keywords.delete(:example)) if keywords.key?(:example)
54
+
55
+ @name = name.to_s
56
+ @schema = Schema.new(keywords)
57
+ end
58
+
59
+ # Returns true if empty values are allowed as specified by \OpenAPI,
60
+ # false otherwise.
61
+ def allow_empty_value?
62
+ schema.existence <= Existence::ALLOW_EMPTY && self.in != 'path'
63
+ end
64
+
65
+ # Returns true if it is required as specified by \JSON \Schema,
66
+ # false otherwise.
67
+ def required?
68
+ schema.existence > Existence::ALLOW_OMITTED || self.in == 'path'
69
+ end
70
+
71
+ # Returns an array of hashes representing the \OpenAPI parameter objects.
72
+ def to_openapi(version, definitions)
73
+ version = OpenAPI::Version.from(version)
74
+ schema = self.schema.resolve(definitions)
75
+
76
+ if schema.object?
77
+ explode_object_parameter(
78
+ name,
79
+ schema,
80
+ version,
81
+ definitions,
82
+ required: required?,
83
+ deprecated: deprecated?
84
+ )
85
+ else
86
+ parameter_name = schema.array? ? "#{name}[]" : name
87
+ [
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
114
+ ]
115
+ end
116
+ end
117
+
118
+ private
119
+
120
+ def explode_object_parameter(name, schema, version, definitions, **options)
121
+ schema.resolve_properties(:read, definitions).values.flat_map do |property|
122
+ property_schema = property.schema.resolve(definitions)
123
+ parameter_name = "#{name}[#{property.name}]"
124
+
125
+ required = (property.required? && options[:required]).presence
126
+ deprecated = (property.deprecated? || options[:deprecated]).presence
127
+
128
+ if property_schema.object?
129
+ explode_object_parameter(
130
+ parameter_name,
131
+ property_schema,
132
+ version,
133
+ definitions,
134
+ required: required,
135
+ deprecated: deprecated
136
+ )
137
+ else
138
+ parameter_name = "#{parameter_name}[]" if property_schema.array?
139
+ description = property_schema.description
140
+ allow_empty_value = property.schema.existence <= Existence::ALLOW_EMPTY
141
+ [
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
163
+ ]
164
+ end
165
+ end
166
+ end
167
+ end
168
+ end
169
+ end
170
+ end
@@ -0,0 +1,30 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Jsapi
4
+ module Meta
5
+ module Parameter
6
+ class Reference < BaseReference
7
+ # Returns an array of hashes. Each element represents an \OpenAPI
8
+ # parameter object if the type of the referred parameter is
9
+ # <code>"object"</code>. Otherwise the array contains a single
10
+ # hash representing the \OpenAPI reference object.
11
+ #
12
+ # Raises a ReferenceError if the reference could not be resolved.
13
+ def to_openapi(version, definitions)
14
+ version = OpenAPI::Version.from(version)
15
+ parameter = resolve(definitions)
16
+
17
+ if parameter.schema.resolve(definitions).object?
18
+ # Explode referred parameter
19
+ parameter.to_openapi(version, definitions)
20
+ else
21
+ # Return an array containing the reference object
22
+ path = version.major == 2 ? 'parameters' : 'components/parameters'
23
+
24
+ [{ '$ref': "#/#{path}/#{ref}" }]
25
+ end
26
+ end
27
+ end
28
+ end
29
+ end
30
+ end