skooma 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (86) hide show
  1. checksums.yaml +7 -0
  2. data/CHANGELOG.md +22 -0
  3. data/LICENSE.txt +21 -0
  4. data/README.md +125 -0
  5. data/data/oas-3.1/dialect/base.json +25 -0
  6. data/data/oas-3.1/meta/base.json +96 -0
  7. data/data/oas-3.1/schema/2022-10-07.json +1441 -0
  8. data/data/oas-3.1/schema-base/2022-10-07.json +23 -0
  9. data/lib/skooma/body_parsers.rb +31 -0
  10. data/lib/skooma/dialects/oas_3_1.rb +41 -0
  11. data/lib/skooma/inflector.rb +19 -0
  12. data/lib/skooma/instance.rb +112 -0
  13. data/lib/skooma/keywords/oas_3_1/dialect/discriminator.rb +13 -0
  14. data/lib/skooma/keywords/oas_3_1/dialect/example.rb +13 -0
  15. data/lib/skooma/keywords/oas_3_1/dialect/external_docs.rb +13 -0
  16. data/lib/skooma/keywords/oas_3_1/dialect/xml.rb +13 -0
  17. data/lib/skooma/keywords/oas_3_1/schema.rb +32 -0
  18. data/lib/skooma/keywords/oas_3_1.rb +22 -0
  19. data/lib/skooma/objects/base/keywords/deprecated.rb +13 -0
  20. data/lib/skooma/objects/base/keywords/description.rb +13 -0
  21. data/lib/skooma/objects/base/keywords/security.rb +13 -0
  22. data/lib/skooma/objects/base/keywords/servers.rb +13 -0
  23. data/lib/skooma/objects/base/keywords/summary.rb +13 -0
  24. data/lib/skooma/objects/base/keywords/tags.rb +13 -0
  25. data/lib/skooma/objects/base.rb +33 -0
  26. data/lib/skooma/objects/callback.rb +12 -0
  27. data/lib/skooma/objects/components.rb +30 -0
  28. data/lib/skooma/objects/header/keywords/content.rb +50 -0
  29. data/lib/skooma/objects/header/keywords/example.rb +13 -0
  30. data/lib/skooma/objects/header/keywords/examples.rb +13 -0
  31. data/lib/skooma/objects/header/keywords/explode.rb +13 -0
  32. data/lib/skooma/objects/header/keywords/required.rb +19 -0
  33. data/lib/skooma/objects/header/keywords/schema.rb +19 -0
  34. data/lib/skooma/objects/header/keywords/style.rb +13 -0
  35. data/lib/skooma/objects/header.rb +23 -0
  36. data/lib/skooma/objects/media_type.rb +14 -0
  37. data/lib/skooma/objects/openapi/keywords/components.rb +23 -0
  38. data/lib/skooma/objects/openapi/keywords/info.rb +13 -0
  39. data/lib/skooma/objects/openapi/keywords/json_schema_dialect.rb +21 -0
  40. data/lib/skooma/objects/openapi/keywords/openapi.rb +24 -0
  41. data/lib/skooma/objects/openapi/keywords/paths.rb +62 -0
  42. data/lib/skooma/objects/openapi/keywords/security.rb +13 -0
  43. data/lib/skooma/objects/openapi/keywords/webhooks.rb +15 -0
  44. data/lib/skooma/objects/openapi.rb +39 -0
  45. data/lib/skooma/objects/operation/keywords/callbacks.rb +13 -0
  46. data/lib/skooma/objects/operation/keywords/operation_id.rb +13 -0
  47. data/lib/skooma/objects/operation/keywords/parameters.rb +53 -0
  48. data/lib/skooma/objects/operation/keywords/request_body.rb +21 -0
  49. data/lib/skooma/objects/operation/keywords/responses.rb +48 -0
  50. data/lib/skooma/objects/operation.rb +31 -0
  51. data/lib/skooma/objects/parameter/keywords/allow_empty_value.rb +13 -0
  52. data/lib/skooma/objects/parameter/keywords/allow_reserved.rb +13 -0
  53. data/lib/skooma/objects/parameter/keywords/content.rb +21 -0
  54. data/lib/skooma/objects/parameter/keywords/in.rb +13 -0
  55. data/lib/skooma/objects/parameter/keywords/name.rb +13 -0
  56. data/lib/skooma/objects/parameter/keywords/required.rb +19 -0
  57. data/lib/skooma/objects/parameter/keywords/schema.rb +21 -0
  58. data/lib/skooma/objects/parameter/keywords/value_parser.rb +80 -0
  59. data/lib/skooma/objects/parameter.rb +27 -0
  60. data/lib/skooma/objects/path_item/keywords/base_operation.rb +25 -0
  61. data/lib/skooma/objects/path_item/keywords/delete.rb +16 -0
  62. data/lib/skooma/objects/path_item/keywords/get.rb +16 -0
  63. data/lib/skooma/objects/path_item/keywords/head.rb +16 -0
  64. data/lib/skooma/objects/path_item/keywords/options.rb +16 -0
  65. data/lib/skooma/objects/path_item/keywords/parameters.rb +19 -0
  66. data/lib/skooma/objects/path_item/keywords/patch.rb +16 -0
  67. data/lib/skooma/objects/path_item/keywords/post.rb +16 -0
  68. data/lib/skooma/objects/path_item/keywords/put.rb +16 -0
  69. data/lib/skooma/objects/path_item/keywords/trace.rb +16 -0
  70. data/lib/skooma/objects/path_item.rb +28 -0
  71. data/lib/skooma/objects/ref_base.rb +33 -0
  72. data/lib/skooma/objects/request_body/keywords/required.rb +19 -0
  73. data/lib/skooma/objects/request_body.rb +17 -0
  74. data/lib/skooma/objects/response/keywords/content.rb +51 -0
  75. data/lib/skooma/objects/response/keywords/headers.rb +37 -0
  76. data/lib/skooma/objects/response/keywords/links.rb +13 -0
  77. data/lib/skooma/objects/response.rb +18 -0
  78. data/lib/skooma/output_format.rb +35 -0
  79. data/lib/skooma/rspec.rb +166 -0
  80. data/lib/skooma/validators/double.rb +13 -0
  81. data/lib/skooma/validators/float.rb +13 -0
  82. data/lib/skooma/validators/int_32.rb +15 -0
  83. data/lib/skooma/validators/int_64.rb +15 -0
  84. data/lib/skooma/version.rb +5 -0
  85. data/lib/skooma.rb +26 -0
  86. metadata +161 -0
