openapi3_parser 0.5.2 → 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/.ruby-version +1 -1
- data/.travis.yml +3 -3
- data/CHANGELOG.md +7 -1
- data/README.md +102 -15
- data/lib/openapi3_parser/document.rb +14 -14
- data/lib/openapi3_parser/document/reference_registry.rb +72 -0
- data/lib/openapi3_parser/node/array.rb +10 -2
- data/lib/openapi3_parser/node/components.rb +9 -9
- data/lib/openapi3_parser/node/contact.rb +3 -3
- data/lib/openapi3_parser/node/context.rb +129 -0
- data/lib/openapi3_parser/node/discriminator.rb +2 -2
- data/lib/openapi3_parser/node/encoding.rb +5 -5
- data/lib/openapi3_parser/node/example.rb +4 -4
- data/lib/openapi3_parser/node/external_documentation.rb +2 -2
- data/lib/openapi3_parser/node/info.rb +6 -6
- data/lib/openapi3_parser/node/license.rb +2 -2
- data/lib/openapi3_parser/node/link.rb +6 -6
- data/lib/openapi3_parser/node/map.rb +8 -4
- data/lib/openapi3_parser/node/media_type.rb +5 -5
- data/lib/openapi3_parser/node/oauth_flow.rb +4 -4
- data/lib/openapi3_parser/node/oauth_flows.rb +4 -4
- data/lib/openapi3_parser/node/object.rb +8 -4
- data/lib/openapi3_parser/node/openapi.rb +8 -8
- data/lib/openapi3_parser/node/operation.rb +12 -12
- data/lib/openapi3_parser/node/parameter.rb +2 -2
- data/lib/openapi3_parser/node/parameter_like.rb +11 -11
- data/lib/openapi3_parser/node/path_item.rb +12 -12
- data/lib/openapi3_parser/node/placeholder.rb +34 -0
- data/lib/openapi3_parser/node/request_body.rb +3 -3
- data/lib/openapi3_parser/node/response.rb +4 -4
- data/lib/openapi3_parser/node/responses.rb +1 -1
- data/lib/openapi3_parser/node/schema.rb +36 -36
- data/lib/openapi3_parser/node/security_scheme.rb +8 -8
- data/lib/openapi3_parser/node/server.rb +3 -3
- data/lib/openapi3_parser/node/server_variable.rb +3 -3
- data/lib/openapi3_parser/node/tag.rb +3 -3
- data/lib/openapi3_parser/node/xml.rb +5 -5
- data/lib/openapi3_parser/node_factory/array.rb +15 -13
- data/lib/openapi3_parser/node_factory/callback.rb +2 -2
- data/lib/openapi3_parser/node_factory/context.rb +111 -0
- data/lib/openapi3_parser/node_factory/field.rb +5 -7
- data/lib/openapi3_parser/node_factory/fields/reference.rb +43 -24
- data/lib/openapi3_parser/node_factory/link.rb +1 -1
- data/lib/openapi3_parser/node_factory/map.rb +14 -12
- data/lib/openapi3_parser/node_factory/object.rb +9 -5
- data/lib/openapi3_parser/node_factory/object_factory/node_builder.rb +21 -28
- data/lib/openapi3_parser/node_factory/optional_reference.rb +4 -0
- data/lib/openapi3_parser/node_factory/parameter_like.rb +0 -2
- data/lib/openapi3_parser/node_factory/path_item.rb +7 -4
- data/lib/openapi3_parser/node_factory/paths.rb +2 -2
- data/lib/openapi3_parser/node_factory/reference.rb +17 -10
- data/lib/openapi3_parser/node_factory/responses.rb +2 -2
- data/lib/openapi3_parser/node_factory/security_requirement.rb +2 -2
- data/lib/openapi3_parser/source.rb +27 -24
- data/lib/openapi3_parser/{context → source}/location.rb +13 -1
- data/lib/openapi3_parser/{context → source}/pointer.rb +2 -2
- data/lib/openapi3_parser/source/resolved_reference.rb +67 -0
- data/lib/openapi3_parser/validators/duplicate_parameters.rb +8 -4
- data/lib/openapi3_parser/validators/reference.rb +3 -3
- data/lib/openapi3_parser/version.rb +1 -1
- data/openapi3_parser.gemspec +1 -1
- metadata +11 -10
- data/lib/openapi3_parser/context.rb +0 -162
- data/lib/openapi3_parser/document/reference_register.rb +0 -48
- data/lib/openapi3_parser/node_factory/recursive_pointer.rb +0 -17
- data/lib/openapi3_parser/source/reference_resolver.rb +0 -82
@@ -8,12 +8,12 @@ module Openapi3Parser
|
|
8
8
|
class SecurityScheme < Node::Object
|
9
9
|
# @return [String, nil]
|
10
10
|
def type
|
11
|
-
|
11
|
+
self["type"]
|
12
12
|
end
|
13
13
|
|
14
14
|
# @return [String, nil]
|
15
15
|
def description
|
16
|
-
|
16
|
+
self["description"]
|
17
17
|
end
|
18
18
|
|
19
19
|
# @return [String, nil]
|
@@ -23,32 +23,32 @@ module Openapi3Parser
|
|
23
23
|
|
24
24
|
# @return [String, nil]
|
25
25
|
def name
|
26
|
-
|
26
|
+
self["name"]
|
27
27
|
end
|
28
28
|
|
29
29
|
# @return [String, nil]
|
30
30
|
def in
|
31
|
-
|
31
|
+
self["in"]
|
32
32
|
end
|
33
33
|
|
34
34
|
# @return [String, nil]
|
35
35
|
def scheme
|
36
|
-
|
36
|
+
self["scheme"]
|
37
37
|
end
|
38
38
|
|
39
39
|
# @return [String, nil]
|
40
40
|
def bearer_format
|
41
|
-
|
41
|
+
self["bearerFormat"]
|
42
42
|
end
|
43
43
|
|
44
44
|
# @return [OauthFlows, nil]
|
45
45
|
def flows
|
46
|
-
|
46
|
+
self["flows"]
|
47
47
|
end
|
48
48
|
|
49
49
|
# @return [String, nil]
|
50
50
|
def open_id_connect_url
|
51
|
-
|
51
|
+
self["openIdConnectUrl"]
|
52
52
|
end
|
53
53
|
end
|
54
54
|
end
|
@@ -8,12 +8,12 @@ module Openapi3Parser
|
|
8
8
|
class Server < Node::Object
|
9
9
|
# @return [String]
|
10
10
|
def url
|
11
|
-
|
11
|
+
self["url"]
|
12
12
|
end
|
13
13
|
|
14
14
|
# @return [String, nil]
|
15
15
|
def description
|
16
|
-
|
16
|
+
self["description"]
|
17
17
|
end
|
18
18
|
|
19
19
|
# @return [String, nil]
|
@@ -23,7 +23,7 @@ module Openapi3Parser
|
|
23
23
|
|
24
24
|
# @return [Map<String, ServerVariable>]
|
25
25
|
def variables
|
26
|
-
|
26
|
+
self["variables"]
|
27
27
|
end
|
28
28
|
end
|
29
29
|
end
|
@@ -8,17 +8,17 @@ module Openapi3Parser
|
|
8
8
|
class ServerVariable < Node::Object
|
9
9
|
# @return [Node::Array<String>, nil]
|
10
10
|
def enum
|
11
|
-
|
11
|
+
self["enum"]
|
12
12
|
end
|
13
13
|
|
14
14
|
# @return [String]
|
15
15
|
def default
|
16
|
-
|
16
|
+
self["default"]
|
17
17
|
end
|
18
18
|
|
19
19
|
# @return [String, nil]
|
20
20
|
def description
|
21
|
-
|
21
|
+
self["description"]
|
22
22
|
end
|
23
23
|
|
24
24
|
# @return [String, nil]
|
@@ -8,12 +8,12 @@ module Openapi3Parser
|
|
8
8
|
class Tag < Node::Object
|
9
9
|
# @return [String]
|
10
10
|
def name
|
11
|
-
|
11
|
+
self["name"]
|
12
12
|
end
|
13
13
|
|
14
14
|
# @return [String, nil]
|
15
15
|
def description
|
16
|
-
|
16
|
+
self["description"]
|
17
17
|
end
|
18
18
|
|
19
19
|
# @return [String, nil]
|
@@ -23,7 +23,7 @@ module Openapi3Parser
|
|
23
23
|
|
24
24
|
# @return [ExternalDocumentation, nil]
|
25
25
|
def external_docs
|
26
|
-
|
26
|
+
self["externalDocs"]
|
27
27
|
end
|
28
28
|
end
|
29
29
|
end
|
@@ -8,27 +8,27 @@ module Openapi3Parser
|
|
8
8
|
class Xml < Node::Object
|
9
9
|
# @return [String, nil]
|
10
10
|
def name
|
11
|
-
|
11
|
+
self["name"]
|
12
12
|
end
|
13
13
|
|
14
14
|
# @return [String, nil]
|
15
15
|
def namespace
|
16
|
-
|
16
|
+
self["namespace"]
|
17
17
|
end
|
18
18
|
|
19
19
|
# @return [String, nil]
|
20
20
|
def prefix
|
21
|
-
|
21
|
+
self["prefix"]
|
22
22
|
end
|
23
23
|
|
24
24
|
# @return [Boolean]
|
25
25
|
def attribute?
|
26
|
-
|
26
|
+
self["attribute"]
|
27
27
|
end
|
28
28
|
|
29
29
|
# @return [Boolean]
|
30
30
|
def wrapped?
|
31
|
-
|
31
|
+
self["wrapped"]
|
32
32
|
end
|
33
33
|
end
|
34
34
|
end
|
@@ -41,11 +41,9 @@ module Openapi3Parser
|
|
41
41
|
@errors ||= ValidNodeBuilder.errors(self)
|
42
42
|
end
|
43
43
|
|
44
|
-
def node
|
45
|
-
|
46
|
-
|
47
|
-
data.nil? ? nil : build_node(data)
|
48
|
-
end
|
44
|
+
def node(node_context)
|
45
|
+
data = ValidNodeBuilder.data(self, node_context)
|
46
|
+
data.nil? ? nil : build_node(data, node_context)
|
49
47
|
end
|
50
48
|
|
51
49
|
def inspect
|
@@ -78,8 +76,8 @@ module Openapi3Parser
|
|
78
76
|
end
|
79
77
|
end
|
80
78
|
|
81
|
-
def build_node(data)
|
82
|
-
Node::Array.new(data,
|
79
|
+
def build_node(data, node_context)
|
80
|
+
Node::Array.new(data, node_context) if data
|
83
81
|
end
|
84
82
|
|
85
83
|
def build_resolved_input
|
@@ -95,8 +93,8 @@ module Openapi3Parser
|
|
95
93
|
new(factory).errors
|
96
94
|
end
|
97
95
|
|
98
|
-
def self.data(factory)
|
99
|
-
new(factory).data
|
96
|
+
def self.data(factory, parent_context)
|
97
|
+
new(factory).data(parent_context)
|
100
98
|
end
|
101
99
|
|
102
100
|
def initialize(factory)
|
@@ -112,15 +110,19 @@ module Openapi3Parser
|
|
112
110
|
validatable.collection
|
113
111
|
end
|
114
112
|
|
115
|
-
def data
|
113
|
+
def data(parent_context)
|
116
114
|
return default_value if factory.nil_input?
|
117
115
|
|
118
116
|
TypeChecker.raise_on_invalid_type(factory.context, type: ::Array)
|
119
117
|
check_values(raise_on_invalid: true)
|
120
118
|
validate(raise_on_invalid: true)
|
121
119
|
|
122
|
-
factory.data.map do |value|
|
123
|
-
value.respond_to?(:node)
|
120
|
+
factory.data.each_with_index.map do |value, i|
|
121
|
+
if value.respond_to?(:node)
|
122
|
+
Node::Placeholder.new(value, i, parent_context)
|
123
|
+
else
|
124
|
+
value
|
125
|
+
end
|
124
126
|
end
|
125
127
|
end
|
126
128
|
|
@@ -175,7 +177,7 @@ module Openapi3Parser
|
|
175
177
|
|
176
178
|
first_error = validatable.errors.first
|
177
179
|
raise Openapi3Parser::Error::InvalidData,
|
178
|
-
"Invalid data for #{first_error.context.location_summary}
|
180
|
+
"Invalid data for #{first_error.context.location_summary}: "\
|
179
181
|
"#{first_error.message}"
|
180
182
|
end
|
181
183
|
|
@@ -0,0 +1,111 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Openapi3Parser
|
4
|
+
module NodeFactory
|
5
|
+
# This class is used to specify the data and source information for a
|
6
|
+
# NodeFactory. The same NodeFactory can be used multiple times if the
|
7
|
+
# object is referenced so it is limited in data about it's location
|
8
|
+
# within the document.
|
9
|
+
#
|
10
|
+
# @attr_reader [Any] input
|
11
|
+
# @attr_reader [Source::Location] source_location
|
12
|
+
# @attr_reader [Array<Source::Location>] refernce_locations
|
13
|
+
#
|
14
|
+
class Context
|
15
|
+
# Create a context for the root of a document
|
16
|
+
#
|
17
|
+
# @param [Any] input
|
18
|
+
# @param [Source] source
|
19
|
+
# @return [Context]
|
20
|
+
def self.root(input, source)
|
21
|
+
new(input, source_location: Source::Location.new(source, []))
|
22
|
+
end
|
23
|
+
|
24
|
+
# Create a factory context for a field within the current contexts data
|
25
|
+
# eg for a context of:
|
26
|
+
# root = Context.root({ "test" => {} }, source)
|
27
|
+
# we can get the context of "test" with:
|
28
|
+
# test = Context.next_field(root, "test")
|
29
|
+
#
|
30
|
+
# @param [Context] parent_context
|
31
|
+
# @param [String] field
|
32
|
+
# @return [Context]
|
33
|
+
def self.next_field(parent_context, field)
|
34
|
+
pc = parent_context
|
35
|
+
input = pc.input.respond_to?(:[]) ? pc.input[field] : nil
|
36
|
+
source_location = Source::Location.next_field(pc.source_location, field)
|
37
|
+
new(input,
|
38
|
+
source_location: source_location,
|
39
|
+
reference_locations: pc.reference_locations)
|
40
|
+
end
|
41
|
+
|
42
|
+
# Creates the context for a field that references another field
|
43
|
+
#
|
44
|
+
# @param [Context] reference_context
|
45
|
+
# @param [Source::Location] source_location
|
46
|
+
# @return [Context]
|
47
|
+
def self.resolved_reference(reference_context, source_location:)
|
48
|
+
reference_locations = [reference_context.source_location] +
|
49
|
+
reference_context.reference_locations
|
50
|
+
|
51
|
+
data = source_location.data if source_location.source_available?
|
52
|
+
new(data,
|
53
|
+
source_location: source_location,
|
54
|
+
reference_locations: reference_locations)
|
55
|
+
end
|
56
|
+
|
57
|
+
attr_reader :input, :source_location, :reference_locations
|
58
|
+
|
59
|
+
# @param [Any] input
|
60
|
+
# @param [Source::Location] source_location
|
61
|
+
# @param [Array<Source::Location>] reference_locations
|
62
|
+
def initialize(input,
|
63
|
+
source_location:,
|
64
|
+
reference_locations: [])
|
65
|
+
@input = input
|
66
|
+
@source_location = source_location
|
67
|
+
@reference_locations = reference_locations
|
68
|
+
end
|
69
|
+
|
70
|
+
# @return [Boolean]
|
71
|
+
def ==(other)
|
72
|
+
input == other.input &&
|
73
|
+
source_location == other.source_location &&
|
74
|
+
reference_locations == other.reference_locations
|
75
|
+
end
|
76
|
+
|
77
|
+
# @return [Source]
|
78
|
+
def source
|
79
|
+
source_location.source
|
80
|
+
end
|
81
|
+
|
82
|
+
# @param [String] reference
|
83
|
+
# @param [Object, Map, Array] factory
|
84
|
+
# @param [Boolean] recursive
|
85
|
+
# @return [Source::ResolvedReference]
|
86
|
+
def resolve_reference(reference, factory, recursive: false)
|
87
|
+
source.resolve_reference(reference, factory, self, recursive: recursive)
|
88
|
+
end
|
89
|
+
|
90
|
+
# Used to show when an recursive reference loop has begun
|
91
|
+
#
|
92
|
+
# @return [Boolean]
|
93
|
+
def self_referencing?
|
94
|
+
reference_locations.include?(source_location)
|
95
|
+
end
|
96
|
+
|
97
|
+
def inspect
|
98
|
+
%{#{self.class.name}(source_location: #{source_location}, } +
|
99
|
+
%{referenced_by: #{reference_locations.map(&:to_s).join(', ')})}
|
100
|
+
end
|
101
|
+
|
102
|
+
def location_summary
|
103
|
+
source_location.to_s
|
104
|
+
end
|
105
|
+
|
106
|
+
def to_s
|
107
|
+
location_summary
|
108
|
+
end
|
109
|
+
end
|
110
|
+
end
|
111
|
+
end
|
@@ -39,11 +39,9 @@ module Openapi3Parser
|
|
39
39
|
@errors ||= ValidNodeBuilder.errors(self)
|
40
40
|
end
|
41
41
|
|
42
|
-
def node
|
43
|
-
|
44
|
-
|
45
|
-
data.nil? ? nil : build_node(data)
|
46
|
-
end
|
42
|
+
def node(node_context)
|
43
|
+
data = ValidNodeBuilder.data(self)
|
44
|
+
data.nil? ? nil : build_node(data, node_context)
|
47
45
|
end
|
48
46
|
|
49
47
|
def inspect
|
@@ -52,7 +50,7 @@ module Openapi3Parser
|
|
52
50
|
|
53
51
|
private
|
54
52
|
|
55
|
-
def build_node(data)
|
53
|
+
def build_node(data, _node_context)
|
56
54
|
data
|
57
55
|
end
|
58
56
|
|
@@ -108,7 +106,7 @@ module Openapi3Parser
|
|
108
106
|
|
109
107
|
first_error = validatable.errors.first
|
110
108
|
raise Openapi3Parser::Error::InvalidData,
|
111
|
-
"Invalid data for #{first_error.context.location_summary}
|
109
|
+
"Invalid data for #{first_error.context.location_summary}: "\
|
112
110
|
"#{first_error.message}"
|
113
111
|
end
|
114
112
|
|
@@ -7,55 +7,74 @@ module Openapi3Parser
|
|
7
7
|
module NodeFactory
|
8
8
|
module Fields
|
9
9
|
class Reference < NodeFactory::Field
|
10
|
+
extend Forwardable
|
11
|
+
|
12
|
+
def_delegator :context, :self_referencing?
|
13
|
+
|
10
14
|
def initialize(context, factory)
|
11
|
-
context = Context.as_reference(context)
|
12
15
|
super(context, input_type: String, validate: :validate)
|
13
16
|
@factory = factory
|
14
17
|
@reference = context.input
|
15
|
-
@
|
18
|
+
@resolved_reference = create_resolved_reference
|
16
19
|
end
|
17
20
|
|
18
21
|
def resolved_input
|
19
|
-
return unless
|
22
|
+
return unless resolved_reference
|
20
23
|
|
21
|
-
if
|
22
|
-
RecursiveResolvedInput.new(
|
24
|
+
if context.self_referencing?
|
25
|
+
RecursiveResolvedInput.new(resolved_reference.factory)
|
23
26
|
else
|
24
|
-
|
27
|
+
resolved_reference.resolved_input
|
25
28
|
end
|
26
29
|
end
|
27
30
|
|
28
|
-
def
|
29
|
-
|
30
|
-
end
|
31
|
-
|
32
|
-
def reference_context
|
33
|
-
context.referenced_by
|
31
|
+
def referenced_factory
|
32
|
+
resolved_reference&.factory
|
34
33
|
end
|
35
34
|
|
36
35
|
private
|
37
36
|
|
38
|
-
attr_reader :reference, :factory, :
|
37
|
+
attr_reader :reference, :factory, :resolved_reference
|
38
|
+
|
39
|
+
def build_node(_data, node_context)
|
40
|
+
if resolved_reference.nil?
|
41
|
+
# this shouldn't happen unless dependant code changes
|
42
|
+
raise Openapi3Parser::Error,
|
43
|
+
"can't build node without a resolved reference"
|
44
|
+
end
|
45
|
+
|
46
|
+
reference_context = Node::Context.resolved_reference(
|
47
|
+
node_context, resolved_reference.factory.context
|
48
|
+
)
|
39
49
|
|
40
|
-
|
41
|
-
reference_resolver&.node
|
50
|
+
resolved_reference.node(reference_context)
|
42
51
|
end
|
43
52
|
|
44
53
|
def validate(validatable)
|
45
54
|
if !reference_validator.valid?
|
46
55
|
validatable.add_errors(reference_validator.errors)
|
56
|
+
elsif !reference_resolves?
|
57
|
+
validatable.add_error("Reference doesn't resolve to an object")
|
47
58
|
else
|
48
|
-
validatable.add_errors(
|
59
|
+
validatable.add_errors(resolved_reference&.errors)
|
49
60
|
end
|
50
61
|
end
|
51
62
|
|
63
|
+
def reference_resolves?
|
64
|
+
return true unless referenced_factory.is_a?(NodeFactory::Reference)
|
65
|
+
|
66
|
+
referenced_factory.resolves?
|
67
|
+
end
|
68
|
+
|
52
69
|
def reference_validator
|
53
70
|
@reference_validator ||= Validators::Reference.new(reference)
|
54
71
|
end
|
55
72
|
|
56
|
-
def
|
73
|
+
def create_resolved_reference
|
57
74
|
return unless reference_validator.valid?
|
58
|
-
context.
|
75
|
+
context.resolve_reference(reference,
|
76
|
+
factory,
|
77
|
+
recursive: context.self_referencing?)
|
59
78
|
end
|
60
79
|
|
61
80
|
# Used in the place of a hash for resolved input so the value can
|
@@ -64,15 +83,15 @@ module Openapi3Parser
|
|
64
83
|
extend Forwardable
|
65
84
|
include Enumerable
|
66
85
|
|
67
|
-
def_delegators :
|
68
|
-
attr_reader :
|
86
|
+
def_delegators :value, :each, :[], :keys
|
87
|
+
attr_reader :factory
|
69
88
|
|
70
|
-
def initialize(
|
71
|
-
@
|
89
|
+
def initialize(factory)
|
90
|
+
@factory = factory
|
72
91
|
end
|
73
92
|
|
74
|
-
def
|
75
|
-
|
93
|
+
def value
|
94
|
+
@factory.resolved_input
|
76
95
|
end
|
77
96
|
end
|
78
97
|
end
|