openapi3_parser 0.5.2 → 0.6.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|