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.
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