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.
Files changed (67) hide show
  1. checksums.yaml +4 -4
  2. data/.ruby-version +1 -1
  3. data/.travis.yml +3 -3
  4. data/CHANGELOG.md +7 -1
  5. data/README.md +102 -15
  6. data/lib/openapi3_parser/document.rb +14 -14
  7. data/lib/openapi3_parser/document/reference_registry.rb +72 -0
  8. data/lib/openapi3_parser/node/array.rb +10 -2
  9. data/lib/openapi3_parser/node/components.rb +9 -9
  10. data/lib/openapi3_parser/node/contact.rb +3 -3
  11. data/lib/openapi3_parser/node/context.rb +129 -0
  12. data/lib/openapi3_parser/node/discriminator.rb +2 -2
  13. data/lib/openapi3_parser/node/encoding.rb +5 -5
  14. data/lib/openapi3_parser/node/example.rb +4 -4
  15. data/lib/openapi3_parser/node/external_documentation.rb +2 -2
  16. data/lib/openapi3_parser/node/info.rb +6 -6
  17. data/lib/openapi3_parser/node/license.rb +2 -2
  18. data/lib/openapi3_parser/node/link.rb +6 -6
  19. data/lib/openapi3_parser/node/map.rb +8 -4
  20. data/lib/openapi3_parser/node/media_type.rb +5 -5
  21. data/lib/openapi3_parser/node/oauth_flow.rb +4 -4
  22. data/lib/openapi3_parser/node/oauth_flows.rb +4 -4
  23. data/lib/openapi3_parser/node/object.rb +8 -4
  24. data/lib/openapi3_parser/node/openapi.rb +8 -8
  25. data/lib/openapi3_parser/node/operation.rb +12 -12
  26. data/lib/openapi3_parser/node/parameter.rb +2 -2
  27. data/lib/openapi3_parser/node/parameter_like.rb +11 -11
  28. data/lib/openapi3_parser/node/path_item.rb +12 -12
  29. data/lib/openapi3_parser/node/placeholder.rb +34 -0
  30. data/lib/openapi3_parser/node/request_body.rb +3 -3
  31. data/lib/openapi3_parser/node/response.rb +4 -4
  32. data/lib/openapi3_parser/node/responses.rb +1 -1
  33. data/lib/openapi3_parser/node/schema.rb +36 -36
  34. data/lib/openapi3_parser/node/security_scheme.rb +8 -8
  35. data/lib/openapi3_parser/node/server.rb +3 -3
  36. data/lib/openapi3_parser/node/server_variable.rb +3 -3
  37. data/lib/openapi3_parser/node/tag.rb +3 -3
  38. data/lib/openapi3_parser/node/xml.rb +5 -5
  39. data/lib/openapi3_parser/node_factory/array.rb +15 -13
  40. data/lib/openapi3_parser/node_factory/callback.rb +2 -2
  41. data/lib/openapi3_parser/node_factory/context.rb +111 -0
  42. data/lib/openapi3_parser/node_factory/field.rb +5 -7
  43. data/lib/openapi3_parser/node_factory/fields/reference.rb +43 -24
  44. data/lib/openapi3_parser/node_factory/link.rb +1 -1
  45. data/lib/openapi3_parser/node_factory/map.rb +14 -12
  46. data/lib/openapi3_parser/node_factory/object.rb +9 -5
  47. data/lib/openapi3_parser/node_factory/object_factory/node_builder.rb +21 -28
  48. data/lib/openapi3_parser/node_factory/optional_reference.rb +4 -0
  49. data/lib/openapi3_parser/node_factory/parameter_like.rb +0 -2
  50. data/lib/openapi3_parser/node_factory/path_item.rb +7 -4
  51. data/lib/openapi3_parser/node_factory/paths.rb +2 -2
  52. data/lib/openapi3_parser/node_factory/reference.rb +17 -10
  53. data/lib/openapi3_parser/node_factory/responses.rb +2 -2
  54. data/lib/openapi3_parser/node_factory/security_requirement.rb +2 -2
  55. data/lib/openapi3_parser/source.rb +27 -24
  56. data/lib/openapi3_parser/{context → source}/location.rb +13 -1
  57. data/lib/openapi3_parser/{context → source}/pointer.rb +2 -2
  58. data/lib/openapi3_parser/source/resolved_reference.rb +67 -0
  59. data/lib/openapi3_parser/validators/duplicate_parameters.rb +8 -4
  60. data/lib/openapi3_parser/validators/reference.rb +3 -3
  61. data/lib/openapi3_parser/version.rb +1 -1
  62. data/openapi3_parser.gemspec +1 -1
  63. metadata +11 -10
  64. data/lib/openapi3_parser/context.rb +0 -162
  65. data/lib/openapi3_parser/document/reference_register.rb +0 -48
  66. data/lib/openapi3_parser/node_factory/recursive_pointer.rb +0 -17
  67. 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 { |item| item["name"].nil? || item["in"].nil? }
19
- .group_by { |item| [item["name"], item["in"]] }
20
- .delete_if { |_, group| group.size < 2 }
21
- .keys
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 "expected a string" unless given_reference.is_a?(String)
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 "could not parse as a URI"
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
- "invalid JSON pointer, expected a root slash" if first_char != "/"
36
+ "Invalid JSON pointer, expected a root slash" if first_char != "/"
37
37
  end
38
38
  end
39
39
  end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Openapi3Parser
4
- VERSION = "0.5.2"
4
+ VERSION = "0.6.0"
5
5
  end
@@ -24,7 +24,7 @@ Gem::Specification.new do |spec|
24
24
  f.match(%r{^spec/})
25
25
  end
26
26
 
27
- spec.required_ruby_version = ">= 2.3.0"
27
+ spec.required_ruby_version = ">= 2.4.0"
28
28
 
29
29
  spec.add_dependency "commonmarker", "~> 0.17"
30
30
 
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.5.2
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: 2018-08-29 00:00:00.000000000 Z
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/reference_register.rb
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/reference_resolver.rb
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.3.0
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.5.1
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