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
@@ -15,10 +15,14 @@ module Openapi3Parser
|
|
15
15
|
private
|
16
16
|
|
17
17
|
def duplicate_names_by_in(resolved_input)
|
18
|
-
resolved_input.reject
|
19
|
-
|
20
|
-
|
21
|
-
|
18
|
+
potential_items = resolved_input.reject do |item|
|
19
|
+
next true unless item.respond_to?(:keys)
|
20
|
+
item["name"].nil? || item["in"].nil?
|
21
|
+
end
|
22
|
+
|
23
|
+
potential_items.group_by { |item| [item["name"], item["in"]] }
|
24
|
+
.delete_if { |_, group| group.size < 2 }
|
25
|
+
.keys
|
22
26
|
end
|
23
27
|
|
24
28
|
def message(dupes)
|
@@ -20,11 +20,11 @@ module Openapi3Parser
|
|
20
20
|
attr_reader :given_reference
|
21
21
|
|
22
22
|
def build_errors
|
23
|
-
return "
|
23
|
+
return "Expected a string" unless given_reference.is_a?(String)
|
24
24
|
begin
|
25
25
|
uri = URI.parse(given_reference)
|
26
26
|
rescue URI::Error
|
27
|
-
return "
|
27
|
+
return "Could not parse as a URI"
|
28
28
|
end
|
29
29
|
check_fragment(uri) || []
|
30
30
|
end
|
@@ -33,7 +33,7 @@ module Openapi3Parser
|
|
33
33
|
return if uri.fragment.nil? || uri.fragment.empty?
|
34
34
|
first_char = uri.fragment[0]
|
35
35
|
|
36
|
-
"
|
36
|
+
"Invalid JSON pointer, expected a root slash" if first_char != "/"
|
37
37
|
end
|
38
38
|
end
|
39
39
|
end
|
data/openapi3_parser.gemspec
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: openapi3_parser
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.6.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Kevin Dew
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2019-10-07 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: commonmarker
|
@@ -131,17 +131,15 @@ files:
|
|
131
131
|
- lib/openapi3_parser.rb
|
132
132
|
- lib/openapi3_parser/array_sentence.rb
|
133
133
|
- lib/openapi3_parser/cautious_dig.rb
|
134
|
-
- lib/openapi3_parser/context.rb
|
135
|
-
- lib/openapi3_parser/context/location.rb
|
136
|
-
- lib/openapi3_parser/context/pointer.rb
|
137
134
|
- lib/openapi3_parser/document.rb
|
138
|
-
- lib/openapi3_parser/document/
|
135
|
+
- lib/openapi3_parser/document/reference_registry.rb
|
139
136
|
- lib/openapi3_parser/error.rb
|
140
137
|
- lib/openapi3_parser/markdown.rb
|
141
138
|
- lib/openapi3_parser/node/array.rb
|
142
139
|
- lib/openapi3_parser/node/callback.rb
|
143
140
|
- lib/openapi3_parser/node/components.rb
|
144
141
|
- lib/openapi3_parser/node/contact.rb
|
142
|
+
- lib/openapi3_parser/node/context.rb
|
145
143
|
- lib/openapi3_parser/node/discriminator.rb
|
146
144
|
- lib/openapi3_parser/node/encoding.rb
|
147
145
|
- lib/openapi3_parser/node/example.rb
|
@@ -161,6 +159,7 @@ files:
|
|
161
159
|
- lib/openapi3_parser/node/parameter_like.rb
|
162
160
|
- lib/openapi3_parser/node/path_item.rb
|
163
161
|
- lib/openapi3_parser/node/paths.rb
|
162
|
+
- lib/openapi3_parser/node/placeholder.rb
|
164
163
|
- lib/openapi3_parser/node/request_body.rb
|
165
164
|
- lib/openapi3_parser/node/response.rb
|
166
165
|
- lib/openapi3_parser/node/responses.rb
|
@@ -176,6 +175,7 @@ files:
|
|
176
175
|
- lib/openapi3_parser/node_factory/callback.rb
|
177
176
|
- lib/openapi3_parser/node_factory/components.rb
|
178
177
|
- lib/openapi3_parser/node_factory/contact.rb
|
178
|
+
- lib/openapi3_parser/node_factory/context.rb
|
179
179
|
- lib/openapi3_parser/node_factory/discriminator.rb
|
180
180
|
- lib/openapi3_parser/node_factory/encoding.rb
|
181
181
|
- lib/openapi3_parser/node_factory/example.rb
|
@@ -202,7 +202,6 @@ files:
|
|
202
202
|
- lib/openapi3_parser/node_factory/parameter_like.rb
|
203
203
|
- lib/openapi3_parser/node_factory/path_item.rb
|
204
204
|
- lib/openapi3_parser/node_factory/paths.rb
|
205
|
-
- lib/openapi3_parser/node_factory/recursive_pointer.rb
|
206
205
|
- lib/openapi3_parser/node_factory/reference.rb
|
207
206
|
- lib/openapi3_parser/node_factory/request_body.rb
|
208
207
|
- lib/openapi3_parser/node_factory/response.rb
|
@@ -216,8 +215,10 @@ files:
|
|
216
215
|
- lib/openapi3_parser/node_factory/type_checker.rb
|
217
216
|
- lib/openapi3_parser/node_factory/xml.rb
|
218
217
|
- lib/openapi3_parser/source.rb
|
218
|
+
- lib/openapi3_parser/source/location.rb
|
219
|
+
- lib/openapi3_parser/source/pointer.rb
|
219
220
|
- lib/openapi3_parser/source/reference.rb
|
220
|
-
- lib/openapi3_parser/source/
|
221
|
+
- lib/openapi3_parser/source/resolved_reference.rb
|
221
222
|
- lib/openapi3_parser/source_input.rb
|
222
223
|
- lib/openapi3_parser/source_input/file.rb
|
223
224
|
- lib/openapi3_parser/source_input/raw.rb
|
@@ -252,7 +253,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
252
253
|
requirements:
|
253
254
|
- - ">="
|
254
255
|
- !ruby/object:Gem::Version
|
255
|
-
version: 2.
|
256
|
+
version: 2.4.0
|
256
257
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
257
258
|
requirements:
|
258
259
|
- - ">="
|
@@ -260,7 +261,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
260
261
|
version: '0'
|
261
262
|
requirements: []
|
262
263
|
rubyforge_project:
|
263
|
-
rubygems_version: 2.
|
264
|
+
rubygems_version: 2.6.14.4
|
264
265
|
signing_key:
|
265
266
|
specification_version: 4
|
266
267
|
summary: An OpenAPI V3 parser for Ruby
|
@@ -1,162 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
module Openapi3Parser
|
4
|
-
# Context is a construct used in both the node factories and the nodes
|
5
|
-
# themselves. It is used to represent the data, and the source of it, that
|
6
|
-
# a node is associated with. It also acts as a bridge between a node/node
|
7
|
-
# factory and associated document.
|
8
|
-
#
|
9
|
-
# @attr_reader input
|
10
|
-
# @attr_reader [Context::Location] document_location
|
11
|
-
# @attr_reader [Context::Location, nil] source_location
|
12
|
-
# @attr_reader [Context, nil] referenced_by
|
13
|
-
class Context
|
14
|
-
# Create a context for the root of a document
|
15
|
-
# @return [Context]
|
16
|
-
def self.root(input, source)
|
17
|
-
location = Location.new(source, [])
|
18
|
-
new(input, document_location: location)
|
19
|
-
end
|
20
|
-
|
21
|
-
# Create a context for a field within the current contexts data
|
22
|
-
# eg for a context of:
|
23
|
-
# root = Context.root({ "test" => {} }, source)
|
24
|
-
# we can get the context of "test" with:
|
25
|
-
# test = Context.next_field(root, "test")
|
26
|
-
#
|
27
|
-
# @param [Context] parent_context
|
28
|
-
# @param [String] field
|
29
|
-
# @return [Context]
|
30
|
-
def self.next_field(parent_context, field)
|
31
|
-
pc = parent_context
|
32
|
-
input = pc.input.respond_to?(:[]) ? pc.input[field] : nil
|
33
|
-
new(input,
|
34
|
-
document_location: Location.next_field(pc.document_location, field),
|
35
|
-
source_location: Location.next_field(pc.source_location, field),
|
36
|
-
referenced_by: pc.referenced_by)
|
37
|
-
end
|
38
|
-
|
39
|
-
# Convert a context into one that knows that is a reference
|
40
|
-
#
|
41
|
-
# @param [Context] current_context
|
42
|
-
# @return [Context]
|
43
|
-
def self.as_reference(current_context)
|
44
|
-
new(current_context.input,
|
45
|
-
document_location: current_context.document_location,
|
46
|
-
source_location: current_context.source_location,
|
47
|
-
referenced_by: current_context.referenced_by,
|
48
|
-
is_reference: true)
|
49
|
-
end
|
50
|
-
|
51
|
-
# Creates the context for a field that is referenced by a context.
|
52
|
-
# In this scenario the context of the document is the same but we are in
|
53
|
-
# a different part of the source file, or even a different source file
|
54
|
-
#
|
55
|
-
# @param [Context] referencer_context
|
56
|
-
# @param input
|
57
|
-
# @param [Source] source
|
58
|
-
# @param [::Array] pointer_segments
|
59
|
-
# @return [Context]
|
60
|
-
def self.reference_field(referencer_context,
|
61
|
-
input:,
|
62
|
-
source:,
|
63
|
-
pointer_segments:)
|
64
|
-
new(input,
|
65
|
-
document_location: referencer_context.document_location,
|
66
|
-
source_location: Location.new(source, pointer_segments),
|
67
|
-
referenced_by: referencer_context)
|
68
|
-
end
|
69
|
-
|
70
|
-
attr_reader :input, :document_location, :source_location, :referenced_by
|
71
|
-
|
72
|
-
# @param input
|
73
|
-
# @param [Context::Location] document_location
|
74
|
-
# @param [Context::Location, nil] source_location
|
75
|
-
# @param [Context, nil] referenced_by
|
76
|
-
# @param [Boolean] is_reference
|
77
|
-
def initialize(input,
|
78
|
-
document_location:,
|
79
|
-
source_location: nil,
|
80
|
-
referenced_by: nil,
|
81
|
-
is_reference: false)
|
82
|
-
@input = input
|
83
|
-
@document_location = document_location
|
84
|
-
@source_location = source_location || document_location
|
85
|
-
@referenced_by = referenced_by
|
86
|
-
@is_reference = is_reference
|
87
|
-
end
|
88
|
-
|
89
|
-
# @return [Boolean]
|
90
|
-
def ==(other)
|
91
|
-
input == other.input &&
|
92
|
-
document_location == other.document_location &&
|
93
|
-
source_location == other.source_location &&
|
94
|
-
referenced_by == other.referenced_by
|
95
|
-
end
|
96
|
-
|
97
|
-
# @return [Document]
|
98
|
-
def document
|
99
|
-
document_location.source.document
|
100
|
-
end
|
101
|
-
|
102
|
-
# @return [Source]
|
103
|
-
def source
|
104
|
-
source_location.source
|
105
|
-
end
|
106
|
-
|
107
|
-
# @return [Source::ReferenceResolver]
|
108
|
-
def register_reference(reference, factory)
|
109
|
-
source.register_reference(reference, factory, self)
|
110
|
-
end
|
111
|
-
|
112
|
-
# @deprecated
|
113
|
-
def namespace
|
114
|
-
document_location.pointer.segments
|
115
|
-
end
|
116
|
-
|
117
|
-
# @return [Boolean]
|
118
|
-
def reference?
|
119
|
-
@is_reference
|
120
|
-
end
|
121
|
-
|
122
|
-
def inspect
|
123
|
-
%{#{self.class.name}(document_location: #{document_location}, } +
|
124
|
-
%{source_location: #{source_location}), referenced_by: } +
|
125
|
-
%{#{referenced_by})}
|
126
|
-
end
|
127
|
-
|
128
|
-
def location_summary
|
129
|
-
summary = document_location.to_s
|
130
|
-
summary += " (#{source_location})" if document_location != source_location
|
131
|
-
summary
|
132
|
-
end
|
133
|
-
|
134
|
-
def to_s
|
135
|
-
location_summary
|
136
|
-
end
|
137
|
-
|
138
|
-
def resolved_input
|
139
|
-
# The resolved input for a reference is at the segment before the
|
140
|
-
# reference
|
141
|
-
pointer = if reference?
|
142
|
-
document_location.pointer.segments[0...-1]
|
143
|
-
else
|
144
|
-
document_location.pointer
|
145
|
-
end
|
146
|
-
|
147
|
-
document.resolved_input_at(pointer)
|
148
|
-
end
|
149
|
-
|
150
|
-
def node
|
151
|
-
# The created node for a reference is at the segment before the
|
152
|
-
# reference
|
153
|
-
pointer = if reference?
|
154
|
-
document_location.pointer.segments[0...-1]
|
155
|
-
else
|
156
|
-
document_location.pointer
|
157
|
-
end
|
158
|
-
|
159
|
-
document.node_at(pointer)
|
160
|
-
end
|
161
|
-
end
|
162
|
-
end
|
@@ -1,48 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
module Openapi3Parser
|
4
|
-
class Document
|
5
|
-
class ReferenceRegister
|
6
|
-
attr_reader :sources, :factories
|
7
|
-
|
8
|
-
def initialize
|
9
|
-
@sources = []
|
10
|
-
@factories = []
|
11
|
-
end
|
12
|
-
|
13
|
-
def register(factory)
|
14
|
-
error = "Can't register references when the register is frozen"
|
15
|
-
raise Error::ImmutableObject, error if frozen?
|
16
|
-
context = factory.context
|
17
|
-
add_source(context.source_location.source)
|
18
|
-
add_factory(factory)
|
19
|
-
end
|
20
|
-
|
21
|
-
def freeze
|
22
|
-
sources.freeze
|
23
|
-
factories.freeze
|
24
|
-
super
|
25
|
-
end
|
26
|
-
|
27
|
-
private
|
28
|
-
|
29
|
-
def add_source(source)
|
30
|
-
return if sources.include?(source)
|
31
|
-
sources << source
|
32
|
-
end
|
33
|
-
|
34
|
-
def add_factory(factory)
|
35
|
-
return if factory_registered?(factory)
|
36
|
-
factories << factory
|
37
|
-
end
|
38
|
-
|
39
|
-
def factory_registered?(factory)
|
40
|
-
source_location = factory.context.source_location
|
41
|
-
factories.any? do |f|
|
42
|
-
same_location = f.context.source_location == source_location
|
43
|
-
same_location && f.class == factory.class
|
44
|
-
end
|
45
|
-
end
|
46
|
-
end
|
47
|
-
end
|
48
|
-
end
|
@@ -1,17 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
module Openapi3Parser
|
4
|
-
module NodeFactory
|
5
|
-
class RecursivePointer
|
6
|
-
attr_reader :reference_context
|
7
|
-
|
8
|
-
def initialize(reference_context)
|
9
|
-
@reference_context = reference_context
|
10
|
-
end
|
11
|
-
|
12
|
-
def node
|
13
|
-
reference_context.node
|
14
|
-
end
|
15
|
-
end
|
16
|
-
end
|
17
|
-
end
|
@@ -1,82 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
module Openapi3Parser
|
4
|
-
class Source
|
5
|
-
class ReferenceResolver
|
6
|
-
def initialize(reference, factory, context)
|
7
|
-
@reference = reference
|
8
|
-
@factory = factory
|
9
|
-
@context = context
|
10
|
-
end
|
11
|
-
|
12
|
-
def reference_factory
|
13
|
-
@reference_factory ||= begin
|
14
|
-
next_context = Context.reference_field(
|
15
|
-
context,
|
16
|
-
input: source.data_at_pointer(json_pointer),
|
17
|
-
source: source,
|
18
|
-
pointer_segments: json_pointer
|
19
|
-
)
|
20
|
-
build_factory(next_context)
|
21
|
-
end
|
22
|
-
end
|
23
|
-
|
24
|
-
def resolved_input
|
25
|
-
reference_factory.resolved_input
|
26
|
-
end
|
27
|
-
|
28
|
-
def valid?
|
29
|
-
errors.empty?
|
30
|
-
end
|
31
|
-
|
32
|
-
def errors
|
33
|
-
@errors ||= Array(build_errors)
|
34
|
-
end
|
35
|
-
|
36
|
-
def node
|
37
|
-
reference_factory.node
|
38
|
-
end
|
39
|
-
|
40
|
-
def in_root_source?
|
41
|
-
source == context.document.root_source
|
42
|
-
end
|
43
|
-
|
44
|
-
private
|
45
|
-
|
46
|
-
attr_reader :reference, :factory, :context
|
47
|
-
|
48
|
-
def source
|
49
|
-
@source ||= context.source.resolve_source(reference)
|
50
|
-
end
|
51
|
-
|
52
|
-
def build_errors
|
53
|
-
return source_unavailabe_error unless source.available?
|
54
|
-
return pointer_missing_error unless source.has_pointer?(json_pointer)
|
55
|
-
resolution_error unless reference_factory.valid?
|
56
|
-
end
|
57
|
-
|
58
|
-
def source_unavailabe_error
|
59
|
-
# @todo include a location
|
60
|
-
"Source is unavailable"
|
61
|
-
end
|
62
|
-
|
63
|
-
def pointer_missing_error
|
64
|
-
# @todo include a location and a pointer
|
65
|
-
"Source does not have pointer"
|
66
|
-
end
|
67
|
-
|
68
|
-
def resolution_error
|
69
|
-
# @todo include exepected object
|
70
|
-
"Reference does not resolve to a valid object"
|
71
|
-
end
|
72
|
-
|
73
|
-
def json_pointer
|
74
|
-
reference.json_pointer
|
75
|
-
end
|
76
|
-
|
77
|
-
def build_factory(context)
|
78
|
-
factory.is_a?(Class) ? factory.new(context) : factory.call(context)
|
79
|
-
end
|
80
|
-
end
|
81
|
-
end
|
82
|
-
end
|