openapi3_parser 0.2.0 → 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.
- checksums.yaml +4 -4
- data/.travis.yml +10 -1
- data/CHANGELOG.md +5 -0
- data/README.md +13 -0
- data/TODO.md +11 -8
- data/lib/openapi3_parser.rb +16 -28
- data/lib/openapi3_parser/context.rb +92 -34
- data/lib/openapi3_parser/context/location.rb +37 -0
- data/lib/openapi3_parser/context/pointer.rb +34 -0
- data/lib/openapi3_parser/document.rb +115 -15
- data/lib/openapi3_parser/document/reference_register.rb +50 -0
- data/lib/openapi3_parser/error.rb +27 -1
- data/lib/openapi3_parser/node/object.rb +26 -1
- data/lib/openapi3_parser/node_factories/array.rb +15 -14
- data/lib/openapi3_parser/node_factories/callback.rb +2 -1
- data/lib/openapi3_parser/node_factories/link.rb +1 -1
- data/lib/openapi3_parser/node_factories/map.rb +13 -11
- data/lib/openapi3_parser/node_factories/openapi.rb +2 -0
- data/lib/openapi3_parser/node_factories/path_item.rb +13 -18
- data/lib/openapi3_parser/node_factories/paths.rb +2 -1
- data/lib/openapi3_parser/node_factories/reference.rb +7 -9
- data/lib/openapi3_parser/node_factories/responses.rb +4 -2
- data/lib/openapi3_parser/node_factories/security_requirement.rb +2 -1
- data/lib/openapi3_parser/node_factory.rb +39 -30
- data/lib/openapi3_parser/node_factory/fields/reference.rb +44 -0
- data/lib/openapi3_parser/node_factory/map.rb +5 -5
- data/lib/openapi3_parser/node_factory/object.rb +6 -5
- data/lib/openapi3_parser/node_factory/object/node_builder.rb +12 -11
- data/lib/openapi3_parser/node_factory/object/validator.rb +25 -14
- data/lib/openapi3_parser/nodes/components.rb +9 -11
- data/lib/openapi3_parser/nodes/discriminator.rb +1 -1
- data/lib/openapi3_parser/nodes/encoding.rb +1 -1
- data/lib/openapi3_parser/nodes/link.rb +1 -1
- data/lib/openapi3_parser/nodes/media_type.rb +2 -2
- data/lib/openapi3_parser/nodes/oauth_flow.rb +1 -1
- data/lib/openapi3_parser/nodes/openapi.rb +3 -4
- data/lib/openapi3_parser/nodes/operation.rb +5 -8
- data/lib/openapi3_parser/nodes/parameter/parameter_like.rb +2 -2
- data/lib/openapi3_parser/nodes/path_item.rb +2 -3
- data/lib/openapi3_parser/nodes/request_body.rb +1 -1
- data/lib/openapi3_parser/nodes/response.rb +3 -3
- data/lib/openapi3_parser/nodes/schema.rb +6 -7
- data/lib/openapi3_parser/nodes/server.rb +1 -2
- data/lib/openapi3_parser/nodes/server_variable.rb +1 -1
- data/lib/openapi3_parser/source.rb +136 -0
- data/lib/openapi3_parser/source/reference.rb +68 -0
- data/lib/openapi3_parser/source/reference_resolver.rb +81 -0
- data/lib/openapi3_parser/source_input.rb +71 -0
- data/lib/openapi3_parser/source_input/file.rb +102 -0
- data/lib/openapi3_parser/source_input/raw.rb +90 -0
- data/lib/openapi3_parser/source_input/resolve_next.rb +62 -0
- data/lib/openapi3_parser/source_input/string_parser.rb +43 -0
- data/lib/openapi3_parser/source_input/url.rb +123 -0
- data/lib/openapi3_parser/validation/error.rb +36 -3
- data/lib/openapi3_parser/validation/error_collection.rb +57 -15
- data/lib/openapi3_parser/validators/reference.rb +40 -0
- data/lib/openapi3_parser/version.rb +1 -1
- data/openapi3_parser.gemspec +10 -5
- metadata +34 -20
- data/lib/openapi3_parser/fields/map.rb +0 -83
- data/lib/openapi3_parser/node.rb +0 -115
@@ -0,0 +1,44 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "openapi3_parser/node_factory"
|
4
|
+
require "openapi3_parser/validators/reference"
|
5
|
+
|
6
|
+
module Openapi3Parser
|
7
|
+
module NodeFactory
|
8
|
+
module Fields
|
9
|
+
class Reference
|
10
|
+
include NodeFactory
|
11
|
+
input_type ::String
|
12
|
+
|
13
|
+
def initialize(context, factory)
|
14
|
+
super(context)
|
15
|
+
@factory = factory
|
16
|
+
@given_reference = context.input
|
17
|
+
@reference_resolver = create_reference_resolver
|
18
|
+
end
|
19
|
+
|
20
|
+
private
|
21
|
+
|
22
|
+
attr_reader :given_reference, :factory, :reference_resolver
|
23
|
+
|
24
|
+
def validate(_, _)
|
25
|
+
return reference_validator.errors unless reference_validator.valid?
|
26
|
+
reference_resolver&.errors
|
27
|
+
end
|
28
|
+
|
29
|
+
def build_node(_)
|
30
|
+
reference_resolver&.node
|
31
|
+
end
|
32
|
+
|
33
|
+
def reference_validator
|
34
|
+
@reference_validator ||= Validators::Reference.new(given_reference)
|
35
|
+
end
|
36
|
+
|
37
|
+
def create_reference_resolver
|
38
|
+
return unless given_reference
|
39
|
+
context.register_reference(given_reference, factory)
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
@@ -1,6 +1,7 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
require "openapi3_parser/node_factory"
|
4
|
+
require "openapi3_parser/validation/error_collection"
|
4
5
|
|
5
6
|
module Openapi3Parser
|
6
7
|
module NodeFactory
|
@@ -23,11 +24,10 @@ module Openapi3Parser
|
|
23
24
|
build_map(data, context)
|
24
25
|
end
|
25
26
|
|
26
|
-
def validate_input
|
27
|
-
super
|
28
|
-
|
29
|
-
|
30
|
-
error_collection.merge(value.errors)
|
27
|
+
def validate_input
|
28
|
+
processed_input.each_value.inject(super) do |memo, value|
|
29
|
+
errors = value.respond_to?(:errors) ? value.errors : []
|
30
|
+
Validation::ErrorCollection.combine(memo, errors)
|
31
31
|
end
|
32
32
|
end
|
33
33
|
|
@@ -1,9 +1,11 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
+
require "openapi3_parser/context"
|
3
4
|
require "openapi3_parser/node_factory"
|
4
5
|
require "openapi3_parser/node_factory/field_config"
|
5
6
|
require "openapi3_parser/node_factory/object/node_builder"
|
6
7
|
require "openapi3_parser/node_factory/object/validator"
|
8
|
+
require "openapi3_parser/validation/error_collection"
|
7
9
|
|
8
10
|
module Openapi3Parser
|
9
11
|
module NodeFactory
|
@@ -54,15 +56,14 @@ module Openapi3Parser
|
|
54
56
|
def process_input(input)
|
55
57
|
field_configs.each_with_object(input.dup) do |(field, config), memo|
|
56
58
|
next unless config.factory?
|
57
|
-
next_context =
|
59
|
+
next_context = Context.next_field(context, field)
|
58
60
|
memo[field] = config.initialize_factory(next_context, self)
|
59
61
|
end
|
60
62
|
end
|
61
63
|
|
62
|
-
def validate_input
|
63
|
-
|
64
|
-
|
65
|
-
error_collection.tap { |ec| ec.append(*validator.errors) }
|
64
|
+
def validate_input
|
65
|
+
validator = Validator.new(processed_input, self)
|
66
|
+
Validation::ErrorCollection.combine(super, validator.errors)
|
66
67
|
end
|
67
68
|
|
68
69
|
def build_node(input)
|
@@ -1,7 +1,8 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require "openapi3_parser/
|
3
|
+
require "openapi3_parser/context"
|
4
4
|
require "openapi3_parser/error"
|
5
|
+
require "openapi3_parser/node_factory/object/validator"
|
5
6
|
|
6
7
|
module Openapi3Parser
|
7
8
|
module NodeFactory
|
@@ -32,16 +33,16 @@ module Openapi3Parser
|
|
32
33
|
def check_required_fields
|
33
34
|
fields = Validator.missing_required_fields(input, factory)
|
34
35
|
return if fields.empty?
|
35
|
-
raise Openapi3Parser::Error,
|
36
|
+
raise Openapi3Parser::Error::MissingFields,
|
36
37
|
"Missing required fields for "\
|
37
|
-
"#{context.
|
38
|
+
"#{context.location_summary}: #{fields.join(', ')}"
|
38
39
|
end
|
39
40
|
|
40
41
|
def check_unexpected_fields
|
41
42
|
fields = Validator.unexpected_fields(input, factory)
|
42
43
|
return if fields.empty?
|
43
|
-
raise Openapi3Parser::Error,
|
44
|
-
"Unexpected fields for #{context.
|
44
|
+
raise Openapi3Parser::Error::UnexpectedFields,
|
45
|
+
"Unexpected fields for #{context.location_summary}: "\
|
45
46
|
"#{fields.join(', ')}"
|
46
47
|
end
|
47
48
|
|
@@ -53,23 +54,23 @@ module Openapi3Parser
|
|
53
54
|
end
|
54
55
|
|
55
56
|
def check_type_error(name, field_config)
|
56
|
-
field_context =
|
57
|
+
field_context = Context.next_field(context, name)
|
57
58
|
input = context.input.nil? ? nil : context.input[name]
|
58
59
|
error = field_config.input_type_error(input, factory)
|
59
60
|
|
60
61
|
return unless error
|
61
|
-
raise Openapi3Parser::Error,
|
62
|
+
raise Openapi3Parser::Error::InvalidType,
|
62
63
|
"Invalid type for "\
|
63
|
-
"#{field_context.
|
64
|
+
"#{field_context.location_summary}: #{error}"
|
64
65
|
end
|
65
66
|
|
66
67
|
def check_validation_errors(name, field_config)
|
67
|
-
field_context =
|
68
|
+
field_context = Context.next_field(context, name)
|
68
69
|
errors = field_config.validation_errors(field_context.input, factory)
|
69
70
|
|
70
71
|
return unless errors.any?
|
71
|
-
raise Openapi3Parser::Error,
|
72
|
-
"Invalid field for #{field_context.
|
72
|
+
raise Openapi3Parser::Error::InvalidData,
|
73
|
+
"Invalid field for #{field_context.location_summary}: "\
|
73
74
|
"#{errors.join(', ')}"
|
74
75
|
end
|
75
76
|
|
@@ -1,5 +1,6 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
+
require "openapi3_parser/context"
|
3
4
|
require "openapi3_parser/node_factory"
|
4
5
|
require "openapi3_parser/validation/error"
|
5
6
|
|
@@ -10,7 +11,9 @@ module Openapi3Parser
|
|
10
11
|
def self.missing_required_fields(input, factory)
|
11
12
|
configs = factory.field_configs
|
12
13
|
configs.each_with_object([]) do |(name, field_config), memo|
|
13
|
-
|
14
|
+
f = input[name]
|
15
|
+
is_nil = f.respond_to?(:nil_input?) ? f.nil_input? : f.nil?
|
16
|
+
memo << name if field_config.required?(factory) && is_nil
|
14
17
|
end
|
15
18
|
end
|
16
19
|
|
@@ -44,12 +47,17 @@ module Openapi3Parser
|
|
44
47
|
factory.context
|
45
48
|
end
|
46
49
|
|
50
|
+
def raw_input
|
51
|
+
context.input
|
52
|
+
end
|
53
|
+
|
47
54
|
def missing_required_fields_error
|
48
55
|
fields = self.class.missing_required_fields(input, factory)
|
49
56
|
return unless fields.any?
|
50
57
|
Validation::Error.new(
|
51
|
-
|
52
|
-
|
58
|
+
"Missing required fields: #{fields.join(', ')}",
|
59
|
+
context,
|
60
|
+
factory.class
|
53
61
|
)
|
54
62
|
end
|
55
63
|
|
@@ -57,42 +65,45 @@ module Openapi3Parser
|
|
57
65
|
fields = self.class.unexpected_fields(input, factory)
|
58
66
|
return unless fields.any?
|
59
67
|
Validation::Error.new(
|
60
|
-
|
61
|
-
|
68
|
+
"Unexpected fields: #{fields.join(', ')}",
|
69
|
+
context,
|
70
|
+
factory.class
|
62
71
|
)
|
63
72
|
end
|
64
73
|
|
65
74
|
def invalid_field_errors
|
66
75
|
factory.field_configs.inject([]) do |memo, (name, field_config)|
|
67
|
-
memo + field_errors(name, field_config)
|
76
|
+
memo + Array(field_errors(name, field_config))
|
68
77
|
end
|
69
78
|
end
|
70
79
|
|
71
80
|
def field_errors(name, field_config)
|
72
81
|
field = input[name]
|
73
|
-
return
|
82
|
+
return if field.nil?
|
74
83
|
return field.errors.to_a if field.respond_to?(:errors)
|
75
84
|
type_error = build_type_error(name, field_config)
|
76
|
-
return
|
85
|
+
return type_error if type_error
|
77
86
|
build_validation_errors(name, field_config)
|
78
87
|
end
|
79
88
|
|
80
89
|
def build_type_error(name, field_config)
|
81
|
-
type_error = field_config.input_type_error(
|
90
|
+
type_error = field_config.input_type_error(raw_input[name], factory)
|
82
91
|
return unless type_error
|
83
92
|
Validation::Error.new(
|
84
|
-
|
85
|
-
|
93
|
+
"Invalid type: #{type_error}",
|
94
|
+
Context.next_field(context, name),
|
95
|
+
factory.class
|
86
96
|
)
|
87
97
|
end
|
88
98
|
|
89
99
|
def build_validation_errors(name, field_config)
|
90
100
|
field_config.validation_errors(
|
91
|
-
|
101
|
+
raw_input[name], factory
|
92
102
|
).map do |error|
|
93
103
|
Validation::Error.new(
|
94
|
-
|
95
|
-
|
104
|
+
"Invalid field: #{error}",
|
105
|
+
Context.next_field(context, name),
|
106
|
+
factory.class
|
96
107
|
)
|
97
108
|
end
|
98
109
|
end
|
@@ -8,49 +8,47 @@ module Openapi3Parser
|
|
8
8
|
class Components
|
9
9
|
include Node::Object
|
10
10
|
|
11
|
-
# @return [Map
|
11
|
+
# @return [Map<String, Schema>]
|
12
12
|
def schemas
|
13
13
|
node_data["schemas"]
|
14
14
|
end
|
15
15
|
|
16
|
-
# @return [Map
|
16
|
+
# @return [Map<String, Response>]
|
17
17
|
def responses
|
18
18
|
node_data["responses"]
|
19
19
|
end
|
20
20
|
|
21
|
-
# @return [Map
|
21
|
+
# @return [Map<String, Parameter>]
|
22
22
|
def parameters
|
23
23
|
node_data["parameters"]
|
24
24
|
end
|
25
25
|
|
26
|
-
# @return [Map
|
26
|
+
# @return [Map<String, Example>]
|
27
27
|
def examples
|
28
28
|
node_data["examples"]
|
29
29
|
end
|
30
30
|
|
31
|
-
# @return [Map
|
32
|
-
# objects
|
31
|
+
# @return [Map<String, RequestBody>]
|
33
32
|
def request_bodies
|
34
33
|
node_data["requestBodies"]
|
35
34
|
end
|
36
35
|
|
37
|
-
# @return [Map
|
36
|
+
# @return [Map<String, Header>]
|
38
37
|
def headers
|
39
38
|
node_data["headers"]
|
40
39
|
end
|
41
40
|
|
42
|
-
# @return [Map
|
43
|
-
# objects
|
41
|
+
# @return [Map<String, SecurityScheme>]
|
44
42
|
def security_schemes
|
45
43
|
node_data["securitySchemes"]
|
46
44
|
end
|
47
45
|
|
48
|
-
# @return [Map
|
46
|
+
# @return [Map<String, Link>]
|
49
47
|
def links
|
50
48
|
node_data["links"]
|
51
49
|
end
|
52
50
|
|
53
|
-
# @return [Map
|
51
|
+
# @return [Map<String, Callback>]
|
54
52
|
def callbacks
|
55
53
|
node_data["callbacks"]
|
56
54
|
end
|
@@ -18,12 +18,12 @@ module Openapi3Parser
|
|
18
18
|
node_data["example"]
|
19
19
|
end
|
20
20
|
|
21
|
-
# @return [Map
|
21
|
+
# @return [Map<String, Example>]
|
22
22
|
def examples
|
23
23
|
node_data["examples"]
|
24
24
|
end
|
25
25
|
|
26
|
-
# @return [Map
|
26
|
+
# @return [Map<String, Encoding>]
|
27
27
|
def encoding
|
28
28
|
node_data["encoding"]
|
29
29
|
end
|
@@ -20,7 +20,7 @@ module Openapi3Parser
|
|
20
20
|
node_data["info"]
|
21
21
|
end
|
22
22
|
|
23
|
-
# @return [Nodes::Array
|
23
|
+
# @return [Nodes::Array<Server>]
|
24
24
|
def servers
|
25
25
|
node_data["servers"]
|
26
26
|
end
|
@@ -35,13 +35,12 @@ module Openapi3Parser
|
|
35
35
|
node_data["components"]
|
36
36
|
end
|
37
37
|
|
38
|
-
# @return [Nodes::Array]
|
39
|
-
# {SecurityRequirement}[./SecurityRequirement.html] objects
|
38
|
+
# @return [Nodes::Array<SecurityRequirement>]
|
40
39
|
def security
|
41
40
|
node_data["security"]
|
42
41
|
end
|
43
42
|
|
44
|
-
# @return [Nodes::Array
|
43
|
+
# @return [Nodes::Array<Tag>]
|
45
44
|
def tags
|
46
45
|
node_data["tags"]
|
47
46
|
end
|
@@ -8,7 +8,7 @@ module Openapi3Parser
|
|
8
8
|
class Operation
|
9
9
|
include Node::Object
|
10
10
|
|
11
|
-
# @return [Nodes::Array]
|
11
|
+
# @return [Nodes::Array<String>]
|
12
12
|
def tags
|
13
13
|
node_data["tags"]
|
14
14
|
end
|
@@ -33,8 +33,7 @@ module Openapi3Parser
|
|
33
33
|
node_data["operationId"]
|
34
34
|
end
|
35
35
|
|
36
|
-
# @return [Nodes::Array
|
37
|
-
# objects
|
36
|
+
# @return [Nodes::Array<Parameter>]
|
38
37
|
def parameters
|
39
38
|
node_data["parameters"]
|
40
39
|
end
|
@@ -49,8 +48,7 @@ module Openapi3Parser
|
|
49
48
|
node_data["responses"]
|
50
49
|
end
|
51
50
|
|
52
|
-
# @return [Map
|
53
|
-
# objects
|
51
|
+
# @return [Map<String, Callback>]
|
54
52
|
def callbacks
|
55
53
|
node_data["callbacks"]
|
56
54
|
end
|
@@ -60,13 +58,12 @@ module Openapi3Parser
|
|
60
58
|
node_data["deprecated"]
|
61
59
|
end
|
62
60
|
|
63
|
-
# @return [Nodes::Array]
|
64
|
-
# {SecurityRequirement}[./SecurityRequirement.html] objects
|
61
|
+
# @return [Nodes::Array<SecurityRequirement>]
|
65
62
|
def security
|
66
63
|
node_data["security"]
|
67
64
|
end
|
68
65
|
|
69
|
-
# @return [Nodes::Array
|
66
|
+
# @return [Nodes::Array<Server>]
|
70
67
|
def servers
|
71
68
|
node_data["servers"]
|
72
69
|
end
|
@@ -52,12 +52,12 @@ module Openapi3Parser
|
|
52
52
|
node_data["example"]
|
53
53
|
end
|
54
54
|
|
55
|
-
# @return [Map
|
55
|
+
# @return [Map<String, Example>]
|
56
56
|
def examples
|
57
57
|
node_data["examples"]
|
58
58
|
end
|
59
59
|
|
60
|
-
# @return [Map
|
60
|
+
# @return [Map<String, MediaType>]
|
61
61
|
def content
|
62
62
|
node_data["content"]
|
63
63
|
end
|