openapi3_parser 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (96) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +1 -0
  3. data/.rspec +1 -0
  4. data/.rubocop.yml +9 -0
  5. data/.ruby-version +1 -0
  6. data/.travis.yml +4 -0
  7. data/Gemfile +5 -0
  8. data/LICENCE +19 -0
  9. data/README.md +32 -0
  10. data/Rakefile +10 -0
  11. data/TODO.md +30 -0
  12. data/lib/openapi3_parser.rb +39 -0
  13. data/lib/openapi3_parser/context.rb +54 -0
  14. data/lib/openapi3_parser/document.rb +48 -0
  15. data/lib/openapi3_parser/error.rb +5 -0
  16. data/lib/openapi3_parser/fields/map.rb +83 -0
  17. data/lib/openapi3_parser/node.rb +115 -0
  18. data/lib/openapi3_parser/node/map.rb +24 -0
  19. data/lib/openapi3_parser/node/object.rb +28 -0
  20. data/lib/openapi3_parser/node_factories/array.rb +105 -0
  21. data/lib/openapi3_parser/node_factories/callback.rb +26 -0
  22. data/lib/openapi3_parser/node_factories/components.rb +83 -0
  23. data/lib/openapi3_parser/node_factories/contact.rb +24 -0
  24. data/lib/openapi3_parser/node_factories/discriminator.rb +31 -0
  25. data/lib/openapi3_parser/node_factories/encoding.rb +34 -0
  26. data/lib/openapi3_parser/node_factories/example.rb +25 -0
  27. data/lib/openapi3_parser/node_factories/external_documentation.rb +23 -0
  28. data/lib/openapi3_parser/node_factories/header.rb +36 -0
  29. data/lib/openapi3_parser/node_factories/info.rb +28 -0
  30. data/lib/openapi3_parser/node_factories/license.rb +22 -0
  31. data/lib/openapi3_parser/node_factories/link.rb +40 -0
  32. data/lib/openapi3_parser/node_factories/map.rb +110 -0
  33. data/lib/openapi3_parser/node_factories/media_type.rb +44 -0
  34. data/lib/openapi3_parser/node_factories/oauth_flow.rb +24 -0
  35. data/lib/openapi3_parser/node_factories/oauth_flows.rb +31 -0
  36. data/lib/openapi3_parser/node_factories/openapi.rb +50 -0
  37. data/lib/openapi3_parser/node_factories/operation.rb +76 -0
  38. data/lib/openapi3_parser/node_factories/parameter.rb +43 -0
  39. data/lib/openapi3_parser/node_factories/parameter/parameter_like.rb +37 -0
  40. data/lib/openapi3_parser/node_factories/path_item.rb +75 -0
  41. data/lib/openapi3_parser/node_factories/paths.rb +32 -0
  42. data/lib/openapi3_parser/node_factories/reference.rb +33 -0
  43. data/lib/openapi3_parser/node_factories/request_body.rb +31 -0
  44. data/lib/openapi3_parser/node_factories/response.rb +45 -0
  45. data/lib/openapi3_parser/node_factories/responses.rb +32 -0
  46. data/lib/openapi3_parser/node_factories/schema.rb +106 -0
  47. data/lib/openapi3_parser/node_factories/security_requirement.rb +25 -0
  48. data/lib/openapi3_parser/node_factories/security_scheme.rb +35 -0
  49. data/lib/openapi3_parser/node_factories/server.rb +32 -0
  50. data/lib/openapi3_parser/node_factories/server_variable.rb +28 -0
  51. data/lib/openapi3_parser/node_factories/tag.rb +24 -0
  52. data/lib/openapi3_parser/node_factories/xml.rb +25 -0
  53. data/lib/openapi3_parser/node_factory.rb +126 -0
  54. data/lib/openapi3_parser/node_factory/field_config.rb +88 -0
  55. data/lib/openapi3_parser/node_factory/map.rb +39 -0
  56. data/lib/openapi3_parser/node_factory/object.rb +80 -0
  57. data/lib/openapi3_parser/node_factory/object/node_builder.rb +85 -0
  58. data/lib/openapi3_parser/node_factory/object/validator.rb +102 -0
  59. data/lib/openapi3_parser/node_factory/optional_reference.rb +23 -0
  60. data/lib/openapi3_parser/nodes/array.rb +26 -0
  61. data/lib/openapi3_parser/nodes/callback.rb +11 -0
  62. data/lib/openapi3_parser/nodes/components.rb +47 -0
  63. data/lib/openapi3_parser/nodes/contact.rb +23 -0
  64. data/lib/openapi3_parser/nodes/discriminator.rb +19 -0
  65. data/lib/openapi3_parser/nodes/encoding.rb +31 -0
  66. data/lib/openapi3_parser/nodes/example.rb +27 -0
  67. data/lib/openapi3_parser/nodes/external_documentation.rb +19 -0
  68. data/lib/openapi3_parser/nodes/header.rb +13 -0
  69. data/lib/openapi3_parser/nodes/info.rb +35 -0
  70. data/lib/openapi3_parser/nodes/license.rb +19 -0
  71. data/lib/openapi3_parser/nodes/link.rb +35 -0
  72. data/lib/openapi3_parser/nodes/map.rb +11 -0
  73. data/lib/openapi3_parser/nodes/media_type.rb +27 -0
  74. data/lib/openapi3_parser/nodes/oauth_flow.rb +27 -0
  75. data/lib/openapi3_parser/nodes/oauth_flows.rb +27 -0
  76. data/lib/openapi3_parser/nodes/openapi.rb +44 -0
  77. data/lib/openapi3_parser/nodes/operation.rb +59 -0
  78. data/lib/openapi3_parser/nodes/parameter.rb +21 -0
  79. data/lib/openapi3_parser/nodes/parameter/parameter_like.rb +53 -0
  80. data/lib/openapi3_parser/nodes/path_item.rb +59 -0
  81. data/lib/openapi3_parser/nodes/paths.rb +11 -0
  82. data/lib/openapi3_parser/nodes/request_body.rb +23 -0
  83. data/lib/openapi3_parser/nodes/response.rb +27 -0
  84. data/lib/openapi3_parser/nodes/responses.rb +15 -0
  85. data/lib/openapi3_parser/nodes/schema.rb +159 -0
  86. data/lib/openapi3_parser/nodes/security_requirement.rb +11 -0
  87. data/lib/openapi3_parser/nodes/security_scheme.rb +44 -0
  88. data/lib/openapi3_parser/nodes/server.rb +25 -0
  89. data/lib/openapi3_parser/nodes/server_variable.rb +23 -0
  90. data/lib/openapi3_parser/nodes/tag.rb +23 -0
  91. data/lib/openapi3_parser/nodes/xml.rb +31 -0
  92. data/lib/openapi3_parser/validation/error.rb +14 -0
  93. data/lib/openapi3_parser/validation/error_collection.rb +36 -0
  94. data/lib/openapi3_parser/version.rb +5 -0
  95. data/openapi3_parser.gemspec +28 -0
  96. metadata +208 -0
