jsapi 0.4.1 → 0.6.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.
- checksums.yaml +4 -4
- data/lib/jsapi/controller/error_result.rb +11 -4
- data/lib/jsapi/controller/methods.rb +39 -13
- data/lib/jsapi/controller/parameters.rb +25 -23
- data/lib/jsapi/controller/parameters_invalid.rb +10 -7
- data/lib/jsapi/controller/response.rb +36 -19
- data/lib/jsapi/dsl/class_methods.rb +18 -10
- data/lib/jsapi/dsl/definitions.rb +11 -0
- data/lib/jsapi/dsl/openapi/callbacks.rb +34 -0
- data/lib/jsapi/dsl/openapi/examples.rb +32 -0
- data/lib/jsapi/dsl/openapi.rb +2 -0
- data/lib/jsapi/dsl/operation.rb +1 -1
- data/lib/jsapi/dsl/parameter.rb +1 -1
- data/lib/jsapi/dsl/request_body.rb +1 -1
- data/lib/jsapi/dsl/response.rb +1 -1
- data/lib/jsapi/dsl.rb +1 -3
- data/lib/jsapi/helpers/invalid_value_helper.rb +17 -0
- data/lib/jsapi/invalid_argument_error.rb +12 -0
- data/lib/jsapi/invalid_value_error.rb +12 -0
- data/lib/jsapi/json/object.rb +15 -14
- data/lib/jsapi/json.rb +1 -1
- data/lib/jsapi/meta/{attributes/class_methods.rb → base/attributes.rb} +7 -5
- data/lib/jsapi/meta/base/model.rb +44 -0
- data/lib/jsapi/meta/base/reference.rb +36 -0
- data/lib/jsapi/meta/{attributes → base}/type_caster.rb +2 -2
- data/lib/jsapi/meta/base.rb +4 -40
- data/lib/jsapi/meta/callable/symbol_evaluator.rb +30 -0
- data/lib/jsapi/meta/callable/symbol_sequence_evaluator.rb +29 -0
- data/lib/jsapi/meta/callable.rb +28 -0
- data/lib/jsapi/meta/defaults.rb +28 -0
- data/lib/jsapi/meta/definitions.rb +30 -25
- data/lib/jsapi/meta/openapi/callback/model.rb +1 -1
- data/lib/jsapi/meta/openapi/callback/reference.rb +1 -1
- data/lib/jsapi/meta/openapi/contact.rb +1 -1
- data/lib/jsapi/meta/openapi/example/model.rb +1 -1
- data/lib/jsapi/meta/openapi/example/reference.rb +1 -1
- data/lib/jsapi/meta/openapi/external_documentation.rb +1 -1
- data/lib/jsapi/meta/openapi/header/model.rb +19 -4
- data/lib/jsapi/meta/openapi/header/reference.rb +1 -1
- data/lib/jsapi/meta/openapi/info.rb +1 -1
- data/lib/jsapi/meta/openapi/license.rb +1 -1
- data/lib/jsapi/meta/openapi/link/model.rb +1 -1
- data/lib/jsapi/meta/openapi/link/reference.rb +1 -1
- data/lib/jsapi/meta/openapi/oauth_flow.rb +2 -2
- data/lib/jsapi/meta/openapi/root.rb +6 -20
- data/lib/jsapi/meta/openapi/security_requirement.rb +2 -2
- data/lib/jsapi/meta/openapi/security_scheme/base.rb +1 -1
- data/lib/jsapi/meta/openapi/security_scheme.rb +1 -1
- data/lib/jsapi/meta/openapi/server.rb +1 -1
- data/lib/jsapi/meta/openapi/server_variable.rb +1 -1
- data/lib/jsapi/meta/openapi/tag.rb +1 -1
- data/lib/jsapi/meta/operation.rb +21 -24
- data/lib/jsapi/meta/parameter/model.rb +6 -5
- data/lib/jsapi/meta/parameter/reference.rb +1 -1
- data/lib/jsapi/meta/property.rb +11 -5
- data/lib/jsapi/meta/request_body/model.rb +10 -5
- data/lib/jsapi/meta/request_body/reference.rb +1 -1
- data/lib/jsapi/meta/response/model.rb +11 -6
- data/lib/jsapi/meta/response/reference.rb +1 -1
- data/lib/jsapi/meta/schema/additional_properties.rb +8 -7
- data/lib/jsapi/meta/schema/base.rb +13 -7
- data/lib/jsapi/meta/schema/delegator.rb +2 -2
- data/lib/jsapi/meta/schema/discriminator.rb +3 -11
- data/lib/jsapi/meta/schema/object.rb +27 -4
- data/lib/jsapi/meta/schema/reference.rb +1 -1
- data/lib/jsapi/meta/schema.rb +12 -5
- data/lib/jsapi/meta.rb +3 -4
- data/lib/jsapi/model/attributes.rb +10 -4
- data/lib/jsapi/model/base.rb +1 -1
- data/lib/jsapi/model/nestable.rb +25 -10
- data/lib/jsapi/model/nested_error.rb +2 -2
- data/lib/jsapi/version.rb +1 -1
- data/lib/jsapi.rb +4 -0
- metadata +15 -10
- data/lib/jsapi/dsl/callbacks.rb +0 -32
- data/lib/jsapi/dsl/examples.rb +0 -30
- data/lib/jsapi/meta/attributes.rb +0 -4
- data/lib/jsapi/meta/base_reference.rb +0 -34
- data/lib/jsapi/meta/invalid_argument_error.rb +0 -12
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 49b5e17933d1306b3c7637f0d0dd37d3efb7f698acc43b0664c239d6caf4b593
|
4
|
+
data.tar.gz: '08b7e251c989693f2d055c140488278d2c2fb047a814fe4ff90be7fdb2fa8869'
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: ba696113c7b4e842085baa0ad4462a5566c7b5fb8c96030708eb4e33b47319865d86271d1f4b6643a39e83c7a59ee71c54b7d3ca6837e9515e6665d94e1ff7d2
|
7
|
+
data.tar.gz: 9f0e9aa79495064cdbebdfd12cbdd4501891ef5c5be30ffe3a0435afa58fd7ec87750eeb5c9068ff4da49a17e56c2e028512a260155ed2f0f13b4fde88cd23a4
|
@@ -2,19 +2,26 @@
|
|
2
2
|
|
3
3
|
module Jsapi
|
4
4
|
module Controller
|
5
|
-
# Used by
|
5
|
+
# Used by Methods#api_operation! to produce an error response.
|
6
6
|
class ErrorResult
|
7
|
+
delegate_missing_to :@exception
|
7
8
|
|
8
9
|
# The HTTP status code of the error response to be produced.
|
9
10
|
attr_reader :status
|
10
11
|
|
11
|
-
delegate :message, :to_s, to: :@exception
|
12
|
-
|
13
12
|
# Creates a new instance to produce an error response with the given HTTP status code.
|
14
|
-
def initialize(exception, status:)
|
13
|
+
def initialize(exception, status: nil)
|
15
14
|
@exception = exception
|
16
15
|
@status = status
|
17
16
|
end
|
17
|
+
|
18
|
+
# Returns the string representation of the exception encountered to render this string
|
19
|
+
# when the response type is +string+, for example:
|
20
|
+
#
|
21
|
+
# response 500, type: 'string'
|
22
|
+
def to_s
|
23
|
+
@exception.to_s
|
24
|
+
end
|
18
25
|
end
|
19
26
|
end
|
20
27
|
end
|
@@ -13,9 +13,9 @@ module Jsapi
|
|
13
13
|
end
|
14
14
|
|
15
15
|
# Performs an API operation by calling the given block. The request parameters are
|
16
|
-
# passed as an instance of the operation's model class to the block.
|
17
|
-
#
|
18
|
-
#
|
16
|
+
# passed as an instance of the operation's model class to the block. The object
|
17
|
+
# returned by the block is implicitly rendered according to the appropriate +response+
|
18
|
+
# specification.
|
19
19
|
#
|
20
20
|
# api_operation('foo') do |api_params|
|
21
21
|
# # ...
|
@@ -23,13 +23,22 @@ module Jsapi
|
|
23
23
|
#
|
24
24
|
# +operation_name+ can be +nil+ if the controller handles one operation only.
|
25
25
|
#
|
26
|
-
# If
|
26
|
+
# If +:strong+ is +true+, parameters that can be mapped are accepted only. That means
|
27
27
|
# that the model passed to the block is invalid if there are any request parameters
|
28
28
|
# that can't be mapped to a parameter or a request body property of the operation.
|
29
29
|
#
|
30
|
-
|
30
|
+
# The +:omit+ option specifies on which conditions properties are omitted.
|
31
|
+
# Possible values are:
|
32
|
+
#
|
33
|
+
# - +:empty+ - All of the properties whose value is empty are omitted.
|
34
|
+
# - +:nil+ - All of the properties whose value is +nil+ are omitted.
|
35
|
+
#
|
36
|
+
# Raises an InvalidArgumentError when the value of +:omit+ is invalid.
|
37
|
+
def api_operation(operation_name = nil, omit: nil, status: nil, strong: false, &block)
|
31
38
|
_perform_api_operation(
|
32
|
-
operation_name,
|
39
|
+
operation_name,
|
40
|
+
bang: false,
|
41
|
+
omit: omit,
|
33
42
|
status: status,
|
34
43
|
strong: strong,
|
35
44
|
&block
|
@@ -43,9 +52,11 @@ module Jsapi
|
|
43
52
|
# # ...
|
44
53
|
# end
|
45
54
|
#
|
46
|
-
def api_operation!(operation_name = nil, status: nil, strong: false, &block)
|
55
|
+
def api_operation!(operation_name = nil, omit: nil, status: nil, strong: false, &block)
|
47
56
|
_perform_api_operation(
|
48
|
-
operation_name,
|
57
|
+
operation_name,
|
58
|
+
bang: true,
|
59
|
+
omit: omit,
|
49
60
|
status: status,
|
50
61
|
strong: strong,
|
51
62
|
&block
|
@@ -79,12 +90,20 @@ module Jsapi
|
|
79
90
|
# render(json: api_response(bar, 'foo', status: 200))
|
80
91
|
#
|
81
92
|
# +operation_name+ can be +nil+ if the controller handles one operation only.
|
82
|
-
|
93
|
+
#
|
94
|
+
# The +:omit+ option specifies on which conditions properties are omitted.
|
95
|
+
# Possible values are:
|
96
|
+
#
|
97
|
+
# - +:empty+ - All of the properties whose value is empty are omitted.
|
98
|
+
# - +:nil+ - All of the properties whose value is +nil+ are omitted.
|
99
|
+
#
|
100
|
+
# Raises an InvalidArgumentError when the value of +:omit+ is invalid.
|
101
|
+
def api_response(result, operation_name = nil, omit: nil, status: nil)
|
83
102
|
definitions = api_definitions
|
84
103
|
operation = _api_operation(operation_name, definitions)
|
85
104
|
response = _api_response(operation, status, definitions)
|
86
105
|
|
87
|
-
Response.new(result, response, api_definitions)
|
106
|
+
Response.new(result, response, api_definitions, omit: omit)
|
88
107
|
end
|
89
108
|
|
90
109
|
private
|
@@ -98,7 +117,13 @@ module Jsapi
|
|
98
117
|
|
99
118
|
def _api_params(operation, definitions, strong:)
|
100
119
|
(operation.model || Model::Base).new(
|
101
|
-
Parameters.new(
|
120
|
+
Parameters.new(
|
121
|
+
params.except(:action, :controller, :format).permit!,
|
122
|
+
headers,
|
123
|
+
operation,
|
124
|
+
definitions,
|
125
|
+
strong: strong
|
126
|
+
)
|
102
127
|
)
|
103
128
|
end
|
104
129
|
|
@@ -109,7 +134,7 @@ module Jsapi
|
|
109
134
|
raise "status code not defined: #{status}"
|
110
135
|
end
|
111
136
|
|
112
|
-
def _perform_api_operation(operation_name, bang
|
137
|
+
def _perform_api_operation(operation_name, bang:, omit:, status:, strong:, &block)
|
113
138
|
definitions = api_definitions
|
114
139
|
operation = _api_operation(operation_name, definitions)
|
115
140
|
response = _api_response(operation, status, definitions)
|
@@ -141,10 +166,11 @@ module Jsapi
|
|
141
166
|
|
142
167
|
ErrorResult.new(e, status: status)
|
143
168
|
end
|
144
|
-
render(json: Response.new(result, response, definitions), status: status)
|
169
|
+
render(json: Response.new(result, response, definitions, omit: omit), status: status)
|
145
170
|
else
|
146
171
|
head(status)
|
147
172
|
end
|
173
|
+
self.content_type = response.content_type
|
148
174
|
end
|
149
175
|
end
|
150
176
|
end
|
@@ -6,7 +6,7 @@ module Jsapi
|
|
6
6
|
class Parameters
|
7
7
|
include Model::Nestable
|
8
8
|
|
9
|
-
attr_reader :raw_attributes
|
9
|
+
attr_reader :raw_additional_attributes, :raw_attributes
|
10
10
|
|
11
11
|
# Creates a new instance that wraps +params+ according to +operation+. References are
|
12
12
|
# resolved to API components in +definitions+.
|
@@ -14,29 +14,35 @@ module Jsapi
|
|
14
14
|
# If +strong+ is true+ parameters that can be mapped are accepted only. That means that
|
15
15
|
# the instance created is invalid if +params+ contains any parameters that can't be
|
16
16
|
# mapped to a parameter or a request body property of +operation+.
|
17
|
-
def initialize(params, operation, definitions, strong: false)
|
18
|
-
@params = params
|
17
|
+
def initialize(params, headers, operation, definitions, strong: false)
|
18
|
+
@params = params.to_h
|
19
19
|
@strong = strong == true
|
20
20
|
@raw_attributes = {}
|
21
|
+
@raw_additional_attributes = {}
|
21
22
|
|
22
|
-
#
|
23
|
-
|
24
|
-
|
25
|
-
end
|
26
|
-
request_body = operation.request_body&.resolve(definitions)
|
27
|
-
if request_body && request_body.schema.respond_to?(:properties)
|
28
|
-
meta_models.merge!(request_body.schema.resolve_properties(:write, definitions))
|
29
|
-
end
|
23
|
+
# Parameters
|
24
|
+
operation.parameters.each do |name, parameter_model|
|
25
|
+
parameter_model = parameter_model.resolve(definitions)
|
30
26
|
|
31
|
-
|
32
|
-
|
33
|
-
|
27
|
+
@raw_attributes[name] = JSON.wrap(
|
28
|
+
parameter_model.in == 'header' ? headers[name] : @params[name],
|
29
|
+
parameter_model.schema.resolve(definitions),
|
30
|
+
definitions
|
31
|
+
)
|
34
32
|
end
|
35
|
-
end
|
36
33
|
|
37
|
-
|
38
|
-
|
39
|
-
|
34
|
+
# Request body
|
35
|
+
request_body_schema = operation.request_body&.resolve(definitions)
|
36
|
+
&.schema&.resolve(definitions)
|
37
|
+
if request_body_schema&.object?
|
38
|
+
request_body = JSON.wrap(
|
39
|
+
@params.except(*operation.parameters.keys),
|
40
|
+
request_body_schema,
|
41
|
+
definitions
|
42
|
+
)
|
43
|
+
@raw_attributes.merge!(request_body.raw_attributes)
|
44
|
+
@raw_additional_attributes = request_body.raw_additional_attributes
|
45
|
+
end
|
40
46
|
end
|
41
47
|
|
42
48
|
# Validates the request parameters. Returns true if the parameters are valid, false
|
@@ -44,11 +50,7 @@ module Jsapi
|
|
44
50
|
def validate(errors)
|
45
51
|
[
|
46
52
|
validate_attributes(errors),
|
47
|
-
!@strong || validate_parameters(
|
48
|
-
@params.except(:controller, :action, :format),
|
49
|
-
attributes,
|
50
|
-
errors
|
51
|
-
)
|
53
|
+
!@strong || validate_parameters(@params, attributes, errors)
|
52
54
|
].all?
|
53
55
|
end
|
54
56
|
|
@@ -2,8 +2,10 @@
|
|
2
2
|
|
3
3
|
module Jsapi
|
4
4
|
module Controller
|
5
|
-
# Raised by Methods#api_operation!
|
5
|
+
# Raised by Methods#api_operation! when the request parameters are invalid.
|
6
6
|
class ParametersInvalid < StandardError
|
7
|
+
|
8
|
+
# The parameters.
|
7
9
|
attr_reader :params
|
8
10
|
|
9
11
|
def initialize(params)
|
@@ -11,13 +13,14 @@ module Jsapi
|
|
11
13
|
super('')
|
12
14
|
end
|
13
15
|
|
14
|
-
#
|
16
|
+
# Returns the errors encountered.
|
17
|
+
def errors
|
18
|
+
@params.errors.errors
|
19
|
+
end
|
20
|
+
|
21
|
+
# Overrides <code>Exception#message</code> to lazily generate the error message.
|
15
22
|
def message
|
16
|
-
"#{
|
17
|
-
@params.errors.full_messages.map do |message|
|
18
|
-
message.delete_suffix('.')
|
19
|
-
end.join('. ')
|
20
|
-
}."
|
23
|
+
"#{@params.errors.full_messages.map { |m| m.delete_suffix('.') }.join('. ')}."
|
21
24
|
end
|
22
25
|
end
|
23
26
|
end
|
@@ -7,10 +7,23 @@ module Jsapi
|
|
7
7
|
|
8
8
|
# Creates a new instance to serialize +object+ according to +response+. References
|
9
9
|
# are resolved to API components in +definitions+.
|
10
|
-
|
10
|
+
#
|
11
|
+
# The +:omit+ option specifies on which conditions properties are omitted.
|
12
|
+
# Possible values are:
|
13
|
+
#
|
14
|
+
# - +:empty+ - All of the properties whose value is empty are omitted.
|
15
|
+
# - +:nil+ - All of the properties whose value is +nil+ are omitted.
|
16
|
+
#
|
17
|
+
# Raises an InvalidArgumentError when the value of +:omit+ is invalid.
|
18
|
+
def initialize(object, response, definitions, omit: nil)
|
19
|
+
if [:empty, :nil, nil].exclude?(omit)
|
20
|
+
raise InvalidArgumentError.new('omit', omit, valid_values: %i[empty nil])
|
21
|
+
end
|
22
|
+
|
11
23
|
@object = object
|
12
24
|
@response = response
|
13
25
|
@definitions = definitions
|
26
|
+
@omit = omit
|
14
27
|
end
|
15
28
|
|
16
29
|
def inspect # :nodoc:
|
@@ -32,7 +45,9 @@ module Jsapi
|
|
32
45
|
private
|
33
46
|
|
34
47
|
def serialize(object, schema, path = nil)
|
48
|
+
object = schema.default_value(@definitions, context: :response) if object.nil?
|
35
49
|
return if object.nil? && schema.nullable?
|
50
|
+
|
36
51
|
raise "#{path || 'response'} can't be nil" if object.nil?
|
37
52
|
|
38
53
|
case schema.type
|
@@ -68,32 +83,33 @@ module Jsapi
|
|
68
83
|
end
|
69
84
|
|
70
85
|
def serialize_object(object, schema, path)
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
if (discriminator = schema.discriminator)
|
75
|
-
discriminator_property = schema.properties[discriminator.property_name]
|
76
|
-
schema = discriminator.resolve(
|
77
|
-
object.public_send(discriminator_property.source || discriminator_property.name.underscore),
|
78
|
-
@definitions
|
79
|
-
)
|
80
|
-
end
|
86
|
+
schema = schema.resolve_schema(object, @definitions, context: :response)
|
87
|
+
properties = {}
|
88
|
+
|
81
89
|
# Serialize properties
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
90
|
+
schema.resolve_properties(@definitions, context: :response).each do |key, property|
|
91
|
+
property_schema = property.schema.resolve(@definitions)
|
92
|
+
property_value = property.reader.call(object)
|
93
|
+
property_value = property.default if property_value.nil?
|
94
|
+
|
95
|
+
next if ((@omit == :empty && property_value.try(:empty?)) ||
|
96
|
+
(@omit == :nil && property_value.nil?)) &&
|
97
|
+
property_schema.omittable?
|
98
|
+
|
99
|
+
properties[key] = serialize(
|
100
|
+
property_value,
|
101
|
+
property_schema,
|
86
102
|
path.nil? ? property.name : "#{path}.#{property.name}"
|
87
103
|
)
|
88
104
|
end
|
89
|
-
|
105
|
+
# Serialize additional properties
|
106
|
+
if (additional_properties = schema.additional_properties)
|
90
107
|
additional_properties_schema = additional_properties.schema.resolve(@definitions)
|
91
108
|
|
92
|
-
|
109
|
+
additional_properties.source.call(object)&.each do |key, value|
|
93
110
|
# Don't replace the property with the same key
|
94
111
|
next if properties.key?(key = key.to_s)
|
95
112
|
|
96
|
-
# Serialize the additional property
|
97
113
|
properties[key] = serialize(
|
98
114
|
value,
|
99
115
|
additional_properties_schema,
|
@@ -101,7 +117,8 @@ module Jsapi
|
|
101
117
|
)
|
102
118
|
end
|
103
119
|
end
|
104
|
-
properties
|
120
|
+
# Return properties if present, otherwise nil
|
121
|
+
properties if properties.present?
|
105
122
|
end
|
106
123
|
end
|
107
124
|
end
|
@@ -3,6 +3,14 @@
|
|
3
3
|
module Jsapi
|
4
4
|
module DSL
|
5
5
|
module ClassMethods
|
6
|
+
# Specifies the general default values for +type+.
|
7
|
+
#
|
8
|
+
# api_default 'array', read: [], write: []
|
9
|
+
#
|
10
|
+
def api_default(type, **keywords, &block)
|
11
|
+
api_definitions { default(type, **keywords, &block) }
|
12
|
+
end
|
13
|
+
|
6
14
|
# The API definitions of the current class.
|
7
15
|
def api_definitions(&block)
|
8
16
|
@api_definitions ||= Meta::Definitions.new(self)
|
@@ -30,24 +38,24 @@ module Jsapi
|
|
30
38
|
# end
|
31
39
|
#
|
32
40
|
# +name+ can be +nil+ if the controller handles one operation only.
|
33
|
-
def api_operation(name = nil, **
|
34
|
-
api_definitions { operation(name, **
|
41
|
+
def api_operation(name = nil, **keywords, &block)
|
42
|
+
api_definitions { operation(name, **keywords, &block) }
|
35
43
|
end
|
36
44
|
|
37
45
|
# Defines a reusable parameter.
|
38
46
|
#
|
39
47
|
# api_parameter 'foo', type: 'string'
|
40
48
|
#
|
41
|
-
def api_parameter(name, **
|
42
|
-
api_definitions { parameter(name, **
|
49
|
+
def api_parameter(name, **keywords, &block)
|
50
|
+
api_definitions { parameter(name, **keywords, &block) }
|
43
51
|
end
|
44
52
|
|
45
53
|
# Defines a reusable request body.
|
46
54
|
#
|
47
55
|
# api_request_body 'foo', type: 'string'
|
48
56
|
#
|
49
|
-
def api_request_body(name, **
|
50
|
-
api_definitions { request_body(name, **
|
57
|
+
def api_request_body(name, **keywords, &block)
|
58
|
+
api_definitions { request_body(name, **keywords, &block) }
|
51
59
|
end
|
52
60
|
|
53
61
|
# Specifies the HTTP status code of an error response rendered when an
|
@@ -64,8 +72,8 @@ module Jsapi
|
|
64
72
|
# api_response 'Foo', type: 'object' do
|
65
73
|
# property 'bar', type: 'string'
|
66
74
|
# end
|
67
|
-
def api_response(name, **
|
68
|
-
api_definitions { response(name, **
|
75
|
+
def api_response(name, **keywords, &block)
|
76
|
+
api_definitions { response(name, **keywords, &block) }
|
69
77
|
end
|
70
78
|
|
71
79
|
# Defines a reusable schema.
|
@@ -73,8 +81,8 @@ module Jsapi
|
|
73
81
|
# api_schema 'Foo' do
|
74
82
|
# property 'bar', type: 'string'
|
75
83
|
# end
|
76
|
-
def api_schema(name, **
|
77
|
-
api_definitions { schema(name, **
|
84
|
+
def api_schema(name, **keywords, &block)
|
85
|
+
api_definitions { schema(name, **keywords, &block) }
|
78
86
|
end
|
79
87
|
|
80
88
|
# Defines the root of an OpenAPI document.
|
@@ -5,6 +5,17 @@ module Jsapi
|
|
5
5
|
# Used to define top-level API components.
|
6
6
|
class Definitions < Node
|
7
7
|
|
8
|
+
# Specifies the general default values for +type+.
|
9
|
+
#
|
10
|
+
# default 'array', read: [], write: []
|
11
|
+
#
|
12
|
+
def default(type, **keywords, &block)
|
13
|
+
_define('default', type.inspect) do
|
14
|
+
default = _meta_model.add_default(type, keywords)
|
15
|
+
Node.new(default, &block) if block
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
8
19
|
# Includes API definitions from +klasses+.
|
9
20
|
def include(*klasses)
|
10
21
|
klasses.each do |klass|
|
@@ -0,0 +1,34 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Jsapi
|
4
|
+
module DSL
|
5
|
+
module OpenAPI
|
6
|
+
module Callbacks
|
7
|
+
# Defines an \OpenAPI callback or refers a reusable callback.
|
8
|
+
#
|
9
|
+
# # define a callback
|
10
|
+
# callback 'foo' do
|
11
|
+
# operation '{$request.query.foo}'
|
12
|
+
# end
|
13
|
+
#
|
14
|
+
# # refer a reusable callback
|
15
|
+
# callback ref: 'foo'
|
16
|
+
#
|
17
|
+
# Refers the reusable callback with the same name if neither any
|
18
|
+
# keywords nor a block is specified.
|
19
|
+
#
|
20
|
+
# callback 'foo'
|
21
|
+
#
|
22
|
+
def callback(name = nil, **keywords, &block)
|
23
|
+
_define('callback', name&.inspect) do
|
24
|
+
name = keywords[:ref] if name.nil?
|
25
|
+
keywords = { ref: name } unless keywords.any? || block
|
26
|
+
|
27
|
+
callback_model = _meta_model.add_callback(name, keywords)
|
28
|
+
_eval(callback_model, OpenAPI::Callback, &block)
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
@@ -0,0 +1,32 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Jsapi
|
4
|
+
module DSL
|
5
|
+
module OpenAPI
|
6
|
+
module Examples
|
7
|
+
# Adds an example.
|
8
|
+
#
|
9
|
+
# example 'foo', value: 'bar'
|
10
|
+
#
|
11
|
+
# example 'foo'
|
12
|
+
#
|
13
|
+
# The default name is <code>'default'</code>.
|
14
|
+
def example(name_or_value = nil, **keywords, &block)
|
15
|
+
_define('example', name_or_value&.inspect) do
|
16
|
+
if keywords.any? || block
|
17
|
+
# example 'foo', value: 'bar', ...
|
18
|
+
name = name_or_value
|
19
|
+
else
|
20
|
+
# example 'foo'
|
21
|
+
name = nil
|
22
|
+
keywords = { value: name_or_value }
|
23
|
+
end
|
24
|
+
|
25
|
+
example = _meta_model.add_example(name, keywords)
|
26
|
+
Node.new(example, &block) if block
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
data/lib/jsapi/dsl/openapi.rb
CHANGED
data/lib/jsapi/dsl/operation.rb
CHANGED
data/lib/jsapi/dsl/parameter.rb
CHANGED
data/lib/jsapi/dsl/response.rb
CHANGED
data/lib/jsapi/dsl.rb
CHANGED
@@ -1,15 +1,13 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require_relative 'dsl/callbacks'
|
4
|
-
require_relative 'dsl/examples'
|
5
3
|
require_relative 'dsl/error'
|
6
4
|
require_relative 'dsl/node'
|
5
|
+
require_relative 'dsl/openapi'
|
7
6
|
require_relative 'dsl/schema'
|
8
7
|
require_relative 'dsl/parameter'
|
9
8
|
require_relative 'dsl/request_body'
|
10
9
|
require_relative 'dsl/response'
|
11
10
|
require_relative 'dsl/operation'
|
12
|
-
require_relative 'dsl/openapi'
|
13
11
|
require_relative 'dsl/definitions'
|
14
12
|
require_relative 'dsl/class_methods'
|
15
13
|
|
@@ -0,0 +1,17 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Jsapi
|
4
|
+
module InvalidValueHelper
|
5
|
+
def build_message(name, value, valid_values)
|
6
|
+
case valid_values.count
|
7
|
+
when 0
|
8
|
+
"#{name} must not be #{value.inspect}"
|
9
|
+
when 1
|
10
|
+
"#{name} must be #{valid_values.first.inspect}, is #{value.inspect}"
|
11
|
+
else
|
12
|
+
"#{name} must be one of #{valid_values[0..-2].map(&:inspect).join(', ')} " \
|
13
|
+
"or #{valid_values.last.inspect}, is #{value.inspect}"
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
@@ -0,0 +1,12 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Jsapi
|
4
|
+
# Raised when an argument isn't contained in the list of valid values.
|
5
|
+
class InvalidArgumentError < ArgumentError
|
6
|
+
include InvalidValueHelper
|
7
|
+
|
8
|
+
def initialize(name, value, valid_values: [])
|
9
|
+
super(build_message(name, value, valid_values))
|
10
|
+
end
|
11
|
+
end
|
12
|
+
end
|
@@ -0,0 +1,12 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Jsapi
|
4
|
+
# Raised when a value isn't contained in the list of valid values.
|
5
|
+
class InvalidValueError < RuntimeError
|
6
|
+
include InvalidValueHelper
|
7
|
+
|
8
|
+
def initialize(name, value, valid_values: [])
|
9
|
+
super(build_message(name, value, valid_values))
|
10
|
+
end
|
11
|
+
end
|
12
|
+
end
|
data/lib/jsapi/json/object.rb
CHANGED
@@ -6,18 +6,24 @@ module Jsapi
|
|
6
6
|
class Object < Value
|
7
7
|
include Model::Nestable
|
8
8
|
|
9
|
-
attr_reader :raw_attributes
|
9
|
+
attr_reader :raw_additional_attributes, :raw_attributes
|
10
10
|
|
11
11
|
def initialize(attributes, schema, definitions)
|
12
|
-
|
13
|
-
|
14
|
-
|
12
|
+
schema = schema.resolve_schema(attributes, definitions, context: :request)
|
13
|
+
properties = schema.resolve_properties(definitions, context: :request)
|
14
|
+
|
15
|
+
@raw_attributes = properties.transform_values do |property|
|
16
|
+
JSON.wrap(attributes[property.name], property.schema, definitions)
|
15
17
|
end
|
16
|
-
|
17
|
-
@
|
18
|
-
schema.
|
19
|
-
|
20
|
-
|
18
|
+
|
19
|
+
@raw_additional_attributes =
|
20
|
+
if (additional_properties = schema.additional_properties)
|
21
|
+
additional_properties_schema = additional_properties.schema.resolve(definitions)
|
22
|
+
|
23
|
+
attributes.except(*properties.keys).transform_values do |value|
|
24
|
+
JSON.wrap(value, additional_properties_schema, definitions)
|
25
|
+
end
|
26
|
+
end || {}
|
21
27
|
|
22
28
|
super(schema)
|
23
29
|
end
|
@@ -27,11 +33,6 @@ module Jsapi
|
|
27
33
|
@raw_attributes.values.all?(&:empty?)
|
28
34
|
end
|
29
35
|
|
30
|
-
def inspect # :nodoc:
|
31
|
-
"#<#{self.class.name} " \
|
32
|
-
"#{@raw_attributes.map { |k, v| "#{k}: #{v.inspect}" }.join(', ')}>"
|
33
|
-
end
|
34
|
-
|
35
36
|
# Returns a model to read attributes by.
|
36
37
|
def model
|
37
38
|
@model ||= (schema.model || Model::Base).new(self)
|