skooma 0.1.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 (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,16 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Skooma
4
+ module Objects
5
+ class PathItem
6
+ module Keywords
7
+ class Delete < BaseOperation
8
+ self.key = "options"
9
+ self.depends_on = %w[parameters]
10
+ self.value_schema = :schema
11
+ self.schema_value_class = Objects::Operation
12
+ end
13
+ end
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,16 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Skooma
4
+ module Objects
5
+ class PathItem
6
+ module Keywords
7
+ class Get < BaseOperation
8
+ self.key = "get"
9
+ self.depends_on = %w[parameters]
10
+ self.value_schema = :schema
11
+ self.schema_value_class = Objects::Operation
12
+ end
13
+ end
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,16 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Skooma
4
+ module Objects
5
+ class PathItem
6
+ module Keywords
7
+ class Head < BaseOperation
8
+ self.key = "head"
9
+ self.depends_on = %w[parameters]
10
+ self.value_schema = :schema
11
+ self.schema_value_class = Objects::Operation
12
+ end
13
+ end
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,16 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Skooma
4
+ module Objects
5
+ class PathItem
6
+ module Keywords
7
+ class Options < BaseOperation
8
+ self.key = "options"
9
+ self.depends_on = %w[parameters]
10
+ self.value_schema = :schema
11
+ self.schema_value_class = Objects::Operation
12
+ end
13
+ end
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,19 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Skooma
4
+ module Objects
5
+ class PathItem
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 evaluate(instance, result)
13
+ result.skip_assertion
14
+ end
15
+ end
16
+ end
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,16 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Skooma
4
+ module Objects
5
+ class PathItem
6
+ module Keywords
7
+ class Patch < BaseOperation
8
+ self.key = "patch"
9
+ self.depends_on = %w[parameters]
10
+ self.value_schema = :schema
11
+ self.schema_value_class = Objects::Operation
12
+ end
13
+ end
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,16 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Skooma
4
+ module Objects
5
+ class PathItem
6
+ module Keywords
7
+ class Post < BaseOperation
8
+ self.key = "post"
9
+ self.depends_on = %w[parameters]
10
+ self.value_schema = :schema
11
+ self.schema_value_class = Objects::Operation
12
+ end
13
+ end
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,16 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Skooma
4
+ module Objects
5
+ class PathItem
6
+ module Keywords
7
+ class Put < BaseOperation
8
+ self.key = "put"
9
+ self.depends_on = %w[parameters]
10
+ self.value_schema = :schema
11
+ self.schema_value_class = Objects::Operation
12
+ end
13
+ end
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,16 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Skooma
4
+ module Objects
5
+ class PathItem
6
+ module Keywords
7
+ class Trace < BaseOperation
8
+ self.key = "trace"
9
+ self.depends_on = %w[parameters]
10
+ self.value_schema = :schema
11
+ self.schema_value_class = Objects::Operation
12
+ end
13
+ end
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,28 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Skooma
4
+ module Objects
5
+ # Describes the operations available on a single path.
6
+ # https://spec.openapis.org/oas/v3.1.0#path-item-object
7
+ class PathItem < RefBase
8
+ def kw_classes
9
+ [
10
+ Base::Keywords::Summary,
11
+ Base::Keywords::Description,
12
+
13
+ Keywords::Get,
14
+ Keywords::Put,
15
+ Keywords::Post,
16
+ Keywords::Delete,
17
+ Keywords::Options,
18
+ Keywords::Head,
19
+ Keywords::Patch,
20
+ Keywords::Trace,
21
+
22
+ Base::Keywords::Servers,
23
+ Keywords::Parameters
24
+ ]
25
+ end
26
+ end
27
+ end
28
+ end
@@ -0,0 +1,33 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Skooma
4
+ module Objects
5
+ # A simple object to allow referencing other components in the OpenAPI document.
6
+ # https://spec.openapis.org/oas/v3.1.0#referenceObject
7
+ class RefBase < Base
8
+ # This object cannot be extended with additional properties
9
+ # and any properties added SHALL be ignored.
10
+ def resolve_keywords(value)
11
+ return super unless value.key?("$ref")
12
+
13
+ resolve_ref_keywords(value)
14
+ end
15
+
16
+ def ref_kw_classes
17
+ [
18
+ JSONSkooma::Keywords::Core::Ref,
19
+ Base::Keywords::Summary,
20
+ Base::Keywords::Description
21
+ ]
22
+ end
23
+
24
+ def resolve_ref_keywords(value)
25
+ ref_kw_classes.each do |kw_class|
26
+ next unless value.key?(kw_class.key)
27
+
28
+ add_keyword(kw_class.new(self, value[kw_class.key]))
29
+ end
30
+ end
31
+ end
32
+ end
33
+ end
@@ -0,0 +1,19 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Skooma
4
+ module Objects
5
+ class RequestBody
6
+ module Keywords
7
+ class Required < JSONSkooma::Keywords::Base
8
+ self.key = "required"
9
+
10
+ def evaluate(instance, result)
11
+ if json.value && instance["body"].value.nil?
12
+ result.failure("Body is required")
13
+ end
14
+ end
15
+ end
16
+ end
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,17 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Skooma
4
+ module Objects
5
+ # Describes a single request body.
6
+ # https://spec.openapis.org/oas/v3.1.0#request-body-object
7
+ class RequestBody < RefBase
8
+ def kw_classes
9
+ [
10
+ Base::Keywords::Description,
11
+ Skooma::Objects::Response::Keywords::Content,
12
+ Keywords::Required
13
+ ]
14
+ end
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,51 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Skooma
4
+ module Objects
5
+ class Response
6
+ module Keywords
7
+ class Content < JSONSkooma::Keywords::Base
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 result.discard unless instance["body"].value
14
+
15
+ media_type = instance["headers"]&.[]("Content-Type")&.split(";")&.first&.strip&.downcase
16
+ media_type_object, matched_media_type = find_media_type(media_type)
17
+
18
+ return result.failure("Media type #{media_type} not found") unless media_type_object
19
+
20
+ result.annotate(matched_media_type)
21
+ result.call(instance, matched_media_type) do |media_type_result|
22
+ media_type_object.evaluate(instance["body"], media_type_result)
23
+
24
+ result.failure("Invalid content") unless media_type_result.passed?
25
+ end
26
+ end
27
+
28
+ private
29
+
30
+ # The key is a media type or media type range and the value describes it.
31
+ # For requests that match multiple keys, only the most specific key is applicable.
32
+ # e.g. text/plain overrides text/*
33
+ def find_media_type(media_type)
34
+ matched_media_type =
35
+ if json.key?(media_type)
36
+ media_type
37
+ elsif media_type &&
38
+ (key = "#{media_type.split("/").first}/*") &&
39
+ json.key?(key)
40
+ key
41
+ elsif json.key?("*/*")
42
+ "*/*"
43
+ end
44
+
45
+ [json[matched_media_type], matched_media_type]
46
+ end
47
+ end
48
+ end
49
+ end
50
+ end
51
+ end
@@ -0,0 +1,37 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Skooma
4
+ module Objects
5
+ class Response
6
+ module Keywords
7
+ class Headers < JSONSkooma::Keywords::Base
8
+ self.key = "headers"
9
+ self.value_schema = :object_of_schemas
10
+ self.schema_value_class = Objects::Header
11
+
12
+ def evaluate(instance, result)
13
+ errors = []
14
+ json.each do |key, schema|
15
+ next if ignored_key?(key)
16
+
17
+ result.call(instance["headers"], key) do |subresult|
18
+ schema.evaluate(instance["headers"][key], subresult)
19
+
20
+ errors << key unless subresult.passed?
21
+ end
22
+ end
23
+ return if errors.empty?
24
+
25
+ result.failure("The following headers are invalid: #{errors}")
26
+ end
27
+
28
+ private
29
+
30
+ def ignored_key?(key)
31
+ %w[accept content-type authorization].include?(key.downcase)
32
+ end
33
+ end
34
+ end
35
+ end
36
+ end
37
+ end
@@ -0,0 +1,13 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Skooma
4
+ module Objects
5
+ class Response
6
+ module Keywords
7
+ class Links < JSONSkooma::Keywords::BaseAnnotation
8
+ self.key = "links"
9
+ end
10
+ end
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,18 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Skooma
4
+ module Objects
5
+ # Describes a single response from an API Operation.
6
+ # https://spec.openapis.org/oas/v3.1.0#responseObject
7
+ class Response < RefBase
8
+ def kw_classes
9
+ [
10
+ Base::Keywords::Description,
11
+ Keywords::Headers,
12
+ Keywords::Content,
13
+ Keywords::Links
14
+ ]
15
+ end
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,35 @@
1
+ module Skooma
2
+ module OutputFormat
3
+ class << self
4
+ def call(result, **_options)
5
+ return {"valid" => true} if result.valid?
6
+
7
+ node_data(result, true)
8
+ end
9
+
10
+ private
11
+
12
+ def node_data(node, first = false)
13
+ data = {
14
+ "instanceLocation" => node.instance.path.to_s,
15
+ "relativeKeywordLocation" => node.relative_path.to_s,
16
+ "keywordLocation" => node.path.to_s
17
+ }
18
+
19
+ child_data = node.children.filter_map do |_, child|
20
+ node_data(child) unless child.valid?
21
+ end
22
+
23
+ if first || child_data.length > 1
24
+ data["errors"] = child_data
25
+ elsif child_data.length == 1
26
+ data = child_data[0]
27
+ elsif node.error
28
+ data["error"] = node.error
29
+ end
30
+
31
+ data
32
+ end
33
+ end
34
+ end
35
+ end
@@ -0,0 +1,166 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "yaml"
4
+
5
+ module Skooma
6
+ # RSpec matchers for OpenAPI schema validation
7
+ # @example
8
+ # require "skooma/rspec"
9
+ # # ...
10
+ # RSpec.configure do |config|
11
+ # # ...
12
+ # config.include Skooma::RSpec[Rails.root.join("docs", "openapi.yml")], type: :request
13
+ # end
14
+ class RSpec < Module
15
+ class << self
16
+ alias_method :[], :new
17
+ end
18
+
19
+ module Mapper
20
+ PLAIN_HEADERS = %w[CONTENT_LENGTH CONTENT_TYPE].freeze
21
+ REGEXP_HTTP = /^HTTP_/.freeze
22
+
23
+ def mapped_response(response: true, request: true)
24
+ result = {
25
+ "method" => env["REQUEST_METHOD"].downcase,
26
+ "path" => env["PATH_INFO"]
27
+ }
28
+
29
+ if response
30
+ result["response"] = {
31
+ "status" => response_data[0],
32
+ "headers" => response_data[1],
33
+ "body" => response_data[2]
34
+ }
35
+ end
36
+
37
+ if request
38
+ result["request"] = {
39
+ "query" => env["rack.request.query_string"] || env["QUERY_STRING"],
40
+ "headers" => env.select { |k, _| k.start_with?("HTTP_") || PLAIN_HEADERS.include?(k) }.transform_keys { |k| k.sub(REGEXP_HTTP, "").split("_").map(&:capitalize).join("-") },
41
+ "body" => env["RAW_POST_DATA"]
42
+ }
43
+ end
44
+
45
+ result
46
+ end
47
+
48
+ def env
49
+ request.env
50
+ end
51
+
52
+ def response_data
53
+ [response.status, response.headers.to_h, response.body]
54
+ end
55
+ end
56
+
57
+ def initialize(openapi_path, base_uri: "https://skoomarb.dev/")
58
+ super()
59
+
60
+ pathname = Pathname.new(openapi_path)
61
+
62
+ registry = Skooma.create_registry
63
+ registry.add_source(
64
+ base_uri,
65
+ JSONSkooma::Sources::Local.new(pathname.dirname.to_s)
66
+ )
67
+ schema = registry.schema(URI.parse("#{base_uri}#{pathname.basename}"), schema_class: Skooma::Objects::OpenAPI)
68
+
69
+ include Mapper
70
+
71
+ define_method :skooma_openapi_schema do
72
+ schema
73
+ end
74
+ end
75
+ end
76
+
77
+ ::RSpec::Matchers.define(:conform_schema) do |expected_status|
78
+ match do
79
+ next false unless response.status == expected_status
80
+
81
+ @result = skooma_openapi_schema.evaluate(mapped_response)
82
+ @result.valid?
83
+ end
84
+
85
+ description do
86
+ "conform schema with #{expected_status} response code"
87
+ end
88
+
89
+ failure_message do
90
+ <<~MSG
91
+ ENV:
92
+ #{PP.pp(mapped_response, +"")}
93
+
94
+ Validation Result:
95
+ #{@result ? PP.pp(@result.output(:skooma), +"") : "Expected #{expected_status} status code"}
96
+ MSG
97
+ end
98
+ end
99
+
100
+ ::RSpec::Matchers.define(:conform_request_schema) do
101
+ match do
102
+ @result = skooma_openapi_schema.evaluate(mapped_response(response: false))
103
+ @result.valid?
104
+ end
105
+
106
+ description do
107
+ "conform request schema"
108
+ end
109
+
110
+ failure_message do
111
+ <<~MSG
112
+ ENV:
113
+ #{PP.pp(mapped_response, +"")}
114
+
115
+ Validation Result:
116
+ #{@result ? PP.pp(@result.output(:skooma), +"") : "Expected #{expected_status} status code"}
117
+ MSG
118
+ end
119
+ end
120
+
121
+ ::RSpec::Matchers.define(:conform_response_schema) do |expected_status|
122
+ match do
123
+ next false unless response.status == expected_status
124
+
125
+ @result = skooma_openapi_schema.evaluate(mapped_response(request: false))
126
+ @result.valid?
127
+ end
128
+
129
+ description do
130
+ "conform response schema with #{expected_status} response code"
131
+ end
132
+
133
+ failure_message do
134
+ <<~MSG
135
+ ENV:
136
+ #{PP.pp(mapped_response, +"")}
137
+
138
+ Validation Result:
139
+ #{@result ? PP.pp(@result.output(:skooma), +"") : "Expected #{expected_status} status code"}
140
+ MSG
141
+ end
142
+ end
143
+
144
+ ::RSpec::Matchers.define(:be_valid_document) do
145
+ match do |actual|
146
+ @actual = actual
147
+ next false unless comparable?
148
+
149
+ @result = actual.validate
150
+ @result.valid?
151
+ end
152
+
153
+ description { "be a valid OpenAPI document" }
154
+
155
+ failure_message do
156
+ next "expected value to be an OpenAPI object" unless comparable?
157
+
158
+ pretty_output = PP.pp(@result.output(:detailed), +"")
159
+ "must valid against OpenAPI specification:\n#{pretty_output}"
160
+ end
161
+
162
+ def comparable?
163
+ actual.is_a?(Skooma::Objects::OpenAPI)
164
+ end
165
+ end
166
+ end
@@ -0,0 +1,13 @@
1
+ module Skooma
2
+ module Validators
3
+ class Double < JSONSkooma::Validators::Base
4
+ self.instance_types = "number"
5
+
6
+ def call(instance)
7
+ return if instance.value.is_a?(::Float)
8
+
9
+ raise JSONSkooma::Validators::FormatError, "must be a valid double"
10
+ end
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,13 @@
1
+ module Skooma
2
+ module Validators
3
+ class Float < JSONSkooma::Validators::Base
4
+ self.instance_types = "number"
5
+
6
+ def call(instance)
7
+ return if instance.value.is_a?(::Float)
8
+
9
+ raise JSONSkooma::Validators::FormatError, "must be a valid float"
10
+ end
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,15 @@
1
+ module Skooma
2
+ module Validators
3
+ class Int32 < JSONSkooma::Validators::Base
4
+ def self.assert?(instance)
5
+ instance.type == "number" && instance == instance.to_i
6
+ end
7
+
8
+ def call(instance)
9
+ return if instance.value.bit_length <= 32
10
+
11
+ raise JSONSkooma::Validators::FormatError, "must be a valid int32"
12
+ end
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,15 @@
1
+ module Skooma
2
+ module Validators
3
+ class Int64 < JSONSkooma::Validators::Base
4
+ def self.assert?(instance)
5
+ instance.type == "number" && instance == instance.to_i
6
+ end
7
+
8
+ def call(instance)
9
+ return if instance.value.bit_length <= 64
10
+
11
+ raise JSONSkooma::Validators::FormatError, "must be a valid int64"
12
+ end
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,5 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Skooma
4
+ VERSION = "0.1.0"
5
+ end
data/lib/skooma.rb ADDED
@@ -0,0 +1,26 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "json_skooma"
4
+ require "zeitwerk"
5
+
6
+ require_relative "skooma/inflector"
7
+
8
+ loader = Zeitwerk::Loader.for_gem
9
+ loader.inflector = Skooma::Inflector.new
10
+ loader.setup
11
+
12
+ module Skooma
13
+ DATA_DIR = File.join(__dir__, "..", "data")
14
+ REGISTRY_NAME = "skooma_registry"
15
+
16
+ class Error < StandardError; end
17
+
18
+ JSONSkooma.register_dialect("oas-3.1", Dialects::OAS31)
19
+ JSONSkooma::Formatters.register :skooma, OutputFormat
20
+
21
+ class << self
22
+ def create_registry
23
+ JSONSkooma.create_registry("2020-12", "oas-3.1", name: REGISTRY_NAME, assert_formats: true)
24
+ end
25
+ end
26
+ end