@@ -0,0 +1,37 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Openapi3Parser
4
+ module NodeFactories
5
+ class Parameter
6
+ module ParameterLike
7
+ def default_explode
8
+ context.input["style"] == "form"
9
+ end
10
+
11
+ def schema_factory(context)
12
+ factory = NodeFactory::OptionalReference.new(NodeFactories::Schema)
13
+ factory.call(context)
14
+ end
15
+
16
+ def examples_factory(context)
17
+ factory = NodeFactory::OptionalReference.new(NodeFactories::Schema)
18
+ NodeFactories::Map.new(context, value_factory: factory)
19
+ end
20
+
21
+ def content_factory(context)
22
+ factory = NodeFactory::OptionalReference.new(
23
+ NodeFactories::MediaType
24
+ )
25
+ NodeFactories::Map.new(context, value_factory: factory)
26
+ end
27
+ end
28
+ end
29
+ end
30
+ end
31
+
32
+ # These are in the footer as a cyclic dependency can stop this module loading
33
+ require "openapi3_parser/node_factory/optional_reference"
34
+ require "openapi3_parser/node_factories/schema"
35
+ require "openapi3_parser/node_factories/map"
36
+ require "openapi3_parser/node_factories/example"
37
+ require "openapi3_parser/node_factories/media_type"
@@ -0,0 +1,75 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "openapi3_parser/nodes/path_item"
4
+ require "openapi3_parser/node_factory/object"
5
+ require "openapi3_parser/node_factory/object/node_builder"
6
+ require "openapi3_parser/node_factory/optional_reference"
7
+ require "openapi3_parser/node_factories/array"
8
+ require "openapi3_parser/node_factories/server"
9
+ require "openapi3_parser/node_factories/operation"
10
+ require "openapi3_parser/node_factories/parameter"
11
+
12
+ module Openapi3Parser
13
+ module NodeFactories
14
+ class PathItem
15
+ include NodeFactory::Object
16
+
17
+ allow_extensions
18
+ field "$ref", input_type: String
19
+ field "summary", input_type: String
20
+ field "description", input_type: String
21
+ field "get", factory: :operation_factory
22
+ field "put", factory: :operation_factory
23
+ field "post", factory: :operation_factory
24
+ field "delete", factory: :operation_factory
25
+ field "options", factory: :operation_factory
26
+ field "head", factory: :operation_factory
27
+ field "patch", factory: :operation_factory
28
+ field "trace", factory: :operation_factory
29
+ field "servers", factory: :servers_factory
30
+ field "parameters", factory: :parameters_factory
31
+
32
+ def node_data
33
+ NodeBuilder.new(processed_input, self).data
34
+ end
35
+
36
+ private
37
+
38
+ def build_object(data, context)
39
+ merged_data = merge_reference(data, context)
40
+ merged_data.delete("$ref")
41
+ Nodes::PathItem.new(merged_data, context)
42
+ end
43
+
44
+ def operation_factory(context)
45
+ NodeFactories::Operation.new(context)
46
+ end
47
+
48
+ def servers_factory(context)
49
+ NodeFactories::Array.new(
50
+ context,
51
+ value_factory: NodeFactories::Server
52
+ )
53
+ end
54
+
55
+ def parameters_factory(context)
56
+ factory = NodeFactory::OptionalReference.new(NodeFactories::Parameter)
57
+ NodeFactories::Array.new(context, value_factory: factory)
58
+ end
59
+
60
+ def merge_reference(data, context)
61
+ return data unless data["$ref"]
62
+ factory = context.resolve_reference do |ref_context|
63
+ self.class.new(ref_context)
64
+ end
65
+
66
+ # @TODO In this situation we're basically sacrificing the reference
67
+ # context as we don't know how to merge them. Should develop a system
68
+ # to have a dual context
69
+ factory.node_data.merge(data) do |_, new, old|
70
+ new.nil? ? old : new
71
+ end
72
+ end
73
+ end
74
+ end
75
+ end
@@ -0,0 +1,32 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "openapi3_parser/node_factory/map"
4
+ require "openapi3_parser/node_factory/optional_reference"
5
+ require "openapi3_parser/node_factories/path_item"
6
+ require "openapi3_parser/nodes/paths"
7
+
8
+ module Openapi3Parser
9
+ module NodeFactories
10
+ class Paths
11
+ include NodeFactory::Map
12
+
13
+ private
14
+
15
+ def process_input(input)
16
+ input.each_with_object({}) do |(key, value), memo|
17
+ memo[key] = value if extension?(key)
18
+ memo[key] = child_factory(context.next_namespace(key))
19
+ end
20
+ end
21
+
22
+ def child_factory(child_context)
23
+ NodeFactory::OptionalReference.new(NodeFactories::PathItem)
24
+ .call(child_context)
25
+ end
26
+
27
+ def build_map(data, context)
28
+ Nodes::Paths.new(data, context)
29
+ end
30
+ end
31
+ end
32
+ end
@@ -0,0 +1,33 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "openapi3_parser/node_factory/object"
4
+
5
+ module Openapi3Parser
6
+ module NodeFactories
7
+ class Reference
8
+ include NodeFactory::Object
9
+
10
+ field "$ref", input_type: String, required: true
11
+
12
+ attr_reader :factory
13
+
14
+ def initialize(context, factory)
15
+ super(context)
16
+ @factory = factory
17
+ end
18
+
19
+ private
20
+
21
+ def build_object(_, context)
22
+ context.resolve_reference do |ref_context|
23
+ resolve_factory(ref_context).node
24
+ end
25
+ end
26
+
27
+ def resolve_factory(ref_context)
28
+ return factory.new(ref_context) if factory.is_a?(Class)
29
+ factory.call(ref_context)
30
+ end
31
+ end
32
+ end
33
+ end
@@ -0,0 +1,31 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "openapi3_parser/nodes/request_body"
4
+ require "openapi3_parser/node_factory/object"
5
+ require "openapi3_parser/node_factories/media_type"
6
+ require "openapi3_parser/node_factories/map"
7
+
8
+ module Openapi3Parser
9
+ module NodeFactories
10
+ class RequestBody
11
+ include NodeFactory::Object
12
+
13
+ allow_extensions
14
+ field "description", input_type: String
15
+ field "content", factory: :content_factory, required: true
16
+ field "required", input_type: :boolean, default: false
17
+
18
+ private
19
+
20
+ def build_object(data, context)
21
+ Nodes::RequestBody.new(data, context)
22
+ end
23
+
24
+ def content_factory(context)
25
+ NodeFactories::Map.new(
26
+ context, value_factory: NodeFactories::MediaType
27
+ )
28
+ end
29
+ end
30
+ end
31
+ end
@@ -0,0 +1,45 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "openapi3_parser/nodes/response"
4
+ require "openapi3_parser/node_factory/object"
5
+ require "openapi3_parser/node_factory/optional_reference"
6
+ require "openapi3_parser/node_factories/map"
7
+ require "openapi3_parser/node_factories/header"
8
+ require "openapi3_parser/node_factories/media_type"
9
+ require "openapi3_parser/node_factories/link"
10
+
11
+ module Openapi3Parser
12
+ module NodeFactories
13
+ class Response
14
+ include NodeFactory::Object
15
+
16
+ allow_extensions
17
+ field "description", input_type: String, required: true
18
+ field "headers", factory: :headers_factory
19
+ field "content", factory: :content_factory
20
+ field "links", factory: :links_factory
21
+
22
+ private
23
+
24
+ def build_object(data, context)
25
+ Nodes::Response.new(data, context)
26
+ end
27
+
28
+ def headers_factory(context)
29
+ factory = NodeFactory::OptionalReference.new(NodeFactories::Header)
30
+ NodeFactories::Map.new(context, value_factory: factory)
31
+ end
32
+
33
+ def content_factory(context)
34
+ NodeFactories::Map.new(
35
+ context, value_factory: NodeFactories::MediaType
36
+ )
37
+ end
38
+
39
+ def links_factory(context)
40
+ factory = NodeFactory::OptionalReference.new(NodeFactories::Link)
41
+ NodeFactories::Map.new(context, value_factory: factory)
42
+ end
43
+ end
44
+ end
45
+ end
@@ -0,0 +1,32 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "openapi3_parser/node_factory/map"
4
+ require "openapi3_parser/node_factory/optional_reference"
5
+ require "openapi3_parser/nodes/responses"
6
+ require "openapi3_parser/node_factories/response"
7
+
8
+ module Openapi3Parser
9
+ module NodeFactories
10
+ class Responses
11
+ include NodeFactory::Map
12
+
13
+ private
14
+
15
+ def process_input(input)
16
+ input.each_with_object({}) do |(key, value), memo|
17
+ memo[key] = value if extension?(key)
18
+ memo[key] = child_factory(context.next_namespace(key))
19
+ end
20
+ end
21
+
22
+ def child_factory(child_context)
23
+ NodeFactory::OptionalReference.new(NodeFactories::Response)
24
+ .call(child_context)
25
+ end
26
+
27
+ def build_map(data, context)
28
+ Nodes::Responses.new(data, context)
29
+ end
30
+ end
31
+ end
32
+ end
@@ -0,0 +1,106 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "openapi3_parser/nodes/schema"
4
+ require "openapi3_parser/node_factory/object"
5
+ require "openapi3_parser/node_factory/optional_reference"
6
+ require "openapi3_parser/node_factories/map"
7
+ require "openapi3_parser/node_factories/array"
8
+ require "openapi3_parser/node_factories/external_documentation"
9
+ require "openapi3_parser/node_factories/discriminator"
10
+ require "openapi3_parser/node_factories/xml"
11
+
12
+ module Openapi3Parser
13
+ module NodeFactories
14
+ class Schema
15
+ include NodeFactory::Object
16
+
17
+ allow_extensions
18
+ field "title", input_type: String
19
+ field "multipleOf", input_type: Numeric
20
+ field "maximum", input_type: Integer
21
+ field "exclusiveMaximum", input_type: :boolean, default: false
22
+ field "minimum", input_type: Integer
23
+ field "exclusiveMinimum", input_type: :boolean, default: false
24
+ field "maxLength", input_type: Integer
25
+ field "minLength", input_type: Integer, default: 0
26
+ field :pattern, input_type: String
27
+ field "maxItems", input_type: Integer
28
+ field "minItems", input_type: Integer, default: 0
29
+ field "uniqueItems", input_type: :boolean, default: false
30
+ field "maxProperties", input_type: Integer
31
+ field "minProperties", input_type: Integer, default: 0
32
+ field "required", input_type: ::Array
33
+ field "enum", input_type: ::Array
34
+
35
+ field "type", input_type: String
36
+ field "allOf", factory: :referenceable_schema_array
37
+ field "oneOf", factory: :referenceable_schema_array
38
+ field "anyOf", factory: :referenceable_schema_array
39
+ field "not", factory: :referenceable_schema
40
+ field "items", factory: :referenceable_schema
41
+ field "properties", factory: :properties_factory
42
+ field "additionalProperties",
43
+ input_type: :additional_properties_input_type,
44
+ factory: :additional_properties_factory,
45
+ default: false
46
+ field "description", input_type: String
47
+ field "format", input_type: String
48
+ field "default"
49
+
50
+ field "nullable", input_type: :boolean, default: false
51
+ field "discriminator", factory: :disciminator_factory
52
+ field "readOnly", input_type: :boolean, default: false
53
+ field "writeOnly", input_type: :boolean, default: false
54
+ field "xml", factory: :xml_factory
55
+ field "externalDocs", factory: :external_docs_factory
56
+ field "example"
57
+ field "deprecated", input_type: :boolean, default: false
58
+
59
+ private
60
+
61
+ def build_object(data, context)
62
+ Nodes::Schema.new(data, context)
63
+ end
64
+
65
+ def disciminator_factory(context)
66
+ NodeFactories::Discriminator.new(context)
67
+ end
68
+
69
+ def xml_factory(context)
70
+ NodeFactories::Xml.new(context)
71
+ end
72
+
73
+ def external_docs_factory(context)
74
+ NodeFactories::ExternalDocumentation.new(context)
75
+ end
76
+
77
+ def properties_factory(context)
78
+ NodeFactories::Map.new(
79
+ context,
80
+ value_factory: NodeFactories::Schema
81
+ )
82
+ end
83
+
84
+ def referenceable_schema(context)
85
+ NodeFactory::OptionalReference.new(self.class).call(context)
86
+ end
87
+
88
+ def referenceable_schema_array(context)
89
+ NodeFactories::Array.new(
90
+ context,
91
+ value_factory: NodeFactory::OptionalReference.new(self.class)
92
+ )
93
+ end
94
+
95
+ def additional_properties_input_type(input)
96
+ return if [true, false].include?(input) || input.is_a?(Hash)
97
+ "Expected a boolean or an object"
98
+ end
99
+
100
+ def additional_properties_factory(context)
101
+ return context.input if [true, false].include?(context.input)
102
+ referenceable_schema(context)
103
+ end
104
+ end
105
+ end
106
+ end
@@ -0,0 +1,25 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "openapi3_parser/nodes/security_requirement"
4
+ require "openapi3_parser/node_factory/map"
5
+ require "openapi3_parser/node_factories/array"
6
+
7
+ module Openapi3Parser
8
+ module NodeFactories
9
+ class SecurityRequirement
10
+ include NodeFactory::Map
11
+
12
+ private
13
+
14
+ def process_input(input)
15
+ input.keys.each_with_object({}) do |key, memo|
16
+ memo[key] = NodeFactories::Array.new(context.next_namespace(key))
17
+ end
18
+ end
19
+
20
+ def build_map(data, context)
21
+ Nodes::SecurityRequirement.new(data, context)
22
+ end
23
+ end
24
+ end
25
+ end
@@ -0,0 +1,35 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "openapi3_parser/nodes/security_scheme"
4
+ require "openapi3_parser/node_factories/oauth_flows"
5
+ require "openapi3_parser/node_factory/object"
6
+ require "openapi3_parser/node_factory/optional_reference"
7
+
8
+ module Openapi3Parser
9
+ module NodeFactories
10
+ class SecurityScheme
11
+ include NodeFactory::Object
12
+
13
+ allow_extensions
14
+
15
+ field "type", input_type: String, required: true
16
+ field "description", input_type: String
17
+ field "name", input_type: String
18
+ field "in", input_type: String
19
+ field "scheme", input_type: String
20
+ field "bearerFormat", input_type: String
21
+ field "flows", factory: :flows_factory
22
+ field "openIdConnectUrl", input_type: String
23
+
24
+ private
25
+
26
+ def build_object(data, context)
27
+ Nodes::SecurityScheme.new(data, context)
28
+ end
29
+
30
+ def flows_factory(context)
31
+ NodeFactories::OauthFlows.new(context)
32
+ end
33
+ end
34
+ end
35
+ end