@@ -0,0 +1,14 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Skooma
4
+ module Objects
5
+ # https://spec.openapis.org/oas/v3.1.0#media-type-object
6
+ class MediaType < Base
7
+ def kw_classes
8
+ [
9
+ Keywords::OAS31::Schema
10
+ ]
11
+ end
12
+ end
13
+ end
14
+ end
@@ -0,0 +1,23 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Skooma
4
+ module Objects
5
+ class OpenAPI
6
+ module Keywords
7
+ class Components < JSONSkooma::Keywords::Base
8
+ self.key = "components"
9
+ self.value_schema = :schema
10
+ self.schema_value_class = Objects::Components
11
+
12
+ def each_schema(&block)
13
+ return super unless json.type == "object"
14
+
15
+ json.each_value do |s|
16
+ s.each_value(&block)
17
+ end
18
+ end
19
+ end
20
+ end
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,13 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Skooma
4
+ module Objects
5
+ class OpenAPI
6
+ module Keywords
7
+ class Info < JSONSkooma::Keywords::BaseAnnotation
8
+ self.key = "info"
9
+ end
10
+ end
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,21 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Skooma
4
+ module Objects
5
+ class OpenAPI
6
+ module Keywords
7
+ class JSONSchemaDialect < JSONSkooma::Keywords::Base
8
+ self.key = "jsonSchemaDialect"
9
+ self.static = true
10
+
11
+ def initialize(parent_schema, value)
12
+ super
13
+
14
+ uri = URI.parse(value)
15
+ parent_schema.json_schema_dialect_uri = uri
16
+ end
17
+ end
18
+ end
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,24 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Skooma
4
+ module Objects
5
+ class OpenAPI
6
+ module Keywords
7
+ class OpenAPI < JSONSkooma::Keywords::BaseAnnotation
8
+ self.key = "openapi"
9
+
10
+ def initialize(parent_schema, value)
11
+ unless value.to_s.start_with? "3.1."
12
+ raise Error, "Only OpenAPI version 3.1.x is supported, got #{value}"
13
+ end
14
+
15
+ parent_schema.metaschema_uri = "https://spec.openapis.org/oas/3.1/schema-base/2022-10-07"
16
+ parent_schema.json_schema_dialect_uri = "https://spec.openapis.org/oas/3.1/dialect/base"
17
+
18
+ super
19
+ end
20
+ end
21
+ end
22
+ end
23
+ end
24
+ end
@@ -0,0 +1,62 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Skooma
4
+ module Objects
5
+ class OpenAPI
6
+ module Keywords
7
+ class Paths < JSONSkooma::Keywords::Base
8
+ self.key = "paths"
9
+ self.value_schema = :object_of_schemas
10
+ self.schema_value_class = Objects::PathItem
11
+
12
+ ROUTE_REGEXP = /\{([^}]+)}/.freeze
13
+
14
+ def initialize(parent_schema, value)
15
+ super
16
+ @regexp_map = json.filter_map do |path, subschema|
17
+ next unless path.include?("{") && path.include?("}")
18
+
19
+ path_regex = path.gsub(ROUTE_REGEXP, "(?<\\1>[^/?#]+)")
20
+ path_regex = Regexp.new("\\A#{path_regex}\\z")
21
+
22
+ [path, path_regex, subschema]
23
+ end
24
+ end
25
+
26
+ def evaluate(instance, result)
27
+ path, attributes, path_schema = find_route(instance["path"])
28
+
29
+ return result.failure("Path #{instance["path"]} not found in schema") unless path
30
+
31
+ result.call(instance, path) do |subresult|
32
+ subresult.annotate({"path_attributes" => attributes})
33
+ path_schema.evaluate(instance, subresult)
34
+
35
+ if subresult.passed?
36
+ result.success
37
+ else
38
+ result.failure("Path #{instance["path"]} is invalid")
39
+ end
40
+ end
41
+ end
42
+
43
+ private
44
+
45
+ def find_route(instance_path)
46
+ return [instance_path, {}, json[instance_path]] if json.key?(instance_path)
47
+
48
+ @regexp_map.reduce(nil) do |result, (path, path_regex, subschema)|
49
+ next result unless path.include?("{") && path.include?("}")
50
+
51
+ match = instance_path.match(path_regex)
52
+ next result if match.nil?
53
+ next result if result && result[1].length <= match.named_captures.length
54
+
55
+ [path, match.named_captures, subschema]
56
+ end
57
+ end
58
+ end
59
+ end
60
+ end
61
+ end
62
+ end
@@ -0,0 +1,13 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Skooma
4
+ module Objects
5
+ class OpenAPI
6
+ module Keywords
7
+ class Security < JSONSkooma::Keywords::BaseAnnotation
8
+ self.key = "security"
9
+ end
10
+ end
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,15 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Skooma
4
+ module Objects
5
+ class OpenAPI
6
+ module Keywords
7
+ # Map[string, Path Item Object | Reference Object] ]
8
+ # example: https://github.com/OAI/OpenAPI-Specification/blob/main/examples/v3.1/webhook-example.yaml
9
+ class Webhooks < JSONSkooma::Keywords::BaseAnnotation
10
+ self.key = "webhooks"
11
+ end
12
+ end
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,39 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Skooma
4
+ module Objects
5
+ # OpenAPI Object – the root object of the OpenAPI document.
6
+ # https://spec.openapis.org/oas/v3.1.0#openapi-object
7
+ class OpenAPI < Base
8
+ attr_writer :json_schema_dialect_uri
9
+
10
+ def kw_classes
11
+ [
12
+ Keywords::Info,
13
+ Keywords::JSONSchemaDialect,
14
+ Keywords::Paths,
15
+ Keywords::Webhooks,
16
+ Keywords::Components,
17
+ Base::Keywords::Servers,
18
+ Base::Keywords::Security,
19
+ Base::Keywords::Tags,
20
+ Skooma::Keywords::OAS31::Dialect::ExternalDocs
21
+ ]
22
+ end
23
+
24
+ def bootstrap(value)
25
+ # always evaluate openapi to check version,
26
+ # and set metaschema_uri and json_schema_dialect_uri
27
+ add_keyword(Keywords::OpenAPI.new(self, value["openapi"]))
28
+ end
29
+
30
+ def evaluate(instance, result = nil)
31
+ super(Instance.new(instance), result)
32
+ end
33
+
34
+ def json_schema_dialect_uri
35
+ @json_schema_dialect_uri || parent_schema&.json_schema_dialect_uri
36
+ end
37
+ end
38
+ end
39
+ end
@@ -0,0 +1,13 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Skooma
4
+ module Objects
5
+ class Operation
6
+ module Keywords
7
+ class Callbacks < JSONSkooma::Keywords::BaseAnnotation
8
+ self.key = "callbacks"
9
+ end
10
+ end
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,13 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Skooma
4
+ module Objects
5
+ class Operation
6
+ module Keywords
7
+ class OperationId < JSONSkooma::Keywords::BaseAnnotation
8
+ self.key = "operationId"
9
+ end
10
+ end
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,53 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Skooma
4
+ module Objects
5
+ class Operation
6
+ module Keywords
7
+ class Parameters < JSONSkooma::Keywords::Base
8
+ self.key = "parameters"
9
+ self.value_schema = :array_of_schemas
10
+ self.schema_value_class = Objects::Parameter
11
+
12
+ def initialize(parent_schema, value)
13
+ super
14
+ keys = json.filter_map { |v| v["in"] && [v["in"].value, v["name"].value] }
15
+ parent_params = (parent_schema.parent["parameters"] || [])
16
+ parent_params.reject! do |v|
17
+ v["in"] && keys.include?([v["in"].value, v["name"].value])
18
+ end
19
+ @parent_params = parent_params
20
+ end
21
+
22
+ def evaluate(instance, result)
23
+ return result.discard unless instance.key?("request")
24
+ return result.discard if json&.value&.empty? && @parent_params.empty?
25
+
26
+ errors = []
27
+ process_parameter(json, instance, result) do |subresult|
28
+ errors << [subresult.schema_node["in"], subresult.schema_node["name"]] unless subresult.passed?
29
+ end
30
+ process_parameter(@parent_params, instance, result.parent.sibling(instance, "parameters")) do |subresult|
31
+ key = [subresult.schema_node["in"], subresult.schema_node["name"]]
32
+ errors << key unless subresult.passed?
33
+ end
34
+ return if errors.empty?
35
+
36
+ result.failure("The following parameters are invalid: #{errors}")
37
+ end
38
+
39
+ private
40
+
41
+ def process_parameter(v, instance, result)
42
+ v.each.with_index do |param, index|
43
+ result.call(instance["request"], index.to_s) do |subresult|
44
+ param.evaluate(instance["request"], subresult)
45
+ yield subresult
46
+ end
47
+ end
48
+ end
49
+ end
50
+ end
51
+ end
52
+ end
53
+ end
@@ -0,0 +1,21 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Skooma
4
+ module Objects
5
+ class Operation
6
+ module Keywords
7
+ class RequestBody < JSONSkooma::Keywords::Base
8
+ self.key = "requestBody"
9
+ self.value_schema = :schema
10
+ self.schema_value_class = Objects::RequestBody
11
+
12
+ def evaluate(instance, result)
13
+ return result.discard unless instance.key?("request")
14
+
15
+ json.evaluate(instance["request"], result)
16
+ end
17
+ end
18
+ end
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,48 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Skooma
4
+ module Objects
5
+ class Operation
6
+ module Keywords
7
+ class Responses < JSONSkooma::Keywords::Base
8
+ self.key = "responses"
9
+ self.value_schema = :object_of_schemas
10
+ self.schema_value_class = Objects::Response
11
+
12
+ def evaluate(instance, result)
13
+ response = instance["response"] || {}
14
+ return result.discard unless response["status"]
15
+
16
+ status = find_status(response)
17
+
18
+ return result.failure("Status #{response["status"]} not found for #{instance["method"].upcase} #{instance["path"]}") unless status
19
+
20
+ result.annotate(status)
21
+ result.call(response["status"], status) do |status_result|
22
+ json[status].evaluate(response, status_result)
23
+
24
+ if status_result.passed?
25
+ result.annotate(status)
26
+ else
27
+ result.failure("Res #{response["status"]} is invalid")
28
+ end
29
+ end
30
+ end
31
+
32
+ private
33
+
34
+ def find_status(response)
35
+ response_status = response["status"].to_s
36
+ if json.key?(response_status)
37
+ response_status
38
+ elsif json.key?("#{response_status[0]}XX")
39
+ "#{response_status[0]}XX"
40
+ elsif json.key?("default")
41
+ "default"
42
+ end
43
+ end
44
+ end
45
+ end
46
+ end
47
+ end
48
+ end
@@ -0,0 +1,31 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Skooma
4
+ module Objects
5
+ # Describes a single API operation on a path.
6
+ # https://spec.openapis.org/oas/v3.1.0#operation-object
7
+ class Operation < Base
8
+ def kw_classes
9
+ [
10
+ Base::Keywords::Tags,
11
+ Base::Keywords::Summary,
12
+ Base::Keywords::Description,
13
+ Skooma::Keywords::OAS31::Dialect::ExternalDocs,
14
+ Keywords::OperationId,
15
+ Keywords::Parameters,
16
+ Keywords::RequestBody,
17
+ Keywords::Responses,
18
+ Keywords::Callbacks,
19
+ Base::Keywords::Deprecated,
20
+ Base::Keywords::Security,
21
+ Base::Keywords::Servers
22
+ ]
23
+ end
24
+
25
+ def bootstrap(value)
26
+ # always evaluate parameters to check parent parameters
27
+ add_keyword(Keywords::Parameters.new(self, value["parameters"] || []))
28
+ end
29
+ end
30
+ end
31
+ end
@@ -0,0 +1,13 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Skooma
4
+ module Objects
5
+ class Parameter
6
+ module Keywords
7
+ class AllowEmptyValue < JSONSkooma::Keywords::BaseAnnotation
8
+ self.key = "allowEmptyValue"
9
+ end
10
+ end
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,13 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Skooma
4
+ module Objects
5
+ class Parameter
6
+ module Keywords
7
+ class AllowReserved < JSONSkooma::Keywords::BaseAnnotation
8
+ self.key = "allowReserved"
9
+ end
10
+ end
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,21 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Skooma
4
+ module Objects
5
+ class Parameter
6
+ module Keywords
7
+ class Content < Header::Keywords::Content
8
+ self.key = "content"
9
+ self.value_schema = :object_of_schemas
10
+ self.schema_value_class = Objects::MediaType
11
+
12
+ def evaluate(instance, result)
13
+ return if instance.value.nil?
14
+
15
+ super(ValueParser.call(instance, result), result)
16
+ end
17
+ end
18
+ end
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,13 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Skooma
4
+ module Objects
5
+ class Parameter
6
+ module Keywords
7
+ class In < JSONSkooma::Keywords::BaseAnnotation
8
+ self.key = "in"
9
+ end
10
+ end
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,13 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Skooma
4
+ module Objects
5
+ class Parameter
6
+ module Keywords
7
+ class Name < JSONSkooma::Keywords::BaseAnnotation
8
+ self.key = "name"
9
+ end
10
+ end
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,19 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Skooma
4
+ module Objects
5
+ class Parameter
6
+ module Keywords
7
+ class Required < JSONSkooma::Keywords::Base
8
+ self.key = "required"
9
+
10
+ def evaluate(instance, result)
11
+ if json.value && ValueParser.call(instance, result)&.value.nil?
12
+ result.failure("Parameter is required")
13
+ end
14
+ end
15
+ end
16
+ end
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,21 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Skooma
4
+ module Objects
5
+ class Parameter
6
+ module Keywords
7
+ class Schema < Skooma::Keywords::OAS31::Schema
8
+ self.key = "schema"
9
+ self.depends_on = %w[in name style explode allowReserved allowEmptyValue]
10
+
11
+ def evaluate(instance, result)
12
+ value = ValueParser.call(instance, result)
13
+ return result.discard if value.nil?
14
+
15
+ super(value, result)
16
+ end
17
+ end
18
+ end
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,80 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "cgi"
4
+
5
+ module Skooma
6
+ module Objects
7
+ class Parameter
8
+ module Keywords
9
+ module ValueParser
10
+ class << self
11
+ def call(instance, result)
12
+ type = result.sibling(instance, "in").annotation
13
+ key = result.sibling(instance, "name").annotation
14
+ raise Error, "Missing key: #{key}" unless key
15
+
16
+ case type
17
+ when "query"
18
+ parse_query(instance)[key]
19
+ when "header"
20
+ instance["headers"][key]
21
+ when "path"
22
+ path_item_result = result.parent
23
+ path_item_result = path_item_result.parent until path_item_result.key.start_with?("/")
24
+
25
+ Instance::Attribute.new(
26
+ path_item_result.annotation["path_attributes"][key],
27
+ key: "path",
28
+ parent: instance["path"]
29
+ )
30
+ when "cookie"
31
+ # instance["headers"]["Cookie"]
32
+ else
33
+ raise Error, "Unknown location: #{result.sibling(instance, "in").annotation}"
34
+ end
35
+ end
36
+
37
+ private
38
+
39
+ def parse_query(instance)
40
+ params = {}
41
+ instance["query"]&.value.to_s.split(/[&;]/).each do |pairs|
42
+ key, value = pairs.split("=", 2).collect { |v| CGI.unescape(v) }
43
+ next unless key
44
+
45
+ params[key] = value
46
+ end
47
+
48
+ Instance::Attribute.new(
49
+ params,
50
+ key: "query",
51
+ parent: instance["query"]
52
+ )
53
+ end
54
+
55
+ def style(value, instance, result)
56
+ case result.sibling(instance, "style")
57
+ when "simple"
58
+ value
59
+ when "label"
60
+ value.split(".")
61
+ when "matrix"
62
+ value.split(";")
63
+ when "form"
64
+ value.split("&")
65
+ when "spaceDelimited"
66
+ value.split(" ")
67
+ when "pipeDelimited"
68
+ value.split("|")
69
+ when "deepObject"
70
+ raise Error, "Not implemented yet"
71
+ else
72
+ raise Error, "Unknown style: #{result.sibling(instance, "style")}"
73
+ end
74
+ end
75
+ end
76
+ end
77
+ end
78
+ end
79
+ end
80
+ end
@@ -0,0 +1,27 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Skooma
4
+ module Objects
5
+ # https://spec.openapis.org/oas/v3.1.0#parameter-object
6
+ # Describes a single operation parameter.
7
+ class Parameter < RefBase
8
+ def kw_classes
9
+ [
10
+ Keywords::Name,
11
+ Keywords::In,
12
+ Base::Keywords::Description,
13
+ Base::Keywords::Deprecated,
14
+ Header::Keywords::Style,
15
+ Header::Keywords::Explode,
16
+ Keywords::AllowEmptyValue,
17
+ Keywords::AllowReserved,
18
+ Keywords::Required,
19
+ Keywords::Schema,
20
+ Header::Keywords::Example,
21
+ Header::Keywords::Examples,
22
+ Keywords::Content
23
+ ]
24
+ end
25
+ end
26
+ end
27
+ end
@@ -0,0 +1,25 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Skooma
4
+ module Objects
5
+ class PathItem
6
+ module Keywords
7
+ class BaseOperation < JSONSkooma::Keywords::Base
8
+ def evaluate(instance, result)
9
+ return result.discard unless instance["method"] == key
10
+
11
+ json.evaluate(instance, result)
12
+ return result.success if result.passed?
13
+
14
+ path_item_result = result.parent
15
+ path_item_result = path_item_result.parent until path_item_result.key.start_with?("/")
16
+
17
+ path = path_item_result.annotation["path"]
18
+
19
+ result.failure("Path #{path}/#{key} is invalid")
20
+ end
21
+ end
22
+ end
23
+ end
24
+ end
25
+ end